i.oif.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #!/usr/bin/env python
  2. ############################################################################
  3. #
  4. # MODULE: i.oif
  5. # AUTHOR(S): Markus Neteler
  6. # Converted to Python by Glynn Clements
  7. # PURPOSE: calculates the Optimum Index factor of all band combinations
  8. # for LANDSAT TM 1,2,3,4,5,7
  9. # COPYRIGHT: (C) 1999,2008 by the GRASS Development Team
  10. #
  11. # This program is free software under the GNU General Public
  12. # License (>=v2). Read the file COPYING that comes with GRASS
  13. # for details.
  14. #
  15. #############################################################################
  16. # Ref.: Jensen: Introductory digital image processing 1996, p.98
  17. #
  18. # Input: tm1 - tm5, tm7 (not tm6)
  19. #
  20. # written by Markus Neteler 21.July 1998
  21. # neteler geog.uni-hannover.de
  22. # updated for GRASS 5.7 by Michael Barton 2004/04/05
  23. #% Module
  24. #% description: Calculates Optimum-Index-Factor table for LANDSAT TM bands 1-5, & 7
  25. #% keywords: imagery
  26. #% keywords: landsat
  27. #% keywords: statistics
  28. #% End
  29. #% option G_OPT_R_INPUT
  30. #% key: image1
  31. #% description: LANDSAT TM band 1.
  32. #% end
  33. #% option G_OPT_R_INPUT
  34. #% key: image2
  35. #% description: LANDSAT TM band 2.
  36. #% end
  37. #% option G_OPT_R_INPUT
  38. #% key: image3
  39. #% description: LANDSAT TM band 3.
  40. #% end
  41. #% option G_OPT_R_INPUT
  42. #% key: image4
  43. #% description: LANDSAT TM band 4.
  44. #% end
  45. #% option G_OPT_R_INPUT
  46. #% key: image5
  47. #% description: LANDSAT TM band 5.
  48. #% end
  49. #% option G_OPT_R_INPUT
  50. #% key: image7
  51. #% description: LANDSAT TM band 7.
  52. #% end
  53. #% Flag
  54. #% key: g
  55. #% description: Print in shell script style
  56. #% End
  57. #% Flag
  58. #% key: s
  59. #% description: Process bands serially (default: run in parallel)
  60. #% End
  61. import sys
  62. import os
  63. from grass.script import core as grass
  64. bands = [1,2,3,4,5,7]
  65. def oifcalc(sdev, corr, k1, k2, k3):
  66. # calculate SUM of Stddeviations:
  67. ssdev = [sdev[k1], sdev[k2], sdev[k3]]
  68. numer = sum(ssdev)
  69. # calculate SUM of absolute(Correlation values):
  70. scorr = [corr[k1,k2], corr[k1,k3], corr[k2,k3]]
  71. denom = sum(map(abs, scorr))
  72. # Calculate OIF index:
  73. # Divide (SUM of Stddeviations) and (SUM of Correlation)
  74. return numer / denom
  75. def perms():
  76. for i in range(0,4):
  77. for j in range(i+1,5):
  78. for k in range(j+1,6):
  79. yield (bands[i], bands[j], bands[k])
  80. def main():
  81. shell = flags['g']
  82. serial = flags['s']
  83. image = {}
  84. for band in bands:
  85. image[band] = options['image%d' % band]
  86. # calculate the Stddev for TM bands
  87. grass.message(_("Calculating Standard deviations for all bands..."))
  88. stddev = {}
  89. if serial:
  90. for band in bands:
  91. grass.verbose("band %d" % band)
  92. s = grass.read_command('r.univar', flags = 'g', map = image[band])
  93. kv = grass.parse_key_val(s)
  94. stddev[band] = float(kv['stddev'])
  95. else:
  96. # run all bands in parallel
  97. if "WORKERS" in os.environ:
  98. workers = int(os.environ["WORKERS"])
  99. else:
  100. workers = 6
  101. proc = {}
  102. pout = {}
  103. # spawn jobs in the background
  104. for band in bands:
  105. grass.debug("band %d, <%s> %% %d" % (band, image[band], band % workers))
  106. proc[band] = grass.pipe_command('r.univar', flags = 'g', map = image[band])
  107. if band % workers is 0:
  108. # wait for the ones launched so far to finish
  109. for bandp in bands[:band]:
  110. if not proc[bandp].stdout.closed:
  111. pout[bandp] = proc[bandp].communicate()[0]
  112. proc[bandp].wait()
  113. # wait for jobs to finish, collect the output
  114. for band in bands:
  115. if not proc[band].stdout.closed:
  116. pout[band] = proc[band].communicate()[0]
  117. proc[band].wait()
  118. # parse the results
  119. for band in bands:
  120. kv = grass.parse_key_val(pout[band])
  121. stddev[band] = float(kv['stddev'])
  122. grass.message(_("Calculating Correlation Matrix..."))
  123. correlation = {}
  124. s = grass.read_command('r.covar', flags = 'r', map = [image[band] for band in bands])
  125. for i, row in zip(bands, s.splitlines()):
  126. for j, cell in zip(bands, row.split(' ')):
  127. correlation[i,j] = float(cell)
  128. # Calculate all combinations
  129. grass.message(_("Calculating OIF for the 20 band combinations..."))
  130. oif = []
  131. for p in perms():
  132. oif.append((oifcalc(stddev, correlation, *p), p))
  133. oif.sort(reverse = True)
  134. grass.verbose(_("The Optimum Index Factor analysis result "
  135. "(Best combination comes first):"))
  136. if shell:
  137. fmt = "%d%d%d:%.4f\n"
  138. else:
  139. fmt = "%d%d%d: %.4f\n"
  140. outf = file('i.oif.result', 'w')
  141. for v, p in oif:
  142. sys.stdout.write(fmt % (p + (v,)))
  143. outf.write(fmt % (p + (v,)))
  144. outf.close()
  145. if __name__ == "__main__":
  146. options, flags = grass.parser()
  147. main()