class_KdJamet.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import numpy as np
  4. import sys
  5. import os
  6. Sensor = {'idSEAWIFS' : 0, 'idMODIS' : 1, 'idMERIS' : 2}
  7. NBWL = 6
  8. class KdJamet:
  9. #
  10. # Input :
  11. # idSensor : valid values -> [idSEAWIFS, idMODIS, idMERIS]
  12. #
  13. def __init__(self, idSensor):
  14. self.sensor = idSensor
  15. try:
  16. self.lutpath = os.getenv('KD_LUTS_PATH')
  17. except:
  18. print "KD_LUT_PATH not set, add it to your environment variables"
  19. sys.exit()
  20. if Sensor.has_key(idSensor):
  21. self.init_variables()
  22. try:
  23. self.read_LUTs_Kd()
  24. except:
  25. print "Failed to read %s LUTs" % (idSensor[2:])
  26. raise
  27. sys.exit()
  28. else:
  29. print "invalid Sensor ID : %s" % (idSensor)
  30. # - METHODE init_variables ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  31. # Perceptron parameters setting and array initialization for each Sensor
  32. # --
  33. def init_variables(self):
  34. print "class KdJamet.init_variables Method"
  35. # =======================================================================================================
  36. # MERIS / OLCI
  37. # =======================================================================================================
  38. if self.sensor == 'idMERIS':
  39. self.WL = np.array([413, 443, 490, 510, 560, 665])
  40. # Variables definiton for network Rrs490/Rrs555 >= .85 -------------------------------------------------
  41. # hidden layer number
  42. self.rsup_NC=2
  43. # input data number
  44. self.rsup_NE=5
  45. # number of neuron in the first hidden layer
  46. self.rsup_NC1=7
  47. # number of neuron in the second hidden layer
  48. self.rsup_NC2=4
  49. # nb output
  50. self.rsup_NS=1
  51. # nb input + nb output*/
  52. self.rsup_NES=6
  53. # LUTs file names
  54. self.rsup_LUT_POIDS = "KdOLCI_poids_IOCCG_NOMAD_BOUM_ss_12_COASTCOLOUR_443_to_555_log_Kd_lambda_merge_seuil_15_angle_ascii_6x1_hh_7_4_switch_110416.sn"
  55. self.rsup_LUT_MOY = "Moy_KdOLCI_IOCCG_NOMAD_BOUM_ss_12_COASTCOLOUR_412_to_670_log_Kd_lambda_merge_seuil_15_angle_publi_ss_620.dat"
  56. self.rsup_LUT_ECART = "Ecart_KdOLCI_IOCCG_NOMAD_BOUM_ss_12_COASTCOLOUR_412_to_670_log_Kd_lambda_merge_seuil_15_angle_publi_ss_620.dat"
  57. # Variables definiton for network Variables definiton for network < .85 -----------------------------------
  58. # nombre de couches cachees - hidden layer number
  59. self.rinf_NC=2
  60. # input data number*/
  61. self.rinf_NE=6
  62. # number of neuron in the first hidden layer
  63. self.rinf_NC1=5
  64. # number of neuron in the second hidden layer
  65. self.rinf_NC2=5
  66. # nb output
  67. self.rinf_NS=1
  68. # nb input + nb output
  69. self.rinf_NES=7
  70. #LUTs file names
  71. self.rinf_LUT_POIDS = "KdOLCI_poids_IOCCG_NOMAD_BOUM_ss_12_COASTCOLOUR_443_to_670_log_Kd_lambda_merge_seuil_15_angle_ascii_6x1_hh_5_5_switch_110416.sn"
  72. self.rinf_LUT_MOY = "Moy_KdOLCI_IOCCG_NOMAD_BOUM_ss_12_COASTCOLOUR_412_to_670_log_Kd_lambda_merge_seuil_15_angle_publi_ss_620.dat"
  73. self.rinf_LUT_ECART = "Ecart_KdOLCI_IOCCG_NOMAD_BOUM_ss_12_COASTCOLOUR_412_to_670_log_Kd_lambda_merge_seuil_15_angle_publi_ss_620.dat"
  74. #LUTs arrays definition
  75. self.rsup_b1 = np.zeros((self.rsup_NC1), dtype=np.float64)
  76. self.rsup_b2 = np.zeros((self.rsup_NC2), dtype=np.float64)
  77. self.rsup_b3 = 0.
  78. self.rsup_w1 = np.zeros((self.rsup_NE,self.rsup_NC1), dtype=np.float64)
  79. self.rsup_w2 = np.zeros((self.rsup_NC1,self.rsup_NC2), dtype=np.float64)
  80. self.rsup_w3 = np.zeros((self.rsup_NC2), dtype=np.float64)
  81. self.rsup_moy = np.zeros((self.rsup_NES), dtype=np.float64)
  82. self.rsup_ecart = np.zeros((self.rsup_NES), dtype=np.float64)
  83. self.rinf_b1 = np.zeros((self.rinf_NC1), dtype=np.float64)
  84. self.rinf_b2 = np.zeros((self.rinf_NC2), dtype=np.float64)
  85. self.rinf_b3 = 0.
  86. self.rinf_w1 = np.zeros((self.rinf_NE,self.rinf_NC1), dtype=np.float64)
  87. self.rinf_w2 = np.zeros((self.rinf_NC1,self.rinf_NC2), dtype=np.float64)
  88. self.rinf_w3 = np.zeros((self.rinf_NC2), dtype=np.float64)
  89. self.rinf_moy = np.zeros((self.rinf_NES), dtype=np.float64)
  90. self.rinf_ecart = np.zeros((self.rinf_NES), dtype=np.float64)
  91. # =======================================================================================================
  92. # MODIS
  93. # =======================================================================================================
  94. if self.sensor == 'idMODIS':
  95. self.WL = np.array([412, 443, 488, 531, 547, 667])
  96. # =======================================================================================================
  97. # SEAWIFS
  98. # =======================================================================================================
  99. if self.sensor == 'idSEAWIFS':
  100. self.WL = np.array([412, 443, 490, 510, 555, 670])
  101. # -- METHODE read_LUTs_Kd ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  102. # perceptron weights LUTs reading
  103. # LUTS are expected to be located in environment variable : $KD_LUTS_PATH
  104. # --
  105. def read_LUTs_Kd(self):
  106. print "class KdJamet.read_LUTs_Kd Method"
  107. # ----------------------------------------------------------------------------------
  108. # < .85 weights settings
  109. print " class KdJamet.read_LUTs_Kd : read weights file for Rrs%d/Rrs%d < .85: %s/%s" % (self.WL[2], self.WL[4],self.lutpath, self.rinf_LUT_POIDS)
  110. weights = np.loadtxt( "%s/%s" % (self.lutpath, self.rinf_LUT_POIDS), skiprows=1)
  111. base = 0
  112. self.rinf_b1 = weights[base:base+self.rinf_NC1,2]
  113. base = base+self.rinf_NC1
  114. self.rinf_b2 = weights[base:base+self.rinf_NC2,2]
  115. base = base+self.rinf_NC2
  116. self.rinf_b3 = weights[base:base+self.rinf_NS,2]
  117. base = base+self.rinf_NS
  118. for i in range(self.rinf_NE):
  119. self.rinf_w1[i,:] = weights[base:base+self.rinf_NC1,2]
  120. base = base+self.rinf_NC1
  121. for i in range(self.rinf_NC1):
  122. self.rinf_w2[i,:] = weights[base:base+self.rinf_NC2,2]
  123. base = base+self.rinf_NC2
  124. self.rinf_w3 = weights[base:base+self.rinf_NC2,2]
  125. usedData = np.array([1,2,3,4,5,6,8])
  126. if self.sensor == 'idMODIS':
  127. usedData = np.array([1,2,3,4,6,7,9])
  128. print " class KdJamet.read_LUTs_Kd : read mean file : %s/%s" % (self.lutpath, self.rinf_LUT_MOY)
  129. moy = np.loadtxt( "%s/%s" % (self.lutpath, self.rinf_LUT_MOY))
  130. self.rinf_moy = moy[usedData]
  131. print " class KdJamet.read_LUTs_Kd : read ecart file : %s/%s" % (self.lutpath, self.rinf_LUT_ECART)
  132. ecart = np.loadtxt( "%s/%s" % (self.lutpath, self.rinf_LUT_ECART))
  133. self.rinf_ecart = ecart[usedData]
  134. # ----------------------------------------------------------------------------------
  135. # >= .85 weights settings
  136. print " class KdJamet.read_LUTs_Kd : read weights file for Rrs%d/Rrs%d >= .85: %s/%s" % (self.WL[2], self.WL[4], self.lutpath, self.rsup_LUT_POIDS)
  137. weights = np.loadtxt( "%s/%s" % (self.lutpath, self.rsup_LUT_POIDS), skiprows=1)
  138. base = 0
  139. self.rsup_b1 = weights[base:base+self.rsup_NC1,2]
  140. base = base+self.rsup_NC1
  141. self.rsup_b2 = weights[base:base+self.rsup_NC2,2]
  142. base = base+self.rsup_NC2
  143. self.rsup_b3 = weights[base:base+self.rsup_NS,2]
  144. base = base+self.rsup_NS
  145. for i in range(self.rsup_NE):
  146. self.rsup_w1[i,:] = weights[base:base+self.rsup_NC1,2]
  147. base = base+self.rsup_NC1
  148. for i in range(self.rsup_NC1):
  149. self.rsup_w2[i,:] = weights[base:base+self.rsup_NC2,2]
  150. base = base+self.rsup_NC2
  151. self.rsup_w3 = weights[base:base+self.rsup_NC2,2]
  152. usedData = np.array([1,2,3,4,6,8])
  153. if self.sensor == 'idMODIS':
  154. usedData = np.array([1,2,3,4,7,9])
  155. moy = np.loadtxt( "%s/%s" % (self.lutpath, self.rsup_LUT_MOY))
  156. self.rsup_moy = moy[usedData]
  157. ecart = np.loadtxt( "%s/%s" % (self.lutpath, self.rsup_LUT_ECART))
  158. self.rsup_ecart = ecart[usedData]
  159. # -- METHODE compute_allKd ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  160. # Kd computing at all Sensor used WaveLength
  161. # Inputs -
  162. # - indata : array[] [ Rrs443, Rrs490, Rrs510, Rrs55, Rrs665 ]
  163. # Output -
  164. # - return Kd[] at Sensor Wave Length
  165. # --
  166. def compute_allKd(self, inRrs):
  167. outKd = np.zeros(NBWL,dtype=np.float32)
  168. if inRrs[2] / inRrs[4] < .85 :
  169. indata = np.zeros(self.rinf_NE,dtype=np.float32)
  170. indata[0:self.rinf_NE-1] = inRrs[1:self.rinf_NE]
  171. idLambda = self.rinf_NE-1
  172. FLAGinf = True
  173. else:
  174. indata = np.zeros(self.rsup_NE,dtype=np.float32)
  175. indata[0:self.rsup_NE-1] = inRrs[1:self.rsup_NE]
  176. idLambda = self.rsup_NE-1
  177. FLAGinf = False
  178. inc = 0
  179. for wl in self.WL:
  180. indata[idLambda] = wl
  181. if FLAGinf == True:
  182. outKd[inc] = self.passe_avant_inf(indata)
  183. else:
  184. outKd[inc] = self.passe_avant_sup(indata)
  185. inc = inc+1
  186. return outKd
  187. # -- METHODE passe_avant_sup ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  188. # Kd computing for Rrs490/Rrs55 >= .85 at ONE WaveLength
  189. # Inputs -
  190. # - indata : array[rinf_NE] [ Rrs443, Rrs490, Rrs510, Rrs55, Lambda ]
  191. # Output -
  192. # - return y (Kd) at indata Wave Length
  193. # --
  194. def passe_avant_sup(self, indata):
  195. # Normalization
  196. x = ((2/3.) * (indata[:] - self.rsup_moy[0:self.rsup_NE])) / self.rsup_ecart[0:self.rsup_NE]
  197. a = np.zeros(self.rsup_NC1,dtype=np.float64)
  198. for i in range(self.rsup_NC1):
  199. for j in range(self.rsup_NE):
  200. a[i] = a[i] + x[j] * self.rsup_w1[j][i]
  201. a[:] = 1.715905*np.tanh((2./3.)*(a[:] + self.rsup_b1[:]))
  202. b = np.zeros(self.rsup_NC2,dtype=np.float64)
  203. for i in range(self.rsup_NC2):
  204. for j in range(self.rsup_NC1):
  205. b[i] = b[i] + a[j] * self.rsup_w2[j][i]
  206. b[:] = 1.715905*np.tanh((2./3.)*(b[:] + self.rsup_b2[:]))
  207. y = np.sum(b[:] * self.rsup_w3[:])
  208. # Denormalisation
  209. y = 1.5*(y + self.rsup_b3)*self.rsup_ecart[self.rsup_NES-1] + self.rsup_moy[self.rsup_NES-1]
  210. y = 10.**y
  211. return(y)
  212. # -- METHODE passe_avant_inf ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  213. # Kd computing for Rrs490/Rrs55 < .85 at ONE WaveLength
  214. # Inputs
  215. # - indata : array[rinf_NE] [ Rrs443, Rrs490, Rrs510, Rrs55, Rrs665, Lambda ]
  216. # Output -
  217. # - return y (Kd) at indata Wave Length
  218. # --
  219. def passe_avant_inf(self, indata):
  220. # Normalization
  221. x = ((2/3.) * (indata[:] - self.rinf_moy[0:self.rinf_NE])) / self.rinf_ecart[0:self.rinf_NE]
  222. a = np.zeros(self.rinf_NC1,dtype=np.float64)
  223. for i in range(self.rinf_NC1):
  224. for j in range(self.rinf_NE):
  225. a[i] = a[i] + x[j] * self.rinf_w1[j][i]
  226. a[:] = 1.715905*np.tanh((2./3.)*(a[:] + self.rinf_b1[:]))
  227. b = np.zeros(self.rinf_NC2,dtype=np.float64)
  228. for i in range(self.rinf_NC2):
  229. for j in range(self.rinf_NC1):
  230. b[i] = b[i] + a[j] * self.rinf_w2[j][i]
  231. b[:] = 1.715905*np.tanh((2./3.)*(b[:] + self.rinf_b2[:]))
  232. y = np.sum(b[:] * self.rinf_w3[:])
  233. # Denormalisation
  234. y = 1.5*(y + self.rinf_b3)*self.rinf_ecart[self.rinf_NES-1] + self.rinf_moy[self.rinf_NES-1]
  235. y = 10.**y
  236. return(y)