[3459] | 1 | ############################################################## |
---|
| 2 | ### Python script to visualize a variable in a NetCDF file ### |
---|
| 3 | ############################################################## |
---|
| 4 | |
---|
| 5 | ### This script can display any variable of a NetCDF file. |
---|
| 6 | ### The file name, the variable to display and eventually the |
---|
| 7 | ### dimension are asked to the user in the terminal. |
---|
| 8 | |
---|
| 9 | import os |
---|
| 10 | import readline |
---|
| 11 | import glob |
---|
| 12 | from netCDF4 import Dataset |
---|
| 13 | import matplotlib.pyplot as plt |
---|
| 14 | import numpy as np |
---|
| 15 | |
---|
| 16 | ############################################################## |
---|
| 17 | ### Setup readline for file name autocompletion |
---|
| 18 | def complete(text,state): |
---|
| 19 | line = readline.get_line_buffer().split() |
---|
| 20 | # Use glob to find all matching files/directories for the current text |
---|
| 21 | if '*' not in text: |
---|
| 22 | text += '*' |
---|
| 23 | matches = glob.glob(os.path.expanduser(text)) |
---|
| 24 | # Add '/' if the match is a directory |
---|
| 25 | matches = [match + '/' if os.path.isdir(match) else match for match in matches] |
---|
| 26 | |
---|
| 27 | try: |
---|
| 28 | return matches[state] |
---|
| 29 | except IndexError: |
---|
| 30 | return None |
---|
| 31 | |
---|
| 32 | ### Function to handle autocomplete for variable names |
---|
| 33 | def complete_variable_names(variable_names): |
---|
| 34 | def completer(text, state): |
---|
| 35 | options = [name for name in variable_names if name.startswith(text)] |
---|
| 36 | if state < len(options): |
---|
| 37 | return options[state] |
---|
| 38 | else: |
---|
| 39 | return None |
---|
| 40 | return completer |
---|
| 41 | |
---|
| 42 | ### Function to visualize a variable from a NetCDF file |
---|
| 43 | def visualize_variable(): |
---|
| 44 | # Ask for the NetCDF file name |
---|
| 45 | readline.set_completer(complete) |
---|
| 46 | readline.parse_and_bind('tab: complete') |
---|
| 47 | file = input("Enter the name of the NetCDF file: ") |
---|
| 48 | |
---|
| 49 | # Open the NetCDF file |
---|
| 50 | try: |
---|
| 51 | dataset = Dataset(file,mode='r') |
---|
| 52 | except FileNotFoundError: |
---|
| 53 | print(f"File '{file}' not found.") |
---|
| 54 | return |
---|
| 55 | |
---|
| 56 | # Display available variables |
---|
| 57 | variable_names = list(dataset.variables.keys()) |
---|
| 58 | print("Available variables:\n",variable_names) |
---|
| 59 | |
---|
| 60 | # Ask for the variable to display |
---|
| 61 | readline.set_completer(complete_variable_names(variable_names)) |
---|
| 62 | variable_name = input("\nEnter the name of the variable you want to visualize: ") |
---|
| 63 | |
---|
| 64 | # Check if the variable exists |
---|
| 65 | if variable_name not in dataset.variables: |
---|
| 66 | print(f"Variable '{variable_name}' not found in the dataset.") |
---|
| 67 | dataset.close() |
---|
| 68 | return |
---|
| 69 | |
---|
| 70 | # Extract the selected variable |
---|
| 71 | variable = dataset.variables[variable_name][:] |
---|
| 72 | |
---|
| 73 | # Extract latitude, longitude and altitude |
---|
| 74 | latitude = dataset.variables['latitude'][:] |
---|
| 75 | longitude = dataset.variables['longitude'][:] |
---|
| 76 | |
---|
| 77 | # Check if the variable has altitude and time dimensions |
---|
| 78 | dimensions = dataset.variables[variable_name].dimensions |
---|
| 79 | print(f"\nDimensions of '{variable_name}': {dimensions}") |
---|
| 80 | |
---|
| 81 | # If the variable has a time dimension, ask for the time index |
---|
| 82 | if 'Time' in dimensions: |
---|
| 83 | time_index = int(input(f"Enter the time index (0 to {variable.shape[0] - 1}): ")) |
---|
| 84 | else: |
---|
| 85 | time_index = None |
---|
| 86 | |
---|
| 87 | # If the variable has an altitude dimension, ask for the altitude index |
---|
| 88 | if 'altitude' in dimensions: |
---|
| 89 | altitude = dataset.variables['altitude'][:] |
---|
| 90 | altitude_index = int(input(f"Enter the altitude index (0 to {altitude.shape[0] - 1}): ")) |
---|
| 91 | else: |
---|
| 92 | altitude_index = None |
---|
| 93 | |
---|
| 94 | # Prepare the 2D slice for plotting |
---|
| 95 | if time_index is not None and altitude_index is not None: |
---|
| 96 | data_slice = variable[time_index,altitude_index,:,:] |
---|
| 97 | elif time_index is not None: |
---|
| 98 | data_slice = variable[time_index,:,:] |
---|
| 99 | elif altitude_index is not None: |
---|
| 100 | data_slice = variable[altitude_index,:,:] |
---|
| 101 | else: |
---|
| 102 | data_slice = variable[:,:] |
---|
| 103 | |
---|
| 104 | # Plot the selected variable |
---|
| 105 | plt.figure(figsize=(10,6)) |
---|
| 106 | plt.contourf(longitude,latitude,data_slice,cmap='viridis') |
---|
| 107 | plt.colorbar(label=f"{variable_name.capitalize()} (units)") # Adjust units based on your data |
---|
| 108 | plt.xlabel('Longitude (degrees)') |
---|
| 109 | plt.ylabel('Latitude (degrees)') |
---|
| 110 | plt.title(f"{variable_name.capitalize()} visualization") |
---|
| 111 | |
---|
| 112 | # Show the plot |
---|
| 113 | plt.show() |
---|
| 114 | |
---|
| 115 | # Close the NetCDF file |
---|
| 116 | dataset.close() |
---|
| 117 | |
---|
| 118 | ### Call the main function |
---|
| 119 | visualize_variable() |
---|