Skip to content

Commit 92752cf

Browse files
Add files via upload
1 parent 2f632bd commit 92752cf

3 files changed

Lines changed: 229 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
**vic_inp_prep.py** --- VIC Input Preparation Python Script\
2+
writen by Vu Trung Dung (dtvu2205@gmail.com)
3+
________________________________________________________________________________
4+
5+
# Overview
6+
7+
This Python script extracts climate data (e.g., precipitation, maximum and minimum temperature, and wind speed) from NetCDF files and formats them as input for the Variable Infiltration Capacity (VIC) model. The script supports selecting a spatial domain, a range of years, and specific locations for output.
8+
________________________________________________________________________________
9+
10+
# Requirements
11+
12+
Python 3.8+\
13+
Python packages:\
14+
os – for file and directory operations\
15+
pandas – for working with tabular data\
16+
xarray – for handling NetCDF climate datasets\
17+
________________________________________________________________________________
18+
19+
# Directory Structure
20+
21+
Your project directory should look like:\
22+
project_dir/\
23+
├─ prec/ # Precipitation NetCDF files (e.g., chirps-v2.0.2022.days_p05.nc)\
24+
├─ tmax/ # Maximum temperature NetCDF files (e.g., era5.02m.tmax.1200.22-23.nc)\
25+
├─ tmin/ # Minimum temperature NetCDF files (e.g., era5.02m.tmin.0000.22-23.nc)\
26+
├─ wind/ # Wind speed NetCDF files (e.g., era5.10m.wind.0600.22-23.nc)\
27+
├─ loc_sample.txt # List of locations for VIC input (tab-separated lon/lat)\
28+
├─ vic_inp/ # Output folder for VIC input files (auto-created by script)\
29+
├─ vic_input_prep.py # Python script
30+
________________________________________________________________________________
31+
32+
# Input Files
33+
34+
Precipitation:\
35+
File example: chirps-v2.0.2022.days_p05.nc\
36+
Variable name: precip
37+
38+
Maximum Temperature:\
39+
File example: era5.02m.tmax.1200.22-23.nc\
40+
Variable name: mx2t
41+
42+
Minimum Temperature:\
43+
File example: era5.02m.tmin.0000.22-23.nc\
44+
Variable name: mn2t
45+
46+
Wind Speed:\
47+
File example: era5.10m.wind.0600.22-23.nc\
48+
Variable name: fg10
49+
50+
Locations file (loc_sample.txt):\
51+
Tab-separated file with columns:\
52+
lon lat\
53+
90.123 15.456\
54+
91.234 16.567
55+
________________________________________________________________________________
56+
57+
# Configuration
58+
59+
At the top of the script, adjust the following parameters:
60+
61+
Spatial domain (latitude and longitude)\
62+
min_lat, max_lat = 15, 35\
63+
min_lon, max_lon = 90, 105
64+
65+
Years to process\
66+
sta_year = 2022\
67+
end_year = 2023
68+
69+
Directories\
70+
prec_dir = "prec"\
71+
tmax_dir = "tmax"\
72+
tmin_dir = "tmin"\
73+
wind_dir = "wind"\
74+
outp_dir = "vic_inp"
75+
________________________________________________________________________________
76+
77+
# How It Works
78+
79+
Data Preprocessing:
80+
81+
- Defines the spatial domain and year range.
82+
83+
- Reads all NetCDF files for precipitation and slices them to the selected domain.
84+
85+
- Reads ERA5 data for temperature and wind, inverting latitude if necessary.
86+
87+
VIC Input Extraction:
88+
89+
- Loops through each location in loc_sample.txt.
90+
91+
- Extracts nearest grid values for precip, tmax, tmin, and wind.
92+
93+
- Converts temperature from Kelvin to Celsius.
94+
95+
- Writes tab-separated files for VIC input in vic_inp/.
96+
97+
Export Output: For each location, a file named gf_<lon>_<lat> is created. Files contain 4 columns: prec, tmax, tmin, wind.
98+
99+
________________________________________________________________________________
100+
101+
# Notes
102+
103+
Ensure that NetCDF variable names match your dataset.
104+
105+
The script automatically creates the output folder if it does not exist.
106+
107+
Locations that do not exactly match the grid will use the nearest-neighbor selection.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
106.5944 15.6064
2+
101.2194 17.7939
3+
103.7194 14.9814
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# LIBRARIES ___________________________________________________________________
2+
import os # For handling file paths
3+
import pandas as pd # For handling tabular data (VIC input/output)
4+
import xarray as xr # For working with NetCDF climate data
5+
6+
# PRE-PROCESSING _____________________________________________________________
7+
8+
# Define the spatial domain you want to process (latitude and longitude range)
9+
min_lat, max_lat = 15, 35
10+
min_lon, max_lon = 90, 105
11+
12+
# Define the range of years to process
13+
sta_year = 2022
14+
end_year = 2023
15+
16+
# Set directories for input data and output VIC files
17+
main_dir = os.getcwd()
18+
prec_dir = os.path.join(main_dir, "prec") # Precipitation data folder
19+
tmax_dir = os.path.join(main_dir, "tmax") # Maximum temperature folder
20+
tmin_dir = os.path.join(main_dir, "tmin") # Minimum temperature folder
21+
wind_dir = os.path.join(main_dir, "wind") # Wind speed folder
22+
outp_dir = os.path.join(main_dir, "vic_inp") # Output folder for VIC files
23+
24+
# Ensure the output directory exists
25+
os.makedirs(outp_dir, exist_ok=True)
26+
27+
# PROCESSING __________________________________________________________________
28+
29+
# -------------------- Precipitation --------------------
30+
print("Processing precipitation data: START")
31+
prec = [] # List to store each year's data
32+
years = range(sta_year, end_year+1)
33+
for year in years:
34+
print("year: "+str(year))
35+
file_name = f"chirps-v2.0.{year}.days_p05.nc" # File naming convention
36+
file_path = os.path.join(prec_dir, file_name)
37+
38+
# Open NetCDF file with xarray
39+
data = xr.open_dataset(file_path)
40+
41+
# Slice the data to the defined spatial domain
42+
sliced_data = data.sel({"latitude": slice(min_lat, max_lat),
43+
"longitude": slice(min_lon, max_lon)})
44+
prec.append(sliced_data)
45+
46+
# Concatenate all years along the time dimension
47+
prec = xr.concat(prec, dim="time")
48+
print("Processing precipitation data: DONE")
49+
50+
# -------------------- Maximum Temperature --------------------
51+
print("Processing maximum temperature data: START")
52+
file_name = "era5.02m.tmax.1200.22-23.nc"
53+
file_path = os.path.join(tmax_dir, file_name)
54+
55+
# Open NetCDF file
56+
data = xr.open_dataset(file_path)
57+
58+
# ERA5 latitude may be from north to south, invert if needed
59+
inverted_data = data.isel({"latitude": slice(None, None, -1)})
60+
61+
# Slice to defined spatial domain
62+
tmax = inverted_data.sel({"latitude": slice(min_lat, max_lat),
63+
"longitude": slice(min_lon, max_lon)})
64+
print("Processing maximum temperature data: DONE")
65+
66+
# -------------------- Minimum Temperature --------------------
67+
print("Processing minimum temperature data: START")
68+
file_name = "era5.02m.tmin.0000.22-23.nc"
69+
file_path = os.path.join(tmin_dir, file_name)
70+
71+
data = xr.open_dataset(file_path)
72+
inverted_data = data.isel({"latitude": slice(None, None, -1)})
73+
tmin = inverted_data.sel({"latitude": slice(min_lat, max_lat),
74+
"longitude": slice(min_lon, max_lon)})
75+
print("Processing minimum temperature data: DONE")
76+
77+
# -------------------- Wind Speed --------------------
78+
print("Processing windspeed data: START")
79+
file_name = "era5.10m.wind.0600.22-23.nc"
80+
file_path = os.path.join(wind_dir, file_name)
81+
82+
data = xr.open_dataset(file_path)
83+
inverted_data = data.isel({"latitude": slice(None, None, -1)})
84+
wind = inverted_data.sel({"latitude": slice(min_lat, max_lat),
85+
"longitude": slice(min_lon, max_lon)})
86+
print("Processing windspeed data: DONE")
87+
88+
# EXTRACTING AND WRITING OUT DATA FOR VIC _____________________________________
89+
print("Extracting and writing out data for VIC: START")
90+
91+
# Load locations (longitude, latitude) where VIC input files are needed
92+
loc = pd.read_csv("loc_sample.txt", sep="\t", header=None, names=["lon", "lat"])
93+
94+
# Loop over each location
95+
for index, row in loc.iterrows():
96+
lon = row['lon']
97+
lat = row['lat']
98+
print("lat: "+str(lat)+", lon: "+str(lon))
99+
100+
# Extract the nearest grid point data for each variable
101+
sel_prec = prec["precip"].sel(latitude=lat, longitude=lon, method="nearest")
102+
sel_tmax = tmax["mx2t"].sel(latitude=lat, longitude=lon, method="nearest")
103+
sel_tmin = tmin["mn2t"].sel(latitude=lat, longitude=lon, method="nearest")
104+
sel_wind = wind["fg10"].sel(latitude=lat, longitude=lon, method="nearest")
105+
106+
# Create a pandas DataFrame with VIC-required variables
107+
df = pd.DataFrame({
108+
"prec": sel_prec.values, # Precipitation (mm/day)
109+
"tmax": sel_tmax.values - 273.15, # Max temperature converted from K to °C
110+
"tmin": sel_tmin.values - 273.15, # Min temperature converted from K to °C
111+
"wind": sel_wind.values # Wind speed (m/s)
112+
})
113+
114+
# Define output filename and write to file (tab-separated, no header/index)
115+
filename = f"gf_{lon:.4f}_{lat:.4f}" # Original format, no .txt extension
116+
file_path = os.path.join(outp_dir, filename)
117+
df.to_csv(file_path, sep="\t", index=False, header=False, float_format="%.6f")
118+
119+
print("Extracting and writing out data for VIC: DONE")

0 commit comments

Comments
 (0)