Ejemplo n.º 1
0
    def __getmetadata__(self):
        '''Read Metadata for an ACRES Landsat FastL7A format image as GDAL doesn't get it all.
        Format description: http://www.ga.gov.au/image_cache/GA10348.pdf

        Note:
        hrf = ~30m VNIR/SWIR       (bands 1-5 & 7)
        htm = ~60m thermal         (band 6)
        hpn = ~15m pan             (band 8)
        '''

        f = self.fileinfo['filepath']
        d = os.path.dirname(f)
        hdr = open(f).read()
        err = 'Unable to open %s' % f

        md = self.metadata
        md['filesize'] = sum([os.path.getsize(file) for file in self.filelist])
        md['filetype'] = 'FAST/EOSAT FAST Format'

        rl = 1536  #recordlength

        ######################################
        ##Record 1 - administrative
        ######################################
        rec = 1

        req_id = utilities.readascii(hdr, (rec - 1) * rl, 9, 28)
        loc = utilities.readascii(hdr, (rec - 1) * rl, 35, 51)
        acquisition_date = utilities.readascii(hdr, (rec - 1) * rl, 71, 78)
        md['imgdate'] = '%s-%s-%s' % (
            acquisition_date[:4], acquisition_date[4:6], acquisition_date[6:])
        md['satellite'] = utilities.readascii(hdr, (rec - 1) * rl, 92, 101)
        md['sensor'] = utilities.readascii(hdr, (rec - 1) * rl, 111, 120)
        md['mode'] = utilities.readascii(hdr, (rec - 1) * rl, 135, 140)
        md['viewangle'] = float(
            utilities.readascii(hdr, (rec - 1) * rl, 154, 159))
        product_type = utilities.readascii(hdr, (rec - 1) * rl, 655, 672)
        product_size = utilities.readascii(hdr, (rec - 1) * rl, 688, 697)
        level = utilities.readascii(hdr, (rec - 1) * rl, 741, 751)
        md['resampling'] = utilities.readascii(hdr, (rec - 1) * rl, 765, 766)
        md['cols'] = int(utilities.readascii(hdr, (rec - 1) * rl, 843, 847))
        md['rows'] = int(utilities.readascii(hdr, (rec - 1) * rl, 865, 869))
        md['cellx'] = float(utilities.readascii(hdr, (rec - 1) * rl, 954, 959))
        md['celly'] = md['cellx']
        md['nbits'] = 8  #int(utilities.readascii(hdr,(rec-1)*rl,984,985)) always 8 bit
        md['datatype'] = 'Byte'
        md['nodata'] = '0'
        bands_present = utilities.readascii(hdr, (rec - 1) * rl, 1056, 1087)

        bandindices = [[1131, 1159], [1170, 1198], [1211, 1239], [1250, 1278],
                       [1291, 1319], [1330, 1358]]
        bandfiles = {}
        for i in bandindices:
            band = utilities.readascii(hdr, (rec - 1) * rl, i[0], i[1])
            if band:
                exists, path = utilities.exists(os.path.join(d, band), True)
                if exists: bandfiles[band] = path
                else:  #Assume ACRES format (band*.dat) instead Fast format (l7*.fst)...
                    bandid = band[23:25]
                    if bandid == '61': bandid = '6l'
                    elif bandid == '62': bandid = '6h'
                    else: bandid = bandid[0]
                    exists, path = utilities.exists(
                        os.path.join(d, 'band%s.dat' % bandid), True)
                    if not exists:
                        raise RuntimeError, 'Unable to open band data files.'
                    bandfiles[band] = path
            else:
                break
        md['nbands'] = len(bandfiles)

        md['sceneid'] = os.path.basename(
            bandfiles.keys()[0]
        )[3:
          21]  #Use path/row & aquisition date as sceneid - L7f[ppprrr_rrrYYYYMMDD]_AAA.FST
        if self._filetype == 'HRF':
            md['bands'] = '1 (BLUE),2 (GREEN),3 (RED),4 (NIR),5 (SWIR),7 (SWIR)'
        elif self._filetype == 'HTM':
            md['bands'] = '6L (THERMAL),6H (THERMAL)'
        elif self._filetype == 'HPN':
            md['bands'] = '8 (PAN)'

        ######################################
        ##Record 2 - radiometric
        ######################################
        #Move along, nothing to see here...

        ######################################
        ##Record 3 - geometric
        ######################################
        rec = 3
        map_projection = utilities.readascii(hdr, (rec - 1) * rl, 32, 35)
        prjcode = spatialreferences.GCTP_PROJECTIONS.get(map_projection, 0)
        ellipsoid = utilities.readascii(hdr, (rec - 1) * rl, 48, 65)
        ellcode = spatialreferences.GCTP_ELLIPSOIDS.get(ellipsoid, 0)
        datum = utilities.readascii(hdr, (rec - 1) * rl, 74, 79)
        zone = utilities.readascii(hdr, (rec - 1) * rl, 521, 526)

        #Workaround for UTM zones as GDAL does not pick up southern hemisphere
        #as some FST headers don't include a negative zone number to indicate southern hemisphere
        #as per the FAST format definition
        zone = int(zone) if zone else 0

        usgs_indices = (
            (110, 133),  #Semi-major axis
            (135, 158),  #Semi-minor axis
            (161, 184),
            (186, 209),
            (211, 234),
            (241, 264),
            (266, 289),
            (291, 314),
            (321, 344),
            (346, 369),
            (371, 394),
            (401, 424),
            (426, 449),
            (451, 474),
            (481, 504))
        usgs_params = []
        for i in usgs_indices:
            p = utilities.readascii(hdr, (rec - 1) * rl, i[0], i[1])
            if p: usgs_params.append(float(p))
            else: usgs_params.append(0.0)

        ulx = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 566, 578),
            'DDDMMSSSSSSSH')
        uly = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 580, 591), 'DDMMSSSSSSSH')
        urx = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 646, 658),
            'DDDMMSSSSSSSH')
        ury = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 660, 671), 'DDMMSSSSSSSH')
        lrx = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 726, 738),
            'DDDMMSSSSSSSH')
        lry = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 740, 751), 'DDMMSSSSSSSH')
        llx = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 806, 818),
            'DDDMMSSSSSSSH')
        lly = geometry.DMS2DD(
            utilities.readascii(hdr, (rec - 1) * rl, 820, 831), 'DDMMSSSSSSSH')
        ext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly], [ulx, uly]]

        md['UL'] = '%s,%s' % tuple(ext[0])
        md['UR'] = '%s,%s' % tuple(ext[1])
        md['LR'] = '%s,%s' % tuple(ext[2])
        md['LL'] = '%s,%s' % tuple(ext[3])

        if zone > 0 and uly < 0: zone *= -1
        srs = osr.SpatialReference()
        srs.ImportFromUSGS(prjcode, zone, usgs_params, ellcode)
        if datum == 'GDA':  #Workaround for GDA94 datum as GDAL does not recognise it
            #as per the FAST format definition
            if map_projection == 'UTM':
                epsg = 28300 + abs(zone)
                srs.ImportFromEPSG(epsg)
                md['srs'] = srs.ExportToWkt()
                md['epsg'] = epsg
                md['units'] = 'm'
            else:
                srs.SetGeogCS('GDA94', 'Geocentric_Datum_of_Australia_1994',
                              'GRS 1980', usgs_params[0], 298.257)
                md['srs'] = srs.ExportToWkt()
                md['epsg'] = spatialreferences.IdentifyAusEPSG(md['srs'])
                md['units'] = spatialreferences.GetLinearUnitsName(md['srs'])
        else:
            md['srs'] = srs.ExportToWkt()
            md['epsg'] = spatialreferences.IdentifyAusEPSG(md['srs'])
            md['units'] = spatialreferences.GetLinearUnitsName(md['srs'])

        md['rotation'] = float(
            utilities.readascii(hdr, (rec - 1) * rl, 995, 1000))
        if abs(md['rotation']) < 1:
            md['orientation'] = 'Map oriented'
            md['rotation'] = 0.0
        else:
            md['orientation'] = 'Path oriented'
        md['sunelevation'] = utilities.readascii(hdr, (rec - 1) * rl, 1062,
                                                 1065)
        md['sunazimuth'] = utilities.readascii(hdr, (rec - 1) * rl, 1086, 1090)

        try:  ##Open dataset
            self._gdaldataset = geometry.OpenDataset(f)
            metadata = self._gdaldataset.GetMetadata()
            md['metadata'] = '\n'.join(
                ['%s: %s' % (m, metadata[m]) for m in metadata])
            #Fix for Issue 17
            for i in range(1, self._gdaldataset.RasterCount + 1):
                self._gdaldataset.GetRasterBand(i).SetNoDataValue(
                    float(md['nodata']))

        except:  #build a VRT dataset - if we want to use this for anything other than overview generation, should probably fill out the geotransform, srs, metadata etc...
            bands = bandfiles.values()
            bands.sort()
            #vrtxml=geometry.CreateRawRasterVRT(bands,md['cols'],md['rows'], md['datatype']) #Fix for Issue 17
            vrtxml = geometry.CreateRawRasterVRT(bands,
                                                 md['cols'],
                                                 md['rows'],
                                                 md['datatype'],
                                                 nodata=md['nodata'])
            self._gdaldataset = geometry.OpenDataset(vrtxml)
            md['metadata'] = hdr

        if self._filetype == 'HRF':
            self._gdaldataset.GetRasterBand(4).SetRasterColorInterpretation(
                gdal.GCI_BlueBand)
            self._gdaldataset.GetRasterBand(3).SetRasterColorInterpretation(
                gdal.GCI_GreenBand)
            self._gdaldataset.GetRasterBand(2).SetRasterColorInterpretation(
                gdal.GCI_RedBand)

        if level == 'SYSTEMATIC': md['level'] = '1G '
        elif level == 'SYSTERRAIN': md['level'] = '1Gt'
        elif level == 'PRECISION': md['level'] = '1P'
        elif level == 'TERRAIN': md['level'] = '1T'

        md['compressionratio'] = 0
        md['compressiontype'] = 'None'

        self.extent = ext

        for m in md:
            self.metadata[m] = md[m]
Ejemplo n.º 2
0
    def __getmetadata__(self,f=None):
        '''Read Metadata for an ACRES ALOS AVNIR-2/PRISM/PALSAR format image as GDAL doesn't'''

        #Local copies for brevity
        vol=self._vol
        led=self._led

        if 'led-alpsr' in led.lower():driver='SAR_CEOS'
        else:driver='CEOS'

        extra_md={} #for holding any extra metadata which gets stuffed into self.metadata['metadata'] later on

        self.metadata['satellite']='ALOS'
        nodata = 0

        #ACRES ortho product is in GTIFF format
        tif=False

        if driver=='SAR_CEOS':  #PALSAR - assumes Level 1.5, Level 1.0 not implemented
            #Format Description
            #Level 1.0     - http://www.ga.gov.au/servlet/BigObjFileManager?bigobjid=GA10287
            #Level 1.1/1.5 - http://www.eorc.jaxa.jp/ALOS/doc/fdata/PALSAR_x_Format_EK.pdf
            
            self.metadata['sensor']='PALSAR'
            self.metadata['filetype'] ='CEOS/ALOS PALSAR CEOS Format'
            
            '''
            volume file has 3-6 records, 360 bytes length:
            Record            Length
            =========================
            1 File descriptor 360 
            2 File pointer    360 (3-6 records = N+2 where N is number of polarization)
            3 Text            360
            '''
            meta = open(vol,'rb').read()

            #File descriptor record
            offset = 0

            #Number of file pointers        
            npointers=int(utilities.readbinary(meta,offset,161,164))

            #Text record
            offset = 360*(npointers+1)

            #Product type specifier
            start,stop = 17,56
            prodspec = utilities.readbinary(meta,offset,start,stop)[8:] #Strip of the "'PRODUCT:" string
            if prodspec[1:4] != '1.5':raise Exception, 'ALOS PALSAR Level %s not yet implemented' % level
            if prodspec[0]=='H':self.metadata['mode']='Fine (high resolution) mode'
            elif prodspec[0]=='W':self.metadata['mode']='ScanSAR (wide observation) mode'
            elif prodspec[0]=='D':self.metadata['mode']='Direct Downlink mode'
            elif prodspec[0]=='P':self.metadata['mode']='Polarimetry mode'
            elif prodspec[0]=='C':self.metadata['mode']='Calibration mode'
            level=prodspec[1:5]
            orient=prodspec[4]
            if orient=='G':self.metadata['orientation']='Map oriented'
            else: self.metadata['orientation']='Path oriented'
            orbit=prodspec[6]
            
            '''
            leader file has >9 records of variable length:
            Record                    Length
            ============================================
            1 File descriptor         720 
            2 Data set summary        4096
            3 Map projection data     1620
            4 Platform position data  4680
            5 Attitude data           8192
            6 Radiometric data        9860
            7 Data quality summary    1620
            8 Calibration data        13212
            9 Facility related        Variable
            '''
            meta = open(led,'rb').read()

            #File descriptor
            offset = 0
            
            #Data set summary
            offset = 720
            #Scene ID
            start,stop = 21,52
            sceneid = utilities.readbinary(meta,offset,start,stop)
            #Image date
            start,stop = 69,100
            #imgdate=utilities.readbinary(meta,offset,start,stop)[0:14]#Strip off time
            #self.metadata['imgdate'] = time.strftime(utilities.dateformat,time.strptime(imgdate,'%Y%m%d')) #ISO 8601
            imgdate=utilities.readbinary(meta,offset,start,stop)[0:14] #Keep time, strip off milliseconds
            self.metadata['imgdate'] = time.strftime(utilities.datetimeformat,time.strptime(imgdate,'%Y%m%d%H%M%S'))            #SAR Channels
            start,stop = 389,392
            nbands = int(utilities.readbinary(meta,offset,start,stop))
            
            #Radar wavelength
            start,stop = 501,516
            wavelen = utilities.readbinary(meta,offset,start,stop)
            extra_md['wavelength']=wavelen
            
            #Nominal offnadir angle
            start,stop = 1839,1854
            self.metadata['viewangle'] = utilities.readbinary(meta,offset,start,stop)

            #Map projection data
            offset += 4096
            #Cols & rows
            start,stop = 61,76
            ncols = int(utilities.readbinary(meta,offset,start,stop))
            start,stop = 77,92
            nrows = int(utilities.readbinary(meta,offset,start,stop))
            #cell sizes (metres)
            start,stop = 93,124
            ypix,xpix = map(float,utilities.readbinary(meta,offset,start,stop).split())


            #Orientation at output scene centre
            start,stop = 125,140
            rot = math.radians(float(utilities.readbinary(meta,offset,start,stop)))
            #GeogCS
            src_srs=osr.SpatialReference()
            #src_srs.SetGeogCS('GRS 1980','GRS 1980','GRS 1980',6378137.00000,298.2572220972)
            src_srs.SetWellKnownGeogCS( "WGS84" )
            #Proj CS
            start,stop = 413,444
            projdesc = utilities.readbinary(meta,offset,start,stop)
            epsg=0#default
            if projdesc == 'UTM-PROJECTION':
                nZone = int(utilities.readbinary(meta,offset,477,480))
                dfFalseNorthing = float(utilities.readbinary(meta,offset,497,512))
                if dfFalseNorthing > 0.0:
                    bNorth=False
                    epsg=32700+nZone
                else:
                    bNorth=True
                    epsg=32600+nZone
                src_srs.ImportFromEPSG(epsg)
                #src_srs.SetUTM(nZone,bNorth) #generates WKT that osr.SpatialReference.AutoIdentifyEPSG() doesn't return an EPSG for
            elif projdesc == 'UPS-PROJECTION':
                dfCenterLon = float(utilities.readbinary(meta,offset,625,640))
                dfCenterLat = float(utilities.readbinary(meta,offset,641,656))
                dfScale = float(utilities.readbinary(meta,offset,657,672))
                src_srs.SetPS(dfCenterLat,dfCenterLon,dfScale,0.0,0.0) 	
            elif projdesc == 'MER-PROJECTION':
                dfCenterLon = float(utilities.readbinary(meta,offset,737,752))
                dfCenterLat = float(utilities.readbinary(meta,offset,753,768))
                src_srs.SetMercator(dfCenterLat,dfCenterLon,0,0,0)
            elif projdesc == 'LCC-PROJECTION':
                dfCenterLon = float(utilities.readbinary(meta,offset,737,752))
                dfCenterLat = float(utilities.readbinary(meta,offset,753,768))
                dfStdP1 = float(utilities.readbinary(meta,offset,769,784))
                dfStdP2 = float(utilities.readbinary(meta,offset,785,800))
                src_srs.SetLCC(dfStdP1,dfStdP2,dfCenterLat,dfCenterLon,0,0)
            srs=src_srs.ExportToWkt()
            if not epsg:epsg = spatialreferences.IdentifyAusEPSG(srs)
            units = spatialreferences.GetLinearUnitsName(srs)

            #UL-LR coords
            ##ext=[float(coord)*1000 for coord in utilities.readbinary(meta,offset,945,1072).split()] #Get lat/lon instead of eastings/northings
            ext=[float(coord) for coord in utilities.readbinary(meta,offset,1073,1200).split()]
            uly,ulx,ury,urx,lry,lrx,lly,llx=ext
            ext=[[ulx,uly],[urx,ury],[lrx,lry],[llx,lly],[ulx,uly]] #last xy pair closes the poly

            self.metadata['nbits'] = 16
            self.metadata['datatype']='UInt16'

            #Generate a GDAL Dataset object
            self._gdaldataset=geometry.OpenDataset(self._imgs[0])

        else:        #ALOS AVNIR2/PRISM
            ##Format - http://www.ga.gov.au/servlet/BigObjFileManager?bigobjid=GA10285
            
            '''
            leader file has 5 records, each is 4680 bytes long:
            1. File descriptor record;
            2. Scene header record;
            3. Map projection (scene-related) ancillary record;
            4. Radiometric transformation ancillary record;
            5. Platform position ancillary record.
            '''
            #ACRES ortho product is in GTIFF format
            if '.tif' in self._imgs[0].lower():
                tif=True
                level='ORTHOCORRECTED'
                __default__.Dataset.__getmetadata__(self, self._imgs[0])

            meta = open(led,'rb').read()
            recordlength = 4680

            #Record 2 - Scene header record
            record=2

            #Processing level
            if not tif:
                start,stop = 21,36
                procinfo = utilities.readbinary(meta,(record-1)*recordlength,start,stop)
                level=procinfo[1:4]
                #if level != '1B2':raise Exception, 'Level %s PRISM is not supported' % level
                self.metadata['level']==procinfo[1:4]
                opt=procinfo[4:6].strip().strip('_')
                if opt!='':level+='-'+opt

            #SceneID
            if level[0:3] == '1B2':start,stop = 197,212
            else:start,stop = 37,52
            sceneid = utilities.readbinary(meta,(record-1)*recordlength,start,stop)

            #Lat/Lon of scene center
            ##if level[0:3] == '1B2':start,stop = 245,276
            ##else:start,stop = 85,116
            ##cenrow, cencol=map(float,utilities.readbinary(meta,(record-1)*recordlength,start,stop).split())
            
            #Line & Pixel number for scene center
            ##if level[0:3] == '1B2':start,stop = 245,276
            ##else:start,stop = 85,116
            ##cenrow, cencol=map(float,utilities.readbinary(meta,(record-1)*recordlength,start,stop).split())

            #Orientation Angle NNN.N = degrees
            start,stop = 277,292
            rot = float(utilities.readbinary(meta,(record-1)*recordlength,start,stop))

            #Ascending/descendit orbit
            start,stop = 357,372
            orbit = utilities.readbinary(meta,(record-1)*recordlength,start,stop)

            #view, sun elevation and azimuth angles
            start,stop = 373,388
            self.metadata['viewangle'] = utilities.readbinary(meta,(record-1)*recordlength,start,stop)
            start,stop = 453,466
            sunangles = utilities.readbinary(meta,(record-1)*recordlength,start,stop)
            self.metadata['sunelevation'] = sunangles[6:9].strip()
            self.metadata['sunazimuth']   = sunangles[11:].strip()

            #Image aquisition date
            start,stop = 401,408
            imgdate = utilities.readbinary(meta,(record-1)*recordlength,start,stop)
            imgdate = time.strptime(imgdate,'%d%b%y') #DDMmmYY
            self.metadata['imgdate'] = time.strftime(utilities.dateformat,imgdate) #ISO 8601 

            #Sensor type and bands
            start,stop = 443,452
            sensor,bands=utilities.readbinary(meta,(record-1)*recordlength,start,stop).split()
            if sensor=='PSM':
                self.metadata['sensor']='PRISM'
                if sceneid[5] == 'N':  extra_md['SENSOR DIRECTION']='Nadir 35km'
                elif sceneid[5] == 'W':extra_md['SENSOR DIRECTION']='Nadir 70km'
                elif sceneid[5] == 'F':extra_md['SENSOR DIRECTION']='Forward 35km'
                elif sceneid[5] == 'B':extra_md['SENSOR DIRECTION']='Backward 35km'
            else:self.metadata['sensor']='AVNIR-2'
            self.metadata['filetype'] ='CEOS/ALOS %s CEOS Format' % self.metadata['sensor']
            self.metadata['bands']=','.join([band for band in bands])

            #Processing info
            if not tif:
                start,stop = 467,478
                procinfo = utilities.readbinary(meta,(record-1)*recordlength,start,stop)
                orient=procinfo[-1]
                if orient=='G':self.metadata['orientation']='Map oriented'
                else:self.metadata['orientation']='Path oriented'

                #No. bands
                start,stop = 1413,1428
                nbands = int(utilities.readbinary(meta,(record-1)*recordlength,start,stop))

                #No. cols
                start,stop = 1429,1444
                ncols = float(utilities.readbinary(meta,(record-1)*recordlength,start,stop))

                #No. rows
                start,stop = 1445,1460
                nrows = float(utilities.readbinary(meta,(record-1)*recordlength,start,stop))

            #Resampling
            start,stop = 1541,1556
            res = utilities.readbinary(meta,(record-1)*recordlength,start,stop)
            if   res=='NNNNN':self.metadata['resampling']=''      #Raw (L1A,L1B1)
            elif res=='YNNNN':self.metadata['resampling']='NN'    #Nearest neighbour
            elif res=='NYNNN':self.metadata['resampling']='BL'    #Bi-linear
            elif res=='NNYNN':self.metadata['resampling']='CC'    #Cubic convolution
            
            #Lat/Lon extent
            start,stop = 1733,1860
            coords = utilities.readbinary(meta,(record-1)*recordlength,start,stop).split()
            uly,ulx,ury,urx,lly,llx,lry,lrx = map(float, coords)
            ext=[[ulx,uly],[urx,ury],[lrx,lry],[llx,lly],[ulx,uly]]

            if not tif:
                #Record 3
                record=3

                #Hemisphere
                start,stop = 93,96
                hemi = utilities.readbinary(meta,(record-1)*recordlength,start,stop)

                #UTM Zone - revisit if we get polarstereographic projection products
                start,stop = 97,108
                utm = utilities.readbinary(meta,(record-1)*recordlength,start,stop)
                if hemi=='1': #South
                    epsg=int('327%s' % utm) #Assume WGS84
                else:         #North
                    epsg=int('326%s' % utm)
                src_srs = osr.SpatialReference()
                src_srs.ImportFromEPSG(epsg)
                units = 'm'
                #Scene center position - revisit if we get polarstereographic projection products
                ##start,stop = 141,156
                ##ceny = float(utilities.readbinary(meta,(record-1)*recordlength,start,stop)) * 1000 #(Northing - km)
                ##start,stop = 157,172
                ##cenx = float(utilities.readbinary(meta,(record-1)*recordlength,start,stop)) * 1000 #(Easting - km)

                #Orientation Angle NNN.N = radians
                start,stop = 205,220
                rot = float(utilities.readbinary(meta,(record-1)*recordlength,start,stop))

                #Pixel size (x)
                start,stop=541,572
                xpix,ypix=map(float,utilities.readbinary(meta,(record-1)*recordlength,start,stop).split())

                #Get extent of scene
                ##xmin=(cenx+xpix/2)-(cencol*xpix)
                ##ymin=(ceny+ypix/2)-(cenrow*ypix)
                ##xmax=xmin+(ncols*xpix)
                ##ymax=ymin+(nrows*ypix)
                
                ##if procinfo[-1]=='R': #Calculate rotated extent coordinates
                ##    ##angc=math.cos(rot)
                ##    ##angs=math.sin(rot)
                ##    angc=math.cos(math.radians(rot))
                ##    angs=math.sin(math.radians(rot))
                ##    ulx =  (xmin-cenx)*angc + (ymax-ceny)*angs+cenx
                ##    uly = -(xmin-cenx)*angs + (ymax-ceny)*angc+ceny
                ##    llx =  (xmin-cenx)*angc + (ymin-ceny)*angs+cenx
                ##    lly = -(xmin-cenx)*angs + (ymin-ceny)*angc+ceny
                ##    urx =  (xmax-cenx)*angc + (ymax-ceny)*angs+cenx
                ##    ury = -(xmax-cenx)*angs + (ymax-ceny)*angc+ceny
                ##    lrx =  (xmax-cenx)*angc + (ymin-ceny)*angs+cenx
                ##    lry = -(xmax-cenx)*angs + (ymin-ceny)*angc+ceny
                ##else: #Just use xmin etc...
                ##    ulx,uly = xmin,ymax
                ##    llx,lly = xmin,ymin
                ##    urx,ury = xmax,ymax
                ##    lrx,lry = xmax,ymin
                ##ext=[[ulx,uly],[urx,ury],[lrx,lry],[llx,lly],[ulx,uly]]

                #Geotransform
                ##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)

                self.metadata['nbits'] = 8
                self.metadata['datatype'] = 'Byte'

                #Generate a VRT GDAL Dataset object
                self._imgs.sort()
                img=self._imgs[0]
                meta = open(img,'rb').read(1024)
                start,stop = 187,192
                record=1
                recordlength=0
                offset=utilities.readbinary(meta,(record-1)*recordlength,start,stop)
                #don't use ALOS provided no. cols, as it doesn't include 'dummy' pixels
                #vrt=geometry.CreateRawRasterVRT(self._imgs,self.metadata['cols'],self.metadata['rows'],self.metadata['datatype'],offset,byteorder='MSB')
                vrt=geometry.CreateRawRasterVRT(self._imgs,offset,nrows,self.metadata['datatype'],offset,byteorder='MSB')
                self._gdaldataset=geometry.OpenDataset(vrt)

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

        #Fix for Issue 17
        for i in range(1,self._gdaldataset.RasterCount+1):
            self._gdaldataset.GetRasterBand(i).SetNoDataValue(nodata)

        self.metadata['level'] = level
        self.metadata['sceneid'] = sceneid
        if orbit=='A':self.metadata['orbit']='Ascending'
        else: self.metadata['orbit']='Descending'
        self.metadata['metadata']='\n'.join(['%s: %s' %(m,extra_md[m]) for m in extra_md])
        if not tif:
            self.metadata['filesize']=sum([os.path.getsize(tmp) for tmp in self.filelist])
            self.metadata['srs'] = src_srs.ExportToWkt()
            self.metadata['epsg'] = epsg
            self.metadata['units'] = units
            self.metadata['cols'] = ncols
            self.metadata['rows'] = nrows
            self.metadata['nbands'] = nbands
            if abs(math.degrees(rot)) < 1.0:self.metadata['rotation'] = 0.0
            else: self.metadata['rotation'] = math.degrees(rot)
            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])
            self.metadata['cellx'],self.metadata['celly']=xpix,ypix
            self.metadata['nodata'] = nodata
            self.metadata['compressionratio']=0
            self.metadata['compressiontype']='None'
            self.extent=ext
Ejemplo n.º 3
0
    def __getmetadata__(self, f=None):
        '''Read Metadata for ASTER HDF images as GDAL doesn't.'''
        if not f: f = self.fileinfo['filepath']

        hdf_sd = self._gdaldataset.GetSubDatasets()
        hdf_sd = [sd for sd, sz in hdf_sd if 'ImageData' in sd]
        hdf_md = self._hdf_md

        #sd,sz = hdf_sd[0]
        sd = hdf_sd[0]
        sd = geometry.OpenDataset(sd)

        nbands = len(hdf_sd)
        ncols = []
        nrows = []
        nbits = []
        bands = []
        datatypes = []
        cellxy = []
        for i in range(0, len(hdf_md['PROCESSEDBANDS']), 2):
            band = hdf_md['PROCESSEDBANDS'][i:i + 2]
            if i / 2 + 1 <= 4:
                bands.append('VNIR' + band)
                cellxy.append('15')
            elif i / 2 + 1 <= 10:
                bands.append('SWIR' + band)
                cellxy.append('30')
            else:
                bands.append('TIR' + band)
                cellxy.append('90')
            if band.isdigit(): band = str(int(band))  #Get rid of leading zero
            cols, rows, bytes = map(
                int, hdf_md['IMAGEDATAINFORMATION%s' % band].split(','))
            if bytes == 1: datatypes.append('Byte')
            elif bytes == 2: datatypes.append('UInt16')
            ncols.append(str(cols))
            nrows.append(str(rows))
            nbits.append(str(bytes * 8))
        ncols = ','.join(ncols)
        nrows = ','.join(nrows)
        nbits = ','.join(nbits)
        bands = ','.join(bands)
        datatypes = ','.join(datatypes)
        cellxy = ','.join(cellxy)

        uly, ulx = [float(xy) for xy in hdf_md['UPPERLEFT'].split(',')]
        ury, urx = [float(xy) for xy in hdf_md['UPPERRIGHT'].split(',')]
        lry, lrx = [float(xy) for xy in hdf_md['LOWERRIGHT'].split(',')]
        lly, llx = [float(xy) for xy in hdf_md['LOWERLEFT'].split(',')]
        ext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly], [ulx, uly]]

        #SRS reported by GDAL is slightly dodgy, GDA94 is not recognised and doesn't set the North/South properly
        #Get it anyway so we can work out if it's GDA94 based on the spheroid
        srs = sd.GetGCPProjection()
        src_srs = osr.SpatialReference(srs)
        tgt_srs = osr.SpatialReference()
        geogcs = osr.SpatialReference()
        if src_srs.GetAttrValue('SPHEROID') == 'GRS 1980':
            geogcs.ImportFromEPSG(4283)  #Assume 'GDA94'
        else:
            geogcs.ImportFromEPSG(4326)  #Assume 'WGS84'
        tgt_srs.CopyGeogCSFrom(geogcs)

        if hdf_md['PROCESSINGLEVELID'].upper() == '1A':
            units = 'deg'
        else:
            #projparams=map(float, hdf_md['PROJECTIONPARAMETERS1'].split(','))
            if hdf_md['MPMETHOD1'] == 'UTM':  #Universal Transverse Mercator
                if uly < 0:
                    bNorth = False  #GDAL doesn't set the North/South properly
                else:
                    bNorth = True
                nZone = int(hdf_md['UTMZONECODE1'])
                tgt_srs.SetUTM(nZone, bNorth)
                units = 'm'
            #Other projections not (yet?) implemented...
            #elif hdf_md['MPMETHOD1'] == 'PS':#Polar Stereographic
            #    #dfCenterLon = ? GTCP projection params don't list cenlon/lat for PS
            #    dfCenterLat = ?
            #    dfScale = ?
            #    tgt_srs.SetPS(dfCenterLat,dfCenterLon,dfScale,0.0,0.0)
            #elif hdf_md['MPMETHOD1'] == 'LAMCC':#Lambert Conformal Conic
            #    dfCenterLon = ?
            #    dfCenterLat = ?
            #    dfStdP1 = ?
            #    dfStdP2 = ?
            #    tgt_srs.SetLCC(dfStdP1,dfStdP2,dfCenterLat,dfCenterLon,0,0)
            #elif hdf_md['MPMETHOD1'] == 'SOM':#Space Oblique Mercator
            #    dfCenterLon = ?
            #    dfCenterLat = ?
            #    srs.SetMercator(dfCenterLat,dfCenterLon,0,0,0)
            #elif hdf_md['MPMETHOD1'] == 'EQRECT':#Equi-Rectangular
            #    dfCenterLon = ?
            #    dfCenterLat = ?
            #    tgt_srs.SetMercator(dfCenterLat,dfCenterLon,0,0,0)
            else:  #Assume Geog
                units = 'deg'

        srs = tgt_srs.ExportToWkt()

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

        self.metadata['metadata'] = '\n'.join(
            ['%s: %s' % (m, hdf_md[m]) for m in hdf_md])

        self.metadata['satellite'] = 'Terra'
        self.metadata['sensor'] = 'ASTER'
        self.metadata['filetype'] = self._gdaldataset.GetDriver(
        ).ShortName + '/' + self._gdaldataset.GetDriver().LongName + ' (ASTER)'
        self.metadata['sceneid'] = hdf_md['ASTERSCENEID']
        self.metadata['level'] = hdf_md['PROCESSINGLEVELID']
        if '-' in hdf_md['CALENDARDATE']: imgdate = hdf_md['CALENDARDATE']
        else:
            imgdate = time.strftime(utilities.dateformat,
                                    time.strptime(hdf_md['CALENDARDATE'],
                                                  '%Y%m%d'))  #ISO 8601
        imgtime = hdf_md.get('TIMEOFDAY')
        if imgtime:
            self.metadata['imgdate'] = time.strftime(
                utilities.datetimeformat,
                time.strptime(imgdate + imgtime[0:6],
                              '%Y-%m-%d%H%M%S'))  #ISO 8601
        else:
            self.metadata['imgdate'] = imgdate
        #self.metadata['imgdate'] = hdf_md['CALENDARDATE']
        self.metadata['cloudcover'] = float(hdf_md['SCENECLOUDCOVERAGE'])
        if hdf_md['FLYINGDIRECTION'] == 'DE':
            self.metadata['orbit'] = 'Descending'
        else:
            self.metadata['orbit'] = 'Ascending'
        self.metadata['rotation'] = float(
            hdf_md.get('MAPORIENTATIONANGLE',
                       hdf_md.get('SCENEORIENTATIONANGLE')))
        if abs(self.metadata['rotation']) < 1.0:
            self.metadata['orientation'] = 'Map oriented'
        else:
            self.metadata['orientation'] = 'Path oriented'
        self.metadata['sunazimuth'], self.metadata['sunelevation'] = map(
            float, hdf_md['SOLARDIRECTION'].split(','))
        self.metadata['viewangle'] = float(hdf_md['POINTINGANGLE'])
        self.metadata['cols'] = ncols
        self.metadata['rows'] = nrows
        self.metadata['nbands'] = nbands
        self.metadata['datatype'] = datatypes
        self.metadata['nbits'] = nbits
        self.metadata['nodata'] = ','.join(['0' for i in range(0, nbands)])
        self.metadata['bands'] = bands
        self.metadata['resampling'] = hdf_md.get(
            'RESMETHOD1')  #Assume same for all...
        self.metadata['srs'] = srs
        self.metadata['epsg'] = spatialreferences.IdentifyAusEPSG(srs)
        self.metadata['units'] = units
        self.metadata['cellx'], self.metadata['celly'] = cellxy, cellxy

        #Geotransform
        ext = [[ulx, uly], [urx, ury], [lrx, lry], [llx, lly], [ulx, uly]]
        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(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
            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)

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

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

        self.metadata['metadata'] = '\n'.join(
            ['%s: %s' % (m, hdf_md[m]) for m in hdf_md])

        self.metadata['filesize'] = sum(
            [os.path.getsize(file) for file in self.filelist])
        self.metadata['compressionratio'] = 0
        self.metadata['compressiontype'] = 'None'
        self.extent = ext

        #Build gdaldataset object for overviews
        vrtcols = ncols[0]
        vrtrows = nrows[0]
        #vrtbands=[sd for sd,sn in hdf_sd[0:4]]#The 4 VNIR bands
        vrtbands = hdf_sd[0:4]  #The 4 VNIR bands
        vrt = geometry.CreateSimpleVRT(vrtbands, vrtcols, vrtrows,
                                       datatypes.split(',')[0])
        self._gdaldataset = geometry.OpenDataset(vrt)
        for i in range(1, 5):
            self._gdaldataset.GetRasterBand(i).SetNoDataValue(0)
Ejemplo n.º 4
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)