Skip to content

Commit edf56dc

Browse files
Enhance batches
1 parent b2c9e25 commit edf56dc

1 file changed

Lines changed: 50 additions & 7 deletions

File tree

insardev/insardev/Batch.py

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,7 +2251,8 @@ def unwrap2d(self, conncomp=False, conncomp_size=1000, conncomp_gap=None,
22512251
"""
22522252
Unwrap phase using GPU-accelerated IRLS algorithm (L¹ norm).
22532253
2254-
Expects Batches with [BatchWrap (phase), BatchUnit (weight, optional)].
2254+
Expects Batches with [BatchWrap or BatchComplex (phase), BatchUnit (weight, optional)].
2255+
If the first element is BatchComplex, .angle() is called automatically.
22552256
22562257
Parameters
22572258
----------
@@ -2291,8 +2292,12 @@ def unwrap2d(self, conncomp=False, conncomp_size=1000, conncomp_gap=None,
22912292
phase = self[0]
22922293
weight = self[1] if len(self) >= 2 and isinstance(self[1], BatchUnit) else None
22932294

2295+
# Auto-convert complex phase to wrapped phase
2296+
if isinstance(phase, BatchComplex):
2297+
phase = phase.angle()
2298+
22942299
if not isinstance(phase, BatchWrap):
2295-
raise TypeError(f"First element must be BatchWrap, got {type(phase).__name__}")
2300+
raise TypeError(f"First element must be BatchWrap or BatchComplex, got {type(phase).__name__}")
22962301

22972302
# Delegate to BatchWrap.unwrap2d
22982303
return phase.unwrap2d(weight=weight, conncomp=conncomp, conncomp_size=conncomp_size,
@@ -2304,7 +2309,8 @@ def unwrap2d_chunk(self, overlap=None, device='auto', debug=False, **kwargs):
23042309
"""
23052310
Unwrap phase per spatial chunk with overlap using IRLS algorithm.
23062311
2307-
Expects Batches with [BatchWrap (phase), BatchUnit (weight, optional)].
2312+
Expects Batches with [BatchWrap or BatchComplex (phase), BatchUnit (weight, optional)].
2313+
If the first element is BatchComplex, .angle() is called automatically.
23082314
23092315
Unlike unwrap2d() which requires a single spatial chunk, this method
23102316
unwraps each spatial chunk independently with overlap margins.
@@ -2337,8 +2343,12 @@ def unwrap2d_chunk(self, overlap=None, device='auto', debug=False, **kwargs):
23372343
phase = self[0]
23382344
weight = self[1] if len(self) >= 2 and isinstance(self[1], BatchUnit) else None
23392345

2346+
# Auto-convert complex phase to wrapped phase
2347+
if isinstance(phase, BatchComplex):
2348+
phase = phase.angle()
2349+
23402350
if not isinstance(phase, BatchWrap):
2341-
raise TypeError(f"First element must be BatchWrap, got {type(phase).__name__}")
2351+
raise TypeError(f"First element must be BatchWrap or BatchComplex, got {type(phase).__name__}")
23422352

23432353
unwrapped = phase.unwrap2d_chunk(weight=weight, overlap=overlap,
23442354
device=device, debug=debug, **kwargs)
@@ -2350,7 +2360,8 @@ def unwrap1d(self, device='auto', debug=False, **kwargs):
23502360
"""
23512361
1D temporal phase unwrapping using IRLS optimization.
23522362
2353-
Expects Batches with [BatchWrap (phase), BatchUnit (weight, optional)].
2363+
Expects Batches with [BatchWrap or BatchComplex (phase), BatchUnit (weight, optional)].
2364+
If the first element is BatchComplex, .angle() is called automatically.
23542365
23552366
Parameters
23562367
----------
@@ -2368,17 +2379,24 @@ def unwrap1d(self, device='auto', debug=False, **kwargs):
23682379
23692380
Examples
23702381
--------
2371-
>>> phase, corr = stack.pairs(baseline.tolist()).phasediff(wavelength=30).angle()
2382+
>>> # With explicit .angle()
2383+
>>> phase, corr = mintfcorr.detrend1d().angle()
23722384
>>> unwrapped, corr = Batches([phase, corr]).unwrap1d()
2385+
>>> # Or directly from complex phase (angle applied automatically)
2386+
>>> unwrapped, corr = mintfcorr.detrend1d().unwrap1d()
23732387
"""
23742388
if len(self) < 1:
23752389
raise ValueError("unwrap1d() requires Batches with at least 1 element: [phase]")
23762390

23772391
phase = self[0]
23782392
weight = self[1] if len(self) >= 2 and isinstance(self[1], BatchUnit) else None
23792393

2394+
# Auto-convert complex phase to wrapped phase
2395+
if isinstance(phase, BatchComplex):
2396+
phase = phase.angle()
2397+
23802398
if not isinstance(phase, BatchWrap):
2381-
raise TypeError(f"First element must be BatchWrap, got {type(phase).__name__}")
2399+
raise TypeError(f"First element must be BatchWrap or BatchComplex, got {type(phase).__name__}")
23822400

23832401
# Delegate to BatchWrap.unwrap1d
23842402
unwrapped = phase.unwrap1d(weight=weight, device=device, debug=debug, **kwargs)
@@ -2588,6 +2606,31 @@ def lstsq(self, device='auto', cumsum=True, debug=False):
25882606
elements = [result] + list(self[1:])
25892607
return Batches(elements)
25902608

2609+
def displacement_los(self, transform):
2610+
"""
2611+
Convert phase to line-of-sight displacement (meters).
2612+
2613+
Applies Batch.displacement_los() to the first element.
2614+
2615+
Parameters
2616+
----------
2617+
transform : Batch or Stack
2618+
Transform batch or Stack providing radar_wavelength.
2619+
2620+
Returns
2621+
-------
2622+
Batches
2623+
Batches with [displacement Batch] preserving other elements.
2624+
2625+
Examples
2626+
--------
2627+
>>> disp, corr = mintfcorr.detrend1d().unwrap1d().lstsq().displacement_los(stack.transform())
2628+
"""
2629+
data = self[0]
2630+
result = data.displacement_los(transform)
2631+
elements = [result] + list(self[1:])
2632+
return Batches(elements)
2633+
25912634
def regression1d_baseline(self, *args, **kwargs):
25922635
raise NotImplementedError("Batches.regression1d_baseline() is removed. Use Batches.detrend1d() or Batch.trend1d() instead.")
25932636

0 commit comments

Comments
 (0)