Ejemplo n.º 1
0
    def from_geometry_to_record(self,
                                geometry,
                                record,
                                default_srid=MODEL_SRID):
        if not geometry:
            return record
        # we can only deal with point. Getting the centroid should cover polygons
        point = geometry.centroid
        # convert the geometry in the record srid (if any)
        srid = self.cast_srid(record, default_srid=default_srid)
        datum, zone = (None, None)
        if srid:
            point.transform(srid)
            datum, zone = get_datum_and_zone(srid)
        # update record field
        record = record or {}

        if self.datum_field and datum:
            record[self.datum_field.name] = datum
        if self.zone_field and zone:
            record[self.zone_field.name] = zone

        if self.is_easting_northing and is_projected_srid(srid):
            if self.easting_field:
                record[self.easting_field.name] = point.x
            if self.northing_field:
                record[self.northing_field.name] = point.y
        elif self.is_lat_long and not is_projected_srid(srid):
            if self.longitude_field:
                record[self.longitude_field.name] = point.x
            if self.latitude_field:
                record[self.latitude_field.name] = point.y
        else:
            # what is going on here?
            # schema and datum/zone divergence?
            logger.warning(
                "Ambiguous schema and coordinate system. "
                "Cannot extract easting/northing from a spherical coordinate system "
                "or lat/long from a projected one. "
                "Schema: {}, srid: {}, record: {}".format(
                    self.schema, srid, record))
        return record
Ejemplo n.º 2
0
    def test_geometry_to_data(self):
        project = self.project_1
        client = self.custodian_1_client
        schema = self.schema_with_lat_long()
        dataset = self._create_dataset_with_schema(project,
                                                   self.data_engineer_1_client,
                                                   schema)
        self.assertIsNotNone(dataset.schema.latitude_field)
        self.assertIsNotNone(dataset.schema.longitude_field)
        self.assertIsNotNone(dataset.schema.datum_field)

        url = reverse('api:geometry-to-data', kwargs={'pk': dataset.pk})
        # the geometry is required
        payload = {}
        resp = client.post(url, data=payload, format='json')
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)

        # send a geometry and no data.
        new_geometry = {'type': 'Point', 'coordinates': [118, -34.0]}
        payload = {'geometry': new_geometry}
        resp = client.post(url, data=payload, format='json')
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.get('content-type'), 'application/json')
        data = resp.json()
        self.assertTrue('geometry' in data)
        self.assertTrue('data' in data)
        # the returned datum should be the project
        expected_datum, expected_zone = constants.get_datum_and_zone(
            project.datum)
        expected_data = {
            'Longitude': 118.0,
            'Latitude': -34.0,
            'Datum': expected_datum
        }
        self.assertEqual(data['data'], expected_data)
        expected_geometry = new_geometry
        self.assertEqual(data['geometry'], expected_geometry)

        # send geometry and data
        new_geometry = {'type': 'Point', 'coordinates': [118, -34.0]}
        new_data = {
            'What': 'Updated What',
            'When': '01/01/2001',
            'Longitude': 0,
            'Latitude': 0,
            'Datum': 'WGS84'
        }
        payload = {'geometry': new_geometry, 'data': new_data}
        resp = client.post(url, data=payload, format='json')
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.get('content-type'), 'application/json')
        data = resp.json()
        self.assertTrue('geometry' in data)
        self.assertTrue('data' in data)
        expected_data = {
            'What': new_data['What'],
            'When': new_data['When'],
            'Longitude': 118.0,
            'Latitude': -34.0,
            'Datum': new_data['Datum'],
        }
        self.assertEqual(data['data'], expected_data)
        expected_geometry = new_geometry
        self.assertEqual(data['geometry'], expected_geometry)
Ejemplo n.º 3
0
    def __init__(self, schema, project=None):
        if not isinstance(schema, GenericSchema):
            schema = GenericSchema(schema)
        self.schema = schema
        self.project = project
        self.errors = []

        # Site Code
        self.site_code_field, errors = self._find_site_code_field()
        if errors:
            self.errors += errors

        # Datum
        self.datum_field, errors = find_unique_field(
            self.schema, BiosysSchema.DATUM_TYPE_NAME,
            ObservationSchema.DATUM_FIELD_NAME)
        if errors:
            self.errors += errors

        # Zone
        self.zone_field, errors = find_unique_field(
            self.schema, BiosysSchema.ZONE_TYPE_NAME,
            ObservationSchema.ZONE_FIELD_NAME)
        if errors:
            self.errors += errors

        # Latitude
        self.latitude_field, errors = find_unique_field(
            self.schema, BiosysSchema.LATITUDE_TYPE_NAME,
            ObservationSchema.LATITUDE_FIELD_NAME)
        if errors:
            self.errors += errors

        # Longitude
        self.longitude_field, errors = find_unique_field(
            self.schema, BiosysSchema.LONGITUDE_TYPE_NAME,
            ObservationSchema.LONGITUDE_FIELD_NAME)
        if errors:
            self.errors += errors

        # Easting
        self.easting_field, errors = find_unique_field(
            self.schema, BiosysSchema.EASTING_TYPE_NAME,
            ObservationSchema.EASTING_FIELD_NAME)
        if errors:
            self.errors += errors

        # Northing
        self.northing_field, errors = find_unique_field(
            self.schema, BiosysSchema.NORTHING_TYPE_NAME,
            ObservationSchema.NORTHING_FIELD_NAME)
        if errors:
            self.errors += errors

        # some post validations.
        # we need at least one method to get the geometry.
        if not any([
                self.site_code_field, self.latitude_field,
                self.longitude_field, self.easting_field, self.northing_field
        ]):
            msg = "The schema must contain some geometry fields: latitude/longitude or easting/northing or " \
                  "alternatively a reference to the Site Code."
            self.errors.append(msg)
        # if we have a latitude we must have a longitude and vice-versa
        if not self.errors:
            if self.latitude_field and not self.longitude_field:
                self.errors.append("Missing Longitude field")
            if self.longitude_field and not self.latitude_field:
                self.errors.append("Missing Latitude field")
                # same for easting and northing
            if self.easting_field and not self.northing_field:
                self.errors.append("Missing Northing field")
            if self.northing_field and not self.easting_field:
                self.errors.append("Missing Easting field")

        # verify 'required' constraints: required constraints must be set if we are in 'single' mode.
        # e.g lat/long without site code or easting/northing
        if self.is_site_code_only and not self.site_code_field.required:
            self.errors.append(format_required_message(self.site_code_field))
        if self.is_lat_long_only:
            if not self.latitude_field.required:
                self.errors.append(format_required_message(
                    self.latitude_field))
            if not self.longitude_field.required:
                self.errors.append(
                    format_required_message(self.longitude_field))
        if self.is_easting_northing_only:
            if not self.easting_field.required:
                self.errors.append(format_required_message(self.easting_field))
            if not self.northing_field.required:
                self.errors.append(format_required_message(
                    self.northing_field))
            if not self.datum_field and (not self.zone_field
                                         or not self.zone_field.required):
                # Zone is mandatory if the project datum is not one with zone (projected).
                if self.project:
                    datum, zone = get_datum_and_zone(project.datum)
                    if zone is None:
                        if not self.zone_field:
                            msg = "Northing/easting coordinates require a zone," \
                                  " but none has been supplied and the default datum for this project ({datum})" \
                                  " does not include a zone. " \
                                  "Either provide a zone in your data or " \
                                  "change the default datum in the project to include a zone.".format(datum=datum)
                        else:
                            # zone field not set as required
                            msg = "Northing/easting coordinates require a zone, " \
                                  "but your zone field is not set as required and the default datum " \
                                  "for this project ({datum}) does not include a zone. " \
                                  "Either set the field as required or " \
                                  "change the default datum in the project to include a zone.".format(datum=datum)
                        self.errors.append(msg)