Skip to content

Commit

Permalink
Issue #337 added logging support
Browse files Browse the repository at this point in the history
  • Loading branch information
bikegeek committed Apr 26, 2023
1 parent 5710314 commit af4d08d
Showing 1 changed file with 158 additions and 25 deletions.
183 changes: 158 additions & 25 deletions metplotpy/plots/skew_t/skew_t.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
# ============================*

import sys
import os
import re
import logging
import warnings
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
Expand All @@ -22,6 +25,10 @@
"""

# Suppress the UserWarning generated by Metpy skewt.py: "color is redundantly defined
# by the 'color' keyword argument..."
warnings.filterwarnings(action='ignore', category=UserWarning)


def extract_sounding_data(input_file):
with open(input_file) as infile:
Expand All @@ -42,7 +49,7 @@ def extract_sounding_data(input_file):

# Now extract the lines that are in the SOUNDING section. The first line
# contains the pressure levels in mb.
pressure_levels_row:list = data[start_line + 2: start_line + 3]
pressure_levels_row: list = data[start_line + 2: start_line + 3]
# Remove the nlevel and nlevel values from the list
only_pressure_levels = pressure_levels_row[0].split()
pressure_levels = only_pressure_levels[3:]
Expand Down Expand Up @@ -92,6 +99,7 @@ def retrieve_date_and_basin(input_file) -> tuple:

return ymd_date, basin_storm_info


def retrieve_units(sounding_data: pd.DataFrame) -> dict:
'''
Retrieve the units from the ASCII file.
Expand Down Expand Up @@ -171,7 +179,15 @@ def extract_sfc_pressures(sounding_data: pd.DataFrame, pressure_levels: list,
def retrieve_pressures(sounding_data: pd.DataFrame, hour_of_interest: str,
pressure_levels: list) -> list:
'''For each hour of interest, create the list of pressures in mb, extracted from
the ASCII data. '''
the ASCII data.
Args:
sounding_data: The dataframe containing the sounding data.
hour_of_interest: The hour of sounding data.
all_pressure_levels: A list of all the numerical values of pressure in mb
(represented as strings)
'''

# First, get the surface pressure level, all the other pressure levels that are
# above surface level are the same
Expand All @@ -190,6 +206,12 @@ def convert_pressures_to_ints(all_pressure_levels: list) -> list:
''' Convert the str representation of the pressures into ints so they can be used
by Metpy to generate a
skew T plot.
Args:
sounding_data: The dataframe containing the sounding data.
hour_of_interest: The hour of sounding data.
all_pressure_levels: A list of all the numerical values of pressure in mb
(represented as strings)
'''
pressures_as_int = [int(level) for level in all_pressure_levels]

Expand Down Expand Up @@ -413,14 +435,40 @@ def retrieve_height(sounding_data: pd.DataFrame, hour_of_interest: str,
return hgt_by_hour


def create_skew_t(input_file: str) -> None:
def create_skew_t(input_file: str, config: dict) -> None:
'''
Create a skew T diagram from the TC Diag output.
Args:
input_file: The input file of interest. Generate skew T plots for
all the sounding hours of interest (or all hours), as
indicated in the configuration file.
config: A dictionary representation of the settings and their values
in the configuration file.
Return:
None, generate plots as png files in the specified output file directory.
'''

logging.info(' Creating skew T plots for input file %s ', input_file)
sounding_df, plevs = extract_sounding_data(input_file)

# For each hour of available sounding data, generate a skew T plot
# For each hour of available sounding data, generate a skew T plot.
# Each column contains all the sounding data for a particular hour 0-240
columns = list(sounding_df.columns)

# Limit times to the first few
times_list = columns[2:6]
date_ymdh, basin_storm = retrieve_date_and_basin(input_file)

# Limit times to those specified in the configuration file.
if config['all_sounding_hours']:
# Columns 0-1 are Field names and their units.
times_list = columns[2:]
else:
times_list_config = config['sounding_hours_of_interest']
# Convert integers into strings in the event that the user indicated
# integers in the config file instead of strings for the hours of interest.
times_list = [str(cur_time) for cur_time in times_list_config]

for cur_time in times_list:
# Retrieve all the pressures
Expand All @@ -446,31 +494,80 @@ def create_skew_t(input_file: str) -> None:
height = retrieve_height(sounding_df, cur_time, all_pressure_levels)

# Generate plot
fig = plt.figure(figsize=(9, 9))
fig_width = config['figure_size_width']
fig_height = config['figure_size_height']
fig = plt.figure(figsize=(fig_width, fig_height))
skew = SkewT(fig)
skew.plot(pressure, temperature, 'r', linewidth=2, linestyle='-')
skew.plot(pressure, dew_pt, 'g', linewidth=2, linestyle='-')
skew.plot_barbs(pressure, u_winds, v_winds)

# skew.plot_barbs(pressure, u_winds, v_winds)
skew.plot_dry_adiabats()
skew.plot_moist_adiabats()
skew.plot_mixing_lines()
skew.ax.set_xlim(-35, 40)
temp_linewidth = config['temp_line_thickness']
temp_linestyle = config['temp_line_style']
temp_linecolor = config['temp_line_color']
skew.plot(pressure, temperature, 'r', linewidth=temp_linewidth,
linestyle=temp_linestyle, color=temp_linecolor)

dewpt_linewidth = config['dewpt_line_thickness']
dewpt_linestyle = config['dewpt_line_style']
dewpt_linecolor = config['dewpt_line_color']
skew.plot(pressure, dew_pt, 'g', linewidth=dewpt_linewidth,
linestyle=dewpt_linestyle, color=dewpt_linecolor)

# Adiabat and mixing lines.
if config['display_dry_adiabats']:
skew.plot_dry_adiabats()
if config['display_moist_adiabats']:
skew.plot_moist_adiabats()
if config['display_mixing_lines']:
skew.plot_mixing_lines()

# Wind barbs
if config['display_windbarbs']:
skew.plot_barbs(pressure, u_winds, v_winds)

# Add height labels
decimate = 2
decimate = config['decimate_barbs']
for p, t, h in zip(pressure[::decimate], temperature[::decimate],
height[::decimate]):
if p >= 100:
# Heights adjacent to temperature curve.
# skew.ax.text(t, p, round(h, 0 ))
# Heights adjacent to temperature curve. Either along the y2 axis
# or next to the temperature curve
if config['level_labels_along_y2-axis']:
# Axis transform to move to y2 axis
skew.ax.text(1.08, p, round(h, 0),
transform=skew.ax.get_yaxis_transform(which='tick2'))

else:
skew.ax.text(t, p, round(h, 0))

title = "Skew T for " + date_ymdh + " " + basin_storm + " hour: " \
+ str(cur_time)

# Focus in on curves to eliminate "white space" in plot.
if config['set_x_axis_limits']:
x_axis_min = config['x_axis_min']
x_axis_max = config['x_axis_max']
skew.ax.set_xlim(x_axis_min, x_axis_max)

# Axis transform to move to x2 axis
skew.ax.text(1.08, p, round(h, 0),
transform=skew.ax.get_yaxis_transform(which='tick2'))
title = "Skew T for " + input_file + " hour: " + str(cur_time)
plt.title(title)

# Save the plots/figures in the output directory as specified, using
# the same name as the input file, appending the hour of the sounding to
# the data file name, then replacing the datat file extension
# with '.png'.



# Create the plot files in the output directory specified in the config
# file.
output_dir = config['output_directory']
try:
os.mkdir(output_dir)
except FileExistsError:
# Ignore if file/diretory already exists, this is OK.
pass
filename_only, _ = os.path.splitext(input_file)
renamed = filename_only + "_" + cur_time + "_hr.png"
plt.savefig(renamed)

plt.show()


Expand All @@ -489,11 +586,47 @@ def main(config_filename=None):
config_file = config_filename
with open(config_file, 'r') as stream:
try:
yaml.load(stream, Loader=yaml.FullLoader)
config = yaml.load(stream, Loader=yaml.FullLoader)

# Set up the logging.
log_dir = config['log_directory']
log_file = config['log_filename']
log_full_path = os.path.join(log_dir, log_file)
try:
os.mkdir(log_dir)
except FileExistsError:
# If directory already exists, this is OK. Continue.
pass

logging.basicConfig(filename=log_full_path, filemode='w',
format='%(name)s - %(levelname)s - (message)s ')

log_level = config['log_level']
if log_level == 'DEBUG':
logging.basicConfig(level=logging.DEBUG)
elif log_level == 'INFO':
logging.basicConfig(level=logging.INFO)
elif log_level == 'WARNING':
logging.basicConfig(level=logging.WARNING)
else:
# log_level == 'ERROR'
logging.basicConfig(level=logging.ERROR)

# Get the list of input files to visualize.
input_dir = config['input_directory']
file_ext = config['input_file_extension']
for root, dir, files in os.walk(input_dir):
all_files = [file for file in files if file.endswith(file_ext)]
files_of_interest = [os.path.join(root, file) for file in all_files]

# Create skew T diagrams for each input file.
for file_of_interest in files_of_interest:
create_skew_t(file_of_interest, config)

# create_skew_t(input_file, config)
except yaml.YAMLError as exc:
print(exc)


if __name__ == "__main__":
create_skew_t(
'/Volumes/d1/minnawin/TCDiag_Data/2022/al092022/sal092022_avno_doper_2022092200_diag.dat')
main()

0 comments on commit af4d08d

Please sign in to comment.