esa-snappy 1.1.1__cp310-none-any.whl → 1.1.2__cp310-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.
Files changed (75) hide show
  1. esa_snappy/__init__.py +382 -382
  2. esa_snappy/examples/snappy_bmaths.py +59 -59
  3. esa_snappy/examples/snappy_flh.py +52 -52
  4. esa_snappy/examples/snappy_geo_roi.py +54 -54
  5. esa_snappy/examples/snappy_ndvi.py +76 -76
  6. esa_snappy/examples/snappy_ndvi_with_masks.py +72 -72
  7. esa_snappy/examples/snappy_reader_writer_formats.py +19 -19
  8. esa_snappy/examples/snappy_subset.py +34 -34
  9. esa_snappy/examples/snappy_write_image.py +103 -103
  10. esa_snappy/lib/jpy-1.0.0-cp310-cp310-macosx_12_0_universal2.whl +0 -0
  11. esa_snappy/lib/jpy-1.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl +0 -0
  12. esa_snappy/lib/jpy-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +0 -0
  13. esa_snappy/lib/jpy-1.0.0-cp310-cp310-win_amd64.whl +0 -0
  14. esa_snappy/snapista/__init__.py +5 -5
  15. esa_snappy/snapista/binning/__init__.py +5 -5
  16. esa_snappy/snapista/binning/aggregator_avg.py +68 -68
  17. esa_snappy/snapista/binning/aggregator_avg_outlier.py +46 -46
  18. esa_snappy/snapista/binning/aggregator_minmax.py +46 -46
  19. esa_snappy/snapista/binning/aggregator_on_max_set.py +47 -47
  20. esa_snappy/snapista/binning/aggregator_percentile.py +56 -56
  21. esa_snappy/snapista/binning/aggregator_sum.py +46 -46
  22. esa_snappy/snapista/binning/aggregators.py +23 -23
  23. esa_snappy/snapista/binning/binning_band.py +39 -39
  24. esa_snappy/snapista/binning/binning_variable.py +52 -52
  25. esa_snappy/snapista/binning/binning_variables.py +34 -34
  26. esa_snappy/snapista/binning/output_bands.py +34 -34
  27. esa_snappy/snapista/graph_io.py +18 -18
  28. esa_snappy/snapista/operatorparams.py +45 -45
  29. esa_snappy/snapista/target_band.py +39 -39
  30. esa_snappy/snapista/target_band_descriptors.py +18 -18
  31. esa_snappy/snappyutil.py +302 -302
  32. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/detector_index.hdr +13 -13
  33. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/l1_flags.hdr +13 -13
  34. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_1.hdr +14 -14
  35. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_10.hdr +14 -14
  36. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_11.hdr +14 -14
  37. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_12.hdr +14 -14
  38. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_13.hdr +14 -14
  39. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_14.hdr +14 -14
  40. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_15.hdr +14 -14
  41. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_2.hdr +14 -14
  42. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_3.hdr +14 -14
  43. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_4.hdr +14 -14
  44. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_5.hdr +14 -14
  45. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_6.hdr +14 -14
  46. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_7.hdr +14 -14
  47. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_8.hdr +14 -14
  48. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/radiance_9.hdr +14 -14
  49. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/atm_press.hdr +13 -13
  50. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/dem_alt.hdr +13 -13
  51. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/dem_rough.hdr +13 -13
  52. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/lat_corr.hdr +13 -13
  53. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/latitude.hdr +13 -13
  54. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/lon_corr.hdr +13 -13
  55. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/longitude.hdr +13 -13
  56. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/merid_wind.hdr +13 -13
  57. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/ozone.hdr +13 -13
  58. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/rel_hum.hdr +13 -13
  59. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/sun_azimuth.hdr +13 -13
  60. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/sun_zenith.hdr +13 -13
  61. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/view_azimuth.hdr +13 -13
  62. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/view_zenith.hdr +13 -13
  63. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/tie_point_grids/zonal_wind.hdr +13 -13
  64. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/vector_data/ground_control_points.csv +2 -2
  65. esa_snappy/testdata/MER_FRS_L1B_SUBSET.data/vector_data/pins.csv +2 -2
  66. esa_snappy/testdata/MER_FRS_L1B_SUBSET.dim +1208 -1208
  67. esa_snappy/tests/__init__.py +1 -1
  68. esa_snappy/tests/test_snappy_mem.py +34 -34
  69. esa_snappy/tests/test_snappy_perf.py +63 -63
  70. esa_snappy/tests/test_snappy_product.py +103 -103
  71. {esa_snappy-1.1.1.dist-info → esa_snappy-1.1.2.dist-info}/METADATA +1 -1
  72. {esa_snappy-1.1.1.dist-info → esa_snappy-1.1.2.dist-info}/RECORD +75 -71
  73. {esa_snappy-1.1.1.dist-info → esa_snappy-1.1.2.dist-info}/licenses/LICENSE +20 -20
  74. {esa_snappy-1.1.1.dist-info → esa_snappy-1.1.2.dist-info}/WHEEL +0 -0
  75. {esa_snappy-1.1.1.dist-info → esa_snappy-1.1.2.dist-info}/top_level.txt +0 -0
esa_snappy/__init__.py CHANGED
@@ -1,382 +1,382 @@
1
- """
2
- The esa_snappy module provides access to the Java SE APIs and SNAP Java APIs.
3
-
4
- You can configure esa_snappy by using a file named snappy.ini as follows:
5
-
6
- [DEFAULT]
7
- snap_home: C:/Program Files/snap
8
- java_class_path: target/classes
9
- java_library_path: target/lib/amd64
10
- java_options: -Djava.awt.headless=true
11
- java_max_mem: 4G
12
- debug: False
13
-
14
- You can place snappy.ini next to <python3>/site-packages/snappy.py or put it in your current working directory.
15
- The 'snap_home' options and all options starting with 'java_' are only used if you use the SNAP API from Python
16
- and a new Java Virtual Machine is created. They are ignored if the SNAP API is called from SNAP itself
17
- (e.g. SNAP command-line or GUI).
18
-
19
- 'esa_snappy' uses a bundled 'jpy' module, see documentation at http://jpy.readthedocs.org/en/latest
20
- and source code at https://github.com/bcdev/jpy
21
- """
22
-
23
- EXCLUDED_NB_CLUSTERS = {'platform', 'ide', 'bin', 'etc'}
24
-
25
- EXCLUDED_DIR_NAMES = {'org.esa.snap.snap-worldwind', 'org.esa.snap.snap-rcp', 'org.esa.snap.snap-product-library',
26
- 'org.esa.snap.snap-sta-ui'}
27
-
28
- EXCLUDED_JAR_NAMES = {'org-esa-snap-netbeans-docwin.jar', 'org-esa-snap-netbeans-tile.jar',
29
- 'org-esa-snap-snap-worldwind.jar', 'org-esa-snap-snap-tango.jar', 'org-esa-snap-snap-rcp.jar',
30
- 'org-esa-snap-snap-ui.jar', 'org-esa-snap-snap-graph-builder.jar',
31
- 'org-esa-snap-snap-branding.jar'}
32
-
33
- import glob
34
- import os
35
-
36
- import sys
37
-
38
- if sys.version_info >= (3, 0, 0,):
39
- # noinspection PyUnresolvedReferences
40
- import configparser as cp
41
- else:
42
- # noinspection PyUnresolvedReferences
43
- import ConfigParser as cp
44
-
45
- module_dir = os.path.dirname(os.path.realpath(__file__))
46
- module_ini = os.path.basename(module_dir) + '.ini'
47
-
48
- # Read configuration *.ini file from either '.', '<module_dir>/..', '<module_dir>' in this order
49
- config = cp.ConfigParser()
50
- config.read([os.path.join(module_dir, module_ini),
51
- os.path.join(os.path.join(module_dir, '..'), module_ini),
52
- module_ini
53
- ])
54
-
55
- debug = False
56
- if config.has_option('DEFAULT', 'debug'):
57
- debug = config.getboolean('DEFAULT', 'debug')
58
-
59
- # Pre-load Java VM shared library and import 'jpy', the Java-Python bridge
60
- if module_dir not in sys.path:
61
- sys.path.append(module_dir)
62
- import jpyutil
63
-
64
- jpyutil.preload_jvm_dll()
65
- import jpy
66
-
67
- if debug:
68
- # jpy.diag.F_OFF 0x00
69
- # jpy.diag.F_TYPE 0x01
70
- # jpy.diag.F_METH 0x02
71
- # jpy.diag.F_EXEC 0x04
72
- # jpy.diag.F_MEM 0x08
73
- # jpy.diag.F_JVM 0x10
74
- # jpy.diag.F_ERR 0x20
75
- # jpy.diag.F_ALL 0xff
76
- jpy.diag.flags = jpy.diag.F_EXEC + jpy.diag.F_ERR
77
-
78
-
79
- #
80
- # Recursively searches for JAR files in 'dir_path' and appends them to the first member of the
81
- # 'env' tuple (env[0] is the classpath). Also searches for 'lib/LIB_PLATFORM_NAMES[i]' and if one
82
- # exists, appends it to the second member of the 'env' tuple (env[1] is the java.library.path)
83
- # Note: Sub-directories named 'locale' or 'docs' are not searched and
84
- # JAR files ending with '-ui.jar' or '-examples.jar' are excluded.
85
- #
86
- # Note: This function is called only if the 'esa_snappy' module is not imported from Java.
87
- #
88
- def _collect_snap_jvm_env(dir_path, env):
89
- for name in os.listdir(dir_path):
90
- path = os.path.join(dir_path, name)
91
- if os.path.isfile(path) and name.endswith('.jar'):
92
- if not (name.endswith('-ui.jar') or name in EXCLUDED_JAR_NAMES):
93
- env[0][name] = path
94
- elif os.path.isdir(path) and name not in EXCLUDED_DIR_NAMES:
95
- if name == 'lib':
96
- import platform
97
-
98
- os_arch = platform.machine().lower()
99
- os_name = platform.system().lower()
100
- lib_os_arch_path = os.path.join(path, os_arch)
101
- if os.path.exists(lib_os_arch_path):
102
- lib_os_name_path = os.path.join(lib_os_arch_path, os_name)
103
- if os.path.exists(lib_os_name_path):
104
- env[1].append(lib_os_name_path)
105
- env[1].append(lib_os_arch_path)
106
- env[1].append(path)
107
- if not (name == 'locale' or name == 'docs'):
108
- _collect_snap_jvm_env(path, env)
109
-
110
-
111
- #
112
- # Get the NetBeans user directory for installed extra modules
113
- #
114
- def _get_nb_user_modules_dir():
115
- import platform
116
- from os.path import expanduser
117
-
118
- home_dir = expanduser('~')
119
- nb_user_dir = None
120
- if platform.system() == 'Windows':
121
- if home_dir:
122
- nb_user_dir = os.path.join(home_dir, 'AppData\\Roaming\\SNAP')
123
- else:
124
- if home_dir:
125
- nb_user_dir = os.path.join(home_dir, '.snap/system')
126
-
127
- if nb_user_dir:
128
- return os.path.join(nb_user_dir, 'modules')
129
-
130
- return None
131
-
132
-
133
- #
134
- # Searches for *.jar files in directory given by global 'snap_home' variable and returns them as a list.
135
- #
136
- # Note: This function is called only if the 'esa_snappy' module is not imported from Java.
137
- #
138
- def _get_snap_jvm_env():
139
- dir_names = []
140
- for name in os.listdir(snap_home):
141
- if os.path.isdir(os.path.join(snap_home, name)):
142
- dir_names.append(name)
143
-
144
- java_module_dirs = []
145
-
146
- if 'bin' in dir_names and 'etc' in dir_names and 'snap' in dir_names:
147
- # SNAP Desktop Distribution Directory
148
- for dir_name in dir_names:
149
- if dir_name not in EXCLUDED_NB_CLUSTERS:
150
- dir_path = os.path.join(snap_home, dir_name, 'modules')
151
- if os.path.isdir(dir_path):
152
- java_module_dirs.append(dir_path)
153
- elif 'lib' in dir_names and 'modules' in dir_names:
154
- # SNAP Engine Distribution Directory
155
- java_module_dirs = [os.path.join(snap_home, 'modules'), os.path.join(snap_home, 'lib')]
156
- elif glob.glob(snap_home + '/*snap-python*.jar'):
157
- java_module_dirs = [snap_home]
158
- else:
159
- raise RuntimeError('does not seem to be a valid SNAP distribution directory: ' + snap_home)
160
-
161
- # NetBeans modules dir will be scaned as last. It contains the latest module updates and they shall replace
162
- # older modules
163
- nb_user_modules_dir = _get_nb_user_modules_dir()
164
- if nb_user_modules_dir and os.path.isdir(nb_user_modules_dir):
165
- java_module_dirs.append(nb_user_modules_dir)
166
-
167
- if debug:
168
- import pprint
169
-
170
- print(module_dir + ': java_module_dirs = ')
171
- pprint.pprint(java_module_dirs)
172
-
173
- env = (dict(), [])
174
- for path in java_module_dirs:
175
- _collect_snap_jvm_env(path, env)
176
-
177
- if debug:
178
- import pprint
179
-
180
- print(module_dir + ': env =')
181
- pprint.pprint(env)
182
-
183
- return env
184
-
185
-
186
- #
187
- # Creates a list of Java JVM options, including the Java classpath derived from the global 'snap_home' variable.
188
- #
189
- # Note: This function is called only if the 'esa_snappy' module is not imported from Java.
190
- #
191
- def _get_snap_jvm_options():
192
- global snap_home
193
-
194
- if config.has_option('DEFAULT', 'snap_home'):
195
- snap_home = config.get('DEFAULT', 'snap_home')
196
- else:
197
- snap_home = os.getenv('SNAP_HOME')
198
-
199
- if snap_home is None or not os.path.isdir(snap_home):
200
- raise IOError("Can't find SNAP distribution directory. Either configure variable 'snap_home' " +
201
- "in file './snappy.ini' or set environment variable 'SNAP_HOME' to an " +
202
- "existing SNAP distribution directory.")
203
-
204
- env = _get_snap_jvm_env()
205
- class_path = list(env[0].values())
206
- library_path = env[1]
207
-
208
- if config.has_option('DEFAULT', 'java_class_path'):
209
- extra_class_path = config.get('DEFAULT', 'java_class_path')
210
- class_path += extra_class_path.split(os.pathsep)
211
-
212
- if config.has_option('DEFAULT', 'java_library_path'):
213
- extra_library_path = config.get('DEFAULT', 'java_library_path')
214
- library_path += extra_library_path.split(os.pathsep)
215
-
216
- max_mem = '512M'
217
- if config.has_option('DEFAULT', 'java_max_mem'):
218
- max_mem = config.get('DEFAULT', 'java_max_mem')
219
-
220
- options = ['-Djava.awt.headless=true',
221
- '-Djava.class.path=' + os.pathsep.join(class_path),
222
- '-Djava.library.path=' + os.pathsep.join(library_path),
223
- '-Dsnap.home=' + snap_home,
224
- '-Xmx' + max_mem]
225
-
226
- if config.has_option('DEFAULT', 'java_options'):
227
- extra_options = config.get('DEFAULT', 'java_options')
228
- options += extra_options.split('|')
229
-
230
- return options
231
-
232
-
233
- # Figure out if this module is called from a Java VM. If not, derive a list of Java VM options and create the Java VM.
234
- called_from_java = jpy.has_jvm()
235
- if not called_from_java:
236
- jpy.create_jvm(options=_get_snap_jvm_options())
237
-
238
-
239
- # Don't need these functions anymore
240
- del _get_snap_jvm_options
241
- del _get_snap_jvm_env
242
- del _collect_snap_jvm_env
243
-
244
-
245
- # noinspection PyUnusedLocal
246
- def annotate_RasterDataNode_methods(type_name, method):
247
- index = -1
248
-
249
- if sys.version_info >= (3, 0, 0,):
250
- arr_z_type_str = "<class '[Z'>"
251
- arr_i_type_str = "<class '[I'>"
252
- arr_f_type_str = "<class '[F'>"
253
- arr_d_type_str = "<class '[D'>"
254
- else:
255
- arr_z_type_str = "<type '[Z'>"
256
- arr_i_type_str = "<type '[I'>"
257
- arr_f_type_str = "<type '[F'>"
258
- arr_d_type_str = "<type '[D'>"
259
-
260
- if method.name == 'readPixels' and method.param_count >= 5:
261
- index = 4
262
- param_type_str = str(method.get_param_type(index))
263
- if param_type_str == arr_i_type_str \
264
- or param_type_str == arr_f_type_str \
265
- or param_type_str == arr_d_type_str:
266
- method.set_param_mutable(index, True)
267
- method.set_param_output(index, True)
268
- method.set_param_return(index, True)
269
-
270
- if method.name == 'readValidMask' and method.param_count == 5:
271
- index = 4
272
- param_type_str = str(method.get_param_type(index))
273
- if param_type_str == arr_z_type_str:
274
- method.set_param_mutable(index, True)
275
- method.set_param_output(index, True)
276
- method.set_param_return(index, True)
277
-
278
- if index >= 0 and debug:
279
- print('annotate_RasterDataNode_methods: Method "{0}": '
280
- 'modified parameter {1:d}: mutable = {2}, return = {3}'
281
- .format(method.name, index, method.is_param_mutable(index), method.is_param_return(index)))
282
-
283
- return True
284
-
285
-
286
- jpy.type_callbacks['org.esa.snap.core.datamodel.RasterDataNode'] = annotate_RasterDataNode_methods
287
- jpy.type_callbacks['org.esa.snap.core.datamodel.AbstractBand'] = annotate_RasterDataNode_methods
288
- jpy.type_callbacks['org.esa.snap.core.datamodel.Band'] = annotate_RasterDataNode_methods
289
- jpy.type_callbacks['org.esa.snap.core.datamodel.VirtualBand'] = annotate_RasterDataNode_methods
290
-
291
- #
292
- # Preload and assign frequently used Java classes from the Java SE and SNAP Java API.
293
- #
294
-
295
- try:
296
- # Note we may later want to read pre-defined types from a configuration file (snappy.ini)
297
-
298
- # Frequently used classes & interfaces from JRE
299
- String = jpy.get_type('java.lang.String')
300
- File = jpy.get_type('java.io.File')
301
- Point = jpy.get_type('java.awt.Point')
302
- Rectangle = jpy.get_type('java.awt.Rectangle')
303
- Arrays = jpy.get_type('java.util.Arrays')
304
- Collections = jpy.get_type('java.util.Collections')
305
- List = jpy.get_type('java.util.List')
306
- Map = jpy.get_type('java.util.Map')
307
- Set = jpy.get_type('java.util.Set')
308
- ArrayList = jpy.get_type('java.util.ArrayList')
309
- HashMap = jpy.get_type('java.util.HashMap')
310
- HashSet = jpy.get_type('java.util.HashSet')
311
-
312
- #
313
- # Frequently used classes & interfaces from SNAP Engine
314
- #
315
-
316
- # Product tree & associates
317
- Product = jpy.get_type('org.esa.snap.core.datamodel.Product')
318
- VectorDataNode = jpy.get_type('org.esa.snap.core.datamodel.VectorDataNode')
319
- RasterDataNode = jpy.get_type('org.esa.snap.core.datamodel.RasterDataNode')
320
- TiePointGrid = jpy.get_type('org.esa.snap.core.datamodel.TiePointGrid')
321
- AbstractBand = jpy.get_type('org.esa.snap.core.datamodel.AbstractBand')
322
- Band = jpy.get_type('org.esa.snap.core.datamodel.Band')
323
- VirtualBand = jpy.get_type('org.esa.snap.core.datamodel.VirtualBand')
324
- Mask = jpy.get_type('org.esa.snap.core.datamodel.Mask')
325
- GeneralFilterBand = jpy.get_type('org.esa.snap.core.datamodel.GeneralFilterBand')
326
- ConvolutionFilterBand = jpy.get_type('org.esa.snap.core.datamodel.ConvolutionFilterBand')
327
-
328
- # Product tree associates
329
- ProductData = jpy.get_type('org.esa.snap.core.datamodel.ProductData')
330
- GeoCoding = jpy.get_type('org.esa.snap.core.datamodel.GeoCoding')
331
- TiePointGeoCoding = jpy.get_type('org.esa.snap.core.datamodel.TiePointGeoCoding')
332
- ComponentGeoCoding = jpy.get_type('org.esa.snap.core.dataio.geocoding.ComponentGeoCoding')
333
- CrsGeoCoding = jpy.get_type('org.esa.snap.core.datamodel.CrsGeoCoding')
334
- GeoPos = jpy.get_type('org.esa.snap.core.datamodel.GeoPos')
335
- PixelPos = jpy.get_type('org.esa.snap.core.datamodel.PixelPos')
336
- FlagCoding = jpy.get_type('org.esa.snap.core.datamodel.FlagCoding')
337
- ProductNodeGroup = jpy.get_type('org.esa.snap.core.datamodel.ProductNodeGroup')
338
-
339
- # Graph Processing Framework
340
- GPF = jpy.get_type('org.esa.snap.core.gpf.GPF')
341
- Operator = jpy.get_type('org.esa.snap.core.gpf.Operator')
342
- Tile = jpy.get_type('org.esa.snap.core.gpf.Tile')
343
-
344
- # Utilities
345
- EngineConfig = jpy.get_type('org.esa.snap.runtime.EngineConfig')
346
- Engine = jpy.get_type('org.esa.snap.runtime.Engine')
347
- SystemUtils = jpy.get_type('org.esa.snap.core.util.SystemUtils')
348
- ProductIO = jpy.get_type('org.esa.snap.core.dataio.ProductIO')
349
- ProductUtils = jpy.get_type('org.esa.snap.core.util.ProductUtils')
350
- GeoUtils = jpy.get_type('org.esa.snap.core.util.GeoUtils')
351
- ProgressMonitor = jpy.get_type('com.bc.ceres.core.ProgressMonitor')
352
- PlainFeatureFactory = jpy.get_type('org.esa.snap.core.datamodel.PlainFeatureFactory')
353
- FeatureUtils = jpy.get_type('org.esa.snap.core.util.FeatureUtils')
354
-
355
- # GeoTools
356
- DefaultGeographicCRS = jpy.get_type('org.geotools.referencing.crs.DefaultGeographicCRS')
357
- ListFeatureCollection = jpy.get_type('org.geotools.data.collection.ListFeatureCollection')
358
- SimpleFeatureBuilder = jpy.get_type('org.geotools.feature.simple.SimpleFeatureBuilder')
359
-
360
- # JTS
361
- Geometry = jpy.get_type('org.locationtech.jts.geom.Geometry')
362
- WKTReader = jpy.get_type('org.locationtech.jts.io.WKTReader')
363
-
364
-
365
- except Exception:
366
- jpy.destroy_jvm()
367
- raise
368
-
369
-
370
- # Note: use the following code to initialise SNAP's 3rd party libraries, JAI and GeoTools.
371
- # Only needed, if SNAP Python API is not called from Java (e.g. from SNAP gpt or SNAP desktop).
372
- if not called_from_java:
373
- EngineConfig.instance().load()
374
- SystemUtils.init3rdPartyLibs(None)
375
-
376
- start_snap_engine = True
377
- if config.has_option('DEFAULT', 'snap_start_engine'):
378
- start_snap_engine = config.getboolean('DEFAULT', 'snap_start_engine')
379
-
380
- if start_snap_engine:
381
- Engine.start()
382
-
1
+ """
2
+ The esa_snappy module provides access to the Java SE APIs and SNAP Java APIs.
3
+
4
+ You can configure esa_snappy by using a file named snappy.ini as follows:
5
+
6
+ [DEFAULT]
7
+ snap_home: C:/Program Files/snap
8
+ java_class_path: target/classes
9
+ java_library_path: target/lib/amd64
10
+ java_options: -Djava.awt.headless=true
11
+ java_max_mem: 4G
12
+ debug: False
13
+
14
+ You can place snappy.ini next to <python3>/site-packages/snappy.py or put it in your current working directory.
15
+ The 'snap_home' options and all options starting with 'java_' are only used if you use the SNAP API from Python
16
+ and a new Java Virtual Machine is created. They are ignored if the SNAP API is called from SNAP itself
17
+ (e.g. SNAP command-line or GUI).
18
+
19
+ 'esa_snappy' uses a bundled 'jpy' module, see documentation at http://jpy.readthedocs.org/en/latest
20
+ and source code at https://github.com/bcdev/jpy
21
+ """
22
+
23
+ EXCLUDED_NB_CLUSTERS = {'platform', 'ide', 'bin', 'etc'}
24
+
25
+ EXCLUDED_DIR_NAMES = {'org.esa.snap.snap-worldwind', 'org.esa.snap.snap-rcp', 'org.esa.snap.snap-product-library',
26
+ 'org.esa.snap.snap-sta-ui'}
27
+
28
+ EXCLUDED_JAR_NAMES = {'org-esa-snap-netbeans-docwin.jar', 'org-esa-snap-netbeans-tile.jar',
29
+ 'org-esa-snap-snap-worldwind.jar', 'org-esa-snap-snap-tango.jar', 'org-esa-snap-snap-rcp.jar',
30
+ 'org-esa-snap-snap-ui.jar', 'org-esa-snap-snap-graph-builder.jar',
31
+ 'org-esa-snap-snap-branding.jar'}
32
+
33
+ import glob
34
+ import os
35
+
36
+ import sys
37
+
38
+ if sys.version_info >= (3, 0, 0,):
39
+ # noinspection PyUnresolvedReferences
40
+ import configparser as cp
41
+ else:
42
+ # noinspection PyUnresolvedReferences
43
+ import ConfigParser as cp
44
+
45
+ module_dir = os.path.dirname(os.path.realpath(__file__))
46
+ module_ini = os.path.basename(module_dir) + '.ini'
47
+
48
+ # Read configuration *.ini file from either '.', '<module_dir>/..', '<module_dir>' in this order
49
+ config = cp.ConfigParser()
50
+ config.read([os.path.join(module_dir, module_ini),
51
+ os.path.join(os.path.join(module_dir, '..'), module_ini),
52
+ module_ini
53
+ ])
54
+
55
+ debug = False
56
+ if config.has_option('DEFAULT', 'debug'):
57
+ debug = config.getboolean('DEFAULT', 'debug')
58
+
59
+ # Pre-load Java VM shared library and import 'jpy', the Java-Python bridge
60
+ if module_dir not in sys.path:
61
+ sys.path.append(module_dir)
62
+ import jpyutil
63
+
64
+ jpyutil.preload_jvm_dll()
65
+ import jpy
66
+
67
+ if debug:
68
+ # jpy.diag.F_OFF 0x00
69
+ # jpy.diag.F_TYPE 0x01
70
+ # jpy.diag.F_METH 0x02
71
+ # jpy.diag.F_EXEC 0x04
72
+ # jpy.diag.F_MEM 0x08
73
+ # jpy.diag.F_JVM 0x10
74
+ # jpy.diag.F_ERR 0x20
75
+ # jpy.diag.F_ALL 0xff
76
+ jpy.diag.flags = jpy.diag.F_EXEC + jpy.diag.F_ERR
77
+
78
+
79
+ #
80
+ # Recursively searches for JAR files in 'dir_path' and appends them to the first member of the
81
+ # 'env' tuple (env[0] is the classpath). Also searches for 'lib/LIB_PLATFORM_NAMES[i]' and if one
82
+ # exists, appends it to the second member of the 'env' tuple (env[1] is the java.library.path)
83
+ # Note: Sub-directories named 'locale' or 'docs' are not searched and
84
+ # JAR files ending with '-ui.jar' or '-examples.jar' are excluded.
85
+ #
86
+ # Note: This function is called only if the 'esa_snappy' module is not imported from Java.
87
+ #
88
+ def _collect_snap_jvm_env(dir_path, env):
89
+ for name in os.listdir(dir_path):
90
+ path = os.path.join(dir_path, name)
91
+ if os.path.isfile(path) and name.endswith('.jar'):
92
+ if not (name.endswith('-ui.jar') or name in EXCLUDED_JAR_NAMES):
93
+ env[0][name] = path
94
+ elif os.path.isdir(path) and name not in EXCLUDED_DIR_NAMES:
95
+ if name == 'lib':
96
+ import platform
97
+
98
+ os_arch = platform.machine().lower()
99
+ os_name = platform.system().lower()
100
+ lib_os_arch_path = os.path.join(path, os_arch)
101
+ if os.path.exists(lib_os_arch_path):
102
+ lib_os_name_path = os.path.join(lib_os_arch_path, os_name)
103
+ if os.path.exists(lib_os_name_path):
104
+ env[1].append(lib_os_name_path)
105
+ env[1].append(lib_os_arch_path)
106
+ env[1].append(path)
107
+ if not (name == 'locale' or name == 'docs'):
108
+ _collect_snap_jvm_env(path, env)
109
+
110
+
111
+ #
112
+ # Get the NetBeans user directory for installed extra modules
113
+ #
114
+ def _get_nb_user_modules_dir():
115
+ import platform
116
+ from os.path import expanduser
117
+
118
+ home_dir = expanduser('~')
119
+ nb_user_dir = None
120
+ if platform.system() == 'Windows':
121
+ if home_dir:
122
+ nb_user_dir = os.path.join(home_dir, 'AppData\\Roaming\\SNAP')
123
+ else:
124
+ if home_dir:
125
+ nb_user_dir = os.path.join(home_dir, '.snap/system')
126
+
127
+ if nb_user_dir:
128
+ return os.path.join(nb_user_dir, 'modules')
129
+
130
+ return None
131
+
132
+
133
+ #
134
+ # Searches for *.jar files in directory given by global 'snap_home' variable and returns them as a list.
135
+ #
136
+ # Note: This function is called only if the 'esa_snappy' module is not imported from Java.
137
+ #
138
+ def _get_snap_jvm_env():
139
+ dir_names = []
140
+ for name in os.listdir(snap_home):
141
+ if os.path.isdir(os.path.join(snap_home, name)):
142
+ dir_names.append(name)
143
+
144
+ java_module_dirs = []
145
+
146
+ if 'bin' in dir_names and 'etc' in dir_names and 'snap' in dir_names:
147
+ # SNAP Desktop Distribution Directory
148
+ for dir_name in dir_names:
149
+ if dir_name not in EXCLUDED_NB_CLUSTERS:
150
+ dir_path = os.path.join(snap_home, dir_name, 'modules')
151
+ if os.path.isdir(dir_path):
152
+ java_module_dirs.append(dir_path)
153
+ elif 'lib' in dir_names and 'modules' in dir_names:
154
+ # SNAP Engine Distribution Directory
155
+ java_module_dirs = [os.path.join(snap_home, 'modules'), os.path.join(snap_home, 'lib')]
156
+ elif glob.glob(snap_home + '/*snap-python*.jar'):
157
+ java_module_dirs = [snap_home]
158
+ else:
159
+ raise RuntimeError('does not seem to be a valid SNAP distribution directory: ' + snap_home)
160
+
161
+ # NetBeans modules dir will be scaned as last. It contains the latest module updates and they shall replace
162
+ # older modules
163
+ nb_user_modules_dir = _get_nb_user_modules_dir()
164
+ if nb_user_modules_dir and os.path.isdir(nb_user_modules_dir):
165
+ java_module_dirs.append(nb_user_modules_dir)
166
+
167
+ if debug:
168
+ import pprint
169
+
170
+ print(module_dir + ': java_module_dirs = ')
171
+ pprint.pprint(java_module_dirs)
172
+
173
+ env = (dict(), [])
174
+ for path in java_module_dirs:
175
+ _collect_snap_jvm_env(path, env)
176
+
177
+ if debug:
178
+ import pprint
179
+
180
+ print(module_dir + ': env =')
181
+ pprint.pprint(env)
182
+
183
+ return env
184
+
185
+
186
+ #
187
+ # Creates a list of Java JVM options, including the Java classpath derived from the global 'snap_home' variable.
188
+ #
189
+ # Note: This function is called only if the 'esa_snappy' module is not imported from Java.
190
+ #
191
+ def _get_snap_jvm_options():
192
+ global snap_home
193
+
194
+ if config.has_option('DEFAULT', 'snap_home'):
195
+ snap_home = config.get('DEFAULT', 'snap_home')
196
+ else:
197
+ snap_home = os.getenv('SNAP_HOME')
198
+
199
+ if snap_home is None or not os.path.isdir(snap_home):
200
+ raise IOError("Can't find SNAP distribution directory. Either configure variable 'snap_home' " +
201
+ "in file './snappy.ini' or set environment variable 'SNAP_HOME' to an " +
202
+ "existing SNAP distribution directory.")
203
+
204
+ env = _get_snap_jvm_env()
205
+ class_path = list(env[0].values())
206
+ library_path = env[1]
207
+
208
+ if config.has_option('DEFAULT', 'java_class_path'):
209
+ extra_class_path = config.get('DEFAULT', 'java_class_path')
210
+ class_path += extra_class_path.split(os.pathsep)
211
+
212
+ if config.has_option('DEFAULT', 'java_library_path'):
213
+ extra_library_path = config.get('DEFAULT', 'java_library_path')
214
+ library_path += extra_library_path.split(os.pathsep)
215
+
216
+ max_mem = '512M'
217
+ if config.has_option('DEFAULT', 'java_max_mem'):
218
+ max_mem = config.get('DEFAULT', 'java_max_mem')
219
+
220
+ options = ['-Djava.awt.headless=true',
221
+ '-Djava.class.path=' + os.pathsep.join(class_path),
222
+ '-Djava.library.path=' + os.pathsep.join(library_path),
223
+ '-Dsnap.home=' + snap_home,
224
+ '-Xmx' + max_mem]
225
+
226
+ if config.has_option('DEFAULT', 'java_options'):
227
+ extra_options = config.get('DEFAULT', 'java_options')
228
+ options += extra_options.split('|')
229
+
230
+ return options
231
+
232
+
233
+ # Figure out if this module is called from a Java VM. If not, derive a list of Java VM options and create the Java VM.
234
+ called_from_java = jpy.has_jvm()
235
+ if not called_from_java:
236
+ jpy.create_jvm(options=_get_snap_jvm_options())
237
+
238
+
239
+ # Don't need these functions anymore
240
+ del _get_snap_jvm_options
241
+ del _get_snap_jvm_env
242
+ del _collect_snap_jvm_env
243
+
244
+
245
+ # noinspection PyUnusedLocal
246
+ def annotate_RasterDataNode_methods(type_name, method):
247
+ index = -1
248
+
249
+ if sys.version_info >= (3, 0, 0,):
250
+ arr_z_type_str = "<class '[Z'>"
251
+ arr_i_type_str = "<class '[I'>"
252
+ arr_f_type_str = "<class '[F'>"
253
+ arr_d_type_str = "<class '[D'>"
254
+ else:
255
+ arr_z_type_str = "<type '[Z'>"
256
+ arr_i_type_str = "<type '[I'>"
257
+ arr_f_type_str = "<type '[F'>"
258
+ arr_d_type_str = "<type '[D'>"
259
+
260
+ if method.name == 'readPixels' and method.param_count >= 5:
261
+ index = 4
262
+ param_type_str = str(method.get_param_type(index))
263
+ if param_type_str == arr_i_type_str \
264
+ or param_type_str == arr_f_type_str \
265
+ or param_type_str == arr_d_type_str:
266
+ method.set_param_mutable(index, True)
267
+ method.set_param_output(index, True)
268
+ method.set_param_return(index, True)
269
+
270
+ if method.name == 'readValidMask' and method.param_count == 5:
271
+ index = 4
272
+ param_type_str = str(method.get_param_type(index))
273
+ if param_type_str == arr_z_type_str:
274
+ method.set_param_mutable(index, True)
275
+ method.set_param_output(index, True)
276
+ method.set_param_return(index, True)
277
+
278
+ if index >= 0 and debug:
279
+ print('annotate_RasterDataNode_methods: Method "{0}": '
280
+ 'modified parameter {1:d}: mutable = {2}, return = {3}'
281
+ .format(method.name, index, method.is_param_mutable(index), method.is_param_return(index)))
282
+
283
+ return True
284
+
285
+
286
+ jpy.type_callbacks['org.esa.snap.core.datamodel.RasterDataNode'] = annotate_RasterDataNode_methods
287
+ jpy.type_callbacks['org.esa.snap.core.datamodel.AbstractBand'] = annotate_RasterDataNode_methods
288
+ jpy.type_callbacks['org.esa.snap.core.datamodel.Band'] = annotate_RasterDataNode_methods
289
+ jpy.type_callbacks['org.esa.snap.core.datamodel.VirtualBand'] = annotate_RasterDataNode_methods
290
+
291
+ #
292
+ # Preload and assign frequently used Java classes from the Java SE and SNAP Java API.
293
+ #
294
+
295
+ try:
296
+ # Note we may later want to read pre-defined types from a configuration file (snappy.ini)
297
+
298
+ # Frequently used classes & interfaces from JRE
299
+ String = jpy.get_type('java.lang.String')
300
+ File = jpy.get_type('java.io.File')
301
+ Point = jpy.get_type('java.awt.Point')
302
+ Rectangle = jpy.get_type('java.awt.Rectangle')
303
+ Arrays = jpy.get_type('java.util.Arrays')
304
+ Collections = jpy.get_type('java.util.Collections')
305
+ List = jpy.get_type('java.util.List')
306
+ Map = jpy.get_type('java.util.Map')
307
+ Set = jpy.get_type('java.util.Set')
308
+ ArrayList = jpy.get_type('java.util.ArrayList')
309
+ HashMap = jpy.get_type('java.util.HashMap')
310
+ HashSet = jpy.get_type('java.util.HashSet')
311
+
312
+ #
313
+ # Frequently used classes & interfaces from SNAP Engine
314
+ #
315
+
316
+ # Product tree & associates
317
+ Product = jpy.get_type('org.esa.snap.core.datamodel.Product')
318
+ VectorDataNode = jpy.get_type('org.esa.snap.core.datamodel.VectorDataNode')
319
+ RasterDataNode = jpy.get_type('org.esa.snap.core.datamodel.RasterDataNode')
320
+ TiePointGrid = jpy.get_type('org.esa.snap.core.datamodel.TiePointGrid')
321
+ AbstractBand = jpy.get_type('org.esa.snap.core.datamodel.AbstractBand')
322
+ Band = jpy.get_type('org.esa.snap.core.datamodel.Band')
323
+ VirtualBand = jpy.get_type('org.esa.snap.core.datamodel.VirtualBand')
324
+ Mask = jpy.get_type('org.esa.snap.core.datamodel.Mask')
325
+ GeneralFilterBand = jpy.get_type('org.esa.snap.core.datamodel.GeneralFilterBand')
326
+ ConvolutionFilterBand = jpy.get_type('org.esa.snap.core.datamodel.ConvolutionFilterBand')
327
+
328
+ # Product tree associates
329
+ ProductData = jpy.get_type('org.esa.snap.core.datamodel.ProductData')
330
+ GeoCoding = jpy.get_type('org.esa.snap.core.datamodel.GeoCoding')
331
+ TiePointGeoCoding = jpy.get_type('org.esa.snap.core.datamodel.TiePointGeoCoding')
332
+ ComponentGeoCoding = jpy.get_type('org.esa.snap.core.dataio.geocoding.ComponentGeoCoding')
333
+ CrsGeoCoding = jpy.get_type('org.esa.snap.core.datamodel.CrsGeoCoding')
334
+ GeoPos = jpy.get_type('org.esa.snap.core.datamodel.GeoPos')
335
+ PixelPos = jpy.get_type('org.esa.snap.core.datamodel.PixelPos')
336
+ FlagCoding = jpy.get_type('org.esa.snap.core.datamodel.FlagCoding')
337
+ ProductNodeGroup = jpy.get_type('org.esa.snap.core.datamodel.ProductNodeGroup')
338
+
339
+ # Graph Processing Framework
340
+ GPF = jpy.get_type('org.esa.snap.core.gpf.GPF')
341
+ Operator = jpy.get_type('org.esa.snap.core.gpf.Operator')
342
+ Tile = jpy.get_type('org.esa.snap.core.gpf.Tile')
343
+
344
+ # Utilities
345
+ EngineConfig = jpy.get_type('org.esa.snap.runtime.EngineConfig')
346
+ Engine = jpy.get_type('org.esa.snap.runtime.Engine')
347
+ SystemUtils = jpy.get_type('org.esa.snap.core.util.SystemUtils')
348
+ ProductIO = jpy.get_type('org.esa.snap.core.dataio.ProductIO')
349
+ ProductUtils = jpy.get_type('org.esa.snap.core.util.ProductUtils')
350
+ GeoUtils = jpy.get_type('org.esa.snap.core.util.GeoUtils')
351
+ ProgressMonitor = jpy.get_type('com.bc.ceres.core.ProgressMonitor')
352
+ PlainFeatureFactory = jpy.get_type('org.esa.snap.core.datamodel.PlainFeatureFactory')
353
+ FeatureUtils = jpy.get_type('org.esa.snap.core.util.FeatureUtils')
354
+
355
+ # GeoTools
356
+ DefaultGeographicCRS = jpy.get_type('org.geotools.referencing.crs.DefaultGeographicCRS')
357
+ ListFeatureCollection = jpy.get_type('org.geotools.data.collection.ListFeatureCollection')
358
+ SimpleFeatureBuilder = jpy.get_type('org.geotools.feature.simple.SimpleFeatureBuilder')
359
+
360
+ # JTS
361
+ Geometry = jpy.get_type('org.locationtech.jts.geom.Geometry')
362
+ WKTReader = jpy.get_type('org.locationtech.jts.io.WKTReader')
363
+
364
+
365
+ except Exception:
366
+ jpy.destroy_jvm()
367
+ raise
368
+
369
+
370
+ # Note: use the following code to initialise SNAP's 3rd party libraries, JAI and GeoTools.
371
+ # Only needed, if SNAP Python API is not called from Java (e.g. from SNAP gpt or SNAP desktop).
372
+ if not called_from_java:
373
+ EngineConfig.instance().load()
374
+ SystemUtils.init3rdPartyLibs(None)
375
+
376
+ start_snap_engine = True
377
+ if config.has_option('DEFAULT', 'snap_start_engine'):
378
+ start_snap_engine = config.getboolean('DEFAULT', 'snap_start_engine')
379
+
380
+ if start_snap_engine:
381
+ Engine.start()
382
+