arcat 0.1.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.
- arcat-0.1.0/PKG-INFO +173 -0
- arcat-0.1.0/README.md +154 -0
- arcat-0.1.0/arcat/__init__.py +14 -0
- arcat-0.1.0/arcat/core.py +190 -0
- arcat-0.1.0/arcat/core_v1.py +131 -0
- arcat-0.1.0/arcat/utils.py +86 -0
- arcat-0.1.0/arcat/version.py +8 -0
- arcat-0.1.0/arcat.egg-info/PKG-INFO +173 -0
- arcat-0.1.0/arcat.egg-info/SOURCES.txt +14 -0
- arcat-0.1.0/arcat.egg-info/dependency_links.txt +1 -0
- arcat-0.1.0/arcat.egg-info/requires.txt +5 -0
- arcat-0.1.0/arcat.egg-info/top_level.txt +1 -0
- arcat-0.1.0/pyproject.toml +28 -0
- arcat-0.1.0/setup.cfg +28 -0
- arcat-0.1.0/tests/test_core.py +28 -0
arcat-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: arcat
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Atmospheric River Categorization Toolkit
|
|
5
|
+
Author: Kwesi Twentwewa Quagraine
|
|
6
|
+
Author-email: Kwesi Twentwewa Quagraine <kwsquagraine@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: atmospheric rivers,ivt,weather,extremes,python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: xarray
|
|
16
|
+
Requires-Dist: dask
|
|
17
|
+
Requires-Dist: numba
|
|
18
|
+
Requires-Dist: tqdm
|
|
19
|
+
|
|
20
|
+
# ARCat: Atmospheric River Categorization Toolkit
|
|
21
|
+
|
|
22
|
+
**ARCat** is a Python package for **categorizing Atmospheric River (AR) events** based on Integrated Vapor Transport (IVT) data. It provides:
|
|
23
|
+
|
|
24
|
+
- **Event-based AR categorization**: Collapses each AR event to its peak intensity.
|
|
25
|
+
- **Evolution-based AR categorization**: Preserves the intensity evolution within AR events.
|
|
26
|
+
|
|
27
|
+
Additionally, ARCat computes:
|
|
28
|
+
|
|
29
|
+
- **Cumulative IVT** per AR event.
|
|
30
|
+
- **IVT-only values** for each AR event.
|
|
31
|
+
- **Duration-only values** (number of timesteps per event).
|
|
32
|
+
|
|
33
|
+
It is fully compatible with **NumPy arrays**, **xarray**, and **Dask**, allowing analysis of large datasets efficiently.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- Event-based and evolution-based AR categorization.
|
|
40
|
+
- Automatic handling of duration rules:
|
|
41
|
+
- Events < 1 day → downgrade category
|
|
42
|
+
- Events 1–2 days → unchanged
|
|
43
|
+
- Events ≥ 2 days → upgrade category
|
|
44
|
+
- Maximum category enforcement.
|
|
45
|
+
- Option to extract IVT-only and duration-only arrays.
|
|
46
|
+
- Easy integration with **xarray/Dask** for large datasets.
|
|
47
|
+
- Fully documented and tested, with CI support.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
Clone the repository and install locally:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/yourusername/arcat.git
|
|
57
|
+
cd arcat
|
|
58
|
+
pip install -e .
|
|
59
|
+
````
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
### Import the package
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import numpy as np
|
|
66
|
+
from arcat.core import AR_categorization_scheme, AR_categorization_evolution_scheme
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Prepare your IVT array
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# Example: random IVT values for demonstration
|
|
73
|
+
ivt = np.random.rand(20) * 1500 # IVT in kg/m/s
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Event-based AR categorization
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# Run the event-based AR scheme
|
|
80
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_scheme(
|
|
81
|
+
ivt,
|
|
82
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
83
|
+
bin_width=250.0, # IVT bin size
|
|
84
|
+
max_category=6 # Maximum AR category
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
print("Categorized AR events:", final_cat)
|
|
88
|
+
print("Cumulative IVT:", cum_ivt)
|
|
89
|
+
print("IVT-only values:", ivt_event)
|
|
90
|
+
print("Duration per timestep:", duration_event)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Evolution-based AR categorization
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
# Run the evolution-based AR scheme
|
|
97
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_evolution_scheme(
|
|
98
|
+
ivt,
|
|
99
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
100
|
+
bin_width=250.0, # IVT bin size
|
|
101
|
+
max_category=6 # Maximum AR category
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
print("Evolution categories:", final_cat)
|
|
105
|
+
print("Cumulative IVT:", cum_ivt)
|
|
106
|
+
print("IVT-only values:", ivt_event)
|
|
107
|
+
print("Duration per timestep:", duration_event)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Parameters
|
|
113
|
+
|
|
114
|
+
| Parameter | Description |
|
|
115
|
+
| ----------------------- | ------------------------------------------------------- |
|
|
116
|
+
| `ivt_array` | 1D NumPy array of IVT values (kg/m/s) |
|
|
117
|
+
| `time_resolution_hours` | Temporal resolution of your data in hours (default: 6) |
|
|
118
|
+
| `bin_width` | Width of each IVT bin for categorization (default: 250) |
|
|
119
|
+
| `max_category` | Maximum AR category (default: 6) |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Returns
|
|
124
|
+
|
|
125
|
+
1. `final_categories`: Array of AR categories (1–6) after duration adjustments.
|
|
126
|
+
2. `cumulative_ivt`: Cumulative IVT during AR events.
|
|
127
|
+
3. `ivt_event`: Original IVT values during AR events (0 elsewhere).
|
|
128
|
+
4. `duration_event`: Number of timesteps per AR event (0 elsewhere).
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Usage Notes
|
|
133
|
+
|
|
134
|
+
* Event-based scheme collapses each AR event to its maximum intensity (`max_bounded_replace`).
|
|
135
|
+
* Evolution-based scheme preserves temporal evolution of IVT within AR events.
|
|
136
|
+
* Duration rules are applied **per continuous AR segment**.
|
|
137
|
+
* Works with any **NumPy array**, and can be integrated with **xarray or Dask arrays** for large datasets.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
## Adopting for xarray data
|
|
141
|
+
```python
|
|
142
|
+
final_cat, cum_ivt, ivt_event, duration_event = xr.apply_ufunc(AR_categorization_scheme,
|
|
143
|
+
Ivt_ds['IVT'].as_numpy(),
|
|
144
|
+
input_core_dims = [['time']],
|
|
145
|
+
output_core_dims = [['time'],['time'],['time'],['time']],
|
|
146
|
+
vectorize=True, # Auto-vectorize over lat/lon
|
|
147
|
+
dask='parallelized', # Enable parallelization using Dask
|
|
148
|
+
output_dtypes=[np.int8,np.float32,np.float32, np.int8])
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Contributing
|
|
153
|
+
|
|
154
|
+
We welcome contributions! Please follow these steps:
|
|
155
|
+
|
|
156
|
+
1. Fork the repository
|
|
157
|
+
2. Create a new branch: `git checkout -b feature-name`
|
|
158
|
+
3. Make your changes
|
|
159
|
+
4. Run tests
|
|
160
|
+
5. Submit a pull request
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
This project is licensed under the [Creative Commons License](https://web.archive.org/web/20230202010104/https://creativecommons.org/licenses/by/4.0/).
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## References
|
|
171
|
+
|
|
172
|
+
* Ralph, F. M., Rutz, J. J., Cordeira, J. M., Dettinger, M., Anderson, M., Reynolds, D., ... & Smallcomb, C. (2019). A scale to characterize the strength and impacts of atmospheric rivers. Bulletin of the American Meteorological Society, 100(2), 269-289.
|
|
173
|
+
* Visit the [Atmospheric River Tracking Model Intercomparison Project (ARTMIP)](https://ncar.github.io/ARTMIP/intro.html) to follow Atmospheric River community research and publications.
|
arcat-0.1.0/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# ARCat: Atmospheric River Categorization Toolkit
|
|
2
|
+
|
|
3
|
+
**ARCat** is a Python package for **categorizing Atmospheric River (AR) events** based on Integrated Vapor Transport (IVT) data. It provides:
|
|
4
|
+
|
|
5
|
+
- **Event-based AR categorization**: Collapses each AR event to its peak intensity.
|
|
6
|
+
- **Evolution-based AR categorization**: Preserves the intensity evolution within AR events.
|
|
7
|
+
|
|
8
|
+
Additionally, ARCat computes:
|
|
9
|
+
|
|
10
|
+
- **Cumulative IVT** per AR event.
|
|
11
|
+
- **IVT-only values** for each AR event.
|
|
12
|
+
- **Duration-only values** (number of timesteps per event).
|
|
13
|
+
|
|
14
|
+
It is fully compatible with **NumPy arrays**, **xarray**, and **Dask**, allowing analysis of large datasets efficiently.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- Event-based and evolution-based AR categorization.
|
|
21
|
+
- Automatic handling of duration rules:
|
|
22
|
+
- Events < 1 day → downgrade category
|
|
23
|
+
- Events 1–2 days → unchanged
|
|
24
|
+
- Events ≥ 2 days → upgrade category
|
|
25
|
+
- Maximum category enforcement.
|
|
26
|
+
- Option to extract IVT-only and duration-only arrays.
|
|
27
|
+
- Easy integration with **xarray/Dask** for large datasets.
|
|
28
|
+
- Fully documented and tested, with CI support.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
Clone the repository and install locally:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://github.com/yourusername/arcat.git
|
|
38
|
+
cd arcat
|
|
39
|
+
pip install -e .
|
|
40
|
+
````
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
### Import the package
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import numpy as np
|
|
47
|
+
from arcat.core import AR_categorization_scheme, AR_categorization_evolution_scheme
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Prepare your IVT array
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
# Example: random IVT values for demonstration
|
|
54
|
+
ivt = np.random.rand(20) * 1500 # IVT in kg/m/s
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Event-based AR categorization
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
# Run the event-based AR scheme
|
|
61
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_scheme(
|
|
62
|
+
ivt,
|
|
63
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
64
|
+
bin_width=250.0, # IVT bin size
|
|
65
|
+
max_category=6 # Maximum AR category
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
print("Categorized AR events:", final_cat)
|
|
69
|
+
print("Cumulative IVT:", cum_ivt)
|
|
70
|
+
print("IVT-only values:", ivt_event)
|
|
71
|
+
print("Duration per timestep:", duration_event)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Evolution-based AR categorization
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
# Run the evolution-based AR scheme
|
|
78
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_evolution_scheme(
|
|
79
|
+
ivt,
|
|
80
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
81
|
+
bin_width=250.0, # IVT bin size
|
|
82
|
+
max_category=6 # Maximum AR category
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
print("Evolution categories:", final_cat)
|
|
86
|
+
print("Cumulative IVT:", cum_ivt)
|
|
87
|
+
print("IVT-only values:", ivt_event)
|
|
88
|
+
print("Duration per timestep:", duration_event)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Parameters
|
|
94
|
+
|
|
95
|
+
| Parameter | Description |
|
|
96
|
+
| ----------------------- | ------------------------------------------------------- |
|
|
97
|
+
| `ivt_array` | 1D NumPy array of IVT values (kg/m/s) |
|
|
98
|
+
| `time_resolution_hours` | Temporal resolution of your data in hours (default: 6) |
|
|
99
|
+
| `bin_width` | Width of each IVT bin for categorization (default: 250) |
|
|
100
|
+
| `max_category` | Maximum AR category (default: 6) |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Returns
|
|
105
|
+
|
|
106
|
+
1. `final_categories`: Array of AR categories (1–6) after duration adjustments.
|
|
107
|
+
2. `cumulative_ivt`: Cumulative IVT during AR events.
|
|
108
|
+
3. `ivt_event`: Original IVT values during AR events (0 elsewhere).
|
|
109
|
+
4. `duration_event`: Number of timesteps per AR event (0 elsewhere).
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Usage Notes
|
|
114
|
+
|
|
115
|
+
* Event-based scheme collapses each AR event to its maximum intensity (`max_bounded_replace`).
|
|
116
|
+
* Evolution-based scheme preserves temporal evolution of IVT within AR events.
|
|
117
|
+
* Duration rules are applied **per continuous AR segment**.
|
|
118
|
+
* Works with any **NumPy array**, and can be integrated with **xarray or Dask arrays** for large datasets.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
## Adopting for xarray data
|
|
122
|
+
```python
|
|
123
|
+
final_cat, cum_ivt, ivt_event, duration_event = xr.apply_ufunc(AR_categorization_scheme,
|
|
124
|
+
Ivt_ds['IVT'].as_numpy(),
|
|
125
|
+
input_core_dims = [['time']],
|
|
126
|
+
output_core_dims = [['time'],['time'],['time'],['time']],
|
|
127
|
+
vectorize=True, # Auto-vectorize over lat/lon
|
|
128
|
+
dask='parallelized', # Enable parallelization using Dask
|
|
129
|
+
output_dtypes=[np.int8,np.float32,np.float32, np.int8])
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Contributing
|
|
134
|
+
|
|
135
|
+
We welcome contributions! Please follow these steps:
|
|
136
|
+
|
|
137
|
+
1. Fork the repository
|
|
138
|
+
2. Create a new branch: `git checkout -b feature-name`
|
|
139
|
+
3. Make your changes
|
|
140
|
+
4. Run tests
|
|
141
|
+
5. Submit a pull request
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
This project is licensed under the [Creative Commons License](https://web.archive.org/web/20230202010104/https://creativecommons.org/licenses/by/4.0/).
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## References
|
|
152
|
+
|
|
153
|
+
* Ralph, F. M., Rutz, J. J., Cordeira, J. M., Dettinger, M., Anderson, M., Reynolds, D., ... & Smallcomb, C. (2019). A scale to characterize the strength and impacts of atmospheric rivers. Bulletin of the American Meteorological Society, 100(2), 269-289.
|
|
154
|
+
* Visit the [Atmospheric River Tracking Model Intercomparison Project (ARTMIP)](https://ncar.github.io/ARTMIP/intro.html) to follow Atmospheric River community research and publications.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
arcat: Atmospheric River Categorization Toolkit
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- Event-based AR categorization
|
|
6
|
+
- Evolution-based AR categorization
|
|
7
|
+
- xarray + Dask support
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .version import __version__
|
|
11
|
+
from .core import (
|
|
12
|
+
AR_categorization_scheme,
|
|
13
|
+
AR_categorization_evolution_scheme,
|
|
14
|
+
)
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core AR categorization algorithms for the arcat package.
|
|
3
|
+
|
|
4
|
+
This module contains:
|
|
5
|
+
- Event-based AR categorization (collapses to peak intensity)
|
|
6
|
+
- Evolution-based AR categorization (keeps intensity evolution)
|
|
7
|
+
- IVT-only and duration-only outputs for detailed analysis
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import numpy as np # Import NumPy for array operations
|
|
11
|
+
from .utils import ( # Import helper functions from utils
|
|
12
|
+
compute_steps_per_day, # Converts time resolution (hours) to timesteps per day
|
|
13
|
+
bin_ivt, # Converts IVT values into AR categories
|
|
14
|
+
cumulative_reset, # Computes cumulative IVT resetting at zeros
|
|
15
|
+
max_bounded_replace # Collapses nonzero segments to their maximum value
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# ------------------------
|
|
19
|
+
# Internal helper functions
|
|
20
|
+
# ------------------------
|
|
21
|
+
|
|
22
|
+
def _adjust_segment(arr, start, end, duration, steps_per_day):
|
|
23
|
+
"""
|
|
24
|
+
Apply duration adjustment rule to a segment (in-place modification).
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
arr : np.ndarray
|
|
29
|
+
Array of AR categories to modify.
|
|
30
|
+
start : int
|
|
31
|
+
Start index of the event segment.
|
|
32
|
+
end : int
|
|
33
|
+
End index of the event segment.
|
|
34
|
+
duration : int
|
|
35
|
+
Duration of the segment in timesteps.
|
|
36
|
+
steps_per_day : int
|
|
37
|
+
Number of timesteps that correspond to 1 day.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
# If duration is shorter than 1 day, downgrade the category by 1
|
|
41
|
+
if duration < steps_per_day:
|
|
42
|
+
arr[start:end] -= 1 # Subtract 1 from all elements in the segment
|
|
43
|
+
|
|
44
|
+
# If duration is longer than or equal to 2 days, upgrade the category by 1
|
|
45
|
+
elif duration >= 2 * steps_per_day:
|
|
46
|
+
arr[start:end] += 1 # Add 1 to all elements in the segment
|
|
47
|
+
|
|
48
|
+
# Otherwise (duration 1–2 days), do nothing (leave category unchanged)
|
|
49
|
+
|
|
50
|
+
# ------------------------
|
|
51
|
+
def _apply_duration_rule(categories, steps_per_day, max_category):
|
|
52
|
+
"""
|
|
53
|
+
Apply the duration adjustment to continuous AR events.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
categories : np.ndarray
|
|
58
|
+
Array of initial AR categories per timestep.
|
|
59
|
+
steps_per_day : int
|
|
60
|
+
Number of timesteps corresponding to 1 day.
|
|
61
|
+
max_category : int
|
|
62
|
+
Maximum AR category allowed.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
final : np.ndarray
|
|
67
|
+
Array of AR categories after duration adjustment.
|
|
68
|
+
duration_arr : np.ndarray
|
|
69
|
+
Array of duration (in timesteps) for each AR event at each index.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
final = categories.copy() # Copy categories to avoid modifying input
|
|
73
|
+
n = len(categories) # Total number of timesteps
|
|
74
|
+
start = None # Initialize start index of current event
|
|
75
|
+
duration_arr = np.zeros_like(categories, dtype=float) # Store duration per timestep
|
|
76
|
+
|
|
77
|
+
# Loop over each timestep to find AR events
|
|
78
|
+
for i in range(n):
|
|
79
|
+
if categories[i] == 0: # Found a zero → end of AR event
|
|
80
|
+
if start is not None: # There was an ongoing event
|
|
81
|
+
end = i # End index of the event
|
|
82
|
+
duration = end - start # Compute duration in timesteps
|
|
83
|
+
_adjust_segment(final, start, end, duration, steps_per_day) # Apply duration rule
|
|
84
|
+
duration_arr[start:end] = duration # Store duration for all timesteps in event
|
|
85
|
+
start = None # Reset start for next event
|
|
86
|
+
else:
|
|
87
|
+
if start is None: # Found start of a new AR event
|
|
88
|
+
start = i # Mark start index
|
|
89
|
+
|
|
90
|
+
# Handle event that goes until the last timestep
|
|
91
|
+
if start is not None:
|
|
92
|
+
end = n # End index is last timestep
|
|
93
|
+
duration = end - start # Duration of the event
|
|
94
|
+
_adjust_segment(final, start, end, duration, steps_per_day) # Apply duration rule
|
|
95
|
+
duration_arr[start:end] = duration # Store duration
|
|
96
|
+
|
|
97
|
+
# Ensure all categories are within allowed bounds
|
|
98
|
+
return np.clip(final, 0, max_category), duration_arr # Return adjusted categories and duration array
|
|
99
|
+
|
|
100
|
+
# ------------------------
|
|
101
|
+
# Event-based AR categorization
|
|
102
|
+
# ------------------------
|
|
103
|
+
|
|
104
|
+
def AR_categorization_scheme(
|
|
105
|
+
ivt_array: np.ndarray, # Input IVT values
|
|
106
|
+
time_resolution_hours: int = 6, # Time resolution of data in hours
|
|
107
|
+
bin_width: float = 250.0, # Width of each IVT bin for categorization
|
|
108
|
+
max_category: int = 6 # Maximum AR category
|
|
109
|
+
):
|
|
110
|
+
"""
|
|
111
|
+
Event-based AR categorization (collapses each event to peak intensity).
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
final_categories : np.ndarray -> categorized AR values
|
|
115
|
+
cumulative_ivt : np.ndarray -> cumulative IVT over AR events
|
|
116
|
+
ivt_event : np.ndarray -> IVT values only during AR events
|
|
117
|
+
duration_event : np.ndarray -> duration in timesteps for each AR event
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
# Compute how many timesteps correspond to 1 day
|
|
121
|
+
steps_per_day = compute_steps_per_day(time_resolution_hours)
|
|
122
|
+
|
|
123
|
+
# Copy IVT array to preserve original
|
|
124
|
+
original_ivt = ivt_array.copy()
|
|
125
|
+
|
|
126
|
+
# Bin IVT values into categories
|
|
127
|
+
categories = bin_ivt(ivt_array, bin_width, max_category)
|
|
128
|
+
|
|
129
|
+
# Collapse each nonzero event segment to its maximum value
|
|
130
|
+
categories = max_bounded_replace(categories)
|
|
131
|
+
|
|
132
|
+
# Apply duration rule to event segments and get duration per timestep
|
|
133
|
+
final_categories, duration_event = _apply_duration_rule(categories, steps_per_day, max_category)
|
|
134
|
+
|
|
135
|
+
# Create mask of where AR events occur (category > 0)
|
|
136
|
+
mask = final_categories > 0
|
|
137
|
+
|
|
138
|
+
# Compute cumulative IVT over AR events
|
|
139
|
+
cumulative_ivt = cumulative_reset(original_ivt, mask)
|
|
140
|
+
|
|
141
|
+
# Extract IVT values only during AR events, zero elsewhere
|
|
142
|
+
ivt_event = np.where(mask, original_ivt, 0)
|
|
143
|
+
|
|
144
|
+
# Return final categories, cumulative IVT, IVT-only, duration-only arrays
|
|
145
|
+
return final_categories, cumulative_ivt, ivt_event, duration_event
|
|
146
|
+
|
|
147
|
+
# ------------------------
|
|
148
|
+
# Evolution-based AR categorization
|
|
149
|
+
# ------------------------
|
|
150
|
+
|
|
151
|
+
def AR_categorization_evolution_scheme(
|
|
152
|
+
ivt_array: np.ndarray, # Input IVT values
|
|
153
|
+
time_resolution_hours: int = 6, # Time resolution of data in hours
|
|
154
|
+
bin_width: float = 250.0, # IVT bin width
|
|
155
|
+
max_category: int = 6 # Maximum AR category
|
|
156
|
+
):
|
|
157
|
+
"""
|
|
158
|
+
Evolution-based AR categorization (keeps intensity evolution inside each event).
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
final_categories : np.ndarray -> categorized AR values
|
|
162
|
+
cumulative_ivt : np.ndarray -> cumulative IVT over AR events
|
|
163
|
+
ivt_event : np.ndarray -> IVT values only during AR events
|
|
164
|
+
duration_event : np.ndarray -> duration in timesteps for each AR event
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
# Compute timesteps per day
|
|
168
|
+
steps_per_day = compute_steps_per_day(time_resolution_hours)
|
|
169
|
+
|
|
170
|
+
# Copy IVT array to preserve original
|
|
171
|
+
original_ivt = ivt_array.copy()
|
|
172
|
+
|
|
173
|
+
# Bin IVT values into categories
|
|
174
|
+
categories = bin_ivt(ivt_array, bin_width, max_category)
|
|
175
|
+
|
|
176
|
+
# No collapsing for evolution scheme
|
|
177
|
+
# Apply duration rule to event segments and get duration per timestep
|
|
178
|
+
final_categories, duration_event = _apply_duration_rule(categories, steps_per_day, max_category)
|
|
179
|
+
|
|
180
|
+
# Mask of AR events
|
|
181
|
+
mask = final_categories > 0
|
|
182
|
+
|
|
183
|
+
# Compute cumulative IVT over AR events
|
|
184
|
+
cumulative_ivt = cumulative_reset(original_ivt, mask)
|
|
185
|
+
|
|
186
|
+
# Extract IVT values only during AR events, zero elsewhere
|
|
187
|
+
ivt_event = np.where(mask, original_ivt, 0)
|
|
188
|
+
|
|
189
|
+
# Return final categories, cumulative IVT, IVT-only, duration-only arrays
|
|
190
|
+
return final_categories, cumulative_ivt, ivt_event, duration_event
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core AR categorization algorithms.
|
|
3
|
+
|
|
4
|
+
Contains:
|
|
5
|
+
- Event-based scheme
|
|
6
|
+
- Evolution-based scheme
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from .utils import (
|
|
11
|
+
compute_steps_per_day,
|
|
12
|
+
bin_ivt,
|
|
13
|
+
cumulative_reset,
|
|
14
|
+
max_bounded_replace,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _adjust_segment(arr, start, end, duration, steps_per_day):
|
|
19
|
+
"""
|
|
20
|
+
Apply duration adjustment rule to a segment.
|
|
21
|
+
|
|
22
|
+
Rules:
|
|
23
|
+
- < 1 day -> downgrade
|
|
24
|
+
- 1–2 days -> unchanged
|
|
25
|
+
- >= 2 days -> upgrade
|
|
26
|
+
"""
|
|
27
|
+
if duration < steps_per_day:
|
|
28
|
+
arr[start:end] -= 1
|
|
29
|
+
elif duration >= 2 * steps_per_day:
|
|
30
|
+
arr[start:end] += 1
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _apply_duration_rule(categories, steps_per_day, max_category):
|
|
34
|
+
"""
|
|
35
|
+
Apply duration adjustment to continuous AR events.
|
|
36
|
+
|
|
37
|
+
Events are defined as consecutive timesteps
|
|
38
|
+
where category > 0.
|
|
39
|
+
"""
|
|
40
|
+
final = categories.copy()
|
|
41
|
+
n = len(categories)
|
|
42
|
+
start = None
|
|
43
|
+
|
|
44
|
+
for i in range(n):
|
|
45
|
+
if categories[i] == 0:
|
|
46
|
+
if start is not None:
|
|
47
|
+
end = i
|
|
48
|
+
duration = end - start
|
|
49
|
+
_adjust_segment(final, start, end, duration, steps_per_day)
|
|
50
|
+
start = None
|
|
51
|
+
else:
|
|
52
|
+
if start is None:
|
|
53
|
+
start = i
|
|
54
|
+
|
|
55
|
+
if start is not None:
|
|
56
|
+
end = n
|
|
57
|
+
duration = end - start
|
|
58
|
+
_adjust_segment(final, start, end, duration, steps_per_day)
|
|
59
|
+
|
|
60
|
+
return np.clip(final, 0, max_category)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# ============================================================
|
|
64
|
+
# EVENT-BASED SCHEME
|
|
65
|
+
# ============================================================
|
|
66
|
+
|
|
67
|
+
def AR_categorization_scheme(
|
|
68
|
+
ivt_array: np.ndarray,
|
|
69
|
+
time_resolution_hours: int = 6,
|
|
70
|
+
bin_width: float = 250.0,
|
|
71
|
+
max_category: int = 6,
|
|
72
|
+
):
|
|
73
|
+
"""
|
|
74
|
+
Event-based AR categorization.
|
|
75
|
+
|
|
76
|
+
Steps:
|
|
77
|
+
1. Bin IVT into categories
|
|
78
|
+
2. Collapse each AR event to peak intensity
|
|
79
|
+
3. Apply duration rule to event
|
|
80
|
+
4. Compute cumulative IVT
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
steps_per_day = compute_steps_per_day(time_resolution_hours)
|
|
84
|
+
|
|
85
|
+
original_ivt = ivt_array.copy()
|
|
86
|
+
|
|
87
|
+
categories = bin_ivt(ivt_array, bin_width, max_category)
|
|
88
|
+
categories = max_bounded_replace(categories)
|
|
89
|
+
|
|
90
|
+
final_categories = _apply_duration_rule(
|
|
91
|
+
categories, steps_per_day, max_category
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
mask = final_categories > 0
|
|
95
|
+
cumulative_ivt = cumulative_reset(original_ivt, mask)
|
|
96
|
+
|
|
97
|
+
return final_categories, cumulative_ivt
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# ============================================================
|
|
101
|
+
# EVOLUTION-BASED SCHEME
|
|
102
|
+
# ============================================================
|
|
103
|
+
|
|
104
|
+
def AR_categorization_evolution_scheme(
|
|
105
|
+
ivt_array: np.ndarray,
|
|
106
|
+
time_resolution_hours: int = 6,
|
|
107
|
+
bin_width: float = 250.0,
|
|
108
|
+
max_category: int = 6,
|
|
109
|
+
):
|
|
110
|
+
"""
|
|
111
|
+
Evolution-based AR categorization.
|
|
112
|
+
|
|
113
|
+
Same as event-based scheme except:
|
|
114
|
+
- Does NOT collapse event to peak intensity.
|
|
115
|
+
- Duration rule still applied event-wise.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
steps_per_day = compute_steps_per_day(time_resolution_hours)
|
|
119
|
+
|
|
120
|
+
original_ivt = ivt_array.copy()
|
|
121
|
+
|
|
122
|
+
categories = bin_ivt(ivt_array, bin_width, max_category)
|
|
123
|
+
|
|
124
|
+
final_categories = _apply_duration_rule(
|
|
125
|
+
categories, steps_per_day, max_category
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
mask = final_categories > 0
|
|
129
|
+
cumulative_ivt = cumulative_reset(original_ivt, mask)
|
|
130
|
+
|
|
131
|
+
return final_categories, cumulative_ivt
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for AR categorization.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def compute_steps_per_day(time_resolution_hours: int) -> int:
|
|
9
|
+
"""
|
|
10
|
+
Compute number of timesteps per day.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
time_resolution_hours : int
|
|
15
|
+
Temporal resolution of input data in hours.
|
|
16
|
+
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
int
|
|
20
|
+
Number of timesteps corresponding to 1 day.
|
|
21
|
+
"""
|
|
22
|
+
return int(24 / time_resolution_hours)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def bin_ivt(ivt_array: np.ndarray, bin_width: float, max_category: int):
|
|
26
|
+
"""
|
|
27
|
+
Convert IVT values to AR categories.
|
|
28
|
+
|
|
29
|
+
IVT is divided into bins of size `bin_width`.
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
0–249 -> 0
|
|
33
|
+
250–499 -> 1
|
|
34
|
+
etc.
|
|
35
|
+
"""
|
|
36
|
+
bins = np.floor(ivt_array / bin_width)
|
|
37
|
+
bins = np.clip(bins, 0, max_category)
|
|
38
|
+
return bins.astype(int)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def cumulative_reset(values: np.ndarray, mask: np.ndarray):
|
|
42
|
+
"""
|
|
43
|
+
Compute cumulative sum that resets when mask == 0.
|
|
44
|
+
|
|
45
|
+
Used to compute cumulative IVT per AR event.
|
|
46
|
+
"""
|
|
47
|
+
result = np.zeros_like(values, dtype=float)
|
|
48
|
+
running_sum = 0.0
|
|
49
|
+
|
|
50
|
+
for i in range(len(values)):
|
|
51
|
+
if mask[i] == 0:
|
|
52
|
+
running_sum = 0.0
|
|
53
|
+
else:
|
|
54
|
+
running_sum += values[i]
|
|
55
|
+
result[i] = running_sum
|
|
56
|
+
|
|
57
|
+
return result
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def max_bounded_replace(arr: np.ndarray):
|
|
61
|
+
"""
|
|
62
|
+
Replace each nonzero segment by its maximum value.
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
[1,2,3,0,2,1] -> [3,3,3,0,2,2]
|
|
66
|
+
|
|
67
|
+
Used in event-based scheme to collapse AR event
|
|
68
|
+
to peak intensity.
|
|
69
|
+
"""
|
|
70
|
+
arr = arr.copy()
|
|
71
|
+
n = len(arr)
|
|
72
|
+
start = None
|
|
73
|
+
|
|
74
|
+
for i in range(n):
|
|
75
|
+
if arr[i] == 0:
|
|
76
|
+
if start is not None:
|
|
77
|
+
arr[start:i] = np.max(arr[start:i])
|
|
78
|
+
start = None
|
|
79
|
+
else:
|
|
80
|
+
if start is None:
|
|
81
|
+
start = i
|
|
82
|
+
|
|
83
|
+
if start is not None:
|
|
84
|
+
arr[start:n] = np.max(arr[start:n])
|
|
85
|
+
|
|
86
|
+
return arr
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: arcat
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Atmospheric River Categorization Toolkit
|
|
5
|
+
Author: Kwesi Twentwewa Quagraine
|
|
6
|
+
Author-email: Kwesi Twentwewa Quagraine <kwsquagraine@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: atmospheric rivers,ivt,weather,extremes,python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: xarray
|
|
16
|
+
Requires-Dist: dask
|
|
17
|
+
Requires-Dist: numba
|
|
18
|
+
Requires-Dist: tqdm
|
|
19
|
+
|
|
20
|
+
# ARCat: Atmospheric River Categorization Toolkit
|
|
21
|
+
|
|
22
|
+
**ARCat** is a Python package for **categorizing Atmospheric River (AR) events** based on Integrated Vapor Transport (IVT) data. It provides:
|
|
23
|
+
|
|
24
|
+
- **Event-based AR categorization**: Collapses each AR event to its peak intensity.
|
|
25
|
+
- **Evolution-based AR categorization**: Preserves the intensity evolution within AR events.
|
|
26
|
+
|
|
27
|
+
Additionally, ARCat computes:
|
|
28
|
+
|
|
29
|
+
- **Cumulative IVT** per AR event.
|
|
30
|
+
- **IVT-only values** for each AR event.
|
|
31
|
+
- **Duration-only values** (number of timesteps per event).
|
|
32
|
+
|
|
33
|
+
It is fully compatible with **NumPy arrays**, **xarray**, and **Dask**, allowing analysis of large datasets efficiently.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- Event-based and evolution-based AR categorization.
|
|
40
|
+
- Automatic handling of duration rules:
|
|
41
|
+
- Events < 1 day → downgrade category
|
|
42
|
+
- Events 1–2 days → unchanged
|
|
43
|
+
- Events ≥ 2 days → upgrade category
|
|
44
|
+
- Maximum category enforcement.
|
|
45
|
+
- Option to extract IVT-only and duration-only arrays.
|
|
46
|
+
- Easy integration with **xarray/Dask** for large datasets.
|
|
47
|
+
- Fully documented and tested, with CI support.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
Clone the repository and install locally:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/yourusername/arcat.git
|
|
57
|
+
cd arcat
|
|
58
|
+
pip install -e .
|
|
59
|
+
````
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
### Import the package
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import numpy as np
|
|
66
|
+
from arcat.core import AR_categorization_scheme, AR_categorization_evolution_scheme
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Prepare your IVT array
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# Example: random IVT values for demonstration
|
|
73
|
+
ivt = np.random.rand(20) * 1500 # IVT in kg/m/s
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Event-based AR categorization
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# Run the event-based AR scheme
|
|
80
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_scheme(
|
|
81
|
+
ivt,
|
|
82
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
83
|
+
bin_width=250.0, # IVT bin size
|
|
84
|
+
max_category=6 # Maximum AR category
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
print("Categorized AR events:", final_cat)
|
|
88
|
+
print("Cumulative IVT:", cum_ivt)
|
|
89
|
+
print("IVT-only values:", ivt_event)
|
|
90
|
+
print("Duration per timestep:", duration_event)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Evolution-based AR categorization
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
# Run the evolution-based AR scheme
|
|
97
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_evolution_scheme(
|
|
98
|
+
ivt,
|
|
99
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
100
|
+
bin_width=250.0, # IVT bin size
|
|
101
|
+
max_category=6 # Maximum AR category
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
print("Evolution categories:", final_cat)
|
|
105
|
+
print("Cumulative IVT:", cum_ivt)
|
|
106
|
+
print("IVT-only values:", ivt_event)
|
|
107
|
+
print("Duration per timestep:", duration_event)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Parameters
|
|
113
|
+
|
|
114
|
+
| Parameter | Description |
|
|
115
|
+
| ----------------------- | ------------------------------------------------------- |
|
|
116
|
+
| `ivt_array` | 1D NumPy array of IVT values (kg/m/s) |
|
|
117
|
+
| `time_resolution_hours` | Temporal resolution of your data in hours (default: 6) |
|
|
118
|
+
| `bin_width` | Width of each IVT bin for categorization (default: 250) |
|
|
119
|
+
| `max_category` | Maximum AR category (default: 6) |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Returns
|
|
124
|
+
|
|
125
|
+
1. `final_categories`: Array of AR categories (1–6) after duration adjustments.
|
|
126
|
+
2. `cumulative_ivt`: Cumulative IVT during AR events.
|
|
127
|
+
3. `ivt_event`: Original IVT values during AR events (0 elsewhere).
|
|
128
|
+
4. `duration_event`: Number of timesteps per AR event (0 elsewhere).
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Usage Notes
|
|
133
|
+
|
|
134
|
+
* Event-based scheme collapses each AR event to its maximum intensity (`max_bounded_replace`).
|
|
135
|
+
* Evolution-based scheme preserves temporal evolution of IVT within AR events.
|
|
136
|
+
* Duration rules are applied **per continuous AR segment**.
|
|
137
|
+
* Works with any **NumPy array**, and can be integrated with **xarray or Dask arrays** for large datasets.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
## Adopting for xarray data
|
|
141
|
+
```python
|
|
142
|
+
final_cat, cum_ivt, ivt_event, duration_event = xr.apply_ufunc(AR_categorization_scheme,
|
|
143
|
+
Ivt_ds['IVT'].as_numpy(),
|
|
144
|
+
input_core_dims = [['time']],
|
|
145
|
+
output_core_dims = [['time'],['time'],['time'],['time']],
|
|
146
|
+
vectorize=True, # Auto-vectorize over lat/lon
|
|
147
|
+
dask='parallelized', # Enable parallelization using Dask
|
|
148
|
+
output_dtypes=[np.int8,np.float32,np.float32, np.int8])
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Contributing
|
|
153
|
+
|
|
154
|
+
We welcome contributions! Please follow these steps:
|
|
155
|
+
|
|
156
|
+
1. Fork the repository
|
|
157
|
+
2. Create a new branch: `git checkout -b feature-name`
|
|
158
|
+
3. Make your changes
|
|
159
|
+
4. Run tests
|
|
160
|
+
5. Submit a pull request
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
This project is licensed under the [Creative Commons License](https://web.archive.org/web/20230202010104/https://creativecommons.org/licenses/by/4.0/).
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## References
|
|
171
|
+
|
|
172
|
+
* Ralph, F. M., Rutz, J. J., Cordeira, J. M., Dettinger, M., Anderson, M., Reynolds, D., ... & Smallcomb, C. (2019). A scale to characterize the strength and impacts of atmospheric rivers. Bulletin of the American Meteorological Society, 100(2), 269-289.
|
|
173
|
+
* Visit the [Atmospheric River Tracking Model Intercomparison Project (ARTMIP)](https://ncar.github.io/ARTMIP/intro.html) to follow Atmospheric River community research and publications.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
setup.cfg
|
|
4
|
+
arcat/__init__.py
|
|
5
|
+
arcat/core.py
|
|
6
|
+
arcat/core_v1.py
|
|
7
|
+
arcat/utils.py
|
|
8
|
+
arcat/version.py
|
|
9
|
+
arcat.egg-info/PKG-INFO
|
|
10
|
+
arcat.egg-info/SOURCES.txt
|
|
11
|
+
arcat.egg-info/dependency_links.txt
|
|
12
|
+
arcat.egg-info/requires.txt
|
|
13
|
+
arcat.egg-info/top_level.txt
|
|
14
|
+
tests/test_core.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
arcat
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=42", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "arcat"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Atmospheric River Categorization Toolkit"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Kwesi Twentwewa Quagraine", email = "kwsquagraine@gmail.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["atmospheric rivers", "ivt", "weather","extremes", "python"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent"
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
dependencies = [
|
|
23
|
+
"numpy",
|
|
24
|
+
"xarray",
|
|
25
|
+
"dask",
|
|
26
|
+
"numba",
|
|
27
|
+
"tqdm"
|
|
28
|
+
]
|
arcat-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = arcat
|
|
3
|
+
version = 0.1.0
|
|
4
|
+
description = Atmospheric River Categorization Toolkit
|
|
5
|
+
long_description = file: README.md
|
|
6
|
+
long_description_content_type = text/markdown
|
|
7
|
+
author = Kwesi Twentwewa Quagraine
|
|
8
|
+
license = MIT
|
|
9
|
+
keywords = atmospheric rivers, ivt, climate
|
|
10
|
+
classifiers =
|
|
11
|
+
Programming Language :: Python :: 3
|
|
12
|
+
License :: OSI Approved :: MIT License
|
|
13
|
+
Operating System:: OS Independent
|
|
14
|
+
|
|
15
|
+
[options]
|
|
16
|
+
packages = find:
|
|
17
|
+
python_requires = >=3.8
|
|
18
|
+
install_requires =
|
|
19
|
+
numpy
|
|
20
|
+
xarray
|
|
21
|
+
dask
|
|
22
|
+
numba
|
|
23
|
+
tqdm
|
|
24
|
+
|
|
25
|
+
[egg_info]
|
|
26
|
+
tag_build =
|
|
27
|
+
tag_date = 0
|
|
28
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from arcat.core import AR_categorization_scheme, AR_categorization_evolution_scheme
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_short_event_downgrade():
|
|
6
|
+
ivt = np.array([300, 300, 0])
|
|
7
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_scheme(
|
|
8
|
+
|
|
9
|
+
ivt,
|
|
10
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
11
|
+
bin_width=250.0, # IVT bin size
|
|
12
|
+
max_category=6 # Maximum AR category
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
assert np.all(final_cat[:2] == 0)
|
|
16
|
+
|
|
17
|
+
# Run the event-based AR scheme
|
|
18
|
+
def test_long_event_upgrade():
|
|
19
|
+
ivt = np.array([800] * 12)
|
|
20
|
+
# Run the evolution-based AR scheme
|
|
21
|
+
final_cat, cum_ivt, ivt_event, duration_event = AR_categorization_evolution_scheme(
|
|
22
|
+
ivt,
|
|
23
|
+
time_resolution_hours=6, # Data resolution in hours
|
|
24
|
+
bin_width=250.0, # IVT bin size
|
|
25
|
+
max_category=6 # Maximum AR category
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
assert np.all(final_cat >= 3)
|