[3459] | 1 | ############################################################ |
---|
| 2 | ### Python script to analyse a NetCDF file for debugging ### |
---|
| 3 | ############################################################ |
---|
| 4 | |
---|
| 5 | ### This script gives useful information about a NetCDF file |
---|
| 6 | ### to help for debugging. For each variable, it outputs the |
---|
| 7 | ### dimensions, the min & max values, the average value and |
---|
| 8 | ### warns the user in case of NaN or negative values. |
---|
| 9 | ### The file name is asked to the user in the terminal. |
---|
| 10 | |
---|
| 11 | import os |
---|
| 12 | import readline |
---|
| 13 | import glob |
---|
| 14 | from netCDF4 import Dataset |
---|
| 15 | import numpy as np |
---|
| 16 | |
---|
| 17 | ############################################################ |
---|
| 18 | ### Setup readline for file name autocompletion |
---|
| 19 | def complete(text,state): |
---|
| 20 | line = readline.get_line_buffer().split() |
---|
| 21 | # Use glob to find all matching files/directories for the current text |
---|
| 22 | if '*' not in text: |
---|
| 23 | text += '*' |
---|
| 24 | matches = glob.glob(os.path.expanduser(text)) |
---|
| 25 | # Add '/' if the match is a directory |
---|
| 26 | matches = [match + '/' if os.path.isdir(match) else match for match in matches] |
---|
| 27 | |
---|
| 28 | try: |
---|
| 29 | return matches[state] |
---|
| 30 | except IndexError: |
---|
| 31 | return None |
---|
| 32 | |
---|
| 33 | ### Function to analyze a variable in a NetCDF file |
---|
| 34 | def analyze_variable(variable): |
---|
| 35 | # Get the data for the variable |
---|
| 36 | data = variable[:] |
---|
| 37 | |
---|
| 38 | # Calculate min, max and mean |
---|
[3465] | 39 | if np.isnan(data).all(): |
---|
| 40 | min_val = np.nan |
---|
| 41 | max_val = np.nan |
---|
| 42 | mean_val = np.nan |
---|
| 43 | else: |
---|
| 44 | data_min = np.nanmin(data) # Min value ignoring NaN |
---|
| 45 | data_max = np.nanmax(data) # Max value ignoring NaN |
---|
| 46 | data_mean = np.nanmean(data) # Mean value ignoring NaN |
---|
[3459] | 47 | |
---|
| 48 | # Check if there are any NaN values |
---|
| 49 | has_nan = np.isnan(data).any() |
---|
| 50 | |
---|
| 51 | # Check for negative values |
---|
| 52 | has_negative = (data < 0).any() |
---|
| 53 | |
---|
| 54 | # Print the results |
---|
| 55 | print(f"\nAnalysis of variable: {variable.name}") |
---|
| 56 | print(f" Dimensions: {variable.dimensions}") |
---|
| 57 | print(f" Min value : {data_min:>12.6e}") |
---|
| 58 | print(f" Max value : {data_max:>12.6e}") |
---|
| 59 | print(f" Mean value: {data_mean:>12.6e}") |
---|
| 60 | if has_nan: |
---|
| 61 | print(f" \033[91mContains NaN values!\033[0m") |
---|
| 62 | if has_negative: |
---|
| 63 | print(f" \033[93mWarning: contains negative values!\033[0m") |
---|
| 64 | |
---|
| 65 | ### Main function |
---|
| 66 | def analyze_netcdf(): |
---|
| 67 | # Ask for the file name |
---|
| 68 | readline.set_completer(complete) |
---|
| 69 | readline.parse_and_bind('tab: complete') |
---|
| 70 | file = input("Enter the name of the NetCDF file: ") |
---|
| 71 | |
---|
| 72 | # Open the NetCDF file |
---|
| 73 | try: |
---|
| 74 | dataset = Dataset(file,mode='r') |
---|
| 75 | except FileNotFoundError: |
---|
| 76 | print(f"File '{file}' not found.") |
---|
| 77 | return |
---|
| 78 | |
---|
| 79 | # Iterate through all variables in the dataset to analyze them |
---|
| 80 | for variable_name in dataset.variables: |
---|
| 81 | variable = dataset.variables[variable_name] |
---|
| 82 | analyze_variable(variable) |
---|
| 83 | |
---|
| 84 | # Close the NetCDF file |
---|
| 85 | dataset.close() |
---|
| 86 | |
---|
| 87 | ### Call the main function |
---|
| 88 | analyze_netcdf() |
---|
| 89 | |
---|