Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions demo/work_pretty_trio.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,20 +169,20 @@ def saveone(i, pname=None):

# make single image file (for QA)
saveone(16*60, (odir / oname).with_suffix('.png'))
###
### run_parallel = True
### if run_parallel:
### # parallel processing
### # save all frames in parallel
### # 68 for stampede, 24 for ls5
### nthreads = 24 # ls5
### with Pool(nthreads) as pool:
### pool.map(saveone, range(len(tstamps)))
### else:
### # serial processing
### for i in range(len(tstamps)):
### saveone(i)
###
### # make mpeg file
### cmd = f'ffmpeg -i "{wdir / "%04d.png"}" -vf scale=1920:-2 -vframes 2880 -crf 3 -vcodec libx264 -pix_fmt yuv420p -f mp4 -y "{odir / oname}"'
### subprocess.run(shlex.split(cmd), check=True)

run_parallel = True
if run_parallel:
# parallel processing
# save all frames in parallel
# 68 for stampede, 24 for ls5
nthreads = 24 # ls5
with Pool(nthreads) as pool:
pool.map(saveone, range(len(tstamps)))
else:
# serial processing
for i in range(len(tstamps)):
saveone(i)

# make mpeg file
cmd = f'ffmpeg -i "{wdir / "%04d.png"}" -vf scale=1920:-2 -vframes 2880 -crf 3 -vcodec libx264 -pix_fmt yuv420p -f mp4 -y "{odir / oname}"'
subprocess.run(shlex.split(cmd), check=True)
101 changes: 74 additions & 27 deletions demo/work_pretty_trio_added.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@
df_shp = df_shp.to_crs('EPSG:3857')

# title to use for each input
titles = ['Regular Only', f'Regular +\nUnintended,\nContinous {site}',
f'Regular + \nUnintended,\nPulsated {site}']
titles = ['routine emissions',
f'routine +\nunintended continous\n emissions from {site}',
f'routine +\nunintended pulse\n emissions from {site}',
]

# read the data
data = []
Expand Down Expand Up @@ -110,6 +112,7 @@
bndry = [1, 10, 50, 100, 200, 500, 1000, 2000]
norm = colors.BoundaryNorm(bndry, len(bndry))


plotter_options = {
'background_manager': BackgroundManager(bgfile=bgfile,),
'contour_options': {
Expand All @@ -119,15 +122,38 @@
'alpha': .5,
'extend': 'max',
},
'title_options': {'fontsize': 'medium'},
# TODO instead of setting fontsize evrywhere, change across everywhere like this
# https://stackoverflow.com/questions/3899980/how-to-change-the-font-size-on-a-matplotlib-plot
'title_options': {'fontsize': 'small'},
'colorbar_options': None,
'customize_once': [
'plot_customizers': [
# emission points
lambda p: df_shp.plot(ax=p.ax, column='kls', categorical=True, legend=False, zorder=10,
lambda p: df_shp.plot(ax=p.ax, column='kls', categorical=True,
legend=False, zorder=10,
markersize=2,
# got red/blue/yellow from colorbrewer's Set1
cmap=colors.ListedColormap(['#e41a1c', '#377eb8', '#ffff33'])
),
#lambda p: p.ax.scatter(df_shp.geometry.x, df_shp.geometry.y,
# c=df_shp['kls'].apply(lambda x: {'flare':'#e41a1c',
# 'tank':'#377eb8', 'well':'#ffff33'}[x]),
# zorder=10, #markersize=2,
# ),
# emission point annotations
lambda p:
# adjust_text() repels labels from each other
adjust_text(
# make list of annotation
list(
# this part creates annotation for each point
p.ax.annotate(_.Site_Label, (_.geometry.x, _.geometry.y,),
zorder=11,
fontsize=4,
)
# goes across all points but filter by Site_Label
for _ in df_shp.itertuples() if _.Site_Label in ('S2',)
),
),
# Shannon's "original" box
lambda p: p.ax.add_geometries(
[Polygon([(-101.8834373, 31.71350603),
Expand All @@ -149,44 +175,65 @@
# clone the options and let each has own title
plotter_options = [{**plotter_options, 'title': title} for title in titles]

def legend_manager(fig):
ax = fig.get_axes()
#print(ax)
#print(dir(ax[0]))
ll = fig.get_axes()[0].get_legend_handles_labels()
#print(ll)
fig.legend(*ll, loc='lower right')


# colorbar goes to entire figure
figure_options = {
'colorbar_options': {
'label': r'$CH_4$ (ppbV)',
}
'label': r'$CH_4$ (ppbV)',
'colorbar_customizers': [
lambda cb: cb.ax.tick_params(labelsize = 8),
lambda cb: cb.set_label( r'$CH_4$ (ppbV)', fontsize='small')
]
},
'footnote_options': {'fontsize': 'small'},
'figure_customizers': [
# neither worked...
#lambda fig: fig.legend(*fig.get_axes()[0].get_legend_handles_labels())
#legend_manager,
]
}

# make a plot template
p = plotter_multi.Plotter(arrays=arrays, tstamps=tstamps,
pp = plotter_multi.Plotter(arrays=arrays, tstamps=tstamps,
x=x, y=y, projection=LambertConformalTCEQ(),
plotter_options=plotter_options,
figure_options=figure_options)



# function to save one time frame
def saveone(i, pname=None):
if pname is None: pname = wdir / f'{i:04}.png'

ts = tstamps[i]
footnote = str(ts)
p(pname, tidx=i, footnote=footnote)
footnote = str(ts).replace(':00-06:00', ' (UTC-06:00)')
pp(pname, tidx=i, footnote=footnote)

# make single image file (for QA)
saveone(16*60, (odir / oname).with_suffix('.png'))
###
### run_parallel = True
### if run_parallel:
### # parallel processing
### # save all frames in parallel
### # 68 for stampede, 24 for ls5
### nthreads = 24 # ls5
### with Pool(nthreads) as pool:
### pool.map(saveone, range(len(tstamps)))
### else:
### # serial processing
### for i in range(len(tstamps)):
### saveone(i)
###
### # make mpeg file
### cmd = f'ffmpeg -i "{wdir / "%04d.png"}" -vf scale=1920:-2 -vframes 2880 -crf 3 -vcodec libx264 -pix_fmt yuv420p -f mp4 -y "{odir / oname}"'
### subprocess.run(shlex.split(cmd), check=True)


run_parallel = True
if run_parallel:
# parallel processing
# save all frames in parallel
# 68 for stampede, 24 for ls5
nthreads = 24 # ls5
with Pool(nthreads) as pool:
pool.map(saveone, range(len(tstamps)))
else:
# serial processing
for i in range(len(tstamps)):
saveone(i)

# make mpeg file
cmd = f'ffmpeg -i "{wdir / "%04d.png"}" -vf scale=1920:-2 -vframes 2880 -crf 3 -vcodec libx264 -pix_fmt yuv420p -f mp4 -y "{odir / oname}"'
subprocess.run(shlex.split(cmd), check=True)
34 changes: 25 additions & 9 deletions plotter/plotter_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(self, array, tstamps, projection=None, extent=None, x=None, y=None,

self.colorbar_options = plotter_options.get('colorbar_options', {})

self.footnote_options = plotter_options.get('footnote_options', {})
self.footnote_options = plotter_options.get('footnote_options', None)

self.title = plotter_options.get('title', None)
self.title_options = plotter_options.get('title_options', None)
Expand Down Expand Up @@ -108,7 +108,11 @@ def __init__(self, array, tstamps, projection=None, extent=None, x=None, y=None,
self.ax.set_title(**ttlopt)

# other customizations
if 'plot_customizers' in plotter_options:
self.customize(plotter_options['plot_customizers'])
if 'customize_once' in plotter_options:
warnings.warn("'customize_once' renamed to 'plot_customizer'",
DeprecationWarning)
self.customize(plotter_options['customize_once'])

self.hasdata = False
Expand Down Expand Up @@ -175,15 +179,27 @@ def __call__(self, tidx=None, footnote='', title=None):
warnings.warn('No data to show, Colorbar turned off',
pu.PlotterWarning)

if footnote is not None:
if footnote is not None or self.footnote_options:
# default set of options
my_footnote_options = {
'xy': (0.5, 0), # bottom center
'xytext': (0, -6), # drop 6 ponts below (works if there is no x axis label)
#'xytext': (0,-18), # drop 18 ponts below (works with x-small fontsize axis label)
'xycoords': 'axes fraction',
'textcoords': 'offset points',
'ha': 'center', 'va':'top'}

if self.footnote_options:

# user overrides options
my_footnote_options.update(self.footnote_options)
if footnote is not None:
my_footnote_options['text'] = footnote


self.footnote = self.ax.annotate(footnote,
xy=(0.5, 0), # bottom center
xytext=(0, -6),
# drop 6 ponts below (works if there is no x axis label)
# xytext=(0,-18), # drop 18 ponts below (works with x-small fontsize axis label)
xycoords='axes fraction',
textcoords='offset points',
ha='center', va='top')
**my_footnote_options)


self.hasdata = True

Expand Down
51 changes: 42 additions & 9 deletions plotter/plotter_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,35 @@ def __init__(self, arrays, tstamps, projection=None, extent=None, x=None, y=None
x=x, y=y, plotter_options=po) for arr, po in zip(arrays, plotter_options)]
self.axes = [p.ax for p in self.plotters]

def __call__(self, oname, tidx=None, footnote='', suptitle=None, titles=None, footnotes=''):
figure_customizers = figure_options.pop('figure_customizers', None)

if figure_customizers:
for fc in figure_customizers:
fc(self.fig)

# TODO rename footnotes to subplot_footnote or something like that...
def __call__(self, oname, tidx=None, footnote='', suptitle=None,
titles=None):#, footnotes=''):

# remember if plots were blank
haddata = self.plotters[0].hasdata

if isinstance(footnotes, str) or len(footnotes) != len(self.plotters):
footnotes = [footnotes] * len(self.plotters)
#if isinstance(footnotes, str) or len(footnotes) != len(self.plotters):
# footnotes = [footnotes] * len(self.plotters)

for p,fn in zip(self.plotters, footnotes):
#print(footnotes)
# if footnotes:
#for p,fn in zip(self.plotters, footnotes):

p(tidx, footnote=fn)
# p(tidx, footnote=fn)
for p in self.plotters:

p(tidx, footnote=None)

# if it was blank, need some initalization
if not haddata:
cbopt = self.figure_options.get('colorbar_options', None)
fnopt = self.figure_options.get('footnote_options', None)
if cbopt is not None:
self.fig.subplots_adjust(wspace=.1)

Expand All @@ -90,20 +104,39 @@ def __call__(self, oname, tidx=None, footnote='', suptitle=None, titles=None, fo
elif self.nplot >= 3:
my_shrink = .5

self.fig.colorbar(
# TODO do this on plotter_core too
cb_customizers = cbopt.pop('colorbar_customizers', None)

cb = self.fig.colorbar(
mappable=self.plotters[0].mappable,
ax=self.axes,
use_gridspec=True,
**{'shrink': my_shrink, **cbopt})
for cbc in cb_customizers:
cbc(cb)

if footnote is not None:

if footnote is not None or fnopt is not None:
# no clue why, but y=0.2 puts text nicely below the plots, for pair case...
if self.nplot <= 2:
my_ypos = .2
elif self.nplot >=3:
my_ypos = .3
self.footnote = self.fig.text(0.5, my_ypos, footnote,
ha='center', va='top')


# default options
my_footnote_options = {
'x': 0.5,
'y': my_ypos,
's': '',
'ha': 'center',
'va': 'top',
}
if footnote is not None:
my_footnote_options['s'] = footnote
if fnopt is not None:
my_footnote_options.update(fnopt)
self.footnote = self.fig.text(**my_footnote_options)
else:
if footnote is not None:
self.footnote.set_text(footnote)
Expand Down