Skip to content

Commit

Permalink
Feature 240 tcmpr (#322)
Browse files Browse the repository at this point in the history
* add tickformat to xaxes #240

* initial version #240

* initial version #240

* initial version #240

* fixed the type of config_value in calculate_plot_dimension to string  #240

* add more plotly markers  #240

* check if image name is not None before removing the old image  #240

* initial version #240
  • Loading branch information
TatianaBurek authored Feb 28, 2023
1 parent 25f7300 commit 3f95ada
Show file tree
Hide file tree
Showing 39 changed files with 4,082 additions and 5 deletions.
2 changes: 1 addition & 1 deletion metplotpy/plots/base_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ def remove_file(self):
image_name = self.get_config_value('plot_filename')

# remove the old file if it exist
if os.path.exists(image_name):
if image_name is not None and os.path.exists(image_name):
os.remove(image_name)

def show_in_browser(self):
Expand Down
2 changes: 1 addition & 1 deletion metplotpy/plots/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ def create_list_by_plot_val_ordering(self, setting_to_order: str) -> list:
return ordered_settings_list


def calculate_plot_dimension(self, config_value: int , output_units: str) -> int:
def calculate_plot_dimension(self, config_value: str , output_units: str) -> int:
'''
To calculate the width or height that defines the size of the plot.
Matplotlib defines these values in inches, Python plotly defines these
Expand Down
147 changes: 147 additions & 0 deletions metplotpy/plots/config/tcmpr_defaults.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
alpha: 0.05
colors:
- '#696969'
- '#0000FF'
- '#008000'
- '#000000'
- '#ff0000'
- '#800080'
- '#FFA500'
create_html: 'False'
derived_series_1: []
fixed_vars_vals_input:
BASIN:
BASIN_0:
- AL

grid_col: '#cccccc'
grid_lty: 3
grid_lwd: 1
grid_on: 'False'
grid_x: listX

indy_vals: []

indy_label: []

indy_var: 'LEAD'
legend_box: o
legend_inset:
x: 0.0
y: -0.25
legend_ncol: 3
legend_size: 0.8
line_type: None

list_stat_1: []

mar:
l: 0 #left margin
r: 0 #right margin
b: 105 #bottom margin
t: 120 #top margin
mgp:
- 1
- 1
- 0
plot_caption: ''
plot_disp: []

plot_height: 8.5
plot_res: 72
plot_stat: median
plot_type: png16m
plot_units: in
plot_width: 11.0
series_order: []
series_val_1: {}
series_ci: []
series_line_width:
- 1
- 1
- 1
series_line_style:
- '-'
- '-'
- '-'
series_symbols:
- 'circle-open'
- 'circle-open'
- 'circle-open'

series_symbols_size:
- 7
- 7
- 7


show_nstats: 'True'

tcst_dir:
tcst_files: []

title:
title_align: 0.5
title_offset: -2.0833
title_size: 1.4
title_weight: 2.0
user_legend: []
x2lab_align: 0.5
x2lab_offset: -0.5
x2lab_size: 0.8
x2lab_weight: 1
x2tlab_horiz: 0.5
x2tlab_orient: 1
x2tlab_perp: 1
x2tlab_size: 0.8
xaxis: 'Lead Time(h)'
xaxis_reverse: 'False'
xlab_align: 0.5
xlab_offset: 2
xlab_size: 1
xlab_weight: 1
xlim: []
xtlab_decim: 0
xtlab_horiz: 0.5
xtlab_orient: 1
xtlab_perp: -0.75
xtlab_size: 1

yaxis_1:
ylab_align: 0.5
ylab_offset: 15
ylab_size: 1
ylab_weight: 1
ylim: []
ytlab_horiz: 0.5
ytlab_orient: 1
ytlab_perp: 0.5
ytlab_size: 1

box_notch: True
box_outline: True
box_avg: True

caption_size: 0.8
caption_offset: 3
caption_weight: 1
caption_align: 0
caption_col: '#333333'
n_min: 11
plot_list: [] # boxplot, point, mean, median, relperf, rank, scatter ,skill_mn, skill_md
rp_diff:
- '>=100'
hfip_bsln: no
footnote_flag: 'False'
event_equal: 'False'
skill_ref: []
demo_yr: NA #not used in Rscript. not sure if we need it
scatter_x: []
scatter_y: []
plot_dir: './'
subtitle: ''
prefix:
baseline_file: ./hfip_baseline.dat
column_info_file: ./plot_tcmpr_hdr.dat


4 changes: 2 additions & 2 deletions metplotpy/plots/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@


AVAILABLE_MARKERS_LIST = ["o", "^", "s", "d", "H", ".", "h"]
AVAILABLE_PLOTLY_MARKERS_LIST = ["open-circle", "circle",
AVAILABLE_PLOTLY_MARKERS_LIST = ["circle-open", "circle",
"square", "diamond",
"hexagon", "triangle-up"]
"hexagon", "triangle-up", "asterisk-open"]

PCH_TO_MATPLOTLIB_MARKER = {'20': '.', '19': 'o', '17': '^', '1': 'H',
'18': 'd', '15': 's', 'small circle': '.',
Expand Down
3 changes: 2 additions & 1 deletion metplotpy/plots/line/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,8 @@ def _add_xaxis(self) -> None:
},
title_standoff=abs(self.config_obj.parameters['xlab_offset']),
tickangle=self.config_obj.x_tickangle,
tickfont={'size': self.config_obj.x_tickfont_size}
tickfont={'size': self.config_obj.x_tickfont_size},
tickformat='d'
)

def _add_yaxis(self) -> None:
Expand Down
Empty file.
Empty file.
89 changes: 89 additions & 0 deletions metplotpy/plots/tcmpr_plots/box/tcmpr_box.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import os

import plotly.graph_objects as go

from plots.tcmpr_plots.box.tcmpr_box_point import TcmprBoxPoint
from plots.tcmpr_plots.tcmpr_series import TcmprSeries


class TcmprBox(TcmprBoxPoint):
def __init__(self, config_obj, column_info, col, case_data, input_df, baseline_data):
super().__init__(config_obj, column_info, col, case_data, input_df, baseline_data)

print("--------------------------------------------------------")
print(f"Plotting BOXPLOT time series by {self.config_obj.series_val_names[0]}")
self._adjust_titles()
self.series_list = self._create_series(self.input_df)
self.case_data = None
self.cur_baseline = baseline_data['cur_baseline']
self.cur_baseline_data = baseline_data['cur_baseline_data']
self._init_hfip_baseline_for_plot()

if self.config_obj.prefix is None or len(self.config_obj.prefix) == 0:
self.plot_filename = f"{self.config_obj.plot_dir}{os.path.sep}{self.config_obj.list_stat_1[0]}_boxplot.png"
else:
self.plot_filename = f"{self.config_obj.plot_dir}{os.path.sep}{self.config_obj.prefix}.png"

# remove the old file if it exist
if os.path.exists(self.plot_filename):
os.remove(self.plot_filename)
self._create_figure()

def _adjust_titles(self):
if self.yaxis_1 is None or len(self.yaxis_1) == 0:
self.yaxis_1 = self.config_obj.list_stat_1[0] + '(' + self.col['units'] + ')'

if self.title is None or len(self.title) == 0:
self.title = 'Boxplots of ' + self.col['desc'] + ' by ' \
+ self.column_info[self.column_info['COLUMN'] == self.config_obj.series_val_names[0]][
"DESCRIPTION"].tolist()[0]

def _draw_series(self, series: TcmprSeries) -> None:
"""
Draws the boxes on the plot
:param series: Line series object with data and parameters
"""

# defaults markers and colors for the regular box plot
line_color = dict(color='rgb(0,0,0)')
marker_color = series.color
marker_line_color = series.color

if len([x for x in series.series_data['PLOT'].tolist() if x is not None]) < self.config_obj.n_min:
line_color = dict(color='rgba(0,0,0,0)')
fillcolor = 'rgba(0,0,0,0)'
marker_symbol = 'circle'
else:
if series.color == 'rgb(0,0,0)' or series.color == 'black' or series.color == '#000000':
fillcolor = '#ffffff'
else:
fillcolor = series.color
marker_symbol = 'circle-open'

# create a trace
self.figure.add_trace(
go.Box(x=series.series_data['LEAD_HR'],
y=series.series_data['PLOT'],
mean=series.series_points['mean'],
notched=self.config_obj.box_notch,
line=line_color,
fillcolor=fillcolor,
name=series.user_legends,
showlegend=True,
# quartilemethod='linear', #"exclusive", "inclusive", or "linear"
boxmean=self.config_obj.box_avg,
boxpoints='outliers', # outliers, all, False
pointpos=0,
marker=dict(size=4,
color=marker_color,
line=dict(
width=1,
color=marker_line_color
),
symbol=marker_symbol,
),
jitter=0
),
secondary_y=series.y_axis != 1
)
75 changes: 75 additions & 0 deletions metplotpy/plots/tcmpr_plots/box/tcmpr_box_point.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from plots.tcmpr_plots.tcmpr import Tcmpr
from plots.tcmpr_plots.tcmpr_series import TcmprSeries


class TcmprBoxPoint(Tcmpr):
def __init__(self, config_obj, column_info, col, case_data, input_df, baseline_data):
super().__init__(config_obj, column_info, col, case_data, input_df)

def _init_hfip_baseline_for_plot(self):
if 'Water Only' in self.config_obj.title or self.cur_baseline == 'no':
print("Plot HFIP Baseline:" + self.cur_baseline)
else:
self.cur_baseline_data = self.cur_baseline_data[(self.cur_baseline_data['TYPE'] == 'CONS')]
print('Plot HFIP Baseline:' + self.cur_baseline.replace('Error ', ''))

def _draw_series(self, series: TcmprSeries) -> None:
pass

def _create_figure(self):
""" Create a box plot from default and custom parameters"""

self.figure = self._create_layout()
self._add_xaxis()
self._add_yaxis()
self._add_legend()

# placeholder for the min and max values for y-axis
yaxis_min = None
yaxis_max = None

if self.config_obj.xaxis_reverse is True:
self.series_list.reverse()

# add x ticks for line plots
self.figure.update_layout(
xaxis={
'tickmode': 'array',
'tickvals': self.config_obj.indy_vals,
'ticktext': self.config_obj.indy_label
}
)

for series in self.series_list:
# Don't generate the plot for this series if
# it isn't requested (as set in the config file)
if series.plot_disp:
# collect min-max if we need to sync axis
yaxis_min, yaxis_max = self.find_min_max(series, yaxis_min, yaxis_max)
self._draw_series(series)

print(f'Range of {self.config_obj.list_stat_1[0]}: {yaxis_min}, {yaxis_max}')
self._add_hfip_baseline()

self.figure.update_layout(shapes=[dict(
type='line',
yref='y', y0=0, y1=0,
xref='paper', x0=0, x1=0.95,
line={'color': '#727273',
'dash': 'dot',
'width': 1},
)])

self.figure.update_layout(boxmode='group')

# add custom lines
if len(self.series_list) > 0:
self._add_lines(
self.config_obj,
sorted(self.series_list[0].series_data[self.config_obj.indy_var].unique())
)
# apply y axis limits
self._yaxis_limits()

# add x2 axis
self._add_x2axis(self.config_obj.indy_vals)
Loading

0 comments on commit 3f95ada

Please sign in to comment.