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()
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