| 403 # Read global attributes |
415 # Read global attributes |
| 404 station_id = read_global_attribute(netcdf_file_path, 'station_ID') |
416 station_id = read_global_attribute(netcdf_file_path, 'station_ID') |
| 405 station_location = read_global_attribute(netcdf_file_path, 'location') |
417 station_location = read_global_attribute(netcdf_file_path, 'location') |
| 406 |
418 |
| 407 # Read data |
419 # Read data |
| |
420 h = 0 |
| 408 for g in range(len(groups)): |
421 for g in range(len(groups)): |
| 409 # Read the altitude variable |
422 if check_group_presence(netcdf_file_path, groups[g]): |
| 410 altitude = read_variable_in_group(netcdf_file_path, groups[g], 'altitude') |
423 # Read the altitude variable |
| 411 |
424 altitude = read_variable_in_group(netcdf_file_path, groups[g], 'altitude') |
| 412 if altitude['metadata']['units'] == 'm': |
425 |
| 413 altitude['data'] = altitude['data'] / 1000.0 |
426 if altitude['metadata']['units'] == 'm': |
| 414 altitude['metadata']['units'] = 'km' |
427 altitude['data'] = altitude['data'] / 1000.0 |
| 415 |
428 altitude['metadata']['units'] = 'km' |
| 416 # Initialize variables |
429 |
| 417 data = None |
430 # Initialize variables |
| 418 variables_with_data = None |
431 data = None |
| 419 variables_axis = None |
432 variables_with_data = None |
| 420 |
433 variables_axis = None |
| 421 # Read the data |
434 |
| 422 for v in range(len(variable)): |
435 # Read the data |
| 423 # Initialize var |
436 for v in range(len(variable)): |
| 424 var = None |
437 # Initialize var |
| 425 |
438 var = None |
| 426 try: |
439 |
| 427 var, dim, met = read_variable_in_group2(netcdf_file_path, groups[g], variable[v]) |
440 try: |
| 428 except TypeError: |
441 var, dim, met = read_variable_in_group2(netcdf_file_path, groups[g], variable[v]) |
| 429 print(f"The variable {variable[v]} is not present. Cannot unpack non-iterable NoneType object") |
442 except TypeError: |
| 430 |
443 print(f"The variable {variable[v]} is not present. Cannot unpack non-iterable NoneType object") |
| 431 if var is not None: # If the variable that we're trying to read exists |
444 |
| 432 if var.max() != var.min(): # If there is data in the array |
445 if var is not None: # If the variable that we're trying to read exists |
| 433 if variables_with_data is None: |
446 if var.max() != var.min(): # If there is data in the array |
| 434 variables_with_data = [variable[v]] |
447 if variables_with_data is None: |
| 435 variables_axis = [met['long_name'] + ' [ ' + met['units'] + ' ]'] |
448 variables_with_data = [variable[v]] |
| |
449 variables_axis = [met['long_name'] + ' [ ' + met['units'] + ' ]'] |
| |
450 else: |
| |
451 variables_with_data += [variable[v]] |
| |
452 variables_axis += [met['long_name'] + ' [ ' + met['units'] + ' ]'] |
| |
453 |
| |
454 var_error, dim_error, met_error = read_variable_in_group2(netcdf_file_path, groups[g], |
| |
455 variable_error[v]) |
| |
456 if variable[v] == 'volumedepolarization': |
| |
457 var_error_negative, dim, met = read_variable_in_group2(netcdf_file_path, groups[g], |
| |
458 variable_negative_error_volumedepol) |
| |
459 else: |
| |
460 var_error_negative = var_error |
| |
461 |
| |
462 # Add read data to the data variable to have it all grouped |
| |
463 if data is None: |
| |
464 # Start populating data and data_error |
| |
465 data = {variable[v]: var} |
| |
466 data_error_positive = {variable[v]: var_error} |
| |
467 data_error_negative = {variable[v]: var_error_negative} |
| |
468 else: |
| |
469 # Add more data to data and data_error |
| |
470 data[variable[v]] = var |
| |
471 data_error_positive[variable[v]] = var_error |
| |
472 data_error_negative[variable[v]] = var_error_negative |
| 436 else: |
473 else: |
| 437 variables_with_data += [variable[v]] |
474 print(f'There is no data for {variable[v]} in the {groups_names[g]} group.') |
| 438 variables_axis += [met['long_name'] + ' [ ' + met['units'] + ' ]'] |
475 |
| 439 |
476 dimensions = dim |
| 440 var_error, dim_error, met_error = read_variable_in_group2(netcdf_file_path, groups[g], |
477 |
| 441 variable_error[v]) |
478 # Save lowres and highres in variables to plot them together afterwards |
| 442 if variable[v] == 'volumedepolarization': |
479 if groups[g] == 'lowres_products': |
| 443 var_error_negative, dim, met = read_variable_in_group2(netcdf_file_path, groups[g], |
480 altitude_lr = altitude |
| 444 variable_negative_error_volumedepol) |
481 dimensions_lr = dim |
| 445 else: |
482 data_lr = data |
| 446 var_error_negative = var_error |
483 data_error_positive_lr = data_error_positive |
| 447 |
484 data_error_negative_lr = data_error_negative |
| 448 # Add read data to the data variable to have it all grouped |
485 variables_with_data_lr = variables_with_data |
| 449 if data is None: |
486 variables_axis_lr = variables_axis |
| 450 # Start populating data and data_error |
487 if groups[g] == 'highres_products': |
| 451 data = {variable[v]: var} |
488 altitude_hr = altitude |
| 452 data_error_positive = {variable[v]: var_error} |
489 dimensions_hr = dim |
| 453 data_error_negative = {variable[v]: var_error_negative} |
490 data_hr = data |
| 454 else: |
491 data_error_positive_hr = data_error_positive |
| 455 # Add more data to data and data_error |
492 data_error_negative_hr = data_error_negative |
| 456 data[variable[v]] = var |
493 variables_with_data_hr = variables_with_data |
| 457 data_error_positive[variable[v]] = var_error |
494 variables_axis_hr = variables_axis |
| 458 data_error_negative[variable[v]] = var_error_negative |
495 |
| 459 else: |
496 # If interactive is set to True, ask user if he/she wants to plot different temporal profiles in different rows |
| 460 print(f'There is no data for {variable[v]} in the {groups_names[g]} group.') |
497 # If interactive is set to False, proceed with default values |
| 461 |
498 if h == 0: |
| 462 dimensions = dim |
499 # Initialize |
| 463 |
500 timeinplots = True |
| 464 # Save lowres and highres in variables to plot them together afterwards |
501 timeinrows = False |
| 465 if groups[g] == 'lowres_products': |
502 # If interactive (config.py) = True, ask user how he/she wants the plot |
| 466 altitude_lr = altitude |
503 if interactive and len(dimensions['time']) > 1: |
| 467 dimensions_lr = dim |
|
| 468 data_lr = data |
|
| 469 data_error_positive_lr = data_error_positive |
|
| 470 data_error_negative_lr = data_error_negative |
|
| 471 variables_with_data_lr = variables_with_data |
|
| 472 variables_axis_lr = variables_axis |
|
| 473 if groups[g] == 'highres_products': |
|
| 474 altitude_hr = altitude |
|
| 475 dimensions_hr = dim |
|
| 476 data_hr = data |
|
| 477 data_error_positive_hr = data_error_positive |
|
| 478 data_error_negative_hr = data_error_negative |
|
| 479 variables_with_data_hr = variables_with_data |
|
| 480 variables_axis_hr = variables_axis |
|
| 481 |
|
| 482 # If interactive is set to True, ask user if he/she wants to plot different temporal profiles in different rows |
|
| 483 # If interactive is set to False, proceed with default values |
|
| 484 if g == 0: |
|
| 485 # Initialize |
|
| 486 timeinplots = True |
|
| 487 timeinrows = False |
|
| 488 # If interactive (config.py) = True, ask user how he/she wants the plot |
|
| 489 if interactive and len(dimensions['time']) > 1: |
|
| 490 answer = input( |
|
| 491 f"There are {len(dimensions['time'])} temporal profiles, " |
|
| 492 f"do you want to plot them on different plots [y/n]? ") |
|
| 493 if answer[0:1].lower() == 'n': |
|
| 494 timeinplots = False |
|
| 495 if not timeinplots: |
|
| 496 answer = input( |
504 answer = input( |
| 497 f"There are {len(dimensions['time'])} temporal profiles, " |
505 f"There are {len(dimensions['time'])} temporal profiles, " |
| 498 f"do you want to plot them on different rows [y/n]? ") |
506 f"do you want to plot them on different plots [y/n]? ") |
| 499 if answer[0:1].lower() == 'y': |
507 if answer[0:1].lower() == 'n': |
| 500 timeinrows = True |
508 timeinplots = False |
| 501 |
509 if not timeinplots: |
| 502 if variables_with_data is not None: |
510 answer = input( |
| 503 timeiter = dimensions['time'] |
511 f"There are {len(dimensions['time'])} temporal profiles, " |
| 504 if timeinplots: |
512 f"do you want to plot them on different rows [y/n]? ") |
| 505 # Default plotting |
513 if answer[0:1].lower() == 'y': |
| 506 dimensions_t = dimensions |
514 timeinrows = True |
| 507 for t in range(len(dimensions['time'])): |
515 |
| 508 dimensions_t['time'] = [timeiter[t]] |
516 if variables_with_data is not None: |
| 509 for vr in range(len(variables_with_data)): |
517 timeiter = dimensions['time'] |
| 510 if vr == 0: |
518 if timeinplots: |
| 511 data_t = {variables_with_data[vr]: data[variables_with_data[vr]][:, t:t + 1, :]} |
519 # Default plotting |
| |
520 dimensions_t = dimensions |
| |
521 for t in range(len(dimensions['time'])): |
| |
522 dimensions_t['time'] = [timeiter[t]] |
| |
523 for vr in range(len(variables_with_data)): |
| |
524 if vr == 0: |
| |
525 data_t = {variables_with_data[vr]: data[variables_with_data[vr]][:, t:t + 1, :]} |
| |
526 else: |
| |
527 data_t[variables_with_data[vr]] = data[variables_with_data[vr]][:, t:t + 1, :] |
| |
528 |
| |
529 title = station_location + " (" + station_id.upper() + ") - " + str( |
| |
530 datetime.fromtimestamp(dimensions_t['time'][0], tz=timezone.utc).strftime( |
| |
531 '%d/%m/%Y %H:%M:%S')) + " - ELDA MWL " + groups_names[g] |
| |
532 |
| |
533 # Timestamps for the filename |
| |
534 t0 = datetime.fromtimestamp(timeiter[t], tz=timezone.utc).strftime('%Y%m%d%H%M') |
| |
535 if t + 1 < len(timeiter): |
| |
536 t1 = datetime.fromtimestamp( |
| |
537 timeiter[t+1], tz=timezone.utc).strftime('%Y%m%d%H%M') |
| 512 else: |
538 else: |
| 513 data_t[variables_with_data[vr]] = data[variables_with_data[vr]][:, t:t + 1, :] |
539 t1 = netcdf_file[29:41] |
| 514 |
540 |
| |
541 filename = "ELDAmwl_" + netcdf_file[0:3].upper() + "_" + t0 + "-" + t1 + "_" + \ |
| |
542 groups[g] + ".html" |
| |
543 |
| |
544 fig = plot_vertical_profiles_plotly( |
| |
545 variables=variables_with_data, |
| |
546 data=data_t, |
| |
547 dimensions=dimensions_t, |
| |
548 y_array=altitude, |
| |
549 positive_error_array=data_error_positive, |
| |
550 negative_error_array=data_error_negative, |
| |
551 xaxis_label=variables_axis, |
| |
552 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
| |
553 title=title, |
| |
554 timeinrows=True |
| |
555 ) |
| |
556 |
| |
557 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
| |
558 # fig.show() |
| |
559 |
| |
560 # Save the plot |
| |
561 fig.write_html(html_path + filename) |
| |
562 |
| |
563 else: |
| |
564 # Plotting in one plot (even if there are different time profiles) |
| 515 fig = plot_vertical_profiles_plotly( |
565 fig = plot_vertical_profiles_plotly( |
| 516 variables=variables_with_data, |
566 variables_with_data, |
| 517 data=data_t, |
567 data, |
| 518 dimensions=dimensions_t, |
568 dimensions, |
| 519 y_array=altitude, |
569 altitude, |
| 520 positive_error_array=data_error_positive, |
570 data_error_positive, |
| 521 negative_error_array=data_error_negative, |
571 data_error_negative, |
| 522 xaxis_label=variables_axis, |
572 xaxis_label=variables_axis, |
| 523 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
573 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
| 524 title=station_location + " (" + station_id.upper() + ") - " + str( |
574 title=station_location + " (" + station_id.upper() + ") - " + str( |
| 525 datetime.fromtimestamp(dimensions_t['time'][0]).strftime('%d/%m/%Y %H:%M:%S')) + |
575 datetime.fromtimestamp(dimensions['time'][0], tz=timezone.utc).strftime( |
| 526 " - ELDA MWL " + groups_names[g], |
576 '%d/%m/%Y')) + " - ELDA MWL " + groups_names[ |
| 527 timeinrows=True |
577 g], |
| |
578 timeinrows=timeinrows |
| 528 ) |
579 ) |
| 529 |
580 |
| 530 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
581 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
| 531 # fig.show() |
582 # fig.show() |
| 532 |
583 |
| 533 # Save the plot |
584 # Save the plot |
| 534 filename = "ELDAmwl_" + netcdf_file[0:3].upper() + "_" + datetime.fromtimestamp( |
585 if timeinrows: |
| 535 dimensions['time'][0]).strftime('%Y%m%d-%H%M%S') + "_" + groups[g] + ".html" |
586 filename = "ELDAmwl_" + station_id.upper() + "_" + datetime.fromtimestamp( |
| |
587 dimensions['time'][0], tz=timezone.utc).strftime('%Y%m%d%H%M') + '-' + datetime.fromtimestamp( |
| |
588 dimensions['time'][-1], tz=timezone.utc).strftime('%Y%m%d%H%M') + "_" + groups[ |
| |
589 g] + "_timeinrows.html" |
| |
590 else: |
| |
591 filename = "ELDAmwl_" + station_id.upper() + "_" + datetime.fromtimestamp( |
| |
592 dimensions['time'][0], tz=timezone.utc).strftime('%Y%m%d%H%M') + '-' + datetime.fromtimestamp( |
| |
593 dimensions['time'][-1], tz=timezone.utc).strftime('%Y%m%d%H%M') + "_" + groups[g] + ".html" |
| |
594 |
| 536 fig.write_html(html_path + filename) |
595 fig.write_html(html_path + filename) |
| 537 |
596 |
| |
597 dimensions['time'] = timeiter |
| |
598 |
| 538 else: |
599 else: |
| 539 # Plotting in one plot (even if there are different time profiles) |
600 print(f'There is no data to be plotted in the {groups_names[g]} group.') |
| 540 fig = plot_vertical_profiles_plotly( |
601 |
| 541 variables_with_data, |
602 h = h + 1 |
| 542 data, |
603 |
| 543 dimensions, |
604 # Plotting high and low resolution together |
| 544 altitude, |
605 if 'variables_with_data_lr' in locals() and 'variables_with_data_hr' in locals(): |
| 545 data_error_positive, |
606 if len(variables_with_data_lr) > 0 and len(variables_with_data_hr) > 0: |
| 546 data_error_negative, |
607 print(f'We have low and high resolution data, let''s combine it!') |
| |
608 |
| |
609 # Variables with data |
| |
610 variables_with_data = list(variables_with_data_lr) |
| |
611 variables_with_data.extend(x for x in variables_with_data_hr if x not in variables_with_data) |
| |
612 print(f'Variables with data: {variables_with_data}') |
| |
613 |
| |
614 # Variables axis |
| |
615 variables_axis = list(variables_axis_lr) |
| |
616 variables_axis.extend(x for x in variables_axis_hr if x not in variables_axis) |
| |
617 |
| |
618 # Joining dimensions for both resolutions |
| |
619 # Wavelength |
| |
620 wav = list(dimensions_lr['wavelength']) |
| |
621 dhrw = list(dimensions_hr['wavelength']) |
| |
622 wav.extend(x for x in dimensions_hr['wavelength'] if x not in wav) |
| |
623 dimensions['wavelength'] = wav |
| |
624 # Add LR/HR to the wavelength |
| |
625 wlr = list(dimensions_lr['wavelength']) |
| |
626 for r in range(len(wlr)): |
| |
627 wlr[r] = str(wlr[r]) + ' (LR)' |
| |
628 whr = list(dhrw) |
| |
629 for r in range(len(whr)): |
| |
630 whr[r] = str(whr[r]) + ' (HR)' |
| |
631 dimensions['wavelength_res'] = wlr + whr |
| |
632 dimensions_hr['wavelength'] = dhrw |
| |
633 dimensions['wavelength'] = wav |
| |
634 # Time |
| |
635 tim = list(dimensions_lr['time']) |
| |
636 tim.extend(x for x in dimensions_hr['time'] if x not in tim) |
| |
637 dimensions['time'] = tim |
| |
638 # Level |
| |
639 lev = list(dimensions_lr['level']) |
| |
640 lev.extend(x for x in dimensions_hr['level'] if x not in lev) |
| |
641 dimensions['level'] = lev |
| |
642 |
| |
643 # Populate the arrays with data and errors |
| |
644 for v in variables_with_data: |
| |
645 # Create array to store the joint data |
| |
646 # data_var = np.ma.masked_all((len(dimensions['wavelength_res']), len(tim), len(lev))) |
| |
647 data_var = np.ma.zeros((len(dimensions['wavelength_res']), len(tim), len(lev))) |
| |
648 data_error_positive_var = np.ma.zeros((len(dimensions['wavelength_res']), len(tim), len(lev))) |
| |
649 data_error_negative_var = np.ma.zeros((len(dimensions['wavelength_res']), len(tim), len(lev))) |
| |
650 # ToDo check if needed |
| |
651 data_var = np.ma.masked_values(data_var, 0) |
| |
652 data_error_positive_var = np.ma.masked_values(data_error_positive_var, 0) |
| |
653 data_error_negative_var = np.ma.masked_values(data_error_negative_var, 0) |
| |
654 for w in range(len(dimensions['wavelength_res'])): |
| |
655 for t in range(len(dimensions['time'])): |
| |
656 # Incorporate data into the main array |
| |
657 print(f"{v} - Wavelength: {dimensions['wavelength_res'][w]}. Time: {dimensions['time'][t]}.") |
| |
658 |
| |
659 # High resolution |
| |
660 if dimensions['wavelength_res'][w].find('HR') >= 0: |
| |
661 # Is there HR data? |
| |
662 if v in data_hr: |
| |
663 try: |
| |
664 # Find position of w and t |
| |
665 wl = float(dimensions['wavelength_res'][w].split(' ')[0]) |
| |
666 wp = dimensions_hr['wavelength'].index(wl) |
| |
667 wp = dhrw.index(wl) # ToDo test |
| |
668 tp = dimensions_hr['time'].index(dimensions['time'][t]) |
| |
669 # Check if there is data |
| |
670 a = data_hr[v][wp, tp, :] |
| |
671 d = np.average(np.ma.masked_array(a, np.isnan(a))) |
| |
672 if np.ma.min(d) is not np.ma.masked: |
| |
673 print(f'\tWe have HR data for {v}') |
| |
674 # Save data into common structure |
| |
675 data_var[w, t, :] = a |
| |
676 if np.average(np.ma.masked_array(data_error_positive_hr[v][wp, tp, :], np.isnan( |
| |
677 data_error_positive_hr[v][wp, tp, :]))) is not np.ma.masked: |
| |
678 data_error_positive_var[w, t, :] = data_error_positive_hr[v][wp, tp, :] |
| |
679 if np.average(np.ma.masked_array(data_error_negative_hr[v][wp, tp, :], np.isnan( |
| |
680 data_error_negative_hr[v][wp, tp, :]))) is not np.ma.masked: |
| |
681 data_error_negative_var[w, t, :] = data_error_negative_hr[v][wp, tp, :] |
| |
682 except ValueError: |
| |
683 pass |
| |
684 |
| |
685 # Low resolution |
| |
686 if dimensions['wavelength_res'][w].find('LR') >= 0: |
| |
687 # Is there LR data? |
| |
688 if v in data_lr: |
| |
689 # Find position of w and t |
| |
690 try: |
| |
691 wl = float(dimensions['wavelength_res'][w].split(' ')[0]) |
| |
692 # wp = dimensions_hr['wavelength'].index(wl) # ToDo check |
| |
693 if wl in dimensions_lr['wavelength']: |
| |
694 wp = dimensions_lr['wavelength'].index(dimensions['wavelength'][w]) |
| |
695 else: |
| |
696 wp = -1 |
| |
697 # if dimensions['time'][t] in dimensions_lr['time']: |
| |
698 tp = dimensions_lr['time'].index(dimensions['time'][t]) |
| |
699 # else: |
| |
700 # tp = -1 |
| |
701 if wp > -1 and tp > -1: |
| |
702 # Check if there is data |
| |
703 a = data_lr[v][wp, tp, :] |
| |
704 d = np.average(np.ma.masked_array(a, np.isnan(a))) |
| |
705 if np.ma.min(d) is not np.ma.masked: |
| |
706 print(f'\tWe have LR data for {v}') |
| |
707 # Save data into common structure |
| |
708 data_var[w, t, :] = a |
| |
709 if np.average(np.ma.masked_array(data_error_positive_lr[v][wp, tp, :], np.isnan( |
| |
710 data_error_positive_lr[v][wp, tp, :]))) is not np.ma.masked: |
| |
711 data_error_positive_var[w, t, :] = data_error_positive_lr[v][wp, tp, :] |
| |
712 if np.average(np.ma.masked_array(data_error_negative_lr[v][wp, tp, :], np.isnan( |
| |
713 data_error_negative_lr[v][wp, tp, :]))) is not np.ma.masked: |
| |
714 data_error_negative_var[w, t, :] = data_error_negative_lr[v][wp, tp, :] |
| |
715 except ValueError: |
| |
716 # i.e. no 1064 wavelength in dimensions_lr |
| |
717 pass |
| |
718 # except IndexError: |
| |
719 # pass |
| |
720 |
| |
721 # Store data in the global matrices |
| |
722 if variables_with_data.index(v) == 0: |
| |
723 data_all = {v: data_var} |
| |
724 data_error_positive = {v: data_error_positive_var} |
| |
725 data_error_negative = {v: data_error_negative_var} |
| |
726 else: |
| |
727 data_all[v] = data_var |
| |
728 data_error_positive[v] = data_error_positive_var |
| |
729 data_error_negative[v] = data_error_negative_var |
| |
730 |
| |
731 # Plot |
| |
732 timeiter = dimensions['time'] |
| |
733 # Default plotting |
| |
734 dimensions_t = dimensions |
| |
735 for t in range(len(dimensions['time'])): |
| |
736 print(f'plotting hr & lr for {timeiter[t]}') |
| |
737 dimensions_t['time'] = [timeiter[t]] |
| |
738 for vr in range(len(variables_with_data)): |
| |
739 if vr == 0: |
| |
740 data_t = {variables_with_data[vr]: data_all[variables_with_data[vr]][:, t:t + 1, :]} |
| |
741 else: |
| |
742 data_t[variables_with_data[vr]] = data_all[variables_with_data[vr]][:, t:t + 1, :] |
| |
743 |
| |
744 fig = plot_vertical_profiles_plotly_allres( |
| |
745 variables=variables_with_data, |
| |
746 data=data_t, |
| |
747 dimensions=dimensions_t, |
| |
748 y_array=altitude, |
| |
749 positive_error_array=data_error_positive, |
| |
750 negative_error_array=data_error_negative, |
| 547 xaxis_label=variables_axis, |
751 xaxis_label=variables_axis, |
| 548 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
752 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
| 549 title=station_location + " (" + station_id.upper() + ") - " + str( |
753 title=station_location + " (" + station_id.upper() + ") - " + str( |
| 550 datetime.fromtimestamp(dimensions['time'][0]).strftime('%d/%m/%Y')) + " - ELDA MWL " + groups_names[ |
754 datetime.fromtimestamp(dimensions_t['time'][0], tz=timezone.utc).strftime( |
| 551 g], |
755 '%d/%m/%Y %H:%M:%S')) + " - ELDA MWL - High and low resolution") |
| 552 timeinrows=timeinrows |
|
| 553 ) |
|
| 554 |
756 |
| 555 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
757 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
| 556 # fig.show() |
758 # fig.show() |
| 557 |
759 |
| 558 # Save the plot |
760 # Save the plot |
| 559 if timeinrows: |
761 |
| 560 filename = "ELDAmwl_" + station_id.upper() + "_" + datetime.fromtimestamp( |
762 # Timestamps for the filename |
| 561 dimensions['time'][0]).strftime('%Y%m%d%H%M%S') + '-' + datetime.fromtimestamp( |
763 t0 = datetime.fromtimestamp(timeiter[t], tz=timezone.utc).strftime('%Y%m%d%H%M') |
| 562 dimensions['time'][-1]).strftime('%Y%m%d%H%M%S') + "_" + groups[g] + "_timeinrows.html" |
764 if t + 1 < len(timeiter): |
| |
765 t1 = datetime.fromtimestamp( |
| |
766 timeiter[t + 1], tz=timezone.utc).strftime('%Y%m%d%H%M') |
| 563 else: |
767 else: |
| 564 filename = "ELDAmwl_" + station_id.upper() + "_" + datetime.fromtimestamp( |
768 t1 = netcdf_file[29:41] |
| 565 dimensions['time'][0]).strftime('%Y%m%d%H%M%S') + '-' + datetime.fromtimestamp( |
769 |
| 566 dimensions['time'][-1]).strftime('%Y%m%d%H%M%S') + "_" + groups[g] + ".html" |
770 filename = "ELDAmwl_" + netcdf_file[0:3].upper() + "_" + t0 + "-" + t1 + "_all.html" |
| 567 |
|
| 568 fig.write_html(html_path + filename) |
771 fig.write_html(html_path + filename) |
| 569 |
|
| 570 else: |
|
| 571 print(f'There is no data to be plotted in the {groups_names[g]} group.') |
|
| 572 |
|
| 573 # Plotting high and low resolution together |
|
| 574 if len(variables_with_data_lr) > 0 and len(variables_with_data_hr) > 0: |
|
| 575 print(f'We have low and high resolution data, let''s combine it!') |
|
| 576 |
|
| 577 # Variables with data |
|
| 578 variables_with_data = list(variables_with_data_lr) |
|
| 579 variables_with_data.extend(x for x in variables_with_data_hr if x not in variables_with_data) |
|
| 580 print(f'Variables with data: {variables_with_data}') |
|
| 581 |
|
| 582 # Variables axis |
|
| 583 variables_axis = list(variables_axis_lr) |
|
| 584 variables_axis.extend(x for x in variables_axis_hr if x not in variables_axis) |
|
| 585 |
|
| 586 # Joining dimensions for both resolutions |
|
| 587 # Wavelength |
|
| 588 wav = list(dimensions_lr['wavelength']) |
|
| 589 wav.extend(x for x in dimensions_hr['wavelength'] if x not in wav) |
|
| 590 dimensions['wavelength'] = wav |
|
| 591 # Add LR/HR to the wavelength |
|
| 592 wlr = list(dimensions_lr['wavelength']) |
|
| 593 for r in range(len(wlr)): |
|
| 594 wlr[r] = str(wlr[r]) + ' (LR)' |
|
| 595 whr = list(dimensions_hr['wavelength']) |
|
| 596 for r in range(len(whr)): |
|
| 597 whr[r] = str(whr[r]) + ' (HR)' |
|
| 598 dimensions['wavelength_res'] = wlr + whr |
|
| 599 # Time |
|
| 600 tim = list(dimensions_lr['time']) |
|
| 601 tim.extend(x for x in dimensions_hr['time'] if x not in tim) |
|
| 602 dimensions['time'] = tim |
|
| 603 # Level |
|
| 604 lev = list(dimensions_lr['level']) |
|
| 605 lev.extend(x for x in dimensions_hr['level'] if x not in lev) |
|
| 606 dimensions['level'] = lev |
|
| 607 |
|
| 608 # Populate the arrays with data and errors |
|
| 609 for v in variables_with_data: |
|
| 610 # Create array to store the joint data |
|
| 611 # data_var = np.ma.masked_all((len(dimensions['wavelength_res']), len(tim), len(lev))) |
|
| 612 data_var = np.ma.zeros((len(dimensions['wavelength_res']), len(tim), len(lev))) |
|
| 613 data_error_positive_var = np.ma.zeros((len(dimensions['wavelength_res']), len(tim), len(lev))) |
|
| 614 data_error_negative_var = np.ma.zeros((len(dimensions['wavelength_res']), len(tim), len(lev))) |
|
| 615 # ToDo check if needed |
|
| 616 data_var = np.ma.masked_values(data_var, 0) |
|
| 617 data_error_positive_var = np.ma.masked_values(data_error_positive_var, 0) |
|
| 618 data_error_negative_var = np.ma.masked_values(data_error_negative_var, 0) |
|
| 619 for w in range(len(dimensions['wavelength_res'])): |
|
| 620 for t in range(len(dimensions['time'])): |
|
| 621 # Incorporate data into the main array |
|
| 622 print(f"{v} - Wavelength: {dimensions['wavelength_res'][w]}. Time: {dimensions['time'][t]}.") |
|
| 623 |
|
| 624 # High resolution |
|
| 625 if dimensions['wavelength_res'][w].find('HR') >= 0: |
|
| 626 # Is there HR data? |
|
| 627 if v in data_hr: |
|
| 628 try: |
|
| 629 # Find position of w and t |
|
| 630 wl = float(dimensions['wavelength_res'][w].split(' ')[0]) |
|
| 631 wp = dimensions_hr['wavelength'].index(wl) |
|
| 632 tp = dimensions_hr['time'].index(dimensions['time'][t]) |
|
| 633 # Check if there is data |
|
| 634 a = data_hr[v][wp, tp, :] |
|
| 635 d = np.average(np.ma.masked_array(a, np.isnan(a))) |
|
| 636 if np.ma.min(d) is not np.ma.masked: |
|
| 637 print(f'\tWe have HR data for {v}') |
|
| 638 # Save data into common structure |
|
| 639 data_var[w, t, :] = a |
|
| 640 if np.average(np.ma.masked_array(data_error_positive_hr[v][wp, tp, :], np.isnan( |
|
| 641 data_error_positive_hr[v][wp, tp, :]))) is not np.ma.masked: |
|
| 642 data_error_positive_var[w, t, :] = data_error_positive_hr[v][wp, tp, :] |
|
| 643 if np.average(np.ma.masked_array(data_error_negative_hr[v][wp, tp, :], np.isnan( |
|
| 644 data_error_negative_hr[v][wp, tp, :]))) is not np.ma.masked: |
|
| 645 data_error_negative_var[w, t, :] = data_error_negative_hr[v][wp, tp, :] |
|
| 646 except ValueError: |
|
| 647 pass |
|
| 648 |
|
| 649 # Low resolution |
|
| 650 if dimensions['wavelength_res'][w].find('LR') >= 0: |
|
| 651 # Is there LR data? |
|
| 652 if v in data_lr: |
|
| 653 # Find position of w and t |
|
| 654 try: |
|
| 655 wl = float(dimensions['wavelength_res'][w].split(' ')[0]) |
|
| 656 wp = dimensions_hr['wavelength'].index(wl) |
|
| 657 if wl in dimensions_lr['wavelength']: |
|
| 658 wp = dimensions_lr['wavelength'].index(dimensions['wavelength'][w]) |
|
| 659 else: |
|
| 660 wp = -1 |
|
| 661 # if dimensions['time'][t] in dimensions_lr['time']: |
|
| 662 tp = dimensions_lr['time'].index(dimensions['time'][t]) |
|
| 663 # else: |
|
| 664 # tp = -1 |
|
| 665 if wp > -1 and tp > -1: |
|
| 666 # Check if there is data |
|
| 667 a = data_lr[v][wp, tp, :] |
|
| 668 d = np.average(np.ma.masked_array(a, np.isnan(a))) |
|
| 669 if np.ma.min(d) is not np.ma.masked: |
|
| 670 print(f'\tWe have LR data for {v}') |
|
| 671 # Save data into common structure |
|
| 672 data_var[w, t, :] = a |
|
| 673 if np.average(np.ma.masked_array(data_error_positive_lr[v][wp, tp, :], np.isnan( |
|
| 674 data_error_positive_lr[v][wp, tp, :]))) is not np.ma.masked: |
|
| 675 data_error_positive_var[w, t, :] = data_error_positive_lr[v][wp, tp, :] |
|
| 676 if np.average(np.ma.masked_array(data_error_negative_lr[v][wp, tp, :], np.isnan( |
|
| 677 data_error_negative_lr[v][wp, tp, :]))) is not np.ma.masked: |
|
| 678 data_error_negative_var[w, t, :] = data_error_negative_lr[v][wp, tp, :] |
|
| 679 except ValueError: |
|
| 680 # i.e. no 1064 wavelength in dimensions_lr |
|
| 681 pass |
|
| 682 # except IndexError: |
|
| 683 # pass |
|
| 684 |
|
| 685 # Store data in the global matrices |
|
| 686 if variables_with_data.index(v) == 0: |
|
| 687 data_all = {v: data_var} |
|
| 688 data_error_positive = {v: data_error_positive_var} |
|
| 689 data_error_negative = {v: data_error_negative_var} |
|
| 690 else: |
|
| 691 data_all[v] = data_var |
|
| 692 data_error_positive[v] = data_error_positive_var |
|
| 693 data_error_negative[v] = data_error_negative_var |
|
| 694 |
|
| 695 # Plot |
|
| 696 timeiter = dimensions['time'] |
|
| 697 # Default plotting |
|
| 698 dimensions_t = dimensions |
|
| 699 for t in range(len(dimensions['time'])): |
|
| 700 print(f'plotting hr & lr for {timeiter[t]}') |
|
| 701 dimensions_t['time'] = [timeiter[t]] |
|
| 702 for vr in range(len(variables_with_data)): |
|
| 703 if vr == 0: |
|
| 704 data_t = {variables_with_data[vr]: data_all[variables_with_data[vr]][:, t:t + 1, :]} |
|
| 705 else: |
|
| 706 data_t[variables_with_data[vr]] = data_all[variables_with_data[vr]][:, t:t + 1, :] |
|
| 707 |
|
| 708 fig = plot_vertical_profiles_plotly_allres( |
|
| 709 variables=variables_with_data, |
|
| 710 data=data_t, |
|
| 711 dimensions=dimensions_t, |
|
| 712 y_array=altitude, |
|
| 713 positive_error_array=data_error_positive, |
|
| 714 negative_error_array=data_error_negative, |
|
| 715 xaxis_label=variables_axis, |
|
| 716 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
|
| 717 title=station_location + " (" + station_id.upper() + ") - " + str(datetime.fromtimestamp(dimensions_t['time'][0]).strftime('%d/%m/%Y %H:%M:%S')) + " - ELDA MWL - High and low resolution") |
|
| 718 |
|
| 719 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
|
| 720 fig.show() |
|
| 721 |
|
| 722 # Save the plot |
|
| 723 filename = "ELDAmwl_" + netcdf_file[0:3].upper() + "_" + datetime.fromtimestamp( |
|
| 724 dimensions['time'][0]).strftime('%Y%m%d-%H%M%S') + "_all.html" |
|
| 725 fig.write_html(html_path + filename) |
|
| 726 |
|