satcube 0.1.0__tar.gz → 0.1.1__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.
Potentially problematic release.
This version of satcube might be problematic. Click here for more details.
- satcube-0.1.1/PKG-INFO +224 -0
- satcube-0.1.1/README.md +193 -0
- satcube-0.1.1/pyproject.toml +54 -0
- satcube-0.1.1/satcube/cloud_detection.py +160 -0
- satcube-0.1.1/satcube/download.py +65 -0
- satcube-0.1.1/satcube/download_old.py +82 -0
- {satcube-0.1.0 → satcube-0.1.1}/satcube/main.py +2 -2
- satcube-0.1.1/satcube/utils.py +70 -0
- satcube-0.1.0/PKG-INFO +0 -31
- satcube-0.1.0/README.md +0 -3
- satcube-0.1.0/pyproject.toml +0 -116
- satcube-0.1.0/satcube/__init__.py +0 -3
- satcube-0.1.0/setup.py +0 -43
- {satcube-0.1.0 → satcube-0.1.1}/LICENSE +0 -0
- /satcube-0.1.0/satcube/cloud_detection.py → /satcube-0.1.1/satcube/cloud_detection_old.py +0 -0
- {satcube-0.1.0 → satcube-0.1.1}/satcube/dataclass.py +0 -0
- /satcube-0.1.0/satcube/utils.py → /satcube-0.1.1/satcube/utils_old.py +0 -0
satcube-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: satcube
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A Python package to create cloud-free monthly composites by fusing Landsat and Sentinel-2 data.
|
|
5
|
+
Home-page: https://github.com/IPL-UV/satcube
|
|
6
|
+
Author: Cesar Aybar
|
|
7
|
+
Author-email: fcesar.aybar@uv.es
|
|
8
|
+
Requires-Python: >=3.10,<4.0
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Provides-Extra: full
|
|
14
|
+
Requires-Dist: cubexpress (>=0.1.2)
|
|
15
|
+
Requires-Dist: earthengine-api (>=0.1.4.0) ; extra == "full"
|
|
16
|
+
Requires-Dist: fastcubo (>=0.0.999)
|
|
17
|
+
Requires-Dist: mlstac (>=0.5.0)
|
|
18
|
+
Requires-Dist: numpy (>=1.25.0)
|
|
19
|
+
Requires-Dist: pandas (>=2.0.0)
|
|
20
|
+
Requires-Dist: pydantic (>=2.8.0)
|
|
21
|
+
Requires-Dist: rasterio (>=1.2.0) ; extra == "full"
|
|
22
|
+
Requires-Dist: requests (>=2.26.0)
|
|
23
|
+
Requires-Dist: satalign (>=0.0.999)
|
|
24
|
+
Requires-Dist: scikit-learn (>=1.2.0) ; extra == "full"
|
|
25
|
+
Requires-Dist: segmentation-models-pytorch (>=0.3.0) ; extra == "full"
|
|
26
|
+
Requires-Dist: torch (>=2.0.0) ; extra == "full"
|
|
27
|
+
Requires-Dist: xarray (>=2023.7.0)
|
|
28
|
+
Project-URL: Documentation, https://ipl-uv.github.io/satcube/
|
|
29
|
+
Project-URL: Repository, https://github.com/IPL-UV/satcube
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<img src="https://huggingface.co/datasets/JulioContrerasH/DataMLSTAC/resolve/main/banner_satcube.png" width="33%">
|
|
36
|
+
</p>
|
|
37
|
+
|
|
38
|
+
<p align="center">
|
|
39
|
+
<em>A Python package for managing Sentinel-2 satellite data cubes</em> 🚀
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
<p align="center">
|
|
43
|
+
<a href='https://pypi.python.org/pypi/satcube'>
|
|
44
|
+
<img src='https://img.shields.io/pypi/v/satcube.svg' alt='PyPI' />
|
|
45
|
+
</a>
|
|
46
|
+
<a href="https://opensource.org/licenses/MIT" target="_blank">
|
|
47
|
+
<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License">
|
|
48
|
+
</a>
|
|
49
|
+
<a href="https://github.com/psf/black" target="_blank">
|
|
50
|
+
<img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Black">
|
|
51
|
+
</a>
|
|
52
|
+
<a href="https://pycqa.github.io/isort/" target="_blank">
|
|
53
|
+
<img src="https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336" alt="isort">
|
|
54
|
+
</a>
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
**GitHub**: [https://github.com/IPL-UV/satcube](https://github.com/IPL-UV/satcube) 🌐
|
|
60
|
+
|
|
61
|
+
**PyPI**: [https://pypi.org/project/satcube/](https://pypi.org/project/satcube/) 🛠️
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## **Overview** 📊
|
|
66
|
+
|
|
67
|
+
**satcube** is a Python package designed for efficient management, processing, and analysis of Sentinel-2 satellite image cubes. It allows for downloading, cloud masking, gap filling, and super-resolving Sentinel-2 imagery, as well as creating monthly composites and performing interpolation.
|
|
68
|
+
|
|
69
|
+
## **Key Features** ✨
|
|
70
|
+
- **Satellite image download**: Retrieve Sentinel-2 images from Earth Engine efficiently. 🛰️
|
|
71
|
+
- **Cloud masking**: Automatically remove clouds from Sentinel-2 images. ☁️
|
|
72
|
+
- **Gap filling**: Fill missing data using methods like linear interpolation and histogram matching. 🧩
|
|
73
|
+
- **Super-resolution**: Apply super-resolution models to enhance image quality. 🔍
|
|
74
|
+
- **Monthly composites**: Aggregate images into monthly composites with various statistical methods. 📅
|
|
75
|
+
- **Temporal smoothing**: Smooth reflectance values across time using interpolation techniques. 📈
|
|
76
|
+
## **Installation** ⚙️
|
|
77
|
+
|
|
78
|
+
Install the latest version from PyPI:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pip install satcube
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## **How to use** 🛠️
|
|
85
|
+
|
|
86
|
+
### **Basic usage: working with sentinel-2 data** 🌍
|
|
87
|
+
|
|
88
|
+
#### **Load libraries**
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import ee
|
|
92
|
+
import satcube
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### **Authenticate and initialize earth engine**
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
ee.Authenticate()
|
|
99
|
+
ee.Initialize(project="ee-csaybar-real")
|
|
100
|
+
```
|
|
101
|
+
#### **Download model weights**
|
|
102
|
+
```python
|
|
103
|
+
outpath = satcube.download_weights(path="weights")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### **Create a satellite dataCube**
|
|
107
|
+
```python
|
|
108
|
+
datacube = satcube.SatCube(
|
|
109
|
+
coordinates=(-77.68598590138802,-8.888223962022263),
|
|
110
|
+
sensor=satcube.Sentinel2(weight_path=outpath, edge_size=384),
|
|
111
|
+
output_dir="wendy01",
|
|
112
|
+
max_workers=12,
|
|
113
|
+
device="cuda",
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
### **Query and process sentinel-2 data** 🛰️
|
|
119
|
+
|
|
120
|
+
#### **Query the sentinel-2 image collection**
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
# Query the Sentinel-2 image collection
|
|
124
|
+
table_query = datacube.metadata_s2()
|
|
125
|
+
|
|
126
|
+
# Filter images based on cloud cover and remove duplicates
|
|
127
|
+
table_query_subset = table_query[table_query["cs_cdf"] > 0.30]
|
|
128
|
+
table_query_subset = table_query_subset.drop_duplicates(subset="img_date")
|
|
129
|
+
mgrs_tile_max = table_query_subset["mgrs_title"].value_counts().idxmax()
|
|
130
|
+
table_query_subset = table_query_subset[table_query_subset["mgrs_title"] == mgrs_tile_max]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### **Download sentinel-2 images**
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
table_download = datacube.download_s2_image(table_query_subset)
|
|
137
|
+
```
|
|
138
|
+
#### **Cloud masking**
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
# Remove clouds from the images
|
|
142
|
+
table_nocloud = datacube.cloudmasking_s2(table_download)
|
|
143
|
+
table_nocloud = table_nocloud[table_nocloud["cloud_cover"] < 0.75]
|
|
144
|
+
table_nocloud.reset_index(drop=True, inplace=True)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### **Gap filling**
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
# Fill missing data in the images
|
|
151
|
+
table_nogaps = datacube.gapfilling_s2(table_nocloud)
|
|
152
|
+
table_nogaps = table_nogaps[table_nogaps["match_error"] < 0.1]
|
|
153
|
+
```
|
|
154
|
+
### **Monthly composites and image smoothing 📅**
|
|
155
|
+
|
|
156
|
+
#### **Create monthly composites**
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
# Generate monthly composites
|
|
160
|
+
table_composites = datacube.monthly_composites_s2(
|
|
161
|
+
table_nogaps, agg_method="median", date_range=("2016-01-01", "2024-07-31")
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### **Interpolate missing data**
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
# Interpolate missing months if necessary
|
|
169
|
+
table_interpolate = datacube.interpolate_s2(table=table_composites)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### **Smooth reflectance values**
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
# Smooth reflectance values across time
|
|
176
|
+
table_smooth = datacube.smooth_s2(table=table_interpolate)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### **Super-resolution and visualization** 📐
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
#### **Super-resolution**
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
# Apply super-resolution to the image cube
|
|
187
|
+
# table_final = datacube.super_s2(table_smooth)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
#### **Display images**
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
# Display the images from the data cube
|
|
195
|
+
datacube.display_images(table=table_smooth)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### **Create a GIF**
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
# !apt-get install imagemagick
|
|
202
|
+
import os
|
|
203
|
+
os.system("convert -delay 20 -loop 0 wendy01/z_s2_07_smoothed_png/temp_07*.png animation.gif")
|
|
204
|
+
|
|
205
|
+
from IPython.display import Image
|
|
206
|
+
Image(filename='animation.gif', width=500)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
<p align="center">
|
|
210
|
+
<img src="https://huggingface.co/datasets/JulioContrerasH/DataMLSTAC/resolve/main/gif_satcube.gif" width="100%">
|
|
211
|
+
</p>
|
|
212
|
+
|
|
213
|
+
#### **Smooth reflectance values**
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
# Smooth reflectance values across time
|
|
217
|
+
table_smooth = datacube.smooth_s2(table=table_interpolate)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## **Supported features and filters** ✨
|
|
221
|
+
|
|
222
|
+
- **Cloud masking:** Efficient removal of clouds from satellite images.
|
|
223
|
+
- **Resampling methods:** Various methods for resampling and aligning imagery.
|
|
224
|
+
- **Super-resolution:** ONNX-based models for improving image resolution.
|
satcube-0.1.1/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://huggingface.co/datasets/JulioContrerasH/DataMLSTAC/resolve/main/banner_satcube.png" width="33%">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<em>A Python package for managing Sentinel-2 satellite data cubes</em> 🚀
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href='https://pypi.python.org/pypi/satcube'>
|
|
13
|
+
<img src='https://img.shields.io/pypi/v/satcube.svg' alt='PyPI' />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://opensource.org/licenses/MIT" target="_blank">
|
|
16
|
+
<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License">
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://github.com/psf/black" target="_blank">
|
|
19
|
+
<img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Black">
|
|
20
|
+
</a>
|
|
21
|
+
<a href="https://pycqa.github.io/isort/" target="_blank">
|
|
22
|
+
<img src="https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336" alt="isort">
|
|
23
|
+
</a>
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
**GitHub**: [https://github.com/IPL-UV/satcube](https://github.com/IPL-UV/satcube) 🌐
|
|
29
|
+
|
|
30
|
+
**PyPI**: [https://pypi.org/project/satcube/](https://pypi.org/project/satcube/) 🛠️
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## **Overview** 📊
|
|
35
|
+
|
|
36
|
+
**satcube** is a Python package designed for efficient management, processing, and analysis of Sentinel-2 satellite image cubes. It allows for downloading, cloud masking, gap filling, and super-resolving Sentinel-2 imagery, as well as creating monthly composites and performing interpolation.
|
|
37
|
+
|
|
38
|
+
## **Key Features** ✨
|
|
39
|
+
- **Satellite image download**: Retrieve Sentinel-2 images from Earth Engine efficiently. 🛰️
|
|
40
|
+
- **Cloud masking**: Automatically remove clouds from Sentinel-2 images. ☁️
|
|
41
|
+
- **Gap filling**: Fill missing data using methods like linear interpolation and histogram matching. 🧩
|
|
42
|
+
- **Super-resolution**: Apply super-resolution models to enhance image quality. 🔍
|
|
43
|
+
- **Monthly composites**: Aggregate images into monthly composites with various statistical methods. 📅
|
|
44
|
+
- **Temporal smoothing**: Smooth reflectance values across time using interpolation techniques. 📈
|
|
45
|
+
## **Installation** ⚙️
|
|
46
|
+
|
|
47
|
+
Install the latest version from PyPI:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install satcube
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## **How to use** 🛠️
|
|
54
|
+
|
|
55
|
+
### **Basic usage: working with sentinel-2 data** 🌍
|
|
56
|
+
|
|
57
|
+
#### **Load libraries**
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import ee
|
|
61
|
+
import satcube
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### **Authenticate and initialize earth engine**
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
ee.Authenticate()
|
|
68
|
+
ee.Initialize(project="ee-csaybar-real")
|
|
69
|
+
```
|
|
70
|
+
#### **Download model weights**
|
|
71
|
+
```python
|
|
72
|
+
outpath = satcube.download_weights(path="weights")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### **Create a satellite dataCube**
|
|
76
|
+
```python
|
|
77
|
+
datacube = satcube.SatCube(
|
|
78
|
+
coordinates=(-77.68598590138802,-8.888223962022263),
|
|
79
|
+
sensor=satcube.Sentinel2(weight_path=outpath, edge_size=384),
|
|
80
|
+
output_dir="wendy01",
|
|
81
|
+
max_workers=12,
|
|
82
|
+
device="cuda",
|
|
83
|
+
)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### **Query and process sentinel-2 data** 🛰️
|
|
88
|
+
|
|
89
|
+
#### **Query the sentinel-2 image collection**
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
# Query the Sentinel-2 image collection
|
|
93
|
+
table_query = datacube.metadata_s2()
|
|
94
|
+
|
|
95
|
+
# Filter images based on cloud cover and remove duplicates
|
|
96
|
+
table_query_subset = table_query[table_query["cs_cdf"] > 0.30]
|
|
97
|
+
table_query_subset = table_query_subset.drop_duplicates(subset="img_date")
|
|
98
|
+
mgrs_tile_max = table_query_subset["mgrs_title"].value_counts().idxmax()
|
|
99
|
+
table_query_subset = table_query_subset[table_query_subset["mgrs_title"] == mgrs_tile_max]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### **Download sentinel-2 images**
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
table_download = datacube.download_s2_image(table_query_subset)
|
|
106
|
+
```
|
|
107
|
+
#### **Cloud masking**
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
# Remove clouds from the images
|
|
111
|
+
table_nocloud = datacube.cloudmasking_s2(table_download)
|
|
112
|
+
table_nocloud = table_nocloud[table_nocloud["cloud_cover"] < 0.75]
|
|
113
|
+
table_nocloud.reset_index(drop=True, inplace=True)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### **Gap filling**
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
# Fill missing data in the images
|
|
120
|
+
table_nogaps = datacube.gapfilling_s2(table_nocloud)
|
|
121
|
+
table_nogaps = table_nogaps[table_nogaps["match_error"] < 0.1]
|
|
122
|
+
```
|
|
123
|
+
### **Monthly composites and image smoothing 📅**
|
|
124
|
+
|
|
125
|
+
#### **Create monthly composites**
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
# Generate monthly composites
|
|
129
|
+
table_composites = datacube.monthly_composites_s2(
|
|
130
|
+
table_nogaps, agg_method="median", date_range=("2016-01-01", "2024-07-31")
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### **Interpolate missing data**
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
# Interpolate missing months if necessary
|
|
138
|
+
table_interpolate = datacube.interpolate_s2(table=table_composites)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### **Smooth reflectance values**
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
# Smooth reflectance values across time
|
|
145
|
+
table_smooth = datacube.smooth_s2(table=table_interpolate)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### **Super-resolution and visualization** 📐
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
#### **Super-resolution**
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# Apply super-resolution to the image cube
|
|
156
|
+
# table_final = datacube.super_s2(table_smooth)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
#### **Display images**
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# Display the images from the data cube
|
|
164
|
+
datacube.display_images(table=table_smooth)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### **Create a GIF**
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
# !apt-get install imagemagick
|
|
171
|
+
import os
|
|
172
|
+
os.system("convert -delay 20 -loop 0 wendy01/z_s2_07_smoothed_png/temp_07*.png animation.gif")
|
|
173
|
+
|
|
174
|
+
from IPython.display import Image
|
|
175
|
+
Image(filename='animation.gif', width=500)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
<p align="center">
|
|
179
|
+
<img src="https://huggingface.co/datasets/JulioContrerasH/DataMLSTAC/resolve/main/gif_satcube.gif" width="100%">
|
|
180
|
+
</p>
|
|
181
|
+
|
|
182
|
+
#### **Smooth reflectance values**
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
# Smooth reflectance values across time
|
|
186
|
+
table_smooth = datacube.smooth_s2(table=table_interpolate)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## **Supported features and filters** ✨
|
|
190
|
+
|
|
191
|
+
- **Cloud masking:** Efficient removal of clouds from satellite images.
|
|
192
|
+
- **Resampling methods:** Various methods for resampling and aligning imagery.
|
|
193
|
+
- **Super-resolution:** ONNX-based models for improving image resolution.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "satcube"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = "A Python package to create cloud-free monthly composites by fusing Landsat and Sentinel-2 data."
|
|
5
|
+
authors = ["Cesar Aybar <fcesar.aybar@uv.es>"]
|
|
6
|
+
repository = "https://github.com/IPL-UV/satcube"
|
|
7
|
+
documentation = "https://ipl-uv.github.io/satcube/"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
packages = [{ include = "satcube" }]
|
|
10
|
+
|
|
11
|
+
[tool.poetry.dependencies]
|
|
12
|
+
python = ">=3.10,<4.0"
|
|
13
|
+
cubexpress = ">=0.1.2"
|
|
14
|
+
mlstac = ">=0.5.0"
|
|
15
|
+
fastcubo = ">=0.0.999"
|
|
16
|
+
satalign = ">=0.0.999"
|
|
17
|
+
torch = ">=2.0.0"
|
|
18
|
+
pandas = ">=2.0.0"
|
|
19
|
+
pydantic = ">=2.8.0"
|
|
20
|
+
earthengine-api = ">=0.1.4.0"
|
|
21
|
+
numpy = ">=1.25.0"
|
|
22
|
+
rasterio = ">=1.2.0"
|
|
23
|
+
requests = ">=2.26.0"
|
|
24
|
+
scikit-learn = ">=1.2.0"
|
|
25
|
+
segmentation-models-pytorch = ">=0.3.0"
|
|
26
|
+
xarray = ">=2023.7.0"
|
|
27
|
+
|
|
28
|
+
[tool.poetry.extras]
|
|
29
|
+
full = [
|
|
30
|
+
"torch",
|
|
31
|
+
"segmentation-models-pytorch",
|
|
32
|
+
"scikit-learn",
|
|
33
|
+
"rasterio",
|
|
34
|
+
"earthengine-api",
|
|
35
|
+
"fastparquet"
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
# --- tooling fixes ----------------------------------------------------------
|
|
39
|
+
[tool.mypy]
|
|
40
|
+
files = ["satcube"]
|
|
41
|
+
disallow_untyped_defs = true
|
|
42
|
+
disallow_any_unimported = true
|
|
43
|
+
no_implicit_optional = true
|
|
44
|
+
check_untyped_defs = true
|
|
45
|
+
warn_return_any = true
|
|
46
|
+
warn_unused_ignores = true
|
|
47
|
+
show_error_codes = true
|
|
48
|
+
|
|
49
|
+
[tool.ruff]
|
|
50
|
+
target-version = "py310"
|
|
51
|
+
line-length = 120
|
|
52
|
+
fix = true
|
|
53
|
+
select = ["YTT","S","B","A","C4","T10","SIM","I","C90","E","W","F","PGH","UP","RUF","TRY"]
|
|
54
|
+
ignore = ["E501","E731"]
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Predict cloud masks for Sentinel-2 GeoTIFFs with the SEN2CloudEnsemble model.
|
|
2
|
+
|
|
3
|
+
The callable :pyfunc:`cloud_masking` accepts **either** a single ``.tif`` file
|
|
4
|
+
or a directory tree; in both cases it writes a masked copy of every image (and,
|
|
5
|
+
optionally, the binary mask) to *output*.
|
|
6
|
+
|
|
7
|
+
Example
|
|
8
|
+
-------
|
|
9
|
+
>>> from satcube.cloud_detection import cloud_masking
|
|
10
|
+
>>> cloud_masking("~/s2/input", "~/s2/output", device="cuda")
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import time
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import List
|
|
18
|
+
|
|
19
|
+
import mlstac
|
|
20
|
+
import numpy as np
|
|
21
|
+
import rasterio as rio
|
|
22
|
+
import torch
|
|
23
|
+
|
|
24
|
+
from satcube.utils import DeviceManager, _reset_gpu
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def cloud_masking(
|
|
28
|
+
input: str | Path, # noqa: A002 (shadowing built-in is OK here)
|
|
29
|
+
output: str | Path,
|
|
30
|
+
*,
|
|
31
|
+
tile: int = 512,
|
|
32
|
+
pad: int = 64,
|
|
33
|
+
save_mask: bool = False,
|
|
34
|
+
device: str = "cpu",
|
|
35
|
+
max_pix_cpu: float = 7.0e7,
|
|
36
|
+
) -> List[Path]:
|
|
37
|
+
"""Write cloud-masked Sentinel-2 images.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
input
|
|
42
|
+
Path to a single ``.tif`` file **or** a directory containing them.
|
|
43
|
+
output
|
|
44
|
+
Destination directory (created if missing).
|
|
45
|
+
tile, pad
|
|
46
|
+
Tile size and padding (pixels) when tiling is required.
|
|
47
|
+
save_mask
|
|
48
|
+
If *True*, store the binary mask alongside the masked image.
|
|
49
|
+
device
|
|
50
|
+
Torch device for inference, e.g. ``"cpu"`` or ``"cuda:0"``.
|
|
51
|
+
max_pix_cpu
|
|
52
|
+
Tile images larger than this when running on CPU.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
list[pathlib.Path]
|
|
57
|
+
Paths to the generated masked images.
|
|
58
|
+
"""
|
|
59
|
+
t_start = time.perf_counter()
|
|
60
|
+
|
|
61
|
+
src = Path(input).expanduser().resolve()
|
|
62
|
+
dst_dir = Path(output).expanduser().resolve()
|
|
63
|
+
dst_dir.mkdir(parents=True, exist_ok=True)
|
|
64
|
+
|
|
65
|
+
# Collect files to process -------------------------------------------------
|
|
66
|
+
tif_paths: list[Path]
|
|
67
|
+
if src.is_dir():
|
|
68
|
+
tif_paths = [p for p in src.rglob("*.tif")]
|
|
69
|
+
elif src.is_file() and src.suffix.lower() == ".tif":
|
|
70
|
+
tif_paths = [src]
|
|
71
|
+
src = src.parent # for relative-path bookkeeping below
|
|
72
|
+
else:
|
|
73
|
+
raise ValueError(f"Input must be a .tif or directory, got: {src}")
|
|
74
|
+
|
|
75
|
+
if not tif_paths:
|
|
76
|
+
print(f"[cloud_masking] No .tif files found in {src}")
|
|
77
|
+
return []
|
|
78
|
+
|
|
79
|
+
experiment = mlstac.load("SEN2CloudEnsemble")
|
|
80
|
+
dm = DeviceManager(experiment, init_device=device)
|
|
81
|
+
|
|
82
|
+
masked_paths: list[Path] = []
|
|
83
|
+
|
|
84
|
+
# -------------------------------------------------------------------------
|
|
85
|
+
for idx, tif_path in enumerate(tif_paths, 1):
|
|
86
|
+
rel = tif_path.relative_to(src)
|
|
87
|
+
out_dir = dst_dir / rel.parent
|
|
88
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
89
|
+
|
|
90
|
+
mask_path = out_dir / f"{tif_path.stem}_cloudmask.tif"
|
|
91
|
+
masked_path = out_dir / f"{tif_path.stem}_masked.tif"
|
|
92
|
+
|
|
93
|
+
with rio.open(tif_path) as src_img:
|
|
94
|
+
profile = src_img.profile
|
|
95
|
+
h, w = src_img.height, src_img.width
|
|
96
|
+
|
|
97
|
+
mask_prof = profile.copy()
|
|
98
|
+
mask_prof.update(driver="GTiff", count=1, dtype="uint8", nodata=255)
|
|
99
|
+
|
|
100
|
+
do_tiling = (dm.device == "cuda") or (h * w > max_pix_cpu)
|
|
101
|
+
full_mask = np.full((h, w), 255, np.uint8)
|
|
102
|
+
|
|
103
|
+
t0 = time.perf_counter()
|
|
104
|
+
|
|
105
|
+
# ----------------------- inference -----------------------------------
|
|
106
|
+
if not do_tiling: # full frame
|
|
107
|
+
with rio.open(tif_path) as src_img, torch.inference_mode():
|
|
108
|
+
img = src_img.read().astype(np.float32) / 1e4
|
|
109
|
+
h32, w32 = (h + 31) // 32 * 32, (w + 31) // 32 * 32
|
|
110
|
+
pad_b, pad_r = h32 - h, w32 - w
|
|
111
|
+
tensor = torch.from_numpy(img).unsqueeze(0)
|
|
112
|
+
if pad_b or pad_r:
|
|
113
|
+
tensor = torch.nn.functional.pad(tensor, (0, pad_r, 0, pad_b))
|
|
114
|
+
mask = dm.model(tensor.to(dm.device)).squeeze(0)
|
|
115
|
+
full_mask[:] = mask[..., :h, :w].cpu().numpy().astype(np.uint8)
|
|
116
|
+
else: # tiled
|
|
117
|
+
with rio.open(tif_path) as src_img, torch.inference_mode():
|
|
118
|
+
for y0 in range(0, h, tile):
|
|
119
|
+
for x0 in range(0, w, tile):
|
|
120
|
+
y0r, x0r = max(0, y0 - pad), max(0, x0 - pad)
|
|
121
|
+
y1r, x1r = min(h, y0 + tile + pad), min(w, x0 + tile + pad)
|
|
122
|
+
win = rio.windows.Window(x0r, y0r, x1r - x0r, y1r - y0r)
|
|
123
|
+
|
|
124
|
+
patch = src_img.read(window=win).astype(np.float32) / 1e4
|
|
125
|
+
tensor = torch.from_numpy(patch).unsqueeze(0).to(dm.device)
|
|
126
|
+
mask = dm.model(tensor).squeeze(0).cpu().numpy().astype(np.uint8)
|
|
127
|
+
|
|
128
|
+
y_in0 = pad if y0r else 0
|
|
129
|
+
x_in0 = pad if x0r else 0
|
|
130
|
+
y_in1 = mask.shape[0] - (pad if y1r < h else 0)
|
|
131
|
+
x_in1 = mask.shape[1] - (pad if x1r < w else 0)
|
|
132
|
+
core = mask[y_in0:y_in1, x_in0:x_in1]
|
|
133
|
+
full_mask[y0 : y0 + core.shape[0], x0 : x0 + core.shape[1]] = core
|
|
134
|
+
|
|
135
|
+
# ----------------------- output --------------------------------------
|
|
136
|
+
if save_mask:
|
|
137
|
+
with rio.open(mask_path, "w", **mask_prof) as dst:
|
|
138
|
+
dst.write(full_mask, 1)
|
|
139
|
+
|
|
140
|
+
with rio.open(tif_path) as src_img:
|
|
141
|
+
data = src_img.read()
|
|
142
|
+
img_prof = src_img.profile.copy()
|
|
143
|
+
|
|
144
|
+
masked = data.copy()
|
|
145
|
+
masked[:, full_mask != 0] = 65535
|
|
146
|
+
img_prof.update(dtype="uint16", nodata=65535)
|
|
147
|
+
|
|
148
|
+
with rio.open(masked_path, "w", **img_prof) as dst:
|
|
149
|
+
dst.write(masked)
|
|
150
|
+
|
|
151
|
+
masked_paths.append(masked_path)
|
|
152
|
+
dt = time.perf_counter() - t0
|
|
153
|
+
print(f"[{idx}/{len(tif_paths)}] {rel} → done in {dt:.1f}s")
|
|
154
|
+
|
|
155
|
+
if dm.device == "cuda":
|
|
156
|
+
_reset_gpu()
|
|
157
|
+
|
|
158
|
+
total_time = time.perf_counter() - t_start
|
|
159
|
+
print(f"Processed {len(masked_paths)} image(s) in {total_time:.1f}s.")
|
|
160
|
+
return masked_paths
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import ee
|
|
3
|
+
import cubexpress
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def download_data(
|
|
8
|
+
*, # keyword-only
|
|
9
|
+
lon: float,
|
|
10
|
+
lat: float,
|
|
11
|
+
cloud_max: int = 40,
|
|
12
|
+
edge_size: int = 2_048,
|
|
13
|
+
start: str,
|
|
14
|
+
end: str,
|
|
15
|
+
output: str = "raw",
|
|
16
|
+
scale: int = 10,
|
|
17
|
+
nworks: int = 4,
|
|
18
|
+
mosaic: bool = True,
|
|
19
|
+
auto_init_gee: bool = True,
|
|
20
|
+
) -> pd.DataFrame:
|
|
21
|
+
"""
|
|
22
|
+
Download a Sentinel cube for (lon, lat) and return its metadata.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
lon, lat Center point in degrees.
|
|
27
|
+
cloud_max Max cloud cover (%).
|
|
28
|
+
edge_size Square side length (m).
|
|
29
|
+
start, end YYYY-MM-DD date range.
|
|
30
|
+
output Folder for GeoTIFFs.
|
|
31
|
+
scale Pixel size (m).
|
|
32
|
+
nworks Parallel workers.
|
|
33
|
+
mosaic Merge scenes per date.
|
|
34
|
+
auto_init_gee Call ee.Initialize() if needed.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
pandas.DataFrame
|
|
39
|
+
Scene catalogue used for the request.
|
|
40
|
+
"""
|
|
41
|
+
# EE ready
|
|
42
|
+
if auto_init_gee:
|
|
43
|
+
try:
|
|
44
|
+
ee.Initialize()
|
|
45
|
+
except ee.EEException:
|
|
46
|
+
ee.Authenticate(); ee.Initialize()
|
|
47
|
+
|
|
48
|
+
# Filter scenes
|
|
49
|
+
df = cubexpress.cloud_table(
|
|
50
|
+
lon=lon,
|
|
51
|
+
lat=lat,
|
|
52
|
+
edge_size=edge_size,
|
|
53
|
+
scale=scale,
|
|
54
|
+
cloud_max=cloud_max,
|
|
55
|
+
start=start,
|
|
56
|
+
end=end,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Build requests + ensure dir
|
|
60
|
+
requests = cubexpress.table_to_requestset(df, mosaic=mosaic)
|
|
61
|
+
pathlib.Path(output).mkdir(parents=True, exist_ok=True)
|
|
62
|
+
|
|
63
|
+
# Download cube
|
|
64
|
+
cubexpress.get_cube(requests, output, nworks)
|
|
65
|
+
return df
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import ee
|
|
2
|
+
import cubexpress
|
|
3
|
+
import pathlib
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
def download_data(
|
|
8
|
+
lon: float,
|
|
9
|
+
lat: float,
|
|
10
|
+
cs_cdf: Optional[float] = 0.6,
|
|
11
|
+
buffer_size: Optional[int] = 1280,
|
|
12
|
+
start_date: Optional[str] = "2015-01-01",
|
|
13
|
+
end_date: Optional[str] = datetime.today().strftime('%Y-%m-%d'),
|
|
14
|
+
outfolder: Optional[str] = "raw/"
|
|
15
|
+
) -> pathlib.Path:
|
|
16
|
+
"""
|
|
17
|
+
Download Sentinel-2 imagery data using cubexpress and Earth Engine API.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
lon (float): Longitude of the point of interest.
|
|
21
|
+
lat (float): Latitude of the point of interest.
|
|
22
|
+
cs_cdf (Optional[float]): Cloud mask threshold (default 0.6).
|
|
23
|
+
buffer_size (Optional[int]): Buffer size for image extraction (default 1280).
|
|
24
|
+
start_date (Optional[str]): Start date for image filtering (default "2015-01-01").
|
|
25
|
+
end_date (Optional[str]): End date for image filtering (default today’s date).
|
|
26
|
+
outfolder (Optional[str]): Output folder to save images (default "raw/").
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
pathlib.Path: Path to the folder where the data is stored.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
# Initialize Earth Engine
|
|
33
|
+
ee.Initialize(project="ee-julius013199")
|
|
34
|
+
|
|
35
|
+
# Define point of interest
|
|
36
|
+
point = ee.Geometry.Point([lon, lat])
|
|
37
|
+
|
|
38
|
+
# Filter image collection by location and date
|
|
39
|
+
collection = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") \
|
|
40
|
+
.filterBounds(point) \
|
|
41
|
+
.filterDate(start_date, end_date)
|
|
42
|
+
|
|
43
|
+
# Get image IDs
|
|
44
|
+
image_ids = collection.aggregate_array('system:id').getInfo()
|
|
45
|
+
|
|
46
|
+
# Cloud mask function
|
|
47
|
+
def cloud_mask(image) -> ee.Image:
|
|
48
|
+
"""Apply cloud mask to the image."""
|
|
49
|
+
return image.select('MSK_CLDPRB').lt(20)
|
|
50
|
+
|
|
51
|
+
# Apply cloud mask
|
|
52
|
+
collection = collection.map(cloud_mask)
|
|
53
|
+
|
|
54
|
+
# Generate geotransform for cubexpress
|
|
55
|
+
geotransform = cubexpress.lonlat2rt(lon=lon, lat=lat, edge_size=buffer_size, scale=10)
|
|
56
|
+
|
|
57
|
+
# Prepare requests for cubexpress
|
|
58
|
+
requests = [
|
|
59
|
+
cubexpress.Request(
|
|
60
|
+
id=f"s2test_{i}",
|
|
61
|
+
raster_transform=geotransform,
|
|
62
|
+
bands=["B4", "B3", "B2"], # RGB bands
|
|
63
|
+
image=ee.Image(image_id).divide(10000) # Adjust image scaling
|
|
64
|
+
)
|
|
65
|
+
for i, image_id in enumerate(image_ids)
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
# Create request set
|
|
69
|
+
cube_requests = cubexpress.RequestSet(requestset=requests)
|
|
70
|
+
|
|
71
|
+
# Set output folder
|
|
72
|
+
output_path = pathlib.Path(outfolder)
|
|
73
|
+
|
|
74
|
+
# Download the data
|
|
75
|
+
cubexpress.getcube(
|
|
76
|
+
request=cube_requests,
|
|
77
|
+
output_path=output_path,
|
|
78
|
+
nworkers=4,
|
|
79
|
+
max_deep_level=5
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return output_path
|
|
@@ -7,7 +7,7 @@ import pandas as pd
|
|
|
7
7
|
import torch
|
|
8
8
|
|
|
9
9
|
from satcube.dataclass import Sensor
|
|
10
|
-
from satcube.
|
|
10
|
+
from satcube.utils_old import (aligned_s2, cloudmasking_s2, display_images,
|
|
11
11
|
gapfilling_s2, intermediate_process, interpolate_s2,
|
|
12
12
|
metadata_s2, monthly_composites_s2, smooth_s2, super_s2)
|
|
13
13
|
|
|
@@ -252,7 +252,7 @@ class SatCube:
|
|
|
252
252
|
out_table["folder"] = out_folder
|
|
253
253
|
|
|
254
254
|
return out_table
|
|
255
|
-
|
|
255
|
+
|
|
256
256
|
def monthly_composites_s2(
|
|
257
257
|
self,
|
|
258
258
|
table: Optional[pd.DataFrame],
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import gc
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
import torch
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _reset_gpu() -> None:
|
|
10
|
+
"""Release CUDA memory and reset allocation statistics.
|
|
11
|
+
|
|
12
|
+
Calling this on a system without a CUDA device is a no-op.
|
|
13
|
+
"""
|
|
14
|
+
torch.cuda.empty_cache()
|
|
15
|
+
torch.cuda.reset_peak_memory_stats()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DeviceManager:
|
|
19
|
+
"""Hold a compiled mlstac model and move it between devices on demand."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, experiment: Any, init_device: str = "cpu") -> None:
|
|
22
|
+
"""
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
experiment
|
|
26
|
+
An mlstac experiment exposing ``compiled_model``.
|
|
27
|
+
init_device
|
|
28
|
+
Device where the model is first compiled, e.g. ``"cpu"`` or
|
|
29
|
+
``"cuda:0"``.
|
|
30
|
+
"""
|
|
31
|
+
self._experiment: Any = experiment
|
|
32
|
+
self.device: Optional[str] = None
|
|
33
|
+
self.model: Optional[torch.nn.Module] = None
|
|
34
|
+
self.switch(init_device)
|
|
35
|
+
|
|
36
|
+
def switch(self, new_device: str) -> torch.nn.Module:
|
|
37
|
+
"""Return a model compiled for *new_device*, recompiling if needed.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
new_device
|
|
42
|
+
Target device identifier.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
torch.nn.Module
|
|
47
|
+
The model resident on *new_device*.
|
|
48
|
+
|
|
49
|
+
Raises
|
|
50
|
+
------
|
|
51
|
+
AssertionError
|
|
52
|
+
If *new_device* requests CUDA but no GPU is available.
|
|
53
|
+
"""
|
|
54
|
+
if new_device == self.device:
|
|
55
|
+
return self.model # type: ignore[return-value]
|
|
56
|
+
|
|
57
|
+
if self.model is not None:
|
|
58
|
+
del self.model
|
|
59
|
+
gc.collect()
|
|
60
|
+
|
|
61
|
+
if self.device == "cuda":
|
|
62
|
+
_reset_gpu()
|
|
63
|
+
|
|
64
|
+
if new_device == "cuda":
|
|
65
|
+
assert torch.cuda.is_available(), "CUDA device not detected"
|
|
66
|
+
|
|
67
|
+
print(f"→ Compiling model on {new_device} …")
|
|
68
|
+
self.model = self._experiment.compiled_model(device=new_device, mode="max")
|
|
69
|
+
self.device = new_device
|
|
70
|
+
return self.model
|
satcube-0.1.0/PKG-INFO
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: satcube
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: A Python package to create cloud-free monthly composites by fusing Landsat and Sentinel-2 data.
|
|
5
|
-
Home-page: https://github.com/IPL-UV/satcube
|
|
6
|
-
Author: Cesar Aybar
|
|
7
|
-
Author-email: fcesar.aybar@uv.es
|
|
8
|
-
Requires-Python: >=3.10,<4.0
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
-
Requires-Dist: earthengine-api (>=0.1.4.0)
|
|
12
|
-
Requires-Dist: fastcubo (>=0.0.999)
|
|
13
|
-
Requires-Dist: matplotlib (>=3.7.0)
|
|
14
|
-
Requires-Dist: numpy (>=1.25.0)
|
|
15
|
-
Requires-Dist: pandas (>=2.0.0)
|
|
16
|
-
Requires-Dist: phicloudmask (>=0.0.2)
|
|
17
|
-
Requires-Dist: pydantic (>=2.8.0)
|
|
18
|
-
Requires-Dist: rasterio (>=1.2.0)
|
|
19
|
-
Requires-Dist: requests (>=2.26.0)
|
|
20
|
-
Requires-Dist: satalign (>=0.0.999)
|
|
21
|
-
Requires-Dist: scikit-learn (>=1.2.0)
|
|
22
|
-
Requires-Dist: segmentation-models-pytorch (>=0.2.0)
|
|
23
|
-
Requires-Dist: torch (>=2.0.0)
|
|
24
|
-
Requires-Dist: xarray (>=2023.7.0)
|
|
25
|
-
Project-URL: Documentation, https://ipl-uv.github.io/satcube/
|
|
26
|
-
Project-URL: Repository, https://github.com/IPL-UV/satcube
|
|
27
|
-
Description-Content-Type: text/markdown
|
|
28
|
-
|
|
29
|
-
# satcube
|
|
30
|
-
|
|
31
|
-
[colab code](https://colab.research.google.com/drive/1)
|
satcube-0.1.0/README.md
DELETED
satcube-0.1.0/pyproject.toml
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "satcube"
|
|
3
|
-
version = "0.1.0"
|
|
4
|
-
description = "A Python package to create cloud-free monthly composites by fusing Landsat and Sentinel-2 data."
|
|
5
|
-
authors = ["Cesar Aybar <fcesar.aybar@uv.es>"]
|
|
6
|
-
repository = "https://github.com/IPL-UV/satcube"
|
|
7
|
-
documentation = "https://ipl-uv.github.io/satcube/"
|
|
8
|
-
readme = "README.md"
|
|
9
|
-
packages = [
|
|
10
|
-
{include = "satcube"}
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
[tool.poetry.dependencies]
|
|
14
|
-
python = ">=3.10,<4.0"
|
|
15
|
-
fastcubo = ">=0.0.999"
|
|
16
|
-
torch = ">=2.0.0"
|
|
17
|
-
pandas = ">=2.0.0"
|
|
18
|
-
pydantic = ">=2.8.0"
|
|
19
|
-
earthengine-api = ">=0.1.4.0"
|
|
20
|
-
matplotlib = ">=3.7.0"
|
|
21
|
-
numpy = ">=1.25.0"
|
|
22
|
-
phicloudmask = ">=0.0.2"
|
|
23
|
-
rasterio = ">=1.2.0"
|
|
24
|
-
requests = ">=2.26.0"
|
|
25
|
-
satalign = ">=0.0.999"
|
|
26
|
-
scikit-learn = ">=1.2.0"
|
|
27
|
-
segmentation-models-pytorch = ">=0.2.0"
|
|
28
|
-
xarray = ">=2023.7.0"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
[tool.poetry.group.dev.dependencies]
|
|
32
|
-
pytest = "^7.2.0"
|
|
33
|
-
pytest-cov = "^4.0.0"
|
|
34
|
-
deptry = "^0.12.0"
|
|
35
|
-
mypy = "^1.5.1"
|
|
36
|
-
pre-commit = "^3.4.0"
|
|
37
|
-
tox = "^4.11.1"
|
|
38
|
-
|
|
39
|
-
[tool.poetry.group.docs.dependencies]
|
|
40
|
-
mkdocs = "^1.4.2"
|
|
41
|
-
mkdocs-material = "^9.2.7"
|
|
42
|
-
mkdocstrings = {extras = ["python"], version = "^0.23.0"}
|
|
43
|
-
|
|
44
|
-
[build-system]
|
|
45
|
-
requires = ["poetry-core>=1.0.0"]
|
|
46
|
-
build-backend = "poetry.core.masonry.api"
|
|
47
|
-
|
|
48
|
-
[tool.mypy]
|
|
49
|
-
files = ["satcube"]
|
|
50
|
-
disallow_untyped_defs = "True"
|
|
51
|
-
disallow_any_unimported = "True"
|
|
52
|
-
no_implicit_optional = "True"
|
|
53
|
-
check_untyped_defs = "True"
|
|
54
|
-
warn_return_any = "True"
|
|
55
|
-
warn_unused_ignores = "True"
|
|
56
|
-
show_error_codes = "True"
|
|
57
|
-
|
|
58
|
-
[tool.pytest.ini_options]
|
|
59
|
-
testpaths = ["tests"]
|
|
60
|
-
|
|
61
|
-
[tool.ruff]
|
|
62
|
-
target-version = "py37"
|
|
63
|
-
line-length = 120
|
|
64
|
-
fix = true
|
|
65
|
-
select = [
|
|
66
|
-
# flake8-2020
|
|
67
|
-
"YTT",
|
|
68
|
-
# flake8-bandit
|
|
69
|
-
"S",
|
|
70
|
-
# flake8-bugbear
|
|
71
|
-
"B",
|
|
72
|
-
# flake8-builtins
|
|
73
|
-
"A",
|
|
74
|
-
# flake8-comprehensions
|
|
75
|
-
"C4",
|
|
76
|
-
# flake8-debugger
|
|
77
|
-
"T10",
|
|
78
|
-
# flake8-simplify
|
|
79
|
-
"SIM",
|
|
80
|
-
# isort
|
|
81
|
-
"I",
|
|
82
|
-
# mccabe
|
|
83
|
-
"C90",
|
|
84
|
-
# pycodestyle
|
|
85
|
-
"E", "W",
|
|
86
|
-
# pyflakes
|
|
87
|
-
"F",
|
|
88
|
-
# pygrep-hooks
|
|
89
|
-
"PGH",
|
|
90
|
-
# pyupgrade
|
|
91
|
-
"UP",
|
|
92
|
-
# ruff
|
|
93
|
-
"RUF",
|
|
94
|
-
# tryceratops
|
|
95
|
-
"TRY",
|
|
96
|
-
]
|
|
97
|
-
ignore = [
|
|
98
|
-
# LineTooLong
|
|
99
|
-
"E501",
|
|
100
|
-
# DoNotAssignLambda
|
|
101
|
-
"E731",
|
|
102
|
-
]
|
|
103
|
-
|
|
104
|
-
[tool.ruff.format]
|
|
105
|
-
preview = true
|
|
106
|
-
|
|
107
|
-
[tool.coverage.report]
|
|
108
|
-
skip_empty = true
|
|
109
|
-
|
|
110
|
-
[tool.coverage.run]
|
|
111
|
-
branch = true
|
|
112
|
-
source = ["satcube"]
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
[tool.ruff.per-file-ignores]
|
|
116
|
-
"tests/*" = ["S101"]
|
satcube-0.1.0/setup.py
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from setuptools import setup
|
|
3
|
-
|
|
4
|
-
packages = \
|
|
5
|
-
['satcube']
|
|
6
|
-
|
|
7
|
-
package_data = \
|
|
8
|
-
{'': ['*']}
|
|
9
|
-
|
|
10
|
-
install_requires = \
|
|
11
|
-
['earthengine-api>=0.1.4.0',
|
|
12
|
-
'fastcubo>=0.0.999',
|
|
13
|
-
'matplotlib>=3.7.0',
|
|
14
|
-
'numpy>=1.25.0',
|
|
15
|
-
'pandas>=2.0.0',
|
|
16
|
-
'phicloudmask>=0.0.2',
|
|
17
|
-
'pydantic>=2.8.0',
|
|
18
|
-
'rasterio>=1.2.0',
|
|
19
|
-
'requests>=2.26.0',
|
|
20
|
-
'satalign>=0.0.999',
|
|
21
|
-
'scikit-learn>=1.2.0',
|
|
22
|
-
'segmentation-models-pytorch>=0.2.0',
|
|
23
|
-
'torch>=2.0.0',
|
|
24
|
-
'xarray>=2023.7.0']
|
|
25
|
-
|
|
26
|
-
setup_kwargs = {
|
|
27
|
-
'name': 'satcube',
|
|
28
|
-
'version': '0.1.0',
|
|
29
|
-
'description': 'A Python package to create cloud-free monthly composites by fusing Landsat and Sentinel-2 data.',
|
|
30
|
-
'long_description': '# satcube\n\n[colab code](https://colab.research.google.com/drive/1)',
|
|
31
|
-
'author': 'Cesar Aybar',
|
|
32
|
-
'author_email': 'fcesar.aybar@uv.es',
|
|
33
|
-
'maintainer': 'None',
|
|
34
|
-
'maintainer_email': 'None',
|
|
35
|
-
'url': 'https://github.com/IPL-UV/satcube',
|
|
36
|
-
'packages': packages,
|
|
37
|
-
'package_data': package_data,
|
|
38
|
-
'install_requires': install_requires,
|
|
39
|
-
'python_requires': '>=3.10,<4.0',
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
setup(**setup_kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|