insardev 2025.2.20.dev0__tar.gz

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.
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Alexey Pechnikov, https://orcid.org/0000-0001-9626-8615 (ORCID)
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.2
2
+ Name: insardev
3
+ Version: 2025.2.20.dev0
4
+ Summary: InSAR.dev (Python InSAR): Satellite Interferometry Framework
5
+ Home-page: https://github.com/AlexeyPechnikov/pygmtsar
6
+ Author: Alexey Pechnikov
7
+ Author-email: alexey@pechnikov.dev
8
+ License: BSD-3-Clause
9
+ Keywords: satellite interferometry,InSAR,remote sensing,geospatial analysis,Sentinel-1,SBAS,PSI
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Natural Language :: English
13
+ Classifier: License :: OSI Approved :: BSD License
14
+ Classifier: Operating System :: POSIX
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE.txt
25
+ Requires-Dist: insardev_toolkit
26
+ Requires-Dist: xarray
27
+ Requires-Dist: numpy
28
+ Requires-Dist: numba
29
+ Requires-Dist: pandas
30
+ Requires-Dist: geopandas
31
+ Requires-Dist: distributed
32
+ Requires-Dist: dask[complete]
33
+ Requires-Dist: scipy
34
+ Requires-Dist: xgboost
35
+ Requires-Dist: cffi
36
+ Requires-Dist: scikit-learn
37
+ Requires-Dist: statsmodels>=0.14.0
38
+ Requires-Dist: matplotlib
39
+ Requires-Dist: adjustText
40
+ Requires-Dist: seaborn
41
+ Dynamic: author
42
+ Dynamic: author-email
43
+ Dynamic: classifier
44
+ Dynamic: description
45
+ Dynamic: description-content-type
46
+ Dynamic: home-page
47
+ Dynamic: keywords
48
+ Dynamic: license
49
+ Dynamic: requires-dist
50
+ Dynamic: requires-python
51
+ Dynamic: summary
52
+
53
+ [![View on GitHub](https://img.shields.io/badge/GitHub-View%20on%20GitHub-blue)](https://github.com/AlexeyPechnikov/pygmtsar)
54
+ [![Available on pypi](https://img.shields.io/pypi/v/pygmtsar.svg)](https://pypi.python.org/pypi/pygmtsar/)
55
+ [![Docker](https://badgen.net/badge/icon/docker?icon=docker&label)](https://hub.docker.com/r/pechnikov/pygmtsar)
56
+ [![DOI](https://zenodo.org/badge/398018212.svg)](https://zenodo.org/badge/latestdoi/398018212)
57
+ [![Support on Patreon](https://img.shields.io/badge/Patreon-Support-orange.svg)](https://www.patreon.com/pechnikov)
58
+ [![ChatGPT Assistant](https://img.shields.io/badge/ChatGPT-Assistant-green?logo=openai)](https://insar.dev/ai)
59
+
60
+ ## PyGMTSAR (Python InSAR): Powerful, Accessible Satellite Interferometry
61
+
62
+ <img src="assets/logo.jpg" width="15%" />
63
+
64
+ PyGMTSAR (Python InSAR) is designed for both occasional users and experts working with Sentinel-1 satellite interferometry. It supports a wide range of features, including SBAS, PSI, PSI-SBAS, and more. In addition to the examples below, you’ll find more Jupyter notebook use cases on [Patreon](https://www.patreon.com/pechnikov) and updates on [LinkedIn](https://www.linkedin.com/in/alexey-pechnikov/).
65
+
66
+ ## About PyGMTSAR
67
+
68
+ PyGMTSAR offers reproducible, high-performance Sentinel-1 interferometry accessible to everyone—whether you prefer Google Colab, cloud servers, or local processing. It automatically retrieves Sentinel-1 SLC scenes and bursts, DEMs, and orbits; computes interferograms and correlations; performs time-series analysis; and provides 3D visualization. This single library enables users to build a fully integrated InSAR project with minimal hassle. Whether you need a single interferogram or a multi-year analysis involving thousands of datasets, PyGMTSAR can handle the task efficiently, even on standard commodity hardware.
69
+
70
+ ## PyGMTSAR Live Examples on Google Colab
71
+
72
+ Google Colab is a free service that lets you run interactive notebooks directly in your browser—no powerful computer, extensive disk space, or special installations needed. You can even do InSAR processing from a smartphone. These notebooks automate every step: installing PyGMTSAR library and its dependencies on a Colab host (Ubuntu 22, Python 3.10), downloading Sentinel-1 SLCs, orbit files, SRTM DEM data (automatically converted to ellipsoidal heights via EGM96), land mask data, and then performing complete interferometry with final mapping. You can also modify scene or bursts names to analyze your own area of interest, and each notebook includes instant interactive 3D maps.
73
+
74
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1TARVTB7z8goZyEVDRWyTAKJpyuqZxzW2?usp=sharing) **Central Türkiye Earthquakes (2023).** The area is large, covering two consecutive Sentinel-1 scenes or a total of 56 bursts.
75
+
76
+ <img src="assets/turkie_2023a.jpg" width="40%" /><img src="assets/turkie_2023b.jpg" width="40%" />
77
+
78
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1dDFG8BoF4WfB6tOF5sAi5mjdBKRbhxHo?usp=sharing) **Pico do Fogo Volcano Eruption, Fogo Island, Cape Verde (2014).** The interferogram for this event is compared to the study *The 2014–2015 eruption of Fogo volcano: Geodetic modeling of Sentinel-1 TOPS interferometry* (*Geophysical Research Letters*, DOI: [10.1002/2015GL066003](https://doi.org/10.1002/2015GL066003)).
79
+
80
+ <img src="assets/pico_2014a.jpg" width="40%" /><img src="assets/pico_2014b.jpg" width="40%" />
81
+
82
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1d9RcqBmWIKQDEwJYo8Dh6M4tMjJtvseC?usp=sharing) **La Cumbre Volcano Eruption, Ecuador (2020).** The results compare with the report from Instituto Geofísico, Escuela Politécnica Nacional (IG-EPN) (InSAR software unspecified).
83
+
84
+ <img src="assets/la_cumbre_2020a.jpg" width="40%" /><img src="assets/la_cumbre_2020b.jpg" width="40%" />
85
+
86
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1shNGvUlUiXeyV7IcTmDbWaEM6XrB0014?usp=sharing) **Iran–Iraq Earthquake (2017).** The event has been well investigated, and the results compared to outputs from GMTSAR, SNAP, and GAMMA software.
87
+
88
+ <img src="assets/iran_iraq_2017a.jpg" width="40%" /><img src="assets/iran_iraq_2017b.jpg" width="40%" />
89
+
90
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1h4XxJZwFfm7EC8NUzl34cCkOVUG2uJr4?usp=sharing) **Imperial Valley Subsidence, CA USA (2015).** This example is provided in the [GMTSAR project](https://topex.ucsd.edu/gmtsar/downloads/) in the archive file [S1A_Stack_CPGF_T173.tar.gz](http://topex.ucsd.edu/gmtsar/tar/S1A_Stack_CPGF_T173.tar.gz), titled 'Sentinel-1 TOPS Time Series'.
91
+
92
+ The resulting InSAR velocity map is available as a self-contained web page at: [Imperial_Valley_2015.html](https://insar.dev/ui/Imperial_Valley_2015.html)
93
+
94
+ <img src="assets/imperial_valley_2015a.jpg" width="40%" /> <img src="assets/imperial_valley_2015b.jpg" width="40%" />
95
+
96
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1aqAr9KWKzGx9XpVie1M000C3vUxzNDxu?usp=sharing) **Kalkarindji Flooding, NT Australia (2024).** Correlation loss serves to identify flooded areas.
97
+
98
+ <img src="assets/kalkarindji_2024.jpg" width="80%" />
99
+
100
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1ipiQGbvUF8duzjZER8v-_R48DSpSmgvQ?usp=sharing) **Golden Valley Subsidence, CA USA (2021).** This example demonstrates the case study 'Antelope Valley Freeway in Santa Clarita, CA,' as detailed in [SAR Technical Series Part 4 Sentinel-1 global velocity layer: Using global InSAR at scale](https://blog.descarteslabs.com/using-global-insar-at-scale) and [Sentinel-1 Technical Series Part 5 Targeted Analysis](https://blog.descarteslabs.com/sentinel-1-targeted-analysis) with a significant subsidence rate 'exceeding 5cm/year in places'.
101
+
102
+ <img src="assets/golden_valley_2021.jpg" width="80%" />
103
+
104
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1O3aZtZsTrQIldvCqlVRel13wJRLhmTJt?usp=sharing) **Lake Sarez Landslides, Tajikistan (2017).** The example reproduces the findings shared in the following paper: [Integration of satellite SAR and optical acquisitions for the characterization of the Lake Sarez landslides in Tajikistan](https://www.google.com/url?q=https%3A%2F%2Fwww.researchgate.net%2Fpublication%2F378176884_Integration_of_satellite_SAR_and_optical_acquisitions_for_the_characterization_of_the_Lake_Sarez_landslides_in_Tajikistan).
105
+
106
+ <img src="assets/lake_sarez_2017.jpg" width="80%" />
107
+
108
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/19PLuebOZ4gaYX5ym1H7SwUbJKfl23qPr?usp=sharing) **Erzincan Elevation, Türkiye (2019).** This example reproduces 29-page ESA document [DEM generation with Sentinel-1 IW](https://step.esa.int/docs/tutorials/S1TBX%20DEM%20generation%20with%20Sentinel-1%20IW%20Tutorial.pdf).
109
+
110
+ <img src="assets/erzincan_2019.jpg" width="80%" />
111
+
112
+ ## More PyGMTSAR Live Examples on Google Colab
113
+
114
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1yuuA1ES2ly4QG3hyPg8YYT0nnpGDiQDw?usp=sharing) **Mexico City Subsidence, Mexico (2016).** This example replicates the 29-page ESA manual [TRAINING KIT – HAZA03. LAND SUBSIDENCE WITH SENTINEL-1 using SNAP](https://eo4society.esa.int/wp-content/uploads/2022/01/HAZA03_Land-Subsidence_Mexico-city.pdf).
115
+
116
+ ## PyGMTSAR Live Examples on Google Colab Pro
117
+
118
+ I share additional InSAR projects on Google Colab Pro through my [Patreon page](https://www.patreon.com/pechnikov). These are ideal for InSAR learners, researchers, and industry professionals tackling challenging projects with large areas, big stacks of interferograms, low-coherence regions, or significant atmospheric delays. You can run these privately shared notebooks online with Colab Pro or locally/on remote servers.
119
+
120
+ ## Projects and Publications Using PyGMTSAR
121
+
122
+ See the [Projects and Publications](/pubs/README.md) page for real-world projects and academic research applying PyGMTSAR. This is not an exhaustive list—contact me if you’d like your project or publication included.
123
+
124
+ ## Resources
125
+
126
+ **PyGMTSAR projects and e-books**
127
+ Available on [Patreon](https://www.patreon.com/c/pechnikov/shop). Preview versions can be found in this GitHub repo:
128
+
129
+ - [PyGMTSAR Introduction Preview](https://github.com/AlexeyPechnikov/pygmtsar/blob/pygmtsar2/book/PyGMTSAR_preview.pdf)
130
+ - [PyGMTSAR Gaussian Filtering Preview](https://github.com/AlexeyPechnikov/pygmtsar/blob/pygmtsar2/book/Gaussian_preview.pdf)
131
+
132
+ <img src="assets/listing.jpg" width="40%" />
133
+
134
+ **Video Lessons and Notebooks**
135
+ Find PyGMTSAR (Python InSAR) video lessons and educational notebooks on [Patreon](https://www.patreon.com/collection/12458) and [YouTube](https://www.youtube.com/channel/UCSEeXKAn9f_bDiTjT6l87Lg).
136
+
137
+ **PyGMTSAR AI Assistant**
138
+ The [PyGMTSAR AI Assistant](https://insar.dev/ai), powered by OpenAI ChatGPT, can explain InSAR theory, guide you through examples, help build an InSAR processing pipeline, and troubleshoot.
139
+
140
+ <img width="40%" alt="PyGMTSAR AI Assistant" src="assets/ai.jpg" />
141
+
142
+ **PyGMTSAR on DockerHub**
143
+ Run InSAR processing on macOS, Linux, or Windows via [Docker images](https://hub.docker.com/r/pechnikov/pygmtsar).
144
+
145
+ **PyGMTSAR on PyPI**
146
+ Install the library from [PyPI](https://pypi.python.org/pypi/pygmtsar).
147
+
148
+ **PyGMTSAR Previous Versions**
149
+ 2023 releases are still on GitHub, PyPI, DockerHub, and Google Colab. Compare PyGMTSAR InSAR with other software by checking out the [PyGMTSAR 2023 Repository](https://github.com/AlexeyPechnikov/pygmtsar/tree/pygmtsar).
150
+
151
+ © Alexey Pechnikov, 2025
@@ -0,0 +1,106 @@
1
+ # ----------------------------------------------------------------------------
2
+ # PyGMTSAR
3
+ #
4
+ # This file is part of the PyGMTSAR project: https://github.com/mobigroup/gmtsar
5
+ #
6
+ # Copyright (c) 2025, Alexey Pechnikov
7
+ #
8
+ # Licensed under the BSD 3-Clause License (see LICENSE for details)
9
+ # ----------------------------------------------------------------------------
10
+ from .Stack_export import Stack_export
11
+
12
+ class Stack(Stack_export):
13
+
14
+ def __repr__(self):
15
+ return 'Object %s %d bursts %d dates' % (self.__class__.__name__, len(self.ds), len(self.ds[0].date))
16
+
17
+ def to_dataset(self):
18
+ import numpy as np
19
+ import xarray as xr
20
+ data = xr.concat(xr.align(*self.ds, join='outer'), dim='stack_dim').mean('stack_dim')
21
+ return data
22
+
23
+ def __init__(self, basedir, pattern_burst='*_*_?W?', pattern_date = '????????.nc', scale = 2.5e-07):
24
+ """
25
+ Initialize an instance of the Stack class.
26
+ """
27
+ import numpy as np
28
+ import xarray as xr
29
+ import glob
30
+ import os
31
+
32
+ self.basedir = basedir
33
+
34
+ bursts = glob.glob(pattern_burst, root_dir=self.basedir)
35
+ datas = []
36
+ for burst in bursts:
37
+ data = xr.open_mfdataset(
38
+ os.path.join(self.basedir, burst, pattern_date),
39
+ engine=self.netcdf_engine_read,
40
+ format=self.netcdf_format,
41
+ parallel=True,
42
+ concat_dim='date',
43
+ chunks={'date': 1, 'y': self.chunksize, 'x': self.chunksize},
44
+ combine='nested',
45
+ )
46
+ #print (data)
47
+ # zero in np.int16 type means NODATA
48
+ data = self.spatial_ref(
49
+ scale*(data.re.astype(np.float32) + 1j*data.im.astype(np.float32)).where(data.re != 0).rename('data'),
50
+ data
51
+ )\
52
+ .to_dataset(name='data')\
53
+ .assign({v: data[v] for v in data.data_vars if v not in ['im', 're']})\
54
+ .assign_attrs({'burst': burst})
55
+ datas.append(data)
56
+ del data
57
+
58
+ self.ds = datas
59
+
60
+ def baseline_table(self):
61
+ import xarray as xr
62
+ return xr.concat([ds.BPR for ds in self.ds], dim='burst').mean('burst').to_dataframe()[['BPR']]
63
+
64
+ def baseline_pairs(self, days=None, meters=None, invert=False):
65
+ """
66
+ Generates a sorted list of baseline pairs.
67
+ Returns
68
+ -------
69
+ pandas.DataFrame
70
+ A DataFrame containing the sorted list of baseline pairs with reference and repeat dates,
71
+ timelines, and baselines.
72
+
73
+ """
74
+ import numpy as np
75
+ import pandas as pd
76
+
77
+ if days is None:
78
+ # use large number for unlimited time interval in days
79
+ days = 1e6
80
+
81
+ tbl = self.baseline_table()
82
+ data = []
83
+ for line1 in tbl.itertuples():
84
+ counter = 0
85
+ for line2 in tbl.itertuples():
86
+ #print (line1, line2)
87
+ if not (line1.Index < line2.Index and (line2.Index - line1.Index).days < days + 1):
88
+ continue
89
+ if meters is not None and not (abs(line1.BPR - line2.BPR)< meters + 1):
90
+ continue
91
+
92
+ counter += 1
93
+ if not invert:
94
+ data.append({'ref':line1.Index, 'rep': line2.Index,
95
+ 'ref_baseline': np.round(line1.BPR, 2),
96
+ 'rep_baseline': np.round(line2.BPR, 2)})
97
+ else:
98
+ data.append({'ref':line2.Index, 'rep': line1.Index,
99
+ 'ref_baseline': np.round(line2.BPR, 2),
100
+ 'rep_baseline': np.round(line1.BPR, 2)})
101
+
102
+ df = pd.DataFrame(data).sort_values(['ref', 'rep'])
103
+ return df.assign(pair=[f'{ref} {rep}' for ref, rep in zip(df['ref'].dt.date, df['rep'].dt.date)],
104
+ baseline=df.rep_baseline - df.ref_baseline,
105
+ duration=(df['rep'] - df['ref']).dt.days,
106
+ rel=np.datetime64('nat'))
@@ -0,0 +1,149 @@
1
+ # ----------------------------------------------------------------------------
2
+ # InSAR.dev
3
+ #
4
+ # This file is part of the InSAR.dev project: https://InSAR.dev
5
+ #
6
+ # Copyright (c) 2025, Alexey Pechnikov
7
+ #
8
+ # Licensed under the BSD 3-Clause License (see LICENSE for details)
9
+ # ----------------------------------------------------------------------------
10
+ from insardev_toolkit import tqdm_joblib, tqdm_dask
11
+ from .dataset import dataset
12
+
13
+ class Stack_base(tqdm_joblib, dataset):
14
+
15
+ def get_pairs(self, pairs, dates=False):
16
+ """
17
+ Get pairs as DataFrame and optionally dates array.
18
+
19
+ Parameters
20
+ ----------
21
+ pairs : np.ndarray, optional
22
+ An array of pairs. If None, all pairs are considered. Default is None.
23
+ dates : bool, optional
24
+ Whether to return dates array. Default is False.
25
+ name : str, optional
26
+ The name of the phase filter. Default is 'phasefilt'.
27
+
28
+ Returns
29
+ -------
30
+ pd.DataFrame or tuple
31
+ A DataFrame of pairs. If dates is True, also returns an array of dates.
32
+ """
33
+ import xarray as xr
34
+ import pandas as pd
35
+ import numpy as np
36
+ from glob import glob
37
+
38
+ if isinstance(pairs, pd.DataFrame):
39
+ # workaround for baseline_pairs() output
40
+ pairs = pairs.rename(columns={'ref_date': 'ref', 'rep_date': 'rep'})
41
+ elif isinstance(pairs, (xr.DataArray, xr.Dataset)):
42
+ # pairs = pd.DataFrame({
43
+ # 'ref': pairs.coords['ref'].values,
44
+ # 'rep': pairs.coords['rep'].values
45
+ # })
46
+ refs = pairs.coords['ref'].values
47
+ reps = pairs.coords['rep'].values
48
+ pairs = pd.DataFrame({
49
+ 'ref': refs if isinstance(refs, np.ndarray) else [refs],
50
+ 'rep': reps if isinstance(reps, np.ndarray) else [reps]
51
+ })
52
+ else:
53
+ # Convert numpy array to DataFrame
54
+ # in case of 1d array with 2 items convert to a single pair
55
+ pairs_2d = [pairs] if np.asarray(pairs).shape == (2,) else pairs
56
+ pairs = pd.DataFrame(pairs_2d, columns=['ref', 'rep'])
57
+
58
+ # Convert ref and rep columns to datetime format
59
+ pairs['ref'] = pd.to_datetime(pairs['ref'])
60
+ pairs['rep'] = pd.to_datetime(pairs['rep'])
61
+ pairs['pair'] = [f'{ref} {rep}' for ref, rep in zip(pairs['ref'].dt.date, pairs['rep'].dt.date)]
62
+ # Calculate the duration in days and add it as a new column
63
+ #pairs['duration'] = (pairs['rep'] - pairs['ref']).dt.days
64
+
65
+ if dates:
66
+ # pairs is DataFrame
67
+ dates = np.unique(pairs[['ref', 'rep']].astype(str).values.flatten())
68
+ return (pairs, dates)
69
+ return pairs
70
+
71
+ def get_pairs_matrix(self, pairs):
72
+ """
73
+ Create a matrix based on interferogram dates and pairs.
74
+
75
+ Parameters
76
+ ----------
77
+ pairs : pandas.DataFrame or xarray.DataArray or xarray.Dataset
78
+ DataFrame or DataArray containing interferogram date pairs.
79
+
80
+ Returns
81
+ -------
82
+ numpy.ndarray
83
+ A matrix with one row for every interferogram and one column for every date.
84
+ Each element in the matrix is a float, with 1 indicating the start date,
85
+ -1 indicating the end date, 0 if the date is covered by the corresponding
86
+ interferogram timeline, and NaN otherwise.
87
+
88
+ """
89
+ import numpy as np
90
+ import pandas as pd
91
+
92
+ # also define image capture dates from interferogram date pairs
93
+ pairs, dates = self.get_pairs(pairs, dates=True)
94
+ pairs = pairs[['ref', 'rep']].astype(str).values
95
+
96
+ # here are one row for every interferogram and one column for every date
97
+ matrix = []
98
+ for pair in pairs:
99
+ #mrow = [date>=pair[0] and date<=pair[1] for date in dates]
100
+ mrow = [(-1 if date==pair[0] else (1 if date==pair[1] else (0 if date>pair[0] and date<pair[1] else np.nan))) for date in dates]
101
+ matrix.append(mrow)
102
+ matrix = np.stack(matrix).astype(np.float32)
103
+ return matrix
104
+
105
+ @staticmethod
106
+ def phase_to_positive_range(phase):
107
+ """
108
+ Convert phase from the range [-pi, pi] to [0, 2pi].
109
+
110
+ Parameters
111
+ ----------
112
+ phase : array_like
113
+ Input phase values in the range [-pi, pi].
114
+
115
+ Returns
116
+ -------
117
+ ndarray
118
+ Phase values converted to the range [0, 2pi].
119
+
120
+ Examples
121
+ --------
122
+ >>> phase_to_positive_range(np.array([-np.pi, -np.pi/2, np.pi, 2*-np.pi-1e-6, 2*-np.pi]))
123
+ array([3.14159265, 4.71238898, 3.14159265, 6.28318431, 0. ])
124
+ """
125
+ import numpy as np
126
+ return (phase + 2 * np.pi) % (2 * np.pi)
127
+
128
+ @staticmethod
129
+ def phase_to_symmetric_range(phase):
130
+ """
131
+ Convert phase from the range [0, 2pi] to [-pi, pi].
132
+
133
+ Parameters
134
+ ----------
135
+ phase : array_like
136
+ Input phase values in the range [0, 2pi].
137
+
138
+ Returns
139
+ -------
140
+ ndarray
141
+ Phase values converted to the range [-pi, pi].
142
+
143
+ Examples
144
+ --------
145
+ >>> phase_to_symmetric_range(np.array([0, np.pi, 3*np.pi/2, 2*np.pi]))
146
+ array([ 0. , 3.14159265, -1.57079633, 0. ])
147
+ """
148
+ import numpy as np
149
+ return (phase + np.pi) % (2 * np.pi) - np.pi