gdalwarp.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. ############################################################################
  2. #
  3. # MODULE: r.in.wms / wms_gdalwarp.py
  4. #
  5. # AUTHOR(S): Cedric Shock, 2006
  6. # Update for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
  7. #
  8. # PURPOSE: To import data from web mapping servers
  9. # (based on Bash script by Cedric Shock)
  10. #
  11. # COPYRIGHT: (C) 2009 Martin Landa, and GRASS development team
  12. #
  13. # This program is free software under the GNU General
  14. # Public License (>=v2). Read the file COPYING that
  15. # comes with GRASS for details.
  16. #
  17. #############################################################################
  18. #
  19. # This file needs major rewrite...
  20. #
  21. import os
  22. import subprocess
  23. from grass.script import core as grass
  24. class GDALWarp:
  25. def __init__(self, flags, options):
  26. self.flags = flags
  27. self.options = options
  28. self.tmp = grass.tempfile()
  29. self.suffixes = []
  30. self.patches = []
  31. self.maplist = []
  32. self.tiler = 0
  33. if not flags['p']:
  34. # todo: check if gdalwarp is available
  35. pass
  36. # flags for r.in.gdal
  37. self.gdal_flags = ''
  38. if flags['e']:
  39. self.gdal_flags += 'e'
  40. if flags['k']:
  41. self.gdal_flags += 'k'
  42. def run(self):
  43. # import tiles
  44. tiler = 0
  45. for input in self.options['input'].split(','):
  46. tmptilename = self.options['output'] + '_tile_' + str(tiler)
  47. if not os.path.exists(input):
  48. grass.warning("Missing input '%s'" % input)
  49. continue
  50. grass.info("Importing tile '%s'..." % os.path.basename(input))
  51. if self.flags['p']:
  52. self.nowarp_import(input, tmptilename)
  53. else:
  54. self.warp_import(input, tmptilename)
  55. self.maplist.append(tmptilename)
  56. tiler += 1
  57. if tiler < 1:
  58. grass.message("Nothing imported")
  59. return 0
  60. # if there's more than one tile patch them together, otherwise
  61. # just rename that tile.
  62. if tiler == 1:
  63. if len(self.channel_suffixes) > 0:
  64. # multi-band
  65. for suffix in self.channel_suffixes:
  66. # rename tile 0 to be the output
  67. ffile = self.options['output'] + '_tile_0' + suffix
  68. tfile = self.options['output'] + suffix
  69. if grass.run_command('g.rename',
  70. quiet = True,
  71. rast = ffile + ',' + tfile) != 0:
  72. grass.fatal('g.rename failed')
  73. else: # single-band, single-tile
  74. ffile = self.options['output'] + '_tile_0' # + sfx ?
  75. tfile = self.options['output'] # + sfx ?
  76. if grass.run_command('g.rename',
  77. quiet = True,
  78. rast = ffile + ',' + tfile) != 0:
  79. grass.fatal('g.rename failed')
  80. else:
  81. # patch together each channel
  82. grass.debug('suffixes: %s' % ','.join(suffixes))
  83. if len(suffixes) > 0:
  84. # multi-band data
  85. for suffix in suffixes:
  86. suffix = suffix.replace('.', '_')
  87. # patch these together (using nulls only)
  88. grass.message("Patching '%s' channel..." % suffix)
  89. if grass.run_command('r.patch',
  90. quiet = True,
  91. input = patches, # ???
  92. output = self.options['output'] + suffix) != 0:
  93. grass.fatal('r.patch failed')
  94. # remove the temporary patches we made
  95. if grass.run_command('g.remove',
  96. quiet = True,
  97. rast = patches) != 0:
  98. grass.fatal('g.remove failed')
  99. else:
  100. # single-band data
  101. grass.info("Patching tiles (this may take some time)...")
  102. grass.debug("patch list = %s" % ','.join(maplist))
  103. # HACK: for 8bit PNG, GIF all the different tiles can have
  104. # different color tables so patches output end up all freaky.
  105. # r.mapcalc r#,g#,b# manual patching + r.composite?
  106. # or d.out.file + r.in.png + r.region?
  107. # *** there is a GDAL utility to do this: gdal_merge.py
  108. # http://www.gdal.org/gdal_merge.html
  109. for color in ('r', 'g', 'b'):
  110. maplist_color = []
  111. for map in maplist:
  112. outmap = map + '_' + color
  113. maplist_color.append(outmap)
  114. if grass.run_command('r.mapcalc',
  115. quiet = True,
  116. expression = '%s = %s#%s' % (outmap, color, map)) != 0:
  117. grass.fatal('r.mapcalc failed')
  118. if grass.run_command('r.colors',
  119. quiet = True,
  120. map = outmap,
  121. color = 'grey255') != 0:
  122. grass.fatal('r.colors failed')
  123. if grass.run_command('r.null',
  124. quiet = True,
  125. map = outmap,
  126. setnull = 255) != 0:
  127. grass.fatal('r.null failed')
  128. if grass.run_command('r.patch',
  129. input = ','.join(maplist_color),
  130. output = outmap + '_all') != 0:
  131. grass.fatal('r.patch failed')
  132. if grass.run_command('r.composite',
  133. quiet = True,
  134. red = map + '_r_all',
  135. green = map + '_g_all',
  136. blue = map + '_b_all',
  137. output = self.options['output']) != 0:
  138. grass.fatal('r.composite failed')
  139. if grass.run_command('g.mremove',
  140. quiet = True,
  141. flags = 'f',
  142. rast = map + '*') != 0:
  143. grass.fatal('g.remove failed')
  144. # there's already a no suffix, can't make colors
  145. # can only go up from here ;)
  146. colors = 0
  147. for suffix in self.suffixes:
  148. if suffix in ('.red', '.green', '.blue'):
  149. colors += 1
  150. # make a composite image if asked for and colors exist
  151. if colors == 3 and self.flags['c']:
  152. grass.message("Building color image <%s>..." % self.options['output'])
  153. if grass.run_command('r.composite',
  154. quiet = True,
  155. red = self.options['output'] + '.red',
  156. green = self.options['output'] + '.green',
  157. blue = self.options['output'] + '.blue',
  158. output = self.options['output']) != 0:
  159. grass.fatal('r.composite failed')
  160. return 0
  161. def warp_import(self, file, map):
  162. """Wrap raster file using gdalwarp and import wrapped file
  163. into GRASS"""
  164. warpfile = self.tmp + 'warped.geotiff'
  165. tmpmapname = map + '_tmp'
  166. t_srs = grass.read_command('g.proj',
  167. quiet = True,
  168. flags = 'jf').rstrip('\n')
  169. if not t_srs:
  170. grass.fatal('g.proj failed')
  171. grass.debug("gdalwarp -s_srs '%s' -t_srs '%s' -r %s %s %s %s" % \
  172. (self.options['srs'], t_srs,
  173. self.options['method'], self.options['warpoptions'],
  174. file, warpfile))
  175. grass.verbose("Warping input file '%s'..." % os.path.basename(file))
  176. if self.options['warpoptions']:
  177. ps = subprocess.Popen(['gdalwarp',
  178. '-s_srs', '%s' % self.options['srs'],
  179. '-t_srs', '%s' % t_srs,
  180. '-r', self.options['method'],
  181. self.options['warpoptions'],
  182. file, warpfile])
  183. else:
  184. ps = subprocess.Popen(['gdalwarp',
  185. '-s_srs', '%s' % self.options['srs'],
  186. '-t_srs', '%s' % t_srs,
  187. '-r', self.options['method'],
  188. file, warpfile])
  189. ps.wait()
  190. if ps.returncode != 0 or \
  191. not os.path.exists(warpfile):
  192. grass.fatal('gdalwarp failed')
  193. # import it into a temporary map
  194. grass.info('Importing raster map...')
  195. if grass.run_command('r.in.gdal',
  196. quiet = True,
  197. flags = self.gdal_flags,
  198. input = warpfile,
  199. output = tmpmapname) != 0:
  200. grass.fatal('r.in.gdal failed')
  201. os.remove(warpfile)
  202. # get list of channels
  203. pattern = tmpmapname + '*'
  204. grass.debug('Pattern: %s' % pattern)
  205. mapset = grass.gisenv()['MAPSET']
  206. channel_list = grass.mlist_grouped(type = 'rast', pattern = pattern, mapset = mapset)[mapset]
  207. grass.debug('Channel list: %s' % ','.join(channel_list))
  208. if len(channel_list) < 2: # test for single band data
  209. self.channel_suffixes = []
  210. else:
  211. self.channel_suffixes = channel_list # ???
  212. grass.debug('Channel suffixes: %s' % ','.join(self.channel_suffixes))
  213. # add to the list of all suffixes
  214. self.suffixes = self.suffixes + self.channel_suffixes
  215. self.suffixes.sort()
  216. # get last suffix
  217. if len(self.channel_suffixes) > 0:
  218. last_suffix = self.channel_suffixes[-1]
  219. else:
  220. last_suffix = ''
  221. # find the alpha layer
  222. if self.flags['k']:
  223. alphalayer = tmpmapname + last_suffix
  224. else:
  225. alphalayer = tmpmapname + '.alpha'
  226. # test to see if the alpha map exists
  227. if not grass.find_file(element = 'cell', name = alphalayer)['name']:
  228. alphalayer = ''
  229. # calculate the new maps:
  230. for suffix in self.channel_suffixes:
  231. grass.debug("alpha=%s MAPsfx=%s%s tmpname=%s%s" % \
  232. (alphalayer, map, suffix, tmpmapname, suffix))
  233. if alphalayer:
  234. # Use alpha channel for nulls: problem: I've seen a map
  235. # where alpha was 1-255; 1 being transparent. what to do?
  236. # (Geosci Australia Gold layer, format=tiff)
  237. if grass.run_command('r.mapcalc',
  238. quiet = True,
  239. expression = "%s%s = if(%s, %s%s, null())" % \
  240. (map, sfx, alphalayer, tmpmapname, sfx)) != 0:
  241. grass.fatal('r.mapcalc failed')
  242. else:
  243. if grass.run_command('g.copy',
  244. quiet = True,
  245. rast = "%s%s,%s%s" % \
  246. (tmpmapname, suffix, map, suffix)) != 0:
  247. grass.fatal('g.copy failed')
  248. # copy the color tables
  249. if grass.run_command('r.colors',
  250. quiet = True,
  251. map = map + suffix,
  252. rast = tmpmapname + suffix) != 0:
  253. grass.fatal('g.copy failed')
  254. # make patch lists
  255. suffix = suffix.replace('.', '_')
  256. # this is a hack to make the patch lists empty:
  257. if self.tiler == 0:
  258. self.patches = []
  259. self.patches = self.patches.append(map + suffix)
  260. # if no suffix, processing is simple (e.g. elevation has only 1
  261. # band)
  262. if len(channel_list) < 2:
  263. # run r.mapcalc to crop to region
  264. if grass.run_command('r.mapcalc',
  265. quiet = True,
  266. expression = "%s = %s" % \
  267. (map, tmpmapname)) != 0:
  268. grass.fatal('r.mapcalc failed')
  269. if grass.run_command('r.colors',
  270. quiet = True,
  271. map = map,
  272. rast = tmpmapname) != 0:
  273. grass.fatal('r.colors failed')
  274. # remove the old channels
  275. if grass.run_command('g.remove',
  276. quiet = True,
  277. rast = ','.join(channel_list)) != 0:
  278. grass.fatal('g.remove failed')
  279. def nowarp_import(self, file, map):
  280. """Import raster file into GRASS"""
  281. if grass.run_command('r.in.gdal',
  282. quiet = True,
  283. flags = 'o' + self.gdal_flags,
  284. input = file,
  285. output = map) != 0:
  286. grass.fatal('r.in.gdal failed')
  287. # get a list of channels:
  288. pattern = map + '*'
  289. grass.debug("pattern: %s" % ','.join(pattern))
  290. mapset = grass.gisenv()['MAPSET']
  291. channel_list = grass.mlist_grouped(type = 'rast', pattern = pattern, mapset = mapset)
  292. grass.debug("channel list: %s" % ','.join(channel_list))
  293. if len(channel_list) < 2:
  294. # test for single band data
  295. self.channel_suffixes = []
  296. else:
  297. self.channel_suffixes = channel_list # ???
  298. # add to the list of all suffixes:
  299. self.suffixes = self.suffixes + channel.suffixes
  300. self.suffixes.sort()
  301. for suffix in self.channel_suffixes:
  302. # make patch lists
  303. suffix = suffix.replace('.', '_')
  304. # this is a hack to make the patch lists empty
  305. if self.tiler == 0:
  306. self.patches = []
  307. self.patches = self.patches.append(map + suffix)