Пример #1
0
    def test_unwrap(self):
        """Test different geometry types are appropriately unwrapped."""

        wrapper = Wrapper()
        path = tempfile.mkdtemp()
        for desc, geom in self.possible.iteritems():
            unwrapped = wrapper.unwrap(geom)
            if desc in self.actual_unwrapped:
                self.assertTrue(self.actual_unwrapped[desc].almost_equals(unwrapped, decimal=5))
            try:
                self.assertEqual(type(geom), type(unwrapped))
            except AssertionError:
                if desc == 'axis_polygon':
                    # by necessity of being split on the axis, this will come out as a multipolygon
                    self.assertIsInstance(unwrapped, MultiPolygon)
                else:
                    raise

            self.assertFalse(np.any(np.array(unwrapped) < 0.0))
            if isinstance(unwrapped, (MultiPolygon, Polygon)):
                it = get_iter(unwrapped)
                for polygon in it:
                    self.assertFalse(np.any(np.array(polygon.exterior) > 360.0))
            else:
                self.assertFalse(np.any(np.array(unwrapped) > 360.0))
Пример #2
0
 def test_unwrap(self):
     sd = ShpDataset('state_boundaries')        
     for axis in self.axes:
         w = Wrapper(axis=axis)
         for geom in sd.spatial.geom:
             new_geom = w.unwrap(geom)
             bounds = np.array(new_geom.bounds)
             self.assertFalse(np.any(bounds < axis))
Пример #3
0
 def test_wrap(self):
     sd = ShpDataset('state_boundaries')
     for axis in self.axes:
         w = Wrapper(axis=axis)
         unwrapped = [w.unwrap(geom) for geom in sd.spatial.geom]
         for idx,unwrapped_geom in enumerate(unwrapped):
             new_geom = w.wrap(unwrapped_geom)
             self.assertFalse(unwrapped_geom.equals(new_geom))
             self.assertTrue(sd.spatial.geom[idx].almost_equals(new_geom))
Пример #4
0
    def test_wrap(self):
        """Test different geometry types are appropriately wrapped."""

        wrapper = Wrapper()
        for desc, geom in self.possible.iteritems():
            unwrapped = wrapper.unwrap(geom)
            wrapped = wrapper.wrap(unwrapped)
            try:
                self.assertTrue(geom.almost_equals(wrapped))
            except AssertionError:
                # the axis multipolygon when wrapped will have an extra polygon as the split portion on the axis will
                # be in two parts
                if desc == 'axis_multipolygon':
                    self.assertNumpyAllClose(np.array(wrapped.bounds), np.array(geom.bounds))
                    self.assertEqual(len(wrapped), 4)
                # polygon will also be split...
                elif desc == 'axis_polygon':
                    self.assertNumpyAllClose(np.array(wrapped.bounds), np.array(geom.bounds))
                    self.assertEqual(len(wrapped), 2)
                else:
                    raise
Пример #5
0
def get_collection((so, geom)):
    '''
    :type so: SubsetOperation
    :type geom: None, GeometryDataset, ShpDataset
    :rtype: AbstractCollection
    '''

    ## initialize the collection object to store the subsetted data.
    coll = RawCollection(ugeom=geom)
    ## perform the operations on each request dataset
    if env.VERBOSE:
        print('{0} request dataset(s) to process.'.format(len(so.ops.dataset)))
    for request_dataset in so.ops.dataset:
        if env.VERBOSE:
            if geom is None:
                msg = 'processing: alias={0}'.format(request_dataset.alias)
            else:
                msg = 'processing: ugid={0}, alias={1}'.format(
                    geom.spatial.uid[0], request_dataset.alias)
            print(msg)
        ## copy the geometry
        copy_geom = deepcopy(geom)
        ## reference the dataset object
        ods = request_dataset.ds
        ## return a slice or do the other operations
        if so.ops.slice is not None:
            ods = ods.__getitem__(so.ops.slice)
        ## other subsetting operations
        else:
            ## if a geometry is passed and the target dataset is 360 longitude,
            ## unwrap the passed geometry to match the spatial domain of the target
            ## dataset.
            if copy_geom is None:
                igeom = None
            else:
                ## check projections adjusting projection the selection geometry
                ## if necessary
                if type(ods.spatial.projection) != type(
                        copy_geom.spatial.projection):
                    copy_geom.project(ods.spatial.projection)
                ## unwrap the data if it is geographic and 360
                if type(ods.spatial.projection
                        ) == WGS84 and ods.spatial.is_360:
                    w = Wrapper(axis=ods.spatial.pm)
                    copy_geom.spatial.geom[0] = w.unwrap(
                        deepcopy(copy_geom.spatial.geom[0]))
                igeom = copy_geom.spatial.geom[0]
            ## perform the data subset
            try:
                ods = ods.get_subset(
                    spatial_operation=so.ops.spatial_operation,
                    igeom=igeom,
                    temporal=request_dataset.time_range,
                    level=request_dataset.level_range)
                ## aggregate the geometries and data if requested
                if so.ops.aggregate:
                    ## the new geometry will have the same id as the passed
                    ## geometry. if it does not have one, simple give it a value
                    ## of 1 as it is the only geometry requested for subsetting.
                    try:
                        new_geom_id = copy_geom.spatial.uid[0]
                    except AttributeError:
                        new_geom_id = 1
                    ## do the aggregation in place.
                    clip_geom = None if copy_geom is None else copy_geom.spatial.geom[
                        0]
                    ods.aggregate(new_geom_id=new_geom_id, clip_geom=clip_geom)
                ## wrap the returned data depending on the conditions of the
                ## operations.
                if not env.OPTIMIZE_FOR_CALC:
                    if type(ods.spatial.projection) == WGS84 and \
                       ods.spatial.is_360 and \
                       so.ops.output_format != 'nc' and \
                       so.ops.vector_wrap:
                        ods.spatial.vector.wrap()
                ## check for all masked values
                if not so.ops.file_only and ods.value.mask.all():
                    if so.ops.snippet or so.ops.allow_empty:
                        if env.VERBOSE:
                            if so.ops.snippet:
                                print(
                                    'all masked data encountered but allowed for snippet.'
                                )
                            if so.ops.allow_empty:
                                print(
                                    'all masked data encountered but empty returns are allowed.'
                                )
                        pass
                    else:
                        raise (MaskedDataError)
            ## there may be no data returned - this may be real or could be an
            ## error. by default, empty returns are not allowed
            except EmptyData:
                if so.ops.allow_empty:
                    if env.VERBOSE:
                        print(
                            'the geometric operations returned empty but empty returns are allowed'
                        )
                    continue
                else:
                    raise (ExtentError(request_dataset))
        coll.variables.update({request_dataset.alias: ods})

    ## if there are calculations, do those now and return a new type of collection
    if so.cengine is not None:
        coll = so.cengine.execute(coll, file_only=so.ops.file_only)

    ## conversion of groups.
    if so.ops.output_grouping is not None:
        raise (NotImplementedError)
    else:
        return (coll)
Пример #6
0
 def wrap(self):
     wrap = Wrapper().wrap
     geom = self.geom
     for (ii, jj), to_wrap in iter_array(geom, return_value=True):
         geom[ii, jj] = wrap(to_wrap)
Пример #7
0
 def unwrap_geoms(self, axis=0.0):
     axis = float(axis)
     w = Wrapper(axis=axis)
     geom = self.geom
     for idx in range(geom.shape[0]):
         geom[idx] = w.unwrap(geom[idx])
Пример #8
0
def get_collection((so,geom)):
    '''
    :type so: SubsetOperation
    :type geom: None, GeometryDataset, ShpDataset
    :rtype: AbstractCollection
    '''
    
    ## initialize the collection object to store the subsetted data.
    coll = RawCollection(ugeom=geom)
    ## perform the operations on each request dataset
    if env.VERBOSE: print('{0} request dataset(s) to process.'.format(len(so.ops.dataset)))
    for request_dataset in so.ops.dataset:
        if env.VERBOSE:
            if geom is None:
                msg = 'processing: alias={0}'.format(request_dataset.alias)
            else:
                msg = 'processing: ugid={0}, alias={1}'.format(geom.spatial.uid[0],request_dataset.alias)
            print(msg)
        ## copy the geometry
        copy_geom = deepcopy(geom)
        ## reference the dataset object
        ods = request_dataset.ds
        ## return a slice or do the other operations
        if so.ops.slice is not None:
            ods = ods.__getitem__(so.ops.slice)
        ## other subsetting operations
        else:
            ## if a geometry is passed and the target dataset is 360 longitude,
            ## unwrap the passed geometry to match the spatial domain of the target
            ## dataset.
            if copy_geom is None:
                igeom = None
            else:
                ## check projections adjusting projection the selection geometry
                ## if necessary
                if type(ods.spatial.projection) != type(copy_geom.spatial.projection):
                    copy_geom.project(ods.spatial.projection)
                ## unwrap the data if it is geographic and 360
                if type(ods.spatial.projection) == WGS84 and ods.spatial.is_360:
                    w = Wrapper(axis=ods.spatial.pm)
                    copy_geom.spatial.geom[0] = w.unwrap(deepcopy(copy_geom.spatial.geom[0]))
                igeom = copy_geom.spatial.geom[0]
            ## perform the data subset
            try:
                ods = ods.get_subset(spatial_operation=so.ops.spatial_operation,
                                     igeom=igeom,
                                     temporal=request_dataset.time_range,
                                     level=request_dataset.level_range)
                ## aggregate the geometries and data if requested
                if so.ops.aggregate:
                    ## the new geometry will have the same id as the passed
                    ## geometry. if it does not have one, simple give it a value
                    ## of 1 as it is the only geometry requested for subsetting.
                    try:
                        new_geom_id = copy_geom.spatial.uid[0]
                    except AttributeError:
                        new_geom_id = 1
                    ## do the aggregation in place.
                    clip_geom = None if copy_geom is None else copy_geom.spatial.geom[0]
                    ods.aggregate(new_geom_id=new_geom_id,
                                  clip_geom=clip_geom)
                ## wrap the returned data depending on the conditions of the
                ## operations.
                if not env.OPTIMIZE_FOR_CALC:
                    if type(ods.spatial.projection) == WGS84 and \
                       ods.spatial.is_360 and \
                       so.ops.output_format != 'nc' and \
                       so.ops.vector_wrap:
                        ods.spatial.vector.wrap()
                ## check for all masked values
                if not so.ops.file_only and ods.value.mask.all():
                    if so.ops.snippet or so.ops.allow_empty:
                        if env.VERBOSE:
                            if so.ops.snippet:
                                print('all masked data encountered but allowed for snippet.')
                            if so.ops.allow_empty:
                                print('all masked data encountered but empty returns are allowed.')
                        pass
                    else:
                        raise(MaskedDataError)
            ## there may be no data returned - this may be real or could be an
            ## error. by default, empty returns are not allowed
            except EmptyData:
                if so.ops.allow_empty:
                    if env.VERBOSE:
                        print('the geometric operations returned empty but empty returns are allowed')
                    continue
                else:
                    raise(ExtentError(request_dataset))
        coll.variables.update({request_dataset.alias:ods})

    ## if there are calculations, do those now and return a new type of collection
    if so.cengine is not None:
        coll = so.cengine.execute(coll,file_only=so.ops.file_only)
    
    ## conversion of groups.
    if so.ops.output_grouping is not None:
        raise(NotImplementedError)
    else:
        return(coll)
Пример #9
0
def get_collection((so,geom,logger)):
    '''
    :type so: SubsetOperation
    :type geom: None, GeometryDataset, ShpDataset
    :rtype: AbstractCollection
    '''
    
    ## initialize the collection object to store the subsetted data.
    coll = RawCollection(ugeom=geom,ops=so.ops)
    ## perform the operations on each request dataset
    ocgis_lh('{0} request dataset(s) to process'.format(len(so.ops.dataset)),logger)
    ## reference the geometry ugid
    ugid = None if geom is None else geom.spatial.uid[0]
    for request_dataset in so.ops.dataset:
        ## reference the request dataset alias
        alias = request_dataset.alias
        ocgis_lh('processing',logger,level=logging.INFO,alias=alias,ugid=ugid)
        ## copy the geometry
        copy_geom = deepcopy(geom)
        ## reference the dataset object
        ods = request_dataset.ds
        ## return a slice or do the other operations
        if so.ops.slice is not None:
            ods = ods.__getitem__(so.ops.slice)
        ## other subsetting operations
        else:
            ## if a geometry is passed and the target dataset is 360 longitude,
            ## unwrap the passed geometry to match the spatial domain of the target
            ## dataset.
            if copy_geom is None:
                igeom = None
            else:
                ## check projections adjusting projection the selection geometry
                ## if necessary
                if type(ods.spatial.projection) != type(copy_geom.spatial.projection):
                    msg = 'projecting selection geometry to match input projection: {0} to {1}'
                    msg = msg.format(copy_geom.spatial.projection.__class__.__name__,
                                     ods.spatial.projection.__class__.__name__)
                    ocgis_lh(msg,logger,alias=alias,ugid=ugid)
                    copy_geom.project(ods.spatial.projection)
                else:
                    ocgis_lh('projections match',logger,alias=alias,ugid=ugid)
                ## unwrap the data if it is geographic and 360
                if type(ods.spatial.projection) == WGS84 and ods.spatial.is_360:
                    ocgis_lh('unwrapping selection geometry with axis={0}'.format(ods.spatial.pm),
                             logger,alias=alias,ugid=ugid)
                    w = Wrapper(axis=ods.spatial.pm)
                    copy_geom.spatial.geom[0] = w.unwrap(deepcopy(copy_geom.spatial.geom[0]))
                igeom = copy_geom.spatial.geom[0]
            ## perform the data subset
            try:
                ## pull the temporal subset which may be a range or region. if
                ## it is a snippet operation, set the temporal subset to None
                ## as a slice has already been applied. however, if a calculation
                ## is present leave the temporal subset alone.
                if so.ops.snippet and so.ops.calc is None:
                    temporal = None
                else:
                    temporal = request_dataset.time_range or request_dataset.time_region
                
                ocgis_lh('executing get_subset',logger,level=logging.DEBUG)
                ods = ods.get_subset(spatial_operation=so.ops.spatial_operation,
                                     igeom=igeom,
                                     temporal=temporal,
                                     level=request_dataset.level_range)
                
                ## for the case of time range and time region subset, apply the
                ## time region subset following the time range subset.
                if request_dataset.time_range is not None and request_dataset.time_region is not None:
                    ods._temporal = ods.temporal.subset(request_dataset.time_region)
                
                ## aggregate the geometries and data if requested
                if so.ops.aggregate:
                    ocgis_lh('aggregating target geometries and area-weighting values',
                             logger,alias=alias,ugid=ugid)
                    ## the new geometry will have the same id as the passed
                    ## geometry. if it does not have one, simple give it a value
                    ## of 1 as it is the only geometry requested for subsetting.
                    try:
                        new_geom_id = copy_geom.spatial.uid[0]
                    except AttributeError:
                        new_geom_id = 1
                    ## do the aggregation in place.
                    clip_geom = None if copy_geom is None else copy_geom.spatial.geom[0]
                    ods.aggregate(new_geom_id=new_geom_id,
                                  clip_geom=clip_geom)
                ## wrap the returned data depending on the conditions of the
                ## operations.
                if not env.OPTIMIZE_FOR_CALC:
                    if type(ods.spatial.projection) == WGS84 and \
                       ods.spatial.is_360 and \
                       so.ops.output_format != 'nc' and \
                       so.ops.vector_wrap:
                        ocgis_lh('wrapping output geometries',logger,alias=alias,
                                 ugid=ugid)
                        ods.spatial.vector.wrap()
                        ocgis_lh('geometries wrapped',logger,alias=alias,
                                 ugid=ugid,level=logging.DEBUG)
                ## check for all masked values
                if env.OPTIMIZE_FOR_CALC is False and so.ops.file_only is False:
                    if ods.value.mask.all():
                        ## masked data may be okay depending on other opeartional
                        ## conditions.
                        if so.ops.snippet or so.ops.allow_empty:
                            if so.ops.snippet:
                                ocgis_lh('all masked data encountered but allowed for snippet',
                                         logger,alias=alias,ugid=ugid,level=logging.WARN)
                            if so.ops.allow_empty:
                                ocgis_lh('all masked data encountered but empty returns allowed',
                                         logger,alias=alias,ugid=ugid,level=logging.WARN)
                            pass
                        else:
                            ## if the geometry is also masked, it is an empty spatial
                            ## operation.
                            if ods.spatial.vector.geom.mask.all():
                                raise(EmptyData)
                            else:
                                ocgis_lh(None,logger,exc=MaskedDataError(),alias=alias,ugid=ugid)
            ## there may be no data returned - this may be real or could be an
            ## error. by default, empty returns are not allowed
            except EmptyData as ed:
                if so.ops.allow_empty:
                    if ed.origin == 'time':
                        msg = 'the time subset returned empty but empty returns are allowed'
                    else:
                        msg = 'the geometric operations returned empty but empty returns are allowed'
                    ocgis_lh(msg,logger,alias=alias,ugid=ugid)
                    continue
                else:
                    if ed.origin == 'time':
                        msg = 'empty temporal subset operation'
                    else:
                        msg = 'empty geometric operation'
                    ocgis_lh(msg,logger,exc=ExtentError(msg),alias=alias,ugid=ugid)
        ods.spatial._ugid = ugid
        coll.variables.update({request_dataset.alias:ods})

    ## if there are calculations, do those now and return a new type of collection
    if so.cengine is not None:
        ocgis_lh('performing computations',logger,alias=alias,ugid=ugid)
        coll = so.cengine.execute(coll,file_only=so.ops.file_only)
    
    ## conversion of groups.
    if so.ops.output_grouping is not None:
        raise(NotImplementedError)
    else:
        ocgis_lh('subset returning',logger,level=logging.INFO)
        return(coll)
Пример #10
0
 def unwrap_geoms(self,axis=0.0):
     axis = float(axis)
     w = Wrapper(axis=axis)
     geom = self.geom
     for idx in range(geom.shape[0]):
         geom[idx] = w.unwrap(geom[idx])
Пример #11
0
def get_collection((so, geom, logger)):
    '''
    :type so: SubsetOperation
    :type geom: None, GeometryDataset, ShpDataset
    :rtype: AbstractCollection
    '''

    ## initialize the collection object to store the subsetted data.
    coll = RawCollection(ugeom=geom, ops=so.ops)
    ## perform the operations on each request dataset
    ocgis_lh('{0} request dataset(s) to process'.format(len(so.ops.dataset)),
             logger)
    ## reference the geometry ugid
    ugid = None if geom is None else geom.spatial.uid[0]
    for request_dataset in so.ops.dataset:
        ## reference the request dataset alias
        alias = request_dataset.alias
        ocgis_lh('processing',
                 logger,
                 level=logging.INFO,
                 alias=alias,
                 ugid=ugid)
        ## copy the geometry
        copy_geom = deepcopy(geom)
        ## reference the dataset object
        ods = request_dataset.ds
        ## return a slice or do the other operations
        if so.ops.slice is not None:
            ods = ods.__getitem__(so.ops.slice)
        ## other subsetting operations
        else:
            ## if a geometry is passed and the target dataset is 360 longitude,
            ## unwrap the passed geometry to match the spatial domain of the target
            ## dataset.
            if copy_geom is None:
                igeom = None
            else:
                ## check projections adjusting projection the selection geometry
                ## if necessary
                if type(ods.spatial.projection) != type(
                        copy_geom.spatial.projection):
                    msg = 'projecting selection geometry to match input projection: {0} to {1}'
                    msg = msg.format(
                        copy_geom.spatial.projection.__class__.__name__,
                        ods.spatial.projection.__class__.__name__)
                    ocgis_lh(msg, logger, alias=alias, ugid=ugid)
                    copy_geom.project(ods.spatial.projection)
                else:
                    ocgis_lh('projections match',
                             logger,
                             alias=alias,
                             ugid=ugid)
                ## unwrap the data if it is geographic and 360
                if type(ods.spatial.projection
                        ) == WGS84 and ods.spatial.is_360:
                    ocgis_lh(
                        'unwrapping selection geometry with axis={0}'.format(
                            ods.spatial.pm),
                        logger,
                        alias=alias,
                        ugid=ugid)
                    w = Wrapper(axis=ods.spatial.pm)
                    copy_geom.spatial.geom[0] = w.unwrap(
                        deepcopy(copy_geom.spatial.geom[0]))
                igeom = copy_geom.spatial.geom[0]
            ## perform the data subset
            try:
                ## pull the temporal subset which may be a range or region. if
                ## it is a snippet operation, set the temporal subset to None
                ## as a slice has already been applied. however, if a calculation
                ## is present leave the temporal subset alone.
                if so.ops.snippet and so.ops.calc is None:
                    temporal = None
                else:
                    temporal = request_dataset.time_range or request_dataset.time_region

                ocgis_lh('executing get_subset', logger, level=logging.DEBUG)
                ods = ods.get_subset(
                    spatial_operation=so.ops.spatial_operation,
                    igeom=igeom,
                    temporal=temporal,
                    level=request_dataset.level_range)

                ## for the case of time range and time region subset, apply the
                ## time region subset following the time range subset.
                if request_dataset.time_range is not None and request_dataset.time_region is not None:
                    ods._temporal = ods.temporal.subset(
                        request_dataset.time_region)

                ## aggregate the geometries and data if requested
                if so.ops.aggregate:
                    ocgis_lh(
                        'aggregating target geometries and area-weighting values',
                        logger,
                        alias=alias,
                        ugid=ugid)
                    ## the new geometry will have the same id as the passed
                    ## geometry. if it does not have one, simple give it a value
                    ## of 1 as it is the only geometry requested for subsetting.
                    try:
                        new_geom_id = copy_geom.spatial.uid[0]
                    except AttributeError:
                        new_geom_id = 1
                    ## do the aggregation in place.
                    clip_geom = None if copy_geom is None else copy_geom.spatial.geom[
                        0]
                    ods.aggregate(new_geom_id=new_geom_id, clip_geom=clip_geom)
                ## wrap the returned data depending on the conditions of the
                ## operations.
                if not env.OPTIMIZE_FOR_CALC:
                    if type(ods.spatial.projection) == WGS84 and \
                       ods.spatial.is_360 and \
                       so.ops.output_format != 'nc' and \
                       so.ops.vector_wrap:
                        ocgis_lh('wrapping output geometries',
                                 logger,
                                 alias=alias,
                                 ugid=ugid)
                        ods.spatial.vector.wrap()
                        ocgis_lh('geometries wrapped',
                                 logger,
                                 alias=alias,
                                 ugid=ugid,
                                 level=logging.DEBUG)
                ## check for all masked values
                if env.OPTIMIZE_FOR_CALC is False and so.ops.file_only is False:
                    if ods.value.mask.all():
                        ## masked data may be okay depending on other opeartional
                        ## conditions.
                        if so.ops.snippet or so.ops.allow_empty:
                            if so.ops.snippet:
                                ocgis_lh(
                                    'all masked data encountered but allowed for snippet',
                                    logger,
                                    alias=alias,
                                    ugid=ugid,
                                    level=logging.WARN)
                            if so.ops.allow_empty:
                                ocgis_lh(
                                    'all masked data encountered but empty returns allowed',
                                    logger,
                                    alias=alias,
                                    ugid=ugid,
                                    level=logging.WARN)
                            pass
                        else:
                            ## if the geometry is also masked, it is an empty spatial
                            ## operation.
                            if ods.spatial.vector.geom.mask.all():
                                raise (EmptyData)
                            else:
                                ocgis_lh(None,
                                         logger,
                                         exc=MaskedDataError(),
                                         alias=alias,
                                         ugid=ugid)
            ## there may be no data returned - this may be real or could be an
            ## error. by default, empty returns are not allowed
            except EmptyData as ed:
                if so.ops.allow_empty:
                    if ed.origin == 'time':
                        msg = 'the time subset returned empty but empty returns are allowed'
                    else:
                        msg = 'the geometric operations returned empty but empty returns are allowed'
                    ocgis_lh(msg, logger, alias=alias, ugid=ugid)
                    continue
                else:
                    if ed.origin == 'time':
                        msg = 'empty temporal subset operation'
                    else:
                        msg = 'empty geometric operation'
                    ocgis_lh(msg,
                             logger,
                             exc=ExtentError(msg),
                             alias=alias,
                             ugid=ugid)
        ods.spatial._ugid = ugid
        coll.variables.update({request_dataset.alias: ods})

    ## if there are calculations, do those now and return a new type of collection
    if so.cengine is not None:
        ocgis_lh('performing computations', logger, alias=alias, ugid=ugid)
        coll = so.cengine.execute(coll, file_only=so.ops.file_only)

    ## conversion of groups.
    if so.ops.output_grouping is not None:
        raise (NotImplementedError)
    else:
        ocgis_lh('subset returning', logger, level=logging.INFO)
        return (coll)