sarpyx 0.1.5__py3-none-any.whl → 0.1.6__py3-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.
- docs/examples/advanced/batch_processing.py +1 -1
- docs/examples/advanced/custom_processing_chains.py +1 -1
- docs/examples/advanced/performance_optimization.py +1 -1
- docs/examples/basic/snap_integration.py +1 -1
- docs/examples/intermediate/quality_assessment.py +1 -1
- outputs/baseline/20260205-234828/__init__.py +33 -0
- outputs/baseline/20260205-234828/main.py +493 -0
- outputs/final/20260205-234851/__init__.py +33 -0
- outputs/final/20260205-234851/main.py +493 -0
- sarpyx/__init__.py +2 -2
- sarpyx/algorithms/__init__.py +2 -2
- sarpyx/cli/__init__.py +1 -1
- sarpyx/cli/focus.py +3 -5
- sarpyx/cli/main.py +106 -7
- sarpyx/cli/shipdet.py +1 -1
- sarpyx/cli/worldsar.py +549 -0
- sarpyx/processor/__init__.py +1 -1
- sarpyx/processor/core/decode.py +43 -8
- sarpyx/processor/core/focus.py +104 -57
- sarpyx/science/__init__.py +1 -1
- sarpyx/sla/__init__.py +8 -0
- sarpyx/sla/metrics.py +101 -0
- sarpyx/{snap → snapflow}/__init__.py +1 -1
- sarpyx/snapflow/engine.py +6165 -0
- sarpyx/{snap → snapflow}/op.py +0 -1
- sarpyx/utils/__init__.py +1 -1
- sarpyx/utils/geos.py +652 -0
- sarpyx/utils/grid.py +285 -0
- sarpyx/utils/io.py +77 -9
- sarpyx/utils/meta.py +55 -0
- sarpyx/utils/nisar_utils.py +652 -0
- sarpyx/utils/rfigen.py +108 -0
- sarpyx/utils/wkt_utils.py +109 -0
- sarpyx/utils/zarr_utils.py +55 -37
- {sarpyx-0.1.5.dist-info → sarpyx-0.1.6.dist-info}/METADATA +9 -5
- {sarpyx-0.1.5.dist-info → sarpyx-0.1.6.dist-info}/RECORD +41 -32
- {sarpyx-0.1.5.dist-info → sarpyx-0.1.6.dist-info}/WHEEL +1 -1
- sarpyx-0.1.6.dist-info/licenses/LICENSE +201 -0
- sarpyx-0.1.6.dist-info/top_level.txt +4 -0
- tests/test_zarr_compat.py +35 -0
- sarpyx/processor/core/decode_v0.py +0 -0
- sarpyx/processor/core/decode_v1.py +0 -849
- sarpyx/processor/core/focus_old.py +0 -1550
- sarpyx/processor/core/focus_v1.py +0 -1566
- sarpyx/processor/core/focus_v2.py +0 -1625
- sarpyx/snap/engine.py +0 -633
- sarpyx-0.1.5.dist-info/top_level.txt +0 -2
- {sarpyx-0.1.5.dist-info → sarpyx-0.1.6.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SARPyX Command Line Interface.
|
|
4
|
+
|
|
5
|
+
Main entry point for all sarpyx CLI tools.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import argparse
|
|
9
|
+
import sys
|
|
10
|
+
from typing import List
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def create_main_parser() -> argparse.ArgumentParser:
|
|
14
|
+
"""
|
|
15
|
+
Create the main argument parser with subcommands.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
Configured ArgumentParser instance.
|
|
19
|
+
"""
|
|
20
|
+
parser = argparse.ArgumentParser(
|
|
21
|
+
prog='sarpyx',
|
|
22
|
+
description='SARPyX: A comprehensive toolkit for SAR data processing',
|
|
23
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
24
|
+
epilog="""
|
|
25
|
+
Available commands:
|
|
26
|
+
decode Decode Sentinel-1 Level-0 products to zarr format
|
|
27
|
+
focus Focus SAR data using Range-Doppler Algorithm
|
|
28
|
+
shipdet Ship detection using SNAP GPT engine
|
|
29
|
+
unzip Extract SAR data from zip archives
|
|
30
|
+
upload Upload data to Hugging Face Hub
|
|
31
|
+
worldsar Process SAR products with SNAP GPT pipelines and tiling
|
|
32
|
+
|
|
33
|
+
Examples:
|
|
34
|
+
sarpyx decode --input /path/to/file.dat --output /path/to/output
|
|
35
|
+
sarpyx focus --input /path/to/data.zarr --output /path/to/output
|
|
36
|
+
sarpyx shipdet --product-path /path/to/S1A_*.SAFE --outdir /path/to/output
|
|
37
|
+
sarpyx unzip --input /path/to/file.zip --output /path/to/output
|
|
38
|
+
sarpyx upload --folder /path/to/folder --repo username/dataset-name
|
|
39
|
+
sarpyx worldsar --input /path/to/product --output /path/to/output \\
|
|
40
|
+
--cuts-outdir /path/to/tiles --product-wkt "POLYGON ((...))" \\
|
|
41
|
+
--prod-mode S1TOPS
|
|
42
|
+
|
|
43
|
+
For command-specific help:
|
|
44
|
+
sarpyx <command> --help
|
|
45
|
+
"""
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
'--version',
|
|
50
|
+
action='version',
|
|
51
|
+
version='sarpyx-cli 0.1.6'
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Create subparsers for different commands
|
|
55
|
+
subparsers = parser.add_subparsers(
|
|
56
|
+
dest='command',
|
|
57
|
+
help='Available commands',
|
|
58
|
+
metavar='<command>'
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Decode subcommand
|
|
62
|
+
decode_parser = subparsers.add_parser(
|
|
63
|
+
'decode',
|
|
64
|
+
help='Decode Sentinel-1 Level-0 products to zarr format',
|
|
65
|
+
description='Decode S1 L0 products (.dat files or .SAFE folders) to zarr format'
|
|
66
|
+
)
|
|
67
|
+
_add_decode_arguments(decode_parser)
|
|
68
|
+
|
|
69
|
+
# Focus subcommand
|
|
70
|
+
focus_parser = subparsers.add_parser(
|
|
71
|
+
'focus',
|
|
72
|
+
help='Focus SAR data using Range-Doppler Algorithm',
|
|
73
|
+
description='Focus SAR data from zarr files using CoarseRDA processor'
|
|
74
|
+
)
|
|
75
|
+
_add_focus_arguments(focus_parser)
|
|
76
|
+
|
|
77
|
+
# Ship detection subcommand
|
|
78
|
+
shipdet_parser = subparsers.add_parser(
|
|
79
|
+
'shipdet',
|
|
80
|
+
help='Ship detection using SNAP GPT engine',
|
|
81
|
+
description='Detect ships in SAR data using adaptive thresholding and object discrimination'
|
|
82
|
+
)
|
|
83
|
+
_add_shipdet_arguments(shipdet_parser)
|
|
84
|
+
|
|
85
|
+
# Unzip subcommand
|
|
86
|
+
unzip_parser = subparsers.add_parser(
|
|
87
|
+
'unzip',
|
|
88
|
+
help='Extract SAR data from zip archives',
|
|
89
|
+
description='Extract zip files containing SAR data'
|
|
90
|
+
)
|
|
91
|
+
_add_unzip_arguments(unzip_parser)
|
|
92
|
+
|
|
93
|
+
# Upload subcommand
|
|
94
|
+
upload_parser = subparsers.add_parser(
|
|
95
|
+
'upload',
|
|
96
|
+
help='Upload data to Hugging Face Hub',
|
|
97
|
+
description='Upload processed SAR data to Hugging Face Hub'
|
|
98
|
+
)
|
|
99
|
+
_add_upload_arguments(upload_parser)
|
|
100
|
+
|
|
101
|
+
# WorldSAR subcommand
|
|
102
|
+
worldsar_parser = subparsers.add_parser(
|
|
103
|
+
'worldsar',
|
|
104
|
+
help='Process SAR products with SNAP GPT pipelines and tiling',
|
|
105
|
+
description='Process SAR products from multiple missions and generate tiles'
|
|
106
|
+
)
|
|
107
|
+
_add_worldsar_arguments(worldsar_parser)
|
|
108
|
+
|
|
109
|
+
return parser
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _add_decode_arguments(parser: argparse.ArgumentParser) -> None:
|
|
113
|
+
"""
|
|
114
|
+
Add arguments for the decode subcommand.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
parser: The subparser for decode command.
|
|
118
|
+
"""
|
|
119
|
+
parser.add_argument(
|
|
120
|
+
'--input',
|
|
121
|
+
type=str,
|
|
122
|
+
required=True,
|
|
123
|
+
help='Path to .dat file or .SAFE folder'
|
|
124
|
+
)
|
|
125
|
+
parser.add_argument(
|
|
126
|
+
'--output',
|
|
127
|
+
type=str,
|
|
128
|
+
default='./decoded_data',
|
|
129
|
+
help='Output directory for decoded files (default: ./decoded_data)'
|
|
130
|
+
)
|
|
131
|
+
parser.add_argument(
|
|
132
|
+
'--verbose',
|
|
133
|
+
'-v',
|
|
134
|
+
action='store_true',
|
|
135
|
+
help='Enable verbose logging'
|
|
136
|
+
)
|
|
137
|
+
parser.add_argument(
|
|
138
|
+
'--debug',
|
|
139
|
+
action='store_true',
|
|
140
|
+
help='Enable debug logging'
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _add_focus_arguments(parser: argparse.ArgumentParser) -> None:
|
|
145
|
+
"""
|
|
146
|
+
Add arguments for the focus subcommand.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
parser: The subparser for focus command.
|
|
150
|
+
"""
|
|
151
|
+
parser.add_argument(
|
|
152
|
+
'--input',
|
|
153
|
+
type=str,
|
|
154
|
+
required=True,
|
|
155
|
+
help='Input zarr file path'
|
|
156
|
+
)
|
|
157
|
+
parser.add_argument(
|
|
158
|
+
'--output',
|
|
159
|
+
type=str,
|
|
160
|
+
default='./focused_data',
|
|
161
|
+
help='Output directory (default: ./focused_data)'
|
|
162
|
+
)
|
|
163
|
+
parser.add_argument(
|
|
164
|
+
'--slice-height',
|
|
165
|
+
type=int,
|
|
166
|
+
default=15000,
|
|
167
|
+
help='Slice height for processing (default: 15000)'
|
|
168
|
+
)
|
|
169
|
+
parser.add_argument(
|
|
170
|
+
'--verbose',
|
|
171
|
+
'-v',
|
|
172
|
+
action='store_true',
|
|
173
|
+
help='Enable verbose output'
|
|
174
|
+
)
|
|
175
|
+
parser.add_argument(
|
|
176
|
+
'--keep-tmp',
|
|
177
|
+
action='store_true',
|
|
178
|
+
help='Keep temporary files after processing'
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _add_shipdet_arguments(parser: argparse.ArgumentParser) -> None:
|
|
183
|
+
"""
|
|
184
|
+
Add arguments for the shipdet subcommand.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
parser: The subparser for shipdet command.
|
|
188
|
+
"""
|
|
189
|
+
# Required arguments
|
|
190
|
+
parser.add_argument(
|
|
191
|
+
'--product-path',
|
|
192
|
+
type=str,
|
|
193
|
+
required=True,
|
|
194
|
+
help='Path to the SAR product (.SAFE directory or zip file)'
|
|
195
|
+
)
|
|
196
|
+
parser.add_argument(
|
|
197
|
+
'--outdir',
|
|
198
|
+
type=str,
|
|
199
|
+
required=True,
|
|
200
|
+
help='Output directory for processed data'
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Optional processing arguments
|
|
204
|
+
parser.add_argument(
|
|
205
|
+
'--format',
|
|
206
|
+
type=str,
|
|
207
|
+
default='BEAM-DIMAP',
|
|
208
|
+
choices=['BEAM-DIMAP', 'GeoTIFF', 'NetCDF4-CF', 'ENVI', 'HDF5'],
|
|
209
|
+
help='Output format (default: BEAM-DIMAP)'
|
|
210
|
+
)
|
|
211
|
+
parser.add_argument(
|
|
212
|
+
'--gpt-path',
|
|
213
|
+
type=str,
|
|
214
|
+
default=None,
|
|
215
|
+
help='Path to GPT executable (default: None - use system PATH)'
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# Calibration arguments
|
|
219
|
+
parser.add_argument(
|
|
220
|
+
'--output-complex',
|
|
221
|
+
action='store_true',
|
|
222
|
+
help='Output complex values for calibration (default: False)'
|
|
223
|
+
)
|
|
224
|
+
parser.add_argument(
|
|
225
|
+
'--polarizations',
|
|
226
|
+
type=str,
|
|
227
|
+
nargs='+',
|
|
228
|
+
default=['VV'],
|
|
229
|
+
choices=['VV', 'VH', 'HH', 'HV'],
|
|
230
|
+
help='Polarizations to process (default: VV)'
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Adaptive thresholding arguments
|
|
234
|
+
parser.add_argument(
|
|
235
|
+
'--pfa',
|
|
236
|
+
type=float,
|
|
237
|
+
default=6.5,
|
|
238
|
+
help='Probability of false alarm for adaptive thresholding (default: 6.5)'
|
|
239
|
+
)
|
|
240
|
+
parser.add_argument(
|
|
241
|
+
'--background-window-m',
|
|
242
|
+
type=float,
|
|
243
|
+
default=800.0,
|
|
244
|
+
help='Background window size in meters (default: 800.0)'
|
|
245
|
+
)
|
|
246
|
+
parser.add_argument(
|
|
247
|
+
'--guard-window-m',
|
|
248
|
+
type=float,
|
|
249
|
+
default=500.0,
|
|
250
|
+
help='Guard window size in meters (default: 500.0)'
|
|
251
|
+
)
|
|
252
|
+
parser.add_argument(
|
|
253
|
+
'--target-window-m',
|
|
254
|
+
type=float,
|
|
255
|
+
default=50.0,
|
|
256
|
+
help='Target window size in meters (default: 50.0)'
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
# Object discrimination arguments
|
|
260
|
+
parser.add_argument(
|
|
261
|
+
'--min-target-m',
|
|
262
|
+
type=float,
|
|
263
|
+
default=50.0,
|
|
264
|
+
help='Minimum target size in meters (default: 50.0)'
|
|
265
|
+
)
|
|
266
|
+
parser.add_argument(
|
|
267
|
+
'--max-target-m',
|
|
268
|
+
type=float,
|
|
269
|
+
default=600.0,
|
|
270
|
+
help='Maximum target size in meters (default: 600.0)'
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# Processing options
|
|
274
|
+
parser.add_argument(
|
|
275
|
+
'--skip-calibration',
|
|
276
|
+
action='store_true',
|
|
277
|
+
help='Skip calibration step (default: False)'
|
|
278
|
+
)
|
|
279
|
+
parser.add_argument(
|
|
280
|
+
'--skip-discrimination',
|
|
281
|
+
action='store_true',
|
|
282
|
+
help='Skip object discrimination step (default: False)'
|
|
283
|
+
)
|
|
284
|
+
parser.add_argument(
|
|
285
|
+
'--verbose',
|
|
286
|
+
'-v',
|
|
287
|
+
action='store_true',
|
|
288
|
+
help='Enable verbose output (default: False)'
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _add_unzip_arguments(parser: argparse.ArgumentParser) -> None:
|
|
293
|
+
"""
|
|
294
|
+
Add arguments for the unzip subcommand.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
parser: The subparser for unzip command.
|
|
298
|
+
"""
|
|
299
|
+
parser.add_argument(
|
|
300
|
+
'--input',
|
|
301
|
+
type=str,
|
|
302
|
+
required=True,
|
|
303
|
+
help='Path to zip file or directory containing zip files'
|
|
304
|
+
)
|
|
305
|
+
parser.add_argument(
|
|
306
|
+
'--output',
|
|
307
|
+
type=str,
|
|
308
|
+
default='./extracted_data',
|
|
309
|
+
help='Output directory for extracted files (default: ./extracted_data)'
|
|
310
|
+
)
|
|
311
|
+
parser.add_argument(
|
|
312
|
+
'--recursive',
|
|
313
|
+
'-r',
|
|
314
|
+
action='store_true',
|
|
315
|
+
help='Recursively search for zip files in subdirectories'
|
|
316
|
+
)
|
|
317
|
+
parser.add_argument(
|
|
318
|
+
'--verbose',
|
|
319
|
+
'-v',
|
|
320
|
+
action='store_true',
|
|
321
|
+
help='Enable verbose logging'
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def _add_upload_arguments(parser: argparse.ArgumentParser) -> None:
|
|
326
|
+
"""
|
|
327
|
+
Add arguments for the upload subcommand.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
parser: The subparser for upload command.
|
|
331
|
+
"""
|
|
332
|
+
parser.add_argument(
|
|
333
|
+
'--folder',
|
|
334
|
+
type=str,
|
|
335
|
+
required=True,
|
|
336
|
+
help='Path to the folder to upload'
|
|
337
|
+
)
|
|
338
|
+
parser.add_argument(
|
|
339
|
+
'--repo',
|
|
340
|
+
type=str,
|
|
341
|
+
required=True,
|
|
342
|
+
help='Repository ID in format username/repo-name'
|
|
343
|
+
)
|
|
344
|
+
parser.add_argument(
|
|
345
|
+
'--repo-type',
|
|
346
|
+
type=str,
|
|
347
|
+
default='dataset',
|
|
348
|
+
choices=['dataset', 'model', 'space'],
|
|
349
|
+
help='Type of repository (default: dataset)'
|
|
350
|
+
)
|
|
351
|
+
parser.add_argument(
|
|
352
|
+
'--verbose',
|
|
353
|
+
'-v',
|
|
354
|
+
action='store_true',
|
|
355
|
+
help='Enable verbose logging'
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def _add_worldsar_arguments(parser: argparse.ArgumentParser) -> None:
|
|
360
|
+
"""
|
|
361
|
+
Add arguments for the worldsar subcommand.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
parser: The subparser for worldsar command.
|
|
365
|
+
"""
|
|
366
|
+
parser.add_argument(
|
|
367
|
+
'--input',
|
|
368
|
+
'-i',
|
|
369
|
+
dest='product_path',
|
|
370
|
+
type=str,
|
|
371
|
+
required=True,
|
|
372
|
+
help='Path to the input SAR product.'
|
|
373
|
+
)
|
|
374
|
+
parser.add_argument(
|
|
375
|
+
'--output',
|
|
376
|
+
'-o',
|
|
377
|
+
dest='output_dir',
|
|
378
|
+
type=str,
|
|
379
|
+
required=True,
|
|
380
|
+
help='Directory to save the processed output.'
|
|
381
|
+
)
|
|
382
|
+
parser.add_argument(
|
|
383
|
+
'--cuts-outdir',
|
|
384
|
+
'--cuts_outdir',
|
|
385
|
+
dest='cuts_outdir',
|
|
386
|
+
type=str,
|
|
387
|
+
required=True,
|
|
388
|
+
help='Where to store the tiles after extraction.'
|
|
389
|
+
)
|
|
390
|
+
parser.add_argument(
|
|
391
|
+
'--product-wkt',
|
|
392
|
+
'--product_wkt',
|
|
393
|
+
dest='product_wkt',
|
|
394
|
+
type=str,
|
|
395
|
+
required=True,
|
|
396
|
+
help='WKT string defining the product region of interest.'
|
|
397
|
+
)
|
|
398
|
+
parser.add_argument(
|
|
399
|
+
'--prod-mode',
|
|
400
|
+
'--prod_mode',
|
|
401
|
+
dest='prod_mode',
|
|
402
|
+
type=str,
|
|
403
|
+
required=True,
|
|
404
|
+
help='Product mode: ["S1TOPS", "S1STRIP", "BM", "NISAR", "TSX", "CSG", "ICE"].'
|
|
405
|
+
)
|
|
406
|
+
parser.add_argument(
|
|
407
|
+
'--gpt-path',
|
|
408
|
+
dest='gpt_path',
|
|
409
|
+
type=str,
|
|
410
|
+
default=None,
|
|
411
|
+
help='Override GPT executable path (default: gpt_path env var).'
|
|
412
|
+
)
|
|
413
|
+
parser.add_argument(
|
|
414
|
+
'--grid-path',
|
|
415
|
+
dest='grid_path',
|
|
416
|
+
type=str,
|
|
417
|
+
default=None,
|
|
418
|
+
help='Override grid GeoJSON path (default: grid_path env var).'
|
|
419
|
+
)
|
|
420
|
+
parser.add_argument(
|
|
421
|
+
'--db-dir',
|
|
422
|
+
dest='db_dir',
|
|
423
|
+
type=str,
|
|
424
|
+
default=None,
|
|
425
|
+
help='Override database output directory (default: db_dir env var).'
|
|
426
|
+
)
|
|
427
|
+
parser.add_argument(
|
|
428
|
+
'--gpt-memory',
|
|
429
|
+
dest='gpt_memory',
|
|
430
|
+
type=str,
|
|
431
|
+
default=None,
|
|
432
|
+
help='Override GPT Java heap (e.g., 24G).'
|
|
433
|
+
)
|
|
434
|
+
parser.add_argument(
|
|
435
|
+
'--gpt-parallelism',
|
|
436
|
+
dest='gpt_parallelism',
|
|
437
|
+
type=int,
|
|
438
|
+
default=None,
|
|
439
|
+
help='Override GPT parallelism (number of tiles).'
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def main() -> None:
|
|
444
|
+
"""
|
|
445
|
+
Main entry point for sarpyx CLI.
|
|
446
|
+
"""
|
|
447
|
+
parser = create_main_parser()
|
|
448
|
+
args = parser.parse_args()
|
|
449
|
+
|
|
450
|
+
# Check if a command was provided
|
|
451
|
+
if args.command is None:
|
|
452
|
+
parser.print_help()
|
|
453
|
+
sys.exit(1)
|
|
454
|
+
|
|
455
|
+
# Route to appropriate command handler
|
|
456
|
+
original_argv = sys.argv.copy()
|
|
457
|
+
|
|
458
|
+
try:
|
|
459
|
+
if args.command == 'decode':
|
|
460
|
+
from .decode import main as decode_main
|
|
461
|
+
sys.argv = ['sarpyx-decode'] + [arg for arg in original_argv[2:]]
|
|
462
|
+
decode_main()
|
|
463
|
+
elif args.command == 'focus':
|
|
464
|
+
from .focus import main as focus_main
|
|
465
|
+
sys.argv = ['sarpyx-focus'] + [arg for arg in original_argv[2:]]
|
|
466
|
+
focus_main()
|
|
467
|
+
elif args.command == 'shipdet':
|
|
468
|
+
from .shipdet import main as shipdet_main
|
|
469
|
+
sys.argv = ['sarpyx-shipdet'] + [arg for arg in original_argv[2:]]
|
|
470
|
+
shipdet_main()
|
|
471
|
+
elif args.command == 'unzip':
|
|
472
|
+
from .unzip import main as unzip_main
|
|
473
|
+
sys.argv = ['sarpyx-unzip'] + [arg for arg in original_argv[2:]]
|
|
474
|
+
unzip_main()
|
|
475
|
+
elif args.command == 'upload':
|
|
476
|
+
from .upload import main as upload_main
|
|
477
|
+
sys.argv = ['sarpyx-upload'] + [arg for arg in original_argv[2:]]
|
|
478
|
+
upload_main()
|
|
479
|
+
elif args.command == 'worldsar':
|
|
480
|
+
from .worldsar import main as worldsar_main
|
|
481
|
+
sys.argv = ['sarpyx-worldsar'] + [arg for arg in original_argv[2:]]
|
|
482
|
+
worldsar_main()
|
|
483
|
+
else:
|
|
484
|
+
print(f'Unknown command: {args.command}', file=sys.stderr)
|
|
485
|
+
sys.exit(1)
|
|
486
|
+
except SystemExit as e:
|
|
487
|
+
sys.exit(e.code)
|
|
488
|
+
finally:
|
|
489
|
+
sys.argv = original_argv
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
if __name__ == '__main__':
|
|
493
|
+
main()
|
sarpyx/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ data processing, including sub-look analysis, visualization, and integration
|
|
|
5
5
|
with processing frameworks.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = '0.1.
|
|
8
|
+
__version__ = '0.1.6'
|
|
9
9
|
__author__ = 'ESA Phi-Lab'
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
@@ -33,4 +33,4 @@ def __getattr__(name):
|
|
|
33
33
|
_module_cache[name] = module
|
|
34
34
|
return module
|
|
35
35
|
|
|
36
|
-
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
36
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
sarpyx/algorithms/__init__.py
CHANGED
|
@@ -4,7 +4,7 @@ This module contains various algorithms for Synthetic Aperture Radar (SAR)
|
|
|
4
4
|
data processing and analysis.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = '0.1.
|
|
7
|
+
__version__ = '0.1.6'
|
|
8
8
|
__author__ = 'SAR Processing Team'
|
|
9
9
|
|
|
10
10
|
# Import main algorithm modules here when they are created
|
|
@@ -15,4 +15,4 @@ __author__ = 'SAR Processing Team'
|
|
|
15
15
|
|
|
16
16
|
__all__ = [
|
|
17
17
|
# Add algorithm function/class names here as they are implemented
|
|
18
|
-
]
|
|
18
|
+
]
|
sarpyx/cli/__init__.py
CHANGED
sarpyx/cli/focus.py
CHANGED
|
@@ -186,7 +186,7 @@ def process_sar_slice(
|
|
|
186
186
|
|
|
187
187
|
# Focus slice data
|
|
188
188
|
result = focalize_slice(raw_data=raw_data, verbose=verbose)
|
|
189
|
-
logger.info(
|
|
189
|
+
logger.info('✅ Slice focused successfully.')
|
|
190
190
|
|
|
191
191
|
# Drop overlapping data
|
|
192
192
|
result['raw'] = result['raw'][drop_start:-drop_end] if drop_end > 0 else result['raw'][drop_start:]
|
|
@@ -198,10 +198,8 @@ def process_sar_slice(
|
|
|
198
198
|
if hasattr(result['metadata'], 'iloc'):
|
|
199
199
|
if drop_end > 0:
|
|
200
200
|
result['metadata'] = result['metadata'].iloc[drop_start:-drop_end]
|
|
201
|
-
result['ephemeris'] = result['ephemeris'].iloc[drop_start:-drop_end]
|
|
202
201
|
else:
|
|
203
202
|
result['metadata'] = result['metadata'].iloc[drop_start:]
|
|
204
|
-
result['ephemeris'] = result['ephemeris'].iloc[drop_start:]
|
|
205
203
|
|
|
206
204
|
logger.info(f'📉 Dropped overlapping data: start={drop_start}, end={drop_end}')
|
|
207
205
|
logger.info(f'📊 Focused data shape: {result["raw"].shape}')
|
|
@@ -217,7 +215,7 @@ def process_sar_slice(
|
|
|
217
215
|
zarr_path = tmp_dir.parent / f'{filename}.zarr'
|
|
218
216
|
logger.info(f'💾 Saving entire product to: {zarr_path}')
|
|
219
217
|
dask_slice_saver(result, zarr_path, chunks='auto', clevel=5)
|
|
220
|
-
logger.info(
|
|
218
|
+
logger.info('📂 Product saved successfully.')
|
|
221
219
|
|
|
222
220
|
# Clean up memory
|
|
223
221
|
del raw_data, result
|
|
@@ -258,7 +256,7 @@ def main() -> None:
|
|
|
258
256
|
# Extract product name
|
|
259
257
|
product_name = input_path.stem
|
|
260
258
|
|
|
261
|
-
logger.info(
|
|
259
|
+
logger.info('🚀 Starting SAR data focusing...')
|
|
262
260
|
logger.info(f'📁 Input file: {input_path}')
|
|
263
261
|
logger.info(f'📁 Output directory: {output_dir}')
|
|
264
262
|
logger.info(f'📁 Temporary directory: {tmp_dir}')
|