def parse(self): ''' The parse method for the landsat instance needs two different sources of metadata. The first source is the usual local file, using this, further information is obtained, and a request to the usgs server is created. The response is then parsed into a new dictionary. ''' metadata = open(self.filepath, 'r') group_dictionary = {} groups = {} stack = [] LOGGER.debug('File: %s will be parsed as Landsat metadata file.', self.filepath) for line in metadata.readlines(): if '=' in line: key, value = line.split('=') if key.lower().strip() == 'group': stack.append(value.strip()) # put_in_dictionary(groups, stack, {}) elif key.lower().strip() == 'end_group': if group_dictionary: put_in_dictionary(groups, stack, group_dictionary) stack.pop() group_dictionary = {} else: group_dictionary[key.strip()] = parse_value(value.strip()) metadata.close() self.metadata = groups LOGGER.debug('File metadata has been parsed.') path = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'WRS_PATH' ]) row = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'WRS_ROW' ]) sensor = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'SENSOR_ID' ]) acquisition_date = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'DATE_ACQUIRED'] ) self.usgs_metadata = {} try: request = _get_usgs_metadata(path, row, sensor, acquisition_date) document = dom.parseString(request.text) stack = [] _xml_to_json(document.documentElement, stack, self.usgs_metadata) LOGGER.debug('USGS metadata has been parsed.') except: LOGGER.error('USGS metadata was not received.')
def parse(self): ''' The parse method for the landsat instance needs two different sources of metadata. The first source is the usual local file, using this, further information is obtained, and a request to the usgs server is created. The response is then parsed into a new dictionary. ''' metadata = open(self.filepath, 'r') group_dictionary = {} groups = {} stack = [] LOGGER.debug('File: %s will be parsed as Landsat metadata file.', self.filepath) for line in metadata.readlines(): if "=" in line: key, value = line.split('=') if key.lower().strip() == 'group': stack.append(value.strip()) # put_in_dictionary(groups, stack, {}) elif key.lower().strip() == 'end_group': if group_dictionary: put_in_dictionary(groups, stack, group_dictionary) stack.pop() group_dictionary = {} else: group_dictionary[key.strip()] = parse_value(value.strip()) metadata.close() self.metadata = groups LOGGER.debug('File metadata has been parsed.') path = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'WRS_PATH' ]) row = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'WRS_ROW' ]) sensor = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'SENSOR_ID' ]) acquisition_date = self.get_attribute([ 'L1_METADATA_FILE', 'PRODUCT_METADATA', 'DATE_ACQUIRED'] ) request = _get_usgs_metadata(path, row, sensor, acquisition_date) document = dom.parseString(request.text) stack = [] self.usgs_metadata = {} _xml_to_json(document.documentElement, stack, self.usgs_metadata) LOGGER.debug('USGS metadata has been parsed.')
def new_options_for_create_raster_from_reference(reference_metadata, new_option, value, options): ''' Convenience method to add options to the dictionary. ''' if not options: options = default_options_for_create_raster_from_reference( reference_metadata) put_in_dictionary(options, new_option, value) return options put_in_dictionary(options, new_option, value)
def parse(self): ''' Spot metadata file is rather complex, instead of parsing the whole file, only a few attributes are looked up and added to the metadata dictionary. In the future it might be desirable to implement a full parser for this sensor. Specifications for the metadata xml file can be found in: http://www.spotimage.fr/dimap/spec/dictionary/Spot_Scene/DIMAP_DOCUMENT.htm ''' document = dom.parse(self.filepath) for attribute in self.metadata_list: values = document.getElementsByTagName(attribute[-1]) if len(values) == 1: put_in_dictionary(self.metadata, attribute, values[0].firstChild.nodeValue) else: put_in_dictionary( self.metadata, attribute, [value.firstChild.nodeValue for value in values] )
def _extract_raster_properties(self): ''' Extract some raster info from the raster image file using gdal functions. ''' self.metadata['properties'] = { 'projection': None, 'geotransform': None, 'geotransform_from_gcps': None, 'data_shape': None, 'footprint': None } put_in_dictionary(self.metadata, PROJECTION, self.data_file.GetProjection()) put_in_dictionary(self.metadata, GEOTRANSFORM, self.data_file.GetGeoTransform()) #DATA_SHAPE equivalence for numpy array.shape is data_shape[2], data_shape[1], data_shape[0] put_in_dictionary( self.metadata, DATA_SHAPE, (self.data_file.RasterXSize, self.data_file.RasterYSize, self.data_file.RasterCount)) put_in_dictionary(self.metadata, FOOTPRINT, self._get_footprint()) put_in_dictionary(self.metadata, GEOTRANSFORM_FROM_GCPS, self.gcps_to_geotransform())
def default_options_for_create_raster_from_reference(reference_metadata): ''' This method will extract the metadata from a given reference file to be used in the creation of a new file. ''' geotransform = _get_attribute(GEOTRANSFORM, reference_metadata) projection = _get_attribute(PROJECTION, reference_metadata) options = { 'features_of_image_for_create': None, 'gdal_create_options': None, 'dataset': None } options['features_of_image_for_create'] = { 'projection': None, 'geotransform': None, 'create_using_geotransform_from_gcps': None, 'raster_stacked': None } put_in_dictionary(options, CREATE_WITH_PROJECTION, projection) put_in_dictionary(options, CREATE_WITH_GEOTRANSFORM, geotransform) put_in_dictionary(options, CREATE_WITH_GEOTRANSFORM_FROM_GCPS, False) put_in_dictionary(options, CREATE_STACKING, False) put_in_dictionary(options, GDAL_CREATE_OPTIONS, []) return options
def parse(self): ''' Spot metadata file is rather complex, instead of parsing the whole file, only a few attributes are looked up and added to the metadata dictionary. In the future it might be desirable to implement a full parser for this sensor. Specifications for the metadata xml file can be found in: http://www.spotimage.fr/dimap/spec/dictionary/Spot_Scene/DIMAP_DOCUMENT.htm ''' self.document = dom.parse(self.filepath) for attribute in self.metadata_list: values = self.document.getElementsByTagName(attribute[-1]) if len(values) == 1: if len(values[0].childNodes) > 1: values = self.get_element_node(values[0].childNodes) put_in_dictionary(self.metadata, attribute, [value for value in values]) else: put_in_dictionary(self.metadata, attribute, values[0].firstChild.nodeValue) else: values = self.persist(attribute[:-1], values) put_in_dictionary( self.metadata, attribute, [value.firstChild.nodeValue for value in values])
def harmonize_images(images):#, projection, shape): ''' Harmonizes a list of images into the minimum common extent. If one of the images is not in the specified projection, it will be ignored. ''' import raster projection = images[0].get_projection() shape = images[0].get_data_shape() if not projection or not shape: LOGGER.error('Projection and shape should not be null.') raise Exception('Projection and shape should not be null.') extents = {} geotransforms = [] projections = [] shapes = [] accepted_images = [] for image in images: #if projection and shape and image and image.get_attribute(raster.PROJECTION) == projection and image.get_attribute(raster.DATA_SHAPE) == shape: if image.get_attribute(raster.PROJECTION) == projection:# and image.get_attribute(raster.DATA_SHAPE) == shape: geotransforms.append(image.get_attribute(raster.GEOTRANSFORM)) projections.append(image.get_attribute(raster.PROJECTION)) shapes.append(image.get_attribute(raster.DATA_SHAPE)) accepted_images.append(image) else: LOGGER.warn('Image not in the specified projection, will be ignored.') LOGGER.warn('Image %s projection: %s' % (image.image_path,image.get_attribute(raster.PROJECTION))) if accepted_images: LOGGER.info('Number of accepted images: %d' % len(accepted_images)) put_in_dictionary(extents, raster.PROJECTION, projection) #put_in_dictionary(extents, DATA_SHAPE, shape)#TODO: Is it necessary the data shape?? geotransforms = numpy.array(geotransforms) projections = numpy.array(projections) shapes = numpy.array(shapes) # Intersect boundary coordinates # Get upper left coordinates ul_x = max(geotransforms[:, 0]) ul_y = min(geotransforms[:, 3]) # Calculate lower right coordinates lr_x = min(geotransforms[:, 0] + shapes[:, 0] * geotransforms[:, 1]) lr_y = max(geotransforms[:, 3] + shapes[:, 1] * geotransforms[:, 5]) # Calculate range in x and y dimension in pixels x_range = (lr_x - ul_x) / geotransforms[0, 1] y_range = (lr_y - ul_y) / geotransforms[0, 5] # Calculate offset values for each image x_offset = (ul_x - geotransforms[:, 0]) / geotransforms[:, 1] y_offset = (ul_y - geotransforms[:, 3]) / geotransforms[:, 5] # Calculate unique geo transformation geotransform = (ul_x, geotransforms[0, 1], 0.0, ul_y, 0.0, geotransforms[0, 5]) put_in_dictionary(extents, raster.GEOTRANSFORM, geotransform) put_in_dictionary(extents, XRANGE, x_range) put_in_dictionary(extents, YRANGE, y_range) put_in_dictionary(extents, XOFFSET, x_offset) put_in_dictionary(extents, YOFFSET, y_offset) return extents
def harmonize_images(images):#, projection, shape): ''' Harmonizes a list of images into the minimum common extent. If one of the images is not in the specified projection, it will be ignored. ''' import raster projection = images[0].get_attribute(raster.PROJECTION) shape = images[0].get_attribute(raster.DATA_SHAPE) if not projection or not shape: LOGGER.error('Projection and shape should not be null.') raise Exception('Projection and shape should not be null.') extents = {} geotransforms = [] projections = [] shapes = [] accepted_images = [] for image in images: #if projection and shape and image and image.get_attribute(raster.PROJECTION) == projection and image.get_attribute(raster.DATA_SHAPE) == shape: if image.get_attribute(raster.PROJECTION) == projection:# and image.get_attribute(raster.DATA_SHAPE) == shape: geotransforms.append(image.get_attribute(raster.GEOTRANSFORM)) projections.append(image.get_attribute(raster.PROJECTION)) shapes.append(image.get_attribute(raster.DATA_SHAPE)) accepted_images.append(image) else: LOGGER.warn('Image not in the specified projection, will be ignored.') if accepted_images: LOGGER.info('Number of accepted images: %d' % len(accepted_images)) put_in_dictionary(extents, raster.PROJECTION, projection) #put_in_dictionary(extents, DATA_SHAPE, shape)#TODO: Is it necessary the data shape?? geotransforms = numpy.array(geotransforms) projections = numpy.array(projections) shapes = numpy.array(shapes) # Intersect boundary coordinates # Get upper left coordinates ul_x = max(geotransforms[:, 0]) ul_y = min(geotransforms[:, 3]) # Calculate lower right coordinates lr_x = min(geotransforms[:, 0] + shapes[:, 0] * geotransforms[:, 1]) lr_y = max(geotransforms[:, 3] + shapes[:, 1] * geotransforms[:, 5]) # Calculate range in x and y dimension in pixels x_range = (lr_x - ul_x) / geotransforms[0, 1] y_range = (lr_y - ul_y) / geotransforms[0, 5] # Calculate offset values for each image x_offset = (ul_x - geotransforms[:, 0]) / geotransforms[:, 1] y_offset = (ul_y - geotransforms[:, 3]) / geotransforms[:, 5] # Calculate unique geo transformation geotransform = (ul_x, geotransforms[0, 1], 0.0, ul_y, 0.0, geotransforms[0, 5]) put_in_dictionary(extents, raster.GEOTRANSFORM, geotransform) put_in_dictionary(extents, XRANGE, x_range) put_in_dictionary(extents, YRANGE, y_range) put_in_dictionary(extents, XOFFSET, x_offset) put_in_dictionary(extents, YOFFSET, y_offset) return extents