176 clr = clrs[0, colorind] |
186 clr = clrs[0, colorind] |
177 else: |
187 else: |
178 clr = 'rgb(0,0,0)' |
188 clr = 'rgb(0,0,0)' |
179 |
189 |
180 data_values = data[variables[v]][w, t, :] |
190 data_values = data[variables[v]][w, t, :] |
181 error_values = positive_error_array[variables[v]][w, t, :] |
191 if np.average(np.ma.masked_array(data_values, np.isnan(data_values))) is not np.ma.masked: |
182 vertical_levels = y_array["data"][t, :] |
192 vertical_levels = y_array["data"][t, :] |
183 |
193 error_values = positive_error_array[variables[v]][w, t, :] |
184 # Add trace |
194 |
185 fig.add_trace(go.Scatter( |
195 # Add trace |
186 x=data_values, |
196 fig.add_trace(go.Scatter( |
187 y=vertical_levels, |
197 x=data_values, |
188 error_x=dict(array=error_values, width=0, thickness=0.1), |
198 y=vertical_levels, |
189 # ToDo Include distinction between positive and negative errors |
199 error_x=dict(array=error_values, width=0, thickness=0.1), |
190 mode='lines', |
200 # ToDo Include distinction between positive and negative errors |
191 line=dict(width=2, color=clr), |
201 mode='lines', |
192 name=lgnd), |
202 line=dict(width=2, color=clr), |
193 row=rown, col=v + 1, |
203 name=lgnd), |
194 ) |
204 row=rown, col=v + 1, |
195 |
205 ) |
196 # ToDo Check formatting options (showlegend, mapbox) |
206 |
197 fig.update_xaxes({"title": xaxis_label[v]}, row=rown, col=v + 1) |
207 # ToDo Check formatting options (showlegend, mapbox) |
198 fig.update_xaxes({"mirror": True, "ticks": 'outside', "showline": True, "color": "black"}, row=rown, |
208 fig.update_xaxes({"title": xaxis_label[v]}, row=rown, col=v + 1) |
199 col=v + 1) |
209 fig.update_xaxes({"mirror": True, "ticks": 'outside', "showline": True, "color": "black"}, row=rown, |
200 |
210 col=v + 1) |
201 fig.update_xaxes(ticks="outside") |
211 |
202 fig.update_yaxes(ticks="outside", row=rown, col=v + 1) # ToDo check tickformat (i.e. tickformat=":.2e") |
212 fig.update_xaxes(ticks="outside") |
203 if v == 0: |
213 fig.update_yaxes(ticks="outside", row=rown, col=v + 1) |
204 fig.update_yaxes({"title": yaxis_label}, row=rown, col=v + 1) |
214 # ToDo check tickformat (i.e. tickformat=":.2e") |
|
215 if v == 0: |
|
216 fig.update_yaxes({"title": yaxis_label}, row=rown, col=v + 1) |
|
217 |
|
218 # ToDo add boxes |
|
219 a = fig.layout['xaxis']['domain'] |
|
220 # print(a) |
|
221 b = fig.layout['yaxis']['domain'] |
|
222 # print(b) |
|
223 # fig.add_hline(y=b[0], line=dict(color="yellow", width=2), row=rown, col=v+1) |
|
224 # fig.add_hline(y=b[1], line=dict(color="purple", width=2), row=rown, col=v+1) |
|
225 # fig.add_vline(x=a[0], line=dict(color="orange", width=2), row=rown, col=v+1) |
|
226 # fig.add_vline(x=a[1], line=dict(color="pink", width=2), row=rown, col=v+1) |
|
227 # fig.add_shape(type="line", xref="paper", yref="paper", x0=a[0], y0=b[0], x1=a[1], y1=b[1], |
|
228 # line=dict(color="grey", width=2, ), row=rown, col=v+1) |
|
229 # fig.add_shape(type="line", xref="paper", yref="paper", x0=1, y0=1, x1=1, y1=0, |
|
230 # line=dict(color="blue", width=2, ), row=rown, col=v+1) |
|
231 # fig.add_shape(type="line", xref="paper", yref="paper", x0=0, y0=0, x1=1, y1=0, |
|
232 # line=dict(color="red", width=2, ), row=rown, col=v+1) |
|
233 # fig.add_shape(type="line", xref="paper", yref="paper", x0=0, y0=0, x1=0, y1=1, |
|
234 # line=dict(color="green", width=2, ), row=rown, col=v+1) |
|
235 # fig.add_hline(y=0, line=dict(color="yellow", width=2)) |
|
236 # print(fig.data[0]['x']) |
205 |
237 |
206 # Set axis labels and title |
238 # Set axis labels and title |
207 fig.update_layout( |
239 fig.update_layout( |
208 yaxis_title=yaxis_label, |
240 yaxis_title=yaxis_label, |
209 title=title, |
241 title=title, |
214 ) |
246 ) |
215 |
247 |
216 return fig |
248 return fig |
217 |
249 |
218 |
250 |
|
251 def plot_vertical_profiles_plotly_allres(variables, data, dimensions, y_array, positive_error_array, |
|
252 negative_error_array, xaxis_label, yaxis_label, title): |
|
253 """ |
|
254 ToDo Complete |
|
255 Plot vertical profiles using plotly |
|
256 |
|
257 Parameters: |
|
258 - |
|
259 |
|
260 Returns: |
|
261 - fig: html |
|
262 """ |
|
263 |
|
264 # Set number of columns, number of rows, and subtitles if needed |
|
265 ncols = len(variables) |
|
266 nrows = 1 |
|
267 subtitles = '' |
|
268 |
|
269 # Create figure |
|
270 fig = make_subplots(rows=nrows, cols=ncols, |
|
271 subplot_titles=subtitles, |
|
272 shared_yaxes=True) |
|
273 |
|
274 # Define colours |
|
275 clrs = [['rgb(0,35,255)', 'rgb(0,20,150)'], # UV |
|
276 ['rgb(90,210,50)', 'rgb(40,90,25)'], # VIS |
|
277 ['rgb(250,30,30)', 'rgb(130,30,10)']] # IR |
|
278 clrs = np.array(clrs) |
|
279 |
|
280 # Plot |
|
281 for v in range(len(variables)): |
|
282 for t in range(len(dimensions['time'])): |
|
283 for w in range(len(dimensions['wavelength_res'])): |
|
284 wl = float(dimensions['wavelength_res'][w].split(' ')[0]) |
|
285 wn = str(dimensions['wavelength_res'][w]) |
|
286 lgnd = wn.replace(' ', ' nm ') |
|
287 rown = 1 |
|
288 if wn.find('LR') > 0: |
|
289 colorind = 0 |
|
290 else: |
|
291 colorind = 1 |
|
292 |
|
293 # colour definition |
|
294 if abs(wl - 1064) < 1: |
|
295 clr = clrs[2, colorind] |
|
296 elif abs(wl - 532) < 1: |
|
297 clr = clrs[1, colorind] |
|
298 elif abs(wl - 355) < 1: |
|
299 clr = clrs[0, colorind] |
|
300 else: |
|
301 clr = 'rgb(0,0,0)' |
|
302 |
|
303 data_values = data[variables[v]][w, t, :] |
|
304 if np.average(np.ma.masked_array(data_values, np.isnan(data_values))) is not np.ma.masked: |
|
305 vertical_levels = y_array["data"][t, :] |
|
306 error_values = positive_error_array[variables[v]][w, t, :] |
|
307 # Add trace |
|
308 fig.add_trace(go.Scatter( |
|
309 x=data_values, |
|
310 y=vertical_levels, |
|
311 error_x=dict(array=error_values, width=0, thickness=0.1), |
|
312 # ToDo Include distinction between positive and negative errors |
|
313 mode='lines', |
|
314 line=dict(width=2, color=clr), |
|
315 name=lgnd), |
|
316 row=rown, col=v + 1, |
|
317 ) |
|
318 |
|
319 # ToDo Check formatting options (showlegend, mapbox) |
|
320 fig.update_xaxes({"title": xaxis_label[v]}, row=rown, col=v + 1) |
|
321 fig.update_xaxes({"mirror": True, "ticks": 'outside', "showline": True, "color": "black"}, row=rown, |
|
322 col=v + 1) |
|
323 |
|
324 fig.update_xaxes(ticks="outside") |
|
325 fig.update_yaxes(ticks="outside", row=rown, col=v + 1) |
|
326 # ToDo check tickformat (i.e. tickformat=":.2e") |
|
327 if v == 0: |
|
328 fig.update_yaxes({"title": yaxis_label}, row=rown, col=v + 1) |
|
329 |
|
330 # ToDo add boxes |
|
331 a = fig.layout['xaxis']['domain'] |
|
332 # print(a) |
|
333 b = fig.layout['yaxis']['domain'] |
|
334 # print(b) |
|
335 # fig.add_hline(y=b[0], line=dict(color="yellow", width=2), row=rown, col=v+1) |
|
336 # fig.add_hline(y=b[1], line=dict(color="purple", width=2), row=rown, col=v+1) |
|
337 # fig.add_vline(x=a[0], line=dict(color="orange", width=2), row=rown, col=v+1) |
|
338 # fig.add_vline(x=a[1], line=dict(color="pink", width=2), row=rown, col=v+1) |
|
339 # fig.add_shape(type="line", xref="paper", yref="paper", x0=a[0], y0=b[0], x1=a[1], y1=b[1], |
|
340 # line=dict(color="grey", width=2, ), row=rown, col=v+1) |
|
341 # fig.add_shape(type="line", xref="paper", yref="paper", x0=1, y0=1, x1=1, y1=0, |
|
342 # line=dict(color="blue", width=2, ), row=rown, col=v+1) |
|
343 # fig.add_shape(type="line", xref="paper", yref="paper", x0=0, y0=0, x1=1, y1=0, |
|
344 # line=dict(color="red", width=2, ), row=rown, col=v+1) |
|
345 # fig.add_shape(type="line", xref="paper", yref="paper", x0=0, y0=0, x1=0, y1=1, |
|
346 # line=dict(color="green", width=2, ), row=rown, col=v+1) |
|
347 # fig.add_hline(y=0, line=dict(color="yellow", width=2)) |
|
348 # print(fig.data[0]['x']) |
|
349 |
|
350 # Set axis labels and title |
|
351 fig.update_layout( |
|
352 yaxis_title=yaxis_label, |
|
353 title=title, |
|
354 template="seaborn", # You can change the template as per your preference |
|
355 # ['ggplot2', 'seaborn', 'simple_white', 'plotly', 'plotly_white', 'plotly_dark', 'presentation', |
|
356 # 'xgridoff', 'ygridoff', 'gridon', 'none'] |
|
357 height=max(600, 450 * rown), width=min(max(400 * len(variables), 750), 1400), |
|
358 ) |
|
359 |
|
360 return fig |
|
361 |
|
362 |
219 # Files for testing |
363 # Files for testing |
220 # netcdf_file = 'hpb_012_0000598_201810172100_201810172300_20181017oh00_ELDAmwl_v0.0.1.nc' # Backscatter and extinction, no error |
364 # Backscatter and extinction, no error: |
221 # netcdf_file = 'hpb_012_0000627_202308240200_202308240400_20230824hpb0200_ELDAmwl_v0.0.1.nc' # Extinction with error |
365 # netcdf_file = 'hpb_012_0000598_201810172100_201810172300_20181017oh00_ELDAmwl_v0.0.1.nc' |
|
366 # Extinction with error: |
|
367 # netcdf_file = 'hpb_012_0000627_202308240200_202308240400_20230824hpb0200_ELDAmwl_v0.0.1.nc' |
222 |
368 |
223 |
369 |
224 try: |
370 try: |
225 netcdf_file = sys.argv[1] |
371 netcdf_file = sys.argv[1] |
226 except: |
372 except: |
227 print('Syntax is incorrect, you need to pass the filename of the file to be plotted.\n' |
373 print('Syntax is incorrect, you need to pass the filename of the file to be plotted.\n' |
228 'Example: ./eldamwl_plot.py hpb_012_0000598_201810172100_201810172300_20181017oh00_ELDAmwl_v0.0.1.nc') |
374 'Example: ./eldamwl_plot.py hpb_012_0000598_201810172100_201810172300_20181017oh00_ELDAmwl_v0.0.1.nc') |
229 exit() |
375 exit() |
230 |
376 |
|
377 # Print help |
|
378 if netcdf_file == '-h' or netcdf_file == '--h': |
|
379 print('Syntax: ./eldamwl_plot.py hpb_012_0000598_201810172100_201810172300_20181017oh00_ELDAmwl_v0.0.1.nc') |
|
380 exit() |
|
381 |
231 netcdf_file_path = netcdf_path + netcdf_file |
382 netcdf_file_path = netcdf_path + netcdf_file |
232 |
383 |
233 file_exists = exists(netcdf_file_path) |
384 file_exists = exists(netcdf_file_path) |
234 if not file_exists: |
385 if not file_exists: |
235 print('The file that you provided does not exist.') |
386 print('The file that you provided does not exist.') |
238 # Groups of data in the NetCDF file (low and high resolution) |
389 # Groups of data in the NetCDF file (low and high resolution) |
239 groups = ['lowres_products', 'highres_products'] |
390 groups = ['lowres_products', 'highres_products'] |
240 groups_names = ['Low resolution', 'High resolution'] |
391 groups_names = ['Low resolution', 'High resolution'] |
241 |
392 |
242 # Variables that we want to plot |
393 # Variables that we want to plot |
243 variable = ['backscatter', 'extinction', 'lidarratio', 'volumedepolarization', 'particledepolarization'] # ToDo Test particledepolarization when available |
394 variable = ['backscatter', 'extinction', 'lidarratio', 'volumedepolarization', |
|
395 'particledepolarization'] # ToDo Test particledepolarization when available |
244 # Errors associated to the variables |
396 # Errors associated to the variables |
245 variable_error = ['error_backscatter', 'error_extinction', 'error_lidarratio', |
397 variable_error = ['error_backscatter', 'error_extinction', 'error_lidarratio', |
246 'positive_systematic_error_volumedepolarization', 'error_particledepolarization'] |
398 'positive_systematic_error_volumedepolarization', 'error_particledepolarization'] |
247 variable_negative_error_volumedepol = 'negative_systematic_error_volumedepolarization' |
399 variable_negative_error_volumedepol = 'negative_systematic_error_volumedepolarization' |
248 # Other variables: |
400 # ToDo Consider adding other variables: |
249 # cloud_mask (time, level) |
401 # cloud_mask (time, level) |
250 |
402 |
251 |
403 # Read global attributes |
|
404 station_id = read_global_attribute(netcdf_file_path, 'station_ID') |
|
405 station_location = read_global_attribute(netcdf_file_path, 'location') |
|
406 |
|
407 # Read data |
252 for g in range(len(groups)): |
408 for g in range(len(groups)): |
253 # Read the altitude variable |
409 # Read the altitude variable |
254 altitude = read_variable_in_group(netcdf_file_path, groups[g], 'altitude') |
410 altitude = read_variable_in_group(netcdf_file_path, groups[g], 'altitude') |
255 |
411 |
256 if altitude['metadata']['units'] == 'm': |
412 if altitude['metadata']['units'] == 'm': |
303 else: |
459 else: |
304 print(f'There is no data for {variable[v]} in the {groups_names[g]} group.') |
460 print(f'There is no data for {variable[v]} in the {groups_names[g]} group.') |
305 |
461 |
306 dimensions = dim |
462 dimensions = dim |
307 |
463 |
308 # Ask user if he/she wants to plot different temporal profiles in different rows |
464 # Save lowres and highres in variables to plot them together afterwards |
|
465 if groups[g] == 'lowres_products': |
|
466 altitude_lr = altitude |
|
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 |
309 if g == 0: |
484 if g == 0: |
310 # Initialize |
485 # Initialize |
311 timeinplots = False |
486 timeinplots = True |
312 timeinrows = False |
487 timeinrows = False |
313 # Ask user how he/she wants the plot |
488 # If interactive (config.py) = True, ask user how he/she wants the plot |
314 if len(dimensions['time']) > 1: |
489 if interactive and len(dimensions['time']) > 1: |
315 answer = input( |
490 answer = input( |
316 f"There are {len(dimensions['time'])} temporal profiles, do you want to plot them on different plots [y/n]? ") |
491 f"There are {len(dimensions['time'])} temporal profiles, " |
317 if answer[0:1].lower() == 'y': |
492 f"do you want to plot them on different plots [y/n]? ") |
318 timeinplots = True |
493 if answer[0:1].lower() == 'n': |
319 if timeinplots == False: |
494 timeinplots = False |
|
495 if not timeinplots: |
320 answer = input( |
496 answer = input( |
321 f"There are {len(dimensions['time'])} temporal profiles, do you want to plot them on different rows [y/n]? ") |
497 f"There are {len(dimensions['time'])} temporal profiles, " |
|
498 f"do you want to plot them on different rows [y/n]? ") |
322 if answer[0:1].lower() == 'y': |
499 if answer[0:1].lower() == 'y': |
323 timeinrows = True |
500 timeinrows = True |
324 |
501 |
325 if variables_with_data is not None: |
502 if variables_with_data is not None: |
326 timeiter = dimensions['time'] |
503 timeiter = dimensions['time'] |
327 if timeinplots == True: |
504 if timeinplots: |
|
505 # Default plotting |
328 dimensions_t = dimensions |
506 dimensions_t = dimensions |
329 for t in range(len(dimensions['time'])): |
507 for t in range(len(dimensions['time'])): |
330 dimensions_t['time'] = [timeiter[t]] |
508 dimensions_t['time'] = [timeiter[t]] |
331 for vr in range(len(variables_with_data)): |
509 for vr in range(len(variables_with_data)): |
332 if vr == 0: |
510 if vr == 0: |
367 altitude, |
544 altitude, |
368 data_error_positive, |
545 data_error_positive, |
369 data_error_negative, |
546 data_error_negative, |
370 xaxis_label=variables_axis, |
547 xaxis_label=variables_axis, |
371 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
548 yaxis_label=altitude['metadata']['long_name'] + ' [' + altitude['metadata']['units'] + ']', |
372 title=netcdf_file[0:3].upper() + " - " + str( |
549 title=station_location + " (" + station_id.upper() + ") - " + str( |
373 datetime.fromtimestamp(dimensions['time'][0]).strftime('%d/%m/%Y')) + " - ELDA MWL " + groups_names[ |
550 datetime.fromtimestamp(dimensions['time'][0]).strftime('%d/%m/%Y')) + " - ELDA MWL " + groups_names[ |
374 g], |
551 g], |
375 timeinrows=timeinrows |
552 timeinrows=timeinrows |
376 ) |
553 ) |
377 |
554 |
378 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
555 # Show the plot (in Jupyter Notebook or Jupyter Lab) |
379 fig.show() |
556 # fig.show() |
380 |
557 |
381 # Save the plot |
558 # Save the plot |
382 if timeinrows == True: |
559 if timeinrows: |
383 filename = "ELDAmwl_" + netcdf_file[0:3].upper() + "_" + datetime.fromtimestamp( |
560 filename = "ELDAmwl_" + station_id.upper() + "_" + datetime.fromtimestamp( |
384 dimensions['time'][0]).strftime('%Y%m%d%H%M%S') + '-' + datetime.fromtimestamp( |
561 dimensions['time'][0]).strftime('%Y%m%d%H%M%S') + '-' + datetime.fromtimestamp( |
385 dimensions['time'][-1]).strftime('%Y%m%d%H%M%S') + "_" + groups[g] + "_timeinrows.html" |
562 dimensions['time'][-1]).strftime('%Y%m%d%H%M%S') + "_" + groups[g] + "_timeinrows.html" |
386 else: |
563 else: |
387 filename = "ELDAmwl_" + netcdf_file[0:3].upper() + "_" + datetime.fromtimestamp( |
564 filename = "ELDAmwl_" + station_id.upper() + "_" + datetime.fromtimestamp( |
388 dimensions['time'][0]).strftime('%Y%m%d%H%M%S') + '-' + datetime.fromtimestamp( |
565 dimensions['time'][0]).strftime('%Y%m%d%H%M%S') + '-' + datetime.fromtimestamp( |
389 dimensions['time'][-1]).strftime('%Y%m%d%H%M%S') + "_" + groups[g] + ".html" |
566 dimensions['time'][-1]).strftime('%Y%m%d%H%M%S') + "_" + groups[g] + ".html" |
390 |
567 |
391 fig.write_html(html_path + filename) |
568 fig.write_html(html_path + filename) |
392 |
569 |
393 else: |
570 else: |
394 print(f'There is no data to be plotted in the {groups_names[g]} group.') |
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 |