PageRenderTime 55ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/nansatlite/mappers/mapper_landsat.py

https://gitlab.com/jobel-open-source/nansat-lite
Python | 160 lines | 148 code | 4 blank | 8 comment | 1 complexity | 803892b7e566f7024cbbeda6ab43f752 MD5 | raw file
  1. # Name: mapper_landsat
  2. # Purpose: Mapping for LANDSAT*.tar.gz
  3. # Authors: Anton Korosov
  4. # Licence: This file is part of NANSAT. You can redistribute it or modify
  5. # under the terms of GNU General Public License, v.3
  6. # http://www.gnu.org/licenses/gpl-3.0.html
  7. import os
  8. import glob
  9. import tarfile
  10. import warnings
  11. import datetime
  12. import json
  13. import pythesint as pti
  14. from nansat.tools import WrongMapperError, parse_time
  15. from nansat.tools import gdal, np
  16. from nansat.vrt import VRT
  17. class Mapper(VRT):
  18. ''' Mapper for LANDSAT5,6,7,8 .tar.gz or tif files'''
  19. def __init__(self, fileName, gdalDataset, gdalMetadata,
  20. resolution='low', **kwargs):
  21. ''' Create LANDSAT VRT from multiple tif files or single tar.gz file'''
  22. mtlFileName = ''
  23. bandFileNames = []
  24. bandSizes = []
  25. bandDatasets = []
  26. fname = os.path.split(fileName)[1]
  27. if (fileName.endswith('.tar') or
  28. fileName.endswith('.tar.gz') or
  29. fileName.endswith('.tgz')):
  30. # try to open .tar or .tar.gz or .tgz file with tar
  31. try:
  32. tarFile = tarfile.open(fileName)
  33. except:
  34. raise WrongMapperError
  35. # collect names of bands and corresponding sizes
  36. # into bandsInfo dict and bandSizes list
  37. tarNames = sorted(tarFile.getnames())
  38. for tarName in tarNames:
  39. # check if TIF files inside TAR qualify
  40. if (tarName[0] in ['L', 'M'] and
  41. os.path.splitext(tarName)[1] in ['.TIF', '.tif']):
  42. # open TIF file from TAR using VSI
  43. sourceFilename = '/vsitar/%s/%s' % (fileName, tarName)
  44. gdalDatasetTmp = gdal.Open(sourceFilename)
  45. # keep name, GDALDataset and size
  46. bandFileNames.append(sourceFilename)
  47. bandSizes.append(gdalDatasetTmp.RasterXSize)
  48. bandDatasets.append(gdalDatasetTmp)
  49. elif (tarName.endswith('MTL.txt') or
  50. tarName.endswith('MTL.TXT')):
  51. # get mtl file
  52. mtlFileName = tarName
  53. elif ((fname.startswith('L') or fname.startswith('M')) and
  54. (fname.endswith('.tif') or
  55. fname.endswith('.TIF') or
  56. fname.endswith('._MTL.txt'))):
  57. # try to find TIF/tif files with the same name as input file
  58. path, coreName = os.path.split(fileName)
  59. coreName = os.path.splitext(coreName)[0].split('_')[0]
  60. coreNameMask = coreName+'*[tT][iI][fF]'
  61. tifNames = sorted(glob.glob(os.path.join(path, coreNameMask)))
  62. for tifName in tifNames:
  63. sourceFilename = tifName
  64. gdalDatasetTmp = gdal.Open(sourceFilename)
  65. # keep name, GDALDataset and size
  66. bandFileNames.append(sourceFilename)
  67. bandSizes.append(gdalDatasetTmp.RasterXSize)
  68. bandDatasets.append(gdalDatasetTmp)
  69. # get mtl file
  70. mtlFiles = glob.glob(coreName+'*[mM][tT][lL].[tT][xX][tT]')
  71. if len(mtlFiles) > 0:
  72. mtlFileName = mtlFiles[0]
  73. else:
  74. raise WrongMapperError
  75. # if not TIF files found - not appropriate mapper
  76. if not bandFileNames:
  77. raise WrongMapperError
  78. # get appropriate band size based on number of unique size and
  79. # required resoltuion
  80. if resolution == 'low':
  81. bandXSise = min(bandSizes)
  82. elif resolution in ['high', 'hi']:
  83. bandXSise = max(bandSizes)
  84. else:
  85. raise OptionError('Wrong resolution %s for file %s' % (resolution, fileName))
  86. # find bands with appropriate size and put to metaDict
  87. metaDict = []
  88. for bandFileName, bandSize, bandDataset in zip(bandFileNames,
  89. bandSizes,
  90. bandDatasets):
  91. if bandSize == bandXSise:
  92. # let last part of file name be suffix
  93. bandSuffix = os.path.splitext(bandFileName)[0].split('_')[-1]
  94. metaDict.append({
  95. 'src': {'SourceFilename': bandFileName,
  96. 'SourceBand': 1,
  97. 'ScaleRatio': 0.1},
  98. 'dst': {'wkv': 'toa_outgoing_spectral_radiance',
  99. 'suffix': bandSuffix}})
  100. gdalDataset4Use = bandDataset
  101. # create empty VRT dataset with geolocation only
  102. VRT.__init__(self, gdalDataset4Use)
  103. # add bands with metadata and corresponding values to the empty VRT
  104. self._create_bands(metaDict)
  105. if len(mtlFileName) > 0:
  106. mtlFileName = os.path.join(os.path.split(bandFileNames[0])[0],
  107. mtlFileName)
  108. mtlFileLines = [line.strip() for line in
  109. self.read_xml(mtlFileName).split('\n')]
  110. dateString = [line.split('=')[1].strip()
  111. for line in mtlFileLines
  112. if ('DATE_ACQUIRED' in line or
  113. 'ACQUISITION_DATE' in line)][0]
  114. timeStr = [line.split('=')[1].strip()
  115. for line in mtlFileLines
  116. if ('SCENE_CENTER_TIME' in line or
  117. 'SCENE_CENTER_SCAN_TIME' in line)][0]
  118. time_start = parse_time(dateString + 'T' + timeStr).isoformat()
  119. time_end = (parse_time(dateString + 'T' + timeStr) +
  120. datetime.timedelta(microseconds=60000000)).isoformat()
  121. self.dataset.SetMetadataItem('time_coverage_start', time_start)
  122. self.dataset.SetMetadataItem('time_coverage_end', time_end)
  123. # set platform
  124. platform = 'LANDSAT'
  125. if fname[2].isdigit():
  126. platform += '-'+fname[2]
  127. ee = pti.get_gcmd_platform(platform)
  128. self.dataset.SetMetadataItem('platform', json.dumps(ee))
  129. # set instrument
  130. instrument = {
  131. 'LANDSAT' : 'MSS',
  132. 'LANDSAT-1' : 'MSS',
  133. 'LANDSAT-2' : 'MSS',
  134. 'LANDSAT-3' : 'MSS',
  135. 'LANDSAT-4' : 'TM',
  136. 'LANDSAT-5' : 'TM',
  137. 'LANDSAT-7' : 'ETM+',
  138. 'LANDSAT-8' : 'OLI'}[platform]
  139. ee = pti.get_gcmd_instrument(instrument)
  140. self.dataset.SetMetadataItem('instrument', json.dumps(ee))