DASPy-toolbox 1.0.0__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.
- DASPy-toolbox-1.0.0/DASPy_toolbox.egg-info/PKG-INFO +85 -0
- DASPy-toolbox-1.0.0/DASPy_toolbox.egg-info/SOURCES.txt +52 -0
- DASPy-toolbox-1.0.0/DASPy_toolbox.egg-info/dependency_links.txt +1 -0
- DASPy-toolbox-1.0.0/DASPy_toolbox.egg-info/entry_points.txt +2 -0
- DASPy-toolbox-1.0.0/DASPy_toolbox.egg-info/requires.txt +9 -0
- DASPy-toolbox-1.0.0/DASPy_toolbox.egg-info/top_level.txt +1 -0
- DASPy-toolbox-1.0.0/LICENSE.txt +1 -0
- DASPy-toolbox-1.0.0/PKG-INFO +85 -0
- DASPy-toolbox-1.0.0/README.md +60 -0
- DASPy-toolbox-1.0.0/daspy/__init__.py +4 -0
- DASPy-toolbox-1.0.0/daspy/advanced_tools/__init__.py +0 -0
- DASPy-toolbox-1.0.0/daspy/advanced_tools/channel.py +354 -0
- DASPy-toolbox-1.0.0/daspy/advanced_tools/decomposition.py +165 -0
- DASPy-toolbox-1.0.0/daspy/advanced_tools/denoising.py +276 -0
- DASPy-toolbox-1.0.0/daspy/advanced_tools/fdct.py +789 -0
- DASPy-toolbox-1.0.0/daspy/advanced_tools/strain2vel.py +245 -0
- DASPy-toolbox-1.0.0/daspy/basic_tools/__init__.py +0 -0
- DASPy-toolbox-1.0.0/daspy/basic_tools/filter.py +257 -0
- DASPy-toolbox-1.0.0/daspy/basic_tools/freqattributes.py +117 -0
- DASPy-toolbox-1.0.0/daspy/basic_tools/preprocessing.py +238 -0
- DASPy-toolbox-1.0.0/daspy/basic_tools/visualization.py +186 -0
- DASPy-toolbox-1.0.0/daspy/core/__init__.py +4 -0
- DASPy-toolbox-1.0.0/daspy/core/collection.py +279 -0
- DASPy-toolbox-1.0.0/daspy/core/dasdatetime.py +72 -0
- DASPy-toolbox-1.0.0/daspy/core/example.pkl +0 -0
- DASPy-toolbox-1.0.0/daspy/core/make_example.py +32 -0
- DASPy-toolbox-1.0.0/daspy/core/read.py +544 -0
- DASPy-toolbox-1.0.0/daspy/core/section.py +1319 -0
- DASPy-toolbox-1.0.0/daspy/core/write.py +282 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/__init__.py +1 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/calc_travel_time.py +23 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/core.py +119 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/detection.py +12 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/gamma/__init__.py +13 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/gamma/_base.py +549 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/gamma/_bayesian_mixture.py +875 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/gamma/_gaussian_mixture.py +866 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/gamma/app.py +192 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/gamma/seismic_ops.py +478 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/gamma/utils.py +512 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/location.py +266 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/magnitude.py +43 -0
- DASPy-toolbox-1.0.0/daspy/seismic_detection/phase_picking.py +67 -0
- DASPy-toolbox-1.0.0/daspy/structure_imaging/__init__.py +0 -0
- DASPy-toolbox-1.0.0/daspy/structure_imaging/ambient_noise.py +4 -0
- DASPy-toolbox-1.0.0/daspy/structure_imaging/dispersion.py +27 -0
- DASPy-toolbox-1.0.0/daspy/structure_imaging/fault_zone.py +59 -0
- DASPy-toolbox-1.0.0/daspy/structure_imaging/inversion.py +6 -0
- DASPy-toolbox-1.0.0/daspy/traffic_monitoring/JamDetection.py +6 -0
- DASPy-toolbox-1.0.0/daspy/traffic_monitoring/SpeedMeasurement.py +6 -0
- DASPy-toolbox-1.0.0/daspy/traffic_monitoring/VehicleDetection.py +6 -0
- DASPy-toolbox-1.0.0/daspy/traffic_monitoring/__init__.py +0 -0
- DASPy-toolbox-1.0.0/setup.cfg +4 -0
- DASPy-toolbox-1.0.0/setup.py +46 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: DASPy-toolbox
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: DASPy is an open-source project dedicated to provide a python package for DAS (Distributed Acoustic Sensing) data processing, which comprises classic seismic data processing techniques and Specialized algorithms for DAS applications.
|
|
5
|
+
Home-page: https://github.com/HMZ-03/DASPy
|
|
6
|
+
Author: Minzhe Hu, Zefeng Li
|
|
7
|
+
Author-email: hmz2018@mail.ustc.edu.cn
|
|
8
|
+
Maintainer: Minzhe Hu
|
|
9
|
+
Maintainer-email: hmz2018@mail.ustc.edu.cn
|
|
10
|
+
License: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
License-File: LICENSE.txt
|
|
16
|
+
Requires-Dist: numpy
|
|
17
|
+
Requires-Dist: scipy>=1.13
|
|
18
|
+
Requires-Dist: matplotlib
|
|
19
|
+
Requires-Dist: geographiclib
|
|
20
|
+
Requires-Dist: pyproj
|
|
21
|
+
Requires-Dist: h5py
|
|
22
|
+
Requires-Dist: segyio
|
|
23
|
+
Requires-Dist: nptdms
|
|
24
|
+
Requires-Dist: tqdm
|
|
25
|
+
|
|
26
|
+
<img src="./website/USTC.svg" height="170" /> <img src="./website/DAMS.png" height="150" />
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## DASPy
|
|
30
|
+
|
|
31
|
+
DASPy is an open-source project dedicated to provide a python package for DAS (Distributed Acoustic Sensing) data processing.
|
|
32
|
+
|
|
33
|
+
The goal of the DASPy project is to lower the bar of DAS data processing. DASPy includes:
|
|
34
|
+
* Classic seismic data processing techniques, including preprocessing, filter, spectrum analysis, and visualization
|
|
35
|
+
* Specialized algorithms for DAS applications, including denoising, waveform decomposition, channel attribute analysis, and strain-velocity conversion.
|
|
36
|
+
|
|
37
|
+
DASPy is licensed under the MIT License. [An English version of DASPy tutorial](https://daspy-tutorial.readthedocs.io/en/latest/), [a Chinese version of DASPy tutorial](https://daspy-tutorial-cn.readthedocs.io/zh-cn/latest/) and [the DASPy paper](document/srl-2024124.1.pdf) is available. If you have any questions, please contact me via <hmz2018@mail.ustc.edu.cn>.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
DASPy is currently running on Linux, Windows and Mac OS.
|
|
41
|
+
DASPy runs on Python 3.9 and up. We recommend you use the latest version of python 3 if possible.
|
|
42
|
+
|
|
43
|
+
### Pip (recommanded)
|
|
44
|
+
```
|
|
45
|
+
pip install git+https://github.com/HMZ-03/DASPy.git
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If you installed DASPy this way, you can upgrade DASPy with the following command:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
pip install --upgrade git+https://github.com/HMZ-03/DASPy.git
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Conda
|
|
55
|
+
```
|
|
56
|
+
conda install -c hmz-03 daspy
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If an error is reported, please try updating conda:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
conda update -n base -c conda-forge conda
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Manual installation
|
|
66
|
+
1. Install dependent packages: numpy, scipy >=1.13, matplotlib, geographiclib, pyproj, h5py, segyio, nptdms, tqdm
|
|
67
|
+
|
|
68
|
+
2. Add DASPy into your Python path.
|
|
69
|
+
|
|
70
|
+
## Getting started
|
|
71
|
+
```
|
|
72
|
+
from daspy import read
|
|
73
|
+
sec = read() # load example waveform
|
|
74
|
+
sec.bandpass(1, 15)
|
|
75
|
+
sec.plot()
|
|
76
|
+
```
|
|
77
|
+
<img src="./website/waveform.png" height="500" />
|
|
78
|
+
|
|
79
|
+
### Contributing
|
|
80
|
+
|
|
81
|
+
Please see details on how to contribute to the project [here](CONTRIBUTING.md) and [here](CodingStyleGuide.md).
|
|
82
|
+
|
|
83
|
+
### Reference
|
|
84
|
+
|
|
85
|
+
* Minzhe Hu and Zefeng Li (2024), [DASPy: A Python Toolbox for DAS Seismology](https://pubs.geoscienceworld.org/ssa/srl/article/95/5/3055/645865/DASPy-A-Python-Toolbox-for-DAS-Seismology), *Seismological Research Letters*, 95(5), 3055–3066, doi: `https://doi.org/10.1785/0220240124`.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
LICENSE.txt
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
DASPy_toolbox.egg-info/PKG-INFO
|
|
5
|
+
DASPy_toolbox.egg-info/SOURCES.txt
|
|
6
|
+
DASPy_toolbox.egg-info/dependency_links.txt
|
|
7
|
+
DASPy_toolbox.egg-info/entry_points.txt
|
|
8
|
+
DASPy_toolbox.egg-info/requires.txt
|
|
9
|
+
DASPy_toolbox.egg-info/top_level.txt
|
|
10
|
+
daspy/__init__.py
|
|
11
|
+
daspy/advanced_tools/__init__.py
|
|
12
|
+
daspy/advanced_tools/channel.py
|
|
13
|
+
daspy/advanced_tools/decomposition.py
|
|
14
|
+
daspy/advanced_tools/denoising.py
|
|
15
|
+
daspy/advanced_tools/fdct.py
|
|
16
|
+
daspy/advanced_tools/strain2vel.py
|
|
17
|
+
daspy/basic_tools/__init__.py
|
|
18
|
+
daspy/basic_tools/filter.py
|
|
19
|
+
daspy/basic_tools/freqattributes.py
|
|
20
|
+
daspy/basic_tools/preprocessing.py
|
|
21
|
+
daspy/basic_tools/visualization.py
|
|
22
|
+
daspy/core/__init__.py
|
|
23
|
+
daspy/core/collection.py
|
|
24
|
+
daspy/core/dasdatetime.py
|
|
25
|
+
daspy/core/example.pkl
|
|
26
|
+
daspy/core/make_example.py
|
|
27
|
+
daspy/core/read.py
|
|
28
|
+
daspy/core/section.py
|
|
29
|
+
daspy/core/write.py
|
|
30
|
+
daspy/seismic_detection/__init__.py
|
|
31
|
+
daspy/seismic_detection/calc_travel_time.py
|
|
32
|
+
daspy/seismic_detection/core.py
|
|
33
|
+
daspy/seismic_detection/detection.py
|
|
34
|
+
daspy/seismic_detection/location.py
|
|
35
|
+
daspy/seismic_detection/magnitude.py
|
|
36
|
+
daspy/seismic_detection/phase_picking.py
|
|
37
|
+
daspy/seismic_detection/gamma/__init__.py
|
|
38
|
+
daspy/seismic_detection/gamma/_base.py
|
|
39
|
+
daspy/seismic_detection/gamma/_bayesian_mixture.py
|
|
40
|
+
daspy/seismic_detection/gamma/_gaussian_mixture.py
|
|
41
|
+
daspy/seismic_detection/gamma/app.py
|
|
42
|
+
daspy/seismic_detection/gamma/seismic_ops.py
|
|
43
|
+
daspy/seismic_detection/gamma/utils.py
|
|
44
|
+
daspy/structure_imaging/__init__.py
|
|
45
|
+
daspy/structure_imaging/ambient_noise.py
|
|
46
|
+
daspy/structure_imaging/dispersion.py
|
|
47
|
+
daspy/structure_imaging/fault_zone.py
|
|
48
|
+
daspy/structure_imaging/inversion.py
|
|
49
|
+
daspy/traffic_monitoring/JamDetection.py
|
|
50
|
+
daspy/traffic_monitoring/SpeedMeasurement.py
|
|
51
|
+
daspy/traffic_monitoring/VehicleDetection.py
|
|
52
|
+
daspy/traffic_monitoring/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
daspy
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
daspy/LICENSE.txt
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: DASPy-toolbox
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: DASPy is an open-source project dedicated to provide a python package for DAS (Distributed Acoustic Sensing) data processing, which comprises classic seismic data processing techniques and Specialized algorithms for DAS applications.
|
|
5
|
+
Home-page: https://github.com/HMZ-03/DASPy
|
|
6
|
+
Author: Minzhe Hu, Zefeng Li
|
|
7
|
+
Author-email: hmz2018@mail.ustc.edu.cn
|
|
8
|
+
Maintainer: Minzhe Hu
|
|
9
|
+
Maintainer-email: hmz2018@mail.ustc.edu.cn
|
|
10
|
+
License: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
License-File: LICENSE.txt
|
|
16
|
+
Requires-Dist: numpy
|
|
17
|
+
Requires-Dist: scipy>=1.13
|
|
18
|
+
Requires-Dist: matplotlib
|
|
19
|
+
Requires-Dist: geographiclib
|
|
20
|
+
Requires-Dist: pyproj
|
|
21
|
+
Requires-Dist: h5py
|
|
22
|
+
Requires-Dist: segyio
|
|
23
|
+
Requires-Dist: nptdms
|
|
24
|
+
Requires-Dist: tqdm
|
|
25
|
+
|
|
26
|
+
<img src="./website/USTC.svg" height="170" /> <img src="./website/DAMS.png" height="150" />
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## DASPy
|
|
30
|
+
|
|
31
|
+
DASPy is an open-source project dedicated to provide a python package for DAS (Distributed Acoustic Sensing) data processing.
|
|
32
|
+
|
|
33
|
+
The goal of the DASPy project is to lower the bar of DAS data processing. DASPy includes:
|
|
34
|
+
* Classic seismic data processing techniques, including preprocessing, filter, spectrum analysis, and visualization
|
|
35
|
+
* Specialized algorithms for DAS applications, including denoising, waveform decomposition, channel attribute analysis, and strain-velocity conversion.
|
|
36
|
+
|
|
37
|
+
DASPy is licensed under the MIT License. [An English version of DASPy tutorial](https://daspy-tutorial.readthedocs.io/en/latest/), [a Chinese version of DASPy tutorial](https://daspy-tutorial-cn.readthedocs.io/zh-cn/latest/) and [the DASPy paper](document/srl-2024124.1.pdf) is available. If you have any questions, please contact me via <hmz2018@mail.ustc.edu.cn>.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
DASPy is currently running on Linux, Windows and Mac OS.
|
|
41
|
+
DASPy runs on Python 3.9 and up. We recommend you use the latest version of python 3 if possible.
|
|
42
|
+
|
|
43
|
+
### Pip (recommanded)
|
|
44
|
+
```
|
|
45
|
+
pip install git+https://github.com/HMZ-03/DASPy.git
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If you installed DASPy this way, you can upgrade DASPy with the following command:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
pip install --upgrade git+https://github.com/HMZ-03/DASPy.git
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Conda
|
|
55
|
+
```
|
|
56
|
+
conda install -c hmz-03 daspy
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If an error is reported, please try updating conda:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
conda update -n base -c conda-forge conda
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Manual installation
|
|
66
|
+
1. Install dependent packages: numpy, scipy >=1.13, matplotlib, geographiclib, pyproj, h5py, segyio, nptdms, tqdm
|
|
67
|
+
|
|
68
|
+
2. Add DASPy into your Python path.
|
|
69
|
+
|
|
70
|
+
## Getting started
|
|
71
|
+
```
|
|
72
|
+
from daspy import read
|
|
73
|
+
sec = read() # load example waveform
|
|
74
|
+
sec.bandpass(1, 15)
|
|
75
|
+
sec.plot()
|
|
76
|
+
```
|
|
77
|
+
<img src="./website/waveform.png" height="500" />
|
|
78
|
+
|
|
79
|
+
### Contributing
|
|
80
|
+
|
|
81
|
+
Please see details on how to contribute to the project [here](CONTRIBUTING.md) and [here](CodingStyleGuide.md).
|
|
82
|
+
|
|
83
|
+
### Reference
|
|
84
|
+
|
|
85
|
+
* Minzhe Hu and Zefeng Li (2024), [DASPy: A Python Toolbox for DAS Seismology](https://pubs.geoscienceworld.org/ssa/srl/article/95/5/3055/645865/DASPy-A-Python-Toolbox-for-DAS-Seismology), *Seismological Research Letters*, 95(5), 3055–3066, doi: `https://doi.org/10.1785/0220240124`.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<img src="./website/USTC.svg" height="170" /> <img src="./website/DAMS.png" height="150" />
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## DASPy
|
|
5
|
+
|
|
6
|
+
DASPy is an open-source project dedicated to provide a python package for DAS (Distributed Acoustic Sensing) data processing.
|
|
7
|
+
|
|
8
|
+
The goal of the DASPy project is to lower the bar of DAS data processing. DASPy includes:
|
|
9
|
+
* Classic seismic data processing techniques, including preprocessing, filter, spectrum analysis, and visualization
|
|
10
|
+
* Specialized algorithms for DAS applications, including denoising, waveform decomposition, channel attribute analysis, and strain-velocity conversion.
|
|
11
|
+
|
|
12
|
+
DASPy is licensed under the MIT License. [An English version of DASPy tutorial](https://daspy-tutorial.readthedocs.io/en/latest/), [a Chinese version of DASPy tutorial](https://daspy-tutorial-cn.readthedocs.io/zh-cn/latest/) and [the DASPy paper](document/srl-2024124.1.pdf) is available. If you have any questions, please contact me via <hmz2018@mail.ustc.edu.cn>.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
DASPy is currently running on Linux, Windows and Mac OS.
|
|
16
|
+
DASPy runs on Python 3.9 and up. We recommend you use the latest version of python 3 if possible.
|
|
17
|
+
|
|
18
|
+
### Pip (recommanded)
|
|
19
|
+
```
|
|
20
|
+
pip install git+https://github.com/HMZ-03/DASPy.git
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If you installed DASPy this way, you can upgrade DASPy with the following command:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
pip install --upgrade git+https://github.com/HMZ-03/DASPy.git
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Conda
|
|
30
|
+
```
|
|
31
|
+
conda install -c hmz-03 daspy
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If an error is reported, please try updating conda:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
conda update -n base -c conda-forge conda
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Manual installation
|
|
41
|
+
1. Install dependent packages: numpy, scipy >=1.13, matplotlib, geographiclib, pyproj, h5py, segyio, nptdms, tqdm
|
|
42
|
+
|
|
43
|
+
2. Add DASPy into your Python path.
|
|
44
|
+
|
|
45
|
+
## Getting started
|
|
46
|
+
```
|
|
47
|
+
from daspy import read
|
|
48
|
+
sec = read() # load example waveform
|
|
49
|
+
sec.bandpass(1, 15)
|
|
50
|
+
sec.plot()
|
|
51
|
+
```
|
|
52
|
+
<img src="./website/waveform.png" height="500" />
|
|
53
|
+
|
|
54
|
+
### Contributing
|
|
55
|
+
|
|
56
|
+
Please see details on how to contribute to the project [here](CONTRIBUTING.md) and [here](CodingStyleGuide.md).
|
|
57
|
+
|
|
58
|
+
### Reference
|
|
59
|
+
|
|
60
|
+
* Minzhe Hu and Zefeng Li (2024), [DASPy: A Python Toolbox for DAS Seismology](https://pubs.geoscienceworld.org/ssa/srl/article/95/5/3055/645865/DASPy-A-Python-Toolbox-for-DAS-Seismology), *Seismological Research Letters*, 95(5), 3055–3066, doi: `https://doi.org/10.1785/0220240124`.
|
|
File without changes
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# Purpose: Several functions for analysis data quality and geometry of channels
|
|
2
|
+
# Author: Minzhe Hu, Zefeng Li
|
|
3
|
+
# Date: 2024.10.11
|
|
4
|
+
# Email: hmz2018@mail.ustc.edu.cn
|
|
5
|
+
import numpy as np
|
|
6
|
+
from copy import deepcopy
|
|
7
|
+
from geographiclib.geodesic import Geodesic
|
|
8
|
+
from pyproj import Proj
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def robust_polyfit(data, deg, thresh):
|
|
12
|
+
"""
|
|
13
|
+
Fit a curve with a robust weighted polynomial.
|
|
14
|
+
|
|
15
|
+
:param data: 1-dimensional array.
|
|
16
|
+
:param deg: int. Degree of the fitting polynomial
|
|
17
|
+
:param thresh: int or float. Defined MAD multiple of outliers.
|
|
18
|
+
:return: Fitting data
|
|
19
|
+
"""
|
|
20
|
+
nch = len(data)
|
|
21
|
+
channels = np.arange(nch)
|
|
22
|
+
p_coef = np.polyfit(channels, data, deg)
|
|
23
|
+
p_fit = np.poly1d(p_coef)
|
|
24
|
+
old_data = p_fit(channels)
|
|
25
|
+
mse = 1
|
|
26
|
+
|
|
27
|
+
# robust fitting until the fitting curve changes < 0.1% at every point.
|
|
28
|
+
while mse > 0.001:
|
|
29
|
+
rsl = abs(data - old_data)
|
|
30
|
+
mad = np.median(rsl)
|
|
31
|
+
weights = np.zeros(nch)
|
|
32
|
+
weights[rsl < thresh * mad] = 1
|
|
33
|
+
p_coef = np.polyfit(channels, data, deg, w=weights)
|
|
34
|
+
p_fit = np.poly1d(p_coef)
|
|
35
|
+
new_data = p_fit(channels)
|
|
36
|
+
mse = np.nanmax(np.abs((new_data - old_data) / old_data))
|
|
37
|
+
old_data = new_data
|
|
38
|
+
|
|
39
|
+
return new_data, weights
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _continuity_checking(lst1, lst2, adjacent=2, toleration=2):
|
|
43
|
+
lst1_raw = deepcopy(lst1)
|
|
44
|
+
for chn in lst1_raw:
|
|
45
|
+
discont = [a for a in lst2 if abs(a - chn) <= adjacent]
|
|
46
|
+
if len(discont) >= adjacent * 2 + 1 - toleration:
|
|
47
|
+
lst1.remove(chn)
|
|
48
|
+
lst2.append(chn)
|
|
49
|
+
|
|
50
|
+
return lst1, lst2
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def channel_checking(data, deg=10, thresh=5, continuity=True, adjacent=2,
|
|
54
|
+
toleration=2, mode='low', verbose=False):
|
|
55
|
+
"""
|
|
56
|
+
Use the energy of each channel to determine which channels are bad.
|
|
57
|
+
|
|
58
|
+
:param data: 2-dimensional np.ndarray. Axis 0 is channel number and axis 1 is
|
|
59
|
+
time series
|
|
60
|
+
:param deg: int. Degree of the fitting polynomial
|
|
61
|
+
:param thresh: int or float. The MAD multiple of bad channel energy lower
|
|
62
|
+
than good channels.
|
|
63
|
+
:param continuity: bool. Perform continuity checks on bad channels and good
|
|
64
|
+
channels.
|
|
65
|
+
:param adjacent: int. The number of nearby channels for continuity checks.
|
|
66
|
+
:param toleration: int. The number of discontinuous channel allowed in each
|
|
67
|
+
channel (including itself) in the continuity check.
|
|
68
|
+
:param mode: str. 'low' means bad channels have low amplitude, 'high' means
|
|
69
|
+
bad channels have high amplitude, and 'both' means bad channels are
|
|
70
|
+
likely to have low or high amplitude.
|
|
71
|
+
:return: Good channels and bad channels.
|
|
72
|
+
"""
|
|
73
|
+
nch = len(data)
|
|
74
|
+
energy = np.log10(np.sum(data**2, axis=1))
|
|
75
|
+
|
|
76
|
+
# Remove abnormal value by robust polynomial fitting.
|
|
77
|
+
fitted_energy, weights = robust_polyfit(energy, deg, thresh)
|
|
78
|
+
deviation = energy - fitted_energy
|
|
79
|
+
|
|
80
|
+
# Iterate eliminates outliers.
|
|
81
|
+
mad = np.median(abs(deviation[weights > 0]))
|
|
82
|
+
if mode == 'low':
|
|
83
|
+
bad_chn = np.argwhere(deviation < -thresh * mad).ravel().tolist()
|
|
84
|
+
elif mode == 'high':
|
|
85
|
+
bad_chn = np.argwhere(deviation > thresh * mad).ravel().tolist()
|
|
86
|
+
elif mode == 'high':
|
|
87
|
+
bad_chn = np.argwhere(deviation < -thresh * mad).ravel().tolist() + \
|
|
88
|
+
np.argwhere(deviation > thresh * mad).ravel().tolist()
|
|
89
|
+
good_chn = list(set(range(nch)) - set(bad_chn))
|
|
90
|
+
|
|
91
|
+
if continuity:
|
|
92
|
+
# Discontinuous normal value are part of bad channels.
|
|
93
|
+
good_chn, bad_chn = _continuity_checking(good_chn, bad_chn,
|
|
94
|
+
adjacent=adjacent,
|
|
95
|
+
toleration=toleration)
|
|
96
|
+
|
|
97
|
+
# Discontinuous outliers are usually not bad channels.
|
|
98
|
+
bad_chn, good_chn = _continuity_checking(bad_chn, good_chn,
|
|
99
|
+
adjacent=adjacent,
|
|
100
|
+
toleration=toleration)
|
|
101
|
+
|
|
102
|
+
bad_chn = np.sort(np.array(bad_chn))
|
|
103
|
+
good_chn = np.sort(np.array(good_chn))
|
|
104
|
+
if verbose:
|
|
105
|
+
return good_chn, bad_chn, energy, fitted_energy - thresh * mad
|
|
106
|
+
|
|
107
|
+
return good_chn, bad_chn
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _channel_location(track_pt):
|
|
111
|
+
track, tn = track_pt[:, :-1], track_pt[:, -1]
|
|
112
|
+
dim = track.shape[1]
|
|
113
|
+
l_track = np.sqrt(np.sum(np.diff(track, axis=0) ** 2, axis=1))
|
|
114
|
+
l_track_cum = np.hstack(([0], np.cumsum(l_track)))
|
|
115
|
+
idx_kp = np.where(tn >= 0)[0]
|
|
116
|
+
|
|
117
|
+
interp_ch = []
|
|
118
|
+
chn = np.floor(tn[idx_kp[0]])
|
|
119
|
+
if abs(chn - tn[idx_kp[0]]) < 1e-6:
|
|
120
|
+
interp_ch.append([*track[idx_kp[0]], chn])
|
|
121
|
+
|
|
122
|
+
seg_interval = []
|
|
123
|
+
for i in range(1, len(idx_kp)):
|
|
124
|
+
# calculate actual interval between known-channel points
|
|
125
|
+
istart, iend = idx_kp[i - 1], idx_kp[i]
|
|
126
|
+
n_chn_kp = tn[iend] - tn[istart]
|
|
127
|
+
d_interp = (l_track_cum[iend] - l_track_cum[istart]) / n_chn_kp
|
|
128
|
+
seg_interval.append([tn[istart], tn[iend], d_interp])
|
|
129
|
+
|
|
130
|
+
l_res = 0 # remaining fiber length before counting the next segment
|
|
131
|
+
# consider if the given channelnumber is not an integer
|
|
132
|
+
chn_res = tn[istart] - int(tn[istart])
|
|
133
|
+
for j in range(istart, iend):
|
|
134
|
+
l_start = l_track[j] + l_res
|
|
135
|
+
|
|
136
|
+
# if tp segment length is large for more than one interval, get the
|
|
137
|
+
# channel loc
|
|
138
|
+
if l_start >= d_interp * (1 - chn_res):
|
|
139
|
+
# floor int, num of channel available
|
|
140
|
+
n_chn_tp = int(l_start / d_interp + chn_res)
|
|
141
|
+
l_new = (np.arange(n_chn_tp) + 1 - chn_res) * d_interp - \
|
|
142
|
+
l_res # channel distance from segment start
|
|
143
|
+
|
|
144
|
+
# interpolate the channel loc
|
|
145
|
+
t_new = np.zeros((len(l_new), dim))
|
|
146
|
+
for d in range(dim):
|
|
147
|
+
t_new[:, d] = np.interp(l_new, [0, l_track[j]],
|
|
148
|
+
[track[j, d], track[j + 1, d]])
|
|
149
|
+
|
|
150
|
+
# remaining length to add to next segment
|
|
151
|
+
l_res = l_start - n_chn_tp * d_interp
|
|
152
|
+
|
|
153
|
+
# write interpolated channel loc
|
|
154
|
+
for ti in t_new:
|
|
155
|
+
chn += 1
|
|
156
|
+
interp_ch.append([*ti, chn])
|
|
157
|
+
|
|
158
|
+
# handle floor int problem when l_start/d_interp is near an
|
|
159
|
+
# interger
|
|
160
|
+
if (d_interp - l_res) / d_interp < 1e-6:
|
|
161
|
+
chn += 1
|
|
162
|
+
interp_ch.append([*track[j + 1, :], int(tn[j + 1])])
|
|
163
|
+
l_res = 0
|
|
164
|
+
chn_res = 0
|
|
165
|
+
# if tp segment length is not enough for one interval, simply add
|
|
166
|
+
# the length to next segment
|
|
167
|
+
elif l_start < d_interp:
|
|
168
|
+
l_res = l_start
|
|
169
|
+
|
|
170
|
+
return np.array(seg_interval), np.array(interp_ch)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def location_interpolation(known_pt, track_pt=None, dx=2, data_type='lonlat',
|
|
174
|
+
verbose=False):
|
|
175
|
+
"""
|
|
176
|
+
Interpolate to obtain the positions of all channels.
|
|
177
|
+
|
|
178
|
+
:param known_pt: np.ndarray. Points with known channel numbers. Each row
|
|
179
|
+
includes 2 or 3 coordinates and a channel number.
|
|
180
|
+
:param track_pt: np.ndarray. Optional fiber spatial track points without
|
|
181
|
+
channel numbers. Each row includes 2 or 3 coordinates. Please ensure
|
|
182
|
+
that the track points are arranged in increasing order of track number.
|
|
183
|
+
If track points is not dense enough, please insert the coordinates of
|
|
184
|
+
known points into track points in order.
|
|
185
|
+
:param dx: Known points far from the track (> dx) will be excluded.
|
|
186
|
+
Recommended setting is channel interval. The unit is m.
|
|
187
|
+
:param data_type: str. Coordinate type. 'lonlat' ('lonlatheight') for
|
|
188
|
+
longitude, latitude in degree (and height in meters), 'xy' ('xyz') for
|
|
189
|
+
x, y (and z) in meters.
|
|
190
|
+
:param verbose: bool. If True, return interpoleted channel location and
|
|
191
|
+
segment interval.
|
|
192
|
+
:return: Interpoleted channel location if verbose is False.
|
|
193
|
+
"""
|
|
194
|
+
known_pt = known_pt[known_pt[:,-1].argsort()]
|
|
195
|
+
dim = known_pt.shape[1] - 1
|
|
196
|
+
if 'lonlat' in data_type:
|
|
197
|
+
zone = np.floor((max(known_pt[:,0]) + min(known_pt[:,0])) / 2 / 6)\
|
|
198
|
+
.astype(int) + 31
|
|
199
|
+
DASProj = Proj(proj='utm', zone=zone, ellps='WGS84',
|
|
200
|
+
preserve_units=False)
|
|
201
|
+
known_pt[:, 0], known_pt[:, 1] = DASProj(known_pt[:, 0], known_pt[:, 1])
|
|
202
|
+
else:
|
|
203
|
+
assert 'xy' in data_type, ('data_type should be \'lonlat\',\''
|
|
204
|
+
'lonlatheight\', \'xy\' or \'xyz\'')
|
|
205
|
+
|
|
206
|
+
if track_pt is None:
|
|
207
|
+
seg_interval, interp_ch = _channel_location(known_pt)
|
|
208
|
+
else:
|
|
209
|
+
K = len(known_pt)
|
|
210
|
+
T = len(track_pt)
|
|
211
|
+
track_pt = np.c_[track_pt, np.zeros(T) - 1]
|
|
212
|
+
if 'lonlat' in data_type:
|
|
213
|
+
track_pt[:, 0], track_pt[:, 1] = DASProj(track_pt[:, 0],
|
|
214
|
+
track_pt[:, 1])
|
|
215
|
+
|
|
216
|
+
# insert the known points into the fiber track data
|
|
217
|
+
matrix = [np.tile(track_pt[:, d], (K, 1)) -
|
|
218
|
+
np.tile(known_pt[:, d], (T, 1)).T for d in range(dim)]
|
|
219
|
+
|
|
220
|
+
dist = np.sqrt(np.sum(np.array(matrix) ** 2, axis=0))
|
|
221
|
+
for k in range(K):
|
|
222
|
+
if min(dist[k]) < dx:
|
|
223
|
+
t_list = np.sort(np.where(dist[k] == min(dist[k]))[0])
|
|
224
|
+
for t in t_list:
|
|
225
|
+
if track_pt[t, -1] == -1:
|
|
226
|
+
track_pt[t, -1] = known_pt[k, -1]
|
|
227
|
+
last_pt = t
|
|
228
|
+
break
|
|
229
|
+
|
|
230
|
+
# interpolation with regular spacing along the fiber track
|
|
231
|
+
try:
|
|
232
|
+
track_pt = track_pt[:last_pt + 1]
|
|
233
|
+
except NameError:
|
|
234
|
+
print('All known points are too far away from the track points. If '
|
|
235
|
+
'they are reliable, they can be merged in sequence as track '
|
|
236
|
+
'points to input')
|
|
237
|
+
return None
|
|
238
|
+
|
|
239
|
+
seg_interval, interp_ch = _channel_location(track_pt)
|
|
240
|
+
|
|
241
|
+
if data_type == 'lonlat':
|
|
242
|
+
interp_ch[:, 0], interp_ch[:, 1] = \
|
|
243
|
+
DASProj(interp_ch[:, 0], interp_ch[:, 1], inverse=True)
|
|
244
|
+
|
|
245
|
+
if verbose:
|
|
246
|
+
return interp_ch, seg_interval
|
|
247
|
+
return interp_ch
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _xcorr(x, y):
|
|
251
|
+
N = len(x)
|
|
252
|
+
meanx = np.mean(x)
|
|
253
|
+
meany = np.mean(y)
|
|
254
|
+
stdx = np.std(np.asarray(x))
|
|
255
|
+
stdy = np.std(np.asarray(y))
|
|
256
|
+
c = np.sum((y - meany) * (x - meanx)) / (N * stdx * stdy)
|
|
257
|
+
return c
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _horizontal_angle_change(geo, gap=10):
|
|
261
|
+
nch = len(geo)
|
|
262
|
+
angle = np.zeros(nch)
|
|
263
|
+
for i in range(1, nch - 1):
|
|
264
|
+
lon, lat = geo[i]
|
|
265
|
+
lon_s, lat_s = geo[max(i - gap, 0)]
|
|
266
|
+
lon_e, lat_e = geo[min(i + gap, nch - 1)]
|
|
267
|
+
azi_s = Geodesic.WGS84.Inverse(lat_s, lon_s, lat, lon)['azi1']
|
|
268
|
+
azi_e = Geodesic.WGS84.Inverse(lat, lon, lat_e, lon_e)['azi1']
|
|
269
|
+
dazi = azi_e - azi_s
|
|
270
|
+
if abs(dazi) > 180:
|
|
271
|
+
dazi = -np.sign(dazi) * (360 - abs(dazi))
|
|
272
|
+
angle[i] = dazi
|
|
273
|
+
|
|
274
|
+
return angle
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _vertical_angle_change(geo, gap=10):
|
|
278
|
+
nch = len(geo)
|
|
279
|
+
angle = np.zeros(nch)
|
|
280
|
+
for i in range(1, nch - 1):
|
|
281
|
+
lon, lat, dep = geo[i]
|
|
282
|
+
lon_s, lat_s, dep_s = geo[max(i - gap, 0)]
|
|
283
|
+
lon_e, lat_e, dep_e = geo[min(i + gap, nch - 1)]
|
|
284
|
+
s12_s = Geodesic.WGS84.Inverse(lat_s, lon_s, lat, lon)['s12']
|
|
285
|
+
theta_s = np.arctan((dep - dep_s) / s12_s) / np.pi * 180
|
|
286
|
+
s12_e = Geodesic.WGS84.Inverse(lat, lon, lat_e, lon_e)['s12']
|
|
287
|
+
theta_e = np.arctan((dep_e - dep) / s12_e) / np.pi * 180
|
|
288
|
+
angle[i] = theta_e - theta_s
|
|
289
|
+
|
|
290
|
+
return angle
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _local_maximum_indexes(data, thresh):
|
|
294
|
+
idx = np.where(data > thresh)[0]
|
|
295
|
+
if len(idx):
|
|
296
|
+
i = list(np.where(np.diff(idx) > 1)[0] + 1)
|
|
297
|
+
if len(idx) - 1 not in i:
|
|
298
|
+
i.append(len(idx) - 1)
|
|
299
|
+
b = 0
|
|
300
|
+
max_idx = []
|
|
301
|
+
for e in i:
|
|
302
|
+
max_idx.append(idx[b] + np.argmax(data[idx[b]:idx[e]]))
|
|
303
|
+
b = e
|
|
304
|
+
return max_idx
|
|
305
|
+
else:
|
|
306
|
+
return []
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def turning_points(data, data_type='coordinate', thresh=5, depth_info=False,
|
|
310
|
+
channel_gap=3):
|
|
311
|
+
"""
|
|
312
|
+
Seek turning points in the DAS channel.
|
|
313
|
+
|
|
314
|
+
:param data: numpy.ndarray. Data used to seek turning points.
|
|
315
|
+
:param data_type: str. If data_type is 'coordinate', data should include
|
|
316
|
+
longitude and latitude (first two columns), and can also include depth
|
|
317
|
+
(last column). If data_type is 'waveform', data should be continuous
|
|
318
|
+
waveform, preferably containing signal with strong coherence
|
|
319
|
+
(earthquake, traffic signal, etc.).
|
|
320
|
+
:param thresh: For coordinate data, when the angle of the optical cables on
|
|
321
|
+
both sides centered on a certain point exceeds thresh, it is considered
|
|
322
|
+
an turning point. For waveform, thresh means the MAD multiple of
|
|
323
|
+
adjacent channel cross-correlation values lower than their median.
|
|
324
|
+
:param depth_info: bool. Optional if data_type is 'coordinate'. Whether
|
|
325
|
+
depth (in meters) is included in the coordinate data and need to be
|
|
326
|
+
used.
|
|
327
|
+
:param channel_gap: int. Optional if data_type is 'coordinate'. The smaller
|
|
328
|
+
the value is, the finer the segmentation will be. It is recommended to
|
|
329
|
+
set it to half the ratio of gauge length and channel interval.
|
|
330
|
+
:return: list. Channel index of turning points.
|
|
331
|
+
"""
|
|
332
|
+
if data_type == 'coordinate':
|
|
333
|
+
angle = _horizontal_angle_change(data[:, :2], gap=channel_gap)
|
|
334
|
+
turning_h = _local_maximum_indexes(abs(angle), thresh)
|
|
335
|
+
|
|
336
|
+
if depth_info:
|
|
337
|
+
angle = _vertical_angle_change(data, gap=channel_gap)
|
|
338
|
+
turning_v = _local_maximum_indexes(abs(angle), thresh)
|
|
339
|
+
return turning_h, turning_v
|
|
340
|
+
|
|
341
|
+
return turning_h
|
|
342
|
+
|
|
343
|
+
elif data_type == 'waveform':
|
|
344
|
+
nch = len(data)
|
|
345
|
+
cc = np.zeros(nch - 1)
|
|
346
|
+
for i in range(nch - 1):
|
|
347
|
+
cc[i] = _xcorr(data[i], data[i + 1])
|
|
348
|
+
median = np.median(cc)
|
|
349
|
+
mad = np.median(abs(cc - median))
|
|
350
|
+
|
|
351
|
+
return np.argwhere(cc < median - thresh * mad)[0]
|
|
352
|
+
|
|
353
|
+
else:
|
|
354
|
+
raise ValueError('Data_type should be \'coordinate\' or \'waveform\'.')
|