eldamwl_plot.py

changeset 4
75213aef70b8
parent 2
763a7ac22031
equal deleted inserted replaced
3:bd2181f8295e 4:75213aef70b8
2 # import xarray as xr 2 # import xarray as xr
3 from config import * 3 from config import *
4 import plotly.graph_objects as go 4 import plotly.graph_objects as go
5 from plotly.subplots import make_subplots 5 from plotly.subplots import make_subplots
6 import netCDF4 as nc 6 import netCDF4 as nc
7 from datetime import datetime 7 from datetime import datetime, timezone
8 import numpy as np 8 import numpy as np
9 import sys 9 import sys
10 from os.path import exists 10 from os.path import exists
11
12
13 def check_group_presence(nc_file_path, group_name):
14 with nc.Dataset(nc_file_path, 'r') as dataset:
15 if group_name in dataset.groups:
16 print(f'{group_name} group exists')
17 return True
18 else:
19 print(f'{group_name} group does not exist')
20 return False
11 21
12 22
13 def read_variable_in_group(nc_file_path, group_name, variable_name): 23 def read_variable_in_group(nc_file_path, group_name, variable_name):
14 try: 24 try:
15 with nc.Dataset(nc_file_path, 'r') as dataset: 25 with nc.Dataset(nc_file_path, 'r') as dataset:
363 # Files for testing 373 # Files for testing
364 # Backscatter and extinction, no error: 374 # Backscatter and extinction, no error:
365 # netcdf_file = 'hpb_012_0000598_201810172100_201810172300_20181017oh00_ELDAmwl_v0.0.1.nc' 375 # netcdf_file = 'hpb_012_0000598_201810172100_201810172300_20181017oh00_ELDAmwl_v0.0.1.nc'
366 # Extinction with error: 376 # Extinction with error:
367 # netcdf_file = 'hpb_012_0000627_202308240200_202308240400_20230824hpb0200_ELDAmwl_v0.0.1.nc' 377 # netcdf_file = 'hpb_012_0000627_202308240200_202308240400_20230824hpb0200_ELDAmwl_v0.0.1.nc'
378 # v0.0.3
379 # pot_012_0000721_202406081503_202406081601_20240608pot150N_ELDAmwl_v0.0.3.nc
368 380
369 381
370 try: 382 try:
371 netcdf_file = sys.argv[1] 383 netcdf_file = sys.argv[1]
372 except: 384 except:
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

mercurial