Coverage for webgeodyn/server/datahandlers.py: 0%

231 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-12-18 09:33 +0000

1from tornado.web import * 

2from concurrent.futures import ThreadPoolExecutor 

3from tornado.concurrent import run_on_executor 

4from tornado.web import HTTPError 

5 

6import re 

7import json 

8 

9globalExecutor = ThreadPoolExecutor(max_workers=10) 

10 

11 

12class ServerError(HTTPError): 

13 def __init__(self, reason, **kwargs): 

14 super().__init__(reason=reason, **kwargs) 

15 

16 

17class GenericDataHandler(RequestHandler): 

18 def initialize(self, models, obsdata): 

19 self.models = models 

20 print("{0} initialisation...".format(type(self).__name__)) 

21 self.obsdata = obsdata 

22 

23 def getModel(self, dataName): 

24 if self.models.isCached(dataName): 

25 return self.models[dataName] 

26 else: 

27 raise ValueError("No model named " + dataName) 

28 

29 @run_on_executor 

30 def async_getModel(self, dataName): 

31 # Loads model from data directory, async = ask to load and return nothing 

32 if not self.models.isCached(dataName) and not self.models.isModelLoading(dataName): 

33 self.getModel(dataName) 

34 return True 

35 

36 def write_error(self, status_code, **kwargs): 

37 print("Raised error '{}' (status code {}) in {}".format(self._reason, status_code, type(self).__name__)) 

38 self.finish(json.dumps({ 

39 'SUCCESS': False, 

40 'ERROR': self._reason, 

41 'error_code': status_code 

42 })) 

43 

44 

45class DataListHandler(GenericDataHandler): 

46 def get(self): 

47 json_output_data = {"datalist": {}} 

48 for dataName in self.models.getModelList(): 

49 model = self.getModel(dataName) 

50 if not model: 

51 continue 

52 json_output_data["datalist"][dataName] = model.getDataInfo() 

53 self.write(json.dumps(json_output_data)) 

54 

55 

56class ExportFileInfoHandler(GenericDataHandler): 

57 """ Handler that gets the info of files to export for all the models but the ones with export set to False. """ 

58 def get(self): 

59 json_output_data = {"exportfileinfo": {}} 

60 for dataName in self.models.getModelList(): 

61 model = self.getModel(dataName) 

62 if model.export: 

63 # Skip CHAOS and COV-OBS model that will not be available for export 

64 json_output_data["exportfileinfo"][dataName] = model.getFileInfo() 

65 

66 self.write(json.dumps(json_output_data)) 

67 

68 

69class ObservatoryDataHandler(GenericDataHandler): 

70 executor = globalExecutor 

71 

72 @tornado.gen.coroutine 

73 def post(self): 

74 str_data = tornado.escape.url_unescape(self.request.body) 

75 json_request = json.loads(str_data) 

76 json_output_data = {} 

77 json_output_data["SUCCESS"] = False 

78 print("ObservatoryDataHandler post", json_request) 

79 

80 if "theta" not in json_request: 

81 json_output_data["obsdata"] = self.obsdata.getDataInfo() 

82 json_output_data["SUCCESS"] = True 

83 elif "phi" not in json_request: 

84 json_output_data["ERROR"] = "Invalid data request, please specify theta and phi" 

85 elif "selecteddata" not in json_request: 

86 json_output_data["ERROR"] = "Invalid data request, please specify selecteddata" 

87 elif "obstypes" not in json_request: 

88 json_output_data["ERROR"] = "Invalid data request, please specify obstypes" 

89 else: 

90 theta = json_request.get("theta") 

91 phi = json_request.get("phi") 

92 obstypes = json_request.get("obstypes") 

93 selecteddata = json_request.get("selecteddata") 

94 measuretype = json_request.get("measuretype") 

95 

96 r = self.obsdata.getObsR(theta,phi,obstypes) 

97 

98 json_output_data["modeldata"] = {} 

99 for data in selecteddata: 

100 dataName = data.get("dataname") 

101 measureName = data.get("measurename") 

102 if dataName not in json_output_data["modeldata"]: 

103 json_output_data["modeldata"][dataName] = {} 

104 json_output_data["modeldata"][dataName][measureName] = \ 

105 self.getModel(dataName).getObservatoryData(measureName, r, theta, phi) 

106 

107 json_output_data["obsdata"] = self.obsdata.getData(measuretype, theta, phi, obstypes) 

108 json_output_data["SUCCESS"] = True 

109 

110 self.write(json.dumps(json_output_data)) 

111 

112 

113class GlobeDataHandler(GenericDataHandler): 

114 executor = globalExecutor 

115 

116 @tornado.gen.coroutine 

117 def post(self): 

118 async_compute = False 

119 str_data = tornado.escape.url_unescape(self.request.body) 

120 json_request = json.loads(str_data) 

121 json_output_data = {} 

122 json_output_data["SUCCESS"] = False 

123 

124 if "dataname" not in json_request: 

125 json_output_data["ERROR"] = "Invalid data request, please specify dataname" 

126 elif "measure" not in json_request: 

127 if self.models.isCached(json_request["dataname"]): 

128 json_output_data = self.getModel(json_request["dataname"]).getDataInfo() 

129 else: 

130 json_output_data["computing"] = "loading " + json_request["dataname"] + " data files" 

131 self.async_getModel(json_request["dataname"]) # Get model data for further 

132 json_output_data["SUCCESS"] = True 

133 elif "time" not in json_request: 

134 json_output_data["ERROR"] = "Invalid data request, please specify time" 

135 else: 

136 datatime = json_request.get("time") 

137 measureName = json_request.get("measure") 

138 vectorComponent = json_request.get("vectorcomponent") 

139 removemean = json_request.get("removemean") 

140 dataName = json_request.get("dataname") 

141 toCompute, isComputing = \ 

142 self.getModel(dataName).canGetGlobeData(measureName, vectorComponent) 

143 if (not toCompute) and (not isComputing): 

144 # Return cached value 

145 json_output_data["computing"] = False 

146 json_output_data["data"] = \ 

147 yield self.async_getData(dataName, measureName, vectorComponent, datatime, removemean) 

148 else: 

149 # Return computing in progress 

150 json_output_data["computing"] = "computing real space grid" 

151 json_output_data["computingState"] = self.getModel(dataName).getGlobeDataComputingState(measureName) 

152 if not isComputing: 

153 # Tell to compute 

154 async_compute = True 

155 

156 json_output_data["SUCCESS"] = True 

157 

158 self.write(json.dumps(json_output_data)) 

159 self.finish() 

160 

161 if async_compute: 

162 #self.executor.submit(self.getModel(dataName).getGlobeData,*(measureName,vectorComponent,datatime,removemean)) 

163 #Compute after anwser 

164 #self.async_getData(dataName, measureName, vectorComponent, datatime, removemean) 

165 self.async_getData(dataName, measureName, vectorComponent, datatime, removemean) 

166 

167 @run_on_executor 

168 def async_getData(self, dataName, measureName, vectorComponent, datatime, removemean): 

169 return self.getModel(dataName).getGlobeData(measureName, vectorComponent, datatime, removemean) 

170 

171 

172class LodDataHandler(GenericDataHandler): 

173 executor = globalExecutor 

174 

175 @tornado.gen.coroutine 

176 def post(self): 

177 str_data = tornado.escape.url_unescape(self.request.body) 

178 json_request = json.loads(str_data) 

179 json_output_data = {"SUCCESS": False} 

180 

181 print("LodDataHandler post", json_request) 

182 

183 if "selecteddata" not in json_request: 

184 raise ServerError("Invalid data request, please select some data") 

185 

186 if "removemean" not in json_request: 

187 raise ServerError("Invalid data request, please specify removemean") 

188 

189 selected_data = json_request.get("selecteddata") 

190 removemean = json_request.get("removemean") 

191 

192 for data in selected_data: 

193 data_name = data.get("dataname") 

194 if data_name not in json_output_data: 

195 json_output_data[data_name] = {} 

196 try: 

197 json_output_data[data_name] = self.getModel(data_name).getLodData(removemean) 

198 except ValueError as e: 

199 # Transform the ValueError in HTTPError that will be caught by tornado write_error 

200 raise ServerError("Error while getting LOD data of {}: {}".format(data_name, e)) 

201 

202 json_output_data["SUCCESS"] = True 

203 self.write(json.dumps(json_output_data)) 

204 

205 

206class SpectraDataHandler(GenericDataHandler): 

207 executor = globalExecutor 

208 

209 @tornado.gen.coroutine 

210 def post(self): 

211 str_data = tornado.escape.url_unescape(self.request.body) 

212 json_request = json.loads(str_data) 

213 json_output_data = {"SUCCESS": False} 

214 

215 print("SpectraDataHandler post", json_request) 

216 

217 if "selecteddata" not in json_request: 

218 raise ServerError("Invalid data request, please select some data") 

219 

220 if "type" not in json_request: 

221 raise ServerError("Invalid data request, please specify a spectra type") 

222 

223 if "date" not in json_request: 

224 raise ServerError("Invalid data request, please specify a date") 

225 

226 selected_data = json_request.get("selecteddata") 

227 spectra_type = json_request.get("type") 

228 spectra_date = json_request.get("date") 

229 

230 if type(spectra_date) is not float: 

231 spectra_date = float(spectra_date) 

232 

233 for data in selected_data: 

234 data_name = data.get("dataname") 

235 measure_name = data.get("measurename") 

236 if data_name not in json_output_data: 

237 json_output_data[data_name] = {} 

238 try: 

239 json_output_data[data_name][measure_name] = self.getModel(data_name).getSpectraData(measure_name, spectra_type, spectra_date) 

240 except ValueError as e: 

241 # Transform the ValueError in HTTPError that will be catched by tornado write_error 

242 raise ServerError("Error while computing spectra of {}: {}".format(data_name, e)) 

243 

244 json_output_data["SUCCESS"] = True 

245 self.write(json.dumps(json_output_data)) 

246 

247 

248class SpherHarmDataHandler(GenericDataHandler): 

249 executor = globalExecutor 

250 

251 @tornado.gen.coroutine 

252 def post(self): 

253 str_data = tornado.escape.url_unescape(self.request.body) 

254 json_request = json.loads(str_data) 

255 json_output_data = {} 

256 json_output_data["SUCCESS"] = False 

257 print("SpherHarmDataHandler post", json_request) 

258 

259 if "selecteddata" not in json_request: 

260 json_output_data["ERROR"] = "Invalid data request, please specify selecteddata" 

261 elif "m" not in json_request: 

262 json_output_data["ERROR"] = "Invalid data request, please specify l" 

263 elif "l" not in json_request: 

264 json_output_data["ERROR"] = "Invalid data request, please specify l" 

265 else: 

266 l = json_request.get("l") 

267 m = json_request.get("m") 

268 removemean = json_request.get("removemean") 

269 selecteddata = json_request.get("selecteddata") 

270 

271 for data in selecteddata: 

272 dataName = data.get("dataname") 

273 measureName = data.get("measurename") 

274 if dataName not in json_output_data: 

275 json_output_data[dataName] = {} 

276 json_output_data[dataName][measureName] = \ 

277 self.getModel(dataName).getSpherHarmData(measureName, l, m, removemean) 

278 

279 json_output_data["SUCCESS"] = True 

280 

281 self.write(json.dumps(json_output_data)) 

282 

283 

284class TimeSerieDataHandler(GenericDataHandler): 

285 executor = globalExecutor 

286 

287 @tornado.gen.coroutine 

288 def post(self): 

289 str_data = tornado.escape.url_unescape(self.request.body) 

290 json_request = json.loads(str_data) 

291 json_output_data = {} 

292 json_output_data["SUCCESS"] = False 

293 print("TimeSerieDataHandler post", json_request) 

294 

295 if "dataname" not in json_request: 

296 json_output_data["ERROR"] = "Invalid data request, please specify dataname" 

297 elif "measure" not in json_request: 

298 if self.models.isCached(json_request["dataname"]): 

299 json_output_data = self.getModel(json_request["dataname"]).getDataInfo() # True is for analysis times only 

300 else: 

301 json_output_data["computing"] = "loading " + json_request["dataname"] + " data files" 

302 self.async_getModel(json_request["dataname"]) # Get model data for further 

303 json_output_data["SUCCESS"] = True 

304 elif "cutvalue" not in json_request: 

305 json_output_data["ERROR"] = "Invalid data request, please specify cutvalue" 

306 elif "cutvariable" not in json_request: 

307 json_output_data["ERROR"] = "Invalid data request, please specify cutvariable" 

308 else: 

309 measureName = json_request.get("measure") 

310 vectorComponent = json_request.get("vectorcomponent") 

311 removemean = json_request.get("removemean") 

312 cutvalue = json_request.get("cutvalue") 

313 cutvariable = json_request.get("cutvariable") 

314 dataName = json_request.get("dataname") 

315 coordtype = json_request.get("coordtype") 

316 print("getting timeSerieData", measureName, vectorComponent, cutvariable, cutvalue, coordtype) 

317 json_output_data = \ 

318 self.getModel(dataName).getTimeSerieData(measureName, vectorComponent, cutvariable, cutvalue, removemean, coordtype) 

319 json_output_data["SUCCESS"] = True 

320 

321 self.write(json.dumps(json_output_data))