@@ -615,13 +615,28 @@ def run_component(self):
615
615
class XanthosComponent (ComponentBase ):
616
616
"""Class for the global hydrologic model Xanthos
617
617
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) .
620
620
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.
622
626
623
627
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
625
640
"""
626
641
627
642
def __init__ (self , cap_tbl ):
@@ -652,65 +667,59 @@ def run_component(self):
652
667
config_file = self .params ["config_file" ]
653
668
654
669
xth = xanthos .Xanthos (config_file )
655
-
656
670
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 )
657
684
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 )
664
690
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 )
667
692
668
693
return 0
669
694
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.
688
697
689
698
Retrieve Xanthos grid cells from alternately indexed vectors.
690
699
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
-
694
700
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
696
703
697
704
returns:
698
705
2d array of Xanthos cells by month
699
706
700
707
"""
701
- ycolnames = c ('index' , 'lat' , 'lon' )
702
- ycells = pd .DataFrame (monthly_data ['data' ].T , columns = ycolnames )
708
+ coords = pd .DataFrame (coords , columns = ['lat' , 'lon' ])
703
709
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 )
705
712
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' ] )
708
715
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 , :]
711
721
712
- # Rows and columns need to be flipped
713
- return cells .T
722
+ return ordered_data
714
723
715
724
716
725
class FldgenComponent (ComponentBase ):
0 commit comments