r.regression.line.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #!/usr/bin/env python
  2. #
  3. ############################################################################
  4. #
  5. # MODULE: r.regression line
  6. # AUTHOR(S): Dr. Agustin Lobo - alobo@ija.csic.es
  7. # Updated to GRASS 5.7 by Michael Barton
  8. # Converted to Python by Glynn Clements
  9. # PURPOSE: Calculates linear regression from two raster maps: y = a + b*x
  10. # COPYRIGHT: (C) 2004 by the GRASS Development Team
  11. #
  12. # This program is free software under the GNU General Public
  13. # License (>=v2). Read the file COPYING that comes with GRASS
  14. # for details.
  15. #
  16. #############################################################################
  17. #%Module
  18. #% description: Calculates linear regression from two raster maps: y = a + b*x
  19. #% keywords: raster, statistics
  20. #%End
  21. #%flag
  22. #% key: g
  23. #% description: Print in shell script style
  24. #%End
  25. #%flag
  26. #% key: s
  27. #% description: Slower but accurate (applies to FP maps only)
  28. #%End
  29. #%option
  30. #% key: map1
  31. #% type: string
  32. #% gisprompt: old,cell,raster
  33. #% description: Map for x coefficient
  34. #% required : yes
  35. #%end
  36. #%option
  37. #% key: map2
  38. #% type: string
  39. #% gisprompt: old,cell,raster
  40. #% description: Map for y coefficient
  41. #% required : yes
  42. #%end
  43. #%option
  44. #% key: output
  45. #% type: string
  46. #% gisprompt: new_file,file,output
  47. #% description: ASCII file for storing regression coefficients (output to screen if file not specified).
  48. #% required : no
  49. #%end
  50. import sys
  51. import os
  52. import math
  53. from grass.script import core as grass
  54. def main():
  55. shell = flags['g']
  56. slow = flags['s']
  57. map1 = options['map1']
  58. map2 = options['map2']
  59. output = options['output']
  60. if not grass.find_file(map1)['name']:
  61. grass.fatal("Raster map <%s> not found" % map1)
  62. if not grass.find_file(map2)['name']:
  63. grass.fatal("Raster map <%s> not found" % map2)
  64. #calculate regression equation
  65. if slow:
  66. # slower but accurate
  67. statsflags = 'n1'
  68. # | sed 's+$+ 1+g' > "$TMP"
  69. else:
  70. # count "identical" pixels
  71. statsflags = 'cnA'
  72. p = grass.pipe_command('r.stats', flags = statsflags, input = (map1, map2))
  73. tot = sumX = sumsqX = sumY = sumsqY = sumXY = 0.0
  74. for line in p.stdout:
  75. line = line.rstrip('\r\n')
  76. if slow:
  77. line += ' 1'
  78. f = line.split(' ')
  79. if len(f) != 3:
  80. continue
  81. x = float(f[0])
  82. y = float(f[1])
  83. n = float(f[2])
  84. tot += n
  85. sumX += n * x
  86. sumsqX += n * x * x
  87. sumY += n * y
  88. sumsqY += n * y * y
  89. sumXY += n * x * y
  90. p.wait()
  91. B = (sumXY - sumX*sumY/tot)/(sumsqX - sumX*sumX/tot)
  92. R = (sumXY - sumX*sumY/tot)/math.sqrt((sumsqX - sumX*sumX/tot)*(sumsqY - sumY*sumY/tot))
  93. mediaX = sumX/tot
  94. sumsqX = sumsqX/tot
  95. varX = sumsqX-(mediaX*mediaX)
  96. sdX = math.sqrt(varX)
  97. mediaY = sumY/tot
  98. sumsqY = sumsqY/tot
  99. varY = sumsqY-(mediaY*mediaY)
  100. sdY = math.sqrt(varY)
  101. A = mediaY - B*mediaX
  102. F = R*R/(1-R*R/tot-2)
  103. vars = dict(
  104. a = A,
  105. b = B,
  106. R = R,
  107. N = tot,
  108. F = F,
  109. medX = mediaX,
  110. sdX = sdX,
  111. medY = mediaY,
  112. sdY = sdY)
  113. keys = ['a', 'b', 'R', 'N', 'F', 'medX', 'sdX', 'medY', 'sdY']
  114. #send output to screen or text file
  115. if output:
  116. fh = file(output, 'w')
  117. else:
  118. fh = sys.stdout
  119. if shell:
  120. for k, v in vars.iteritems():
  121. fh.write('%s=%f\n' % (k, v))
  122. else:
  123. lines = [
  124. "y = a + b*x",
  125. " a: offset",
  126. " b: gain",
  127. " R: sumXY - sumX*sumY/tot",
  128. " N: number of elements",
  129. " medX, medY: Means",
  130. " sdX, sdY: Standard deviations",
  131. ' '.join(keys),
  132. ]
  133. fh.write('\n'.join(lines) + '\n')
  134. fh.write(' '.join([str(vars[k]) for k in keys]) + '\n')
  135. if __name__ == "__main__":
  136. options, flags = grass.parser()
  137. main()