Пример #1
0
def calculate_slopes(min_slope = 1.0e-3):
    """
    Calculates channel slopes taking into account flow directions
    (use after the directions have been corrected)
    """


    METERS_PER_KM = 1000.0

    number_of_negative_slopes = 0
    number_of_slopes = 0

    for i in range(n_cols):
        for j in range(n_rows):
            slope = min_slope
            current = cells[i][j]
            next = current.next
            current_lon, current_lat = lons[current.x, current.y], lats[current.x, current.y]
            if next is not None:
                number_of_slopes += 1
                lon2, lat2 = lons[next.x, next.y], lats[next.x, next.y]
                if current.area <= 0:
                    dist = get_distance_in_meters(current_lon, current_lat, lon2, lat2)
                else:
                    dist = ( current.area ) ** 0.5 * METERS_PER_KM

                slope = ( - next.topo + current.topo ) / dist
                if slope <= 0:
                    slope = min_slope
                    number_of_negative_slopes += 1
            else:
                #check whether there is a neighbor cell, lower than the current if not,
                #assign minimum slope
                dys = []
                for di in range(-1, 2):
                    for dj in range(-1, 2):
                        if di == 0 and dj == 0: continue
                        i1 = i + di
                        j1 = j + dj
                        if i1 < 0 or j1 < 0 or i1 == n_cols or j1 == n_rows:
                            continue

                        dy = current.topo - cells[i1][j1].topo
                        if dy > 0:
                            lon2, lat2 = lons[i1, j1], lats[i1, j1]
                            if current.area <= 0:
                                dist = get_distance_in_meters(current_lon, current_lat, lon2, lat2)
                            else:
                                dist = (current.area) ** 0.5 * METERS_PER_KM
                            dys.append(dy / dist)
                if len(dys) > 0:
                    slope = np.min(dys)
            cells[i][j].chslp = slope

    
    print '%d corrected slopes of %d' % (number_of_negative_slopes, number_of_slopes)
    pass
def get_corresponding_station(lon, lat, cell_drain_area_km2, station_list):
    """
    returns the closest station to (lon, lat),
    or None if it was not found
    """
    #find distance to the closest station
    objective = None
    result = None
    for station in station_list:
        station_drainage = station.drainage_km2
        distance = get_distance_in_meters(lon, lat, station.longitude, station.latitude)
        objective1 = objective_function(distance, station_drainage, cell_drain_area_km2)
        
        if objective is None:
            objective = objective1
            result = station
        else:
            if objective1 < objective:
                result = station
                objective = objective1
        
    
    if objective <= 1.0:
        return result
    else:
        return None
Пример #3
0
    def interpolate_from_grid_to_point(self, data, longitude, latitude):
        lons = self._longitudes
        lats = self._latitudes
        the_delta = self._delta

        lon_min, lon_max = lons[0], lons[-1]
        lat_min, lat_max = lats[0], lats[-1]


        lon_indices = []
        if longitude > lon_min and longitude < lon_max:
            i1 = int( (longitude - lon_min) / the_delta )
            lon_indices.append( i1 )
            lon_indices.append( i1 + 1 )
        elif longitude >= lon_max:
            lon_indices.append(-1) #last element in the row
        elif longitude <= lon_min:
            lon_indices.append(0)


        lat_indices = []
        if latitude > lat_min and latitude < lat_max:
            i1 = int( (latitude - lat_min) / the_delta )
            lat_indices.append( i1 )
            lat_indices.append( i1 + 1 )
        elif latitude >= lat_max:
            lat_indices.append(-1) #last element in the row
        elif latitude <= lat_min:
            lat_indices.append(0)

        result = 0.0
        the_norm = 0.0
        for i in lon_indices:
            for j in lat_indices:
                the_lon = lon_min + i * the_delta if i >= 0 else lon_max
                the_lat = lat_min + j * the_delta if j >= 0 else lat_max

                d = get_distance_in_meters(the_lon, the_lat, longitude, latitude)
                if d == 0:
                    return data[i,j]

                coef = 1.0 / d ** 2.0
                result += coef * data[i,j]
                the_norm += coef
        return result / the_norm
Пример #4
0
    def interpolate_from_grid_to_point(self, data, longitude, latitude):
        lons = self._longitudes
        lats = self._latitudes
        the_delta = self._delta

        lon_min, lon_max = lons[0], lons[-1]
        lat_min, lat_max = lats[0], lats[-1]

        lon_indices = []
        if longitude > lon_min and longitude < lon_max:
            i1 = int((longitude - lon_min) / the_delta)
            lon_indices.append(i1)
            lon_indices.append(i1 + 1)
        elif longitude >= lon_max:
            lon_indices.append(-1)  #last element in the row
        elif longitude <= lon_min:
            lon_indices.append(0)

        lat_indices = []
        if latitude > lat_min and latitude < lat_max:
            i1 = int((latitude - lat_min) / the_delta)
            lat_indices.append(i1)
            lat_indices.append(i1 + 1)
        elif latitude >= lat_max:
            lat_indices.append(-1)  #last element in the row
        elif latitude <= lat_min:
            lat_indices.append(0)

        result = 0.0
        the_norm = 0.0
        for i in lon_indices:
            for j in lat_indices:
                the_lon = lon_min + i * the_delta if i >= 0 else lon_max
                the_lat = lat_min + j * the_delta if j >= 0 else lat_max

                d = get_distance_in_meters(the_lon, the_lat, longitude,
                                           latitude)
                if d == 0:
                    return data[i, j]

                coef = 1.0 / d**2.0
                result += coef * data[i, j]
                the_norm += coef
        return result / the_norm
def save_channel_slopes_to_netcdf(file_name = 'slopes.nc', 
                                  lower_left_point = GeoPoint(-80, 45),
                                  the_shape = (300, 300),
                                  resolution = 5.0 / 60.0):


    #check the sanity of input  arguments
    max_longitude = lower_left_point.longitude + resolution * (the_shape[0] - 1 )
    max_latitude = lower_left_point.latitude + resolution * (the_shape[1] - 1 )
    assert max_longitude >= -180 and max_longitude <= 180
    assert max_latitude >= -90.0 and max_latitude <= 90.0


    flow_directions = get_data_subset(lower_left_point = lower_left_point,
                       the_shape = the_shape,
                       resolution = resolution,
                       file_name = '5minfdr.img')

    longitudes, latitudes, elevations = get_topography_interpolated_to_graham_grid(grid_shape = the_shape,
                                                            grid_lower_left = lower_left_point)

    slopes = np.zeros(the_shape)

    lon0 = lower_left_point.longitude
    lat0 = lower_left_point.latitude

    for i in range(the_shape[0]):
        for j in range(the_shape[1]):
            fdir = flow_directions[i, j]
            i1, j1 = get_next_indices(i, j, fdir)

            if i1 < 0 and j1 < 0:
                slopes[i,j] = -1
                continue

            #do not route water outside the clculation domain
            if i1 >= the_shape[0] or j1 >= the_shape[1] or i1 < 0 or j1 < 0:
                slopes[i,j] = -1
                continue


            lon, lat = lon0 + i * resolution, lat0 + j * resolution
            lon1, lat1 = lon0 + i1 * resolution, lat0 + j1 * resolution
            distance = lat_lon.get_distance_in_meters(lon, lat, lon1, lat1)


            slope = (elevations[i, j] - elevations[i1, j1]) / distance
            if slope <= 0:
                print elevations[i, j], elevations[i1, j1], distance
                slope = MINIMUM_ALLOWED_SLOPE

            slopes[i, j] = slope


    opt = 'c' #create netcdf file
    if os.path.isfile(file_name):
        os.remove(file_name)

    file = Nio.open_file( file_name, opt )
    WEST_EAST = 'west_east'
    NORTH_SOUTH = 'north_south'

    file.create_dimension(WEST_EAST, the_shape[0])
    file.create_dimension(NORTH_SOUTH, the_shape[1])

    file.create_variable('channel slopes', 'd', (WEST_EAST, NORTH_SOUTH))
    file.close()
Пример #6
0
def main():

    lake_names = ["Matagami", "Mistassini", "Nemiscau"]
    lake_areas_km2 = [370.7,  2162.7, 148.3]

    level_st_ids = [
        "080716", "081003",  "081001"
    ]
    level_stations = cehq.read_station_data(folder="data/cehq_levels",
                        selected_ids=level_st_ids)

    stfl_st_ids = [
        "080707", "081007", "081002"
    ]
    stfl_stations = cehq.read_station_data(folder="data/cehq_measure_data",
            selected_ids=stfl_st_ids)

    q_obs = []
    q_calc = []

    plt.figure()
    for lev_station, stfl_station, lake_name, lake_area_km2, c in zip(level_stations,
                                                                    stfl_stations, lake_names, lake_areas_km2,
                                                                    ["r","g","b"]
                                                                ):
        assert isinstance(lev_station, Station)
        assert isinstance(stfl_station, Station)

        count_intersection = sum( [int(d in stfl_station.dates) for d in lev_station.dates] )
        intersection_dates = list( filter( lambda d: d in stfl_station.dates, lev_station.dates) )

        q_vals = [stfl_station.get_value_for_date(d) for d in intersection_dates]
        h_vals = [lev_station.get_value_for_date(d) for d in intersection_dates]


        q_obs.append(q_vals)
        q_calc.append(get_streamflows_from_active_stores_bowling(get_active_storages(h_vals,lake_area_km2), lake_area_km2))

        #Calculate correlation between Q and H
        print(10 * "-" + lake_name)
        print("r = {0}".format(np.corrcoef([q_vals, h_vals])[0,1]))
        print((lev_station.latitude, lev_station.longitude))

        print("dist_m = {0} km ".format( 1.0e-3 * lat_lon.get_distance_in_meters(lev_station.longitude, lev_station.latitude,
                                                                                stfl_station.longitude, stfl_station.latitude)))



        print("{0} and {1} have {2} measurements at the same time ({3}).".format(lev_station.id, stfl_station.id,
            count_intersection, lake_name ))

        #plot storage-discharge relation
        plt.title(lake_name)
        plt.scatter(get_active_storages(h_vals,lake_area_km2), q_vals, c = c , label = lake_name, linewidths=0)


        #plt.plot(intersection_dates, q_vals, c, label = lake_name )
        #plt.plot(intersection_dates, get_active_storages(h_vals,lake_area_km2), c+"-", label = lake_name )


        #plt.xlabel("S-active (obs)")
        #plt.ylabel("Q (obs)")
    plt.legend()


    #Compare observed and theoretical lake outflows
    plt.figure()
    title = ""

    for qo, qc, name, c  in zip(q_obs, q_calc,lake_names, ["r","g","b"]):
        qc_a = np.array(qc)
        qo_a = np.array(qo)
        title = "ME = {0:.2f}".format(1 - sum((qc_a - qo_a) ** 2) / sum( (qo_a - qo_a.mean()) ** 2))
        plt.scatter(qo, qc, c= c, linewidths=0,label = name + ", " + title)

    #plt.title(title)
    plt.xlabel("$Q_{\\rm obs}$")
    plt.ylabel("$Q_{\\rm mod}$")

    xmin, xmax = plt.xlim()
    print(plt.xlim())
    plt.plot([xmin, xmax], [xmin, xmax], "k-",lw = 3, zorder = 5)


    plt.legend()
    plt.show()


    #TODO: implement
    pass