esa-snappy 1.1.0__cp39-none-any.whl → 1.1.2__cp39-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esa_snappy/snapista/graph.py +118 -90
- esa_snappy/snapista/operator.py +57 -18
- esa_snappy/snapista/operatorparams.py +0 -2
- esa_snappy/snapista/target_band.py +5 -9
- {esa_snappy-1.1.0.dist-info → esa_snappy-1.1.2.dist-info}/METADATA +1 -1
- {esa_snappy-1.1.0.dist-info → esa_snappy-1.1.2.dist-info}/RECORD +9 -9
- {esa_snappy-1.1.0.dist-info → esa_snappy-1.1.2.dist-info}/WHEEL +1 -1
- {esa_snappy-1.1.0.dist-info → esa_snappy-1.1.2.dist-info}/licenses/LICENSE +0 -0
- {esa_snappy-1.1.0.dist-info → esa_snappy-1.1.2.dist-info}/top_level.txt +0 -0
esa_snappy/snapista/graph.py
CHANGED
|
@@ -3,6 +3,7 @@ import subprocess
|
|
|
3
3
|
import tempfile
|
|
4
4
|
import platform
|
|
5
5
|
import lxml.etree as etree
|
|
6
|
+
import re
|
|
6
7
|
from esa_snappy import GPF
|
|
7
8
|
from xml.sax.saxutils import unescape
|
|
8
9
|
from esa_snappy.snapista.binning.output_bands import BinningOutputBands
|
|
@@ -19,7 +20,6 @@ class Graph:
|
|
|
19
20
|
Attributes:
|
|
20
21
|
None.
|
|
21
22
|
"""
|
|
22
|
-
|
|
23
23
|
def __init__(self, wdir=".", root=None):
|
|
24
24
|
|
|
25
25
|
if root is None:
|
|
@@ -27,7 +27,6 @@ class Graph:
|
|
|
27
27
|
|
|
28
28
|
version = etree.SubElement(self.root, "version")
|
|
29
29
|
version.text = "1.0"
|
|
30
|
-
|
|
31
30
|
else:
|
|
32
31
|
self.root = root
|
|
33
32
|
|
|
@@ -37,7 +36,6 @@ class Graph:
|
|
|
37
36
|
self.gpt_path = self.get_gpt_cmd()
|
|
38
37
|
|
|
39
38
|
if not self.gpt_path:
|
|
40
|
-
|
|
41
39
|
raise Exception("gpt not found")
|
|
42
40
|
|
|
43
41
|
def __str__(self):
|
|
@@ -65,11 +63,8 @@ class Graph:
|
|
|
65
63
|
gpt_executable = "gpt"
|
|
66
64
|
|
|
67
65
|
for p in os.getenv("PATH").split(path_split_char):
|
|
68
|
-
|
|
69
66
|
if os.path.exists(os.path.join(p, gpt_executable)):
|
|
70
|
-
|
|
71
67
|
gpt_cmd = os.path.join(p, gpt_executable)
|
|
72
|
-
|
|
73
68
|
break
|
|
74
69
|
|
|
75
70
|
return gpt_cmd
|
|
@@ -99,11 +94,11 @@ class Graph:
|
|
|
99
94
|
snap_operators = []
|
|
100
95
|
|
|
101
96
|
while op_spi_it.hasNext():
|
|
102
|
-
|
|
103
97
|
op_spi = op_spi_it.next()
|
|
104
|
-
|
|
105
98
|
snap_operators.append(op_spi.getOperatorAlias())
|
|
106
99
|
|
|
100
|
+
print('Number of operators provided by SNAP: ' + str(len(snap_operators)))
|
|
101
|
+
|
|
107
102
|
return snap_operators
|
|
108
103
|
|
|
109
104
|
@staticmethod
|
|
@@ -132,45 +127,19 @@ class Graph:
|
|
|
132
127
|
)
|
|
133
128
|
|
|
134
129
|
while op_spi_it.hasNext():
|
|
135
|
-
|
|
136
130
|
op_spi = op_spi_it.next()
|
|
137
|
-
|
|
138
131
|
alias = op_spi.getOperatorDescriptor().getAlias()
|
|
139
132
|
description = op_spi.getOperatorDescriptor().getDescription()
|
|
133
|
+
src_prod_descriptors = op_spi.getOperatorDescriptor().getSourceProductDescriptors()
|
|
134
|
+
if src_prod_descriptors is not None and len(src_prod_descriptors) > 0:
|
|
135
|
+
src_prod_id = src_prod_descriptors.get(0)
|
|
136
|
+
print('describe_operators src_prod_id: ' + src_prod_id)
|
|
140
137
|
|
|
141
138
|
desc_dict[alias] = description
|
|
142
139
|
print("{} - {}".format(alias, description))
|
|
143
140
|
|
|
144
141
|
return desc_dict
|
|
145
142
|
|
|
146
|
-
# todo: seems that this is not needed. Check.
|
|
147
|
-
def nice_view(self):
|
|
148
|
-
|
|
149
|
-
try:
|
|
150
|
-
from pygments import highlight
|
|
151
|
-
from pygments.lexers import XmlLexer
|
|
152
|
-
from pygments.formatters import HtmlFormatter
|
|
153
|
-
import IPython
|
|
154
|
-
from IPython.display import HTML
|
|
155
|
-
|
|
156
|
-
def display_xml_nice(xml):
|
|
157
|
-
formatter = HtmlFormatter()
|
|
158
|
-
IPython.display.display(
|
|
159
|
-
HTML(
|
|
160
|
-
'<style type="text/css">{}</style> {}'.format(
|
|
161
|
-
formatter.get_style_defs(".highlight"),
|
|
162
|
-
highlight(xml, XmlLexer(), formatter),
|
|
163
|
-
)
|
|
164
|
-
)
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
display_xml_nice(etree.tostring(self.root, pretty_print=True))
|
|
168
|
-
|
|
169
|
-
except ModuleNotFoundError:
|
|
170
|
-
|
|
171
|
-
print(etree.tostring(self.root, pretty_print=True).decode("utf-8")).replace(
|
|
172
|
-
"\\n", "\n"
|
|
173
|
-
)
|
|
174
143
|
|
|
175
144
|
def view(self):
|
|
176
145
|
"""This method prints SNAP Graph
|
|
@@ -184,8 +153,74 @@ class Graph:
|
|
|
184
153
|
Raises:
|
|
185
154
|
None.
|
|
186
155
|
"""
|
|
156
|
+
#print(unescape(etree.tostring(self.root, pretty_print=True).decode("utf-8")).replace("&", "&"))
|
|
187
157
|
print(unescape(etree.tostring(self.root, pretty_print=True).decode("utf-8")))
|
|
188
158
|
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def remove_duplicate_tag(parameter_elem, root_tag):
|
|
162
|
+
"""This method removes duplicated tags in a xml etree element with a given root tag
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
parameter_elem: the XML element
|
|
166
|
+
root_tag: the root tag of the element
|
|
167
|
+
Returns
|
|
168
|
+
None.
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
None.
|
|
172
|
+
"""
|
|
173
|
+
for tagn in parameter_elem.iter(root_tag):
|
|
174
|
+
if tagn.getparent().getparent() is not None and tagn.getparent().getparent().tag == root_tag:
|
|
175
|
+
ipar_of_parent = tagn.getparent().getparent()
|
|
176
|
+
i_parent = tagn.getparent()
|
|
177
|
+
if ipar_of_parent.text is None:
|
|
178
|
+
ipar_of_parent.addnext(i_parent)
|
|
179
|
+
ipar_of_parent.getparent().remove(ipar_of_parent)
|
|
180
|
+
elif tagn.getparent() is not None and tagn.getparent().tag == root_tag:
|
|
181
|
+
i_parent = tagn.getparent()
|
|
182
|
+
if i_parent.text is None:
|
|
183
|
+
i_parent.addnext(tagn)
|
|
184
|
+
i_parent.getparent().remove(i_parent)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def append_merge_op_nested_param(self, operator, parameter_elem, param):
|
|
188
|
+
print('special case: nested parameter <' + param + '>' )
|
|
189
|
+
# we want to get this:
|
|
190
|
+
# '<exclude><productId>Read</productId><namePattern>Oa.*radiance</namePattern></exclude><exclude><productId>vicarious</productId><namePattern>Oa12_radiance</namePattern></exclude>'
|
|
191
|
+
# transformed to:
|
|
192
|
+
# <excludes>
|
|
193
|
+
# <exclude>
|
|
194
|
+
# <productId>Read</productId>
|
|
195
|
+
# <namePattern>Oa.*radiance</namePattern>
|
|
196
|
+
# </exclude>
|
|
197
|
+
# <exclude>
|
|
198
|
+
# <productId>vicarious</productId>
|
|
199
|
+
# <namePattern>Oa12_radiance</namePattern>
|
|
200
|
+
# </exclude>
|
|
201
|
+
# </excludes>
|
|
202
|
+
|
|
203
|
+
open_tag = '<' + param + '>'
|
|
204
|
+
close_tag = '</' + param + '>'
|
|
205
|
+
nested_param = open_tag + getattr(operator, param) + close_tag
|
|
206
|
+
if nested_param is not None:
|
|
207
|
+
nested_param_elems = nested_param.split('</' + param + '>')
|
|
208
|
+
|
|
209
|
+
pattern = '<' + param + '>' + '<' + param[:-1] + '>' + \
|
|
210
|
+
'<productId>.*</productId><namePattern>.*</namePattern>' + '</' + param[:-1] + '>'
|
|
211
|
+
valid = True
|
|
212
|
+
for elem in nested_param_elems:
|
|
213
|
+
x = re.match(pattern, elem)
|
|
214
|
+
print (elem)
|
|
215
|
+
if x is None and len(elem) > 0:
|
|
216
|
+
valid = False
|
|
217
|
+
print('WARNING: malforatted nested parameter: ' + elem)
|
|
218
|
+
|
|
219
|
+
if valid:
|
|
220
|
+
parameter_elem.append(etree.fromstring(nested_param))
|
|
221
|
+
self.remove_duplicate_tag(parameter_elem, param)
|
|
222
|
+
|
|
223
|
+
|
|
189
224
|
def add_node(self, operator, node_id, source=None):
|
|
190
225
|
"""This method adds or overwrites a node to the SNAP Graph
|
|
191
226
|
|
|
@@ -200,13 +235,14 @@ class Graph:
|
|
|
200
235
|
Raises:
|
|
201
236
|
None.
|
|
202
237
|
"""
|
|
238
|
+
#print('entering add_node...')
|
|
239
|
+
|
|
203
240
|
xpath_expr = '/graph/node[@id="%s"]' % node_id
|
|
204
241
|
|
|
205
242
|
if len(self.root.xpath(xpath_expr)) != 0:
|
|
206
243
|
|
|
207
244
|
node_elem = self.root.xpath(xpath_expr)[0]
|
|
208
245
|
operator_elem = self.root.xpath(xpath_expr + "/operator")[0]
|
|
209
|
-
sources_elem = self.root.xpath(xpath_expr + "/sources")[0]
|
|
210
246
|
parameters_elem = self.root.xpath(xpath_expr + "/parameters")
|
|
211
247
|
|
|
212
248
|
for param in [
|
|
@@ -236,7 +272,11 @@ class Graph:
|
|
|
236
272
|
"productCustomizerConfig",
|
|
237
273
|
]:
|
|
238
274
|
|
|
239
|
-
if
|
|
275
|
+
if param in ["bandConfigurations",
|
|
276
|
+
"variableConfigs",
|
|
277
|
+
"postProcessorConfig",
|
|
278
|
+
"productCustomizerConfig"] and not getattr(operator, param):
|
|
279
|
+
continue
|
|
240
280
|
|
|
241
281
|
if (
|
|
242
282
|
isinstance(getattr(operator, param), TargetBandDescriptors)
|
|
@@ -247,12 +287,8 @@ class Graph:
|
|
|
247
287
|
parameters_elem.append(getattr(operator, param).to_xml())
|
|
248
288
|
|
|
249
289
|
elif isinstance(getattr(operator, param), str):
|
|
250
|
-
|
|
251
|
-
parameters_elem.append(
|
|
252
|
-
etree.fromstring(getattr(operator, param))
|
|
253
|
-
)
|
|
290
|
+
parameters_elem.append(etree.fromstring(getattr(operator, param)))
|
|
254
291
|
else:
|
|
255
|
-
|
|
256
292
|
raise ValueError()
|
|
257
293
|
|
|
258
294
|
else:
|
|
@@ -263,9 +299,8 @@ class Graph:
|
|
|
263
299
|
if getattr(operator, param)[0] != "<":
|
|
264
300
|
p_elem.text = getattr(operator, param)
|
|
265
301
|
else:
|
|
266
|
-
|
|
267
|
-
etree.fromstring(getattr(operator, param))
|
|
268
|
-
)
|
|
302
|
+
if param != 'excludes':
|
|
303
|
+
p_elem.text.append(etree.fromstring(getattr(operator, param)))
|
|
269
304
|
except IndexError:
|
|
270
305
|
pass
|
|
271
306
|
|
|
@@ -274,31 +309,24 @@ class Graph:
|
|
|
274
309
|
node_elem = etree.SubElement(self.root, "node")
|
|
275
310
|
operator_elem = etree.SubElement(node_elem, "operator")
|
|
276
311
|
sources_elem = etree.SubElement(node_elem, "sources")
|
|
312
|
+
|
|
313
|
+
src_prod_id = operator.get_src_product_id()
|
|
314
|
+
if src_prod_id is None:
|
|
315
|
+
src_prod_id = 'source'
|
|
277
316
|
|
|
278
317
|
if isinstance(source, list):
|
|
279
|
-
|
|
280
318
|
for index, s in enumerate(source):
|
|
281
319
|
if index == 0:
|
|
282
|
-
source_product_elem = etree.SubElement(
|
|
283
|
-
sources_elem, "sourceProduct"
|
|
284
|
-
)
|
|
285
|
-
|
|
320
|
+
source_product_elem = etree.SubElement(sources_elem, src_prod_id)
|
|
286
321
|
else:
|
|
287
|
-
source_product_elem = etree.SubElement(
|
|
288
|
-
sources_elem, "sourceProduct.%s" % str(index)
|
|
289
|
-
)
|
|
290
|
-
|
|
322
|
+
source_product_elem = etree.SubElement(sources_elem, "source.%s" % str(index))
|
|
291
323
|
source_product_elem.attrib["refid"] = s
|
|
292
|
-
|
|
293
324
|
elif isinstance(source, dict):
|
|
294
|
-
|
|
295
325
|
for key, value in source.iteritems():
|
|
296
|
-
|
|
297
326
|
source_product_elem = etree.SubElement(sources_elem, key)
|
|
298
327
|
source_product_elem.text = value
|
|
299
|
-
|
|
300
328
|
elif source is not None:
|
|
301
|
-
source_product_elem = etree.SubElement(sources_elem,
|
|
329
|
+
source_product_elem = etree.SubElement(sources_elem, src_prod_id)
|
|
302
330
|
source_product_elem.attrib["refid"] = source
|
|
303
331
|
|
|
304
332
|
parameters_elem = etree.SubElement(node_elem, "parameters")
|
|
@@ -331,46 +359,48 @@ class Graph:
|
|
|
331
359
|
"productCustomizerConfig",
|
|
332
360
|
]:
|
|
333
361
|
print(param, getattr(operator, param))
|
|
334
|
-
if
|
|
362
|
+
if param in ["bandConfigurations",
|
|
363
|
+
"variableConfigs",
|
|
364
|
+
"postProcessorConfig",
|
|
365
|
+
"productCustomizerConfig"] and not getattr(operator, param): continue
|
|
335
366
|
|
|
336
367
|
print('Instance TargetBandDescriptors: ' + str(isinstance(getattr(operator, param), TargetBandDescriptors)))
|
|
337
368
|
print('Instance Aggregators: ' + str(isinstance(getattr(operator, param), Aggregators)))
|
|
338
369
|
print('Instance BinningOutputBands: ' + str(isinstance(getattr(operator, param), BinningOutputBands)))
|
|
339
370
|
print('Instance BinningVariables: ' + str(isinstance(getattr(operator, param), BinningVariables)))
|
|
340
371
|
print('Instance str: ' + str(isinstance(getattr(operator, param), str)))
|
|
372
|
+
|
|
341
373
|
if (
|
|
342
374
|
isinstance(getattr(operator, param), TargetBandDescriptors)
|
|
343
375
|
or isinstance(getattr(operator, param), Aggregators)
|
|
344
376
|
or isinstance(getattr(operator, param), BinningOutputBands)
|
|
345
377
|
or isinstance(getattr(operator, param), BinningVariables)
|
|
346
378
|
):
|
|
347
|
-
|
|
348
379
|
parameters_elem.append(getattr(operator, param).to_xml())
|
|
349
|
-
|
|
350
380
|
elif isinstance(getattr(operator, param), str):
|
|
351
|
-
|
|
352
|
-
parameters_elem.append(
|
|
353
|
-
etree.fromstring(getattr(operator, param))
|
|
354
|
-
)
|
|
381
|
+
parameters_elem.append(etree.fromstring(getattr(operator, param)))
|
|
355
382
|
else:
|
|
356
383
|
|
|
357
384
|
raise ValueError()
|
|
358
385
|
|
|
359
386
|
else:
|
|
360
|
-
|
|
361
387
|
parameter_elem = etree.SubElement(parameters_elem, param)
|
|
362
|
-
|
|
363
388
|
if getattr(operator, param) is not None:
|
|
364
|
-
|
|
365
|
-
|
|
389
|
+
# special case: 'Merge' operator which has nested parameters 'excludes' and 'includes'
|
|
390
|
+
if operator.operator == 'Merge' and (param == 'excludes' or param == 'includes'):
|
|
391
|
+
self.append_merge_op_nested_param(operator, parameter_elem, param)
|
|
366
392
|
else:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
393
|
+
if getattr(operator, param)[0] != "<":
|
|
394
|
+
parameter_elem.text = getattr(operator, param)
|
|
395
|
+
else:
|
|
396
|
+
parameter_elem.append(
|
|
397
|
+
etree.fromstring(getattr(operator, param))
|
|
398
|
+
)
|
|
370
399
|
|
|
371
400
|
node_elem.attrib["id"] = node_id
|
|
372
401
|
|
|
373
402
|
operator_elem.text = operator.operator
|
|
403
|
+
|
|
374
404
|
|
|
375
405
|
def save_graph(self, filename):
|
|
376
406
|
"""This method saves the SNAP Graph
|
|
@@ -387,9 +417,10 @@ class Graph:
|
|
|
387
417
|
|
|
388
418
|
with open(filename, "w") as file:
|
|
389
419
|
file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
|
|
420
|
+
#file.write(unescape(etree.tostring(self.root, pretty_print=True).decode()).replace("&", "&"))
|
|
390
421
|
file.write(unescape(etree.tostring(self.root, pretty_print=True).decode()))
|
|
391
422
|
|
|
392
|
-
def run(self, gpt_options=
|
|
423
|
+
def run(self, gpt_options=None):
|
|
393
424
|
"""This method runs the SNAP Graph using gpt
|
|
394
425
|
|
|
395
426
|
Args:
|
|
@@ -403,14 +434,17 @@ class Graph:
|
|
|
403
434
|
None.
|
|
404
435
|
"""
|
|
405
436
|
|
|
406
|
-
|
|
437
|
+
if gpt_options is None:
|
|
438
|
+
gpt_options = ["-x", "-c", "1024M"]
|
|
407
439
|
|
|
408
|
-
|
|
440
|
+
def _run_command(command, **kwargs):
|
|
441
|
+
process = subprocess.Popen(args=command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
|
|
409
442
|
# todo: this hangs in the while loop. Check why!
|
|
410
443
|
#while True:
|
|
411
444
|
# output = process.stdout.readline()
|
|
412
445
|
# err = process.stderr.readline()
|
|
413
|
-
#
|
|
446
|
+
# return_code = process.poll()
|
|
447
|
+
# if output.decode() == "" and return_code is not None:
|
|
414
448
|
# break
|
|
415
449
|
# if output:
|
|
416
450
|
# print(output.strip().decode())
|
|
@@ -418,35 +452,29 @@ class Graph:
|
|
|
418
452
|
# print(err.strip().decode())
|
|
419
453
|
|
|
420
454
|
# this works, but output (i.e. gpt progress) is not written before subprocess finished. todo: try to improve
|
|
421
|
-
process = subprocess.Popen(args=command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
|
|
422
455
|
out, err = process.communicate()
|
|
423
456
|
if out:
|
|
424
|
-
|
|
457
|
+
print ('standard output of subprocess: ')
|
|
425
458
|
print (out.strip().decode())
|
|
426
459
|
if err:
|
|
427
|
-
|
|
460
|
+
print ('standard error of subprocess: ')
|
|
428
461
|
print (err.strip().decode())
|
|
429
462
|
|
|
430
|
-
|
|
463
|
+
return_code = process.poll()
|
|
431
464
|
|
|
432
|
-
return
|
|
465
|
+
return return_code
|
|
433
466
|
|
|
434
467
|
os.environ["LD_LIBRARY_PATH"] = "."
|
|
435
468
|
|
|
436
469
|
print("Processing the graph, this may take a while. Please wait...")
|
|
437
470
|
|
|
438
471
|
fd, path = tempfile.mkstemp()
|
|
439
|
-
|
|
440
472
|
rc = None
|
|
441
473
|
|
|
442
474
|
try:
|
|
443
|
-
|
|
444
475
|
self.save_graph(filename=path)
|
|
445
|
-
|
|
446
476
|
options = [self.gpt_path, *gpt_options, path]
|
|
447
|
-
|
|
448
477
|
rc = _run_command(options)
|
|
449
|
-
|
|
450
478
|
finally:
|
|
451
479
|
try:
|
|
452
480
|
os.remove(path)
|
esa_snappy/snapista/operator.py
CHANGED
|
@@ -5,36 +5,31 @@ from .operatorparams import OperatorParams
|
|
|
5
5
|
|
|
6
6
|
class Operator(SimpleNamespace):
|
|
7
7
|
def __init__(self, operator, **kwargs):
|
|
8
|
-
|
|
9
8
|
self.operator = operator
|
|
10
9
|
self._params = {**OperatorParams(self.operator).params, **kwargs}
|
|
11
10
|
|
|
12
11
|
return super().__init__(**self._params)
|
|
13
12
|
|
|
14
13
|
def __str__(self):
|
|
15
|
-
|
|
16
14
|
return "{}:\n\t{}".format(
|
|
17
15
|
self.operator, "\n\t".join(["{}='{}'".format(key, value) for key, value in self.to_dict().items()])
|
|
18
16
|
)
|
|
19
17
|
|
|
20
18
|
def __repr__(self):
|
|
21
|
-
|
|
22
19
|
return "Operator('{}', {})".format(
|
|
23
20
|
self.operator, ", ".join(["{}='{}'".format(key, value) for key, value in self.to_dict().items()])
|
|
24
21
|
)
|
|
25
22
|
|
|
26
23
|
def to_dict(self):
|
|
27
|
-
|
|
28
24
|
return dict([(name, getattr(self, name)) for name in list(self._params.keys())])
|
|
29
25
|
|
|
30
26
|
def describe(self):
|
|
31
|
-
"""This function prints the human
|
|
27
|
+
"""This function prints the human-readable information about a SNAP operator
|
|
32
28
|
|
|
33
29
|
Args:
|
|
34
|
-
operator: SNAP operator
|
|
35
30
|
|
|
36
31
|
Returns
|
|
37
|
-
The human
|
|
32
|
+
The human-readable information about the provided SNAP operator.
|
|
38
33
|
|
|
39
34
|
Raises:
|
|
40
35
|
None.
|
|
@@ -46,10 +41,15 @@ class Operator(SimpleNamespace):
|
|
|
46
41
|
print("Authors: {}\n".format(op_spi.getOperatorDescriptor().getAuthors()))
|
|
47
42
|
print("{}".format(op_spi.getOperatorDescriptor().getName()))
|
|
48
43
|
print("Version: {}\n".format(op_spi.getOperatorDescriptor().getVersion()))
|
|
44
|
+
print("Sources:\n")
|
|
45
|
+
source_desc = op_spi.getOperatorDescriptor().getSourceProductDescriptors()
|
|
46
|
+
for src in source_desc:
|
|
47
|
+
print('getSourceProductDescriptors src name: ' + src.getName())
|
|
48
|
+
|
|
49
49
|
print("Parameters:\n")
|
|
50
|
-
|
|
50
|
+
param_desc = op_spi.getOperatorDescriptor().getParameterDescriptors()
|
|
51
51
|
|
|
52
|
-
for param in
|
|
52
|
+
for param in param_desc:
|
|
53
53
|
print(
|
|
54
54
|
"\t{}: {}\n\t\tDefault Value: {}\n".format(
|
|
55
55
|
param.getName(), param.getDescription(), param.getDefaultValue()
|
|
@@ -57,20 +57,59 @@ class Operator(SimpleNamespace):
|
|
|
57
57
|
)
|
|
58
58
|
|
|
59
59
|
if self.operator == "Write" and param.getName() == "formatName":
|
|
60
|
-
|
|
61
60
|
print("\t\tPossible values: {}\n".format(self._get_formats("Write")))
|
|
62
|
-
|
|
63
61
|
elif self.operator == "Read" and param.getName() == "formatName":
|
|
64
|
-
|
|
65
62
|
print("\t\tPossible values: {}\n".format(self._get_formats("Read")))
|
|
66
|
-
|
|
67
63
|
else:
|
|
68
|
-
|
|
69
64
|
print("\t\tPossible values: {}\n".format(list(param.getValueSet())))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def get_src_product_id(self):
|
|
68
|
+
"""This function returns the reference single source product identifier as specified in the Operator.
|
|
69
|
+
It is not unique in SNAP, can be e.g. 'source', 'sourceProduct', 'l1BProduct' etc.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
The source product identifier as specified in the SNAP Operator.
|
|
75
|
+
|
|
76
|
+
Raises:
|
|
77
|
+
None.
|
|
78
|
+
"""
|
|
79
|
+
op_spi = GPF.getDefaultInstance().getOperatorSpiRegistry().getOperatorSpi(self.operator)
|
|
80
|
+
source_descr = op_spi.getOperatorDescriptor().getSourceProductDescriptors()
|
|
81
|
+
if len(source_descr) > 0:
|
|
82
|
+
return source_descr[0].getName()
|
|
83
|
+
else:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def get_src_product_ids(self):
|
|
87
|
+
"""This function returns the source product identifiers as specified in the Operator.
|
|
88
|
+
They are not unique in SNAP, can be e.g. 'source', 'sourceProduct', 'l1BProduct' etc.
|
|
89
|
+
There can be more than one, e.g. for 'Collocate' operator: 'reference' and 'secondary'
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
The source product identifier as specified in the SNAP Operator.
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
None.
|
|
98
|
+
"""
|
|
99
|
+
op_spi = GPF.getDefaultInstance().getOperatorSpiRegistry().getOperatorSpi(self.operator)
|
|
100
|
+
source_descr = op_spi.getOperatorDescriptor().getSourceProductDescriptors()
|
|
101
|
+
if len(source_descr) > 0:
|
|
102
|
+
src_descr_names = []
|
|
103
|
+
for index, src in enumerate(source_descr):
|
|
104
|
+
src_descr_names.append(src[index].getName())
|
|
105
|
+
return src_descr_names
|
|
106
|
+
else:
|
|
107
|
+
return None
|
|
108
|
+
|
|
70
109
|
|
|
71
110
|
@staticmethod
|
|
72
111
|
def _get_formats(method):
|
|
73
|
-
"""This function provides a human
|
|
112
|
+
"""This function provides a human-readable list of SNAP Read or Write operator formats.
|
|
74
113
|
|
|
75
114
|
Args:
|
|
76
115
|
None.
|
|
@@ -81,12 +120,12 @@ class Operator(SimpleNamespace):
|
|
|
81
120
|
Raises:
|
|
82
121
|
None.
|
|
83
122
|
"""
|
|
84
|
-
|
|
123
|
+
product_io_plug_in_manager = jpy.get_type("org.esa.snap.core.dataio.product_io_plug_in_manager")
|
|
85
124
|
|
|
86
125
|
if method == "Read":
|
|
87
|
-
plugins =
|
|
126
|
+
plugins = product_io_plug_in_manager.getInstance().getAllReaderPlugIns()
|
|
88
127
|
elif method == "Write":
|
|
89
|
-
plugins =
|
|
128
|
+
plugins = product_io_plug_in_manager.getInstance().getAllWriterPlugIns()
|
|
90
129
|
else:
|
|
91
130
|
raise ValueError
|
|
92
131
|
|
|
@@ -12,7 +12,6 @@ class OperatorParams:
|
|
|
12
12
|
"""This function returns the SNAP operator ParameterDescriptors (snappy method op_spi.getOperatorDescriptor().getParameterDescriptors())
|
|
13
13
|
|
|
14
14
|
Args:
|
|
15
|
-
operator: SNAP operator
|
|
16
15
|
|
|
17
16
|
Returns
|
|
18
17
|
The snappy object returned by op_spi.getOperatorDescriptor().getParameterDescriptors().
|
|
@@ -30,7 +29,6 @@ class OperatorParams:
|
|
|
30
29
|
"""This function returns a Python dictionary with the SNAP operator parameters and their default values, if available.
|
|
31
30
|
|
|
32
31
|
Args:
|
|
33
|
-
operator: SNAP operator
|
|
34
32
|
|
|
35
33
|
Returns
|
|
36
34
|
A Python dictionary with the SNAP operator parameters and their default values.
|
|
@@ -15,30 +15,26 @@ class TargetBand(object):
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def __str__(self):
|
|
18
|
-
|
|
19
18
|
return self.__repr__()
|
|
20
19
|
|
|
21
20
|
def __repr__(self):
|
|
22
|
-
|
|
23
21
|
return "TargetBand({})".format(
|
|
24
22
|
", ".join(["{}='{}'".format(key, value) for key, value in self.to_dict().items()])
|
|
25
23
|
)
|
|
26
24
|
|
|
27
25
|
def to_dict(self):
|
|
28
|
-
|
|
29
26
|
return attr.asdict(self)
|
|
30
27
|
|
|
31
28
|
def to_xml(self):
|
|
32
|
-
|
|
33
29
|
root = etree.Element("targetBand")
|
|
34
30
|
|
|
35
31
|
for key, value in self.to_dict().items():
|
|
36
|
-
|
|
37
32
|
elem = etree.SubElement(root, key)
|
|
38
33
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
elem.text = value
|
|
35
|
+
#if key == 'expression':
|
|
36
|
+
# elem.text = escape(value)
|
|
37
|
+
#else:
|
|
38
|
+
# elem.text = value
|
|
43
39
|
|
|
44
40
|
return root
|
|
@@ -14,11 +14,11 @@ esa_snappy/lib/jpy-1.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.
|
|
|
14
14
|
esa_snappy/lib/jpy-1.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl,sha256=nPANBkNHRfyfJayf7RHQpdJDxrlgbAWNq_URmffR520,391227
|
|
15
15
|
esa_snappy/lib/jpy-1.0.0-cp39-cp39-win_amd64.whl,sha256=R4d5H1Nq2CDVwiev07PLuQgIRD5CEAB0smoLq9_V14w,124091
|
|
16
16
|
esa_snappy/snapista/__init__.py,sha256=UoFdyRO7zKbvdzCK9PeRb2EgChNPso3DbwypPztG0cw,230
|
|
17
|
-
esa_snappy/snapista/graph.py,sha256=
|
|
17
|
+
esa_snappy/snapista/graph.py,sha256=zXUq_0SLzYrOuGSZfr4dwNlAHRpuaV7N-4G8eyvGH94,18101
|
|
18
18
|
esa_snappy/snapista/graph_io.py,sha256=tk5lUG9Wg6PtGeJTO7fi8Wvm-kagbvAdlowTdAKWSn4,377
|
|
19
|
-
esa_snappy/snapista/operator.py,sha256=
|
|
20
|
-
esa_snappy/snapista/operatorparams.py,sha256=
|
|
21
|
-
esa_snappy/snapista/target_band.py,sha256=
|
|
19
|
+
esa_snappy/snapista/operator.py,sha256=_C5qSXaIHm-p9aEmli2uC2t3SNIBojORGrpS2FfbFRg,5245
|
|
20
|
+
esa_snappy/snapista/operatorparams.py,sha256=kN0yNfxPUEffHX81d-3jxzHfhTupGVrWMigfY6z1tnQ,1307
|
|
21
|
+
esa_snappy/snapista/target_band.py,sha256=xi9PA_ab3T0w9_eBbRmgnBeuBjuNidICMfNXGiGi1Tk,1001
|
|
22
22
|
esa_snappy/snapista/target_band_descriptors.py,sha256=PRFSjJCB7Lgy0IESFnIased1Cj6J3A-iT5SoG9UP3S0,412
|
|
23
23
|
esa_snappy/snapista/binning/__init__.py,sha256=iRK9Q63y-tMastSzG1F6JDZJg-u_VMEVCnnl5kelYao,219
|
|
24
24
|
esa_snappy/snapista/binning/aggregator_avg.py,sha256=rBaDK060oiiQvo2V2kJUZr4oFgZFaTFlP9HfyfcyL5M,1707
|
|
@@ -108,8 +108,8 @@ esa_snappy/tests/__init__.py,sha256=F4oR5lxuvk4xsRSJ65fkZPrsrfPD8fNVbhSuAyHox7Q,
|
|
|
108
108
|
esa_snappy/tests/test_snappy_mem.py,sha256=5UeN4A5-kgV534eRforf6OqO0UbqcTbREeRVvUqeU9A,971
|
|
109
109
|
esa_snappy/tests/test_snappy_perf.py,sha256=W1nlzDzvmbhDNc4ma4u5m4qRjEjLIU-gCbKzLkHdIwM,1710
|
|
110
110
|
esa_snappy/tests/test_snappy_product.py,sha256=zCPMOTQ3zoRN0OLLMy7NsHd7YuZnsa2loYGcD9Ehf3A,3564
|
|
111
|
-
esa_snappy-1.1.
|
|
112
|
-
esa_snappy-1.1.
|
|
113
|
-
esa_snappy-1.1.
|
|
114
|
-
esa_snappy-1.1.
|
|
115
|
-
esa_snappy-1.1.
|
|
111
|
+
esa_snappy-1.1.2.dist-info/licenses/LICENSE,sha256=WhZlPzkdURd2lAAvpQrjy1tIXgkmxrKFS45OPs2PxPM,1105
|
|
112
|
+
esa_snappy-1.1.2.dist-info/METADATA,sha256=03WGGIDrrteYBIsQ24LOJWzDXvf9jLX8tPOSXvvBiug,2545
|
|
113
|
+
esa_snappy-1.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
114
|
+
esa_snappy-1.1.2.dist-info/top_level.txt,sha256=Rp5J9LQi3dYksBH5aChaVvqyd0FecQA5byHcDTal2vk,11
|
|
115
|
+
esa_snappy-1.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|