def test_bmp_sum(self): """ Make sure that runoff, evapotranspiration, and infiltration sum to precipitation. """ census = { "cell_count": 1, "distribution": { "d:developed_med": {"cell_count": 1} }, "modifications": [ { "change": ":developed_high:", "cell_count": 1, "distribution": { "d:developed_med": {"cell_count": 1} } } ] } precip = 0.984 result = simulate_day(census, precip) runoff = result['modified']['runoff'] et = result['modified']['et'] inf = result['modified']['inf'] total = runoff + et + inf self.assertAlmostEqual(total, precip)
def test_bmp_sum(self): """ Make sure that runoff, evapotranspiration, and infiltration sum to precipitation. """ census = { "cell_count": 1, "distribution": { "d:developed_med": { "cell_count": 1 } }, "modifications": [{ "change": ":developed_high:", "cell_count": 1, "distribution": { "d:developed_med": { "cell_count": 1 } } }] } precip = 0.984 result = simulate_day(census, precip) runoff = result['modified']['runoff'] et = result['modified']['et'] inf = result['modified']['inf'] total = runoff + et + inf self.assertAlmostEqual(total, precip)
def test_day_2(self): """ Test the simulate_day function with lots of BMPs. """ precip = 2 actual = simulate_day(CENSUS_2, precip) expected = DAY_OUTPUT_2 self.assertEqual(actual, expected)
def test_day_1(self): """ Test the simulate_day function. """ self.maxDiff = None precip = 2 actual = simulate_day(CENSUS_1, precip) expected = DAY_OUTPUT_1 self.assertEqual(actual, expected)
def test_day_1(self): """ Test the simulate_day function with only land cover modifications. """ self.maxDiff = None precip = 2 actual = simulate_day(CENSUS_1, precip) expected = DAY_OUTPUT_1 self.assertEqual(actual, expected)
def test_water_balance_2(self): """ Make sure that R, ET, and I sum to precip with with lots of BMPs. """ precip = 4.429 result = simulate_day(CENSUS_2, precip) runoff = result['modified']['runoff'] et = result['modified']['et'] inf = result['modified']['inf'] total = runoff + et + inf self.assertEqual(total, precip)
def test_water_balance_1(self): """ Make sure that R, ET, and I sum to precip with only land cover modifications. """ precip = 2.362 result = simulate_day(CENSUS_1, precip) runoff = result['modified']['runoff'] et = result['modified']['et'] inf = result['modified']['inf'] total = runoff + et + inf self.assertEqual(total, precip)
def test_water_balance(self): """ Make sure that R, ET, and I sum to precip with no modifications. """ census = { "cell_count": 1, "distribution": { "d:developed_med": {"cell_count": 1} }, } precip = 0.984 result = simulate_day(census, precip) runoff = result['modified']['runoff'] et = result['modified']['et'] inf = result['modified']['inf'] total = runoff + et + inf self.assertEqual(total, precip)
def test_water_balance(self): """ Make sure that R, ET, and I sum to precip with no modifications. """ census = { "cell_count": 1, "distribution": { "d:developed_med": { "cell_count": 1 } }, } precip = 0.984 result = simulate_day(census, precip) runoff = result['modified']['runoff'] et = result['modified']['et'] inf = result['modified']['inf'] total = runoff + et + inf self.assertEqual(total, precip)
def test_bmp_runoff(self): """ Make sure that BMPs do not produce negative runoff. """ census = { "cell_count": 1, "distribution": { "d:developed_med": {"cell_count": 1} }, "modifications": [ { "change": "::green_roof", "cell_count": 1, "distribution": { "d:developed_med": {"cell_count": 1} } } ] } result = simulate_day(census, 0.984) self.assertTrue(result['modified']['runoff'] >= 0)
def test_bmp_runoff(self): """ Make sure that BMPs do not produce negative runoff. """ census = { "cell_count": 1, "distribution": { "d:developed_med": { "cell_count": 1 } }, "modifications": [{ "change": "::green_roof", "cell_count": 1, "distribution": { "d:developed_med": { "cell_count": 1 } } }] } result = simulate_day(census, 0.984) self.assertTrue(result['modified']['runoff'] >= 0)
def run_tr55(censuses, aoi, model_input, cached_aoi_census=None): """ A Celery wrapper around our TR55 implementation. censuses is either output from previous tasks in the job chain or are provided directly (in the case where the AoI census and modification censuses are cached). If cached_aoi_census is provided, censuses will only contain the modification_censuses, which were generated in the previous task. If cached_aoi_census isn't provided, the AoI census will be the first census in censuses, and everything else is a modification census. """ # Get precipitation and cell resolution precip = precipitation(model_input) # Normalize AOI to handle single-ring multipolygon # inputs sent from RWD as well as shapes sent from the front-end aoi = to_one_ring_multipolygon(aoi) width = aoi_resolution(aoi) resolution = width * width if precip is None: raise Exception('No precipitation value defined') # Modification/BMP fragments and their censuses # The original modifications are not POSTed. We only # send the altered modifications/modification pieces. modification_pieces = model_input.get('modification_pieces') modification_censuses = (censuses[1:] if cached_aoi_census is None else censuses[0:]) # Calculate total areas for each type modification area_sums = {} for piece in modification_pieces: kinds = piece['value'] area = piece['area'] if 'bmp' in kinds: kind = kinds['bmp'] else: kind = kinds['reclass'] if kind in area_sums: area_sums[kind] += area else: area_sums[kind] = area # The area of interest census aoi_census = cached_aoi_census if cached_aoi_census else censuses[0] if modification_pieces and not modification_censuses: raise Exception('Missing censuses for modifications') elif modification_censuses and not modification_pieces: modification_censuses = [] modifications = apply_modifications_to_census(modification_pieces, modification_censuses) aoi_census['modifications'] = modifications aoi_census['BMPs'] = area_sums # Run the model under both current conditions and Pre-Columbian # conditions. try: model_output = simulate_day(aoi_census, precip, cell_res=resolution) precolumbian_output = simulate_day(aoi_census, precip, cell_res=resolution, precolumbian=True) model_output['pc_unmodified'] = precolumbian_output['unmodified'] model_output['pc_modified'] = precolumbian_output['modified'] runoff = format_runoff(model_output) quality = format_quality(model_output) except KeyError as e: runoff = {} quality = [] logger.error('Bad input data to TR55: %s' % e) # Modifications were added to aoi_census for TR-55, but we do # not want to persist it since we have it stored seperately # and it may cause problems when sharing the aoi_census # for other model runs and scenarios. aoi_census.pop('modifications', None) # Return all results return { 'inputmod_hash': model_input['inputmod_hash'], 'modification_hash': model_input['modification_hash'], 'aoi_census': aoi_census, 'modification_censuses': modification_censuses, 'runoff': runoff, 'quality': quality }
soil_types = ['a', 'b', 'c', 'd'] soil_type_map = { 'a': 0, 'b': 1, 'c': 2, 'd': 3 } # For each input value, compute the model outputs for a # single day and tile. for precip, land_use, soil_type in product(precips, land_uses, soil_types): cells = { 'cell_count': 1, 'distribution': { '%s:%s' % (soil_type, land_use): {'cell_count': 1} } } model_out = simulate_day(cells, precip)['unmodified'] writer.writerow((precip, land_use, soil_type_map[soil_type], model_out['et'], model_out['inf'], model_out['runoff']))
soil_types = ['a', 'b', 'c', 'd'] soil_type_map = { 'a': 0, 'b': 1, 'c': 2, 'd': 3 } # For each input value, compute the model outputs for a # single day and tile. for precip, land_use, soil_type in product(precip_cm, land_uses, soil_types): cells = { 'cell_count': 1, 'distribution': { '%s:%s' % (soil_type, land_use): {'cell_count': 1} } } model_out = simulate_day(cells, cm_to_inches(precip))['unmodified'] writer.writerow((precip, land_use, soil_type_map[soil_type], inches_to_cm(model_out['et']), inches_to_cm(model_out['inf']), inches_to_cm(model_out['runoff'])))
def run_tr55(censuses, model_input, cached_aoi_census=None): """ A Celery wrapper around our TR55 implementation. censuses is either output from previous tasks in the job chain or are provided directly (in the case where the AoI census and modification censuses are cached). If cached_aoi_census is provided, censuses will only contain the modification_censuses, which were generated in the previous task. If cached_aoi_census isn't provided, the AoI census will be the first census in censuses, and everything else is a modification census. """ # Get precipitation and cell resolution precip = get_precip(model_input) width = aoi_resolution(model_input.get('area_of_interest')) resolution = width * width if precip is None: raise Exception('No precipitation value defined') # Modification/BMP fragments and their censuses # The original modifications are not POSTed. We only # send the altered modifications/modification pieces. modification_pieces = model_input.get('modification_pieces') modification_censuses = (censuses[1:] if cached_aoi_census is None else censuses[0:]) # Calculate total areas for each type modification area_sums = {} for piece in modification_pieces: kind = piece['value'] area = piece['area'] if kind in area_sums: area_sums[kind] += area else: area_sums[kind] = area area_bmps = {k: v for k, v in area_sums.iteritems()} # The area of interest census aoi_census = cached_aoi_census if cached_aoi_census else censuses[0] modifications = [] if (modification_pieces and not modification_censuses): raise Exception('Missing censuses for modifications') elif (modification_censuses and not modification_pieces): modification_censuses = [] modifications = build_tr55_modification_input(modification_pieces, modification_censuses) aoi_census['modifications'] = modifications aoi_census['BMPs'] = area_bmps # Run the model under both current conditions and Pre-Columbian # conditions. try: model_output = simulate_day(aoi_census, precip, cell_res=resolution) precolumbian_output = simulate_day(aoi_census, precip, cell_res=resolution, precolumbian=True) model_output['pc_unmodified'] = precolumbian_output['unmodified'] model_output['pc_modified'] = precolumbian_output['modified'] runoff = format_runoff(model_output) quality = format_quality(model_output) except KeyError as e: model_output = None precolumbian_output = None runoff = {} quality = [] logger.error('Bad input data to TR55: %s' % e) # Modifications were added to aoi_census for TR-55, but we do # not want to persist it since we have it stored seperately # and it may cause problems when sharing the aoi_census # for other model runs and scenarios. aoi_census.pop('modifications', None) # Return all results return { 'inputmod_hash': model_input['inputmod_hash'], 'modification_hash': model_input['modification_hash'], 'aoi_census': aoi_census, 'modification_censuses': modification_censuses, 'runoff': runoff, 'quality': quality }
# number being used for the calculations in tables.py. land_uses = [ 'open_water', 'developed_open', 'developed_low', 'developed_med', 'developed_high', 'barren_land', 'deciduous_forest', 'shrub', 'grassland', 'pasture', 'cultivated_crops', 'woody_wetlands' ] soil_types = ['a', 'b', 'c', 'd'] soil_type_map = {'a': 0, 'b': 1, 'c': 2, 'd': 3} # For each input value, compute the model outputs for a # single day and tile. for precip, land_use, soil_type in product(precip_cm, land_uses, soil_types): cells = { 'cell_count': 1, 'distribution': { '%s:%s' % (soil_type, land_use): { 'cell_count': 1 } } } model_out = simulate_day(cells, cm_to_inches(precip))['unmodified'] writer.writerow( (precip, land_use, soil_type_map[soil_type], inches_to_cm(model_out['et']), inches_to_cm(model_out['inf']), inches_to_cm(model_out['runoff'])))