forked from JCSDA-internal/eva
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Contour and Filled Contour Plotting Capabilities (JCSDA-internal#216
) ## Description This PR adds the ability to plot contour and filled contour plots from EMCPy's plotting capabilities. The appropriate driver scripts and configuration yamls have been created. ## Dependencies None. ## Impact Please list the other repositories (if any) that this PR will require changes in (example below): None.
- Loading branch information
1 parent
474199a
commit f2e3242
Showing
9 changed files
with
451 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
from eva.eva_path import return_eva_path | ||
from eva.utilities.config import get | ||
from eva.utilities.utils import get_schema, update_object, slice_var_from_str | ||
import numpy as np | ||
|
||
from abc import ABC, abstractmethod | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
|
||
class ContourPlot(ABC): | ||
|
||
"""Base class for creating Contour plots.""" | ||
|
||
def __init__(self, config, logger, dataobj): | ||
|
||
""" | ||
Creates a Contour plot abstract class based on the provided configuration. | ||
Args: | ||
config (dict): A dictionary containing the configuration for the contour plot on a map. | ||
logger (Logger): An instance of the logger for logging messages. | ||
dataobj: An instance of the data object containing input data. | ||
Example: | ||
:: | ||
config = { | ||
"x": {"variable": "collection::group::variable"}, | ||
"y": {"variable": "collection::group::variable"}, | ||
"z": {"variable": "collection::group::variable"}, | ||
"plot_property": "property_value", | ||
"plot_option": "option_value", | ||
"schema": "path_to_schema_file.yaml" | ||
} | ||
logger = Logger() | ||
contour_plot = ContourPlot(config, logger, None) | ||
""" | ||
|
||
self.config = config | ||
self.logger = logger | ||
self.dataobj = dataobj | ||
self.xdata = [] | ||
self.ydata = [] | ||
self.zdata = [] | ||
self.plotobj = None | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
def data_prep(self): | ||
""" Preparing data for configure_plot """ | ||
|
||
# Get the data to plot from the data_collection | ||
# --------------------------------------------- | ||
var0 = self.config['x']['variable'] | ||
var1 = self.config['y']['variable'] | ||
var2 = self.config['z']['variable'] | ||
|
||
var0_cgv = var0.split('::') | ||
var1_cgv = var1.split('::') | ||
var2_cgv = var2.split('::') | ||
|
||
if len(var0_cgv) != 3: | ||
self.logger.abort('Contour: comparison first var \'var0\' does not appear to ' + | ||
'be in the required format of collection::group::variable.') | ||
if len(var1_cgv) != 3: | ||
self.logger.abort('Contour: comparison second var \'var1\' does not appear to ' + | ||
'be in the required format of collection::group::variable.') | ||
if len(var2_cgv) != 3: | ||
self.logger.abort('Contour: comparison second var \'var2\' does not appear to ' + | ||
'be in the required format of collection::group::variable.') | ||
|
||
# Optionally get the channel to plot | ||
channel = None | ||
if 'channel' in self.config: | ||
channel = self.config.get('channel') | ||
|
||
xdata = self.dataobj.get_variable_data(var0_cgv[0], var0_cgv[1], var0_cgv[2], channel) | ||
ydata = self.dataobj.get_variable_data(var1_cgv[0], var1_cgv[1], var1_cgv[2], channel) | ||
zdata = self.dataobj.get_variable_data(var2_cgv[0], var2_cgv[1], var2_cgv[2], channel) | ||
|
||
# see if we need to slice data | ||
xdata = slice_var_from_str(self.config['x'], xdata, self.logger) | ||
ydata = slice_var_from_str(self.config['y'], ydata, self.logger) | ||
zdata = slice_var_from_str(self.config['z'], zdata, self.logger) | ||
|
||
# contour data should be flattened | ||
xdata = xdata.flatten() | ||
ydata = ydata.flatten() | ||
zdata = zdata.flatten() | ||
|
||
@abstractmethod | ||
def configure_plot(self): | ||
""" Virtual method for configuring plot based on selected backend """ | ||
pass | ||
|
||
# -------------------------------------------------------------------------------------------------- |
100 changes: 100 additions & 0 deletions
100
src/eva/plotting/batch/base/diagnostics/filled_contour_plot.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
from eva.eva_path import return_eva_path | ||
from eva.utilities.config import get | ||
from eva.utilities.utils import get_schema, update_object, slice_var_from_str | ||
import numpy as np | ||
|
||
from abc import ABC, abstractmethod | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
|
||
class FilledContourPlot(ABC): | ||
|
||
"""Base class for creating Filled Contour plots.""" | ||
|
||
def __init__(self, config, logger, dataobj): | ||
|
||
""" | ||
Creates a Filled Contour plot abstract class based on the provided configuration. | ||
Args: | ||
config (dict): A dictionary containing the configuration for the filled contour | ||
plot on a map. | ||
logger (Logger): An instance of the logger for logging messages. | ||
dataobj: An instance of the data object containing input data. | ||
Example: | ||
:: | ||
config = { | ||
"x": {"variable": "collection::group::variable"}, | ||
"y": {"variable": "collection::group::variable"}, | ||
"z": {"variable": "collection::group::variable"}, | ||
"plot_property": "property_value", | ||
"plot_option": "option_value", | ||
"schema": "path_to_schema_file.yaml" | ||
} | ||
logger = Logger() | ||
filled_contour_plot = FilledContourPlot(config, logger, None) | ||
""" | ||
|
||
self.config = config | ||
self.logger = logger | ||
self.dataobj = dataobj | ||
self.xdata = [] | ||
self.ydata = [] | ||
self.zdata = [] | ||
self.plotobj = None | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
def data_prep(self): | ||
""" Preparing data for configure_plot """ | ||
|
||
# Get the data to plot from the data_collection | ||
# --------------------------------------------- | ||
var0 = self.config['x']['variable'] | ||
var1 = self.config['y']['variable'] | ||
var2 = self.config['z']['variable'] | ||
|
||
var0_cgv = var0.split('::') | ||
var1_cgv = var1.split('::') | ||
var2_cgv = var2.split('::') | ||
|
||
if len(var0_cgv) != 3: | ||
self.logger.abort('Contour: comparison first var \'var0\' does not appear to ' + | ||
'be in the required format of collection::group::variable.') | ||
if len(var1_cgv) != 3: | ||
self.logger.abort('Contour: comparison second var \'var1\' does not appear to ' + | ||
'be in the required format of collection::group::variable.') | ||
if len(var2_cgv) != 3: | ||
self.logger.abort('Contour: comparison third var \'var2\' does not appear to ' + | ||
'be in the required format of collection::group::variable.') | ||
|
||
# Optionally get the channel to plot | ||
channel = None | ||
if 'channel' in self.config: | ||
channel = self.config.get('channel') | ||
|
||
xdata = self.dataobj.get_variable_data(var0_cgv[0], var0_cgv[1], var0_cgv[2], channel) | ||
ydata = self.dataobj.get_variable_data(var1_cgv[0], var1_cgv[1], var1_cgv[2], channel) | ||
zdata = self.dataobj.get_variable_data(var2_cgv[0], var2_cgv[1], var2_cgv[2], channel) | ||
|
||
# see if we need to slice data | ||
xdata = slice_var_from_str(self.config['x'], xdata, self.logger) | ||
ydata = slice_var_from_str(self.config['y'], ydata, self.logger) | ||
zdata = slice_var_from_str(self.config['z'], zdata, self.logger) | ||
|
||
# contour data should be flattened | ||
xdata = xdata.flatten() | ||
ydata = ydata.flatten() | ||
zdata = zdata.flatten() | ||
|
||
@abstractmethod | ||
def configure_plot(self): | ||
""" Virtual method for configuring plot based on selected backend """ | ||
pass | ||
|
||
# -------------------------------------------------------------------------------------------------- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from eva.eva_path import return_eva_path | ||
from eva.utilities.utils import get_schema, update_object, slice_var_from_str | ||
|
||
from abc import ABC, abstractmethod | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
|
||
class MapContour(ABC): | ||
|
||
"""Base class for creating map contour plots.""" | ||
|
||
def __init__(self, config, logger, dataobj): | ||
|
||
""" | ||
Creates a contour map plot abstract class based on the provided configuration. | ||
Args: | ||
config (dict): A dictionary containing the configuration for the contour map plot. | ||
logger (Logger): An instance of the logger for logging messages. | ||
dataobj: An instance of the data object containing input data. | ||
Example: | ||
:: | ||
config = { | ||
"longitude": {"variable": "collection::group::variable"}, | ||
"latitude": {"variable": "collection::group::variable"}, | ||
"data": {"variable": "collection::group::variable"}, | ||
"plot_property": "property_value", | ||
"plot_option": "option_value", | ||
"schema": "path_to_schema_file.yaml" | ||
} | ||
logger = Logger() | ||
map_plot = MapContour(config, logger, None) | ||
""" | ||
self.collection = None | ||
self.datavar_name = None | ||
|
||
self.config = config | ||
self.logger = logger | ||
self.dataobj = dataobj | ||
self.lonvar = [] | ||
self.latvar = [] | ||
self.datavar = [] | ||
self.plotobj = None | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
def data_prep(self): | ||
""" Preparing data for configure_plot """ | ||
|
||
# prepare data based on config | ||
lonvar_cgv = self.config['longitude']['variable'].split('::') | ||
self.collection = lonvar_cgv[0] | ||
self.lonvar = self.dataobj.get_variable_data(lonvar_cgv[0], lonvar_cgv[1], | ||
lonvar_cgv[2], None) | ||
self.lonvar = slice_var_from_str(self.config['longitude'], self.lonvar, self.logger) | ||
latvar_cgv = self.config['latitude']['variable'].split('::') | ||
self.latvar = self.dataobj.get_variable_data(latvar_cgv[0], latvar_cgv[1], | ||
latvar_cgv[2], None) | ||
self.latvar = slice_var_from_str(self.config['latitude'], self.latvar, self.logger) | ||
datavar_cgv = self.config['data']['variable'].split('::') | ||
self.datavar_name = datavar_cgv[1] + '::' + datavar_cgv[2] | ||
self.datavar = self.dataobj.get_variable_data(datavar_cgv[0], datavar_cgv[1], | ||
datavar_cgv[2], None) | ||
self.datavar = slice_var_from_str(self.config['data'], self.datavar, self.logger) | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
@abstractmethod | ||
def configure_plot(self): | ||
""" Virtual method for configuring plot based on selected backend """ | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Contour default yaml | ||
corner_mask: False | ||
colors: 'black' | ||
alpha: | ||
cmap: | ||
norm: | ||
vmin: | ||
vmax: | ||
levels: |
13 changes: 13 additions & 0 deletions
13
src/eva/plotting/batch/emcpy/defaults/filled_contour_plot.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Filled Contour default yaml | ||
corner_mask: False | ||
colors: | ||
alpha: | ||
cmap: 'viridis' | ||
norm: | ||
vmin: | ||
vmax: | ||
origin: | ||
extent: | ||
locator: | ||
extend: | ||
colorbar: True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# MapContour class default schema | ||
levels: | ||
clabel: False | ||
colors: 'black' | ||
linewidths: 1.5 | ||
linestyles: '-' | ||
cmap: | ||
vmin: | ||
vmax: | ||
alpha: | ||
colorbar: False |
50 changes: 50 additions & 0 deletions
50
src/eva/plotting/batch/emcpy/diagnostics/emcpy_contour_plot.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from eva.eva_path import return_eva_path | ||
from eva.utilities.config import get | ||
from eva.utilities.utils import get_schema, update_object | ||
import emcpy.plots.plots | ||
import os | ||
|
||
from eva.plotting.batch.base.diagnostics.contour_plot import ContourPlot | ||
|
||
# -------------------------------------------------------------------------------------------------- | ||
|
||
|
||
class EmcpyContourPlot(ContourPlot): | ||
|
||
""" | ||
EmcpyContourPlot class is a subclass of the ContourPlot class, designed for configuring | ||
and plotting contour plot visualizations using the emcpy library. | ||
Attributes: | ||
Inherits attributes from the ContourPlot class. | ||
Methods: | ||
configure_plot(): Configures the plotting settings for the contour plot. | ||
""" | ||
|
||
def configure_plot(self): | ||
|
||
""" | ||
Configures the plotting settings for the contour plot. | ||
Returns: | ||
plotobj: The configured plot object for emcpy contour plots. | ||
""" | ||
|
||
# Create declarative plotting ContourPlot object | ||
# ------------------------------------------- | ||
self.plotobj = emcpy.plots.plots.ContourPlot(self.xdata, self.ydata, self.z) | ||
|
||
# Get defaults from schema | ||
# ------------------------ | ||
layer_schema = self.config.get('schema', os.path.join(return_eva_path(), 'plotting', | ||
'batch', 'emcpy', 'defaults', 'contour_plot.yaml')) | ||
new_config = get_schema(layer_schema, self.config, self.logger) | ||
delvars = ['x', 'y', 'z', 'type', 'schema'] | ||
for d in delvars: | ||
new_config.pop(d, None) | ||
self.plotobj = update_object(self.plotobj, new_config, self.logger) | ||
|
||
return self.plotobj | ||
|
||
# -------------------------------------------------------------------------------------------------- |
Oops, something went wrong.