Пример #1
0
    def test_write():
        """Test writing JimVect objects."""
        jimv = pj.JimVect(vector)

        output = os.path.join('/tmp',
                              ''.join(random.sample(string.ascii_letters, 5)))
        jimv.io.write(output)

        assert os.path.isfile(output), \
            'Error in io.write(filename) (file does not exist after writing)'
        os.remove(output)

        output2 = os.path.join('/tmp',
                               ''.join(random.sample(string.ascii_letters, 5)))

        jimv_2 = pj.geometry.convexHull(jimv, output=output2)

        jimv.io.close()
        jimv_2.io.close()

        jimv_3 = pj.JimVect(output2)
        jimv_3.io.close()
        os.remove(output2)

        assert jimv_3.properties.getFeatureCount() == 1, \
            'Error in io.write() (changes not written to the original file)'
Пример #2
0
    def test_dict_conversions():
        """Test JimVect.np() method."""
        vect = pj.JimVect(vector)
        dict = vect.dict()

        assert 'nuts3id' in dict.keys(), \
            'Error in dict method, no nuts3id in keys'
        assert len(dict.keys()) == len(dict.values()), \
            'Error in dict method, length of keys != length of values'
        assert 'IT' in dict['n0cd'], \
            'Error in dict method, IT not in values of n0cd'
Пример #3
0
    def test_numpy_conversions():
        """Test JimVect.np() method."""
        vect = pj.JimVect(vector)
        anp0 = vect.np(ln=0)  # layer 0
        anp1 = vect.np(ln=1)  # layer 1

        assert (anp0 == pj.jimvect2np(
            vect, ln=0)).all(), 'np function not equal to method '

        assert isinstance(anp0, np.ndarray), \
            'Error in numpy conversion layer 0: not an instance of ndarray'
        assert isinstance(anp1, np.ndarray), \
            'Error in numpy conversion layer 1: not an instance of ndarray'
        assert anp0.shape[0] == 1, \
            'Error in numpy conversion: first dimension (number of features)'
        assert anp0.shape[1] == 12, \
            'Error in numpy conversion: second dimension (number of fields)'
        assert np.append(anp0, anp1, axis=0).shape[0] == 2, \
            'Error in geometry.merge() ' \
            '(append first dimension)'
        assert np.append(anp0, anp1, axis=0).shape[1] == 12, \
            'Error in geometry.merge() ' \
            '(append second dimension)'
Пример #4
0
    def test_jimvect_creations():
        """Test creating of JimVect objects."""
        out_path = pj._get_random_path()

        # Test empty vector

        vect = pj.JimVect()

        assert vect.properties.isEmpty(), \
            'Error in creating an empty JimVect object'
        assert vect.properties.getLayerCount() == 0, \
            'Error in creating an empty JimVect object'

        # Test vector with filepath defined

        vect = pj.JimVect(vector)

        assert not vect.properties.isEmpty(), \
            'Error in creating a JimVect object with specified path'
        assert vect.properties.getLayerCount() == 2, \
            'Error in creating a JimVect object with specified path'

        # Test vector with filepath and kwargs

        vect = pj.JimVect(vector, ln='milano')

        assert not vect.properties.isEmpty(), \
            'Error in creating a JimVect object with specified path and kwargs'
        assert vect.properties.getLayerCount() == 1, \
            'Error in creating a JimVect object with specified path and kwargs'

        # Test with parent vector

        vect = pj.JimVect(vect, output=out_path)

        assert os.path.isfile(out_path), \
            'Error in creating JimVect object based on another JimVect ' \
            '(output does not exist)'
        assert not vect.properties.isEmpty(), \
            'Error in creating JimVect object based on another JimVect ' \
            '(JimVect empty)'
        assert vect.properties.getLayerCount() == 1, \
            'Error in creating JimVect object based on another JimVect ' \
            '(wrong number of layers)'

        # Copy constructor with new field

        # add field with unique key
        vect = pj.JimVect(v1)
        vect = pj.JimVect(vect, output=out_path, newfield='fid')
        assert 'fid' in vect.properties.getFieldNames(), \
            'Error in creating JimVect object based on another JimVect' \
            'with new fid (fid not found)'

        assert np.amax(vect.np(field=['fid'])) + 1 == \
            vect.properties.getFeatureCount(), \
            'Error in creating JimVect object based on another JimVect' \
            'with new fid (value)'

        vect.io.close()
        os.remove(out_path)

        # add field with fixed numeric label of default integer type
        vect = pj.JimVect(v1)
        vect = pj.JimVect(vect, output=out_path, newfield='label', newvalue=10)
        assert 'label' in vect.properties.getFieldNames(), \
            'Error in creating JimVect object based on another JimVect' \
            'with new field (label not found)'

        assert np.amax(vect.np(field=['label'])) == 10, \
            'Error in creating JimVect object based on another JimVect' \
            'with new field (value=10)'

        vect.io.close()
        os.remove(out_path)

        # add field with fixed numeric label of Real type
        vect = pj.JimVect(v1)
        vect = pj.JimVect(vect,
                          output=out_path,
                          newfield='label',
                          newtype='Real',
                          newvalue=9.9,
                          verbose=2)
        assert np.amax(vect.np(field=['label'])) == 9.9, \
            'Error in creating JimVect object based on another JimVect' \
            'with new field (value=9.9)'

        vect.io.close()
        os.remove(out_path)

        # Copy constructor with new field with two layers

        # add field with unique key
        vect = pj.JimVect(vector)
        vect = pj.JimVect(vect, output=out_path, newfield='fid')

        assert 'fid' in vect.properties.getFieldNames(), \
            'Error in creating JimVect object based on another JimVect' \
            'with new fid (fid not found)'
        max_value = 0
        for layer in range(0, vect.properties.getLayerCount()):
            max_value += np.amax(vect.np(field=['fid'])) + 1
        assert max_value == vect.properties.getFeatureCount(), \
            'Error in creating JimVect object based on another JimVect' \
            'with new fid (value)'

        vect.io.close()
        os.remove(out_path)

        # Test with JSON string

        jsonstring = \
            '{"polygons": ' \
                '{"type": "FeatureCollection", ' \
                '"crs": ' \
                    '{"type": "name", ' \
                    '"properties": ' \
                    '{"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}, ' \
                '"features": ' \
                    '[{"type": "Feature", ' \
                    '"properties": {"label": 1}, ' \
                    '"geometry": ' \
                        '{"type": "Polygon", ' \
                        '"coordinates": ' \
                            '[[[ 16.296883885037882, 48.07125730037879 ], ' \
                            '[ 16.29418254261364, 47.787616345833342 ], ' \
                            '[ 16.518393963825762, 47.814629770075761 ], ' \
                            '[ 16.413041609280306, 48.04424387613637 ], ' \
                            '[ 16.296883885037882, 48.07125730037879 ]]' \
            ']}}]}}'

        vect = pj.JimVect(jsonstring)

        assert not vect.properties.isEmpty(), \
            'Error in creating JimVect object based on json string' \
            '(JimVect empty)'
        assert vect.properties.getLayerCount() == 1, \
            'Error in creating JimVect object based on json string' \
            '(wrong number of layers)'
        assert vect.properties.getFeatureCount() == 1, \
            'Error in creating JimVect object based on json string' \
            '(wrong number of features)'

        vect = pj.JimVect(output=vector)

        assert not vect.properties.isEmpty(), \
            'Error in creating JimVect object based on kwarg output=... ' \
            '(JimVect empty)'
        assert vect.properties.getLayerCount() == 2, \
            'Error in creating JimVect object based on kwarg output=... ' \
            '(wrong number of layers)'

        # Test JimVect creation based on WKT

        wkt_string = 'POLYGON ((23.314208 37.768469, 24.039306 37.768469, ' \
                     '24.039306 38.214372, 23.314208 38.214372, ' \
                     '23.314208 37.768469))'

        vect = pj.JimVect(wkt=wkt_string)

        out_path = pj._get_random_path()
        wkt_jimvect = pj.JimVect(vect, output=out_path, oformat='GeoJSON')

        assert wkt_jimvect.properties.getFeatureCount() == 1, \
            'Error in creating JimVect object based on kwarg wkt=... '

        os.remove(out_path)

        # Test wrong JimVects catches

        try:
            _ = pj.JimVect(vect)
            raised = False
        except pj.exceptions.JimVectIllegalArgumentError:
            raised = True

        assert raised, \
            'Error in catching wrong parameters for JimVect creation ' \
            '(no output, but initial vector)'

        try:
            _ = pj.JimVect(vect, ln='milano')
            raised = False
        except pj.exceptions.JimVectIllegalArgumentError:
            raised = True

        assert raised, \
            'Error in catching wrong parameters for JimVect creation ' \
            '(no output, but initial vector and kwargs)'

        try:
            _ = pj.JimVect(ulx=0, uly=1, lrx=1, lry=0, output=out_path)
            raised = False
        except pj.exceptions.JimVectIllegalArgumentError:
            raised = True

        assert raised, \
            'Error in catching non-existing output without defining ' \
            'a JimVect template'
Пример #5
0
    def test_isEqual(self):
        """Test JimVect isEqual method."""
        assert self.jimv.properties.isEqual(self.jimv) is True, \
            'Error in properties.isEqual(): not equal to itself (2 layers)'
        assert pj.properties.isEqual(self.jimv, self.jimv) is True, \
            'Error in function properties.isEqual(): not equal to itself'

        jimv1 = pj.JimVect(vector, ln='milano')
        jimv2 = pj.JimVect(vector, ln='lodi')

        assert self.jimv.properties.isEqual(jimv1) is False, \
            'Error in properties.isEqual(): \
            2 layer vector should be different from 1 layer vector'
        assert pj.properties.isEqual(self.jimv, jimv1) is False, \
            'Error in function properties.isEqual(): \
            2 layer vector should be different from 1 layer vector'
        assert jimv1.properties.isEqual(jimv1) is True, \
            'Error in properties.isEqual(): not equal to itself (1 layer)'
        assert pj.properties.isEqual(jimv1, jimv1) is True, \
            'Error in function properties.isEqual(): \
            not equal to itself (1 layer)'
        assert jimv1.properties.isEqual(jimv2) is False, \
            'Error in properties.isEqual(): \
            layer milano should be different from lodi'
        assert pj.properties.isEqual(jimv1, jimv2) is False, \
            'Error in function properties.isEqual(): \
            layer milano should be different from lodi'

        jimv1_double = pj.geometry.append(jimv1, jimv1,
                                          output=pj._get_random_path())

        assert not jimv1_double.properties.isEqual(jimv1), \
            'Error in properties.isEqual() method ' \
            '(JimVects with different number of features considered equal)'
        assert not pj.properties.isEqual(jimv1_double, jimv1), \
            'Error in properties.isEqual() function ' \
            '(JimVects with different number of features considered equal)'

        # Test with the argument Jim empty

        jimv_empty = pj.JimVect()

        equal = jimv1.properties.isEqual(jimv_empty)

        assert equal is False, \
            'Error in properties.isEqual(JimVect) method ' \
            '(did not return False when the argument JimVect was emmpty)'

        equal = pj.properties.isEqual(jimv1, jimv_empty)

        assert equal is False, \
            'Error in properties.isEqual(JimVet, JimVect) function ' \
            '(did not return False when the argument JimVect was emmpty)'

        # Test wrong calls

        try:
            _ = jimv_empty.properties.isEqual(jimv1)
            raised = False
        except pj.exceptions.JimVectEmptyError:
            raised = True

        assert raised, \
            'Error in properties.isEqual() method ' \
            '(ValueError not raised when called on an empty JimVect)'

        try:
            _ = pj.properties.isEqual(jimv_empty, jimv1)
            raised = False
        except pj.exceptions.JimVectEmptyError:
            raised = True

        assert raised, \
            'Error in properties.isEqual() function ' \
            '(ValueError not raised when called on an empty JimVect)'
Пример #6
0
class BadPropsVects(unittest.TestCase):
    """Test JimVect funcs and methods for getting and setting properties."""

    jimv = pj.JimVect(vector)

    def test_isEqual(self):
        """Test JimVect isEqual method."""
        assert self.jimv.properties.isEqual(self.jimv) is True, \
            'Error in properties.isEqual(): not equal to itself (2 layers)'
        assert pj.properties.isEqual(self.jimv, self.jimv) is True, \
            'Error in function properties.isEqual(): not equal to itself'

        jimv1 = pj.JimVect(vector, ln='milano')
        jimv2 = pj.JimVect(vector, ln='lodi')

        assert self.jimv.properties.isEqual(jimv1) is False, \
            'Error in properties.isEqual(): \
            2 layer vector should be different from 1 layer vector'
        assert pj.properties.isEqual(self.jimv, jimv1) is False, \
            'Error in function properties.isEqual(): \
            2 layer vector should be different from 1 layer vector'
        assert jimv1.properties.isEqual(jimv1) is True, \
            'Error in properties.isEqual(): not equal to itself (1 layer)'
        assert pj.properties.isEqual(jimv1, jimv1) is True, \
            'Error in function properties.isEqual(): \
            not equal to itself (1 layer)'
        assert jimv1.properties.isEqual(jimv2) is False, \
            'Error in properties.isEqual(): \
            layer milano should be different from lodi'
        assert pj.properties.isEqual(jimv1, jimv2) is False, \
            'Error in function properties.isEqual(): \
            layer milano should be different from lodi'

        jimv1_double = pj.geometry.append(jimv1, jimv1,
                                          output=pj._get_random_path())

        assert not jimv1_double.properties.isEqual(jimv1), \
            'Error in properties.isEqual() method ' \
            '(JimVects with different number of features considered equal)'
        assert not pj.properties.isEqual(jimv1_double, jimv1), \
            'Error in properties.isEqual() function ' \
            '(JimVects with different number of features considered equal)'

        # Test with the argument Jim empty

        jimv_empty = pj.JimVect()

        equal = jimv1.properties.isEqual(jimv_empty)

        assert equal is False, \
            'Error in properties.isEqual(JimVect) method ' \
            '(did not return False when the argument JimVect was emmpty)'

        equal = pj.properties.isEqual(jimv1, jimv_empty)

        assert equal is False, \
            'Error in properties.isEqual(JimVet, JimVect) function ' \
            '(did not return False when the argument JimVect was emmpty)'

        # Test wrong calls

        try:
            _ = jimv_empty.properties.isEqual(jimv1)
            raised = False
        except pj.exceptions.JimVectEmptyError:
            raised = True

        assert raised, \
            'Error in properties.isEqual() method ' \
            '(ValueError not raised when called on an empty JimVect)'

        try:
            _ = pj.properties.isEqual(jimv_empty, jimv1)
            raised = False
        except pj.exceptions.JimVectEmptyError:
            raised = True

        assert raised, \
            'Error in properties.isEqual() function ' \
            '(ValueError not raised when called on an empty JimVect)'

    def test_geospatial_infos(self):
        """Test JimVect methods connected to geospatial informations."""
        bbox = self.jimv.properties.getBBox()

        assert self.jimv.properties.getUlx() == bbox[0], \
            'Error in properties.getBBox() or properties.getUlx() for JimVects'
        assert self.jimv.properties.getUly() == bbox[1], \
            'Error in properties.getBBox() or properties.getUly() for JimVects'
        assert self.jimv.properties.getLrx() == bbox[2], \
            'Error in properties.getBBox() or properties.getLrx() for JimVects'
        assert self.jimv.properties.getLry() == bbox[3], \
            'Error in properties.getBBox() or properties.getLry() for JimVects'

        """Test JimVect properties.getBBox() method at target projection."""
        assert bbox == self.jimv.properties.getBBox(
            t_srs=self.jimv.properties.getProjection()), \
            'Error in properties getBBox() with projection '

        """Test JimVect properties.getBBox() method at target projection."""
        bbox = self.jimv.properties.getBBox(t_srs = 4326)
        assert bbox[0] > 8.70 and bbox[0] < 8.71, \
            "Error in properties.getBBox() with projection [0]: {}".format(bbox[0])
        assert bbox[1] > 45.73 and bbox[1] < 45.74, \
            "Error in properties.getBBox() with projection [1]: {}".format(bbox[1])
        assert bbox[2] > 9.89 and bbox[2] < 9.90, \
            "Error in properties.getBBox() with projection [2]: {}".format(bbox[2])
        assert bbox[3] > 45.05 and bbox[3] < 45.06, \
            "Error in properties.getBBox() with projection [3]: {}".format(bbox[3])

        # assert bbox[0] > 7.70 and bbox[0] < 7.71, \
        # assert bbox[1] > 46.04 and bbox[1] < 46.05, \
        # assert bbox[2] > 7.77 and bbox[2] < 7.78, \
        # assert bbox[3] > 46.00 and bbox[3] < 46.01, \
        projection = self.jimv.properties.getProjection()

        assert (projection.split('GEOGCS["')[1][:6] == 'ETRS89' or
                projection.split('GEOGCS["')[1][:13] == 'GCS_ETRS_1989'), \
                'Error in properties.getProjection() for JimVects (wrong GEOGCS)'

    def test_feature_layer_counts(self):
        """Test JimVect methods getLayerCount() and getFeatureType()."""
        assert self.jimv.properties.getLayerCount() == 2, \
            'Error in properties.getLayerCount() for JimVects'

        assert self.jimv.properties.getFeatureCount() == \
               self.jimv.properties.getFeatureCount(0) + \
               self.jimv.properties.getFeatureCount(1), \
            'Error in properties.getFeatureCount() for JimVects'
Пример #7
0
def load_collection(agraph,
                    nodeid,
                    jim,
                    tileindex=None,
                    tiletotal=None,
                    virtual=False):
    verbose = True
    node = agraph[nodeid]
    # collectionId = node.content['arguments']['id'].split('.')
    collectionId = node.content['arguments']['id']
    if verbose:
        print("load_collection")
    # coll=Collection(collectionId[0])
    coll = Collection(collectionId)
    # if len(collectionId) > 1:
    #     coll.filterOn('productType',collectionId[1])
    properties = {}

    spatiallyFiltered = False
    mgrs = None
    properties = node.content['arguments'].get('properties')
    if properties is not None:
        for property in properties:
            if node.content['arguments']['properties'][property].get(
                    'from_node') is not None:
                property_node = agraph[node.content['arguments']['properties']
                                       [property]['from_node']]
            else:
                property_node = None
            if 'cloud_cover' in property:
                minCloud = property_node.content['arguments'].get('min', 0)
                maxCloud = property_node.content['arguments'].get('max', 100)
                coll.filterOn('cloudCoverPercentage', '<' + str(maxCloud))
                coll.filterOn('cloudCoverPercentage', '>' + str(minCloud))
            if 'mgrs' in property:
                mgrs = property_node.content['arguments'].get('y')
                if mgrs is not None:
                    if property_node.content['process_id'] == 'eq':
                        coll.filterOn('mgrs', str(mgrs))
                    elif property_node.content['process_id'] == 'neq':
                        coll.filterOn('mgrs', '<>' + str(mgrs))
                    else:
                        raise AttributeError(
                            "Error: process_id {} not supported for property {}"
                            .format(property_node.content['process_id'],
                                    property))
                spatiallyFiltered = True
            if 'platform' in property:
                platform = property_node.content['arguments'].get('y')
                if platform is not None:
                    if property_node.content['process_id'] == 'eq':
                        coll.filterOn('platform', '=' + str(platform))
                    elif property_node.content['process_id'] == 'neq':
                        coll.filterOn('platform', '<>' + str(platform))
                    else:
                        raise AttributeError(
                            "Error: process_id {} not supported for property {}"
                            .format(property_node.content['process_id'],
                                    property))
            if property_node is not None:
                jim[property_node.id] = True

    #filter on bounding box (defined in lat/lon)
    west = None
    east = None
    north = None
    south = None
    spatial_extent = node.content['arguments'].get('spatial_extent')

    features = None
    crs = None
    if spatial_extent is not None:
        west = spatial_extent.get('west')
        east = spatial_extent.get('east')
        north = spatial_extent.get('north')
        south = spatial_extent.get('south')
        crs = spatial_extent.get('crs')
        geometries = node.content['arguments'].get('spatial_extent').get(
            'geometries')
        if geometries is not None:
            features = node.content['arguments'].get('spatial_extent')
            print('features {}'.format(features))
            features = json.dumps(features)
            print('features {}'.format(features))
            v1 = pj.JimVect(features)
            print(v1.properties.getFeatureCount())
            bbox = v1.properties.getBBox()
            if west is not None:
                print(
                    "Warning: overwriting west boundary {west} with bbox {bbox} from geometries"
                    .format(west=west, bbox=bbox[0]))
            west = bbox[0]
            if north is not None:
                print(
                    "Warning: overwriting north boundary {north} with bbox {bbox} from geometries"
                    .format(north=north, bbox=bbox[1]))
            north = bbox[1]
            if east is not None:
                print(
                    "Warning: overwriting east boundary {east} with bbox {bbox} from geometries"
                    .format(east=east, bbox=bbox[2]))
            east = bbox[2]
            if south is not None:
                print(
                    "Warning: overwriting south boundary {south} with bbox {bbox} from geometries"
                    .format(south=south, bbox=bbox[3]))
            south = bbox[3]

    if mgrs is not None and tileindex is not None and tiletotal is not None:
        attribute = "Name=" + '\'' + str(mgrs) + '\''
        print("attribute: {}".format(attribute))
        fn = '/eos/jeodpp/data/base/GeographicalGridSystems/GLOBAL/MGRS/S2/LATEST/Data/Shapefile/S2grid2D.shp'
        v1 = pj.JimVect(pj.JimVect(fn, attributeFilter=attribute),
                        output='/vsimem/v1',
                        co=['OVERWRITE=YES'])
        v1.io.write()
        bbox = v1.properties.getBBox()
        west = bbox[0]
        north = bbox[1]
        east = bbox[2]
        south = bbox[3]

    if west is not None and east is not None and north is not None and south is not None:
        coll.filter_bbox(west=west,
                         east=east,
                         north=north,
                         south=south,
                         regions=features,
                         crs=crs,
                         tileindex=tileindex,
                         tiletotal=tiletotal)
        spatiallyFiltered = True
    if not spatiallyFiltered:
        raise AttributeError(
            "Error: {} bounding box or mgrs must be defined to filter collection"
            .format(type(jim[node.id])))

    #filter on dates:

    print("temporal_extent: {}".format(
        node.content['arguments']['temporal_extent']))
    daterange = [
        dateutil.parser.parse(d)
        for d in node.content['arguments']['temporal_extent']
    ]
    print("daterange: {}".format(daterange))
    # self.filter_daterange(dateString)
    #daterange = [datetime.strptime(d, '%Y-%m-%d') for d in node.content['arguments']['temporal_extent']]
    dateString = [
        single_date.strftime('%Y-%m-%dT%H:%M:%S') for single_date in daterange
    ]
    print('dateString: {}'.format(dateString))
    coll.filter_daterange(dateString)
    #make sure the following filters are called after filtering dates and bounding box)
    #filter spectral bands
    bands = None
    if 'bands' in node.content['arguments']:
        bands = node.content['arguments']['bands']
        if bands is not None:
            print("filter bands: {}".format(
                node.content['arguments']['bands']))
            coll.filter_bands(node.content['arguments']['bands'])
    #define spatial and temporal resolution to load collection as data cube.
    resolution = {}
    #todo: define spatial resolution
    dx = 10
    dy = 10
    resolution.update({'spatial': [dx, dy]})
    resolution.update({'temporal': timedelta(1)})
    #todo: define projection t_srs?
    #todo: define appropriate output data type?
    print("daterange is {}".format(daterange))
    # jim[node.id]=coll.load_collection(spatial_extent,temporal_extent=daterange,bands=bands,resolution=resolution,t_srs=3857,otype='GDT_Float32',rule='overwrite', nodata=0)
    #todo: support empty projection t_srs to keep original?
    #test
    #jim[node.id]=coll.load_collection(spatial_extent,temporal_extent=daterange,bands=bands, properties=properties,resolution=resolution,t_srs=32632,otype='GDT_Float32',rule='overwrite', nodata=0)
    if virtual:
        jim[node.id] = coll
    else:
        jim[node.id] = coll.load_collection(t_srs=crs,
                                            resolution=resolution,
                                            bands=bands,
                                            otype='GDT_Float32',
                                            rule='overwrite',
                                            nodata=0)
    # jim[node.id]=coll.load_collection(spatial_extent,temporal_extent=daterange,bands=bands, properties=properties,resolution=resolution,t_srs=None,otype='GDT_Float32',rule='overwrite', nodata=0)
    #test
    if verbose:
        print("return Jim {}".format(jim[node.id]))
        print("temporal dimension: {}".format(
            jim[node.id].getDimension('temporal')))
        print("band dimension: {}".format(jim[node.id].getDimension('band')))
    return jim[node.id]
Пример #8
0
def aggregate_spatial(agraph, nodeid, jim):
    verbose = True
    node = agraph[nodeid]
    if verbose:
        print("aggregating spatial")
    if jim[node.content['arguments']['data']['from_node']] is None:
        return None
    reducer_node = agraph[node.content['arguments']['reducer']['from_node']]
    if verbose:
        print("node is: {}".format(node.content))
        print("reducer node is: {}".format(reducer_node))
    # if jim[node.content['arguments']['reducer']['from_node']] is None:
    #test
    if jim[reducer_node.id] is None:
        rule = reducer_node.content['process_id']
        if verbose:
            print("reducer graph is: {}".format(reducer_node.content))
            print("rule: {}".format(rule))
        if 'geometries' in node.content['arguments']:
            geometries = node.content['arguments']['geometries']
            geometryType = geometries['type']
            if geometryType == 'FeatureCollection':
                print(json.dumps(geometries))
                print(geometries)
                invect = pj.JimVect(json.dumps(geometries), verbose=1)
                # print(invect.np().shape)
                # print(invect.np())
                # ds=gdal.OpenEx(geojson)
                # lyr = ds.GetLayer()
            elif geometryType == 'file':
                invect = pj.JimVect(geometries['path'])
                # print(invect.np().shape)
                # print(invect.np())
        elif 'file' in node.content['arguments']:
            raise ValueError("Error: not implemented yet")
            #todo: handle vector files...
        else:
            raise ValueError(
                "Error: only polygons supported in geojson format")
        srcnodata = 0
        buffer = None
        if 'context' in node.content['arguments']:
            buffer = node.content['arguments']['context'].get('buffer')
            srcnodata = node.content['arguments']['context'].get(
                'srcnodata', 0)
        # for points in node.content['arguments']['polygons']['coordinates']:
        #     wktstring=node.content['arguments']['polygons']['type']
        #     wktstring+=' (('
        #     wktstring+=",".join(" ".join(str(coordinate) for coordinate in point) for point in points)
        #     wktstring+='))'
        # invect=pj.JimVect(wkt=wktstring,output=os.path.join('/vsimem/invect.sqlite'))
        #todo: support multiple invect
        outvect = os.path.join('/vsimem', node.id + '.sqlite')

        if isinstance(jim[node.content['arguments']['data']['from_node']],
                      pj.Jim):
            print("we have a Jim")
            times = jim[node.content['arguments']['data']
                        ['from_node']].dimension['temporal']
            planename = [t.strftime('%Y%m%d') for t in times]
            if not planename:
                planename = [
                    't' + str(t) for t in range(
                        0, jim[node.content['arguments']['data']
                               ['from_node']].properties.nrOfPlane())
                ]

            bandname = jim[node.content['arguments']['data']
                           ['from_node']].dimension['band']
            if not bandname:
                bandname = [
                    'b' + str(b) for b in range(
                        0, jim[node.content['arguments']['data']
                               ['from_node']].properties.nrOfBand())
                ]
            if buffer is not None:
                jim[reducer_node.id] = pj.geometry.extract(
                    invect,
                    jim[node.content['arguments']['data']['from_node']],
                    outvect,
                    rule,
                    bandname=bandname,
                    planename=planename,
                    co=['OVERWRITE=TRUE'],
                    srcnodata=srcnodata,
                    buffer=buffer)
            else:
                jim[reducer_node.id] = pj.geometry.extract(
                    invect,
                    jim[node.content['arguments']['data']['from_node']],
                    outvect,
                    rule,
                    bandname=bandname,
                    planename=planename,
                    co=['OVERWRITE=TRUE'],
                    srcnodata=srcnodata)
        elif isinstance(jim[node.content['arguments']['data']['from_node']],
                        Collection):
            print("rule is: {}".format(rule))
            jim[reducer_node.id] = jim[node.content['arguments']['data']
                                       ['from_node']].aggregate_spatial(
                                           invect, rule, outvect)
        elif isinstance(jim[reducer_node.id], pj.JimVect):
            raise TypeError(
                "Error: aggretate_spatial not implemented for JimVect")

        if jim[reducer_node.id] is not None:
            jim[node.id] = jim[reducer_node.id]
            print("output vector has {} features".format(
                jim[node.id].properties.getFeatureCount()))
            print("output vector has fields: {}".format(
                jim[node.id].properties.getFieldNames()))
            # print('extracted vector: {}'.format(jim[node.id].np()))
            jim[node.id].io.write()
            return jim[node.id]
        else:
            raise ValueError("Error: could not aggregate polygon")
    else:
        jim[node.id] = jim[reducer_node.id]
        return jim[node.id]