def _calc_cost_of_per_ton_inputs(vars_dict, crop, lulc_raster): ''' Implements the following equations provided in the User Guide: sum_across_fert(FertAppRate_fert * LULCCropCellArea * CostPerTon_fert) ''' economics_table_crop = vars_dict['economics_table_dict'][crop] fert_maps_dict = vars_dict['fertilizer_maps_dict'] masked_lulc_raster = _get_masked_lulc_raster(vars_dict, crop, lulc_raster) masked_lulc_raster_float = masked_lulc_raster.set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) CostPerTonInputTotal_raster = masked_lulc_raster_float.zeros() try: cost_nitrogen_per_kg = economics_table_crop['cost_nitrogen_per_kg'] Nitrogen_raster = Raster.from_file( fert_maps_dict['nitrogen']).set_nodata(NODATA_FLOAT) NitrogenCost_raster = Nitrogen_raster * cost_nitrogen_per_kg CostPerTonInputTotal_raster += NitrogenCost_raster except KeyError: LOGGER.warning("Skipping nitrogen cost because insufficient amount " "of information provided.") try: cost_phosphorous_per_kg = economics_table_crop[ 'cost_phosphorous_per_kg'] Phosphorous_raster = Raster.from_file( fert_maps_dict['phosphorous']).set_nodata(NODATA_FLOAT) PhosphorousCost_raster = Phosphorous_raster * cost_phosphorous_per_kg CostPerTonInputTotal_raster += PhosphorousCost_raster except KeyError: LOGGER.warning("Skipping phosphorous cost because insufficient amount " "of information provided.") try: cost_potash_per_kg = economics_table_crop['cost_potash_per_kg'] Potash_raster = Raster.from_file( fert_maps_dict['potash']).set_nodata(NODATA_FLOAT) PotashCost_raster = Potash_raster * cost_potash_per_kg CostPerTonInputTotal_raster += PotashCost_raster except KeyError: LOGGER.warning("Skipping potash cost because insufficient amount of " "information provided.") CostPerTonInputTotal_masked_raster = CostPerTonInputTotal_raster * masked_lulc_raster_float return CostPerTonInputTotal_masked_raster
def _get_climate_bin_over_lulc(vars_dict, crop, aoi_vector, base_raster_float): ''' Clips the climate bin values in the global dataset, reprojects and resamples those values to a new raster aligned to the given LULC raster that is then returned to the user. ''' climate_bin_raster = Raster.from_file( vars_dict['climate_bin_maps_dict'][crop]) reproj_aoi_vector = aoi_vector.reproject( climate_bin_raster.get_projection()) clipped_climate_bin_raster = climate_bin_raster.clip( reproj_aoi_vector.uri).set_nodata(NODATA_INT) if clipped_climate_bin_raster.get_shape() == (1, 1): climate_bin_val = float(clipped_climate_bin_raster.get_band( 1)[0, 0]) aligned_climate_bin_raster = base_raster_float.ones() * climate_bin_val else: # note: this reprojection could result in very long computation times reproj_climate_bin_raster = clipped_climate_bin_raster.reproject( base_raster_float.get_projection(), 'nearest', base_raster_float.get_affine().a) aligned_climate_bin_raster = reproj_climate_bin_raster.align_to( base_raster_float, 'nearest') return aligned_climate_bin_raster
def _get_observed_yield_from_dataset(vars_dict, crop, aoi_vector, base_raster_float): ''' Clips the observed crop yield values in the global dataset, reprojects and resamples those values to a new raster aligned to the given LULC raster that is then returned to the user. ''' crop_observed_yield_raster = Raster.from_file( vars_dict['observed_yields_maps_dict'][crop]) reproj_aoi_vector = aoi_vector.reproject( crop_observed_yield_raster.get_projection()) clipped_crop_raster = crop_observed_yield_raster.clip( reproj_aoi_vector.uri).set_nodata(NODATA_FLOAT) if clipped_crop_raster.get_shape() == (1, 1): observed_yield_val = float(clipped_crop_raster.get_band(1)[0, 0]) aligned_crop_raster = observed_yield_val * base_raster_float.ones() else: # this reprojection could result in very long computation times reproj_crop_raster = clipped_crop_raster.reproject( base_raster_float.get_projection(), 'nearest', base_raster_float.get_affine().a) aligned_crop_raster = reproj_crop_raster.align_to( base_raster_float, 'nearest') return aligned_crop_raster
def create_crops_in_aoi_list(vars_dict): ''' Example Returns:: vars_dict = { # ... 'crops_in_aoi_list': ['corn', 'rice', 'soy'] } ''' lulc_raster = Raster.from_file(vars_dict['lulc_map_uri']) crop_lookup_dict = vars_dict['crop_lookup_dict'] # array = np.unique(lulc_raster.get_band(1).data) array = lulc_raster.unique() crops_in_aoi_list = [] for crop_num in array: try: crops_in_aoi_list.append(crop_lookup_dict[crop_num]) except KeyError: LOGGER.warning("Land Use Map contains values not listed in the " "Crop Lookup Table") vars_dict['crops_in_aoi_list'] = convert_dict_to_unicode( crops_in_aoi_list) return vars_dict
def testRaster(): print("Testing Raster:") print('Reading data...') test_dir = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + 'test_data' + os.path.sep test_file = 'test.dep' raster = Raster.from_file(test_dir + test_file) new_raster = Raster.create_from_other(test_dir + 'delete_me.dep', raster) lower_limit = raster.minimum + 0.00*(raster.maximum - raster.minimum) upper_limit = raster.minimum + 0.9*(raster.maximum - raster.minimum) old_progress = 1 for row in range(raster.rows): for col in range(raster.columns): z = raster[row, col] if z == raster.nodata: new_raster[row, col] = new_raster.nodata elif z < lower_limit: new_raster[row, col] = lower_limit elif z > upper_limit: new_raster[row, col] = upper_limit else: new_raster[row, col] = z progress = int(100.0 * (row+1) / raster.rows) if progress != old_progress: print('progress: {}%'.format(progress)) old_progress = progress new_raster *= 2.0 new_raster[100, 100] += 275.6 print('Saving data...') new_raster.calculate_min_and_max() new_raster.display_minimum = new_raster.minimum + 0.1*(new_raster.maximum - new_raster.minimum) new_raster.display_maximum = new_raster.minimum + 0.8*(new_raster.maximum - new_raster.minimum) new_raster.write()
def _calc_regression_yield_for_crop(vars_dict, crop, climate_bin_raster): ''' Calculates yield for an individual crop using the percentile yield function ''' # Fetch Fertilizer Maps fert_maps_dict = vars_dict['fertilizer_maps_dict'] NitrogenAppRate_raster = Raster.from_file( fert_maps_dict['nitrogen']).set_nodata(NODATA_FLOAT) PhosphorousAppRate_raster = Raster.from_file( fert_maps_dict['phosphorous']).set_nodata(NODATA_FLOAT) PotashAppRate_raster = Raster.from_file( fert_maps_dict['potash']).set_nodata(NODATA_FLOAT) Irrigation_raster = Raster.from_file( vars_dict['modeled_irrigation_map_uri']).set_datatype_and_nodata( gdal.GDT_Int16, NODATA_INT) irrigated_lulc_mask = (Irrigation_raster).set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) rainfed_lulc_mask = ((Irrigation_raster * -1) + 1).set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) # Create Rasters of Yield Parameters yield_params = vars_dict['modeled_yield_dict'][crop] nodata = climate_bin_raster.get_nodata(1) b_K2O = _create_reg_yield_reclass_dict( yield_params, 'b_K2O', nodata) b_nut = _create_reg_yield_reclass_dict( yield_params, 'b_nut', nodata) c_N = _create_reg_yield_reclass_dict( yield_params, 'c_N', nodata) c_P2O5 = _create_reg_yield_reclass_dict( yield_params, 'c_P2O5', nodata) c_K2O = _create_reg_yield_reclass_dict( yield_params, 'c_K2O', nodata) yc = _create_reg_yield_reclass_dict( yield_params, 'yield_ceiling', nodata) yc_rf = _create_reg_yield_reclass_dict( yield_params, 'yield_ceiling_rf', nodata) b_K2O_raster = climate_bin_raster.reclass(b_K2O) b_nut_raster = climate_bin_raster.reclass(b_nut) c_N_raster = climate_bin_raster.reclass(c_N) c_P2O5_raster = climate_bin_raster.reclass(c_P2O5) c_K2O_raster = climate_bin_raster.reclass(c_K2O) YieldCeiling_raster = climate_bin_raster.reclass(yc) YieldCeilingRainfed_raster = climate_bin_raster.reclass(yc_rf) # Operations as Noted in User's Guide... PercentMaxYieldNitrogen_raster = 1 - ( b_nut_raster * (np.e ** -c_N_raster) * NitrogenAppRate_raster) PercentMaxYieldPhosphorous_raster = 1 - ( b_nut_raster * (np.e ** -c_P2O5_raster) * PhosphorousAppRate_raster) PercentMaxYieldPotassium_raster = 1 - ( b_K2O_raster * (np.e ** -c_K2O_raster) * PotashAppRate_raster) PercentMaxYield_raster = (PercentMaxYieldNitrogen_raster.fminimum( PercentMaxYieldPhosphorous_raster.fminimum( PercentMaxYieldPotassium_raster))) MaxYield_raster = PercentMaxYield_raster * YieldCeiling_raster Yield_irrigated_raster = MaxYield_raster.reclass_masked_values( irrigated_lulc_mask, 0) Yield_rainfed_raster = YieldCeilingRainfed_raster.minimum( MaxYield_raster).reclass_masked_values( rainfed_lulc_mask, 0) Yield_raster = Yield_irrigated_raster + Yield_rainfed_raster return Yield_raster
def calc_regression_yield(vars_dict): ''' Calculates yield using the regression model yield function Example Args:: vars_dict = { ... 'fertilizer_maps_dict': {...}, 'modeled_irrigation_map_uri': '', 'modeled_yield_dict': {...} } ''' vars_dict = _create_yield_func_output_folder( vars_dict, "climate_regression_yield") lulc_raster = Raster.from_file( vars_dict['lulc_map_uri']).set_nodata(NODATA_INT) aoi_vector = Vector.from_shapely( lulc_raster.get_aoi(), lulc_raster.get_projection()) # setup useful base rasters base_raster_float = lulc_raster.set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) vars_dict['crop_production_dict'] = {} if vars_dict['do_economic_returns']: economics_table = vars_dict['economics_table_dict'] returns_raster = base_raster_float.zeros() crops = vars_dict['crops_in_aoi_list'] for crop in crops: LOGGER.info('Calculating regression yield for %s' % crop) # Wrangle data... climate_bin_raster = _get_climate_bin_over_lulc( vars_dict, crop, aoi_vector, base_raster_float) masked_lulc_raster = _get_masked_lulc_raster( vars_dict, crop, lulc_raster).set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) # Operations as Noted in User's Guide... Yield_raster = _calc_regression_yield_for_crop( vars_dict, crop, climate_bin_raster) Yield_given_lulc_raster = Yield_raster * masked_lulc_raster Production_raster = _calculate_production_for_crop( vars_dict, crop, Yield_given_lulc_raster) total_production = float(round( Production_raster.sum(), 2)) vars_dict['crop_production_dict'][crop] = total_production if vars_dict['do_economic_returns']: returns_raster_crop = _calc_crop_returns( vars_dict, crop, lulc_raster, Production_raster.set_nodata(NODATA_FLOAT), returns_raster, economics_table[crop]) returns_raster = returns_raster + returns_raster_crop # Clean Up Rasters... del climate_bin_raster del Yield_raster del masked_lulc_raster del Yield_given_lulc_raster del Production_raster if vars_dict['do_nutrition']: vars_dict = _calc_nutrition(vars_dict) # Results Table io.create_results_table(vars_dict) if all([vars_dict['do_economic_returns'], vars_dict['create_crop_production_maps']]): output_observed_yield_dir = vars_dict['output_yield_func_dir'] returns_uri = os.path.join( output_observed_yield_dir, 'economic_returns_map.tif') returns_raster.save_raster(returns_uri) return vars_dict
def calc_percentile_yield(vars_dict): ''' Calculates yield using the percentile yield function Example Args:: vars_dict = { 'percentile_yield_dict': { '' }, '': '' } ''' vars_dict['crop_production_dict'] = {} vars_dict = _create_yield_func_output_folder( vars_dict, "climate_percentile_yield") lulc_raster = Raster.from_file( vars_dict['lulc_map_uri']).set_nodata(NODATA_INT) aoi_vector = Vector.from_shapely( lulc_raster.get_aoi(), lulc_raster.get_projection()) percentile_yield_dict = vars_dict['percentile_yield_dict'] # setup useful base rasters base_raster_float = lulc_raster.set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) crops = vars_dict['crops_in_aoi_list'] crop = crops[0] climate_bin = percentile_yield_dict[crop].keys()[0] percentiles = percentile_yield_dict[crop][climate_bin].keys() percentile_count = 1 for percentile in percentiles: vars_dict['crop_production_dict'] = {} if vars_dict['do_economic_returns']: economics_table = vars_dict['economics_table_dict'] returns_raster = base_raster_float.zeros() for crop in crops: LOGGER.info('Calculating percentile yield for %s in %s' % ( crop, percentile)) # Wrangle Data... climate_bin_raster = _get_climate_bin_over_lulc( vars_dict, crop, aoi_vector, base_raster_float) reclass_dict = {} climate_bins = percentile_yield_dict[crop].keys() for climate_bin in climate_bins: reclass_dict[climate_bin] = percentile_yield_dict[ crop][climate_bin][percentile] # Find Yield and Production crop_yield_raster = climate_bin_raster.reclass(reclass_dict) masked_lulc_raster = _get_masked_lulc_raster( vars_dict, crop, lulc_raster).set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) yield_raster = crop_yield_raster.reclass_masked_values( masked_lulc_raster, 0) Production_raster = _calculate_production_for_crop( vars_dict, crop, yield_raster, percentile=percentile) total_production = float(round( Production_raster.sum(), 2)) vars_dict['crop_production_dict'][crop] = total_production if vars_dict['do_economic_returns']: returns_raster_crop = _calc_crop_returns( vars_dict, crop, lulc_raster, Production_raster, returns_raster, economics_table[crop]) returns_raster = returns_raster + returns_raster_crop # Clean Up Rasters... del climate_bin_raster del crop_yield_raster del masked_lulc_raster del yield_raster del Production_raster if vars_dict['do_nutrition']: vars_dict = _calc_nutrition(vars_dict) # Results Table if percentile_count == 1: io.create_results_table(vars_dict, percentile=percentile) else: io.create_results_table( vars_dict, percentile=percentile, first=False) percentile_count += 1 if all([vars_dict['do_economic_returns'], vars_dict[ 'create_crop_production_maps']]): output_observed_yield_dir = vars_dict['output_yield_func_dir'] returns_uri = os.path.join( output_observed_yield_dir, 'economic_returns_map_' + percentile + '.tif') returns_raster.save_raster(returns_uri) return vars_dict
def _calc_cost_of_per_hectare_inputs(vars_dict, crop, lulc_raster): ''' CostPerHectareInputTotal_crop = Mask_raster * CostPerHectare_input * ha_per_cell ''' # Determine the crop lucode based on its name crop_lucode = None for lucode, luname in vars_dict['crop_lookup_dict'].iteritems(): if luname == crop: crop_lucode = lucode continue lulc_nodata = pygeoprocessing.get_nodata_from_uri(lulc_raster.uri) economics_table_crop = vars_dict['economics_table_dict'][crop] datatype_out = gdal.GDT_Float32 nodata_out = NODATA_FLOAT pixel_size_out = pygeoprocessing.get_cell_size_from_uri(lulc_raster.uri) ha_per_m2 = 0.0001 cell_area_ha = pixel_size_out**2 * ha_per_m2 # The scalar cost is identical for all crop pixels of the current class, # and is based on the presence of absence of columns in the user-provided # economics table. We only need to calculate this once. cost_scalar = 0.0 for key in ['cost_labor_per_ha', 'cost_machine_per_ha', 'cost_seed_per_ha', 'cost_irrigation_per_ha']: try: cost_scalar += (economics_table_crop[key] * cell_area_ha) except KeyError: LOGGER.warning('Key missing from economics table: %s', key) def _calculate_cost(lulc_matrix): """ Calculate the total cost on a single pixel. <pseudocode> If lulc_pixel is nodata: return nodata else: if lulc_pixel is of our crop type: return the cost of this crop (in cost_scalar, above) else: return 0.0 </pseudocode> """ return np.where(lulc_matrix == lulc_nodata, nodata_out, np.where(lulc_matrix == crop_lucode, cost_scalar, 0.0)) new_raster_uri = pygeoprocessing.geoprocessing.temporary_filename() pygeoprocessing.vectorize_datasets( [lulc_raster.uri], _calculate_cost, new_raster_uri, datatype_out, nodata_out, pixel_size_out, bounding_box_mode='intersection', vectorize_op=False, datasets_are_pre_aligned=True ) return Raster.from_file(new_raster_uri, 'GTiff')
def calc_observed_yield(vars_dict): ''' Calculates yield using observed yield function Args: vars_dict (dict): descr Example Args:: vars_dict = { # ... 'lulc_map_uri': '/path/to/lulc_map_uri', 'crop_lookup_dict': { 'code': 'crop_name', ... }, 'observed_yields_maps_dict': { 'crop': '/path/to/crop_climate_bin_map', ... }, 'economics_table_dict': { 'crop': { 'price': <float>, ... } ... }, } ''' vars_dict['crop_production_dict'] = {} vars_dict = _create_yield_func_output_folder( vars_dict, "observed_yield") lulc_raster = Raster.from_file( vars_dict['lulc_map_uri']).set_nodata(NODATA_INT) aoi_vector = Vector.from_shapely( lulc_raster.get_aoi(), lulc_raster.get_projection()) # setup useful base rasters base_raster_float = lulc_raster.set_datatype_and_nodata( gdal.GDT_Float64, NODATA_FLOAT) if vars_dict['do_economic_returns']: returns_raster = base_raster_float.zeros() crops = vars_dict['crops_in_aoi_list'] for crop in crops: LOGGER.info('Calculating observed yield for %s' % crop) # Wrangle Data... observed_yield_over_aoi_raster = _get_observed_yield_from_dataset( vars_dict, crop, aoi_vector, base_raster_float) ObservedLocalYield_raster = _get_yield_given_lulc( vars_dict, crop, lulc_raster, observed_yield_over_aoi_raster) # Operations as Noted in User's Guide... Production_raster = _calculate_production_for_crop( vars_dict, crop, ObservedLocalYield_raster) total_production = float(round( Production_raster.sum(), 2)) vars_dict['crop_production_dict'][crop] = total_production if vars_dict['do_economic_returns']: returns_raster_crop = _calc_crop_returns( vars_dict, crop, lulc_raster, Production_raster, returns_raster, vars_dict['economics_table_dict'][crop]) if not np.isnan(returns_raster_crop.sum()): returns_raster = returns_raster + returns_raster_crop # Clean Up Rasters... del observed_yield_over_aoi_raster del ObservedLocalYield_raster del Production_raster if vars_dict['do_nutrition']: vars_dict = _calc_nutrition(vars_dict) # Results Table io.create_results_table(vars_dict) if all([vars_dict['do_economic_returns'], vars_dict['create_crop_production_maps']]): output_observed_yield_dir = vars_dict['output_yield_func_dir'] returns_uri = os.path.join( output_observed_yield_dir, 'economic_returns_map.tif') returns_raster.save_raster(returns_uri) return vars_dict
def filter(): test_dir = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + 'test_data' + os.path.sep test_file = test_dir + 'test.dep' output_file = test_dir + 'delete_me.dep' print('Reading data...') raster = Raster.from_file(test_file) output = Raster.create_from_other(output_file, raster) filter_size = 7 mid_point = int(filter_size / 2.0) dx = [] dy = [] for r in range(filter_size): for c in range(filter_size): dx.append(c - mid_point) dy.append(r - mid_point) num_neighbours = len(dx) threshold = 10.0 values = [0.0]*num_neighbours w = [0.0]*num_neighbours old_progress = 1 for row in range(raster.rows): for col in range(raster.columns): z = raster[row, col] if z != raster.nodata: sum_w = 0.0 for n in range(num_neighbours): xn = col + dx[n] yn = row + dy[n] zn = raster[yn, xn] if zn != raster.nodata: values[n] = zn diff = math.fabs(zn - z) if diff < threshold: w[n] = 1.0 - diff / threshold sum_w += w[n] else: values[n] = 0.0 w[n] = 0.0 else: values[n] = 0.0 w[n] = 0.0 if sum_w > 0.0: z = 0.0 for n in range(num_neighbours): z += values[n] * w[n] / sum_w output[row, col] = z progress = int(100.0 * (row+1) / raster.rows) if progress != old_progress: print('progress: {}%'.format(progress)) old_progress = progress print('Saving data...') output.write()