def read_metadata(xmlbuffer): # Speciel decoders def dec_isoformat(rts): return datetime.strptime(rts, "%Y-%m-%dT%H:%M:%S.%fZ") def dec_orbit_number(rts): return int(rts[:5]) def dec_satellite_name(rts): return rts.replace('-', '') def dec_calibration_unit(rts): _trans = {'radar brightness': 'nrcs'} rts = rts.replace(' ', '-').lower() return rts attributes = { 'product_level': ('generalHeader/itemName', str), 'satellite_name': ('productInfo/missionInfo/mission', dec_satellite_name), 'orbit_number': ('productInfo/missionInfo/absOrbit', dec_orbit_number), 'sensor_type': ('productInfo/acquisitionInfo/sensor', str), 'beam_mode': ('productInfo/acquisitionInfo/imagingMode', str), 'polarisation': ('productInfo/acquisitionInfo/polarisationList/polLayer', str), 'beamid': ('productInfo/acquisitionInfo/elevationBeamConfiguration', str), 'calibrated': ('productInfo/productVariantInfo/radiometricCorrection', str), 'calibration_factor': ('calibration/calibrationConstant/calFactor', float), 'calibration_beamid': ('calibration/calibrationConstant/beamID', str), 'calibration_unit': ('productInfo/imageDataInfo/pixelValueID', dec_calibration_unit), 'image_data_path': ('productComponents/imageData/file/location/path', str), 'image_data_filename': ('productComponents/imageData/file/location/filename', str), 'time_start': ('productInfo/sceneInfo/start/timeUTC', dec_isoformat), 'center_coor_lat': ('productInfo/sceneInfo/sceneCenterCoord/lat', float), 'center_coor_lon': ('productInfo/sceneInfo/sceneCenterCoord/lon', float) } check_attributes = {'product_level': 'level 1b product', 'satellite_name': 'tsx', 'sensor_type': 'sar'} tree = etree.fromstring(xmlbuffer) # Check satellite, sensor and product level for key, val in check_attributes.items(): try: path = attributes[key][0] attr = tree.xpath(path)[0].text.lower() if not attr.startswith(val): raise mipp.ReaderError("This does not look like a TSX SAR " + "Level 1B Product, %s is '%s' expected '%s'" % (key, attr, val)) except IndexError: raise mipp.ReaderError("This does not look like a TSX SAR " + "Level 1B Product, could not find attribute '%s' (%s)" % (key, path)) mda = Metadata() for key, val in attributes.items(): setattr(mda, key, val[1](tree.xpath(val[0])[0].text)) mda.image_filename = (mda.image_data_path + '/' + mda.image_data_filename) delattr(mda, 'image_data_path') delattr(mda, 'image_data_filename') return mda
def read_manifest(filename, **mdax): """Read a Sentinel-1 manifest file, and extract selected parameters. :Parameters: filename : str Path to manifest file. :Returns: manifest : Metadata object Selected paramters """ def parse_orbit(elm): if elm.get('type').lower() == 'start': return int(elm.text) def parse_text(elm): return elm.text def parse_tolower(elm): return elm.text.lower() def parse_satellite(elm): if elm.text.lower().startswith('sen'): return elm.text.lower() def parse_time(elm): return datetime.strptime(elm.text, "%Y-%m-%dT%H:%M:%S.%f") def parse_coordinates(elm): cor = elm.text.split() arr = [] for c in cor: y, x = [float(i) for i in c.split(',')] arr.append((x, y)) return arr def parse_files(elm): fname = elm.get('href') if fname and fname.startswith('./measurement/'): return os.path.join(basedir, fname[2:]) named_decoder = { '{http://www.esa.int/safe/sentinel-1.0}startTime': ( 'start_time', 1, parse_time), '{http://www.esa.int/safe/sentinel-1.0}stopTime': ( 'stop_time', 1, parse_time), '{http://www.opengis.net/gml}coordinates': ( 'coordinates', 1, parse_coordinates), '{http://www.esa.int/safe/sentinel-1.0}orbitNumber': ( 'orbit_number', 1, parse_orbit), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}mode': ( 'instrument_mode', 1, parse_tolower), '{http://www.esa.int/safe/sentinel-1.0}familyName': ( 'satellite', 1, parse_satellite), # dublicated ! '{http://www.esa.int/safe/sentinel-1.0/sentinel-1}pass': ( 'pass', 1, parse_tolower), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}transmitterReceiverPolarisation': ( 'polarisations', 2, parse_tolower), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}productClassDescription': ( 'description', 1, parse_text), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}productType': ( 'product_type', 1, parse_tolower), 'fileLocation': ( 'files', 2, parse_files), } tags = named_decoder.keys() manifest = Metadata() basedir = os.path.dirname(filename) with open(filename) as fp: xml = etree.parse(fp) for e in xml.getroot().iter(): if e.tag in tags: name, count, decoder = named_decoder[e.tag] value = decoder(e) if value: if count > 1: try: getattr(manifest, name).append(value) except AttributeError: setattr(manifest, name, [value]) else: setattr(manifest, name, value) # Add extra metadata for key, val in mdax.items(): if not hasattr(manifest, key): setattr(manifest, key, val) try: resolution = manifest.resolution_class channels = {} for pol in manifest.polarisations: _text = '-'.join([manifest.mission_id, manifest.instrument_mode, manifest.product_type, pol]) _name = '-'.join([manifest.instrument_mode, resolution, pol]) for fn in manifest.files: if os.path.basename(fn).startswith(_text): channels[_name] = fn manifest.channels = channels manifest.pixel_spacing = PIXEL_SPACING[manifest.instrument_mode + '-' + resolution] except AttributeError: pass return manifest
def read_metadata(xmlbuffer): # Speciel decoders def dec_isoformat(rts): return datetime.strptime(rts, "%Y-%m-%dT%H:%M:%S.%fZ") def dec_orbit_number(rts): return int(rts[:5]) def dec_satellite_name(rts): return rts.replace('-', '') def dec_calibration_unit(rts): _trans = {'radar brightness': 'nrcs'} rts = rts.replace(' ', '-').lower() return rts attributes = { 'product_level': ('generalHeader/itemName', str), 'satellite_name': ('productInfo/missionInfo/mission', dec_satellite_name), 'orbit_number': ('productInfo/missionInfo/absOrbit', dec_orbit_number), 'sensor_type': ('productInfo/acquisitionInfo/sensor', str), 'beam_mode': ('productInfo/acquisitionInfo/imagingMode', str), 'polarisation': ('productInfo/acquisitionInfo/polarisationList/polLayer', str), 'beamid': ('productInfo/acquisitionInfo/elevationBeamConfiguration', str), 'calibrated': ('productInfo/productVariantInfo/radiometricCorrection', str), 'calibration_factor': ('calibration/calibrationConstant/calFactor', float), 'calibration_beamid': ('calibration/calibrationConstant/beamID', str), 'calibration_unit': ('productInfo/imageDataInfo/pixelValueID', dec_calibration_unit), 'image_data_path': ('productComponents/imageData/file/location/path', str), 'image_data_filename': ('productComponents/imageData/file/location/filename', str), 'time_start': ('productInfo/sceneInfo/start/timeUTC', dec_isoformat), 'center_coor_lat': ('productInfo/sceneInfo/sceneCenterCoord/lat', float), 'center_coor_lon': ('productInfo/sceneInfo/sceneCenterCoord/lon', float) } check_attributes = { 'product_level': 'level 1b product', 'satellite_name': 'tsx', 'sensor_type': 'sar' } tree = etree.fromstring(xmlbuffer) # Check satellite, sensor and product level for key, val in check_attributes.items(): try: path = attributes[key][0] attr = tree.xpath(path)[0].text.lower() if not attr.startswith(val): raise mipp.ReaderError( "This does not look like a TSX SAR " + "Level 1B Product, %s is '%s' expected '%s'" % (key, attr, val)) except IndexError: raise mipp.ReaderError( "This does not look like a TSX SAR " + "Level 1B Product, could not find attribute '%s' (%s)" % (key, path)) mda = Metadata() for key, val in attributes.items(): setattr(mda, key, val[1](tree.xpath(val[0])[0].text)) mda.image_filename = (mda.image_data_path + '/' + mda.image_data_filename) delattr(mda, 'image_data_path') delattr(mda, 'image_data_filename') return mda
def read_metadata(xmlbuffer): mda = Metadata() # Speciel decoders def dec_timeformat(strn): strn = strn.split('.') return (datetime.strptime(strn[0], "%Y-%m-%d %H:%M:%S") + timedelta(seconds=float('.' + strn[1]))) def dec_orbit_number(strn): return int(strn[:5]) attributes = ( ('_ROOT_/Attribute', { 'Satellite ID': ('satellite_name', str), 'Product Filename': ('image_filename', str), 'Product Type': ('product_type', str), 'Acquisition Station ID': ('facility_id', str), 'Scene Sensing Start UTC': ('time_start', dec_timeformat), 'Scene Sensing Stop UTC': ('time_stop', dec_timeformat), 'Orbit Number': ('orbit_number', dec_orbit_number), 'Sample Format': ('product_format', str), 'Image Scale': ('image_scale', str), 'Image Layers': ('layers', int), 'Bits per Sample': ('bits_per_sample', int), 'Samples per Pixel': ('samples_per_pixel', int), }), ('MBI/Attribute', { 'Column Spacing': ('sample_spacing', float), 'Line Spacing': ('line_spacing', float) }), ('S01/Attribute', { 'Polarisation': ('polarisation', str), }), ) tree = etree.fromstring(xmlbuffer) # # Get Atrributes # for path, attr in attributes: names = attr.keys() path = tree.xpath(path) for i in path: name = i.attrib['Name'] if name in names: names.remove(name) val = i.text setattr(mda, attr[name][0], attr[name][1](val)) satid = 'CSK' if not mda.satellite_name.upper().startswith(satid): raise mipp.ReaderError( "This does not look like a CosmoSkymed product, " + "satellite ID does now start with '%s'"%satid) mda.image_filename = os.path.splitext(mda.image_filename)[0] + '.MBI.tif' mda.no_data_value = 0 mda.calibrated = 'NOTCALIBRATED' return mda
def read_metadata(xmlbuffer): mda = Metadata() # Speciel decoders def dec_timeformat(strn): strn = strn.split('.') return (datetime.strptime(strn[0], "%Y-%m-%d %H:%M:%S") + timedelta(seconds=float('.' + strn[1]))) def dec_orbit_number(strn): return int(strn[:5]) attributes = ( ('_ROOT_/Attribute', { 'Satellite ID': ('satellite_name', str), 'Product Filename': ('image_filename', str), 'Product Type': ('product_type', str), 'Acquisition Station ID': ('facility_id', str), 'Scene Sensing Start UTC': ('time_start', dec_timeformat), 'Scene Sensing Stop UTC': ('time_stop', dec_timeformat), 'Orbit Number': ('orbit_number', dec_orbit_number), 'Sample Format': ('product_format', str), 'Image Scale': ('image_scale', str), 'Image Layers': ('layers', int), 'Bits per Sample': ('bits_per_sample', int), 'Samples per Pixel': ('samples_per_pixel', int), }), ('MBI/Attribute', { 'Column Spacing': ('sample_spacing', float), 'Line Spacing': ('line_spacing', float) }), ('S01/Attribute', { 'Polarisation': ('polarisation', str), }), ) tree = etree.fromstring(xmlbuffer) # # Get Atrributes # for path, attr in attributes: names = attr.keys() path = tree.xpath(path) for i in path: name = i.attrib['Name'] if name in names: names.remove(name) val = i.text setattr(mda, attr[name][0], attr[name][1](val)) satid = 'CSK' if not mda.satellite_name.upper().startswith(satid): raise mipp.ReaderError( "This does not look like a CosmoSkymed product, " + "satellite ID does now start with '%s'" % satid) mda.image_filename = os.path.splitext(mda.image_filename)[0] + '.MBI.tif' mda.no_data_value = 0 mda.calibrated = 'NOTCALIBRATED' return mda
def read_manifest(filename, **mdax): """Read a Sentinel-1 manifest file, and extract selected parameters. :Parameters: filename : str Path to manifest file. :Returns: manifest : Metadata object Selected paramters """ def parse_orbit(elm): if elm.get('type').lower() == 'start': return int(elm.text) def parse_text(elm): return elm.text def parse_tolower(elm): return elm.text.lower() def parse_satellite(elm): if elm.text.lower().startswith('sen'): return elm.text.lower() def parse_time(elm): return datetime.strptime(elm.text, "%Y-%m-%dT%H:%M:%S.%f") def parse_coordinates(elm): cor = elm.text.split() arr = [] for c in cor: y, x = [float(i) for i in c.split(',')] arr.append((x, y)) return arr def parse_files(elm): fname = elm.get('href') if fname and fname.startswith('./measurement/'): return os.path.join(basedir, fname[2:]) named_decoder = { '{http://www.esa.int/safe/sentinel-1.0}startTime': ('start_time', 1, parse_time), '{http://www.esa.int/safe/sentinel-1.0}stopTime': ('stop_time', 1, parse_time), '{http://www.opengis.net/gml}coordinates': ('coordinates', 1, parse_coordinates), '{http://www.esa.int/safe/sentinel-1.0}orbitNumber': ('orbit_number', 1, parse_orbit), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}mode': ('instrument_mode', 1, parse_tolower), '{http://www.esa.int/safe/sentinel-1.0}familyName': ('satellite', 1, parse_satellite), # dublicated ! '{http://www.esa.int/safe/sentinel-1.0/sentinel-1}pass': ('pass', 1, parse_tolower), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}transmitterReceiverPolarisation': ('polarisations', 2, parse_tolower), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}productClassDescription': ('description', 1, parse_text), '{http://www.esa.int/safe/sentinel-1.0/sentinel-1/sar/level-1}productType': ('product_type', 1, parse_tolower), 'fileLocation': ('files', 2, parse_files), } tags = named_decoder.keys() manifest = Metadata() basedir = os.path.dirname(filename) with open(filename) as fp: xml = etree.parse(fp) for e in xml.getroot().iter(): if e.tag in tags: name, count, decoder = named_decoder[e.tag] value = decoder(e) if value: if count > 1: try: getattr(manifest, name).append(value) except AttributeError: setattr(manifest, name, [value]) else: setattr(manifest, name, value) # Add extra metadata for key, val in mdax.items(): if not hasattr(manifest, key): setattr(manifest, key, val) try: resolution = manifest.resolution_class channels = {} for pol in manifest.polarisations: _text = '-'.join([ manifest.mission_id, manifest.instrument_mode, manifest.product_type, pol ]) _name = '-'.join([manifest.instrument_mode, resolution, pol]) for fn in manifest.files: if os.path.basename(fn).startswith(_text): channels[_name] = fn manifest.channels = channels manifest.pixel_spacing = PIXEL_SPACING[manifest.instrument_mode + '-' + resolution] except AttributeError: pass return manifest
def read_metadata(xml_file): metadata = Metadata() # XML Namespace ns_rs2 = {'xsi': 'http://www.rsi.ca/rs2/prod/xml/schemas'} # Speciel decoders def dec_isoformat(rts): return datetime.strptime(rts, "%Y-%m-%dT%H:%M:%S.%fZ") def dec_orbit_number(rts): return int(rts[:5]) attributes = { 'product_id': ('xsi:productId', str), 'satellite_name': ('xsi:sourceAttributes/xsi:satellite', str), 'sensor_name': ('xsi:sourceAttributes/xsi:sensor', str), 'beam_mode': ('xsi:sourceAttributes/xsi:beamModeMnemonic', str), 'facility_id': ('xsi:sourceAttributes/xsi:inputDatasetFacilityId', str), 'start_time': ('xsi:sourceAttributes/xsi:rawDataStartTime', dec_isoformat), 'orbit_number': ('xsi:sourceAttributes/xsi:orbitAndAttitude/xsi:orbitInformation/xsi:orbitDataFile', dec_orbit_number), 'product_format': ('xsi:imageAttributes/xsi:productFormat', str), 'bits_per_sample': ('xsi:imageAttributes/xsi:rasterAttributes/xsi:bitsPerSample', int), 'samples': ('xsi:imageAttributes/xsi:rasterAttributes/xsi:numberOfSamplesPerLine', int), 'lines': ('xsi:imageAttributes/xsi:rasterAttributes/xsi:numberOfLines', int), 'sample_spacing': ('xsi:imageAttributes/xsi:rasterAttributes/xsi:sampledPixelSpacing', float), 'line_spacing': ('xsi:imageAttributes/xsi:rasterAttributes/xsi:sampledLineSpacing', float), 'data_files': ('xsi:imageAttributes/xsi:fullResolutionImageData', str), 'center_lat': ('centre_lat', str), 'center_lon': ('centre_lon', str), 'tie_point_lines': ('tie_point_lines', str), 'tie_point_samples': ('tie_point_samples', str), 'tie_point_line_jump': ('tie_point_line_jump', str), 'tie_point_sample_jump': ('tie_point_sample_jump', str) } tree = etree.parse(xml_file) # Get some attributes for key, (att, dec) in attributes.items(): if att.startswith('xsi'): rec = tree.xpath(att, namespaces=ns_rs2) if len(rec) > 1: val = tuple([dec(i.text) for i in rec]) else: val = dec(rec[0].text) setattr(metadata, key, val) # # Get tiepoints # tiepoints_xpath = 'xsi:imageAttributes/xsi:geographicInformation/xsi:geolocationGrid/xsi:imageTiePoint' tiepoints_tree = tree.xpath(tiepoints_xpath, namespaces=ns_rs2) tiepoints_count = len(tiepoints_tree) pix_coordinates = numpy.zeros((tiepoints_count, 2)) geo_coordinates = numpy.zeros((tiepoints_count, 2)) counter = 0 for elm in tiepoints_tree: if elm.tag.endswith('imageTiePoint'): pixel, line, lat, lon = None, None, None, None for i in elm.iter(): if i.getparent().tag.endswith('imageCoordinate'): if i.tag.endswith('pixel'): pixel = float(i.text) elif i.tag.endswith('line'): line = float(i.text) elif i.getparent().tag.endswith('geodeticCoordinate'): if i.tag.endswith('latitude'): lat = float(i.text) elif i.tag.endswith('longitude'): lon = float(i.text) if None not in (pixel, line, lat, lon): pix_coordinates[counter] = [line, pixel] geo_coordinates[counter] = [lat, lon] counter += 1 if counter > 0: setattr(metadata, 'tiepoints', TiePoints(pix_coordinates, geo_coordinates)) return metadata