qualitymodis.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/usr/bin/env python
  2. # class to convert/process modis data
  3. #
  4. # (c) Copyright Ingmar Nitze 2013
  5. # Authors: Ingmar Nitze, Luca Delucchi
  6. # Email: initze at ucc dot ie
  7. # Email: luca dot delucchi at iasma dot it
  8. #
  9. ##################################################################
  10. #
  11. # This MODIS Python class is licensed under the terms of GNU GPL 2.
  12. # This program is free software; you can redistribute it and/or
  13. # modify it under the terms of the GNU General Public License as
  14. # published by the Free Software Foundation; either version 2 of
  15. # the License, or (at your option) any later version.
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  19. # See the GNU General Public License for more details.
  20. #
  21. ##################################################################
  22. """A class for the extraction and transformation of MODIS quality layers to
  23. specific information
  24. Classes:
  25. * :class:`QualityModis`
  26. """
  27. # python 2 and 3 compatibility
  28. from __future__ import print_function
  29. from builtins import dict
  30. import os
  31. try:
  32. import numpy as np
  33. except ImportError:
  34. raise ImportError('Numpy library not found, please install it')
  35. try:
  36. import osgeo.gdal as gdal
  37. import osgeo.gdal_array as gdal_array
  38. except ImportError:
  39. try:
  40. import gdal
  41. import gdal_array
  42. except ImportError:
  43. raise ImportError('Python GDAL library not found, please install '
  44. 'python-gdal')
  45. VALIDTYPES = dict({'13': list(map(str, list(range(1, 10)))), '11': list(map(str, list(range(1, 6))))})
  46. PRODUCTPROPS = dict({
  47. 'MOD13Q1': ([2], ['QAGrp1']),
  48. 'MYD13Q1': ([2], ['QAGrp1']),
  49. 'MOD13A1': ([2], ['QAGrp1']),
  50. 'MYD13A1': ([2], ['QAGrp1']),
  51. 'MOD13A2': ([2], ['QAGrp1']),
  52. 'MYD13A2': ([2], ['QAGrp1']),
  53. 'MOD13A3': ([2], ['QAGrp1']),
  54. 'MYD13A3': ([2], ['QAGrp1']),
  55. 'MOD13C1': ([2], ['QAGrp1']),
  56. 'MYD13C1': ([2], ['QAGrp1']),
  57. 'MOD13C2': ([2], ['QAGrp1']),
  58. 'MYD13C2': ([2], ['QAGrp1']),
  59. 'MOD11A1': ([1, 5], ['QAGrp2', 'QAGrp2']),
  60. 'MYD11A1': ([1, 5], ['QAGrp2', 'QAGrp2']),
  61. 'MOD11A2': ([1, 5], ['QAGrp4', 'QAGrp4']),
  62. 'MYD11A2': ([1, 5], ['QAGrp4', 'QAGrp4']),
  63. 'MOD11B1': ([1, 5, -2], ['QAGrp2', 'QAGrp2', 'QAGrp3']),
  64. 'MYD11B1': ([1, 5, -2], ['QAGrp2', 'QAGrp2', 'QAGrp3']),
  65. 'MOD11C1': ([1, 5, -2], ['QAGrp2', 'QAGrp2', 'QAGrp3']),
  66. 'MYD11C1': ([1, 5, -2], ['QAGrp2', 'QAGrp2', 'QAGrp3']),
  67. 'MOD11C2': ([1, 6], ['QAGrp2', 'QAGrp2']),
  68. 'MYD11C2': ([1, 6], ['QAGrp2', 'QAGrp2']),
  69. 'MOD11C3': ([1, 6], ['QAGrp2', 'QAGrp2']),
  70. 'MYD11C3': ([1, 6], ['QAGrp2', 'QAGrp2'])
  71. })
  72. QAindices = dict({
  73. 'QAGrp1': (16, [[-2, None], [-6, -2], [-8, -6], [-9, -8],
  74. [-10, -9], [-11, -10], [-14, -11], [-15, -14],
  75. [-16, -15]]),
  76. 'QAGrp2': (7, [[-2, None], [-3, -2], [-4, -3], [-6, -4],
  77. [-8, -6]]),
  78. 'QAGrp3': (7, [[-3, None], [-6, -3], [-7, -6]]),
  79. 'QAGrp4': (8, [[-2, None], [-4, -2], [-6, -4], [-8, -6]])
  80. })
  81. class QualityModis():
  82. """A Class for the extraction and transformation of MODIS
  83. quality layers to specific information
  84. :param str infile: the full path to the hdf file
  85. :param str outfile: the full path to the parameter file
  86. """
  87. def __init__(self, infile, outfile, qType=None, qLayer=None, pType=None):
  88. """Function to initialize the object"""
  89. self.infile = infile
  90. self.outfile = outfile
  91. self.qType = qType
  92. self.qLayer = qLayer
  93. self.qaGroup = None
  94. self.pType = pType
  95. def loadData(self):
  96. """loads the input file to the object"""
  97. os.path.isfile(self.infile)
  98. self.ds = gdal.Open(self.infile)
  99. def setProductType(self):
  100. """read productType from Metadata of hdf file"""
  101. if self.pType == None:
  102. self.productType = self.ds.GetMetadata()['SHORTNAME']
  103. else:
  104. self.productType = self.pType
  105. def setProductGroup(self):
  106. """read productGroup from Metadata of hdf file"""
  107. self.productGroup = self.productType[3:5]
  108. def setQAGroup(self):
  109. """set QA dataset group type"""
  110. if self.productType in list(PRODUCTPROPS.keys()):
  111. self.qaGroup = PRODUCTPROPS[self.productType][1][int(self.qLayer)-1]
  112. else:
  113. print("Product version is currently not supported!")
  114. def setQALayer(self):
  115. """function sets the input path of the designated QA layer"""
  116. self.qaLayer = self.ds.GetSubDatasets()[PRODUCTPROPS[self.productType][0][int(self.qLayer)-1]][0]
  117. def loadQAArray(self):
  118. """loads the QA layer to the object"""
  119. self.qaArray = gdal_array.LoadFile(self.qaLayer)
  120. def qualityConvert(self, modisQaValue):
  121. """converts encoded Bit-Field values to designated QA information"""
  122. startindex = QAindices[self.qaGroup][1][int(self.qType)-1][0]
  123. endindex = QAindices[self.qaGroup][1][int(self.qType)-1][1]
  124. return int(np.binary_repr(modisQaValue, QAindices[self.qaGroup][0])[startindex: endindex], 2)
  125. def exportData(self):
  126. """writes calculated QA values to physical .tif file"""
  127. qaDS = gdal.Open(self.qaLayer)
  128. dr = gdal.GetDriverByName('GTiff')
  129. outds = dr.Create(self.outfile, self.ncols, self.nrows, 1, gdal.GDT_Byte)
  130. outds.SetProjection(qaDS.GetProjection())
  131. outds.SetGeoTransform(qaDS.GetGeoTransform())
  132. outds.GetRasterBand(1).WriteArray(self.qaOut)
  133. outds = None
  134. qaDS = None
  135. def run(self):
  136. """Function defines the entire process"""
  137. self.loadData()
  138. self.setProductType()
  139. self.setProductGroup()
  140. #self.setDSversion()
  141. self.setQAGroup()
  142. self.setQALayer()
  143. self.loadQAArray()
  144. self.nrows, self.ncols = self.qaArray.shape
  145. print("Conversion started !")
  146. self.qaOut = np.zeros_like(self.qaArray, dtype=np.int8)
  147. if self.productGroup in ['11', '13'] and self.qType in VALIDTYPES[self.productGroup] and self.qaGroup != None:
  148. for val in np.unique(self.qaArray):
  149. ind = np.where(self.qaArray == val)
  150. self.qaOut[ind] = self.qualityConvert(self.qaArray[ind][0])
  151. self.exportData()
  152. print("Export finished!")
  153. else:
  154. print("This MODIS type is currently not supported.")