def get_lake_model_points_for_stations(self, station_list, lake_fraction=None, nneighbours=8): """ For lake levels we have a bit different search algorithm since accumulation area is not a very sensible param to compare :return {station: list of corresponding model points} :param station_list: :param lake_fraction: :param drainaige_area_reldiff_limit: :param nneighbours: :return: :raise Exception: """ station_to_model_point_list = {} nx, ny = self.lons2d.shape i1d, j1d = list(range(nx)), list(range(ny)) j2d, i2d = np.meshgrid(j1d, i1d) i_flat, j_flat = i2d.flatten(), j2d.flatten() for s in station_list: mp_list = [] assert isinstance(s, Station) x, y, z = lat_lon.lon_lat_to_cartesian(s.longitude, s.latitude) dists, inds = self.kdtree.query((x, y, z), k=nneighbours) if nneighbours == 1: dists = [dists] inds = [inds] for d, i in zip(dists, inds): ix = i_flat[i] jy = j_flat[i] mp = ModelPoint(ix=ix, jy=jy) mp.longitude = self.lons2d[ix, jy] mp.latitude = self.lats2d[ix, jy] mp.distance_to_station = d if lake_fraction is not None: if lake_fraction[ix, jy] <= 0.001: # skip the model point if almost no lakes inisde continue mp.lake_fraction = lake_fraction[ix, jy] mp_list.append(mp) if lake_fraction is not None: lf = 0.0 for mp in mp_list: lf += mp.lake_fraction if lf <= 0.001: continue station_to_model_point_list[s] = mp_list print("Found model point for the station {0}".format(s)) return station_to_model_point_list
def get_dataless_model_points_for_stations(station_list, accumulation_area_km2_2d, model_lons2d, model_lats2d, i_array, j_array): """ returns a map {station => modelpoint} for comparison modeled streamflows with observed this uses exactly the same method for searching model points as one in diagnose_point (nc-version) """ lons = model_lons2d[i_array, j_array] lats = model_lats2d[i_array, j_array] model_acc_area_1d = accumulation_area_km2_2d[i_array, j_array] npoints = 1 result = {} x0, y0, z0 = lat_lon.lon_lat_to_cartesian(lons, lats) kdtree = cKDTree(list(zip(x0, y0, z0))) for s in station_list: # list of model points which could represent the station assert isinstance(s, Station) x, y, z = lat_lon.lon_lat_to_cartesian(s.longitude, s.latitude) dists, inds = kdtree.query((x, y, z), k=5) if npoints == 1: deltaDaMin = np.min( np.abs(model_acc_area_1d[inds] - s.drainage_km2)) # this returns a list of numpy arrays imin = np.where( np.abs(model_acc_area_1d[inds] - s.drainage_km2) == deltaDaMin)[0][0] selected_cell_index = inds[imin] # check if difference in drainage areas is not too big less than 10 % print(s.river_name, deltaDaMin / s.drainage_km2) # if deltaDaMin / s.drainage_km2 > 0.2: # continue mp = ModelPoint() mp.accumulation_area = model_acc_area_1d[selected_cell_index] mp.longitude = lons[selected_cell_index] mp.latitude = lats[selected_cell_index] mp.cell_index = selected_cell_index mp.distance_to_station = dists[imin] print("Distance to station: ", dists[imin]) print("Model accumulation area: ", mp.accumulation_area) print("Obs accumulation area: ", s.drainage_km2) result[s] = mp else: raise Exception("npoints = {0}, is not yet implemented ...") return result
def get_dataless_model_points_for_stations(station_list, accumulation_area_km2_2d, model_lons2d, model_lats2d, i_array, j_array): """ returns a map {station => modelpoint} for comparison modeled streamflows with observed this uses exactly the same method for searching model points as one in diagnose_point (nc-version) """ lons = model_lons2d[i_array, j_array] lats = model_lats2d[i_array, j_array] model_acc_area_1d = accumulation_area_km2_2d[i_array, j_array] npoints = 1 result = {} x0, y0, z0 = lat_lon.lon_lat_to_cartesian(lons, lats) kdtree = cKDTree(list(zip(x0, y0, z0))) for s in station_list: # list of model points which could represent the station assert isinstance(s, Station) x, y, z = lat_lon.lon_lat_to_cartesian(s.longitude, s.latitude) dists, inds = kdtree.query((x, y, z), k=5) if npoints == 1: deltaDaMin = np.min(np.abs(model_acc_area_1d[inds] - s.drainage_km2)) # this returns a list of numpy arrays imin = np.where(np.abs(model_acc_area_1d[inds] - s.drainage_km2) == deltaDaMin)[0][0] selected_cell_index = inds[imin] # check if difference in drainage areas is not too big less than 10 % print(s.river_name, deltaDaMin / s.drainage_km2) # if deltaDaMin / s.drainage_km2 > 0.2: # continue mp = ModelPoint() mp.accumulation_area = model_acc_area_1d[selected_cell_index] mp.longitude = lons[selected_cell_index] mp.latitude = lats[selected_cell_index] mp.cell_index = selected_cell_index mp.distance_to_station = dists[imin] print("Distance to station: ", dists[imin]) print("Model accumulation area: ", mp.accumulation_area) print("Obs accumulation area: ", s.drainage_km2) result[s] = mp else: raise Exception("npoints = {0}, is not yet implemented ...") return result
def get_model_points_for_stations(self, station_list, lake_fraction=None, drainaige_area_reldiff_limit=None, nneighbours=4): """ returns a map {station => modelpoint} for comparison modeled streamflows with observed :rtype dict """ # if drainaige_area_reldiff_limit is None: # drainaige_area_reldiff_limit = self.DEFAULT_DRAINAGE_AREA_RELDIFF_MIN # if nneighbours == 1: # raise Exception("Searching over 1 neighbor is not very secure and not implemented yet") station_to_model_point = {} model_acc_area = self.accumulation_area_km2 model_acc_area_1d = model_acc_area.flatten() grid = np.indices(model_acc_area.shape) for s in station_list: x, y, z = lat_lon.lon_lat_to_cartesian(s.longitude, s.latitude) if s.drainage_km2 is None or nneighbours == 1: # return the closest grid point dists, inds = self.kdtree.query((x, y, z), k=1) ix, jy = [g1.flatten()[inds] for g1 in grid] imin = 0 dists = [dists] if s.drainage_km2 is None: print("Using the closest grid point, since the station does not report its drainage area: {}".format(s)) else: if s.drainage_km2 < self.characteristic_distance ** 2 * 1e-12: print("skipping {0}, because drainage area is too small: {1} km**2".format(s.id, s.drainage_km2)) continue assert isinstance(s, Station) dists, inds = self.kdtree.query((x, y, z), k=nneighbours) deltaDaMin = np.min(np.abs(model_acc_area_1d[inds] - s.drainage_km2)) # this returns a list of numpy arrays imin = np.where(np.abs(model_acc_area_1d[inds] - s.drainage_km2) == deltaDaMin)[0][0] # deltaDa2D = np.abs(self.accumulation_area_km2 - s.drainage_km2) # ij = np.where(deltaDa2D == deltaDaMin) ix, jy = grid[0].flatten()[inds][imin], grid[1].flatten()[inds][imin] # check if it is not global lake cell (move downstream if it is) if lake_fraction is not None: while lake_fraction[ix, jy] >= infovar.GLOBAL_LAKE_FRACTION: di, dj = direction_and_value.flowdir_values_to_shift(self.flow_directions[ix, jy]) ix, jy = ix + di, jy + dj # check if the gridcell is not too far from the station # if dists[imin] > 2 * self.characteristic_distance: # continue # check if difference in drainage areas is not too big less than 10 % if drainaige_area_reldiff_limit is not None and deltaDaMin / s.drainage_km2 > drainaige_area_reldiff_limit: print("Drainage area relative difference is too high, skipping {}.".format(s.id)) print(deltaDaMin / s.drainage_km2, deltaDaMin, s.drainage_km2) continue mp = ModelPoint() mp.ix = ix mp.jy = jy mp.longitude = self.lons2d[ix, jy] mp.latitude = self.lats2d[ix, jy] mp.accumulation_area = self.accumulation_area_km2[ix, jy] try: mp.distance_to_station = dists[imin] except TypeError: mp.distance_to_station = float(dists) station_to_model_point[s] = mp print("mp.accumulation_area_km2={}; s.drainage_km2={}".format(mp.accumulation_area, s.drainage_km2)) print("Found model point for the station {0}".format(s)) return station_to_model_point