Skip to content

Commit 2ab1a6d

Browse files
committed
docs: improve README.md
1 parent 1290c34 commit 2ab1a6d

File tree

6 files changed

+157
-55
lines changed

6 files changed

+157
-55
lines changed

README.md

Lines changed: 126 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,136 @@
1-
# Satellite_S5P
2-
### NO2 Data Processing Script
1+
## <div align="center">Satellite_S5P</div>
32

4-
This Python script is designed to process and analyze nitrogen dioxide (NO2) data from satellite observations. Here's a breakdown of its main components:
3+
<div align="center">
54

6-
### Data Extraction:
7-
The script uses the extract_data function to filter and extract relevant NO2 data from a given dataset based on predefined geographical conditions (latitude and longitude ranges) and a quality threshold (qa_value).
5+
![Python](https://img.shields.io/badge/Python-3.12-blue.svg)
6+
![GitHub last commit](https://img.shields.io/github/last-commit/Alex870521/aeroviz?logo=github)
87

9-
### Data Interpolation:
10-
The interp_data function utilizes a KD-tree algorithm to find the nearest neighbors in a 2D array of latitude and longitude. It then performs linear interpolation using the map_coordinates function to estimate NO2 values at specified target coordinates.
8+
</div>
119

12-
### Main Loop:
10+
<div align="center">
11+
<a href="https://github.com/Alex870521"><img src="https://cdn.simpleicons.org/github/0A66C2" width="3%" alt="GitHub"></a>
12+
<span style="margin: 0 1%"></span>
13+
<a href="https://www.linkedin.com/in/Alex870521/"><img src="https://cdn.simpleicons.org/linkedin/0A66C2" width="3%" alt="LinkedIn"></a>
14+
<span style="margin: 0 1%"></span>
15+
<a href="https://medium.com/@alex870521"><img src="https://cdn.simpleicons.org/medium/0A66C2" width="3%" alt="Medium"></a></div>
1316

14-
The script iterates through folders corresponding to different months of a specified year, each containing NetCDF files of satellite observations.
15-
For each NetCDF file, it extracts and interpolates NO2 data and stores the results.
17+
---
1618

17-
### Data Aggregation:
18-
The script aggregates the processed NO2 data from multiple files within a month, calculating the average.
19+
A Python toolkit for retrieving, processing, and visualizing Sentinel-5P satellite data, with a focus on air pollutants like NO₂, CO, SO₂, O₃, and HCHO.
1920

20-
### Output:
21-
The processed NO2 data is stored in NetCDF format, with each file representing a month of observations.
21+
## <div align="center">Features</div>
2222

23-
### Folder Skipping:
24-
The script checks if the output NetCDF file already exists. If it does, it skips processing that particular folder to avoid unnecessary computations.
23+
- Automated data retrieval from Copernicus Open Access Hub
24+
- Advanced data processing with interpolation and quality control
25+
- High-quality visualization of pollutant concentration maps
26+
- Time series analysis capabilities
27+
- Built-in file retention management to prevent storage overflow
2528

26-
### Usage:
27-
The script is designed to be run for a specific year, processing monthly satellite observations of NO2 data and generating NetCDF files for further analysis or visualization.
29+
## <div align="center">Prerequisites</div>
2830

29-
### Dependencies:
30-
The script relies on various Python libraries, including NumPy, xarray, scipy, and netCDF4, for efficient data manipulation and processing.
31-
This script is particularly useful for researchers or analysts working with satellite-derived NO2 data, allowing them to extract, interpolate, and aggregate information for further study.
31+
Before using this toolkit, you need to complete the following steps:
32+
33+
1. **Copernicus Account Setup**:
34+
- Register for a free account at [Copernicus Open Access Hub](https://scihub.copernicus.eu/dhus/#/home)
35+
- Save your username and password for API access
36+
37+
2. **Environment Configuration**:
38+
- Create a `.env` file in the project root directory with your credentials:
39+
```
40+
COPERNICUS_USERNAME=your_username
41+
COPERNICUS_PASSWORD=your_password
42+
```
43+
44+
## <div align="center">Installation</div>
45+
46+
```bash
47+
# Clone the repository
48+
git clone https://github.com/Alex870521/Satellite_S5P.git
49+
50+
# Navigate to the directory
51+
cd Satellite_S5P
52+
53+
# Install required packages
54+
pip install -r requirements.txt
55+
```
56+
57+
## <div align="center">Usage</div>
58+
59+
### Fetching Satellite Data
60+
```python
61+
from src.api.sentinel_api import S5PFetcher
62+
63+
# Initialize fetcher
64+
fetcher = S5PFetcher(max_workers=3)
65+
66+
# Fetch products
67+
products = await fetcher.fetch_data(
68+
file_class='OFFL', # 'OFFL' for offline data, 'NRTI' for near-real-time
69+
file_type='NO2___', # Available types: 'NO2___', 'CO____', 'SO2___', 'O3__PR', 'HCHO__'
70+
start_date='2025-02-20',
71+
end_date='2025-03-06',
72+
boundary=(120, 122, 22, 25),
73+
limit=None
74+
)
75+
76+
# Download products
77+
fetcher.parallel_download(products)
78+
```
79+
80+
Example output:
81+
```
82+
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
83+
│ Fetching sentinel-5p products (NO₂) from 2025-02-20 to 2025-03-06 ... │
84+
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
85+
╭──────────────────────────────────────── Found 7 Products ────────────────────────────────────────╮
86+
│ │
87+
│ Product Information │
88+
│┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓ │
89+
│┃ No. ┃ Time ┃ Name ┃ Size ┃ │
90+
│┡━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩ │
91+
││ 1 │ 2025-02-25T04:54:18 │ S5P_OFFL_L2__NO2____20250225T043243...50226T204825.nc │ 589.88 MB │ │
92+
││ 2 │ 2025-02-24T05:13:14 │ S5P_OFFL_L2__NO2____20250224T045140...50225T210805.nc │ 591.67 MB │ │
93+
││ 3 │ 2025-02-24T03:31:44 │ S5P_OFFL_L2__NO2____20250224T031009...50226T055814.nc │ 593.46 MB │ │
94+
││ 4 │ 2025-02-23T03:50:40 │ S5P_OFFL_L2__NO2____20250223T032906...50224T235016.nc │ 593.48 MB │ │
95+
││ 5 │ 2025-02-22T04:09:37 │ S5P_OFFL_L2__NO2____20250222T034802...50223T200228.nc │ 590.79 MB │ │
96+
││ 6 │ 2025-02-21T04:28:32 │ S5P_OFFL_L2__NO2____20250221T040659...50222T202822.nc │ 589.21 MB │ │
97+
││ 7 │ 2025-02-20T04:47:30 │ S5P_OFFL_L2__NO2____20250220T042555...50221T204529.nc │ 564.02 MB │ │
98+
│└─────┴─────────────────────┴───────────────────────────────────────────────────────┴───────────┘ │
99+
│ │
100+
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
101+
```
102+
103+
### Processing Data
104+
```python
105+
from src.processing.data_processor import S5Processor
106+
107+
# Initialize processor
108+
processor = S5Processor(
109+
interpolation_method='rbf',
110+
resolution=(5.5, 3.5), # Resolution in km
111+
mask_qc_value=0.5 # Quality control threshold
112+
)
113+
114+
# Process data
115+
processor.process_each_data(
116+
file_class='OFFL',
117+
file_type='NO2___',
118+
start_date='2025-02-20',
119+
end_date='2025-03-06',
120+
)
121+
```
122+
123+
## <div align="center">Data Description</div>
124+
125+
### NO2 Data Processing
126+
This toolkit processes nitrogen dioxide (NO2) and other pollutant data from satellite observations with these key features:
127+
128+
- **Quality Control**: Filters out low-quality measurements
129+
- **Spatial Interpolation**: Converts sparse satellite readings to regular grid
130+
- **Temporal Aggregation**: Daily, weekly, and monthly averages
131+
- **Visualization**: Generates high-quality maps and time series plots
132+
- **Data Export**: Creates NetCDF files compatible with other analysis tools
133+
134+
## <div align="center">Contact</div>
135+
136+
For bug reports and feature requests please visit [GitHub Issues](https://github.com/Alex870521/Satellite_S5P/issues).

main.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ async def fetch_data(file_class: ClassInput,
2222
"""下載數據的工作流程"""
2323
try:
2424
rich_print(
25-
f"正在獲取 sentinel-5p 衛星數據 ({PRODUCT_CONFIGS[file_type].display_name}) from {start_date} to {end_date} ...")
25+
f"Fetching sentinel-5p products ({PRODUCT_CONFIGS[file_type].display_name}) from {start_date} to {end_date} ...")
2626

2727
fetcher = S5PFetcher(max_workers=3)
2828

@@ -36,18 +36,18 @@ async def fetch_data(file_class: ClassInput,
3636
)
3737

3838
if products:
39-
if rich_print("是否要下載數據?", confirm=True):
39+
if rich_print("Do you want to download data?", confirm=True):
4040
rich_print(
41-
f"開始下載 sentinel-5p 衛星數據 ({PRODUCT_CONFIGS[file_type].display_name}) from {start_date} to {end_date} ...")
41+
f"Start download sentinel-5p products ({PRODUCT_CONFIGS[file_type].display_name}) from {start_date} to {end_date} ...")
4242
fetcher.parallel_download(products)
43-
rich_print("數據下載完成!")
43+
rich_print("Data download completed!")
4444
else:
45-
rich_print("已取消下載操作")
45+
rich_print("Download canceled")
4646
else:
47-
rich_print("找不到符合條件的數據")
47+
rich_print("No data matching the criteria was found")
4848

4949
except Exception as e:
50-
error_message = f"下載數據失敗: {str(e)}"
50+
error_message = f"Failed to download data: {str(e)}"
5151
rich_print(error_message)
5252
logger.error(error_message)
5353

@@ -58,9 +58,9 @@ def process_data(file_class: ClassInput,
5858
end_date: str | datetime):
5959
"""處理數據的工作流程"""
6060
try:
61-
if rich_print("是否要處理數據?", confirm=True):
61+
if rich_print("Do you want to process the data?", confirm=True):
6262
rich_print(
63-
f"正在處理 sentinel-5p 衛星數據 ({PRODUCT_CONFIGS[file_type].display_name}) from {start_date} to {end_date} ...")
63+
f"Processing sentinel-5p products ({PRODUCT_CONFIGS[file_type].display_name}) from {start_date} to {end_date} ...")
6464

6565
processor = S5Processor(
6666
interpolation_method='rbf',
@@ -75,12 +75,12 @@ def process_data(file_class: ClassInput,
7575
end_date=end_date,
7676
)
7777

78-
rich_print("數據完成處理")
78+
rich_print("Data processing completed")
7979
else:
80-
rich_print("已取消處理操作")
80+
rich_print("Processing canceled")
8181

8282
except Exception as e:
83-
error_message = f"處理數據失敗: {str(e)}"
83+
error_message = f"Failed to process data: {str(e)}"
8484
rich_print(error_message)
8585
logger.error(error_message)
8686

@@ -89,15 +89,15 @@ def main():
8989
# 步驟:
9090
# 1. 前往src.config.settings中更改輸出路徑(硬碟路徑)
9191
# 2. 設定參數
92-
start, end = '2022-01-01', '2024-12-31'
92+
start, end = '2025-02-20', '2025-03-06'
9393
file_class: ClassInput = 'OFFL'
9494
file_type: TypeInput = 'NO2___'
9595

9696
# 3. 設定輸入輸出配置
9797
setup(file_type=file_type, start_date=start, end_date=end)
9898

9999
# 4. 下載數據 (需要有.env 內含 COPERNICUS 帳號密碼才能用)
100-
# asyncio.run(fetch_data(file_class=file_class, file_type=file_type, start_date=start, end_date=end))
100+
asyncio.run(fetch_data(file_class=file_class, file_type=file_type, start_date=start, end_date=end))
101101

102102
# 5. 處理與繪製數據
103103
process_data(file_class=file_class, file_type=file_type, start_date=start, end_date=end)

requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ rioxarray~=0.18.2
1919
imageio~=2.36.0
2020
pillow~=10.4.0
2121
pytest~=8.3.4
22-
tkcalendar~=1.6.1
22+
tkcalendar~=1.6.1
23+
certifi~=2024.8.30
24+
schedule~=1.2.2

run_pipeline.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,7 @@
2525
# 設定輸入輸出配置
2626
setup(file_type='NO2___', start_date=today, end_date=today)
2727

28-
# 設定日誌
29-
logging.basicConfig(
30-
level=logging.INFO,
31-
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
32-
handlers=[
33-
logging.FileHandler(LOGS_DIR / 'satellite_pipeline.log'),
34-
logging.StreamHandler()
35-
]
36-
)
28+
3729
logger = logging.getLogger(__name__)
3830

3931

@@ -117,7 +109,7 @@ def clean_old_files():
117109
retention_manager = FileRetentionManager(retention_days=DATA_RETENTION_DAYS)
118110

119111
# 定義要清理的檔案類型(這裡可以根據實際情況調整)
120-
file_types = ['NO2___', 'SO2___', 'O3__PR', 'HCHO__', 'CO____']
112+
file_types = ['NO2___', 'HCHO__', 'CO____']
121113

122114
# 執行清理,只針對FIGURE_DIR中的檔案
123115
results = retention_manager.clean_satellite_figure_data(BASE_DIR, file_types)
@@ -143,7 +135,7 @@ async def daily_task():
143135
# 設定參數 - 只處理當天的數據
144136
today = datetime.now().strftime('%Y-%m-%d')
145137
file_class: ClassInput = 'NRTI'
146-
file_type: list[TypeInput] = ['NO2___', 'SO2___', 'O3__PR', 'HCHO__', 'CO____']
138+
file_type: list[TypeInput] = ['NO2___', 'HCHO__', 'CO____']
147139

148140
for file_tp in file_type:
149141
# 設定輸入輸出配置

src/api/sentinel_api.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ def __init__(self, max_workers: int = 5):
6666
}
6767

6868
async def fetch_data(self,
69-
file_class: ClassInput,
70-
file_type: TypeInput,
71-
start_date: str,
72-
end_date: str,
73-
boundary: tuple[float, float, float, float] | None = None,
74-
limit: int | None = None,
75-
) -> list[dict]:
69+
file_class: ClassInput,
70+
file_type: TypeInput,
71+
start_date: str,
72+
end_date: str,
73+
boundary: tuple[float, float, float, float] | None = None,
74+
limit: int | None = None,
75+
) -> list[dict]:
7676
"""
7777
擷取數據
7878

src/config/settings.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""API 設定和常數"""
22
from pathlib import Path
3+
import os
4+
import certifi
5+
os.environ['SSL_CERT_FILE'] = certifi.where()
36

47
# API URLs
58
COPERNICUS_TOKEN_URL = "https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token"
@@ -18,7 +21,7 @@
1821
DOWNLOAD_TIMEOUT = 180
1922

2023
# 存儲路徑
21-
BASE_DIR = Path("/Volumes/Transcend/Sentinel-5P")
24+
BASE_DIR = Path("/Users/chanchihyu/DataCenter/Satellite")
2225
RAW_DATA_DIR = BASE_DIR / "raw"
2326
PROCESSED_DATA_DIR = BASE_DIR / "processed"
2427
GEOTIFF_DIR = BASE_DIR / "geotiff"

0 commit comments

Comments
 (0)