Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@

## ✨ Key Features

- Modify parameters via the `calibration.cal` file.
- Run SWAT+ simulations.
- Perform sensitivity analysis on model parameters using the [SALib](https://github.com/SALib/SALib) Python package, with support for parallel computation.
- Compute performance metrics using widely adopted indicators and derive Sobol sensitivity indices.
- Modify model parameters through the `calibration.cal` file.
- Run SWAT+ simulations seamlessly.
- Compute performance metrics using widely adopted indicators.
- Perform sensitivity analysis on model parameters using the [SALib](https://github.com/SALib/SALib) Python package, with support for parallel computation; currently, only Sobol sampling and Sobol indices are supported.


## 📥 Install pySWATPlus
Expand Down
36 changes: 21 additions & 15 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,34 @@

## Version 1.2.0 (Month DD, YYYY, not released yet)

- Introduced the `pySWATPlus.DataManager` class with the following methods to support data processing workflows:

- `read_sensitive_dfs`: Reads sensitivity simulation data generated by the `simulation_by_sobol_sample` method in the `pySWATPlus.SensitivityAnalyzer` class.
- `simulated_timeseries_df`: Moved from the `pySWATPlus.SensitivityAnalyzer` class for improved modularity.
- All SWAT+ simulations with modified parameters are now configured through the `calibration.cal` file, eliminating the need to read and modify individual input files.

- Introduced the `pySWATPlus.PerformanceMetrics` class to compute performance metrics between simulated and observed values using the following indicators:

- Nash–Sutcliffe Efficiency
- Kling–Gupta Efficiency
- Mean Squared Error
- Root Mean Squared Error
- Percent Bias
- Mean Absolute Relative Error
- Nash–Sutcliffe Efficiency
- Kling–Gupta Efficiency
- Mean Squared Error
- Root Mean Squared Error
- Percent Bias
- Mean Absolute Relative Error

- Updated the `pySWATPlus.SensitivityAnalyzer` class:

- Added the `sobol_indices` method to the `pySWATPlus.SensitivityAnalyzer`** class for computing Sobol indices using the available indicators in the `pySWATPlus.PerformanceMetrics` class.
- Renamed the method `simulation_by_sobol_sample` to `simulation_by_sample_parameters` to standardize naming and allow different sampling techniques in the future.
- Added `parameter_sensitivity_indices` for computing sensitivity indices using the available indicators in the `pySWATPlus.PerformanceMetrics` class.

- Introduced the `pySWATPlus.DataManager` class with methods to support data processing workflows:

- `read_sensitive_dfs`: Reads sensitivity simulation data generated by the `simulation_by_sobol_sample` method in the `pySWATPlus.SensitivityAnalyzer` class.
- `simulated_timeseries_df`: Moved from the `pySWATPlus.SensitivityAnalyzer` class to improve modularity.

- Added new methods to the `pySWATPlus.TxtinoutReader` class:
- Updated the `pySWATPlus.TxtinoutReader` class:

- `set_simulation_timestep`: Modifies the simulation timestep in the `time.sim` file.
- `set_print_interval`: Modifies the print interval in the `print.prt` file.
- Added `set_simulation_timestep` to modify the simulation timestep in the `time.sim` file.
- Added `set_print_interval` to modify the print interval in the `print.prt` file.
- Added `set_print_period` to modify the print period in the `print.prt` file for recording simulated results.
- Renamed `set_begin_and_end_date` to `set_simulation_period` for better consistency.

- All SWAT+ simulations with modified parameters are now configured through the `calibration.cal` file, eliminating the need to read and modify individual input files.


## Version 1.1.0 (August 26, 2025)
Expand Down
7 changes: 4 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

## ✨ Key Features

- Modify parameters via the `calibration.cal` file.
- Run SWAT+ simulations.
- Perform sensitivity analysis on model parameters using the [SALib](https://github.com/SALib/SALib) Python package, with support for parallel computation.
- Modify model parameters through the `calibration.cal` file.
- Run SWAT+ simulations seamlessly.
- Compute performance metrics using widely adopted indicators.
- Perform sensitivity analysis on model parameters using the [SALib](https://github.com/SALib/SALib) Python package, with support for parallel computation; currently, only Sobol sampling and Sobol indices are supported.


## 📥 Install pySWATPlus
Expand Down
25 changes: 5 additions & 20 deletions docs/userguide/data_analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ print(output)

## Read Sensitivity Simulation Data

The sensitivity analysis performed using the [`simulation_by_sobol_sample`](https://swat-model.github.io/pySWATPlus/api/sensitivity_analyzer/#pySWATPlus.SensitivityAnalyzer.simulation_by_sobol_sample) method generates a file named `sensitivity_simulation.json` within the simulation directory.
This JSON file contains all the information required for Sobol sensitivity analysis, including:
The sensitivity analysis performed using the
[`simulation_by_sample_parameters`](https://swat-model.github.io/pySWATPlus/api/sensitivity_analyzer/#pySWATPlus.SensitivityAnalyzer.simulation_by_sample_parameters) method generates a file named `sensitivity_simulation.json`. This JSON file contains all the information required for sensitivity analysis, including:

- `problem`: Sobol problem definition
- `problem`: Problem definition dictionary
- `sample`: List of generated samples
- `simulation`: Simulated `DataFrame` corresponding to each sample

To retrieve the selected `DataFrame` for all scenarios, use:

```python
output = pySWATPlus.DataManager().read_sensitive_dfs(
sim_file=r"C:\Users\Username\simulation_folder\sensitivity_simulation.json",
sensim_file=r"C:\Users\Username\simulation_folder\sensitivity_simulation.json",
df_name='channel_sd_mon_df',
add_problem=True,
add_sample=True
Expand All @@ -65,7 +65,7 @@ To compute performance metrics for the desired indicators:

```python
output = pySWATPlus.SensitivityAnalyzer().scenario_indicators(
sim_file=r"C:\Users\Username\simulation_folder\sensitivity_simulation.json",
sensim_file=r"C:\Users\Username\simulation_folder\sensitivity_simulation.json",
df_name='channel_sd_mon_df',
sim_col='flo_out',
obs_file=r"C:\Users\Username\observed_folder\discharge_monthly.csv",
Expand All @@ -76,22 +76,7 @@ output = pySWATPlus.SensitivityAnalyzer().scenario_indicators(
)
```

## Sobol Indices

The available indicators can also be used to compute Sobol indices (first, second, and total orders) along with their confidence intervals.

```python
output = pySWATPlus.SensitivityAnalyzer().sobol_indices(
sim_file=r"C:\Users\Username\simulation_folder\sensitivity_simulation.json",
df_name='channel_sd_mon_df',
sim_col='flo_out',
obs_file=r"C:\Users\Username\observed_folder\discharge_monthly.csv",
date_format='%Y-%m-%d',
obs_col='discharge',
indicators=['KGE', 'RMSE'],
json_file=r"C:\Users\Username\data_analysis\sobol_indices.json"
)
```



72 changes: 45 additions & 27 deletions docs/userguide/sensitivity_interface.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Sensitivity Analysis
# Sensitivity Interface

Sensitivity analysis helps quantify how variation in input parameters affects model outputs. This tutorial demonstrates how to perform sensitivity analysis on SWAT+ model parameters.
The parameter sampling is handled by the [SALib](https://github.com/SALib/SALib) Python package using [Sobol](https://doi.org/10.1016/S0378-4754(00)00270-6) sampling from a defined parameter space.
Sensitivity interface helps quantify how variation in input parameters affects model outputs. This tutorial demonstrates how to perform sensitivity analysis on SWAT+ model parameters.


## Configuration Settings
Expand All @@ -15,34 +14,34 @@ import pySWATPlus

# Initialize the project's TxtInOut folder
txtinout_reader = pySWATPlus.TxtinoutReader(
path=r"C:\Users\Username\project\Scenarios\Default\TxtInOut"
tio_dir=r"C:\Users\Username\project\Scenarios\Default\TxtInOut"
)

# Copy required files to an empty custom directory
target_dir = r"C:\Users\Username\custom_folder"
target_dir = txtinout_reader.copy_required_files(
target_dir=target_dir
# Copy required files to an empty simulation directory
sim_dir = r"C:\Users\Username\custom_folder"
sim_dir = txtinout_reader.copy_required_files(
sim_dir=sim_dir
)

# Initialize TxtinoutReader with the custom directory
target_reader = pySWATPlus.TxtinoutReader(
path=target_dir
# Initialize TxtinoutReader with the simulation directory
sim_reader = pySWATPlus.TxtinoutReader(
tio_dir=sim_dir
)

# Disable CSV file generation to save time
target_reader.disable_csv_print()
sim_reader.disable_csv_print()

# Disable daily time series in print.prt (saves time and space)
target_reader.enable_object_in_print_prt(
sim_reader.enable_object_in_print_prt(
obj=None,
daily=False,
monthly=True,
yearly=True,
avann=True
)

# Run a trial simulation to verify expected time series outputs
target_reader.run_swat(
# Set simulation period and run a trial simulation to verify expected time series outputs
sim_reader.run_swat(
begin_date='01-Jan-2010',
end_date='31-Dec-2012',
warmup=1,
Expand All @@ -51,14 +50,16 @@ target_reader.run_swat(
} # enable daily time series for 'channel_sd'
```

## Sobol-Based Interface
## Sensitivity Simulation

This high-level interface builds on the above configuration to run sensitivity simulations using Sobol sampling. It includes:
This high-level interface builds on the above configuration to run sensitivity simulations using sampling, powered by the [SALib](https://github.com/SALib/SALib) Python package.
Currently, it supports [Sobol](https://doi.org/10.1016/S0378-4754(00)00270-6) sampling from a defined parameter space. The interface provides:

- Automatic generation of samples for the parameter space
- Parallel computation to accelerate simulations
- Output extraction with filtering options
- Structured export of results for downstream analysis

- Automatic generation of Sobol samples for the parameter space
- Parallel computation to speed up simulations
- Output extraction with filtering options
- Structured export of results for downstream analysis

```python
# Sensitivity parameter space
Expand All @@ -78,7 +79,7 @@ parameters = [
]

# Target data extraction from sensitivity simulation
simulation_data = {
extract_data = {
'channel_sdmorph_yr.txt': {
'has_units': True,
'ref_day': 15,
Expand All @@ -97,13 +98,30 @@ simulation_data = {

# Sensitivity simulation
if __name__ == '__main__':
output = pySWATPlus.SensitivityAnalyzer().simulation_by_sobol_sample(
output = pySWATPlus.SensitivityAnalyzer().simulation_by_sample_parameters(
parameters=parameters,
sample_number=1,
simulation_folder=r"C:\Users\Username\simulation_folder",
txtinout_folder=target_dir,
simulation_data=simulation_data,
clean_setup=True
sensim_dir=r"C:\Users\Username\simulation_folder",
txtinout_folder=sim_dir,
extract_data=extract_data
)
print(output)
```

## Sensitivity Indices

Sensitivity indices (first, second, and total orders) are computed using the indicators available in the `pySWATPlus.PerformanceMetrics` class, along with their confidence intervals.


```python
output = pySWATPlus.SensitivityAnalyzer().parameter_sensitivity_indices(
sensim_file=r"C:\Users\Username\simulation_folder\sensitivity_simulation.json",
df_name='channel_sd_mon_df',
sim_col='flo_out',
obs_file=r"C:\Users\Username\observed_folder\discharge_monthly.csv",
date_format='%Y-%m-%d',
obs_col='discharge',
indicators=['KGE', 'RMSE'],
json_file=r"C:\Users\Username\sensitivity_indices.json"
)
```
50 changes: 31 additions & 19 deletions docs/userguide/swatplus_simulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ Once the `TxtInOut` folder is properly configured with the necessary input files
import pySWATPlus

# Replace this with the path to your project's TxtInOut folder
txtinout_folder = r"C:\Users\Username\project\Scenarios\Default\TxtInOut"
txtinout_dir = r"C:\Users\Username\project\Scenarios\Default\TxtInOut"

txtinout_reader = pySWATPlus.TxtinoutReader(
path=txtinout_folder
tio_dir=txtinout_dir
)
```

Expand All @@ -42,26 +42,26 @@ To keep your original `TxtInOut` folder unchanged, it is recommended to run `SWA

```python
# Replace this with your desired empty custom directory
target_dir = r"C:\Users\Username\custom_folder"
sim_dir = r"C:\Users\Username\custom_folder"

# Ensure the required files are copied to the custom directory
txtinout_reader.copy_required_files(
target_dir=target_dir
sim_dir=sim_dir
)
```

- Initialize `TxtinoutReader` class for the custom directory

```python
target_reader = pySWATPlus.TxtinoutReader(
path=target_dir
sim_reader = pySWATPlus.TxtinoutReader(
tio_dir=sim_dir
)
```

- Run simulation

```python
target_reader.run_swat()
sim_reader.run_swat()
```

## Step-wise Configurations and Simulations
Expand All @@ -74,9 +74,9 @@ The following steps demonstrate how to configure parameters in a custom director

```python
# Update timeline in `time.sim` file
target_reader.set_simulation_period(
sim_reader.set_simulation_period(
begin_date='01-Jan-2012',
end_date='31-Dec-2016',
end_date='31-Dec-2016'
)
```

Expand All @@ -93,7 +93,7 @@ The following steps demonstrate how to configure parameters in a custom director

```python
# Ensure simulation outputs for `channel_sd` object in `print.prt` file
target_reader.enable_object_in_print_prt(
sim_reader.enable_object_in_print_prt(
obj='channel_sd',
daily=False,
monthly=True,
Expand All @@ -102,12 +102,22 @@ The following steps demonstrate how to configure parameters in a custom director
)
```

- Set output print interval within the simulation period:
- Set print interval within the simulation period:

```python
# Set ouput print every other day
target_reader.set_print_interval(
interval=2
# Set print interval in `print.prt` file
sim_reader.set_print_interval(
interval=1
)
```

- Set print period within the simulation timeline to record result in output files:

```python
# Set print period in `print.prt` file
sim_reader.set_print_period(
begin_date='15-Jun-2012',
end_date='15-Jun-2016'
)
```

Expand All @@ -121,7 +131,7 @@ The following steps demonstrate how to configure parameters in a custom director
'value': 0.5
}
]
target_reader.run_swat(
sim_reader.run_swat(
parameters=parameters
)
```
Expand All @@ -148,13 +158,15 @@ parameters = [

# Run SWAT+ simulation from the original `TxtInOut` folder
txtinout_reader.run_swat(
target_dir=r"C:\Users\Username\custom_folder", # mandatory
sim_dir=r"C:\Users\Username\custom_folder", # mandatory
parameters=parameters, # optional
begin_date='01-Jan-2012', # optional
end_date= '31-Dec-2016', # optional
begin_date='01-Jan-2012', # optional
end_date= '31-Dec-2016', # optional
simulation_timestep=0, # optional
warmup=1, # optional
print_prt_control={'channel_sd': {'daily': False}}, # optional
print_begin_date='15-Jun-2012', # optional
print_end_date='15-Jun-2016', # optional
print_interval=1 # optional
)
```

Loading