예제 #1
0
    def write_ugeom(self, path=None, driver='ESRI Shapefile', fobject=None):
        """
        Write the user geometries to a ``fiona``-supported file format.

        :param str path: Full path of file to write. If ``None``, ``fobject`` is required.
        :param str driver: The ``fiona`` driver to use for writing. Ignored if ``fobject`` is provided.
        :param fobject: An open ``fiona`` file object to write to. If ``path`` is provided and this is not ``None``,
         then ``path`` will be ignored.
        :type fobject: :class:`fiona.collection.Collection`
        """

        if fobject is None and self.crs is None:
            msg = 'A coordinate system is required when writing to Fiona formats.'
            raise ValueError(msg)

        from ocgis.conv.fiona_ import AbstractFionaConverter

        build = True if fobject is None else False
        is_open = False
        needs_casting = False
        try:
            for ugid, geom in self.geoms.iteritems():
                if build:
                    # it is possible to end with a mix of singleton and multi-geometries
                    type_check = set()
                    for check_geom in self.geoms.itervalues():
                        type_check.update([check_geom.geom_type])
                    if len(type_check) > 1:
                        needs_casting = True
                        for xx in type_check:
                            if xx.startswith('Multi'):
                                geometry = xx
                            else:
                                cast_target_key = xx
                    else:
                        geometry = type_check.pop()

                    fiona_properties = OrderedDict()
                    archetype_properties = self.properties[ugid]
                    for name in archetype_properties.dtype.names:
                        fiona_properties[name] = AbstractFionaConverter.get_field_type(
                            type(archetype_properties[name][0]))
                    fiona_schema = {'geometry': geometry, 'properties': fiona_properties}
                    fiona_kwds = {'schema': fiona_schema, 'driver': driver, 'mode': 'w'}
                    if self.crs is not None:
                        fiona_kwds['crs'] = self.crs.value
                    fobject = fiona.open(path, **fiona_kwds)
                    is_open = True
                    build = False
                properties = get_ordered_dicts_from_records_array(self.properties[ugid])[0]
                if needs_casting:
                    if not isinstance(geom, BaseMultipartGeometry):
                        geom = self._multi_cast[cast_target_key]([geom])
                mapped_geom = mapping(geom)
                record = {'geometry': mapped_geom, 'properties': properties}
                fobject.write(record)
        finally:
            if is_open:
                fobject.close()
예제 #2
0
    def get_fiona_dict(field, arch):
        """
        :param field: The field object.
        :type field: :class:`ocgis.Field`
        :param dict arch: An archetype data dictionary.
        :returns: A dictionary with fiona types and conversion mappings.
        :rtype: dict
        """

        arch = arch.copy()
        for k, v in arch.iteritems():
            try:
                arch[k] = v.tolist()
            except AttributeError:
                continue

        from ocgis.conv.fiona_ import AbstractFionaConverter

        ret = {}
        fproperties = OrderedDict()
        fconvert = {}
        for k, v in arch.iteritems():
            ftype = AbstractFionaConverter.get_field_type(type(v))
            fproperties[k] = 'int' if ftype is None else ftype
            if ftype == 'str':
                fconvert[k] = str
        schema = {'geometry': field.spatial.abstraction_geometry.geom_type, 'properties': fproperties}

        try:
            ret['crs'] = field.spatial.crs.value
        except AttributeError:
            if field.spatial.crs is None:
                msg = 'A coordinate system is required when writing to fiona formats.'
                raise ValueError(msg)

        ret['schema'] = schema
        ret['fconvert'] = fconvert
        return ret