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
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 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()
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