PageRenderTime 96ms CodeModel.GetById 19ms RepoModel.GetById 2ms app.codeStats 1ms

/beam-3dveglab-vlab/src/main/resources/auxdata/VLabImpl.py

https://github.com/anarisris/esa-beam
Python | 4461 lines | 4383 code | 25 blank | 53 comment | 25 complexity | f8677628c1450eb62c12d9bfef56fdc0 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. #
  2. # Copyright (C) 2010-2014 Netcetera Switzerland (info@netcetera.com)
  3. #
  4. # This program is free software; you can redistribute it and/or modify it
  5. # under the terms of the GNU General Public License as published by the Free
  6. # Software Foundation; either version 3 of the License, or (at your option)
  7. # any later version.
  8. # This program is distributed in the hope that it will be useful, but WITHOUT
  9. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. # more details.
  12. #
  13. # You should have received a copy of the GNU General Public License along
  14. # with this program; if not, see http://www.gnu.org/licenses/
  15. #
  16. # @(#) $Id: $
  17. #
  18. # Authors: Cyrill Schenkel, Daniel Kueckenbrink, Joshy Cyriac, Marcel Kessler, Jason Brazile
  19. #
  20. ##############################################################################
  21. # Three ways to run it:
  22. #
  23. # 1. embedded within the BEAM processor (normal case)
  24. #
  25. # 2. standalone tests - headless (either jython or python)
  26. #
  27. # jython -Dpython.path=jcommon-1.0.16.jar:jfreechart-1.0.13.jar VLabImpl.py
  28. # python VLabImpl.py
  29. #
  30. # 3. standalone with a 'fake' swing-based gui
  31. #
  32. # java -jar ${HOME}/beam-4.11/lib/jython-2.5.2.jar -Dvlab.fakebeam=1 -Dpython.path=${HOME}/beam-4.11/lib/jcommon-1.0.16.jar:${HOME}/beam-4.11/lib/jfreechart-1.0.13.jar VLabImpl.py
  33. #
  34. # Those BEAM-supplied jars can also be obtained like this:
  35. # wget -U "Mozilla/5.0" http://repo1.maven.org/maven2/jfree/jfreechart/1.0.13/jfreechart-1.0.13.jar
  36. # wget -U "Mozilla/5.0" http://repo1.maven.org/maven2/jfree/jcommon/1.0.16/jcommon-1.0.16.jar
  37. #
  38. #
  39. import sys, math, operator, array, time, struct
  40. from array import array
  41. class VLAB:
  42. """VLAB contains conf. constants, static utility methods, and test methods"""
  43. COPYRIGHT_INFO = 'Copyright (C) 2010-2014 Netcetera Switzerland (info@netcetera.com)'
  44. PROCESSOR_NAME = 'BEAM VLab Processor'
  45. PROCESSOR_SNAME = 'beam-vlab'
  46. REQUEST_TYPE = 'VLAB'
  47. UI_TITLE = 'VLab - Processor'
  48. VERSION_STRING = '1.0 (20 July 2014)'
  49. DEFAULT_LOG_PREFIX = 'vlab'
  50. LOGGER_NAME = 'beam.processor.vlab'
  51. D_PRODNAME = 'vlab_out.dim'
  52. P_CONDITION = '.condition'
  53. P_EXPRESSION = '.expression'
  54. P_OUTPUT = '.output'
  55. # NOTE: Once released, random number generation should NOT be reproducible
  56. CONF_RND_REPRODUCE = True
  57. JCB = 'JComboBox'
  58. JTF = 'JTextField'
  59. JTD = (JTF, False)
  60. K_LIBRAT = 'librat'
  61. K_DART = 'DART'
  62. K_DUMMY = 'dummy'
  63. K_LAEGERN = 'Laegern'
  64. K_THARANDT = 'Tharandt'
  65. K_RAMI = 'RAMI'
  66. K_USER_DEFINED = 'User defined (UserDefined.obj)'
  67. K_YES = 'Yes'
  68. K_NO = 'No'
  69. K_SENTINEL2 = 'MSI (Sentinel 2)'
  70. K_SENTINEL3 = 'OLCI (Sentinel 3)'
  71. K_MODIS = 'MODIS'
  72. K_MERIS = 'MERIS'
  73. K_LANDSAT_OLI = 'Landsat (OLI)'
  74. K_LANDSAT_ETM = 'Landsat (ETM)'
  75. K_RURAL = 'Rural'
  76. K_MARITIME = 'Maritime'
  77. K_URBAN = 'Urban'
  78. K_TROPOSPHERIC = 'Tropospheric'
  79. DBG = 'debug'
  80. INF = 'info'
  81. ERR = 'error'
  82. plst = []
  83. if sys.platform.startswith('java'):
  84. from java.util.logging import Logger
  85. from java.util.logging import FileHandler
  86. from java.util.logging import Level
  87. logger = Logger.getLogger(LOGGER_NAME)
  88. # comment these out
  89. # logfh = FileHandler('%s.log' % LOGGER_NAME)
  90. # logfh.setLevel(Level.FINEST)
  91. # logger.addHandler(logfh)
  92. else:
  93. import logging
  94. logger = logging.getLogger(LOGGER_NAME)
  95. logger.setLevel(logging.DEBUG)
  96. logch = logging.StreamHandler()
  97. logch.setLevel(logging.DEBUG)
  98. logger.addHandler(logch)
  99. # comment these out
  100. # logfh = logging.FileHandler('%s.log' % LOGGER_NAME)
  101. # logfh.setLevel(logging.DEBUG)
  102. # logger.addHander(logfh)
  103. model = (
  104. {'Forward Modeling': (
  105. {'Model Selection': (
  106. ('3D Scene', '3dScene', JCB, (K_RAMI, K_LAEGERN, K_THARANDT, K_USER_DEFINED)),
  107. ('RT Processor', 'RTProcessor', JCB, (K_DUMMY, K_LIBRAT, K_DART)))},
  108. {'Spectral Characteristics': (
  109. ('Sensor', 'Sensor', JCB, (K_SENTINEL2, K_SENTINEL3, K_MODIS, K_MERIS, K_LANDSAT_OLI, K_LANDSAT_ETM)),
  110. ('Bands', 'Bands', JTF, '1, 2, 3, 4, 5, 6, 7, 8, 9, 10'))},
  111. {'Viewing Characteristics': (
  112. ('Zenith', 'ViewingZenith', JTF, '20.0'),
  113. ('Azimuth', 'ViewingAzimuth', JTF, '0.0'))},
  114. {'Illumination Characteristics':(
  115. ('Zenith', 'IlluminationZenith', JTF, '20.0'),
  116. ('Azimuth', 'IlluminationAzimuth', JTF, '0.0'))},
  117. {'Scene Parameters': (
  118. ('Pixel Size', 'ScenePixel', JTD, 'not available yet'),
  119. ('(Alt A) Filename', 'SceneLocFile', JTD, 'not available yet'),
  120. ('(Alt B) XC', 'SceneXC', JTD, 'not available yet'),
  121. ('(Alt B) XW', 'SceneXW', JTD, 'not available yet'),
  122. ('(Alt B) YC', 'SceneYC', JTD, 'not available yet'),
  123. ('(Alt B) YW', 'SceneYW', JTD, 'not available yet'))},
  124. {'Atmospheric Parameters': (
  125. ('CO2 Mixing Ratio', 'AtmosphereCO2', JTF, '1.6'),
  126. ('Aerosol Profile', 'AtmosphereAerosol', JCB, (K_RURAL, K_MARITIME, K_URBAN, K_TROPOSPHERIC)),
  127. ('Water Vapor', 'AtmosphereWater', JTF, '0.0'),
  128. ('Ozone Column', 'AtmosphereOzone', JTF, '300'))},
  129. {'Output Parameters': (
  130. ('Result file prefix','OutputPrefix', JTF, 'HET01_DIS_UNI_NIR_20.obj'),
  131. ('Result Directory', 'OutputDirectory', JTF, 'dart.rpv.rami.2'),
  132. ('Image file', 'ImageFile', JCB, (K_YES, K_NO)),
  133. ('Ascii file', 'AsciiFile', JCB, (K_YES, K_NO)))}
  134. )},
  135. {'DHP Simulation': (
  136. {'Model Selection': (
  137. ('3D Scene', 'DHP_3dScene', JCB, (K_RAMI, K_LAEGERN, K_THARANDT)),
  138. (),
  139. ('Resolution', 'DHP_Resolution', JTF, '4000000'),
  140. ())},
  141. {'DHP Location': (
  142. ('X', 'DHP_X', JTD, 'not available yet'),
  143. ('Y', 'DHP_Y', JTD, 'not available yet'))},
  144. {'DHP Properties': (
  145. ('Zenith', 'DHP_Zenith', JTF, '0.0'),
  146. ('Azimuth', 'DHP_Azimuth', JTF, '0.0'))},
  147. {'DHP Imaging Plane': (
  148. ('Orientation', 'DHP_Orientation', JTD, 'not available yet'),
  149. ('Height(z)', 'DHP_Height', JTD, 'not available yet'))},
  150. {'Output Parameters': (
  151. ('Result file prefix','DHP_OutputPrefix', JTF, 'RAMI00_'),
  152. ('Result Directory', 'DHP_OutputDirectory', JTF, ''),
  153. ('Image file', 'DHP_ImageFile', JCB, (K_YES, K_NO)),
  154. ('Ascii file', 'DHP_AsciiFile', JCB, (K_YES, K_NO)))}
  155. )},
  156. )
  157. # set parameter names
  158. for tabGroups in model:
  159. for tabName in tabGroups:
  160. for group in tabGroups[tabName]:
  161. for groupName in group:
  162. for groupTuple in group[groupName]:
  163. if len(groupTuple) == 4:
  164. (lbl, nm, typ, vals) = groupTuple
  165. exec('P_' + nm + ' = nm')
  166. exec('L_' + nm + ' = lbl')
  167. plst.append(nm)
  168. def __init__(self):
  169. self.cmap = {}
  170. self.vmap = {}
  171. def me():
  172. """Returns name of currently executing method"""
  173. nm = ''
  174. try:
  175. raise ZeroDivisionError
  176. except ZeroDivisionError:
  177. nm = sys.exc_info()[2].tb_frame.f_back.f_code.co_name
  178. return nm+'()'
  179. me = staticmethod(me)
  180. def lineSeparator():
  181. """Return the OS line separator"""
  182. if sys.platform.startswith('java'):
  183. from java.lang import System
  184. if sys.platform.startswith('java1.6'):
  185. return System.getProperty('line.separator')
  186. elif sys.platform.startswith('java1.7'):
  187. return System.lineSeparator()
  188. else:
  189. import os
  190. os.linesep
  191. lineSeparator = staticmethod(lineSeparator)
  192. def listdir(path):
  193. """list files in the directory given by path"""
  194. if sys.platform.startswith('java'):
  195. from java.io import File
  196. array = File(path).list()
  197. listFile = []
  198. if array != None:
  199. for i in xrange(len(array)):
  200. listFile.append(array[i])
  201. return listFile
  202. else:
  203. import os
  204. return os.listdir(path)
  205. listdir = staticmethod(listdir)
  206. def getenv(key, default=None):
  207. if sys.platform.startswith('java'):
  208. from java.lang.System import getenv
  209. return getenv(key)
  210. else:
  211. import os
  212. return os.getenv(key)
  213. getenv = staticmethod(getenv)
  214. def checkFile(fname):
  215. """open a file if it exists, otherwise die"""
  216. try:
  217. fp = open(fname, 'r+')
  218. return fp
  219. except IOError, e:
  220. raise RuntimeError(e)
  221. checkFile = staticmethod(checkFile)
  222. def fileExists(fname):
  223. """check if fname exists as a file"""
  224. if sys.platform.startswith('java'):
  225. from java.io import File
  226. return File(fname).exists()
  227. else:
  228. import os
  229. return os.path.exists(fname)
  230. fileExists = staticmethod(fileExists)
  231. def getFullPath(fname):
  232. """return canonical/absolute path of given fname"""
  233. if sys.platform.startswith('java'):
  234. from java.io import File
  235. return File(fname).getCanonicalPath()
  236. else:
  237. import os
  238. return os.path.abspath(fname)
  239. getFullPath = staticmethod(getFullPath)
  240. def copyDir(dname, target):
  241. """Recursively copy 'dname' directory to 'target'.
  242. /!\If 'target' already exists it will be removed or overwrited.
  243. """
  244. if sys.platform.startswith('java'):
  245. # import java module
  246. from java.io import File
  247. from java.io import FileInputStream
  248. from java.io import FileOutputStream
  249. from java.util import Scanner
  250. from java.lang import String
  251. dnameFile = File(dname)
  252. targetFile = File(target)
  253. # recursive copy
  254. if dnameFile.isDirectory():
  255. # Create folder if not exists
  256. if not targetFile.exists():
  257. targetFile.mkdir()
  258. # Copy all content recursively
  259. for fname in dnameFile.list().tolist():
  260. VLAB.copyDir(dname + File.separator + fname, target + File.separator + fname)
  261. else:
  262. # Read dname file
  263. istream = FileInputStream(dname)
  264. scan = Scanner(istream).useDelimiter("\\Z")
  265. # Test if file is empty
  266. if scan.hasNextLine():
  267. content = String(scan.next())
  268. else:
  269. content = String("")
  270. scan.close()
  271. # Create and write target
  272. if not targetFile.exists():
  273. targetFile.createNewFile()
  274. ostream = FileOutputStream(target)
  275. ostream.write(content.getBytes())
  276. ostream.flush()
  277. ostream.close()
  278. else:
  279. import shutil, os
  280. # remove exisiting target
  281. if os.path.isdir(target) or os.path.isfile(target):
  282. shutil.rmtree(target)
  283. # recursive copy of dnma to target
  284. shutil.copytree(dname, target)
  285. copyDir = staticmethod(copyDir)
  286. def XMLEditNode(fname, nodeName, attributName, value, multiple=False):
  287. """ Edit a given node (nodeName) in a given XML file (fname)
  288. attributName and value could be either a list of string or a string
  289. """
  290. if sys.platform.startswith('java'):
  291. from javax.xml.parsers import DocumentBuilderFactory
  292. from javax.xml.transform import TransformerFactory
  293. from javax.xml.transform import OutputKeys
  294. from javax.xml.transform.dom import DOMSource
  295. from javax.xml.transform.stream import StreamResult
  296. from java.io import File
  297. # Get whole tree
  298. tree = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fname)
  299. # Get nodeName
  300. node = tree.getElementsByTagName(nodeName)
  301. # Check if we get only one node (as expected)
  302. if node.getLength() == 0:
  303. raise IOError("Cannot found '%s' in file '%s'" % (nodeName, fname))
  304. elif node.getLength() == 1:
  305. nodes = [node.item(0)]
  306. else:
  307. if not multiple:
  308. raise IOError("Get multiple nodes for '%s' in file '%s'" % (nodeName, fname))
  309. else:
  310. nodes = [ node.item(i) for i in xrange(node.getLength()) ]
  311. for node in nodes:
  312. # Modify the node attribute
  313. if isinstance(attributName, list) and isinstance(value, list):
  314. for att, val in zip(attributName, value):
  315. node.setAttribute(att, val)
  316. elif isinstance(attributName, str) and isinstance(value, str):
  317. node.setAttribute(attributName, value)
  318. else:
  319. raise ValueError("Wrong parameter used: attributName and value should be both either a list of string or a string")
  320. # Write new XML tree in fname
  321. transformer = TransformerFactory.newInstance().newTransformer()
  322. transformer.setOutputProperty(OutputKeys.INDENT, "yes")
  323. source = DOMSource(tree)
  324. result = StreamResult(File(fname))
  325. transformer.transform(source, result)
  326. else:
  327. import xml.etree.ElementTree as ET
  328. # Get whole tree from xml
  329. tree = ET.parse(fname)
  330. # Get nodeName
  331. #nodes = tree.findall(".//*%s" % nodeName) # This line seems to not work for root child node!! Bug?
  332. nodes = tree.findall(".//*../%s" % nodeName)
  333. # Check if we get only one node (as expected)
  334. if len(nodes) == 0:
  335. raise IOError("Cannot found '%s' in file '%s'" % (nodeName, fname))
  336. elif len(nodes) > 1 and not multiple:
  337. raise IOError("Get multiple nodes for '%s' in file '%s'" % (nodeName, fname))
  338. for node in nodes:
  339. # Modify the node attribute
  340. if isinstance(attributName, list) and isinstance(value, list):
  341. for att, val in zip(attributName, value):
  342. node.set(att, val)
  343. elif isinstance(attributName, str) and isinstance(value, str):
  344. node.set(attributName, value)
  345. else:
  346. raise ValueError("Wrong parameter used: attributName and value should be both either a list of string or a string")
  347. # Write new XML tree in fname
  348. tree.write(fname)
  349. XMLEditNode = staticmethod(XMLEditNode)
  350. def XMLReplaceNodeContent(fname, parent, subnode, attributName, value, spectralBands=False):
  351. """ Edit an XML file (fname) and replace the content of a node with subnode(s) (subnode) within attribute(s) and value(s).
  352. attributName and value could be either a list of string or a string
  353. """
  354. if sys.platform.startswith('java'):
  355. from javax.xml.parsers import DocumentBuilderFactory
  356. from javax.xml.transform import TransformerFactory
  357. from javax.xml.transform import OutputKeys
  358. from javax.xml.transform.dom import DOMSource
  359. from javax.xml.transform.stream import StreamResult
  360. from java.io import File
  361. # Get whole tree
  362. tree = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fname)
  363. # Get nodeName
  364. node = tree.getElementsByTagName(parent)
  365. # Check if we get only one node (as expected)
  366. if node.getLength() > 1:
  367. raise IOError("Get multiple nodes for '%s' in file '%s'" % (parent, fname))
  368. elif node.getLength() == 0:
  369. raise IOError("Cannot found '%s' in file '%s'" % (parent, fname))
  370. else:
  371. node = node.item(0)
  372. # Remove content node
  373. while node.hasChildNodes():
  374. node.removeChild(node.getFirstChild())
  375. # Modify the node attribute
  376. elem = tree.createElement(subnode)
  377. if spectralBands:
  378. elem.setAttribute("bandNumber", "0")
  379. elem.setAttribute("spectralDartMode", "0")
  380. if isinstance(attributName, list) and isinstance(value, list):
  381. if isinstance(value[0], list):
  382. for bandNumber, val in enumerate(value):
  383. if spectralBands:
  384. elem.setAttribute("bandNumber", str(bandNumber))
  385. for atr, v in zip(attributName, val):
  386. elem.setAttribute(atr, v)
  387. node.appendChild(elem.cloneNode(True))
  388. else:
  389. elem = tree.createElement(subnode)
  390. for atr, v in zip(attributName, value):
  391. elem.setAttribute(atr, v)
  392. node.appendChild(elem)
  393. elif isinstance(attributName, str) and isinstance(value, str):
  394. elem = tree.createElement(subnode)
  395. elem.setAttribute(attributName, value)
  396. node.appendChild(elem)
  397. else:
  398. raise ValueError("Wrong parameter used: attributName and value should be both either a list of string or a string")
  399. # Write new XML tree in fname
  400. transformer = TransformerFactory.newInstance().newTransformer()
  401. transformer.setOutputProperty(OutputKeys.INDENT, "yes")
  402. source = DOMSource(tree)
  403. result = StreamResult(File(fname))
  404. transformer.transform(source, result)
  405. else:
  406. import xml.etree.ElementTree as ET
  407. # Get whole tree from xml
  408. tree = ET.parse(fname)
  409. # Get nodeName
  410. #nodes = tree.findall(".//*%s" % nodeName) # This line seems to not work for root child node!! Bug?
  411. node = tree.findall(".//*../%s" % parent)
  412. # Check if we get only one node (as expected)
  413. if len(node) > 1:
  414. raise IOError("Get multiple nodes for '%s' in file '%s'" % (parent, fname))
  415. elif len(node) == 0:
  416. raise IOError("Cannot found '%s' in file '%s'" % (parent, fname))
  417. else:
  418. node = node[0]
  419. # Remove content of node
  420. node.clear()
  421. # Modify the node attribute
  422. if spectralBands:
  423. attrib = {"bandNumber":"0", "spectralDartMode":"0"}
  424. else:
  425. attrib = {}
  426. if isinstance(attributName, list) and isinstance(value, list):
  427. if isinstance(value[0], list):
  428. for bandNumber, val in enumerate(value):
  429. if spectralBands:
  430. attrib["bandNumber"] = str(bandNumber)
  431. for atr, v in zip(attributName, val):
  432. attrib[atr] = v
  433. node.append(ET.Element(subnode, attrib=attrib))
  434. else:
  435. for atr, v in zip(attributName, value):
  436. attrib[atr] = v
  437. node.append(ET.Element(subnode, attrib=attrib))
  438. elif isinstance(attributName, str) and isinstance(value, str):
  439. attrib[attributName] = value
  440. node.append(ET.Element(subnode, attrib=attrib))
  441. else:
  442. raise ValueError("Wrong parameter used: attributName and value should be both either a list of string or a string")
  443. # Write new XML tree in fname
  444. tree.write(fname)
  445. XMLReplaceNodeContent = staticmethod(XMLReplaceNodeContent)
  446. def XMLAddNode(fname, parent, treeNodes, nodesSetup):
  447. """ Add a node (subnode) to a given parent in the provided fname file.
  448. """
  449. if sys.platform.startswith('java'):
  450. from javax.xml.parsers import DocumentBuilderFactory
  451. from javax.xml.transform import TransformerFactory
  452. from javax.xml.transform import OutputKeys
  453. from javax.xml.transform.dom import DOMSource
  454. from javax.xml.transform.stream import StreamResult
  455. from java.io import File
  456. # Get whole tree
  457. tree = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fname)
  458. # Get nodeName
  459. node = tree.getElementsByTagName(parent)
  460. # Check if we get only one node (as expected)
  461. if node.getLength() > 1:
  462. raise IOError("Get multiple nodes for '%s' in file '%s'" % (parent, fname))
  463. elif node.getLength() == 0:
  464. raise IOError("Cannot found '%s' in file '%s'" % (parent, fname))
  465. else:
  466. node = node.item(0)
  467. # Create all the new nodes
  468. nodes = {parent:node}
  469. for name in treeNodes:
  470. nodes[name] = (tree.createElement(name))
  471. for atr, val in zip(*[ nodesSetup[name][key] for key in nodesSetup[name].iterkeys() if key in ["attribute", "value"] ]):
  472. nodes[name].setAttribute(atr, val)
  473. # Add all created node to its parent (previous node in the list)
  474. for name, elem in nodes.iteritems():
  475. if name != parent:
  476. nodes[nodesSetup[name]["parent"]].appendChild(elem)
  477. # Write new XML tree in fname
  478. transformer = TransformerFactory.newInstance().newTransformer()
  479. transformer.setOutputProperty(OutputKeys.INDENT, "yes")
  480. source = DOMSource(tree)
  481. result = StreamResult(File(fname))
  482. transformer.transform(source, result)
  483. else:
  484. import xml.etree.ElementTree as ET
  485. # Get whole tree from xml
  486. tree = ET.parse(fname)
  487. # Get nodeName
  488. #nodes = tree.findall(".//*%s" % nodeName) # This line seems to not work for root child node!! Bug?
  489. node = tree.findall(".//*../%s" % parent)
  490. # Check if we get only one node (as expected)
  491. if len(node) > 1:
  492. raise IOError("Get multiple nodes for '%s' in file '%s'" % (parent, fname))
  493. elif len(node) == 0:
  494. raise IOError("Cannot found '%s' in file '%s'" % (parent, fname))
  495. else:
  496. node = node[0]
  497. # Create all the new nodes
  498. nodes = {parent:node}
  499. for name in treeNodes:
  500. attrib = {}
  501. for atr, val in zip(*[ nodesSetup[name][key] for key in nodesSetup[name].iterkeys() if key in ["attribute", "value"] ]):
  502. attrib[atr] = val
  503. nodes[name] = ET.Element(name, attrib)
  504. # Add all created node to its parent (previous node in the list)
  505. for name, elem in nodes.iteritems():
  506. if name != parent:
  507. nodes[nodesSetup[name]["parent"]].append(elem)
  508. # Write new XML tree in fname
  509. tree.write(fname)
  510. XMLAddNode = staticmethod(XMLAddNode)
  511. def XMLGetNodeAttributeValue(fname, nodeName, attributName):
  512. """ Return the value of the given attributName for the given nodeName
  513. """
  514. if sys.platform.startswith('java'):
  515. from javax.xml.parsers import DocumentBuilderFactory
  516. from org.w3c.dom import Element
  517. # Get whole tree
  518. tree = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fname)
  519. # Get nodeName
  520. node = tree.getElementsByTagName(nodeName)
  521. # Check if we get only one node (as expected)
  522. if node.getLength() > 1:
  523. raise IOError("Get multiple nodes for '%s' in file '%s'" % (nodeName, fname))
  524. elif node.getLength() == 0:
  525. raise IOError("Cannot found '%s' in file '%s'" % (nodeName, fname))
  526. else:
  527. node = node.item(0)
  528. # Check if that node has attributName
  529. if node.hasAttribute(attributName):
  530. return node.getAttributes().getNamedItem(attributName).getNodeValue()
  531. else:
  532. raise IOError("Attribute name '%s' not found for node '%s' in file '%s'" % (attributName, nodeName, fname))
  533. else:
  534. import xml.etree.ElementTree as ET
  535. # Get whole tree from xml
  536. tree = ET.parse(fname)
  537. # Get nodeName
  538. #nodes = tree.findall(".//*%s" % nodeName) # This line seems to not work for root child node!! Bug?
  539. node = tree.findall(".//*../%s[@%s]" % (nodeName, attributName))
  540. # Check if we get only one node (as expected)
  541. if len(node) > 1:
  542. raise IOError("Get multiple nodes for '%s' in file '%s'" % (nodeName, fname))
  543. elif len(node) == 0:
  544. raise IOError("Cannot found '%s' in file '%s'" % (nodeName, fname))
  545. else:
  546. node = node[0]
  547. # Check if that node has an attributName
  548. if attributName in node.keys():
  549. return node.get(attributName)
  550. else:
  551. raise IOError("Attribute name '%s' not found for node '%s' in file '%s'" % (attributName, nodeName, fname))
  552. XMLGetNodeAttributeValue = staticmethod(XMLGetNodeAttributeValue)
  553. def getBandsFromGUI(bands):
  554. """ Return a DART spectral bands list: ["deltaLambda", "meanLambda"] in micro meter
  555. In case of several bands the result should be a list of list:
  556. [["deltaLambda0", "meanLambda0"], ["deltaLambda1", "meanLambda1"], ["deltaLambda2", "meanLambda2"], ...]
  557. e.g.: [["0.02", "0.56"], ["0.02", "0.58"], ["0.02", "0.60"], ["0.02", "0.62"]]
  558. """
  559. # TODO: You should write the spectral band converter here!
  560. return [["0.02", "0.56"], ["0.02", "0.58"], ["0.02", "0.60"], ["0.02", "0.62"]]
  561. getBandsFromGUI = staticmethod(getBandsFromGUI)
  562. class path:
  563. def exists(path):
  564. if sys.platform.startswith('java'):
  565. from java.io import File
  566. return File(path).exists()
  567. else:
  568. import os
  569. return os.path.exists(path)
  570. exists = staticmethod(exists)
  571. def isabs(path):
  572. if sys.platform.startswith('java'):
  573. from java.io import File
  574. return File(path).isAbsolute()
  575. else:
  576. import os
  577. return os.path.isabs(path)
  578. isabs = staticmethod(isabs)
  579. def isdir(path):
  580. if sys.platform.startswith('java'):
  581. from java.io import File
  582. return File(path).isDirectory()
  583. else:
  584. import os
  585. return os.path.isdir(path)
  586. isdir = staticmethod(isdir)
  587. def join(path, *args):
  588. if sys.platform.startswith('java'):
  589. from java.io import File
  590. f = File(path)
  591. for a in args:
  592. g = File(a)
  593. if g.isAbsolute() or len(f.getPath()) == 0:
  594. f = g
  595. else:
  596. f = File(f, a)
  597. return f.getPath()
  598. else:
  599. import os
  600. return os.path.join(path, *args)
  601. join = staticmethod(join)
  602. def isfile(path):
  603. if sys.platform.startswith('java'):
  604. from java.io import File
  605. return File(path).isfile()
  606. else:
  607. import os
  608. return os.path.isfile(path)
  609. isfile = staticmethod(isfile)
  610. def normcase(path):
  611. if sys.platform.startswith('java'):
  612. from java.io import File
  613. return File(path).getPath()
  614. else:
  615. import os
  616. return os.path.normcase(path)
  617. normcase = staticmethod(normcase)
  618. def normpath(path):
  619. if sys.platform.startswith('java'):
  620. from java.io import File
  621. return File(path).getCanonicalPath()
  622. else:
  623. import os
  624. return os.path.normpath(path)
  625. normpath = staticmethod(normpath)
  626. def split(path):
  627. if sys.platform.startswith('java'):
  628. from java.io import File
  629. f=File(path)
  630. d=f.getParent()
  631. if not d:
  632. if f.isAbsolute():
  633. d = path
  634. else:
  635. d = ""
  636. return (d, f.getName())
  637. else:
  638. import os
  639. return os.path.split(path)
  640. split = staticmethod(split)
  641. def frange(end, start=0, inc=0):
  642. """a jython-compatible range function with float increments"""
  643. import math
  644. if not start:
  645. start = end + 0.0
  646. end = 0.0
  647. else: end += 0.0
  648. if not inc:
  649. inc = 1.0
  650. count = int(math.ceil((start - end) / inc))
  651. L = [None] * count
  652. L[0] = end
  653. for i in (xrange(1,count)):
  654. L[i] = L[i-1] + inc
  655. return L
  656. frange = staticmethod(frange)
  657. def openFileIfNotExists(filename):
  658. """open file exclusively"""
  659. if sys.platform.startswith('java'):
  660. from java.io import File
  661. File(filename).getParentFile().mkdirs()
  662. if File(filename).createNewFile():
  663. return open(filename, 'w')
  664. else:
  665. return None
  666. else:
  667. import os
  668. try:
  669. # os.O_EXCL => open exclusive => acquire a lock on the file
  670. fd = os.open(filename, os.O_CREAT|os.O_EXCL|os.O_WRONLY|os.O_TRUNC)
  671. except:
  672. return None
  673. fobj = os.fdopen(fd,'w')
  674. return fobj
  675. openFileIfNotExists = staticmethod(openFileIfNotExists)
  676. def rndInit(seed = None):
  677. """initialize the randon number generator"""
  678. if sys.platform.startswith('java'):
  679. from java.util import Random
  680. if seed == None:
  681. return Random()
  682. else:
  683. return Random(seed)
  684. else:
  685. import random
  686. random.seed(seed)
  687. return None
  688. rndInit = staticmethod(rndInit)
  689. def rndNextFloat(randState):
  690. """return the next pseudo-random floating point number in the sequence"""
  691. if sys.platform.startswith('java'):
  692. from java.util import Random
  693. return randState.nextFloat()
  694. else:
  695. import random
  696. return random.random()
  697. rndNextFloat = staticmethod(rndNextFloat)
  698. def r2d(v):
  699. """jython-compatible conversion of radians to degrees"""
  700. if sys.platform.startswith('java'):
  701. from java.lang import Math
  702. return Math.toDegrees(v)
  703. else:
  704. return math.degrees(v)
  705. r2d = staticmethod(r2d)
  706. def d2r(v):
  707. """jython-compatible conversion of degrees to radians"""
  708. if sys.platform.startswith('java'):
  709. from java.lang import Math
  710. return Math.toRadians(float(v))
  711. else:
  712. return math.radians(v)
  713. d2r = staticmethod(d2r)
  714. def mkDirPath(path):
  715. """create directory (including non-existing parents) for the given path"""
  716. if sys.platform.startswith('java'):
  717. from java.io import File
  718. if not File(path).isDirectory():
  719. if not File(path).mkdirs():
  720. raise RuntimeError('failed to mkdir %s' % path)
  721. else:
  722. import os
  723. try:
  724. os.stat(path)
  725. except:
  726. os.makedirs(path)
  727. mkDirPath = staticmethod(mkDirPath)
  728. def fPath(d,n):
  729. """get file path of the file defined by directory d and file name n"""
  730. if sys.platform.startswith('java'):
  731. from java.io import File
  732. return File(d, n).getPath()
  733. else:
  734. import os
  735. return os.path.join(d, n)
  736. fPath = staticmethod(fPath)
  737. def savetxt(a, b, fmt=False):
  738. """save text b in a text file named a"""
  739. fh = open(a, 'w')
  740. if not fmt:
  741. fmt = '%s'
  742. for row in b:
  743. for element in row:
  744. fh.write(fmt % element + ' ')
  745. fh.write('\n')
  746. fh.close()
  747. savetxt = staticmethod(savetxt)
  748. def osName():
  749. """return which OS we are currently running on"""
  750. if sys.platform.startswith('java'):
  751. from java.lang import System
  752. oname = System.getProperty('os.name')
  753. else:
  754. import os
  755. oname = os.name
  756. if not oname.endswith('x'): oname = 'Windows'
  757. return oname
  758. osName = staticmethod(osName)
  759. def expandEnv(instr):
  760. """potentially expand environment variables in the given string"""
  761. outstr = instr
  762. m = {'$HOME':'HOME','%HOMEDRIVE%':'HOMEDRIVE','%HOMEPATH%':'HOMEPATH'}
  763. for e in m:
  764. if outstr.find(e) != -1:
  765. if sys.platform.startswith('java'):
  766. from java.lang import System
  767. repl = System.getenv(m[e])
  768. else:
  769. import os
  770. repl = os.getenv(m[e])
  771. if repl != None:
  772. outstr = outstr.replace(e, repl)
  773. return outstr
  774. expandEnv = staticmethod(expandEnv)
  775. if sys.platform.startswith('java'):
  776. from java.lang import Runnable
  777. class Helper(Runnable):
  778. def __init__(self, nm, strm, fName):
  779. self.nm=nm; self.strm=strm; self.fp=None
  780. if fName != None:
  781. if VLAB.fileExists(fName):
  782. self.fp = open(fName, 'w')
  783. else:
  784. self.fp = VLAB.openFileIfNotExists(fName)
  785. def run(self):
  786. """helper class for slurping up child streams"""
  787. from java.io import BufferedReader
  788. from java.io import InputStreamReader
  789. line = None; br = BufferedReader(InputStreamReader(self.strm))
  790. line = br.readLine()
  791. while (line != None):
  792. if self.fp != None:
  793. self.fp.write(line + VLAB.lineSeparator())
  794. self.fp.flush()
  795. VLAB.logger.info('%s %s' %(self.nm, line.rstrip()))
  796. line = br.readLine()
  797. br.close()
  798. if self.fp != None:
  799. self.fp.close()
  800. else:
  801. def helper(nm, strm):
  802. """helper method for slurping up child streams"""
  803. for line in strm: VLAB.logger.info('%s %s' %(nm, line.rstrip()))
  804. if not strm.closed: strm.close()
  805. helper = staticmethod(helper)
  806. def doExec(cmdrec):
  807. """run the specified external program under windows or unix"""
  808. cmdLine = []
  809. osName = VLAB.osName()
  810. if osName.startswith('Windows'):
  811. cmd=cmdrec['windows']
  812. cmdLine = ['cmd', '/c']
  813. else:
  814. cmd=cmdrec['linux']
  815. exe = VLAB.expandEnv(cmd['exe'])
  816. if not (VLAB.fileExists(exe) or osName.startswith('Windows')):
  817. raise RuntimeError('Cannot find exe "%s"' % exe)
  818. cmdLine.append(exe)
  819. for i in cmd['cmdline']:
  820. cmdLine.append(VLAB.expandEnv(i))
  821. VLAB.logger.info('cmdLine is [%s]' % cmdLine)
  822. if sys.platform.startswith('java'):
  823. from java.lang import ProcessBuilder
  824. from java.lang import Thread
  825. from java.io import BufferedWriter
  826. from java.io import OutputStreamWriter
  827. from java.io import File
  828. pb = ProcessBuilder(cmdLine)
  829. if 'cwd' in cmd and cmd['cwd'] != None:
  830. pb.directory(File(VLAB.expandEnv(cmd['cwd'])))
  831. if 'env' in cmd and cmd['env'] != None:
  832. env = pb.environment()
  833. cmdenv = cmd['env']
  834. for e in cmdenv:
  835. env[e] = VLAB.expandEnv(cmdenv[e])
  836. proc = pb.start()
  837. stdoutfName = None
  838. if 'stdout' in cmd and cmd['stdout'] != None:
  839. stdoutfName = VLAB.expandEnv(cmd['stdout'])
  840. stderrfName = None
  841. if 'stderr' in cmd and cmd['stderr'] != None:
  842. stderrfName = VLAB.expandEnv(cmd['stderr'])
  843. outs = Thread(VLAB.Helper('out', proc.getInputStream(), stdoutfName))
  844. errs = Thread(VLAB.Helper('err', proc.getErrorStream(), stderrfName))
  845. outs.start(); errs.start()
  846. bw = BufferedWriter(OutputStreamWriter(proc.getOutputStream()))
  847. if 'stdin' in cmd and cmd['stdin'] != None:
  848. inFile = VLAB.expandEnv(cmd['stdin'])
  849. VLAB.logger.info('stdin is [%s]' % inFile)
  850. if 'cwd' in cmd and cmd['cwd'] != None:
  851. if not VLAB.fileExists(inFile):
  852. # try pre-pending the cwd
  853. inFile = VLAB.fPath(VLAB.expandEnv(cmd['cwd']), inFile)
  854. if not VLAB.fileExists(inFile):
  855. raise RuntimeError('Cannot find stdin "%s"' % cmd['cwd'])
  856. fp = open(inFile, 'r')
  857. for line in fp:
  858. bw.write(line)
  859. bw.close()
  860. fp.close()
  861. exitCode = proc.waitFor()
  862. outs.join(); errs.join()
  863. else:
  864. import threading, subprocess, os
  865. if 'cwd' in cmd and cmd['cwd'] != None:
  866. os.chdir(VLAB.expandEnv(cmd['cwd']))
  867. if 'env' in cmd and cmd['env'] != None:
  868. cmdenv = cmd['env']
  869. for e in cmdenv:
  870. os.putenv(e, VLAB.expandEnv(cmdenv[e]))
  871. if 'stdin' in cmd and cmd['stdin'] != None:
  872. proc = subprocess.Popen(cmdLine, stdin=open(VLAB.expandEnv(cmd['stdin']),'r'),stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  873. else:
  874. proc = subprocess.Popen(cmdLine, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  875. t1 = threading.Thread(target=VLAB.helper, args=('out', proc.stdout))
  876. t2 = threading.Thread(target=VLAB.helper, args=('err', proc.stderr))
  877. t1.start(); t2.start()
  878. exitCode = proc.wait()
  879. t1.join(); t2.join()
  880. VLAB.logger.info('exitCode=%d' % exitCode)
  881. doExec = staticmethod(doExec)
  882. def valuesfromfile(path, transpose=False):
  883. """Returns a 2D array with the values of the csv file at 'path'.
  884. Keyword arguments:
  885. transpose -- transpose the matrix with the values
  886. """
  887. fp = open(path)
  888. values = [line.strip().split() for line in fp
  889. if not line.startswith('#')]
  890. fp.close()
  891. values = [[float(value) for value in row] for row in values]
  892. if transpose:
  893. values = zip(*values)
  894. return values
  895. valuesfromfile = staticmethod(valuesfromfile)
  896. def fabsa(x):
  897. """Return the element-wise abs() of the given array."""
  898. return map(lambda x : math.fabs(x), x)
  899. fabsa = staticmethod(fabsa)
  900. def cosa(arcs):
  901. """Return the element-wise cos() of 'arcs' array given in degrees."""
  902. return map(lambda x : math.cos(VLAB.d2r(x)), arcs)
  903. cosa = staticmethod(cosa)
  904. def replacerectinarray(array, replacement, xul, yul, xlr, ylr):
  905. """Replace the array with the specified rectangle substituted with
  906. replacement.
  907. (array[xul:xlr,yul:ylr])
  908. +---------------+
  909. |(xul, yul) |
  910. | |
  911. | (xlr, ylr)|
  912. +---------------+
  913. """
  914. ri = 0
  915. for x in xrange(xul, xlr):
  916. array[x][yul:ylr] = replacement[ri]
  917. ri += 1
  918. return array
  919. replacerectinarray = staticmethod(replacerectinarray)
  920. def replaceinarray(haystack, predicate, replacement):
  921. """Return 'haystack' with 'predicate' matches replaced by 'replacement'"""
  922. return map(lambda item : {True: replacement, False: item}[predicate(item)],
  923. haystack)
  924. replaceinarray = staticmethod(replaceinarray)
  925. def sqrta(values):
  926. """Return the element-wise sqrt() of the given array."""
  927. return map(math.sqrt, values)
  928. sqrta = staticmethod(sqrta)
  929. def suba(lista, listb):
  930. """Subtract the values of a list from the values of another list."""
  931. if len(lista) != len(listb):
  932. raise ValueError("Arguments have to be of same length.")
  933. return map(operator.sub, lista, listb)
  934. suba = staticmethod(suba)
  935. def adda(lista, listb):
  936. """Add the values of a list to the values of another list."""
  937. if len(lista) != len(listb):
  938. raise ValueError("Arguments have to be of same length.")
  939. return map(operator.add, lista, listb)
  940. adda = staticmethod(adda)
  941. def diva(lista, listb):
  942. """Return the element-wise division of 'lista' by 'listb'."""
  943. if len(lista) != len(listb):
  944. raise ValueError("Arguments have to be of same length.")
  945. return map(operator.div, lista, listb)
  946. diva = staticmethod(diva)
  947. def mula(lista, listb):
  948. """Return the element-wise multiplication of 'lista' with 'listb'."""
  949. if len(lista) != len(listb):
  950. raise ValueError("Arguments have to be of same length.")
  951. return map(operator.mul, lista, listb)
  952. mula = staticmethod(mula)
  953. def powa(values, exponent):
  954. """Returns the element-wise exp('exponent') of the given array."""
  955. if isinstance(exponent, (list, tuple)):
  956. return map(lambda x, y : x ** y, values, exponent)
  957. return map(lambda x : x ** exponent, values)
  958. powa = staticmethod(powa)
  959. def treemap(fn, tree):
  960. """Applies `fn' to every value in `tree' which isn't a list and
  961. returns a list with the same shape as tree and the value of `fn'
  962. applied to the values in their place.
  963. """
  964. result = []
  965. for node in tree:
  966. if isinstance(node, (list, tuple)):
  967. result += [VLAB.treemap(fn, node)]
  968. else:
  969. result += [fn(node)]
  970. return result
  971. treemap = staticmethod(treemap)
  972. def makemaskeq(array, value):
  973. return VLAB.treemap(lambda x : x == value, array)
  974. makemaskeq = staticmethod(makemaskeq)
  975. def awhere(mask):
  976. """Returns the coordinates of the cells which evaluate true."""
  977. result = []
  978. if isinstance(mask, (list, tuple)):
  979. for i, cell in enumerate(mask):
  980. result += [[i] + sub for sub in VLAB.awhere(cell)
  981. if isinstance(sub, (list, tuple))]
  982. return result
  983. else:
  984. if mask:
  985. return [[]]
  986. else:
  987. return []
  988. awhere = staticmethod(awhere)
  989. def aclone(tree):
  990. """Make a deep copy of `tree'."""
  991. if isinstance(tree, (list, tuple)):
  992. return list(map(VLAB.aclone, tree))
  993. return tree
  994. aclone = staticmethod(aclone)
  995. def make_chart(title, x_label, y_label, dataset):
  996. """Helper for creating Charts"""
  997. if sys.platform.startswith('java'):
  998. from org.jfree.chart import ChartFactory, ChartFrame, ChartUtilities
  999. from org.jfree.chart.axis import NumberTickUnit
  1000. from org.jfree.chart.plot import PlotOrientation
  1001. from org.jfree.data.xy import XYSeries, XYSeriesCollection
  1002. chart = ChartFactory.createScatterPlot(title, x_label, y_label, dataset,
  1003. PlotOrientation.VERTICAL, True,
  1004. True, False)
  1005. plot = chart.getPlot()
  1006. domain_axis = plot.getDomainAxis()
  1007. domain_axis.setRange(-70, 70)
  1008. range_axis = plot.getRangeAxis()
  1009. range_axis.setRange(0.0, 0.4)
  1010. range_axis.setTickUnit(NumberTickUnit(0.05))
  1011. return chart
  1012. else:
  1013. # TODO: re-merge original python implementation
  1014. raise Exception("original make_chart()")
  1015. return None
  1016. make_chart = staticmethod(make_chart)
  1017. def make_dataset():
  1018. """Dataset helper for supporting chart creation"""
  1019. if sys.platform.startswith('java'):
  1020. from org.jfree.data.xy import XYSeriesCollection
  1021. return XYSeriesCollection()
  1022. else:
  1023. # TODO: re-merge original python implementation
  1024. raise Exception("original make_dataset()")
  1025. return None
  1026. make_dataset = staticmethod(make_dataset)
  1027. def plot(dataset, x, y, label):
  1028. """plot dataset with x and y values and the given label"""
  1029. if sys.platform.startswith('java'):
  1030. from org.jfree.data.xy import XYSeries
  1031. series = XYSeries(label)
  1032. for next_x, next_y in zip(x, y):
  1033. series.add(float(next_x), float(next_y))
  1034. dataset.addSeries(series)
  1035. else:
  1036. # TODO: re-merge original python implementation
  1037. raise Exception("original plot()")
  1038. return None
  1039. plot = staticmethod(plot)
  1040. def save_chart(chart, filename):
  1041. """save the generated chart in the given filename"""
  1042. if sys.platform.startswith('java'):
  1043. from java.io import File
  1044. from org.jfree.chart import ChartUtilities
  1045. ChartUtilities.saveChartAsPNG(File(filename), chart, 800, 600)
  1046. else:
  1047. # TODO: re-merge original python implementation
  1048. raise Exception("save_chart")
  1049. pass
  1050. save_chart = staticmethod(save_chart)
  1051. def maskand(array, mask):
  1052. return map(lambda a, b : a & b, array, mask)
  1053. maskand = staticmethod(maskand)
  1054. def unique(array):
  1055. """return unique values in the given input array"""
  1056. sortedarray = list(array)
  1057. sortedarray.sort()
  1058. result = []
  1059. def addifunique(x, y):
  1060. if x != y:
  1061. result.append(x)
  1062. return y
  1063. result.append(reduce(addifunique, sortedarray))
  1064. return result
  1065. unique = staticmethod(unique)
  1066. def ravel(a):
  1067. def add(a, i):
  1068. if not(isinstance(a, (list, tuple))):
  1069. a = [a]
  1070. if isinstance(i, (list, tuple)):
  1071. return a + ravel(i)
  1072. else:
  1073. return a + [i]
  1074. return reduce(add, a)
  1075. ravel = staticmethod(ravel)
  1076. def min_l_bfgs_b(f, initial_guess, args=(), bounds=None, epsilon=1e-8):
  1077. """The `approx_grad' is not yet implemented, because it's not yet
  1078. used."""
  1079. if sys.platform.startswith('java'):
  1080. from java.lang import ClassLoader
  1081. from java.io import File
  1082. for path in sys.path:
  1083. if path.endswith('.jar'):
  1084. libdir = File(path).getParent()
  1085. break
  1086. VLAB.logger.info(libdir)
  1087. # hack taken from: http://blog.cedarsoft.com/2010/11/setting-java-library-path-programmatically
  1088. System.setProperty("java.library.path", libdir)
  1089. syspathfield = ClassLoader.getDeclaredField("sys_paths")
  1090. syspathfield.setAccessible(True);
  1091. syspathfield.set(None, None)
  1092. from lbfgsb import DifferentiableFunction, FunctionValues, Bound, Minimizer
  1093. class function(DifferentiableFunction):
  1094. def __init__(self, function, args=()):
  1095. self.function = function
  1096. self.args = args
  1097. def getValues(self, x):
  1098. f = self.function(x, *self.args)
  1099. g = VLAB.approx_fprime(x, self.function, epsilon, *self.args)
  1100. return FunctionValues(f, g)
  1101. min = Minimizer()
  1102. min.setBounds([Bound(bound[0], bound[1]) for bound in bounds])
  1103. result = min.run(function(f, args), VLAB.ravel(initial_guess))
  1104. return result.point
  1105. min_l_bfgs_b = staticmethod(min_l_bfgs_b)
  1106. def approx_fprime(xk, f, epsilon, *args):
  1107. f0 = f(xk, *args)
  1108. grad = [0. for i in xrange(len(xk))]
  1109. ei = [0. for i in xrange(len(xk))]
  1110. for k in xrange(len(xk)):
  1111. ei[k] = 1.0
  1112. d = map(lambda i : i * epsilon, ei)
  1113. grad[k] = (f(VLAB.adda(xk, d), *args) - f0) / d[k]
  1114. ei[k] = 0.0
  1115. return grad
  1116. approx_fprime = staticmethod(approx_fprime)
  1117. def doLibradtran(args):
  1118. q = {
  1119. 'rpv_file': args['rpv_file'],
  1120. 'outfile' : args['outfile'],
  1121. 'infile' : args['infile'],
  1122. }
  1123. for k in args:
  1124. q[k] = args[k]
  1125. if args['scene'] == VLAB.K_LAEGERN:
  1126. q['latitude'] = '47.481667'
  1127. q['longitude'] = '-8.394722,17'
  1128. elif args['scene'] == VLAB.K_THARANDT:
  1129. q['latitude'] = '50.9676498'
  1130. q['longitude'] = '-13.520354'
  1131. if args['aerosol'] == VLAB.K_RURAL:
  1132. q['aerosol'] = '1'
  1133. elif args['aerosol'] == VLAB.K_MARITIME:
  1134. q['aerosol'] = '2'
  1135. elif args['aerosol'] == VLAB.K_URBAN:
  1136. q['aerosol'] = '5'
  1137. elif args['aerosol'] == VLAB.K_TROPOSPHERIC:
  1138. q['aerosol'] = '6'
  1139. # TODO: verify these
  1140. if args['sensor'] == VLAB.K_SENTINEL2:
  1141. q['wavelength'] = '443 2190'
  1142. elif args['sensor'] == VLAB.K_SENTINEL3:
  1143. q['wavelength'] = '400 2400'
  1144. elif args['sensor'] == VLAB.K_MODIS:
  1145. q['wavelength'] = '405 2155'
  1146. elif args['sensor'] == VLAB.K_MERIS:
  1147. q['wavelength'] = '412 900'
  1148. elif args['sensor'] == VLAB.K_LANDSAT_OLI:
  1149. q['wavelength'] = '433 2300'
  1150. elif args['sensor'] == VLAB.K_LANDSAT_ETM:
  1151. q['wavelength'] = '450 2300'
  1152. if VLAB.osName().startswith('Windows'):
  1153. q['solar_file'] = VLAB.expandEnv('%HOMEDRIVE%%HOMEPATH%\\.beam\\beam-vlab\\auxdata\\libRadtran_win32\\data\\solar_flux\\NewGuey2003.day')
  1154. else:
  1155. q['solar_file'] = VLAB.expandEnv('$HOME/.beam/beam-vlab/auxdata/libRadtran_lin64/data/solar_flux/NewGuey2003.dat')
  1156. sdata = """
  1157. solar_file %s
  1158. correlated_k LOWTRAN
  1159. rte_solver cdisort
  1160. rpv_file %s
  1161. deltam on
  1162. nstr 6
  1163. zout TOA
  1164. output_user lambda uu
  1165. quiet
  1166. """ % (q['solar_file'],
  1167. q['rpv_file'])
  1168. if 'aerosol' in q:
  1169. sdata += "aerosol_default\n"
  1170. sdata += "aerosol_haze %s\n" % (q['aerosol'])
  1171. if 'O3' in q:
  1172. sdata += "dens_column O3 %s\n" % (q['O3'])
  1173. if 'CO2' in q:
  1174. sdata += "co2_mixing_ratio %s\n" % (q['CO2'])
  1175. if 'H2O' in q:
  1176. sdata += "h2o_mixing_ratio %s\n" % (q['H2O'])
  1177. if 'umu' in q:
  1178. sdata += "umu %s\n" % (q['umu'])
  1179. if 'phi' in q:
  1180. sdata += "phi %s\n" % (q['phi'])
  1181. if 'latitude' in q:
  1182. sdata += "latitude %s\n" % (q['latitude'])
  1183. if 'longitude' in q:
  1184. sdata += "longitude %s\n" % (q['longitude'])
  1185. if 'time' in q:
  1186. sdata += "time %s\n" % (q['time'])
  1187. if 'sza' in q:
  1188. sdata += "sza %s\n" % (q['sza'])
  1189. if 'phi0' in q:
  1190. sdata += "phi0 %s\n" % (q['phi0'])
  1191. if 'wavelength' in q:
  1192. sdata += "wavelength %s\n" % (q['wavelength'])
  1193. fp = open(q['infile'], 'w')
  1194. fp.write(sdata)
  1195. fp.close()
  1196. cmd = {
  1197. 'linux' : {
  1198. 'cwd' : '$HOME/.beam/beam-vlab/auxdata/libRadtran_lin64/examples',
  1199. 'exe' : '$HOME/.beam/beam-vlab/auxdata/libRadtran_lin64/bin/uvspec',
  1200. 'cmdline' : [],
  1201. 'stdin' : q['infile'],
  1202. 'stdout' : q['outfile'],
  1203. 'stderr' : None,
  1204. 'env' : None
  1205. },
  1206. 'windows' : {
  1207. 'cwd' : '%HOMEDRIVE%%HOMEPATH%\\.beam\\beam-vlab\\auxdata\\libRadtran_win32\\examples',
  1208. 'exe' : '%HOMEDRIVE%%HOMEPATH%\\.beam\\beam-vlab\\auxdata\\libRadtran_win32\\uvspec.exe',
  1209. 'cmdline' : [],
  1210. 'stdin' : q['infile'],
  1211. 'stdout' : q['outfile'],
  1212. 'stderr' : None,
  1213. 'env' : None
  1214. }
  1215. }
  1216. VLAB.logger.info('%s: spawning libradtran...' % VLAB.me())
  1217. VLAB.doExec(cmd)
  1218. doLibradtran = staticmethod(doLibradtran)
  1219. ###########################################################################
  1220. #
  1221. # Minimize_* functions...
  1222. #
  1223. # Nelder-Mead simplex minimization of a nonlinear (multivariate) function.
  1224. #
  1225. # The programming interface is via the minimize() function; see below.
  1226. #
  1227. # This code has been adapted from the C-coded nelmin.c which was
  1228. # adapted from the Fortran-coded nelmin.f which was, in turn, adapted
  1229. # from the papers
  1230. #
  1231. # J.A. Nelder and R. Mead (1965)
  1232. # A simplex method for function minimization.
  1233. # Computer Journal, Volume 7, pp 308-313.
  1234. #
  1235. # R. O'Neill (1971)
  1236. # Algorithm AS47. Function minimization using a simplex algorithm.
  1237. # Applied Statistics, Volume 20, pp 338-345.
  1238. #
  1239. # and some examples are in
  1240. #
  1241. # D.M. Olsson and L.S. Nelson (1975)
  1242. # The Nelder-Mead Simplex procedure for function minimization.
  1243. # Technometrics, Volume 17 No. 1, pp 45-51.
  1244. #
  1245. # For a fairly recent and popular incarnation of this minimizer,
  1246. # see the amoeba function in the famous "Numerical Recipes" text.
  1247. #
  1248. # P. Jacobs
  1249. # School of Engineering, The University of Queensland
  1250. # 07-Jan-04
  1251. #
  1252. # Modifications by C. Schenkel
  1253. # Netcetera
  1254. # 31-Oct-13
  1255. #
  1256. ###########################################################################
  1257. def Minimize_create_new_point(c1, p1, c2, p2):
  1258. """
  1259. Create a new N-dimensional point as a weighting of points p1 and p2.
  1260. """
  1261. p_new = []
  1262. for j in range(len(p1)):
  1263. p_new.append(c1 * p1[j] + c2 * p2[j])
  1264. return p_new
  1265. Minimize_create_new_point = staticmethod(Minimize_create_new_point)
  1266. def Minimize_take_a_step(smplx, Kreflect, Kextend, Kcontract):
  1267. """
  1268. Try to move away from the worst point in the simplex.
  1269. The new point will be inserted into the simplex (in place).
  1270. """
  1271. i_low = smplx.lowest()
  1272. i_high = smplx.highest()
  1273. x_high = smplx.vertex_list[i_high]
  1274. f_high = smplx.f_list[i_high]
  1275. # Centroid of simplex excluding worst point.
  1276. x_mid = smplx.centroid(i_high)
  1277. f_mid = smplx.f(x_mid)
  1278. smplx.nfe += 1
  1279. # First, try moving away from worst point by
  1280. # reflection through centroid
  1281. x_refl = VLAB.Minimize_create_new_point(1.0+Kreflect, x_mid, -Kreflect, x_high)
  1282. f_refl = smplx.f(x_refl)
  1283. smplx.nfe += 1
  1284. if f_refl < f_mid:
  1285. # The reflection through the centroid is good,
  1286. # try to extend in the same direction.
  1287. x_ext = VLAB.Minimize_create_new_point(Kextend, x_refl, 1.0-Kextend, x_mid)
  1288. f_ext = smplx.f(x_ext)
  1289. smplx.nfe += 1
  1290. if f_ext < f_refl:
  1291. # Keep the extension because it's best.
  1292. smplx.replace_vertex(i_high, x_ext, f_ext)
  1293. else:
  1294. # S

Large files files are truncated, but you can click here to view the full file