r.regression.line.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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
  20. #% keywords: statistics
  21. #%End
  22. #%flag
  23. #% key: g
  24. #% description: Print in shell script style
  25. #%End
  26. #%flag
  27. #% key: s
  28. #% description: Slower but accurate (applies to FP maps only)
  29. #%End
  30. #%option
  31. #% key: map1
  32. #% type: string
  33. #% gisprompt: old,cell,raster
  34. #% description: Map for x coefficient
  35. #% required : yes
  36. #%end
  37. #%option
  38. #% key: map2
  39. #% type: string
  40. #% gisprompt: old,cell,raster
  41. #% description: Map for y coefficient
  42. #% required : yes
  43. #%end
  44. #%option
  45. #% key: output
  46. #% type: string
  47. #% gisprompt: new_file,file,output
  48. #% description: ASCII file for storing regression coefficients (output to screen if file not specified).
  49. #% required : no
  50. #%end
  51. import sys
  52. import os
  53. import math
  54. from grass.script import core as grass
  55. def main():
  56. shell = flags['g']
  57. slow = flags['s']
  58. map1 = options['map1']
  59. map2 = options['map2']
  60. output = options['output']
  61. if not grass.find_file(map1)['name']:
  62. grass.fatal(_("Raster map <%s> not found") % map1)
  63. if not grass.find_file(map2)['name']:
  64. grass.fatal(_("Raster map <%s> not found") % map2)
  65. #calculate regression equation
  66. if slow:
  67. # slower but accurate
  68. statsflags = 'n1'
  69. # | sed 's+$+ 1+g' > "$TMP"
  70. else:
  71. # count "identical" pixels
  72. statsflags = 'cnA'
  73. p = grass.pipe_command('r.stats', flags = statsflags, input = (map1, map2))
  74. tot = sumX = sumsqX = sumY = sumsqY = sumXY = 0.0
  75. for line in p.stdout:
  76. line = line.rstrip('\r\n')
  77. if slow:
  78. line += ' 1'
  79. f = line.split(' ')
  80. if len(f) != 3:
  81. continue
  82. x = float(f[0])
  83. y = float(f[1])
  84. n = float(f[2])
  85. tot += n
  86. sumX += n * x
  87. sumsqX += n * x * x
  88. sumY += n * y
  89. sumsqY += n * y * y
  90. sumXY += n * x * y
  91. p.wait()
  92. B = (sumXY - sumX*sumY/tot)/(sumsqX - sumX*sumX/tot)
  93. R = (sumXY - sumX*sumY/tot)/math.sqrt((sumsqX - sumX*sumX/tot)*(sumsqY - sumY*sumY/tot))
  94. mediaX = sumX/tot
  95. sumsqX = sumsqX/tot
  96. varX = sumsqX-(mediaX*mediaX)
  97. sdX = math.sqrt(varX)
  98. mediaY = sumY/tot
  99. sumsqY = sumsqY/tot
  100. varY = sumsqY-(mediaY*mediaY)
  101. sdY = math.sqrt(varY)
  102. A = mediaY - B*mediaX
  103. F = R*R/(1-R*R/tot-2)
  104. vars = dict(
  105. a = A,
  106. b = B,
  107. R = R,
  108. N = tot,
  109. F = F,
  110. medX = mediaX,
  111. sdX = sdX,
  112. medY = mediaY,
  113. sdY = sdY)
  114. keys = ['a', 'b', 'R', 'N', 'F', 'medX', 'sdX', 'medY', 'sdY']
  115. #send output to screen or text file
  116. if output:
  117. fh = file(output, 'w')
  118. else:
  119. fh = sys.stdout
  120. if shell:
  121. for k, v in vars.iteritems():
  122. fh.write('%s=%f\n' % (k, v))
  123. else:
  124. lines = [
  125. "y = a + b*x",
  126. " a: offset",
  127. " b: gain",
  128. " R: sumXY - sumX*sumY/tot",
  129. " N: number of elements",
  130. " medX, medY: Means",
  131. " sdX, sdY: Standard deviations",
  132. ' '.join(keys),
  133. ]
  134. fh.write('\n'.join(lines) + '\n')
  135. fh.write(' '.join([str(vars[k]) for k in keys]) + '\n')
  136. if __name__ == "__main__":
  137. options, flags = grass.parser()
  138. main()