Skip to content
Open
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
42 changes: 26 additions & 16 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,36 @@ env:
GITHUB_TOKEN: ${{ secrets.COVERALLS_TOKEN }}

jobs:
source_check:
lint:
name: Linting (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [ '3.12' ]
python-version: [ '3.13' ]

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install black 'isort[colors]<6'
python -m pip install --editable .
python -m pip install --group lint

- name: Linting checks
run: |
black --check src/spotpy
isort --check src/spotpy

build_sdist:
name: sdist on ${{ matrix.os }} with Python ${{ matrix.python-version }}
test_build:
name: Test and build (${{ matrix.os }}, Python ${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand All @@ -50,20 +55,24 @@ jobs:
python-version: [ '3.10', '3.13' ]

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: '0'
persist-credentials: false

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build pytest-cov
python -m pip install --editable .[test]
python -m pip install --group build --group test

- name: Install spotpy with optional dependencies
run: |
python -m pip install --editable ".[database,describe,mpi,plotting]"

- name: Run tests
run: |
Expand All @@ -82,20 +91,21 @@ jobs:
run: |
python -m build

- uses: actions/upload-artifact@v4
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
- uses: actions/upload-artifact@v7
if: (matrix.os == 'ubuntu-latest') && (matrix.python-version == '3.13')
with:
name: dist-sdist
path: dist/

upload_to_pypi:
name: Upload to PyPI/Test PyPI
needs:
- build_sdist
- test_build
if: (github.ref == 'refs/heads/master') || (startsWith(github.ref, 'refs/tags'))
runs-on: ubuntu-latest
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: dist-sdist
path: dist/
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ prune **
graft src/spotpy
graft tests
graft tutorials
include LICENSE README.md pyproject.toml setup.py
include LICENSE README.md pyproject.toml
global-exclude __pycache__ *.py[co]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A Statistical Parameter Optimization Tool for Python
[![Python Versions][pypi-pyv-image]][pypi-pyv-link]
[![License][license-image]][license-link]
[![Coverage Status](https://coveralls.io/repos/github/thouska/spotpy/badge.svg?branch=master)](https://coveralls.io/github/thouska/spotpy?branch=master)
[![DOI](https://zenodo.org/badge/47562322.svg)](https://zenodo.org/badge/latestdoi/47562322)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4075177.svg)](https://doi.org/10.5281/zenodo.4075177)

[pypi-v-image]: https://img.shields.io/pypi/v/spotpy.png
[pypi-v-link]: https://pypi.python.org/pypi/spotpy
Expand Down
56 changes: 36 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
[build-system]
requires = [
"setuptools>=64",
"setuptools_scm[toml]>=6.4",
"setuptools>=80",
"setuptools_scm[toml]>=9.2",
]
build-backend = "setuptools.build_meta"

[dependency-groups]
build = [
"build"
]
lint = [
"black >=26.3.0",
"isort >=8.0.1"
]
test = [
"pytest >=9.0",
"pytest-cov >=7.1.0",
]

[project]
requires-python = ">=3.10"
name = "spotpy"
Expand All @@ -21,7 +34,8 @@ maintainers = [
{name = "Tobias Houska", email = "tobias.houska@umwelt.uni-giessen.de"},
]
readme = "README.md"
license = {file = "LICENSE"}
license = "MIT"
license-files = ["LICENSE"]
dynamic = ["version"]
keywords = [
"Monte Carlo",
Expand All @@ -47,7 +61,6 @@ classifiers = [
"Intended Audience :: End Users/Desktop",
"Intended Audience :: Science/Research",
"Intended Audience :: Education",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Operating System :: Unix",
"Operating System :: Microsoft",
Expand All @@ -66,25 +79,29 @@ classifiers = [
"Topic :: Utilities",
]
dependencies = [
"numpy>=2.0",
"scipy>=1.5.0",
"click >=8.1",
"numpy >=2.0",
"scipy >=1.12.0",
]

[project.optional-dependencies]
plotting = [
"pandas>=1",
"matplotlib>=3",
database = [
"tables"
]
test = [
"pytest-cov>=3",
"numba",
"pathos",
"matplotlib",
"click",
"pandas",
"tables",
"docutils",
describe = [
"docutils"
]
mpi = [
"mpi4py",
"pathos"
]
plotting = [
"pandas >=2.2.0",
"matplotlib >=3.8.0",
]

[project.scripts]
spotpy = "spotpy.cli:cli"

[project.urls]
Changelog = "https://github.com/thouska/spotpy/blob/master/CHANGELOG.md"
Expand All @@ -108,11 +125,10 @@ multi_line_output = 3
[tool.black]
exclude = "_version.py"
target-version = [
"py39",
"py310",
"py311",
"py312",
"py313",
"py313"
]

[tool.coverage]
Expand Down
1 change: 1 addition & 0 deletions src/spotpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

Please cite our paper, if you are using SPOTPY.
"""

from . import algorithms # Contains all the different algorithms implemented in SPOTPY
from . import (
analyser, # Contains some examples to analyse the results of the different algorithms
Expand Down
3 changes: 1 addition & 2 deletions src/spotpy/algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
To reduce dependencies, one may select here just the needed algorithm.
"""


from ._algorithm import _algorithm
from .abc import abc # Artificial Bee Colony
from .dds import dds # Dynamically Dimensioned Search algorithm
Expand All @@ -28,11 +27,11 @@
from .mc import mc # Monte Carlo
from .mcmc import mcmc # Metropolis Markov Chain Monte Carlo
from .mle import mle # Maximum Likelihood Estimation
from .morris import morris # Morris Screening Sensitivity Test
from .nsgaii import (
NSGAII, # A Fast and Elitist Multiobjective Genetic Algorithm: NSGA-II
)
from .padds import padds # Pareto Archived - Dynamicallly Dimensioned Search algorithm
from .rope import rope # RObust Parameter Estimation
from .sa import sa # Simulated annealing
from .sceua import sceua # Shuffled Complex Evolution
from .morris import morris # Morris Screening Sensitivity Test
2 changes: 1 addition & 1 deletion src/spotpy/algorithms/efast.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,4 +564,4 @@ def calc_sensitivity(self, results, dbname, freq="cukier"):
np.savetxt(f, [sens_data], delimiter=",", fmt="%1.5f")

f.close()
return sens_data
return sens_data
6 changes: 2 additions & 4 deletions src/spotpy/algorithms/fast.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,10 @@ def analyze(self, problem, Y, D, parnames, M=4, print_to_console=False):
"""
)
else:
print(
"""
print("""
Error: Number of samples in model output file must be a multiple of D,
where D is the number of parameters in your parameter file.
"""
)
""")
exit()

# Recreate the vector omega used in the sampling
Expand Down
1 change: 1 addition & 0 deletions src/spotpy/algorithms/list_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
This file is part of Statistical Parameter Optimization Tool for Python(SPOTPY).
:author: Tobias Houska
"""

from .. import analyser
from . import _algorithm

Expand Down
48 changes: 32 additions & 16 deletions src/spotpy/algorithms/morris.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ class morris(_algorithm):
This class holds the Morris Screening Sensitivity Test (MORRIS) based on Morris (1991), Campolongo et al (2007) and Ruano et al. (2012):

Morris, M.D., 1991, Factorial Sampling Plans for Preliminary Computational Experiments. Technometrics 33, 161-174.

Campolongo, F., Cariboni, J., & Saltelli, A. 2007. An effective screening design for sensitivity analysis of large
models. Environmental Modelling & Software, 22(10), 1509-1518.

Ruano, M.V., Ribes, J., Seco, A., Ferrer, J., 2012. An improved sampling strategy based on trajectory design for
application of the Morris method to systems with many input factors. Environmental Modelling & Software 37, 103-109.

The presented code is based on SALib
Copyright (C) 2013-2015 Jon Herman and others. Licensed under the GNU Lesser General Public License.
The Sensitivity Analysis Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Expand Down Expand Up @@ -98,18 +98,29 @@ def scale_samples(self, params, bounds):
def matrix(self, bounds, problem, N, M=4):
from SALib.sample import morris as morris_sample

X = morris_sample.sample(problem, N=N, num_levels=M,
optimal_trajectories=None, # set int to use Campolongo opt design
local_optimization=True, # Ruano-style distance improvement
seed=123)
X = morris_sample.sample(
problem,
N=N,
num_levels=M,
optimal_trajectories=None, # set int to use Campolongo opt design
local_optimization=True, # Ruano-style distance improvement
seed=123,
)

self.scale_samples(X, bounds)
return X

def analyze(self, problem, X, Y, num_levels=4, print_to_console=False):
from SALib.analyze import morris as morris_analyze
Si = morris_analyze.analyze(problem, X, Y, conf_level=0.95, num_levels=num_levels,
print_to_console=print_to_console)

Si = morris_analyze.analyze(
problem,
X,
Y,
conf_level=0.95,
num_levels=num_levels,
print_to_console=print_to_console,
)
return Si

def sample(self, repetitions, num_levels=4):
Expand All @@ -132,7 +143,6 @@ def sample(self, repetitions, num_levels=4):
# distribution
parmin, parmax = self.parameter()["minbound"], self.parameter()["maxbound"]


bounds = []
for i in range(len(parmin)):
bounds.append([parmin[i], parmax[i]])
Expand All @@ -142,14 +152,14 @@ def sample(self, repetitions, num_levels=4):
# Assume df_params from your existing script
# columns: name, change_type, lower_bound, upper_bound, subbasins
problem = {
'num_vars': len(names),
'names': names.tolist(), # or name_spotpy if you expanded names
'bounds': bounds
"num_vars": len(names),
"names": names.tolist(), # or name_spotpy if you expanded names
"bounds": bounds,
#'bounds': self.parameter()[['minbound','maxbound']].values.tolist()
}

k = problem['num_vars']
N = 15 # number of trajectories (adjust for robustness vs runtime)
k = problem["num_vars"]
N = 15 # number of trajectories (adjust for robustness vs runtime)
num_levels = num_levels # classic Morris grid

# Create an Matrix to store the parameter sets
Expand Down Expand Up @@ -179,10 +189,16 @@ def sample(self, repetitions, num_levels=4):
try:
data = self.datawriter.getdata()
# this is likely to crash if database does not assign name 'like1'
Si = self.analyze(problem, Matrix, data["like1"], num_levels=num_levels, print_to_console=False)
Si = self.analyze(
problem,
Matrix,
data["like1"],
num_levels=num_levels,
print_to_console=False,
)
# Si = self.analyze(
# bounds, data["like1"], len(bounds), names, M=num_levels, print_to_console=True
# )
print(Si['mu_star'])
print(Si["mu_star"])
except AttributeError: # Happens if no database was assigned
pass
2 changes: 1 addition & 1 deletion src/spotpy/algorithms/padds.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ def calc_initial_pareto_front(self, its):
]
)
else:
(self.pareto_front, dominance_flag) = nd_check(
self.pareto_front, dominance_flag = nd_check(
self.pareto_front,
self.obj_func_current,
self.parameter_current.copy(),
Expand Down
1 change: 1 addition & 0 deletions src/spotpy/algorithms/rope.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
This file is part of Statistical Parameter Optimization Tool for Python(SPOTPY).
:author: Tobias Houska and Alejandro Chamorro-Chavez
"""

import random
import time

Expand Down
Loading
Loading