Commit 180d7d976f197b5ff1da7df82e9aa9cbbe11c268
1 parent
5f63c83b
Exists in
master
and in
2 other branches
Refactor heavily.
Showing
1 changed file
with
66 additions
and
41 deletions
Show diff stats
web/run.py
@@ -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 |