pyfortracc 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.
- pyfortracc-1.0.0/LICENSE +1 -0
- pyfortracc-1.0.0/MANIFEST.in +8 -0
- pyfortracc-1.0.0/PKG-INFO +147 -0
- pyfortracc-1.0.0/README.md +113 -0
- pyfortracc-1.0.0/pyfortracc/.DS_Store +0 -0
- pyfortracc-1.0.0/pyfortracc/__init__.py +71 -0
- pyfortracc-1.0.0/pyfortracc/_version.py +1 -0
- pyfortracc-1.0.0/pyfortracc/cluster_linking/__init__.py +1 -0
- pyfortracc-1.0.0/pyfortracc/cluster_linking/board_clusters.py +29 -0
- pyfortracc-1.0.0/pyfortracc/cluster_linking/cluster_linking.py +180 -0
- pyfortracc-1.0.0/pyfortracc/cluster_linking/max_uid.py +25 -0
- pyfortracc-1.0.0/pyfortracc/cluster_linking/merge_trajectory.py +89 -0
- pyfortracc-1.0.0/pyfortracc/cluster_linking/new_frame.py +31 -0
- pyfortracc-1.0.0/pyfortracc/cluster_linking/refact_inside.py +47 -0
- pyfortracc-1.0.0/pyfortracc/concat.py +258 -0
- pyfortracc-1.0.0/pyfortracc/default_parameters.py +164 -0
- pyfortracc-1.0.0/pyfortracc/features_extraction/__init__.py +2 -0
- pyfortracc-1.0.0/pyfortracc/features_extraction/clustering.py +118 -0
- pyfortracc-1.0.0/pyfortracc/features_extraction/features_extraction.py +114 -0
- pyfortracc-1.0.0/pyfortracc/features_extraction/statistics.py +103 -0
- pyfortracc-1.0.0/pyfortracc/forecast/__init__.py +1 -0
- pyfortracc-1.0.0/pyfortracc/forecast/forecast.py +273 -0
- pyfortracc-1.0.0/pyfortracc/plot/__init__.py +2 -0
- pyfortracc-1.0.0/pyfortracc/plot/plot.py +411 -0
- pyfortracc-1.0.0/pyfortracc/plot/plot_animation.py +234 -0
- pyfortracc-1.0.0/pyfortracc/post_processing/__init__.py +2 -0
- pyfortracc-1.0.0/pyfortracc/post_processing/duration.py +152 -0
- pyfortracc-1.0.0/pyfortracc/post_processing/fortracc_converter.py +130 -0
- pyfortracc-1.0.0/pyfortracc/spatial_conversion.py +53 -0
- pyfortracc-1.0.0/pyfortracc/spatial_conversions/__init__.py +1 -0
- pyfortracc-1.0.0/pyfortracc/spatial_conversions/boundaries.py +168 -0
- pyfortracc-1.0.0/pyfortracc/spatial_conversions/clusters.py +128 -0
- pyfortracc-1.0.0/pyfortracc/spatial_conversions/spatial_conversions.py +50 -0
- pyfortracc-1.0.0/pyfortracc/spatial_conversions/trajectories.py +95 -0
- pyfortracc-1.0.0/pyfortracc/spatial_conversions/vectorfield.py +100 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/__init__.py +1 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/contains.py +24 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/count_inside.py +46 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/edge_clusters.py +90 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/expansion.py +30 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/overlay.py +31 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/spatial_class.py +131 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/spatial_operations.py +426 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/trajectory.py +34 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/validation.py +130 -0
- pyfortracc-1.0.0/pyfortracc/spatial_operations/within.py +22 -0
- pyfortracc-1.0.0/pyfortracc/track.py +53 -0
- pyfortracc-1.0.0/pyfortracc/utilities/__init__.py +2 -0
- pyfortracc-1.0.0/pyfortracc/utilities/conversions.py +104 -0
- pyfortracc-1.0.0/pyfortracc/utilities/math_utils.py +322 -0
- pyfortracc-1.0.0/pyfortracc/utilities/transform.py +421 -0
- pyfortracc-1.0.0/pyfortracc/utilities/utils.py +937 -0
- pyfortracc-1.0.0/pyfortracc/vector_methods/__init__.py +0 -0
- pyfortracc-1.0.0/pyfortracc/vector_methods/ellipse_mtd.py +55 -0
- pyfortracc-1.0.0/pyfortracc/vector_methods/incores_mtd.py +47 -0
- pyfortracc-1.0.0/pyfortracc/vector_methods/merge_mtd.py +50 -0
- pyfortracc-1.0.0/pyfortracc/vector_methods/opticalflow_filters.py +437 -0
- pyfortracc-1.0.0/pyfortracc/vector_methods/opticalflow_mtd.py +398 -0
- pyfortracc-1.0.0/pyfortracc/vector_methods/split_mtd.py +48 -0
- pyfortracc-1.0.0/pyfortracc.egg-info/PKG-INFO +147 -0
- pyfortracc-1.0.0/pyfortracc.egg-info/SOURCES.txt +66 -0
- pyfortracc-1.0.0/pyfortracc.egg-info/dependency_links.txt +1 -0
- pyfortracc-1.0.0/pyfortracc.egg-info/requires.txt +16 -0
- pyfortracc-1.0.0/pyfortracc.egg-info/top_level.txt +1 -0
- pyfortracc-1.0.0/pyproject.toml +3 -0
- pyfortracc-1.0.0/requirements.txt +16 -0
- pyfortracc-1.0.0/setup.cfg +4 -0
- pyfortracc-1.0.0/setup.py +41 -0
pyfortracc-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DISCLAIMER: All materials contained in this computer program was developed by COPDT/CGIP/INPE (Brazil). You may download, display, print and reproduce this material for your personal, non-commercial use or use within your organisation. All other rights are reserved.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyfortracc
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A Python package for track and forecasting configurable clusters.
|
|
5
|
+
Home-page: https://github.com/fortracc/pyfortracc
|
|
6
|
+
Author: Helvecio B. L. Neto, Alan J. P. Calheiros
|
|
7
|
+
Author-email: fortracc.project@inpe.br
|
|
8
|
+
License: LICENSE
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Hydrology
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: rasterio
|
|
19
|
+
Requires-Dist: geopandas
|
|
20
|
+
Requires-Dist: opencv-python
|
|
21
|
+
Requires-Dist: opencv_contrib_python
|
|
22
|
+
Requires-Dist: xarray
|
|
23
|
+
Requires-Dist: scipy
|
|
24
|
+
Requires-Dist: scikit-learn
|
|
25
|
+
Requires-Dist: pyarrow
|
|
26
|
+
Requires-Dist: duckdb
|
|
27
|
+
Requires-Dist: netCDF4
|
|
28
|
+
Requires-Dist: cartopy
|
|
29
|
+
Requires-Dist: shapelysmooth
|
|
30
|
+
Requires-Dist: tqdm
|
|
31
|
+
Requires-Dist: ipython
|
|
32
|
+
Requires-Dist: ipykernel
|
|
33
|
+
Requires-Dist: psutil
|
|
34
|
+
|
|
35
|
+
# pyForTraCC - Python Library for Tracking and Forecasting Clusters
|
|
36
|
+
|
|
37
|
+
> **Note**: `pyForTraCC` library is currently in a **release candidate** phase, meaning it is nearly finalized but may receive minor updates before the official stable release.
|
|
38
|
+
|
|
39
|
+
<!-- badges: start -->
|
|
40
|
+
[](https://pyfortracc.readthedocs.io)
|
|
41
|
+
[](https://pypi.python.org/pypi/pyfortracc)
|
|
42
|
+
[](https://pyfortracc.readthedocs.io/)
|
|
43
|
+
[](https://pypi.python.org/pypi/pyfortracc)
|
|
44
|
+
[](https://github.com/fortracc/pyfortracc/graphs/contributors)
|
|
45
|
+
[](https://github.com/fortracc/pyfortracc/blob/main/LICENSE)
|
|
46
|
+
<!-- badges: end -->
|
|
47
|
+
|
|
48
|
+
## Overview
|
|
49
|
+
|
|
50
|
+
`pyForTraCC` is a Python library designed to identify and track clusters in diverse datasets, offering flexible integration based on user-defined needs. Its modular structure incorporates specialized methods for feature identification and tracking, allowing for compatibility with various input formats.
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Algorithm Workflow
|
|
54
|
+
|
|
55
|
+
The algorithm is divided into two main modules: **Track** and **Forecast**.
|
|
56
|
+
|
|
57
|
+
1. **Track**: This module identifies and tracks clusters in a time-sequenced field. It follows four steps:
|
|
58
|
+
- **Feature Extraction**: Identifies relevant features using multi-thresholding on a time-varying field, clusters contiguous pixels above thresholds, and vectorizes clusters as geospatial objects.
|
|
59
|
+
- **Spatial Operations**: Establishes spatial relationships between features and computes vector displacements between feature centroids.
|
|
60
|
+
- **Cluster Linkage**: Links features across time steps by indexing current features with those from the previous time step, generating unique cluster identifiers, tracking trajectories, and recording the cluster lifetime.
|
|
61
|
+
- **Concatenation**: Combines all identified features and trajectories into a single Parquet file, forming a consolidated tracking table with complete tracking data.
|
|
62
|
+
|
|
63
|
+
2. **Forecast** (Upcoming): This module will predict future cluster positions through:
|
|
64
|
+
- **Virtual Image**: A persistence-based forecast of cluster positions by shifting clusters in the current time step to a specified future position based on average vector displacement.
|
|
65
|
+
- **Track Routine**: Applies the tracking routine to the virtual image, projecting cluster identification to the anticipated time step.
|
|
66
|
+
|
|
67
|
+
## Documentation
|
|
68
|
+
|
|
69
|
+
For detailed instructions and usage, refer to the [pyForTraCC Documentation](https://pyfortracc.readthedocs.io/).
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
Download the package from GitHub or clone the repository:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git clone https://github.com/fortracc/pyfortracc/
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
It is recommended to use Python 3.12 and a virtual environment (Anaconda3, Miniconda, Mamba, etc.) to avoid dependency conflicts.
|
|
80
|
+
|
|
81
|
+
### Installing with Conda
|
|
82
|
+
Create environment using conda and install from environment.yml file:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
cd pyfortracc
|
|
86
|
+
conda env create -f environment.yml
|
|
87
|
+
conda activate pyfortracc
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Installing with Pip
|
|
91
|
+
```bash
|
|
92
|
+
pip3 install pyfortracc
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Running pyFortracc
|
|
96
|
+
=====================================================================
|
|
97
|
+
To use `pyForTraCC`, install and import the library, then create a custom data-reading function, read_function, tailored to your data’s format. This function should return a two-dimensional matrix as required by the library. Define a dictionary, name_list, with necessary configuration parameters for tracking, including data paths, thresholds, and time intervals. Finally, run the tracking function.
|
|
98
|
+
|
|
99
|
+
Here is an example script:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import pyfortracc
|
|
103
|
+
import xarray as xr
|
|
104
|
+
|
|
105
|
+
# Custom data reading function
|
|
106
|
+
def read_function(path):
|
|
107
|
+
"""
|
|
108
|
+
This function reads data from the given path and returns a two-dimensional matrix.
|
|
109
|
+
"""
|
|
110
|
+
data = xr.open_dataarray(path).data
|
|
111
|
+
return data
|
|
112
|
+
|
|
113
|
+
# Parameter dictionary for tracking configuration
|
|
114
|
+
name_list = {
|
|
115
|
+
'input_path': 'input/', # Path to input data
|
|
116
|
+
'output_path': 'output/', # Path to output data
|
|
117
|
+
'thresholds': [20, 30, 45], # Intensity thresholds
|
|
118
|
+
'min_cluster_size': [10, 5, 3], # Minimum cluster size (in number of points)
|
|
119
|
+
'operator': '>=', # Comparison operator (>=, <=, or ==)
|
|
120
|
+
'timestamp_pattern': '%Y%m%d_%H%M%S.nc', # Timestamp file naming pattern
|
|
121
|
+
'delta_time': 12 # Time interval between frames, in minutes
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# Execute tracking with parameters and custom reading function
|
|
125
|
+
pyfortracc.track(name_list, read_function)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Example Gallery
|
|
129
|
+
=====================================================================
|
|
130
|
+
To use the library we have a gallery of examples that demonstrate the application of the algorithm in different situations.
|
|
131
|
+
The development of this framework is constantly evolving, and several application examples can be seen in our example gallery.
|
|
132
|
+
|
|
133
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/01_Introducing_Example/01_Introducing-pyFortraCC.ipynb) - 01 - Track Synthetic data (Introducing Example)
|
|
134
|
+
|
|
135
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/02_Track-Radar-Data/02_Track-Radar-Dataset.ipynb) - 02 - Track Radar Data (GoAmazon Example)
|
|
136
|
+
|
|
137
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/03_Track-Infrared-Dataset/03_Track-Infrared-Dataset.ipynb) - 03 - Track GOES16-IR (Real Time Tracking from CPTEC/INPE)
|
|
138
|
+
|
|
139
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/04_Track-Global-Precipitation-EDA/04_Track-Global-Precipitation.ipynb) - 04 - Track GSMAP (Milton Hurricane)
|
|
140
|
+
|
|
141
|
+
Support and Contact
|
|
142
|
+
=====================================================================
|
|
143
|
+
For support and contact e-mail:
|
|
144
|
+
- fortracc.project@inpe.br
|
|
145
|
+
- helvecio.neto@inpe.br
|
|
146
|
+
- alan.calheiros@inpe.br
|
|
147
|
+
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# pyForTraCC - Python Library for Tracking and Forecasting Clusters
|
|
2
|
+
|
|
3
|
+
> **Note**: `pyForTraCC` library is currently in a **release candidate** phase, meaning it is nearly finalized but may receive minor updates before the official stable release.
|
|
4
|
+
|
|
5
|
+
<!-- badges: start -->
|
|
6
|
+
[](https://pyfortracc.readthedocs.io)
|
|
7
|
+
[](https://pypi.python.org/pypi/pyfortracc)
|
|
8
|
+
[](https://pyfortracc.readthedocs.io/)
|
|
9
|
+
[](https://pypi.python.org/pypi/pyfortracc)
|
|
10
|
+
[](https://github.com/fortracc/pyfortracc/graphs/contributors)
|
|
11
|
+
[](https://github.com/fortracc/pyfortracc/blob/main/LICENSE)
|
|
12
|
+
<!-- badges: end -->
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
`pyForTraCC` is a Python library designed to identify and track clusters in diverse datasets, offering flexible integration based on user-defined needs. Its modular structure incorporates specialized methods for feature identification and tracking, allowing for compatibility with various input formats.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Algorithm Workflow
|
|
20
|
+
|
|
21
|
+
The algorithm is divided into two main modules: **Track** and **Forecast**.
|
|
22
|
+
|
|
23
|
+
1. **Track**: This module identifies and tracks clusters in a time-sequenced field. It follows four steps:
|
|
24
|
+
- **Feature Extraction**: Identifies relevant features using multi-thresholding on a time-varying field, clusters contiguous pixels above thresholds, and vectorizes clusters as geospatial objects.
|
|
25
|
+
- **Spatial Operations**: Establishes spatial relationships between features and computes vector displacements between feature centroids.
|
|
26
|
+
- **Cluster Linkage**: Links features across time steps by indexing current features with those from the previous time step, generating unique cluster identifiers, tracking trajectories, and recording the cluster lifetime.
|
|
27
|
+
- **Concatenation**: Combines all identified features and trajectories into a single Parquet file, forming a consolidated tracking table with complete tracking data.
|
|
28
|
+
|
|
29
|
+
2. **Forecast** (Upcoming): This module will predict future cluster positions through:
|
|
30
|
+
- **Virtual Image**: A persistence-based forecast of cluster positions by shifting clusters in the current time step to a specified future position based on average vector displacement.
|
|
31
|
+
- **Track Routine**: Applies the tracking routine to the virtual image, projecting cluster identification to the anticipated time step.
|
|
32
|
+
|
|
33
|
+
## Documentation
|
|
34
|
+
|
|
35
|
+
For detailed instructions and usage, refer to the [pyForTraCC Documentation](https://pyfortracc.readthedocs.io/).
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
Download the package from GitHub or clone the repository:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/fortracc/pyfortracc/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It is recommended to use Python 3.12 and a virtual environment (Anaconda3, Miniconda, Mamba, etc.) to avoid dependency conflicts.
|
|
46
|
+
|
|
47
|
+
### Installing with Conda
|
|
48
|
+
Create environment using conda and install from environment.yml file:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cd pyfortracc
|
|
52
|
+
conda env create -f environment.yml
|
|
53
|
+
conda activate pyfortracc
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Installing with Pip
|
|
57
|
+
```bash
|
|
58
|
+
pip3 install pyfortracc
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Running pyFortracc
|
|
62
|
+
=====================================================================
|
|
63
|
+
To use `pyForTraCC`, install and import the library, then create a custom data-reading function, read_function, tailored to your data’s format. This function should return a two-dimensional matrix as required by the library. Define a dictionary, name_list, with necessary configuration parameters for tracking, including data paths, thresholds, and time intervals. Finally, run the tracking function.
|
|
64
|
+
|
|
65
|
+
Here is an example script:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import pyfortracc
|
|
69
|
+
import xarray as xr
|
|
70
|
+
|
|
71
|
+
# Custom data reading function
|
|
72
|
+
def read_function(path):
|
|
73
|
+
"""
|
|
74
|
+
This function reads data from the given path and returns a two-dimensional matrix.
|
|
75
|
+
"""
|
|
76
|
+
data = xr.open_dataarray(path).data
|
|
77
|
+
return data
|
|
78
|
+
|
|
79
|
+
# Parameter dictionary for tracking configuration
|
|
80
|
+
name_list = {
|
|
81
|
+
'input_path': 'input/', # Path to input data
|
|
82
|
+
'output_path': 'output/', # Path to output data
|
|
83
|
+
'thresholds': [20, 30, 45], # Intensity thresholds
|
|
84
|
+
'min_cluster_size': [10, 5, 3], # Minimum cluster size (in number of points)
|
|
85
|
+
'operator': '>=', # Comparison operator (>=, <=, or ==)
|
|
86
|
+
'timestamp_pattern': '%Y%m%d_%H%M%S.nc', # Timestamp file naming pattern
|
|
87
|
+
'delta_time': 12 # Time interval between frames, in minutes
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Execute tracking with parameters and custom reading function
|
|
91
|
+
pyfortracc.track(name_list, read_function)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Example Gallery
|
|
95
|
+
=====================================================================
|
|
96
|
+
To use the library we have a gallery of examples that demonstrate the application of the algorithm in different situations.
|
|
97
|
+
The development of this framework is constantly evolving, and several application examples can be seen in our example gallery.
|
|
98
|
+
|
|
99
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/01_Introducing_Example/01_Introducing-pyFortraCC.ipynb) - 01 - Track Synthetic data (Introducing Example)
|
|
100
|
+
|
|
101
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/02_Track-Radar-Data/02_Track-Radar-Dataset.ipynb) - 02 - Track Radar Data (GoAmazon Example)
|
|
102
|
+
|
|
103
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/03_Track-Infrared-Dataset/03_Track-Infrared-Dataset.ipynb) - 03 - Track GOES16-IR (Real Time Tracking from CPTEC/INPE)
|
|
104
|
+
|
|
105
|
+
[](https://colab.research.google.com/github/fortracc/pyfortracc/blob/main/examples/04_Track-Global-Precipitation-EDA/04_Track-Global-Precipitation.ipynb) - 04 - Track GSMAP (Milton Hurricane)
|
|
106
|
+
|
|
107
|
+
Support and Contact
|
|
108
|
+
=====================================================================
|
|
109
|
+
For support and contact e-mail:
|
|
110
|
+
- fortracc.project@inpe.br
|
|
111
|
+
- helvecio.neto@inpe.br
|
|
112
|
+
- alan.calheiros@inpe.br
|
|
113
|
+
|
|
Binary file
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyfortracc
|
|
3
|
+
=====
|
|
4
|
+
|
|
5
|
+
Provides
|
|
6
|
+
1. Tracking Non-Rigid Clusters in 2D matrix
|
|
7
|
+
2. Forecasting the movement of the Clusters by extrapolation
|
|
8
|
+
3. Plot and analysis of the results of the tracking and forecasting
|
|
9
|
+
4. Visualizing the results of the tracking, validation and forecasting
|
|
10
|
+
|
|
11
|
+
How to use the package
|
|
12
|
+
----------------------------
|
|
13
|
+
Documentation is available in two forms: docstrings provided
|
|
14
|
+
with the code, and a reference guide, available from
|
|
15
|
+
`the project homepage <https://pyfortracc.readthedocs.io/>`.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Available modules
|
|
19
|
+
---------------------
|
|
20
|
+
track
|
|
21
|
+
Tracking Non-Rigid Clusters in 2D matrix
|
|
22
|
+
forecast
|
|
23
|
+
Forecasting the movement of the Clusters by extrapolation
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Available subpackages
|
|
27
|
+
-----------------
|
|
28
|
+
feature_extraction
|
|
29
|
+
Extracting features from the input data
|
|
30
|
+
spatial_operations
|
|
31
|
+
Spatial operations on the features
|
|
32
|
+
cluster_linking
|
|
33
|
+
Linking the clusters
|
|
34
|
+
spatial_conversions
|
|
35
|
+
Converting the results of the tracking or forecasting to spatial data
|
|
36
|
+
plot
|
|
37
|
+
Visualizing the results of the tracking, validation and forecasting
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
About the package
|
|
41
|
+
-----------------------------
|
|
42
|
+
pyForTraCC is a Python package designed to identify, track, forecast and analyze clusters moving in a time-varying field.
|
|
43
|
+
It offers a modular framework that incorporates different algorithms for feature identification, tracking, and analyses.
|
|
44
|
+
One of the key advantages of pyForTraCC is its versatility, as it does not depend on specific input variables or a particular grid structure.
|
|
45
|
+
In its current implementation, pyForTraCC identifies individual cluster features in a 2D field by applying a specified threshold value.
|
|
46
|
+
|
|
47
|
+
By utilizing a time-varying 2D input images and a specified threshold value, pyForTraCC can determine the associated volume for these features. The
|
|
48
|
+
software then establishes consistent trajectories that represent the complete lifecycle of a single cell of feature through the tracking step.
|
|
49
|
+
Furthermore, pyForTraCC provides analysis and visualization methods that facilitate the utilization and display of the tracking results.
|
|
50
|
+
|
|
51
|
+
This algorithm was initially developed and used in the publication "Impact of Multi-Thresholds and Vector Correction for Tracking Precipitating
|
|
52
|
+
Systems over the Amazon Basin" (https://doi.org/10.3390/rs14215408). The methods presented in the research paper have enabled the implementation of robust techniques for extracting the motion vector
|
|
53
|
+
field and trajectory of individual clusters of precipitating cells. These techniques have been applied to the Amazon Basin, where the tracking of
|
|
54
|
+
precipitating systems is essential for understanding the hydrological cycle and its impacts on the environment and used in this algorithm
|
|
55
|
+
|
|
56
|
+
For further information on pyForTraCC, its modules, and the continuous development process, please refer to the official documentation and stay tuned for updates
|
|
57
|
+
from the community.
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
from ._version import __version__
|
|
62
|
+
from .default_parameters import default_parameters
|
|
63
|
+
from pyfortracc.track import track
|
|
64
|
+
from pyfortracc.forecast import forecast
|
|
65
|
+
from pyfortracc.features_extraction import features_extraction
|
|
66
|
+
from pyfortracc.spatial_operations import spatial_operations
|
|
67
|
+
from pyfortracc.cluster_linking import cluster_linking
|
|
68
|
+
from .concat import concat
|
|
69
|
+
from pyfortracc.plot.plot import plot
|
|
70
|
+
from pyfortracc.plot.plot_animation import plot_animation
|
|
71
|
+
from pyfortracc.spatial_conversions import spatial_conversions
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .cluster_linking import *
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
3
|
+
def board_clusters(cur_frame):
|
|
4
|
+
"""
|
|
5
|
+
Copy values from board_idx to board_idx. The board_idx is the index of
|
|
6
|
+
the clusters that are touching the board.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
cur_frame : pandas dataframe
|
|
11
|
+
Current dataframe.
|
|
12
|
+
|
|
13
|
+
Returns
|
|
14
|
+
-------
|
|
15
|
+
cur_frame : pandas dataframe
|
|
16
|
+
Updated dataframe.
|
|
17
|
+
"""
|
|
18
|
+
board_idx = cur_frame[(cur_frame['board'] == True)]
|
|
19
|
+
if board_idx.empty:
|
|
20
|
+
return cur_frame
|
|
21
|
+
current_index = cur_frame.loc[board_idx.index]
|
|
22
|
+
touching_idx = pd.Index(current_index['board_idx'].values.astype(int))
|
|
23
|
+
board_uids = cur_frame.loc[touching_idx]['uid'].values
|
|
24
|
+
board_iuids = cur_frame.loc[touching_idx]['iuid'].values
|
|
25
|
+
board_status = cur_frame.loc[touching_idx]['status'].values
|
|
26
|
+
cur_frame.loc[board_idx.index,'uid'] = board_uids
|
|
27
|
+
cur_frame.loc[board_idx.index,'iuid'] = board_iuids
|
|
28
|
+
cur_frame.loc[board_idx.index,'status'] = board_status
|
|
29
|
+
return cur_frame
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import pathlib
|
|
3
|
+
from pyfortracc.default_parameters import default_parameters
|
|
4
|
+
from pyfortracc.utilities.utils import (get_feature_files, create_dirs,
|
|
5
|
+
get_loading_bar, get_featstamp,
|
|
6
|
+
set_schema, set_outputdf,
|
|
7
|
+
read_parquet, write_parquet,
|
|
8
|
+
check_operational_system)
|
|
9
|
+
from .new_frame import new_frame
|
|
10
|
+
from .max_uid import update_max_uid
|
|
11
|
+
from .board_clusters import board_clusters
|
|
12
|
+
from .refact_inside import refact_inside
|
|
13
|
+
from .merge_trajectory import merge_trajectory
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def cluster_linking(name_lst):
|
|
17
|
+
"""
|
|
18
|
+
The function links clusters over time, ensuring that clusters in different frames (representing different time points)
|
|
19
|
+
are identified and associated with each other based on spatial and temporal proximity.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
name_lst : dict
|
|
24
|
+
Dictionary with the parameters to be used.
|
|
25
|
+
"""
|
|
26
|
+
print('Cluster linking:')
|
|
27
|
+
# Set default parameters
|
|
28
|
+
name_lst = default_parameters(name_lst)
|
|
29
|
+
# Check operational system
|
|
30
|
+
name_lst, _ = check_operational_system(name_lst, False)
|
|
31
|
+
# Get feature files to be processed
|
|
32
|
+
feat_path = name_lst['output_path'] + 'track/processing/spatial/'
|
|
33
|
+
output_path = name_lst['output_path'] + 'track/processing/linked/'
|
|
34
|
+
name_lst['output_spatial'] = output_path
|
|
35
|
+
feat_files = get_feature_files(feat_path)
|
|
36
|
+
create_dirs(output_path)
|
|
37
|
+
loading_bar = get_loading_bar(feat_files)
|
|
38
|
+
# Get number of prev_files to skip based on the number of prev_time
|
|
39
|
+
prev_skip = name_lst['num_prev_skip']
|
|
40
|
+
# Set delta_time
|
|
41
|
+
dt_time = pd.Timedelta(minutes=name_lst['delta_time'])
|
|
42
|
+
max_dt_time = pd.Timedelta(minutes=(name_lst['delta_time'] +
|
|
43
|
+
name_lst['delta_tolerance']))
|
|
44
|
+
max_dt_time = max_dt_time * (prev_skip + 1)
|
|
45
|
+
# Set initial uid if not set in the name_lst
|
|
46
|
+
if 'initial_uid' not in name_lst.keys():
|
|
47
|
+
name_lst['initial_uid'] = 1
|
|
48
|
+
# Uid iterator is used to create new uids
|
|
49
|
+
uid_iter = name_lst['initial_uid']
|
|
50
|
+
# Set set_schema
|
|
51
|
+
schema = set_schema('linked', name_lst)
|
|
52
|
+
# Create empty previous frame
|
|
53
|
+
prv_frame = pd.DataFrame()
|
|
54
|
+
prv_stamp = get_featstamp(feat_files[0]) - dt_time
|
|
55
|
+
# Set idx counter is used to create cindex
|
|
56
|
+
cdx = 0
|
|
57
|
+
for feat_time, feat_file in enumerate(feat_files):
|
|
58
|
+
prv_frame, prv_stamp, uid_iter, cdx = linking((feat_time, feat_file,
|
|
59
|
+
prv_frame, prv_stamp,
|
|
60
|
+
name_lst, uid_iter,
|
|
61
|
+
max_dt_time, schema, cdx))
|
|
62
|
+
loading_bar.update(1)
|
|
63
|
+
loading_bar.close()
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def linking(args):
|
|
68
|
+
"""
|
|
69
|
+
Links clusters between the current and previous frames, updates their unique identifiers (UIDs),
|
|
70
|
+
handles new frames, and saves the processed data.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
args : tuple
|
|
75
|
+
A tuple containing the following elements:
|
|
76
|
+
- time_ (int): The current time step index.
|
|
77
|
+
- cur_file (str): The path to the current frame's data file.
|
|
78
|
+
- prv_frame (pandas.DataFrame): The DataFrame of the previous frame.
|
|
79
|
+
- prv_stamp (pandas.Timestamp): The timestamp of the previous frame.
|
|
80
|
+
- nm_lst (dict): A dictionary with necessary parameters (e.g., output paths, delta times, etc.).
|
|
81
|
+
- uid_iter (int): The current UID iterator used to assign new UIDs.
|
|
82
|
+
- max_dt (pandas.Timedelta): The maximum allowed time difference between frames.
|
|
83
|
+
- schm (pandas.DataFrame): The schema for the output DataFrame.
|
|
84
|
+
- icdx (int): The current index counter, which increments with each frame processed.
|
|
85
|
+
|
|
86
|
+
Returns
|
|
87
|
+
-------
|
|
88
|
+
tuple
|
|
89
|
+
A tuple containing the following elements:
|
|
90
|
+
- cur_frame (pandas.DataFrame): The processed DataFrame of the current frame.
|
|
91
|
+
- cur_stamp (pandas.Timestamp): The timestamp of the current frame.
|
|
92
|
+
- uid_iter (int): The updated UID iterator.
|
|
93
|
+
- icdx (int): The updated index counter.
|
|
94
|
+
"""
|
|
95
|
+
time_, cur_file, prv_frame, prv_stamp, nm_lst, uid_iter, max_dt, schm, icdx = args
|
|
96
|
+
# Read current file print('Empty frame:', cur_file)
|
|
97
|
+
cur_frame = read_parquet(cur_file, ['status','threshold_level',
|
|
98
|
+
'past_idx','inside_idx',
|
|
99
|
+
'board','board_idx',
|
|
100
|
+
'trajectory'])
|
|
101
|
+
# Set output file
|
|
102
|
+
output_file = nm_lst['output_spatial'] + pathlib.Path(cur_file).name
|
|
103
|
+
icdx += 1 # Increment cindex
|
|
104
|
+
# Check if current frame is empty
|
|
105
|
+
if cur_frame.empty:
|
|
106
|
+
cur_frame['cindex'] = []
|
|
107
|
+
cur_frame['uid'] = []
|
|
108
|
+
if len(nm_lst['thresholds']) > 1:
|
|
109
|
+
cur_frame['iuid'] = []
|
|
110
|
+
cur_frame = cur_frame.astype({'cindex': 'int64', 'uid': 'int64'})
|
|
111
|
+
# Calculate lifetime
|
|
112
|
+
cur_frame['lifetime'] = []
|
|
113
|
+
cur_frame['lifetime'] = cur_frame['lifetime'].fillna(0)
|
|
114
|
+
write_parquet(cur_frame, output_file)
|
|
115
|
+
return cur_frame, prv_stamp, uid_iter, icdx
|
|
116
|
+
# Get schema and cols
|
|
117
|
+
link_df = set_outputdf(schm)
|
|
118
|
+
linked_cols = list(link_df.columns)
|
|
119
|
+
# Create a column cal cindex based on the range of the current frame and assign
|
|
120
|
+
# the value to the current frameprv_frame
|
|
121
|
+
cdx_range = range(icdx, icdx + len(cur_frame))
|
|
122
|
+
cur_frame['cindex'] = cdx_range
|
|
123
|
+
cur_frame = pd.concat([cur_frame, link_df])
|
|
124
|
+
# Get current stamp
|
|
125
|
+
cur_stamp = get_featstamp(cur_file)
|
|
126
|
+
# Calculate delta time
|
|
127
|
+
dt_time = cur_stamp - prv_stamp
|
|
128
|
+
# Conditions to enter in this conditional below:
|
|
129
|
+
# - time_ is 0
|
|
130
|
+
# - prv_frame is empty
|
|
131
|
+
# - dt_time is greater than max_dt
|
|
132
|
+
if time_ == 0 or prv_frame.empty or dt_time > max_dt:
|
|
133
|
+
# Classify clusters as new clusters and check board clusprv_frameters
|
|
134
|
+
cur_frame = new_frame(cur_frame, uid_iter)
|
|
135
|
+
cur_frame = board_clusters(cur_frame)
|
|
136
|
+
cur_frame = refact_inside(cur_frame)
|
|
137
|
+
uid_iter = update_max_uid(cur_frame['uid'].max(), uid_iter)
|
|
138
|
+
# Calculate lifetime
|
|
139
|
+
cur_frame['lifetime'] = 0
|
|
140
|
+
write_parquet(cur_frame[linked_cols], output_file)
|
|
141
|
+
return cur_frame, cur_stamp, uid_iter, cdx_range[-1]
|
|
142
|
+
# Get previous indx based for conditions:
|
|
143
|
+
# - prev_idx is not null
|
|
144
|
+
# - status is not NEW
|
|
145
|
+
# The association values is based on prev_idx
|
|
146
|
+
cur_prev_idx = cur_frame.loc[(~cur_frame['past_idx'].isnull())]
|
|
147
|
+
cur_prev_idx = cur_prev_idx[~cur_prev_idx['status'].str.contains('NEW')]
|
|
148
|
+
cur_idx = cur_prev_idx.index
|
|
149
|
+
prv_idx = pd.Index(cur_prev_idx['past_idx'].values.astype(int))
|
|
150
|
+
previous_uids = prv_frame.loc[prv_idx]['uid'].values
|
|
151
|
+
previous_iuids = prv_frame.loc[prv_idx]['iuid'].values
|
|
152
|
+
cur_frame.loc[cur_idx, 'uid'] = previous_uids
|
|
153
|
+
cur_frame.loc[cur_idx, 'iuid'] = previous_iuids
|
|
154
|
+
# Merge trajectories
|
|
155
|
+
cur_frame = merge_trajectory(cur_frame, cur_idx, prv_frame, prv_idx)
|
|
156
|
+
# New frames for base threshold
|
|
157
|
+
cur_frame = new_frame(cur_frame, uid_iter)
|
|
158
|
+
# Check board clusters
|
|
159
|
+
cur_frame = board_clusters(cur_frame)
|
|
160
|
+
# Refact inside clusters
|
|
161
|
+
cur_frame = refact_inside(cur_frame)
|
|
162
|
+
# Update max uid
|
|
163
|
+
uid_iter = update_max_uid(cur_frame['uid'].max(), uid_iter)
|
|
164
|
+
# Calculate lifetime, get previous lifetime and add to current lifetime
|
|
165
|
+
prev_lifetime = prv_frame.loc[prv_idx]['lifetime'].values
|
|
166
|
+
# Calc time interval
|
|
167
|
+
time_int = (cur_stamp - prv_stamp).total_seconds() / 60
|
|
168
|
+
cur_frame.loc[cur_idx, 'lifetime'] = prev_lifetime + time_int
|
|
169
|
+
# Split lifetime: Preserve lifetime of split clusters
|
|
170
|
+
if nm_lst['preserv_split']:
|
|
171
|
+
split_frs = cur_frame.loc[cur_frame['split_pr_idx'].notnull()]
|
|
172
|
+
if len(split_frs) > 0:
|
|
173
|
+
split_idx = split_frs['split_pr_idx'].values.astype(int)
|
|
174
|
+
lifetimes = prv_frame.loc[split_idx]['lifetime']
|
|
175
|
+
cur_frame.loc[split_frs.index, 'lifetime'] = lifetimes.values
|
|
176
|
+
# Fill NaN values to 0
|
|
177
|
+
cur_frame['lifetime'] = cur_frame['lifetime'].fillna(0)
|
|
178
|
+
# Write linked file
|
|
179
|
+
write_parquet(cur_frame[linked_cols], output_file)
|
|
180
|
+
return cur_frame, cur_stamp, uid_iter, cdx_range[-1]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
def update_max_uid(current_max_uid, global_uid):
|
|
2
|
+
"""
|
|
3
|
+
Update the global unique identifier (UID) based on the current maximum UID.
|
|
4
|
+
|
|
5
|
+
This function compares the 'current_max_uid' with 'global_uid' and updates 'global_uid' accordingly.
|
|
6
|
+
If 'current_max_uid' is greater than or equal to 'global_uid', it increments 'global_uid' by 1.
|
|
7
|
+
Otherwise, it leaves 'global_uid' unchanged.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
current_max_uid : int
|
|
12
|
+
The current maximum UID observed.
|
|
13
|
+
global_uid : int
|
|
14
|
+
The global UID that is used and needs to be updated if necessary.
|
|
15
|
+
|
|
16
|
+
Returns
|
|
17
|
+
-------
|
|
18
|
+
int
|
|
19
|
+
The updated global UID.
|
|
20
|
+
"""
|
|
21
|
+
if current_max_uid >= global_uid:
|
|
22
|
+
global_uid = current_max_uid + 1
|
|
23
|
+
else:
|
|
24
|
+
global_uid = global_uid
|
|
25
|
+
return global_uid
|