Coverage for C:\src\imod-python\imod\msw\meteo_mapping.py: 35%
54 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-08 10:26 +0200
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-08 10:26 +0200
1import numpy as np
2import pandas as pd
3import xarray as xr
5from imod.msw.fixed_format import VariableMetaData
6from imod.msw.pkgbase import MetaSwapPackage
7from imod.prepare import common
10class MeteoMapping(MetaSwapPackage):
11 """
12 This class provides common methods for creating mappings between
13 meteorological data and MetaSWAP grids. It should not be instantiated
14 by the user but rather be inherited from within imod-python to create
15 new packages.
16 """
18 def __init__(self):
19 super().__init__()
21 def _render(self, file, index, svat):
22 data_dict = {"svat": svat.values.ravel()[index]}
24 row, column = self.grid_mapping(svat, self.meteo)
26 data_dict["row"] = row[index]
27 data_dict["column"] = column[index]
29 dataframe = pd.DataFrame(
30 data=data_dict, columns=list(self._metadata_dict.keys())
31 )
33 self._check_range(dataframe)
35 return self.write_dataframe_fixed_width(file, dataframe)
37 @staticmethod
38 def grid_mapping(svat: xr.DataArray, meteo_grid: xr.DataArray) -> pd.DataFrame:
39 flip_svat_x = svat.indexes["x"].is_monotonic_decreasing
40 flip_svat_y = svat.indexes["y"].is_monotonic_decreasing
41 flip_meteo_x = meteo_grid.indexes["x"].is_monotonic_decreasing
42 flip_meteo_y = meteo_grid.indexes["y"].is_monotonic_decreasing
43 nrow = meteo_grid["y"].size
44 ncol = meteo_grid["x"].size
46 # Convert to cell boundaries for the meteo grid
47 meteo_x = common._coord(meteo_grid, "x")
48 meteo_y = common._coord(meteo_grid, "y")
50 # Create the SVAT grid
51 svat_grid_y, svat_grid_x = np.meshgrid(svat.y, svat.x, indexing="ij")
52 svat_grid_y = svat_grid_y.ravel()
53 svat_grid_x = svat_grid_x.ravel()
55 # Determine where the svats fit in within the cell boundaries of the meteo grid
56 row = np.searchsorted(meteo_y, svat_grid_y)
57 column = np.searchsorted(meteo_x, svat_grid_x)
59 # Find out of bounds members
60 if (column == 0).any() or (column > ncol).any():
61 raise ValueError("Some values are out of bounds for column")
62 if (row == 0).any() or (row > nrow).any():
63 raise ValueError("Some values are out of bounds for row")
65 # Flip axis if necessary
66 if flip_meteo_y ^ flip_svat_y:
67 row = (nrow + 1) - row
68 if flip_meteo_x ^ flip_svat_x:
69 column = (ncol + 1) - column
71 n_subunit = svat["subunit"].size
73 return np.tile(row, n_subunit), np.tile(column, n_subunit)
76class PrecipitationMapping(MeteoMapping):
77 """
78 This contains the data to connect precipitation grid cells to MetaSWAP
79 svats. The precipitation grid does not have to be equal to the metaswap
80 grid: connections between the precipitation cells to svats will be
81 established using a nearest neighbour lookup.
83 This class is responsible for the file `svat2precgrid.inp`.
85 Parameters
86 ----------
87 precipitation: array of floats (xr.DataArray)
88 Describes the precipitation data. The extend of the grid must be larger
89 than the MetaSvap grid. The data must also be coarser than the MetaSvap
90 grid.
91 """
93 _file_name = "svat2precgrid.inp"
94 _metadata_dict = {
95 "svat": VariableMetaData(10, None, None, int),
96 "row": VariableMetaData(10, None, None, int),
97 "column": VariableMetaData(10, None, None, int),
98 }
100 def __init__(
101 self,
102 precipitation: xr.DataArray,
103 ):
104 super().__init__()
105 self.meteo = precipitation
108class EvapotranspirationMapping(MeteoMapping):
109 """
110 This contains the data to connect evapotranspiration grid cells to MetaSWAP
111 svats. The evapotranspiration grid does not have to be equal to the metaswap
112 grid: connections between the evapotranspiration cells to svats will be
113 established using a nearest neighbour lookup.
115 This class is responsible for the file `svat2etrefgrid.inp`.
117 Parameters
118 ----------
119 evapotransporation: array of floats (xr.DataArray)
120 Describes the evapotransporation data. The extend of the grid must be
121 larger than the MetaSvap grid. The data must also be coarser than the
122 MetaSvap grid.
123 """
125 _file_name = "svat2etrefgrid.inp"
126 _metadata_dict = {
127 "svat": VariableMetaData(10, None, None, int),
128 "row": VariableMetaData(10, None, None, int),
129 "column": VariableMetaData(10, None, None, int),
130 }
132 def __init__(
133 self,
134 evapotranspiration: xr.DataArray,
135 ):
136 super().__init__()
137 self.meteo = evapotranspiration