def write(self): ocgis_lh('starting write method',self._log,logging.DEBUG) unique_geometry_store = [] # indicates if user geometries should be written to file write_ugeom = False try: build = True for coll in iter(self.colls): if build: # write the user geometries if configured and there is one present on the incoming collection. if self._add_ugeom and coll.geoms.values()[0] is not None: write_ugeom = True f = self._build_(coll) if write_ugeom: ugid_shp_name = self.prefix + '_ugid.shp' ugid_csv_name = self.prefix + '_ugid.csv' if self._add_ugeom_nest: fiona_path = os.path.join(self._get_or_create_shp_folder_(),ugid_shp_name) csv_path = os.path.join(self._get_or_create_shp_folder_(),ugid_csv_name) else: fiona_path = os.path.join(self.outdir,ugid_shp_name) csv_path = os.path.join(self.outdir,ugid_csv_name) if coll.meta is None: # convert the collection properties to fiona properties from fiona_ import FionaConverter fiona_properties = {} for k, v in coll.properties.values()[0].iteritems(): fiona_properties[k] = FionaConverter.get_field_type(type(v)) fiona_schema = {'geometry':'MultiPolygon', 'properties':fiona_properties} fiona_meta = {'schema':fiona_schema,'driver':'ESRI Shapefile'} else: fiona_meta = coll.meta ## always use the CRS from the collection. shapefile metadata ## will always be WGS84, but it may be overloaded in the ## operations. fiona_meta['crs'] = coll.crs.value ## always upper for the properties definition as this happens ## for each record. fiona_meta['schema']['properties'] = {k.upper():v for k,v in fiona_meta['schema']['properties'].iteritems()} ## selection geometries will always come out as MultiPolygon ## regardless if they began as points. points are buffered ## during the subsetting process. fiona_meta['schema']['geometry'] = 'MultiPolygon' fiona_object = fiona.open(fiona_path,'w',**fiona_meta) csv_file = open(csv_path,'w') from ocgis.conv.csv_ import OcgDialect csv_object = DictWriter(csv_file,fiona_meta['schema']['properties'].keys(),dialect=OcgDialect) csv_object.writeheader() build = False self._write_coll_(f,coll) if write_ugeom: ## write the overview geometries to disk r_geom = coll.geoms.values()[0] if isinstance(r_geom,Polygon): r_geom = MultiPolygon([r_geom]) ## see if this geometry is in the unique geometry store should_append = self._get_should_append_to_unique_geometry_store_( unique_geometry_store, r_geom, coll.properties.values()[0]['UGID']) if should_append: unique_geometry_store.append({'geom':r_geom, 'ugid':coll.properties.values()[0]['UGID']}) ## if it is unique write the geometry to the output files to_write = {'geometry':mapping(r_geom), 'properties':{k.upper():v for k,v in coll.properties.values()[0].iteritems()}} fiona_object.write(to_write) ## write the geometry attributes to the corresponding shapefile for row in coll.properties.itervalues(): csv_object.writerow({k.upper():v for k,v in row.iteritems()}) finally: ## errors are masked if the processing failed and file objects, etc. ## were not properly created. if there are UnboundLocalErrors pass ## them through to capture the error that lead to the objects not ## being created. try: try: self._finalize_(f) except UnboundLocalError: pass except Exception as e: ## this the exception we want to log ocgis_lh(exc=e,logger=self._log) finally: if write_ugeom: try: fiona_object.close() except UnboundLocalError: pass try: csv_file.close() except UnboundLocalError: pass ## the metadata and dataset descriptor files may only be written if ## OCGIS operations are present. if self.ops is not None and self.add_auxiliary_files == True: ## added OCGIS metadata output if requested. if self.add_meta: ocgis_lh('adding OCGIS metadata file','conv',logging.DEBUG) lines = MetaConverter(self.ops).write() out_path = os.path.join(self.outdir,self.prefix+'_'+MetaConverter._meta_filename) with open(out_path,'w') as f: f.write(lines) ## add the dataset descriptor file if specified and OCGIS operations ## are present. if self._add_did_file: ocgis_lh('writing dataset description (DID) file','conv',logging.DEBUG) from ocgis.conv.csv_ import OcgDialect headers = ['DID','VARIABLE','ALIAS','URI','STANDARD_NAME','UNITS','LONG_NAME'] out_path = os.path.join(self.outdir,self.prefix+'_did.csv') with open(out_path,'w') as f: writer = csv.writer(f,dialect=OcgDialect) writer.writerow(headers) for rd in self.ops.dataset.itervalues(): for d in rd: row = [rd.did,d['variable'],d['alias'],rd.uri] ref_variable = rd.source_metadata['variables'][d['variable']]['attrs'] row.append(ref_variable.get('standard_name',None)) row.append(ref_variable.get('units',None)) row.append(ref_variable.get('long_name',None)) writer.writerow(row) ## add source metadata if requested if self._add_source_meta: ocgis_lh('writing source metadata file','conv',logging.DEBUG) out_path = os.path.join(self.outdir,self.prefix+'_source_metadata.txt') to_write = [] for rd in self.ops.dataset.itervalues(): ip = Inspect(meta=rd.source_metadata, uri=rd.uri) to_write += ip.get_report_no_variable() with open(out_path,'w') as f: f.writelines('\n'.join(to_write)) ## return the internal path unless overloaded by subclasses. ret = self._get_return_() return(ret)