@@ -99,7 +99,9 @@ def add_smoothed_glacier_topo(gdir, outline_offset=-40,
9999
100100@entity_task (log , writes = ['gridded_data' ])
101101def assign_points_to_band (gdir , topo_variable = 'glacier_topo_smoothed' ,
102- elevation_weight = 1.003 ):
102+ ranking_variables = None ,
103+ ranking_variables_weights = None ,
104+ ):
103105 """Assigns glacier grid points to flowline elevation bands and ranks them.
104106
105107 Creates two variables in gridded_data.nc:
@@ -123,18 +125,25 @@ def assign_points_to_band(gdir, topo_variable='glacier_topo_smoothed',
123125 topo_variable : str
124126 the topography to read from `gridded_data.nc` (could be smoothed, or
125127 smoothed differently).
126- elevation_weight : float
127- how much weight to give to the elevation of the grid point versus the
128- thickness. Arbitrary number, might be tuned differently.
128+ ranking_variables : list
129+ A list of distributed variables used for ranking pixels of each
130+ elevation band. All variables inside of 'gridded_data' can be used (e.g.
131+ 'topo_smoothed', 'slope', 'dis_from_border', 'distributed_thickness',
132+ 'aspect'). Default is 'distributed_thickness'.
133+ ranking_variables_weights : list
134+ A list of weights, corresponding to the ranking_variables. Larger values
135+ assign more weight to the corresponding ranking_variable. Must be in the
136+ same order as ranking_variables! Default is [1].
129137 """
130138 # We need quite a few data from the gridded dataset
131139 with xr .open_dataset (gdir .get_filepath ('gridded_data' )) as ds :
140+ ds_grid = ds .load ()
132141 topo_data = ds [topo_variable ].data .copy ()
133142 glacier_mask = ds .glacier_mask .data == 1
134143 topo_data_flat = topo_data [glacier_mask ]
135144 band_index = topo_data * np .nan # container
136145 per_band_rank = topo_data * np .nan # container
137- distrib_thick = ds . distributed_thickness . data
146+ weighting_per_pixel = topo_data * 0. # container
138147
139148 # For the flowline we need the model flowlines only
140149 fls = gdir .read_pickle ('model_flowlines' )
@@ -173,15 +182,36 @@ def assign_points_to_band(gdir, topo_variable='glacier_topo_smoothed',
173182 # assert np.nanmin(band_index) == 0
174183 assert np .all (np .isfinite (band_index [glacier_mask ]))
175184
176- # Ok now assign within band using ice thickness weighted by elevation
177- # We rank the pixels within one band by elevation, but also add
178- # a penalty is added to higher elevation grid points
179- min_alt = np .nanmin (topo_data )
180- weighted_thick = ((topo_data - min_alt + 1 ) * elevation_weight ) * distrib_thick
185+ # Ok now we rank the pixels within each band, which variables are considered
186+ # can be defined by the user. All variables are normalized (between 0 and 1)
187+ # and multiplied by a weight and summed up. If the weight is negative the
188+ # normalized variable will be inverted (0 becomes 1 and vice versa).
189+ if ranking_variables is None :
190+ # the default variables to use
191+ ranking_variables = ['distributed_thickness' ]
192+ if ranking_variables_weights is None :
193+ # the default weights to use
194+ ranking_variables_weights = [1 ]
195+ assert len (ranking_variables ) == len (ranking_variables_weights )
196+
197+ # normalize all values to the range of 0 to 1
198+ def min_max_normalization (data ):
199+ data = np .where (glacier_mask , data , np .nan )
200+ return (data - np .nanmin (data )) / (np .nanmax (data ) - np .nanmin (data ))
201+
202+ for var , var_weight in zip (ranking_variables ,
203+ ranking_variables_weights ):
204+ normalized_var = min_max_normalization (ds_grid [var ].data )
205+ # for negative weights we invert the normalized variable
206+ # (smallest becomes largest and vice versa)
207+ if var_weight < 0 :
208+ normalized_var = 1 - normalized_var
209+ weighting_per_pixel += normalized_var * np .abs (var_weight )
210+
211+ # now rank the pixel of each band individually
181212 for band_id in np .unique (np .sort (band_index [glacier_mask ])):
182- # We work per band here
183213 is_band = band_index == band_id
184- per_band_rank [is_band ] = mstats .rankdata (weighted_thick [is_band ])
214+ per_band_rank [is_band ] = mstats .rankdata (weighting_per_pixel [is_band ])
185215
186216 with ncDataset (gdir .get_filepath ('gridded_data' ), 'a' ) as nc :
187217 vn = 'band_index'
0 commit comments