Exemple #1
0
    def clean(self, *args, **kwargs):
        # add custom validation here
        print(self.geo_field, '\n New line')
        geos_field = GEOSGeometry(self.geo_field)
        print(self.geo_field, '\n New line')
        farm_s = farm.objects.get(farm_name=self.farm)

        geos_farm = GEOSGeometry(farm_s.geo_farm)

        if not (
                geos_field.within(geos_farm)
        ):  # GEOS method check if field is within the farm, returns a T or F.
            raise ValidationError(_('Field is not inside the selected farm'),
                                  #params={'farm': farm_s.farm_name },
                                  )

        super(field, self).clean(*args, **kwargs)
Exemple #2
0
def point_source_pollution(geojson):
    """
    Given a GeoJSON shape, retrieve point source pollution data
    from the `ms_pointsource` or `ms_pointsource_drb` table to display
    in the Analyze tab.

    Returns a dictionary to append to the outgoing JSON for analysis
    results.
    """
    geom = GEOSGeometry(geojson, srid=4326)
    drb = geom.within(DRB)
    table_name = get_point_source_table(drb)
    sql = '''
          SELECT city, state, npdes_id, mgd, kgn_yr, kgp_yr, latitude,
                 longitude, {facilityname}
          FROM {table_name}
          WHERE ST_Intersects(geom, ST_SetSRID(ST_GeomFromText(%s), 4326))
          '''.format(facilityname='facilityname' if drb else 'null',
                     table_name=table_name)

    with connection.cursor() as cursor:
        cursor.execute(sql, [geom.wkt])

        if cursor.rowcount != 0:
            columns = [col[0] for col in cursor.description]
            point_source_results = [
                dict(
                    zip(columns, [
                        row[0], row[1], row[2],
                        float(row[3]) if row[3] else None,
                        float(row[4]) if row[4] else None,
                        float(row[5]) if row[5] else None,
                        float(row[6]) if row[6] else None,
                        float(row[7]) if row[7] else None, row[8]
                    ])) for row in cursor.fetchall()
            ]
        else:
            point_source_results = []

    return {
        'displayName': 'Point Source',
        'name': 'pointsource',
        'categories': point_source_results
    }
Exemple #3
0
def collect_data(geop_results, geojson, watershed_id=None, weather=None):
    geop_result = {k: v for r in geop_results for k, v in r.items()}

    geom = GEOSGeometry(geojson, srid=4326)
    area = geom.transform(5070, clone=True).area  # Square Meters

    # Data Model is called z by convention
    z = settings.GWLFE_DEFAULTS.copy()

    z['watershed_id'] = watershed_id

    # Statically calculated lookup values
    z['DayHrs'] = day_lengths(geom)

    # Data from the Weather Stations dataset
    if weather is not None:
        ws, wd = weather
    else:
        ws = nearest_weather_stations([(None, watershed_id, geojson)])

    z['Grow'] = growing_season(ws)
    z['Acoef'] = erosion_coeff(ws, z['Grow'])
    z['PcntET'] = et_adjustment(ws)
    z['WxYrBeg'] = int(max([w.begyear for w in ws]))
    z['WxYrEnd'] = int(min([w.endyear for w in ws]))
    z['WxYrs'] = z['WxYrEnd'] - z['WxYrBeg'] + 1

    # Data from the County Animals dataset
    ag_lscp = ag_ls_c_p(geom)
    z['C'][0] = ag_lscp.hp_c
    z['C'][1] = ag_lscp.crop_c

    livestock_aeu, poultry_aeu, population = animal_energy_units(geom)
    z['AEU'] = livestock_aeu / (area * ACRES_PER_SQM)
    z['n41j'] = livestock_aeu
    z['n41k'] = poultry_aeu
    z['n41l'] = livestock_aeu + poultry_aeu
    z['NumAnimals'] = [int(population.get(animal, 0))
                       for animal in ANIMAL_KEYS]

    z['ManNitr'], z['ManPhos'] = manure_spread(z['AEU'])

    # Data from Streams dataset
    z['StreamLength'] = stream_length(geom) or 10   # Meters
    z['n42b'] = round(z['StreamLength'] / 1000, 1)  # Kilometers

    # Data from Point Source Discharge dataset
    n_load, p_load, discharge = point_source_discharge(geom, area,
                                                       drb=geom.within(DRB))
    z['PointNitr'] = n_load
    z['PointPhos'] = p_load
    z['PointFlow'] = discharge

    # Data from National Weather dataset
    if weather is None:
        wd = weather_data(ws, z['WxYrBeg'], z['WxYrEnd'])
        temps_dict, prcps_dict = wd
        temps = average_weather_data(temps_dict.values())
        prcps = average_weather_data(prcps_dict.values())
    else:
        temps, prcps = wd
    z['Temp'] = temps
    z['Prec'] = prcps

    # Begin processing geop_result

    # Set stream related variables to zero if AoI does not contain
    # any streams.
    if 'ag_stream_pct' in geop_result:
        z['AgLength'] = geop_result['ag_stream_pct'] * z['StreamLength']
        z['UrbLength'] = z['StreamLength'] - z['AgLength']
        z['n42'] = round(z['AgLength'] / 1000, 1)
        z['n46e'] = (geop_result['med_high_urban_stream_pct'] *
                     z['StreamLength'] / 1000)
        z['n46f'] = (geop_result['low_urban_stream_pct'] *
                     z['StreamLength'] / 1000)
    else:
        z['AgLength'] = 0
        z['UrbLength'] = 0
        z['n42'] = 0
        z['n46e'] = 0
        z['n46f'] = 0

    z['CN'] = geop_result['cn']
    z['SedPhos'] = geop_result['soilp']
    z['Area'] = [percent * area * HECTARES_PER_SQM
                 for percent in geop_result['landuse_pcts']]

    # Immediately return an error if z['Area'] is a list of 0s
    if sum(z['Area']) == 0:
        raise Exception(NO_LAND_COVER)

    z['UrbAreaTotal'] = sum(z['Area'][NRur:])
    z['PhosConc'] = phosphorus_conc(z['SedPhos'])

    z['NumNormalSys'] = num_normal_sys(z['Area'])

    z['AgSlope3'] = geop_result['ag_slope_3_pct'] * area * HECTARES_PER_SQM
    z['AgSlope3To8'] = (geop_result['ag_slope_3_8_pct'] *
                        area * HECTARES_PER_SQM)
    z['n41'] = geop_result['n41']

    z['AvSlope'] = geop_result['avg_slope']

    z['AvKF'] = geop_result['avg_kf']
    z['KF'] = geop_result['kf']

    z['KV'] = kv_coefficient(geop_result['landuse_pcts'], z['Grow'])

    # Original at [email protected]:9803-9807
    z['n23'] = z['Area'][1]    # Row Crops Area
    z['n23b'] = z['Area'][13]  # High Density Mixed Urban Area
    z['n24'] = z['Area'][0]    # Hay/Pasture Area
    z['n24b'] = z['Area'][11]  # Low Density Mixed Urban Area

    z['SedDelivRatio'] = sediment_delivery_ratio(area * SQKM_PER_SQM)
    z['TotArea'] = area * HECTARES_PER_SQM
    z['GrNitrConc'] = geop_result['gr_nitr_conc']
    z['GrPhosConc'] = geop_result['gr_phos_conc']
    z['MaxWaterCap'] = geop_result['avg_awc']
    z['SedAFactor'] = sed_a_factor(geop_result['landuse_pcts'],
                                   z['CN'], z['AEU'], z['AvKF'], z['AvSlope'])

    # Use zeroed out stream variables if there are no streams in the AoI
    if 'lu_stream_pct' in geop_result:
        z['LS'] = ls_factors(geop_result['lu_stream_pct'], z['StreamLength'],
                             z['Area'], z['AvSlope'], ag_lscp)
    else:
        zeroed_lu_stream_pct = [0.0] * 16
        z['LS'] = ls_factors(zeroed_lu_stream_pct, 0,
                             z['Area'], z['AvSlope'], ag_lscp)

    z['P'] = p_factors(z['AvSlope'], ag_lscp)

    z['SedNitr'] = geop_result['soiln']

    z['RecessionCoef'] = geop_result['recess_coef']

    return z
def start_analyze_drb_2100_land(request, key=None, format=None):
    """
    Starts a job to get a land-use histogram for an area within DRB in 2100.

    Uses simulations of change in land use over the 20-year period 2080-2099
    based on two urban growth scenarios: centers and corridors. Generated by
    Shippensburg University, serviced via APIs by Drexel University and the
    Academy of Natural Sciences.

    For more information, see the
    [technical documentation](https://wikiwatershed.org/
    documentation/mmw-tech/#overlays-tab-coverage).

    ## Response

    You can use the URL provided in the response's `Location`
    header to poll for the job's results.

    <summary>
       **Example of a completed job's `result`**
    </summary>

    <details>

        {
          "survey": {
            "displayName": "DRB 2100 land forecast (corridors)",
            "name": "drb_2100_land_corridors",
            "categories": [
              {
                "area": 3572379,
                "code": "open_water",
                "coverage": 0.041698374846361526,
                "nlcd": 11,
                "type": "Open Water"
              },
              {
                "area": 0,
                "code": "perennial_ice",
                "coverage": 0.0,
                "nlcd": 12,
                "type": "Perennial Ice/Snow"
              },
              {
                "area": 10355769,
                "code": "developed_open",
                "coverage": 0.12087707871542477,
                "nlcd": 21,
                "type": "Developed, Open Space"
              },
              {
                "area": 11455623,
                "code": "developed_low",
                "coverage": 0.13371505709573384,
                "nlcd": 22,
                "type": "Developed, Low Intensity"
              },
              {
                "area": 27048582,
                "code": "developed_med",
                "coverage": 0.3157229149814583,
                "nlcd": 23,
                "type": "Developed, Medium Intensity"
              },
              {
                "area": 29183382,
                "code": "developed_high",
                "coverage": 0.3406412370917419,
                "nlcd": 24,
                "type": "Developed, High Intensity"
              },
              {
                "area": 11187,
                "code": "barren_land",
                "coverage": 0.00013057957159815528,
                "nlcd": 31,
                "type": "Barren Land (Rock/Sand/Clay)"
              },
              {
                "area": 2684196,
                "code": "deciduous_forest",
                "coverage": 0.03133111323549495,
                "nlcd": 41,
                "type": "Deciduous Forest"
              },
              {
                "area": 14301,
                "code": "evergreen_forest",
                "coverage": 0.00016692754567133446,
                "nlcd": 42,
                "type": "Evergreen Forest"
              },
              {
                "area": 93402,
                "code": "mixed_forest",
                "coverage": 0.001090229118298999,
                "nlcd": 43,
                "type": "Mixed Forest"
              },
              {
                "area": 114768,
                "code": "shrub",
                "coverage": 0.001339622443298211,
                "nlcd": 52,
                "type": "Shrub/Scrub"
              },
              {
                "area": 55143,
                "code": "grassland",
                "coverage": 0.000643653286550199,
                "nlcd": 71,
                "type": "Grassland/Herbaceous"
              },
              {
                "area": 59643,
                "code": "pasture",
                "coverage": 0.0006961792606443887,
                "nlcd": 81,
                "type": "Pasture/Hay"
              },
              {
                "area": 14193,
                "code": "cultivated_crops",
                "coverage": 0.0001656669222930739,
                "nlcd": 82,
                "type": "Cultivated Crops"
              },
              {
                "area": 574722,
                "code": "woody_wetlands",
                "coverage": 0.006708407307413516,
                "nlcd": 90,
                "type": "Woody Wetlands"
              },
              {
                "area": 434610,
                "code": "herbaceous_wetlands",
                "coverage": 0.0050729585780168295,
                "nlcd": 95,
                "type": "Emergent Herbaceous Wetlands"
              }
            ]
          }
        }

    </details>
    """
    user = request.user if request.user.is_authenticated else None
    area_of_interest, wkaoi = _parse_input(request)

    errs = []
    if not key:
        errs.append('`key` must be specified')
    if key not in settings.DREXEL_FAST_ZONAL_API['keys']:
        errs.append('`key` must be one of "{}".'.format('", "'.join(
            settings.DREXEL_FAST_ZONAL_API['keys'])))

    # A little redundant since GeoJSON -> GEOSGeometry is already done once
    # within _parse_input, but it is not returned from there and changing
    # that API could break many things.
    geom = GEOSGeometry(area_of_interest, srid=4326)

    # In the front-end, we use DRB_SIMPLE_PERIMETER. This is sent from the
    # back-end on every page render, and is considerably lighter ~0.2% than
    # the actual perimeter. We use the same here for consistency.
    if not geom.within(settings.DRB_SIMPLE_PERIMETER):
        errs.append('The area of interest must be within the'
                    ' Delaware River Basin.')

    if errs:
        return Response({'errors': errs}, status=status.HTTP_400_BAD_REQUEST)

    return start_celery_job(
        [tasks.analyze_drb_2100_land.s(area_of_interest, key)],
        area_of_interest, user)