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