Esempio n. 1
0
    def __getmetadata__(self, f=None):
        '''Populate the metadata'''
        if not f: f = self.fileinfo['filepath']
        self._gdaldataset = geometry.OpenDataset(f)

        led = glob.glob(os.path.dirname(f) +
                        '/[Ll][Ee][Aa][Dd]*')[0]  #volume file

        meta = open(led, 'rb').read()
        '''
        metadata has 4 records, each is 4320 (LS) or 6120 (SPOT) bytes long:
        File descriptor record;
        Scene header record;
        Map projection (scene-related) ancillary record;
        Radiometric transformation ancillary record.
        '''

        #Record 2 - Scene header record
        record = 2
        recordlength = 4320  #LS 5
        satellite = utilities.readbinary(meta, (record - 1) * recordlength,
                                         309, 324)

        #Scene ID, path/row & image date/time
        start, stop = 37, 52
        sceneid = utilities.readbinary(meta, (record - 1) * recordlength,
                                       start, stop)
        start, stop = 165, 180
        pathrow = utilities.readbinary(meta, (record - 1) * recordlength,
                                       start, stop)[1:]
        start, stop = 117, 148
        imgdate = utilities.readbinary(meta, (record - 1) * recordlength,
                                       start, stop)
        self.metadata['imgdate'] = time.strftime(
            utilities.datetimeformat,
            time.strptime(imgdate[0:14], '%Y%m%d%H%M%S'))  #ISO 8601

        #Ascending/descending flag
        start, stop = 357, 372
        if utilities.readbinary(meta, (record - 1) * recordlength, start,
                                stop) == 'D':
            self.metadata['orbit'] = 'Descending'
        else:
            self.metadata['orbit'] = 'Ascending'

        #Processing level
        start, stop = 1573, 1588
        self.metadata['level'] = utilities.readbinary(
            meta, (record - 1) * recordlength, start, stop)

        #Bands
        start, stop = 1653, 1659
        bands = []
        actbands = utilities.readbinary(meta, (record - 1) * recordlength,
                                        start, stop)
        for i in range(0, 7):  #Loop thru the 7 LS 5 bands
            if actbands[i] == '1': bands.append(str(i + 1))
            self._gdaldataset.GetRasterBand(i + 1).SetNoDataValue(0)

        #Record 3 - Map projection (scene-related) ancillary record
        record = 3

        #Bands, rows & columns and rotation
        nbands = int(self._gdaldataset.RasterCount)
        start, stop = 333, 348
        ncols = float(
            utilities.readbinary(meta, (record - 1) * recordlength, start,
                                 stop))
        start, stop = 349, 364
        nrows = float(
            utilities.readbinary(meta, (record - 1) * recordlength, start,
                                 stop))
        start, stop = 445, 460
        self.metadata['rotation'] = float(
            utilities.readbinary(meta, (record - 1) * recordlength, start,
                                 stop))
        if abs(self.metadata['rotation']) < 1:
            self.metadata['orientation'] = 'Map oriented'
            self.metadata['rotation'] = 0.0
        else:
            self.metadata['orientation'] = 'Path oriented'

        #Sun elevation and azimuth
        start, stop = 605, 620
        self.metadata['sunelevation'] = float(
            utilities.readbinary(meta, (record - 1) * recordlength, start,
                                 stop))
        start, stop = 621, 636
        self.metadata['sunazimuth'] = float(
            utilities.readbinary(meta, (record - 1) * recordlength, start,
                                 stop))

        #geometry.CellSizes
        start, stop = 365, 396
        (cellx, celly) = map(
            float,
            utilities.readbinary(meta, (record - 1) * recordlength, start,
                                 stop).split())
        start, stop = 397, 412
        projection = utilities.readbinary(meta, (record - 1) * recordlength,
                                          start, stop).split()
        datum = projection[0]
        zone = projection[1]

        # lat/lons
        start, stop = 765, 892
        coords = utilities.readbinary(meta, (record - 1) * recordlength, start,
                                      stop).split()
        uly, ulx, ury, urx, lry, lrx, lly, llx = map(float, coords)
        ext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly], [ulx, uly]]

        if int(zone) != 0:
            # UTM
            type = 'UTM'
            units = 'm'
            #start,stop =  637,764
            #coords = utilities.readbinary(meta,(record-1)*recordlength,start,stop).split()
            #uly,ulx,ury,urx,lry,lrx,lly,llx = map(float, coords)
            #ext=[[ulx,uly],[urx,ury],[lrx,lry],[llx,lly],[ulx,uly]]

            if datum == 'GDA94': epsg = int('283' + zone)
            elif datum == 'AGD66': epsg = int('202' + zone)
            elif datum == 'WGS84': epsg = int('327' + zone)

        else:  #Assume
            type = 'GEO'
            units = 'deg'
            if datum == 'GDA94': epsg = 4283
            else: epsg = 4326  #Assume WGS84
            gcps = []
            i = 0
            lr = [[0, 0], [ncols, 0], [ncols, nrows], [0, nrows]]
            while i < len(ext) - 1:  #don't need the last xy pair
                gcp = gdal.GCP()
                gcp.GCPPixel, gcp.GCPLine = lr[i]
                gcp.GCPX, gcp.GCPY = ext[i]
                gcp.Id = str(i)
                gcps.append(gcp)
                i += 1
            geotransform = gdal.GCPsToGeoTransform(gcps)
            cellx, celly = geometry.CellSize(geotransform)
            rotation = geometry.Rotation(geotransform)

        srs = osr.SpatialReference()
        srs.ImportFromEPSG(epsg)
        srs = srs.ExportToWkt()

        self.metadata['satellite'] = satellite
        if satellite == 'LANDSAT-5':
            self.metadata['sensor'] = 'TM'
            self.metadata['filetype'] = 'CEOS/Landsat CCRS Format'
        else:
            self.metadata['sensor'] = 'HRV'
            self.metadata['filetype'] = 'CEOS/SPOT CCRS Format'
        self.metadata['filesize'] = sum(
            [os.path.getsize(file) for file in self.filelist])
        self.metadata['srs'] = srs
        self.metadata['epsg'] = epsg
        self.metadata['units'] = units
        self.metadata['cols'] = ncols
        self.metadata['rows'] = nrows
        self.metadata['nbands'] = nbands
        self.metadata['bands'] = ','.join(bands)
        self.metadata['nbits'] = 8
        self.metadata['datatype'] = 'Byte'
        self.metadata['nodata'] = 0
        self.metadata['cellx'], self.metadata['celly'] = map(
            float, [cellx, celly])
        self.metadata['UL'] = '%s,%s' % tuple(ext[0])
        self.metadata['UR'] = '%s,%s' % tuple(ext[1])
        self.metadata['LR'] = '%s,%s' % tuple(ext[2])
        self.metadata['LL'] = '%s,%s' % tuple(ext[3])
        metadata = self._gdaldataset.GetMetadata()
        self.metadata['metadata'] = '\n'.join(
            ['%s: %s' % (m, hdf_self.metadata[m]) for m in metadata])
        self.metadata['compressionratio'] = 0
        self.metadata['compressiontype'] = 'None'
        self.extent = ext
Esempio n. 2
0
    def __getmetadata__(self):
        '''Read Metadata for recognised EO1 ALI (L1G & L1R) & Hyperion (L1R) images as GDAL doesn't'''

        f = self.fileinfo['filepath']
        self.metadata['satellite'] = 'E01'
        self.metadata['nbits'] = 16
        self.metadata['datatype'] = 'Int16'
        self.metadata['nodata'] = 0
        if re.search(r'eo1a.*\.m[1-4]r$', f, re.I):
            self.ali_l1r(f)
        elif re.search(r'eo1.*_mtl\.tif$', f):
            self.ali_l1g_tiff(f)
        elif re.search(r'eo1.*_hdf\.l1g$', f):
            self.ali_l1g_hdf(f)
        elif re.search(r'eo1h.*\.l[1-4]r$', f):
            self.hyp_l1r(f)
        elif re.search(r'eo1.*_mtl_.*\.l1t$', f, re.I):
            self.hyp_l1t(f)

        self.metadata['cols'] = self.ncols
        self.metadata['rows'] = self.nrows
        self.metadata['nbands'] = self.nbands

        #Geotransform
        ncols = map(int, str(self.ncols).split(','))
        nrows = map(int, str(self.nrows).split(','))
        cellx, celly = [], []
        j = 0
        while j < len(ncols):
            gcps = []
            i = 0
            lr = [[0, 0], [ncols[j], 0], [ncols[j], nrows[j]], [0, nrows[j]]]
            while i < len(self.prjext) - 1:  #don't need the last xy pair
                gcp = gdal.GCP()
                gcp.GCPPixel, gcp.GCPLine = lr[i]
                gcp.GCPX, gcp.GCPY = self.prjext[i]
                gcp.Id = str(i)
                gcps.append(gcp)
                i += 1
            j += 1
            geotransform = gdal.GCPsToGeoTransform(gcps)
            x, y = geometry.CellSize(geotransform)
            cellx.append(str(x))
            celly.append(str(abs(y)))

        self.metadata['cellx'] = ','.join(cellx)
        self.metadata['celly'] = ','.join(celly)

        self.metadata['UL'] = '%s,%s' % tuple(self.geoext[0])
        self.metadata['UR'] = '%s,%s' % tuple(self.geoext[1])
        self.metadata['LR'] = '%s,%s' % tuple(self.geoext[2])
        self.metadata['LL'] = '%s,%s' % tuple(self.geoext[3])

        self.metadata['rotation'] = geometry.Rotation(geotransform)
        if abs(self.metadata['rotation']) < 1.0:
            self.metadata['orientation'] = 'Map oriented'
            self.metadata['rotation'] = 0.0
        else:
            self.metadata['orientation'] = 'Path oriented'

        self.metadata['filesize'] = sum(
            [os.path.getsize(tmp) for tmp in self.filelist])
        self.metadata['compressionratio'] = 0
        self.metadata['compressiontype'] = 'None'
        self.extent = self.geoext
    def __getmetadata__(self):
        '''Read Metadata for recognised EO1 ALI (L1G & L1R) & Hyperion (L1R) images as GDAL doesn't'''

        f = self.fileinfo['filepath']
        self.metadata['satellite'] = 'E01'
        self.metadata['nbits'] = 16
        self.metadata['datatype'] = 'Int16'
        self.metadata['nodata'] = 0
        if re.search(r'\.m[1-4]r$', f, re.I):
            self.metadata['level'] = 'L1R'
            self.metadata['sensor'] = 'ALI'

            gdalDataset = geometry.OpenDataset(f)
            #if not gdalDataset: #Error now raised in geometry.OpenDataset
            #    errmsg=gdal.GetLastErrorMsg()
            #    raise IOError, 'Unable to open %s\n%s' % (f,errmsg.strip())

            self.metadata['filetype'] = '%s/%s (%s %s)' % (
                gdalDataset.GetDriver().ShortName,
                gdalDataset.GetDriver().LongName, self.metadata['sensor'],
                self.metadata['level'])

            srs = osr.SpatialReference()
            srs.ImportFromEPSG(4326)
            self.metadata['srs'] = srs.ExportToWkt()
            self.metadata['epsg'] = 4326
            self.metadata['units'] = 'deg'

            hdf_sd = gdalDataset.GetSubDatasets()
            hdf_md = gdalDataset.GetMetadata()
            sd, sz = hdf_sd[0]
            sd = geometry.OpenDataset(sd)
            sd_md = sd.GetMetadata()
            nbands = sd.RasterCount
            ncols = str(
                sd.RasterXSize * 4 - 30
            )  #Account for the four SCA strips and the overlap between SCA strips
            nrows = sd_md[
                'Number of along track pixels']  #sd.RasterYSize is incorrect
            if len(hdf_sd) == 6:  #Includes pan band (3 sds each)
                sd, sz = hdf_sd[3]
                sd = geometry.OpenDataset(sd)
                sd_md = sd.GetMetadata()
                cols = str(
                    int(sd_md['Number of cross track pixels']) * 4 - 30
                )  #Account for the four SCA strips and the overlap between SCA strips
                rows = sd_md['Number of along track pixels']

                #set up to create multispectral only self._gdaldatset for overview generation
                if nbands == 1:
                    multi = 3
                    multibands = sd_md['Number of bands']
                    multicols = cols
                    multirows = rows
                else:
                    multi = 0
                    multibands = nbands
                    multicols = ncols
                    multirows = nrows
                multibands = range(1, int(multibands) + 1)

                #Make a csv list of cols, bands
                ncols = [ncols for i in range(0, nbands)]
                nrows = [nrows for i in range(0, nbands)]
                ncols.extend([cols for i in range(0, sd.RasterCount)])
                nrows.extend([rows for i in range(0, sd.RasterCount)])
                #nbands='%s,%s' % (nbands, sd_md['Number of bands'])
                nbands = nbands + int(sd_md['Number of bands'])
                ncols = ','.join(ncols)
                nrows = ','.join(nrows)

            else:
                #set up to create multispectral only _gdaldatset for overview generation
                multi = 0
                multibands = range(1, nbands + 1)
                multicols = ncols
                multirows = nrows

            #create multispectral only _gdaldatset for overview generation
            #Get all the data files and mosaic the strips
            #strips=[s for s in utilities.rglob(os.path.dirname(f),r'\.m[1-4]r$',True,re.I,False)]
            strips = glob.glob(os.path.join(os.path.dirname(f), '*.m[1-4]r'))
            strips.sort()
            strips.reverse()  #west->east = *.m4r-m1
            scols = (int(multicols) +
                     30) / 4  # +30 handles the 10 pixel overlap
            xoff = 10
            yoff = 400
            srows = int(multirows) - yoff
            srcrects = [[0, yoff, scols, srows]] * 4
            dstrects = []
            srcrect = [0, yoff, scols, srows]
            #dstrect=[None,0,scols,srows]
            files = []
            sd, sz = hdf_sd[multi]
            vrt_opts = []
            indatasetlist = []
            for i in range(0, 4):
                files.append(sd.replace(f, strips[i]))
                dstrects.append([i * (scols - xoff), 0, scols, srows])
            self._gdaldataset = geometry.OpenDataset(
                geometry.CreateMosaicedVRT(files, multibands, srcrects,
                                           dstrects, multicols, srows,
                                           'Int16'))
            self._gdaldataset.GetRasterBand(2).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(3).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(4).SetNoDataValue(0)
            self._stretch = ('STDDEV', (4, 3, 2), [2])

            #Extract other metadata
            met = os.path.splitext(f)[0] + '.met'
            for line in open(met, 'r').readlines():
                if line[0:16] == 'Scene Request ID':
                    line = line.strip().split()
                    self.metadata['sceneid'] = line[3]
                if line[0:14] == 'ALI Start Time':
                    line = line.strip().split()
                    hdf_md['ImageStartTime'] = line[3] + line[4]
                if line[0:8] == 'PRODUCT_':
                    line = line.strip()
                    line = map(string.strip, line.split('='))
                    if line[0] == 'PRODUCT_UL_CORNER_LAT': uly = float(line[1])
                    if line[0] == 'PRODUCT_UL_CORNER_LON': ulx = float(line[1])
                    if line[0] == 'PRODUCT_UR_CORNER_LAT': ury = float(line[1])
                    if line[0] == 'PRODUCT_UR_CORNER_LON': urx = float(line[1])
                    if line[0] == 'PRODUCT_LR_CORNER_LAT': lry = float(line[1])
                    if line[0] == 'PRODUCT_LR_CORNER_LON': lrx = float(line[1])
                    if line[0] == 'PRODUCT_LL_CORNER_LAT': lly = float(line[1])
                    if line[0] == 'PRODUCT_LL_CORNER_LON': llx = float(line[1])
            geoext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly],
                      [ulx, uly]]
            prjext = geoext
        elif re.search(r'eo1.*_mtl\.tif$', f):
            self.metadata['level'] = 'L1G'
            self.metadata['sensor'] = 'ALI'
            self.metadata['sceneid'] = self.metadata['filename'].split('_')[0]
            self.metadata['filetype'] = 'GTiff/GeoTIFF'

            ncols = []
            nrows = []
            nbands = 0
            bands = glob.glob(os.path.join(os.path.dirname(f), 'eo1*_b*.tif'))
            for band in bands:
                band = geometry.OpenDataset(band)
                ncols.append(str(band.RasterXSize))
                nrows.append(str(band.RasterYSize))
                nbands += 1
                #rb=sd.GetRasterBand(1)

            #get all multi bands for use in overview generation
            pancols = max(ncols)
            panindex = ncols.index(pancols)
            multibands = bands
            multincols = ncols
            multinrows = nrows
            if pancols > min(ncols):  #there is a pan band
                multibands.pop(panindex)
                multincols.pop(panindex)
                multinrows.pop(panindex)
            multibands.sort()
            self._gdaldataset = geometry.OpenDataset(
                geometry.CreateSimpleVRT(multibands, multincols[0],
                                         multinrows[0], 'Int16'))
            self._gdaldataset.GetRasterBand(2).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(3).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(4).SetNoDataValue(0)
            self._stretch = ('STDDEV', (4, 3, 2), [2])

            ncols = ','.join(ncols)
            nrows = ','.join(nrows)
            met = f
            md = {}
            for line in open(met, 'r'):
                line = line.replace('"', '')
                line = [l.strip() for l in line.split('=')]
                if line[0] == 'END':  #end of the metadata file
                    break
                elif line[0] == 'GROUP':  #start of a metadata group
                    if line[1] != 'L1_METADATA_FILE':
                        group = line[1]
                        md[group] = {}
                elif line[0] == 'END_GROUP':  #end of a metadata group
                    pass
                else:  #metadata value
                    md[group][line[0]] = line[1]

            uly = float(md['PRODUCT_METADATA']['PRODUCT_UL_CORNER_LAT'])
            ulx = float(md['PRODUCT_METADATA']['PRODUCT_UL_CORNER_LON'])
            ury = float(md['PRODUCT_METADATA']['PRODUCT_UR_CORNER_LAT'])
            urx = float(md['PRODUCT_METADATA']['PRODUCT_UR_CORNER_LON'])
            lry = float(md['PRODUCT_METADATA']['PRODUCT_LR_CORNER_LAT'])
            lrx = float(md['PRODUCT_METADATA']['PRODUCT_LR_CORNER_LON'])
            lly = float(md['PRODUCT_METADATA']['PRODUCT_LL_CORNER_LAT'])
            llx = float(md['PRODUCT_METADATA']['PRODUCT_LL_CORNER_LON'])
            geoext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly],
                      [ulx, uly]]

            uly = float(md['PRODUCT_METADATA']['PRODUCT_UL_CORNER_MAPY'])
            ulx = float(md['PRODUCT_METADATA']['PRODUCT_UL_CORNER_MAPX'])
            ury = float(md['PRODUCT_METADATA']['PRODUCT_UR_CORNER_MAPY'])
            urx = float(md['PRODUCT_METADATA']['PRODUCT_UR_CORNER_MAPX'])
            lry = float(md['PRODUCT_METADATA']['PRODUCT_LR_CORNER_MAPY'])
            lrx = float(md['PRODUCT_METADATA']['PRODUCT_LR_CORNER_MAPX'])
            lly = float(md['PRODUCT_METADATA']['PRODUCT_LL_CORNER_MAPY'])
            llx = float(md['PRODUCT_METADATA']['PRODUCT_LL_CORNER_MAPX'])
            prjext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly],
                      [ulx, uly]]

            self.metadata['imgdate'] = md['PRODUCT_METADATA'][
                'ACQUISITION_DATE']
            self.metadata['resampling'] = md['PROJECTION_PARAMETERS'][
                'RESAMPLING_OPTION']
            try:
                self.metadata['viewangle'] = float(
                    md['PRODUCT_PARAMETERS']['SENSOR_LOOK_ANGLE'])
            except:
                pass  #Exception raised if value == 'UNAVAILABLE'
            try:
                self.metadata['sunazimuth'] = float(
                    md['PRODUCT_PARAMETERS']['SUN_AZIMUTH'])
            except:
                pass  #Exception raised if value == 'UNAVAILABLE'
            try:
                self.metadata['sunelevation'] = float(
                    md['PRODUCT_PARAMETERS']['SUN_ELEVATION'])
            except:
                pass  #Exception raised if value == 'UNAVAILABLE'

            #EPSG:32601: WGS 84 / UTM zone 1N
            #EPSG:32701: WGS 84 / UTM zone 1S
            srs = osr.SpatialReference()
            zone = int(md['UTM_PARAMETERS']['ZONE_NUMBER'])
            if zone > 0: epsg = 32600 + zone  #North
            else: epsg = 32700 - zone  #South
            srs.ImportFromEPSG(epsg)
            self.metadata['units'] = 'm'
            self.metadata['srs'] = srs.ExportToWkt()
            self.metadata['epsg'] = str(epsg)

        elif re.search(r'eo1.*_hdf\.l1g$', f):
            self.metadata['level'] = 'L1G'
            self.metadata['sensor'] = 'ALI'
            self.metadata['sceneid'] = self.metadata['filename'].split('_')[0]

            gdalDataset = geometry.OpenDataset(f)
            #if not gdalDataset: #Error now raised in geometry.OpenDataset
            #    errmsg=gdal.GetLastErrorMsg()
            #    raise IOError, 'Unable to open %s\n%s' % (f,errmsg.strip())

            self.metadata['filetype'] = '%s/%s (%s %s)' % (
                gdalDataset.GetDriver().ShortName,
                gdalDataset.GetDriver().LongName, self.metadata['sensor'],
                self.metadata['level'])

            hdf_sd = gdalDataset.GetSubDatasets()
            hdf_md = gdalDataset.GetMetadata()
            sd, sz = hdf_sd[0]
            sd = geometry.OpenDataset(sd)
            sd_md = sd.GetMetadata()
            ncols = []
            nrows = []
            nbands = 0
            bands = []
            for sd, sz in hdf_sd:
                bands.append(sd)
                ds = geometry.OpenDataset(sd)
                ncols.append(str(ds.RasterXSize))
                nrows.append(str(ds.RasterYSize))
                nbands += 1

            #get all multi bands for use in overview generation
            pancols = max(ncols)
            panindex = ncols.index(pancols)
            multibands = bands
            multincols = ncols
            multinrows = nrows
            if pancols > min(ncols):  #there is a pan band
                multibands.pop(panindex)
                multincols.pop(panindex)
                multinrows.pop(panindex)
            multibands.sort()
            self._gdaldataset = geometry.OpenDataset(
                geometry.CreateSimpleVRT(multibands, multincols[0],
                                         multinrows[0], 'Int16'))
            self._gdaldataset.GetRasterBand(2).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(3).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(4).SetNoDataValue(0)
            self._stretch = ('STDDEV', (4, 3, 2), [2])

            ncols = ','.join(ncols)
            nrows = ','.join(nrows)

            met = f.lower().replace('_hdf.l1g', '_mtl.l1g')
            md = {}
            for line in open(met, 'r'):
                line = line.replace('"', '')
                line = [l.strip() for l in line.split('=')]
                if line[0] == 'END':  #end of the metadata file
                    break
                elif line[0] == 'GROUP':  #start of a metadata group
                    if line[1] != 'L1_METADATA_FILE':
                        group = line[1]
                        md[group] = {}
                elif line[0] == 'END_GROUP':  #end of a metadata group
                    pass
                else:  #metadata value
                    md[group][line[0]] = line[1]

            uly = float(md['PRODUCT_METADATA']['PRODUCT_UL_CORNER_LAT'])
            ulx = float(md['PRODUCT_METADATA']['PRODUCT_UL_CORNER_LON'])
            ury = float(md['PRODUCT_METADATA']['PRODUCT_UR_CORNER_LAT'])
            urx = float(md['PRODUCT_METADATA']['PRODUCT_UR_CORNER_LON'])
            lry = float(md['PRODUCT_METADATA']['PRODUCT_LR_CORNER_LAT'])
            lrx = float(md['PRODUCT_METADATA']['PRODUCT_LR_CORNER_LON'])
            lly = float(md['PRODUCT_METADATA']['PRODUCT_LL_CORNER_LAT'])
            llx = float(md['PRODUCT_METADATA']['PRODUCT_LL_CORNER_LON'])
            geoext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly],
                      [ulx, uly]]
            prjext = geoext

            self.metadata['imgdate'] = md['PRODUCT_METADATA'][
                'ACQUISITION_DATE']
            self.metadata['resampling'] = md['PROJECTION_PARAMETERS'][
                'RESAMPLING_OPTION']
            try:
                self.metadata['viewangle'] = float(
                    md['PRODUCT_PARAMETERS']['SENSOR_LOOK_ANGLE'])
            except:
                pass  #Exception raised if value == 'UNAVAILABLE'
            try:
                self.metadata['sunazimuth'] = float(
                    md['PRODUCT_PARAMETERS']['SUN_AZIMUTH'])
            except:
                pass  #Exception raised if value == 'UNAVAILABLE'
            try:
                self.metadata['sunelevation'] = float(
                    md['PRODUCT_PARAMETERS']['SUN_ELEVATION'])
            except:
                pass  #Exception raised if value == 'UNAVAILABLE'

            #EPSG:32601: WGS 84 / UTM zone 1N
            #EPSG:32701: WGS 84 / UTM zone 1S
            srs = osr.SpatialReference()
            zone = int(md['UTM_PARAMETERS']['ZONE_NUMBER'])
            if zone > 0: epsg = 32600 + zone  #North
            else: epsg = 32700 - zone  #South
            srs.ImportFromEPSG(epsg)
            self.metadata['units'] = 'm'
            self.metadata['srs'] = srs.ExportToWkt()
            self.metadata['epsg'] = str(epsg)

        else:
            self.metadata['level'] = 'L1R'
            self.metadata['sensor'] = 'HYPERION'

            gdalDataset = geometry.OpenDataset(f)
            #if not gdalDataset: #Error now raised in geometry.OpenDataset
            #    errmsg=gdal.GetLastErrorMsg()
            #    raise IOError, 'Unable to open %s\n%s' % (f,errmsg.strip())

            self.metadata['filetype'] = '%s/%s (%s %s)' % (
                gdalDataset.GetDriver().ShortName,
                gdalDataset.GetDriver().LongName, self.metadata['sensor'],
                self.metadata['level'])
            srs = osr.SpatialReference()
            srs.ImportFromEPSG(4326)
            self.metadata['srs'] = srs.ExportToWkt()
            self.metadata['epsg'] = 4326
            self.metadata['units'] = 'deg'

            hdf_sd = gdalDataset.GetSubDatasets()
            hdf_md = gdalDataset.GetMetadata()
            sd, sz = hdf_sd[0]
            sd = geometry.OpenDataset(sd)
            sd_md = sd.GetMetadata()
            nbands = sd.RasterCount
            ncols = sd.RasterXSize
            nrows = sd.RasterYSize
            met = os.path.splitext(f)[0] + '.met'
            for line in open(met, 'r').readlines():
                if line[0:16] == 'Scene Request ID':
                    line = line.strip().split()
                    self.metadata['sceneid'] = line[3]
                if line[0:14] == 'HYP Start Time':
                    line = line.strip().split()
                    imgdate = time.strptime(line[3] + line[4], '%Y%j')
                    self.metadata['imgdate'] = time.strftime(
                        '%Y-%m-%d', imgdate)  #ISO 8601
                if line[0:8] == 'PRODUCT_':
                    line = line.strip()
                    line = map(string.strip, line.split('='))
                    if line[0] == 'PRODUCT_UL_CORNER_LAT': uly = float(line[1])
                    if line[0] == 'PRODUCT_UL_CORNER_LON': ulx = float(line[1])
                    if line[0] == 'PRODUCT_UR_CORNER_LAT': ury = float(line[1])
                    if line[0] == 'PRODUCT_UR_CORNER_LON': urx = float(line[1])
                    if line[0] == 'PRODUCT_LR_CORNER_LAT': lry = float(line[1])
                    if line[0] == 'PRODUCT_LR_CORNER_LON': lrx = float(line[1])
                    if line[0] == 'PRODUCT_LL_CORNER_LAT': lly = float(line[1])
                    if line[0] == 'PRODUCT_LL_CORNER_LON': llx = float(line[1])
            geoext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly],
                      [ulx, uly]]
            prjext = geoext

            #########################################################################################################
            ##set self._gdaldataset for use in overview generation
            ##we'll use bands 21, 30 & 43 for RGB (http://edcsns17.cr.usgs.gov/eo1/Hyperion_Spectral_Coverage.htm)
            ##as they're near the center of the equivalent ALI bands

            ##This generates verrrryyy looong overviews cos hyperion data is one long thin strip eg. 256*3000 etc...
            #self._gdaldataset = geometry.CreateVRTCopy(sd)
            ##Instead we can clip out some of the centre rows
            #vrtcols=ncols
            #vrtrows=int(ncols*1.5)
            #srcrect=[0, int(nrows/2-vrtrows/2),ncols,vrtrows]
            #dstrect=[0, 0,ncols,vrtrows]
            ##Or we can fill out the ncols with nodata
            vrtcols = int(nrows / 1.5)
            vrtrows = nrows
            srcrect = [0, 0, ncols, nrows]
            dstrect = [int(nrows / 2.5 - ncols), 0, ncols, nrows]
            vrt = geometry.CreateMosaicedVRT([sd.GetDescription()],
                                             [43, 30, 21], [srcrect],
                                             [dstrect], vrtcols, vrtrows,
                                             self.metadata['datatype'])
            self._gdaldataset = geometry.OpenDataset(vrt)
            self._gdaldataset.GetRasterBand(3).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(2).SetNoDataValue(0)
            self._gdaldataset.GetRasterBand(1).SetNoDataValue(0)
            self._stretch = ('STDDEV', (1, 2, 3), [2])
            #########################################################################################################
        self.metadata['cols'] = ncols
        self.metadata['rows'] = nrows
        self.metadata['nbands'] = nbands

        #Geotransform
        ncols = map(int, str(ncols).split(','))
        nrows = map(int, str(nrows).split(','))
        cellx, celly = [], []
        j = 0
        while j < len(ncols):
            gcps = []
            i = 0
            lr = [[0, 0], [ncols[j], 0], [ncols[j], nrows[j]], [0, nrows[j]]]
            while i < len(prjext) - 1:  #don't need the last xy pair
                gcp = gdal.GCP()
                gcp.GCPPixel, gcp.GCPLine = lr[i]
                gcp.GCPX, gcp.GCPY = prjext[i]
                gcp.Id = str(i)
                gcps.append(gcp)
                i += 1
            j += 1
            geotransform = gdal.GCPsToGeoTransform(gcps)
            x, y = geometry.CellSize(geotransform)
            cellx.append(str(x))
            celly.append(str(abs(y)))

        self.metadata['cellx'] = ','.join(cellx)
        self.metadata['celly'] = ','.join(celly)

        self.metadata['UL'] = '%s,%s' % tuple(geoext[0])
        self.metadata['UR'] = '%s,%s' % tuple(geoext[1])
        self.metadata['LR'] = '%s,%s' % tuple(geoext[2])
        self.metadata['LL'] = '%s,%s' % tuple(geoext[3])

        self.metadata['rotation'] = geometry.Rotation(geotransform)
        if abs(self.metadata['rotation']) < 1.0:
            self.metadata['orientation'] = 'Map oriented'
            self.metadata['rotation'] = 0.0
        else:
            self.metadata['orientation'] = 'Path oriented'

        self.metadata['filesize'] = sum(
            [os.path.getsize(tmp) for tmp in self.filelist])
        self.metadata['compressionratio'] = 0
        self.metadata['compressiontype'] = 'None'
        self.extent = geoext
    def __getmetadata__(self,f=None):
        '''Populate metadata'''
        if not f:f=self.fileinfo['filepath']
        self._gdaldataset = geometry.OpenDataset(f)

        led=glob.glob(os.path.dirname(f) + '/[Ll][Ee][Aa][Dd]*')[0] #volume file
        meta = open(led,'rb').read()

        ######################
        # Scene header record
        ######################
        record=2
        recordlength=3960 #SPOT recordlength=3960

        ##################
        #SCENE PARAMETERS
        ##################
        sceneid=utilities.readbinary(meta,(record-1)*recordlength,37,52)

        cy=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,85,100),'HDDDMMSS') #Latitude of the Scene Centre
        cx=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,101,116),'HDDDMMSS') #Longitude of the Scene Centre
        uly=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,149,164),'HDDDMMSS')
        ulx=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,165,180),'HDDDMMSS')
        ury=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,213,228),'HDDDMMSS')
        urx=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,229,244),'HDDDMMSS')
        lly=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,277,292),'HDDDMMSS')
        llx=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,293,308),'HDDDMMSS')
        lry=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,341,356),'HDDDMMSS')
        lrx=geometry.DMS2DD(utilities.readbinary(meta,(record-1)*recordlength,357,372),'HDDDMMSS')
        ext=[[ulx,uly],[urx,ury],[lrx,lry],[llx,lly],[ulx,uly]]

        ######################
        #IMAGING PARAMETERS
        ######################
        self.metadata['rotation']=float(utilities.readbinary(meta,(record-1)*recordlength,437,452))
        if abs(self.metadata['rotation']) < 1:
            self.metadata['orientation']='Map oriented'
            self.metadata['rotation']=0.0
        else:self.metadata['orientation']='Path oriented'
        self.metadata['sunazimuth']=float(utilities.readbinary(meta,(record-1)*recordlength,469,484))
        self.metadata['sunelevation']=float(utilities.readbinary(meta,(record-1)*recordlength,485,500))
        imgdate=utilities.readbinary(meta,(record-1)*recordlength,581,612)
        #self.metadata['imgdate']=time.strftime(utilities.dateformat,time.strptime(imgdate[0:8],'%Y%m%d')) #ISO 8601 
        self.metadata['imgdate']=time.strftime(utilities.datetimeformat,time.strptime(imgdate[0:14],'%Y%m%d%H%M%S')) #ISO 8601 
        satellite=utilities.readbinary(meta,(record-1)*recordlength,613,628)
        sensor=utilities.readbinary(meta,(record-1)*recordlength,629,644)
        mode=utilities.readbinary(meta,(record-1)*recordlength,645,660)

        ######################
        #IMAGE PARAMETERS
        ######################
        ncols=int(utilities.readbinary(meta,(record-1)*recordlength,997,1012))
        nrows=int(utilities.readbinary(meta,(record-1)*recordlength,1013,1028))
        nbands=int(utilities.readbinary(meta,(record-1)*recordlength,1045,1060))
        bands=utilities.readbinary(meta,(record-1)*recordlength,1061,1316).replace(' ',',')
        self.metadata['level']=utilities.readbinary(meta,(record-1)*recordlength,1317,1332)
        self.metadata['resampling']=utilities.readbinary(meta,(record-1)*recordlength,1365,1380)
        if self.metadata['level']=='1A': #Not geometrically corrected. Cell size isn't really appropriate
            gcps=geometry.ExtentToGCPs(ext,ncols,nrows)
            gt=gdal.GCPsToGeoTransform(gcps)
            cellx,celly=geometry.CellSize(gt)
        else:
            cellx=float(utilities.readbinary(meta,(record-1)*recordlength,1381,1396))
            celly=float(utilities.readbinary(meta,(record-1)*recordlength,1397,1412))

        #################################################
        #Ancillary "Ephemeris / Attitude" record,
        #################################################
        record=3
        viewangle=float(utilities.readbinary(meta,(record-1)*recordlength,3065,3076))
        
        #################################################
        #Map projection (scene-related) ancillary record
        #################################################
        record=26
        projection = utilities.readbinary(meta,(record-1)*recordlength,21,52).replace('\x00','')
        ellipsoid = utilities.readbinary(meta,(record-1)*recordlength,57,88).replace('\x00','')
        datum = utilities.readbinary(meta,(record-1)*recordlength,101,132).replace('\x00','')

        if 'UTM' in projection:
            # UTM
            type='UTM'
            units='m'
            zone=projection[3:-1]
            if not zone:
                zone=str(spatialreferences.lon2utmzone(cx))
            if   'GDA' in datum: epsg=int('283'+zone)
            elif 'AGD' in datum: epsg=int('202'+zone)
            elif 'WGS' in datum: epsg=int('327'+zone) if projection[-1] =='S' else int('326'+zone)
            
        else: #Assume
            type='GEO'
            units='deg'
            if datum=='GDA94':epsg=4283
            else:epsg=4326 #Assume WGS84
            if   'GDA' in datum: epsg=4283
            elif 'AGD' in datum: epsg=202
            else:                epsg=4326 #Assume WGS84'

            #cell sizes are reported in metres even for geo projections
            gcps=[];i=0
            lr=[[0,0],[ncols,0],[ncols,nrows],[0,nrows]]
            while i < len(ext)-1: #don't need the last xy pair
                gcp=gdal.GCP()
                gcp.GCPPixel,gcp.GCPLine=lr[i]
                gcp.GCPX,gcp.GCPY=ext[i]
                gcp.Id=str(i)
                gcps.append(gcp)
                i+=1
            geotransform = gdal.GCPsToGeoTransform(gcps)
            cellx,celly=geometry.CellSize(geotransform)
            rotation=geometry.Rotation(geotransform)

        srs = osr.SpatialReference()
        srs.ImportFromEPSG(epsg)
        srs=srs.ExportToWkt()

        self.metadata['satellite']=satellite
        self.metadata['sensor']=sensor
        self.metadata['filetype'] ='CEOS/SPOT CCT Format'
        self.metadata['filesize']=sum([os.path.getsize(file) for file in self.filelist])
        self.metadata['sceneid'] = sceneid
        self.metadata['srs'] = srs
        self.metadata['epsg'] = epsg
        self.metadata['units'] = units
        self.metadata['cols'] = ncols
        self.metadata['rows'] = nrows
        self.metadata['nbands'] = nbands
        self.metadata['bands'] = bands
        self.metadata['nbits'] = 8
        self.metadata['datatype'] = 'Byte'
        self.metadata['nodata'] = 0
        self.metadata['mode'] = mode
        self.metadata['cellx'],self.metadata['celly']=map(float,[cellx,celly])
        self.metadata['UL']='%s,%s' % tuple(ext[0])
        self.metadata['UR']='%s,%s' % tuple(ext[1])
        self.metadata['LR']='%s,%s' % tuple(ext[2])
        self.metadata['LL']='%s,%s' % tuple(ext[3])
        metadata=self._gdaldataset.GetMetadata()
        self.metadata['metadata']='\n'.join(['%s: %s' %(m,hdf_self.metadata[m]) for m in metadata])
        self.metadata['compressionratio']=0
        self.metadata['compressiontype']='None'
        self.extent=ext
Esempio n. 5
0
    def __getmetadata__(self, f=None):
        '''
        Generate metadata for generic imagery

        @type  f: string
        @param f: a filepath to the dataset or a VRT XML string
        @return:  None

        @todo: We force a NoData value. This is not ideal, but it makes for better overview images.
        '''
        if not f: f = self.fileinfo['filepath']
        try:
            cwd = os.path.abspath(os.curdir)
            if os.path.exists(f) and os.path.dirname(f):
                p = os.path.split(f)[0]
                os.chdir(p)
            if not self._gdaldataset:
                self._gdaldataset = geometry.OpenDataset(
                    f
                )  #in case we're subclassed and there's already a dataset open
            if self._gdaldataset:
                driver = self._gdaldataset.GetDriver().ShortName
                if driver[0:3] == 'HDF':
                    raise NotImplementedError, 'HDF files are not yet implemented except by custom formats'
                self.metadata[
                    'filetype'] = driver + '/' + self._gdaldataset.GetDriver(
                    ).LongName
                self.metadata['cols'] = self._gdaldataset.RasterXSize
                self.metadata['rows'] = self._gdaldataset.RasterYSize
                self.metadata['nbands'] = self._gdaldataset.RasterCount

                self.metadata['srs'] = self._gdaldataset.GetProjection()
                if not self.metadata['srs'] and self._gdaldataset.GetGCPCount(
                ) > 0:
                    self.metadata['srs'] = self._gdaldataset.GetGCPProjection()
                self.metadata['epsg'] = spatialreferences.IdentifyAusEPSG(
                    self.metadata['srs'])
                self.metadata['units'] = spatialreferences.GetLinearUnitsName(
                    self.metadata['srs'])

                geotransform = self._gdaldataset.GetGeoTransform()
                if geotransform == (0, 1, 0, 0, 0, 1):
                    if self._gdaldataset.GetGCPCount() > 0:
                        gcps = self._gdaldataset.GetGCPs()
                        geotransform = gdal.GCPsToGeoTransform(gcps)
                        gcps = geometry.GeoTransformToGCPs(
                            geotransform, self.metadata['cols'], self.
                            metadata['rows'])  #Just get the 4 corner GCP's
                    else:
                        raise NotImplementedError, 'Dataset is not georeferenced'
                else:
                    gcps = geometry.GeoTransformToGCPs(geotransform,
                                                       self.metadata['cols'],
                                                       self.metadata['rows'])

                ext = [[gcp.GCPX, gcp.GCPY] for gcp in gcps]
                ext.append([gcps[0].GCPX, gcps[0].GCPY
                            ])  #Add the 1st point to close the polygon)

                #Reproject corners to lon,lat
                geom = geometry.GeomFromExtent(ext)
                src_srs = osr.SpatialReference()
                src_srs.ImportFromWkt(self.metadata['srs'])
                tgt_srs = osr.SpatialReference()
                tgt_srs.ImportFromEPSG(4326)
                geom = geometry.ReprojectGeom(geom, src_srs, tgt_srs)
                points = geom.GetGeometryRef(0)  #geom.GetBoundary()
                ext = [[points.GetX(i), points.GetY(i)]
                       for i in range(0, points.GetPointCount())]

                self.metadata['cellx'], self.metadata[
                    'celly'] = geometry.CellSize(geotransform)
                self.metadata['rotation'] = geometry.Rotation(geotransform)
                if abs(self.metadata['rotation']) < 1.0:
                    self.metadata['orientation'] = 'Map oriented'
                    self.metadata['rotation'] = 0.0
                else:
                    self.metadata['orientation'] = 'Path oriented'
                self.metadata['UL'] = '%s,%s' % tuple(ext[0])
                self.metadata['LL'] = '%s,%s' % tuple(ext[1])
                self.metadata['LR'] = '%s,%s' % tuple(ext[2])
                self.metadata['UR'] = '%s,%s' % tuple(ext[3])

                rb = self._gdaldataset.GetRasterBand(1)
                if rb:
                    self.metadata['datatype'] = gdal.GetDataTypeName(
                        rb.DataType)
                    self.metadata['nbits'] = gdal.GetDataTypeSize(rb.DataType)
                    nodata = rb.GetNoDataValue()
                    if nodata is not None:
                        self.metadata['nodata'] = str(nodata)
                    else:
                        ct = rb.GetColorTable()  #Fix for Issue 31
                        if ct is None:
                            if self.metadata['datatype'][0:4] in [
                                    'Byte', 'UInt'
                            ]:
                                nodata = 0  #Unsigned, assume 0
                            else:
                                nodata = -2**(
                                    self.metadata['nbits'] - 1
                                )  #Signed, assume min value in data range
                            self.metadata['nodata'] = str(nodata)
                            #Fix for Issue 17
                            for i in range(1,
                                           self._gdaldataset.RasterCount + 1):
                                self._gdaldataset.GetRasterBand(
                                    i).SetNoDataValue(nodata)
                else:
                    raise IOError, 'No valid rasterbands found.'

                metadata = self._gdaldataset.GetMetadata()
                self.metadata['metadata'] = '\n'.join(
                    ['%s: %s' % (m, metadata[m]) for m in metadata])
                self.metadata['filesize'] = sum(
                    [os.path.getsize(tmp) for tmp in self.filelist])
                if self.metadata['filesize'] > 0:
                    self.metadata['compressionratio'] = int(
                        (self.metadata['nbands'] * self.metadata['cols'] *
                         self.metadata['rows'] *
                         (self.metadata['nbits'] / 8.0)) /
                        self.metadata['filesize'])
                if self.metadata['compressionratio'] > 0:
                    try:
                        if driver[0:3] == 'JP2':
                            self.metadata['compressiontype'] = "JPEG2000"
                        elif driver[0:3] == 'ECW':
                            self.metadata['compressiontype'] = "ECW"
                        else:
                            mdis = self._gdaldataset.GetMetadata(
                                'IMAGE_STRUCTURE')
                            #self.metadata['compressiontype']=mdis['IMAGE_STRUCTURE']
                            self.metadata['compressiontype'] = mdis[
                                'COMPRESSION']
                    except:
                        self.metadata['compressiontype'] = 'Unknown'
                else:
                    self.metadata['compressiontype'] = 'None'
                self.extent = ext
            else:
                errmsg = gdal.GetLastErrorMsg()
                raise IOError, 'Unable to open %s\n%s' % (f, errmsg.strip())

        finally:  #Cleanup
            gdal.ErrorReset()
            os.chdir(cwd)