Skip to content

Commit aea6d18

Browse files
committed
Update Xanthos to work with modified fldgen
1 parent 8a187e6 commit aea6d18

File tree

1 file changed

+53
-44
lines changed

1 file changed

+53
-44
lines changed

cassandra/components.py

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -615,13 +615,28 @@ def run_component(self):
615615
class XanthosComponent(ComponentBase):
616616
"""Class for the global hydrologic model Xanthos
617617
618-
This component makes use of the Xanthos package, an open-source
619-
hydrologic model.
618+
This component makes use of the Xanthos package, an open-source hydrologic
619+
model (https://github.com/JGCRI/xanthos).
620620
621-
For more information: https://github.com/JGCRI/xanthos
621+
The two main inputs to Xanthos are gridded monthly precipitation and
622+
temperature. If these capabilities are provided by another component,
623+
Xanthos will use them as arguments, otherwise it will expect them to be
624+
specified in the Xanthos configuration file. It is assumed the order of
625+
the grids in the precipitation and temperature lists match one another.
622626
623627
params:
624-
config_file - path to Xanthos config file
628+
config_file - Path to Xanthos config file
629+
630+
Capability dependencies (all optional):
631+
gridded_pr - List of gridded monthly precipitation by grid cell
632+
gridded_tas - List of gridded monthly temperature by grid cell
633+
gridded_pr_coord - Matrix of lat/lon coordinates for the precip grid cells
634+
gridded_tas_coord - Matrix of lat/lon coordinates for the tas grid cellss
635+
636+
results:
637+
gridded_runoff - Capability 'gridded_runoff', a list of runoff matrices,
638+
with the units and aggregation level specified in the
639+
Xanthos config file
625640
"""
626641

627642
def __init__(self, cap_tbl):
@@ -652,65 +667,59 @@ def run_component(self):
652667
config_file = self.params["config_file"]
653668

654669
xth = xanthos.Xanthos(config_file)
655-
656670
args = {}
671+
gridded_runoff = []
672+
673+
# Other components should produce gridded climate data as a list of 2d numpy arrays
674+
cap_names = ['gridded_pr', 'gridded_tas', 'gridded_pr_coord', 'gridded_tas_coord']
675+
if all(cap in self.cap_tbl for cap in cap_names):
676+
pr_grids = self.fetch('gridded_pr')
677+
tas_grids = self.fetch('gridded_tas')
678+
pr_coord = self.fetch('gridded_pr_coord')
679+
tas_coord = self.fetch('gridded_tas_coord')
680+
else:
681+
pr_grids = tas_grids = []
682+
xth_results = xth.execute(args)
683+
gridded_runoff.append(xth_results.Q)
657684

658-
# Wait for other components to produce precipitation and
659-
# temperature data (as pandas DataFrames), if provided
660-
self.add_args_from_capability(args, 'PrecipitationFile', 'gridded_pr', 'mm_month-1')
661-
self.add_args_from_capability(args, 'trn_tas', 'gridded_tas', 'C')
662-
663-
xth_results = xth.execute(args)
685+
for pr, tas in zip(pr_grids, tas_grids):
686+
args['PrecipitationFile'] = self.prep_for_xanthos(pr, pr_coord)
687+
args['trn_tas'] = self.prep_for_xanthos(tas, tas_coord) - 273.15 # K to C
688+
xth_results = xth.execute(args)
689+
gridded_runoff.append(xth_results.Q)
664690

665-
# Add runoff (Q) results from xanthos to the gridded_runoff capability
666-
self.addresults("gridded_runoff", xth_results.Q)
691+
self.addresults("gridded_runoff", gridded_runoff)
667692

668693
return 0
669694

670-
def add_args_from_capability(self, args, arg_name, cap_name, units=None):
671-
"""Get Xanthos parameters from another capability.
672-
673-
If the no component provides the requested capability, no arguments are added.
674-
675-
params:
676-
args: Reference to dictionary passed to Xanthos
677-
arg_name: Name of argument to add
678-
cap_name: Name of capability with required value
679-
units: Optional string to use to assert correct units
680-
"""
681-
if cap_name in self.cap_tbl:
682-
arg_val = self.fetch(cap_name)
683-
assert units is None or arg_val['units'] == units
684-
args[arg_name] = self.prep_for_xanthos(arg_val)
685-
686-
def prep_for_xanthos(self, monthly_data):
687-
"""Convert a fldgen output array to Xanthos' expected input format.
695+
def prep_for_xanthos(self, monthly_data, coords):
696+
"""Convert climate data to Xanthos' expected input format.
688697
689698
Retrieve Xanthos grid cells from alternately indexed vectors.
690699
691-
Convert spatial data from a list of numeric vectors (each list element is one
692-
month) to the input format expected by Xanthos (land cell x months).
693-
694700
params:
695-
monthly_data: Input data for xanthos as numpy array (cells x months)
701+
monthly_data - Input data for Xanthos as numpy array (cells x months)
702+
coords - Lat/lon array corresponding to monthly_data
696703
697704
returns:
698705
2d array of Xanthos cells by month
699706
700707
"""
701-
ycolnames = c('index', 'lat', 'lon')
702-
ycells = pd.DataFrame(monthly_data['data'].T, columns=ycolnames)
708+
coords = pd.DataFrame(coords, columns=['lat', 'lon'])
703709

704-
bothcells = ycells.merge(self.cell_map, on=['lat', 'lon'])
710+
# The input data must have the same number of grid cells as Xanthos
711+
assert len(coords.index) == len(self.cell_map.index)
705712

706-
# Order by Xanthos cell id for indexing
707-
bothcells.sort_values(by='cell_id', inplace=True)
713+
# Map the Xanthos coordinate indices to the input coordinates
714+
cell_id_map = coords.merge(self.cell_map, on=['lat', 'lon'])
708715

709-
# Re-order the data to correct order by extracting with the cell index
710-
cells = monthly_data[:, bothcells.index.astype(int)]
716+
# The 'cell_id' column now says the id of the Xanthos cell each row of
717+
# the input data corresponds to. The ids start at 1, so to re-order the
718+
# input data to the Xanthos order, we can just index by one less than
719+
# the value of the 'cell_id' column.
720+
ordered_data = monthly_data[cell_id_map['cell_id'] - 1, :]
711721

712-
# Rows and columns need to be flipped
713-
return cells.T
722+
return ordered_data
714723

715724

716725
class FldgenComponent(ComponentBase):

0 commit comments

Comments
 (0)