i.in.spotvgt.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #!/usr/bin/env python3
  2. ############################################################################
  3. #
  4. # MODULE: i.in.spot
  5. #
  6. # AUTHOR(S): Markus Neteler
  7. # Converted to Python by Glynn Clements
  8. #
  9. # PURPOSE: Import SPOT VEGETATION data into a GRASS raster map
  10. # SPOT Vegetation (1km, global) data:
  11. # http://free.vgt.vito.be/
  12. #
  13. # COPYRIGHT: (c) 2004-2011 GRASS Development Team
  14. #
  15. # This program is free software under the GNU General Public
  16. # License (>=v2). Read the file COPYING that comes with GRASS
  17. # for details.
  18. #
  19. #############################################################################
  20. #
  21. # REQUIREMENTS:
  22. # - gdal: http://www.gdal.org
  23. #
  24. # Notes:
  25. # * According to the faq (http://www.vgt.vito.be/faq/faq.html), SPOT vegetation
  26. # coordinates refer to the center of a pixel.
  27. # * GDAL coordinates refer to the corner of a pixel
  28. # -> correction of 0001/0001_LOG.TXT coordinates by 0.5 pixel
  29. #############################################################################
  30. # %module
  31. # % description: Imports SPOT VGT NDVI data into a raster map.
  32. # % keyword: imagery
  33. # % keyword: import
  34. # % keyword: NDVI
  35. # % keyword: SPOT
  36. # %end
  37. # %flag
  38. # % key: a
  39. # % description: Also import quality map (SM status map layer) and filter NDVI map
  40. # %end
  41. # %option G_OPT_F_INPUT
  42. # % description: Name of input SPOT VGT NDVI HDF file
  43. # %end
  44. # % option G_OPT_R_OUTPUT
  45. # % required : no
  46. # %end
  47. import os
  48. import atexit
  49. import string
  50. import grass.script as gscript
  51. from grass.exceptions import CalledModuleError
  52. vrt = """<VRTDataset rasterXSize="$XSIZE" rasterYSize="$YSIZE">
  53. <SRS>GEOGCS[&quot;wgs84&quot;,DATUM[&quot;WGS_1984&quot;,SPHEROID[&quot;wgs84&quot;,6378137,298.257223563],TOWGS84[0.000,0.000,0.000]],PRIMEM[&quot;Greenwich&quot;,0],UNIT[&quot;degree&quot;,0.0174532925199433]]</SRS>
  54. <GeoTransform>$WESTCORNER, $RESOLUTION, 0.0000000000000000e+00, $NORTHCORNER, 0.0000000000000e+00, -$RESOLUTION</GeoTransform>
  55. <VRTRasterBand dataType="Byte" band="1">
  56. <NoDataValue>0.00000000000000E+00</NoDataValue>
  57. <ColorInterp>Gray</ColorInterp>
  58. <SimpleSource>
  59. <SourceFilename>$FILENAME</SourceFilename>
  60. <SourceBand>1</SourceBand>
  61. <SrcRect xOff="0" yOff="0" xSize="$XSIZE" ySize="$YSIZE"/>
  62. <DstRect xOff="0" yOff="0" xSize="$XSIZE" ySize="$YSIZE"/>
  63. </SimpleSource>
  64. </VRTRasterBand>
  65. </VRTDataset>"""
  66. # a function for writing VRT files
  67. def create_VRT_file(projfile, vrtfile, infile):
  68. fh = open(projfile)
  69. kv = {}
  70. for line in fh:
  71. f = line.rstrip("\r\n").split()
  72. if f < 2:
  73. continue
  74. kv[f[0]] = f[1]
  75. fh.close()
  76. north_center = kv["CARTO_UPPER_LEFT_Y"]
  77. # south_center = kv['CARTO_LOWER_LEFT_Y']
  78. # east_center = kv['CARTO_UPPER_RIGHT_X']
  79. west_center = kv["CARTO_UPPER_LEFT_X"]
  80. map_proj_res = kv["MAP_PROJ_RESOLUTION"]
  81. xsize = kv["IMAGE_UPPER_RIGHT_COL"]
  82. ysize = kv["IMAGE_LOWER_RIGHT_ROW"]
  83. resolution = float(map_proj_res)
  84. north_corner = float(north_center) + resolution / 2
  85. # south_corner = float(south_center) - resolution / 2
  86. # east_corner = float(east_center) + resolution / 2
  87. west_corner = float(west_center) - resolution / 2
  88. t = string.Template(vrt)
  89. s = t.substitute(
  90. NORTHCORNER=north_corner,
  91. WESTCORNER=west_corner,
  92. XSIZE=xsize,
  93. YSIZE=ysize,
  94. RESOLUTION=map_proj_res,
  95. FILENAME=infile,
  96. )
  97. outf = open(vrtfile, "w")
  98. outf.write(s)
  99. outf.close()
  100. def cleanup():
  101. # clean up the mess
  102. gscript.try_remove(vrtfile)
  103. gscript.try_remove(tmpfile)
  104. def main():
  105. global vrtfile, tmpfile
  106. infile = options["input"]
  107. rast = options["output"]
  108. also = flags["a"]
  109. # check for gdalinfo (just to check if installation is complete)
  110. if not gscript.find_program("gdalinfo", "--help"):
  111. gscript.fatal(
  112. _("'gdalinfo' not found, install GDAL tools first " "(http://www.gdal.org)")
  113. )
  114. pid = str(os.getpid())
  115. tmpfile = gscript.tempfile()
  116. # let's go
  117. spotdir = os.path.dirname(infile)
  118. spotname = gscript.basename(infile, "hdf")
  119. if rast:
  120. name = rast
  121. else:
  122. name = spotname
  123. if not gscript.overwrite() and gscript.find_file(name)["file"]:
  124. gscript.fatal(_("<%s> already exists. Aborting.") % name)
  125. # still a ZIP file? (is this portable?? see the r.in.srtm script for
  126. # ideas)
  127. if infile.lower().endswith(".zip"):
  128. gscript.fatal(_("Please extract %s before import.") % infile)
  129. try:
  130. p = gscript.Popen(["file", "-ib", infile], stdout=gscript.PIPE)
  131. s = p.communicate()[0]
  132. if s == "application/x-zip":
  133. gscript.fatal(_("Please extract %s before import.") % infile)
  134. except:
  135. pass
  136. # create VRT header for NDVI
  137. projfile = os.path.join(spotdir, "0001_LOG.TXT")
  138. vrtfile = tmpfile + ".vrt"
  139. # first process the NDVI:
  140. gscript.try_remove(vrtfile)
  141. create_VRT_file(projfile, vrtfile, infile)
  142. # let's import the NDVI map...
  143. gscript.message(_("Importing SPOT VGT NDVI map..."))
  144. try:
  145. gscript.run_command("r.in.gdal", input=vrtfile, output=name)
  146. except CalledModuleError:
  147. gscript.fatal(_("An error occurred. Stop."))
  148. gscript.message(_("Imported SPOT VEGETATION NDVI map <%s>.") % name)
  149. #################
  150. # http://www.vgt.vito.be/faq/FAQS/faq19.html
  151. # What is the relation between the digital number and the real NDVI ?
  152. # Real NDVI =coefficient a * Digital Number + coefficient b
  153. # = a * DN +b
  154. #
  155. # Coefficient a = 0.004
  156. # Coefficient b = -0.1
  157. # clone current region
  158. # switch to a temporary region
  159. gscript.use_temp_region()
  160. gscript.run_command("g.region", raster=name, quiet=True)
  161. gscript.message(_("Remapping digital numbers to NDVI..."))
  162. tmpname = "%s_%s" % (name, pid)
  163. gscript.mapcalc("$tmpname = 0.004 * $name - 0.1", tmpname=tmpname, name=name)
  164. gscript.run_command("g.remove", type="raster", name=name, quiet=True, flags="f")
  165. gscript.run_command("g.rename", raster=(tmpname, name), quiet=True)
  166. # write cmd history:
  167. gscript.raster_history(name)
  168. # apply color table:
  169. gscript.run_command("r.colors", map=name, color="ndvi", quiet=True)
  170. ##########################
  171. # second, optionally process the SM quality map:
  172. # SM Status Map
  173. # http://nieuw.vgt.vito.be/faq/FAQS/faq22.html
  174. # Data about
  175. # Bit NR 7: Radiometric quality for B0 coded as 0 if bad and 1 if good
  176. # Bit NR 6: Radiometric quality for B2 coded as 0 if bad and 1 if good
  177. # Bit NR 5: Radiometric quality for B3 coded as 0 if bad and 1 if good
  178. # Bit NR 4: Radiometric quality for MIR coded as 0 if bad and 1 if good
  179. # Bit NR 3: land code 1 or water code 0
  180. # Bit NR 2: ice/snow code 1 , code 0 if there is no ice/snow
  181. # Bit NR 1: 0 0 1 1
  182. # Bit NR 0: 0 1 0 1
  183. # clear shadow uncertain cloud
  184. #
  185. # Note:
  186. # pos 7 6 5 4 3 2 1 0 (bit position)
  187. # 128 64 32 16 8 4 2 1 (values for 8 bit)
  188. #
  189. #
  190. # Bit 4-7 should be 1: their sum is 240
  191. # Bit 3 land code, should be 1, sum up to 248 along with higher bits
  192. # Bit 2 ice/snow code
  193. # Bit 0-1 should be 0
  194. #
  195. # A good map threshold: >= 248
  196. if also:
  197. gscript.message(_("Importing SPOT VGT NDVI quality map..."))
  198. gscript.try_remove(vrtfile)
  199. qname = spotname.replace("NDV", "SM")
  200. qfile = os.path.join(spotdir, qname)
  201. create_VRT_file(projfile, vrtfile, qfile)
  202. # let's import the SM quality map...
  203. smfile = name + ".sm"
  204. try:
  205. gscript.run_command("r.in.gdal", input=vrtfile, output=smfile)
  206. except CalledModuleError:
  207. gscript.fatal(_("An error occurred. Stop."))
  208. # some of the possible values:
  209. rules = [
  210. r + "\n"
  211. for r in [
  212. "8 50 50 50",
  213. "11 70 70 70",
  214. "12 90 90 90",
  215. "60 grey",
  216. "155 blue",
  217. "232 violet",
  218. "235 red",
  219. "236 brown",
  220. "248 orange",
  221. "251 yellow",
  222. "252 green",
  223. ]
  224. ]
  225. gscript.write_command("r.colors", map=smfile, rules="-", stdin=rules)
  226. gscript.message(_("Imported SPOT VEGETATION SM quality map <%s>.") % smfile)
  227. gscript.message(
  228. _(
  229. "Note: A snow map can be extracted by category "
  230. "252 (d.rast %s cat=252)"
  231. )
  232. % smfile
  233. )
  234. gscript.message("")
  235. gscript.message(_("Filtering NDVI map by Status Map quality layer..."))
  236. filtfile = "%s_filt" % name
  237. gscript.mapcalc(
  238. "$filtfile = if($smfile % 4 == 3 || "
  239. "($smfile / 16) % 16 == 0, null(), $name)",
  240. filtfile=filtfile,
  241. smfile=smfile,
  242. name=name,
  243. )
  244. gscript.run_command("r.colors", map=filtfile, color="ndvi", quiet=True)
  245. gscript.message(_("Filtered SPOT VEGETATION NDVI map <%s>.") % filtfile)
  246. # write cmd history:
  247. gscript.raster_history(smfile)
  248. gscript.raster_history(filtfile)
  249. gscript.message(_("Done."))
  250. if __name__ == "__main__":
  251. options, flags = gscript.parser()
  252. atexit.register(cleanup)
  253. main()