Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the hvplot backend #186

Merged
merged 29 commits into from
May 20, 2024
Merged
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
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ hvplot
nbconvert
bokeh
geopandas
geoviews
59 changes: 29 additions & 30 deletions src/eva/plotting/batch/base/diagnostics/density.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
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 emcpy.plots.plots
import os
import numpy as np

from abc import ABC, abstractmethod

# --------------------------------------------------------------------------------------------------


class Density():
class Density(ABC):

"""Base class for creating density plots."""

def __init__(self, config, logger, dataobj):

"""
Creates a density plot based on the provided configuration and data.
Creates a density plot abstract class based on the provided configuration and data.

Args:
config (dict): A dictionary containing the configuration for the density plot.
logger (Logger): An instance of the logger for logging messages.
dataobj: An instance of the data object containing input data.

This class initializes and configures a density plot based on the provided configuration and
data. The density plot is created using a declarative plotting library from EMCPy
(https://github.com/NOAA-EMC/emcpy).

Example:

::
Expand All @@ -46,45 +41,49 @@ def __init__(self, config, logger, dataobj):
density_plot = Density(config, logger, dataobj)
"""

self.config = config
self.logger = logger
self.dataobj = dataobj
self.plotobj = None
self.data = None

# --------------------------------------------------------------------------------------------------

def data_prep(self):

""" Preparing data for configure_plot """

# Get the data to plot from the data_collection
# ---------------------------------------------
varstr = config['data']['variable']
varstr = self.config['data']['variable']
var_cgv = varstr.split('::')

if len(var_cgv) != 3:
logger.abort('In Density the variable \'var_cgv\' does not appear to ' +
'be in the required format of collection::group::variable.')
self.logger.abort('In Density the variable \'var_cgv\' does not appear to ' +
'be in the required format of collection::group::variable.')

# Optionally get the channel to plot
channel = None
if 'channel' in config['data']:
channel = config['data'].get('channel')
if 'channel' in self.config['data']:
channel = self.config['data'].get('channel')

data = dataobj.get_variable_data(var_cgv[0], var_cgv[1], var_cgv[2], channel)
data = self.dataobj.get_variable_data(var_cgv[0], var_cgv[1], var_cgv[2], channel)

# See if we need to slice data
data = slice_var_from_str(config['data'], data, logger)
data = slice_var_from_str(self.config['data'], data, self.logger)

# Density data should be flattened
data = data.flatten()

# Missing data should also be removed
mask = ~np.isnan(data)
data = data[mask]

# Create declarative plotting density object
# --------------------------------------------
self.plotobj = emcpy.plots.plots.Density(data)

# Get defaults from schema
# ------------------------
layer_schema = config.get('schema', os.path.join(return_eva_path(), 'plotting',
'emcpy', 'defaults', 'density.yaml'))
config = get_schema(layer_schema, config, logger)
delvars = ['type', 'schema', 'data']
for d in delvars:
config.pop(d, None)
self.plotobj = update_object(self.plotobj, config, logger)
self.data = data[mask]

# --------------------------------------------------------------------------------------------------

@abstractmethod
def configure_plot(self):
""" Virtual method for configuring plot based on selected backend """
pass

# --------------------------------------------------------------------------------------------------
53 changes: 26 additions & 27 deletions src/eva/plotting/batch/base/diagnostics/histogram.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
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 emcpy.plots.plots
import os
import numpy as np

from abc import ABC, abstractmethod

# --------------------------------------------------------------------------------------------------


class Histogram():
class Histogram(ABC):

"""Base class for creating histogram plots."""

def __init__(self, config, logger, dataobj):

"""
Creates a histogram plot based on the provided configuration and data.
Creates a histogram plot abstract class based on the provided configuration and data.

Args:
config (dict): A dictionary containing the configuration for the histogram plot.
logger (Logger): An instance of the logger for logging messages.
dataobj: An instance of the data object containing input data.

This class initializes and configures a histogram plot based on the provided configuration
and data. The histogram plot is created using a declarative plotting library from EMCPy
(https://github.com/NOAA-EMC/emcpy).

Example:

Expand All @@ -46,9 +42,20 @@ def __init__(self, config, logger, dataobj):
histogram_plot = Histogram(config, logger, dataobj)
"""

self.config = config
self.logger = logger
self.dataobj = dataobj
self.data = None
self.plotobj = None

# --------------------------------------------------------------------------------------------------

def data_prep(self):
""" Preparing data for configure_plot """

# Get the data to plot from the data_collection
# ---------------------------------------------
varstr = config['data']['variable']
varstr = self.config['data']['variable']
var_cgv = varstr.split('::')

if len(var_cgv) != 3:
Expand All @@ -57,34 +64,26 @@ def __init__(self, config, logger, dataobj):

# Optionally get the channel to plot
channel = None
if 'channel' in config['data']:
channel = config['data'].get('channel')
if 'channel' in self.config['data']:
channel = self.config['data'].get('channel')

data = dataobj.get_variable_data(var_cgv[0], var_cgv[1], var_cgv[2], channel)
data = self.dataobj.get_variable_data(var_cgv[0], var_cgv[1], var_cgv[2], channel)

# See if we need to slice data
data = slice_var_from_str(config['data'], data, logger)
data = slice_var_from_str(self.config['data'], data, self.logger)

# Histogram data should be flattened
data = data.flatten()

# Missing data should also be removed
mask = ~np.isnan(data)
data = data[mask]

# Create declarative plotting histogram object
# --------------------------------------------
self.plotobj = emcpy.plots.plots.Histogram(data)

# Get defaults from schema
# ------------------------
layer_schema = config.get('schema', os.path.join(return_eva_path(), 'plotting',
'emcpy', 'defaults', 'histogram.yaml'))
config = get_schema(layer_schema, config, logger)
delvars = ['type', 'schema', 'data']
for d in delvars:
config.pop(d, None)
self.plotobj = update_object(self.plotobj, config, logger)
self.data = data[mask]

# --------------------------------------------------------------------------------------------------

@abstractmethod
def configure_plot(self):
""" Virtual method for configuring plot based on selected backend """
pass

# --------------------------------------------------------------------------------------------------
41 changes: 17 additions & 24 deletions src/eva/plotting/batch/base/diagnostics/horizontal_line.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from eva.eva_path import return_eva_path
from eva.utilities.utils import get_schema, update_object
import emcpy.plots.plots
import os


from abc import ABC, abstractmethod
# --------------------------------------------------------------------------------------------------


Expand All @@ -14,15 +12,12 @@ class HorizontalLine():
def __init__(self, config, logger, dataobj):

"""
Creates a horizontal line plot based on the provided configuration.
Creates a horizontal line plot abstract class based on the provided configuration.

Args:
config (dict): A dictionary containing the configuration for the horizontal line plot.
logger (Logger): An instance of the logger for logging messages.

This class initializes and configures a horizontal line plot based on the provided
configuration. The horizontal line plot is created using a declarative plotting library from
EMCPy (https://github.com/NOAA-EMC/emcpy).
dataobj: An instance of the data object containing input data.

Example:

Expand All @@ -38,24 +33,22 @@ def __init__(self, config, logger, dataobj):
horizontal_line_plot = HorizontalLine(config, logger)
"""

# Get the y value to plot
# -----------------------
yval = config['y']
self.logger = logger
self.config = config
self.yval = None

# Create declarative plotting HorizontalLine object
# -------------------------------------------
self.plotobj = emcpy.plots.plots.HorizontalLine(yval)
# --------------------------------------------------------------------------------------------------

# Get defaults from schema
# ------------------------
layer_schema = config.get('schema', os.path.join(return_eva_path(), 'plotting',
'emcpy', 'defaults',
'horizontal_line.yaml'))
config = get_schema(layer_schema, config, logger)
delvars = ['type', 'schema']
for d in delvars:
config.pop(d, None)
self.plotobj = update_object(self.plotobj, config, logger)
def data_prep(self):
""" Preparing data for configure_plot """

# Get the y value to plot
# -----------------------
self.yval = self.config['y']

# --------------------------------------------------------------------------------------------------

@abstractmethod
def configure_plot(self):
""" Virtual method for configuring plot based on selected backend """
pass
Loading
Loading