Ejemplo n.º 1
0
    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
Ejemplo n.º 3
0
def regenerate_station_to_gridcell_mapping(start_year, end_year,
                                           model_manager):
    """
    should be called when grid or search algorithm change
    """

    assert isinstance(model_manager, Crcm5ModelDataManager)

    ktree = model_manager.kdtree
    model_acc_area = model_manager.accumulation_area_km2
    model_acc_area_1d = model_acc_area.flatten()

    #    selected_ids = ["104001", "103715",
    #                    "093806", "093801",
    #                    "092715",
    #                    "081006", "040830"]

    selected_ids = None
    start_date = datetime(start_year, 1, 1)
    end_date = datetime(end_year, 12, 31)

    stations = cehq_station.read_station_data(selected_ids=selected_ids,
                                              start_date=start_date,
                                              end_date=end_date)

    station_to_grid_point = {}
    for s in stations:
        assert isinstance(s, Station)
        x, y, z = lat_lon.lon_lat_to_cartesian(s.longitude, s.latitude)
        dists, inds = ktree.query((x, y, z), k=8)

        deltaDaMin = np.min(np.abs(model_acc_area_1d[inds] - s.drainage_km2))

        imin = np.where(
            np.abs(model_acc_area_1d[inds] - s.drainage_km2) == deltaDaMin)[0]

        deltaDa2D = np.abs(model_acc_area - s.drainage_km2)

        ij = np.where(deltaDa2D == deltaDaMin)

        mp = ModelPoint()
        mp.accumulation_area = model_acc_area[ij[0][0], ij[1][0]]
        mp.ix = ij[0][0]
        mp.jy = ij[1][0]
        mp.longitude = model_manager.lons2D[mp.ix, mp.jy]
        mp.latitude = model_manager.lats2D[mp.ix, mp.jy]

        #flow in mask
        mp.flow_in_mask = model_manager.get_mask_for_cells_upstream(
            mp.ix, mp.jy)

        station_to_grid_point[s] = mp

        print("da_diff (sel) = ", deltaDaMin)
        print("dist (sel) = ", dists[imin])

    return station_to_grid_point
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
    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