Commit 180d7d976f197b5ff1da7df82e9aa9cbbe11c268

Authored by Goutte
1 parent 5f63c83b

Refactor heavily.

Showing 1 changed file with 66 additions and 41 deletions   Show diff stats
@@ -175,14 +175,18 @@ def datetime_from_list(time_list): @@ -175,14 +175,18 @@ def datetime_from_list(time_list):
175 ) 175 )
176 176
177 177
178 -def get_source_config(slug): 178 +def get_target_config(slug):
179 for s in config['targets']: # dumb 179 for s in config['targets']: # dumb
180 if s['slug'] == slug: 180 if s['slug'] == slug:
181 return s 181 return s
182 - raise Exception("No source found for slug '%s'." % slug) 182 + raise Exception("No target found in configuration for '%s'." % slug)
183 183
184 184
185 -def retrieve_data(orbiter, what, started_at, stopped_at): 185 +def check_target_config(slug):
  186 + get_target_config(slug)
  187 +
  188 +
  189 +def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at):
186 """ 190 """
187 Handles remote querying Myriam's API, downloading, extracting and caching 191 Handles remote querying Myriam's API, downloading, extracting and caching
188 the netCDF files. 192 the netCDF files.
@@ -268,50 +272,59 @@ def retrieve_data(orbiter, what, started_at, stopped_at): @@ -268,50 +272,59 @@ def retrieve_data(orbiter, what, started_at, stopped_at):
268 return local_netc_files 272 return local_netc_files
269 273
270 274
271 -def generate_csv_contents(source_config, started_at, stopped_at): 275 +# The available parameters in the generated CSV and NetCDF files.
  276 +# The order matters. If you change this you also need to change the
  277 +# innermost loop of `get_data_for_target`.
  278 +# The javascript knows the targets' properties under these names.
  279 +PROPERTIES = ('time', 'vrad', 'vtan', 'vlen', 'magn', 'temp', 'pdyn', 'dens',
  280 + 'angl', 'xhci', 'yhci')
  281 +
  282 +
  283 +def get_data_for_target(target_config, started_at, stopped_at):
  284 + """
  285 + :return: dict whose keys are datetime as str, values tuples of data
  286 + """
  287 + log.debug("Grabbing data for '%s'..." % target_config['slug'])
272 # @todo iterate on models when there are many 288 # @todo iterate on models when there are many
273 try: 289 try:
274 - model_slug = source_config['models'][0]['slug'] 290 + model_slug = target_config['models'][0]['slug']
275 except Exception as e: 291 except Exception as e:
276 abort(500, "Invalid model configuration for '%s' : %s" 292 abort(500, "Invalid model configuration for '%s' : %s"
277 - % (source_config['slug'], str(e))) 293 + % (target_config['slug'], str(e)))
  294 + try:
  295 + orbit_slug = target_config['orbit']['model']
  296 + except Exception as e:
  297 + abort(500, "Invalid orbit configuration for '%s' : %s"
  298 + % (target_config['slug'], str(e)))
278 299
279 # Grab the list of netCDF files from Myriam's API 300 # Grab the list of netCDF files from Myriam's API
280 # http://cdpp.irap.omp.eu/BASE/DDService/getDataUrl.php?dataSet=jupiter_orb_all&StartTime=2014-02-23T10:00:10&StopTime=2017-02-24T23:59:00 301 # http://cdpp.irap.omp.eu/BASE/DDService/getDataUrl.php?dataSet=jupiter_orb_all&StartTime=2014-02-23T10:00:10&StopTime=2017-02-24T23:59:00
281 # http://cdpp.irap.omp.eu/BASE/DATA/TAO/JUPITER/SW/sw_2014.nc.gz 302 # http://cdpp.irap.omp.eu/BASE/DATA/TAO/JUPITER/SW/sw_2014.nc.gz
282 - log.info("Generating CSV for '%s'..." % source_config['slug'])  
283 - model_files = retrieve_data(source_config['slug'], model_slug, started_at, stopped_at)  
284 - orbits_files = retrieve_data(source_config['slug'], source_config['orbit']['model'], started_at, stopped_at)  
285 -  
286 - log.debug("Crunching CSV contents for '%s'..." % source_config['name'])  
287 - si = StringIO.StringIO()  
288 - cw = csv_writer(si)  
289 - cw.writerow(( # the order matters !  
290 - 'time',  
291 - 'vrad', 'vtan', 'vlen',  
292 - 'magn', 'temp', 'pdyn', 'dens', 'angl',  
293 - 'xhci', 'yhci'  
294 - )) 303 + model_files = retrieve_amda_netcdf(target_config['slug'], model_slug,
  304 + started_at, stopped_at)
  305 + orbit_files = retrieve_amda_netcdf(target_config['slug'], orbit_slug,
  306 + started_at, stopped_at)
295 307
296 precision = "%Y-%m-%dT%H" # model and orbits times are equal-ish 308 precision = "%Y-%m-%dT%H" # model and orbits times are equal-ish
297 - orbits_data = {} # keys are datetime as str, values arrays of XY  
298 - for orbits_file in orbits_files: 309 + orbit_data = {} # keys are datetime as str, values arrays of XY
  310 + for orbit_file in orbit_files:
299 log.debug("%s: opening orbit NETCDF4 '%s'..." % 311 log.debug("%s: opening orbit NETCDF4 '%s'..." %
300 - (source_config['name'], orbits_file))  
301 - cdf_handle = Dataset(orbits_file, "r", format="NETCDF4") 312 + (target_config['name'], orbit_file))
  313 + cdf_handle = Dataset(orbit_file, "r", format="NETCDF4")
302 times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms 314 times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms
303 data_hci = cdf_handle.variables['HCI'] 315 data_hci = cdf_handle.variables['HCI']
304 for time, datum_hci in zip(times, data_hci): 316 for time, datum_hci in zip(times, data_hci):
305 dtime = datetime_from_list(time) 317 dtime = datetime_from_list(time)
306 if started_at <= dtime <= stopped_at: 318 if started_at <= dtime <= stopped_at:
307 dkey = dtime.strftime(precision) 319 dkey = dtime.strftime(precision)
308 - orbits_data[dkey] = datum_hci 320 + orbit_data[dkey] = datum_hci
309 cdf_handle.close() 321 cdf_handle.close()
  322 +
310 all_data = {} # keys are datetime as str, values tuples of data 323 all_data = {} # keys are datetime as str, values tuples of data
311 for model_file in model_files: 324 for model_file in model_files:
312 # Time, StartTime, StopTime, V, B, N, T, Delta_angle, P_dyn 325 # Time, StartTime, StopTime, V, B, N, T, Delta_angle, P_dyn
313 log.debug("%s: opening model NETCDF4 '%s'..." % 326 log.debug("%s: opening model NETCDF4 '%s'..." %
314 - (source_config['name'], model_file)) 327 + (target_config['name'], model_file))
315 cdf_handle = Dataset(model_file, "r", format="NETCDF4") 328 cdf_handle = Dataset(model_file, "r", format="NETCDF4")
316 times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms 329 times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms
317 data_v = cdf_handle.variables['V'] 330 data_v = cdf_handle.variables['V']
@@ -321,7 +334,7 @@ def generate_csv_contents(source_config, started_at, stopped_at): @@ -321,7 +334,7 @@ def generate_csv_contents(source_config, started_at, stopped_at):
321 data_p = cdf_handle.variables['P_dyn'] 334 data_p = cdf_handle.variables['P_dyn']
322 data_d = cdf_handle.variables['Delta_angle'] 335 data_d = cdf_handle.variables['Delta_angle']
323 log.debug("%s: aggregating data from '%s'..." % 336 log.debug("%s: aggregating data from '%s'..." %
324 - (source_config['name'], model_file)) 337 + (target_config['name'], model_file))
325 for time, datum_v, datum_b, datum_t, datum_n, datum_p, datum_d \ 338 for time, datum_v, datum_b, datum_t, datum_n, datum_p, datum_d \
326 in zip(times, data_v, data_b, data_t, data_n, data_p, data_d): 339 in zip(times, data_v, data_b, data_t, data_n, data_p, data_d):
327 vrad = datum_v[0] 340 vrad = datum_v[0]
@@ -331,9 +344,9 @@ def generate_csv_contents(source_config, started_at, stopped_at): @@ -331,9 +344,9 @@ def generate_csv_contents(source_config, started_at, stopped_at):
331 dkey = dtime.strftime(precision) 344 dkey = dtime.strftime(precision)
332 x_hci = None 345 x_hci = None
333 y_hci = None 346 y_hci = None
334 - if dkey in orbits_data:  
335 - x_hci = orbits_data[dkey][0]  
336 - y_hci = orbits_data[dkey][1] 347 + if dkey in orbit_data:
  348 + x_hci = orbit_data[dkey][0]
  349 + y_hci = orbit_data[dkey][1]
337 all_data[dkey] = ( 350 all_data[dkey] = (
338 dtime.strftime("%Y-%m-%dT%H:%M:%S+00:00"), 351 dtime.strftime("%Y-%m-%dT%H:%M:%S+00:00"),
339 vrad, vtan, sqrt(vrad * vrad + vtan * vtan), 352 vrad, vtan, sqrt(vrad * vrad + vtan * vtan),
@@ -342,16 +355,28 @@ def generate_csv_contents(source_config, started_at, stopped_at): @@ -342,16 +355,28 @@ def generate_csv_contents(source_config, started_at, stopped_at):
342 ) 355 )
343 cdf_handle.close() 356 cdf_handle.close()
344 357
345 - log.debug("Writing and sorting CSV for '%s'..." % source_config['slug']) 358 + return all_data
  359 +
  360 +
  361 +def generate_csv_contents(target_slug, started_at, stopped_at):
  362 + target_config = get_target_config(target_slug)
  363 + log.debug("Crunching CSV contents for '%s'..." % target_config['name'])
  364 + si = StringIO.StringIO()
  365 + cw = csv_writer(si)
  366 + cw.writerow(PROPERTIES)
  367 +
  368 + all_data = get_data_for_target(target_config, started_at, stopped_at)
  369 +
  370 + log.debug("Writing and sorting CSV for '%s'..." % target_config['slug'])
346 for dkey in sorted(all_data): 371 for dkey in sorted(all_data):
347 cw.writerow(all_data[dkey]) 372 cw.writerow(all_data[dkey])
348 373
349 - log.info("Generated CSV contents for '%s'." % source_config['slug']) 374 + log.info("Generated CSV contents for '%s'." % target_config['slug'])
350 return si.getvalue() 375 return si.getvalue()
351 376
352 377
353 -def generate_csv_file_if_needed(target_config, started_at, stopped_at):  
354 - filename = "%s_%s_%s.csv" % (target_config['slug'], 378 +def generate_csv_file_if_needed(target_slug, started_at, stopped_at):
  379 + filename = "%s_%s_%s.csv" % (target_slug,
355 started_at.strftime(FILE_DATE_FMT), 380 started_at.strftime(FILE_DATE_FMT),
356 stopped_at.strftime(FILE_DATE_FMT)) 381 stopped_at.strftime(FILE_DATE_FMT))
357 local_csv_file = get_path("../cache/%s" % filename) 382 local_csv_file = get_path("../cache/%s" % filename)
@@ -359,7 +384,7 @@ def generate_csv_file_if_needed(target_config, started_at, stopped_at): @@ -359,7 +384,7 @@ def generate_csv_file_if_needed(target_config, started_at, stopped_at):
359 log.info("Generating CSV '%s'..." % local_csv_file) 384 log.info("Generating CSV '%s'..." % local_csv_file)
360 try: 385 try:
361 with open(local_csv_file, mode="w+") as f: 386 with open(local_csv_file, mode="w+") as f:
362 - f.write(generate_csv_contents(target_config, 387 + f.write(generate_csv_contents(target_slug,
363 started_at=started_at, 388 started_at=started_at,
364 stopped_at=stopped_at)) 389 stopped_at=stopped_at))
365 log.info("Generation of '%s' done." % filename) 390 log.info("Generation of '%s' done." % filename)
@@ -453,14 +478,14 @@ def home(): @@ -453,14 +478,14 @@ def home():
453 }) 478 })
454 479
455 480
456 -@app.route("/<source>_<started_at>_<stopped_at>.csv")  
457 -def get_target_csv(source, started_at, stopped_at): 481 +@app.route("/<target>_<started_at>_<stopped_at>.csv")
  482 +def download_target_csv(target, started_at, stopped_at):
458 """ 483 """
459 Grab data and orbit data for the specified `target`, 484 Grab data and orbit data for the specified `target`,
460 rearrange it and return it as a CSV file. 485 rearrange it and return it as a CSV file.
461 `started_at` and `stopped_at` should be UTC. 486 `started_at` and `stopped_at` should be UTC.
462 """ 487 """
463 - source_config = get_source_config(source) 488 + check_target_config(target)
464 try: 489 try:
465 started_at = datetime.datetime.strptime(started_at, FILE_DATE_FMT) 490 started_at = datetime.datetime.strptime(started_at, FILE_DATE_FMT)
466 except: 491 except:
@@ -470,11 +495,11 @@ def get_target_csv(source, started_at, stopped_at): @@ -470,11 +495,11 @@ def get_target_csv(source, started_at, stopped_at):
470 except: 495 except:
471 abort(400, "Invalid stopped_at parameter : '%s'." % stopped_at) 496 abort(400, "Invalid stopped_at parameter : '%s'." % stopped_at)
472 497
473 - filename = "%s_%s_%s.csv" % (source, 498 + filename = "%s_%s_%s.csv" % (target,
474 started_at.strftime(FILE_DATE_FMT), 499 started_at.strftime(FILE_DATE_FMT),
475 stopped_at.strftime(FILE_DATE_FMT)) 500 stopped_at.strftime(FILE_DATE_FMT))
476 local_csv_file = get_path("../cache/%s" % filename) 501 local_csv_file = get_path("../cache/%s" % filename)
477 - generate_csv_file_if_needed(source_config, started_at, stopped_at) 502 + generate_csv_file_if_needed(target, started_at, stopped_at)
478 if not isfile(local_csv_file): 503 if not isfile(local_csv_file):
479 abort(500, "Could not cache CSV file at '%s'." % local_csv_file) 504 abort(500, "Could not cache CSV file at '%s'." % local_csv_file)
480 505
@@ -498,7 +523,7 @@ def download_targets_tarball(targets, started_at, stopped_at): @@ -498,7 +523,7 @@ def download_targets_tarball(targets, started_at, stopped_at):
498 for target in targets: 523 for target in targets:
499 if not target: 524 if not target:
500 abort(400, "Invalid targets format : `%s`." % targets) 525 abort(400, "Invalid targets format : `%s`." % targets)
501 - targets_configs.append(get_source_config(target)) 526 + targets_configs.append(get_target_config(target))
502 if 0 == len(targets_configs): 527 if 0 == len(targets_configs):
503 abort(400, "No valid targets specified. What are you doing?") 528 abort(400, "No valid targets specified. What are you doing?")
504 529
@@ -524,7 +549,7 @@ def download_targets_tarball(targets, started_at, stopped_at): @@ -524,7 +549,7 @@ def download_targets_tarball(targets, started_at, stopped_at):
524 local_csv_file = get_path("../cache/%s" % filename) 549 local_csv_file = get_path("../cache/%s" % filename)
525 if not isfile(local_csv_file): 550 if not isfile(local_csv_file):
526 with open(local_csv_file, mode="w+") as f: 551 with open(local_csv_file, mode="w+") as f:
527 - f.write(generate_csv_contents(target_config, 552 + f.write(generate_csv_contents(target_config['slug'],
528 started_at=started_at, 553 started_at=started_at,
529 stopped_at=stopped_at)) 554 stopped_at=stopped_at))
530 555