Developer Notes
This page documents some of the workflows specific to RdTools development.
Installing RdTools source code
To make changes to RdTools, run the test suite, or build the documentation locally, you'll need to have a local copy of the git repository. Installing RdTools using pip will install a condensed version that doesn't include the full source code. To get the full source code, you'll need to clone the RdTools source repository from Github with e.g.
git clone https://github.com/NatLabRockies/rdtools.git
from the command line, or using a GUI git client like Github Desktop. This will clone the entire git repository onto your computer.
Installing RdTools dependencies
RdTools uses pixi for reproducible environment management.
Pixi creates isolated environments from the lockfile (pixi.lock), ensuring
every contributor gets the exact same package versions.
To install pixi, follow the instructions at https://pixi.sh.
Once pixi is installed, navigate to the repository root and run:
pixi install
This creates the default environment with RdTools and its core dependencies.
Pixi environments are stored locally in .pixi/ (gitignored) and do not
interfere with other Python environments on your system.
To run a command inside a pixi environment, use pixi run:
pixi run python -c "import rdtools; print(rdtools.__version__)"
Available pixi environments
RdTools defines several pixi environments in pyproject.toml:
core — bare RdTools with core dependencies only (Python 3.13)
default — RdTools + notebook extras for regular users (Python 3.13)
dev — notebooks + test extras combined (Python 3.13); recommended for day-to-day development (alias for dev-py313)
dev-py310 through dev-py314 — full dev environment pinned to a specific Python version
dev-min — test-only environment with minimum supported dependency versions (Python 3.10)
For most contributors, the dev environment is the best starting point because it includes everything needed to run the test suite, launch Jupyter notebooks, and check code style:
pixi install -e dev
pixi run -e dev test # run the test suite
pixi run -e dev lab # launch Jupyter Lab
To test against a specific Python version:
pixi run -e dev-py310 test
Updating pixi environments
When pyproject.toml changes (e.g. a dependency is added, removed, or its
version constraint is updated), the pixi lockfile must be regenerated:
Re-solve dependencies — run
pixi updatefrom the repository root. This re-solves all environments against the currentpyproject.tomlconstraints and writes a newpixi.lock:pixi update
Verify environments install correctly — run
pixi installto re-create thedefaultenvironment from the updated lockfile:pixi install
pixi installon its own only refreshes thedefaultenvironment. To refresh a specific environment (for exampledev), pass-e:pixi install -e dev
To refresh every environment defined in
pyproject.tomlin one go (useful after a lockfile format bump or a broad dependency change), use--all:pixi install --all
Run tests to make sure nothing is broken:
pixi run -e dev test
Commit both files — always commit
pyproject.tomlandpixi.locktogether so that CI and other contributors stay in sync:git add pyproject.toml pixi.lock git commit -m "Update dependencies"
Note
If you only want to update a single package, you can target it:
pixi update numpy. To update packages only within a specific
environment, use pixi update -e dev numpy.
Note
Contributors who pull changes that include an updated pixi.lock
typically only need to run pixi install (which refreshes
default) or pixi install -e dev (if they work in the dev
environment) to pick up the new packages.
Installing without pixi
If you prefer not to use pixi, you can still install RdTools and its dependencies with pip. The packages necessary to run RdTools itself can be installed from PyPI:
pip install rdtools
This will install the latest official release of RdTools. If you want to work with a development version and you have cloned the Github repository to your computer, you can also install RdTools and dependencies by navigating to the repository root, switching to the branch you're interested in, for instance:
git checkout development
and running:
pip install .
This will install based on whatever RdTools branch you have checked out. You
can check what version is currently installed by inspecting
rdtools.__version__:
>>> rdtools.__version__
'1.2.0+188.g5a96bb2'
The hex string at the end represents the hash of the git commit for your installed version.
Installing optional dependencies
RdTools has extra dependencies for running its test suite and building its documentation. These packages aren't necessary for running RdTools itself and are only needed if you want to contribute source code to RdTools.
Note
These will install RdTools along with other packages necessary to build its documentation and run its test suite. We recommend doing this in a virtual environment to keep package installations between projects separate!
With pixi (recommended):
pixi install -e dev # all development dependencies (recommended)
pixi install -e dev-py310 # dev environment with Python 3.10
pixi install -e dev-min # minimum supported dependency versions
With pip:
pip install rdtools[dev] # notebooks + test dependencies
pip install rdtools[test] # test suite dependencies only
pip install rdtools[doc] # documentation dependencies
Or, if your local repository has an updated dependencies list:
pip install .[dev] # notebooks + test dependencies
pip install .[test] # test suite dependencies only
pip install .[doc] # documentation dependencies
Running the test suite
RdTools uses pytest to run its test suite. If you haven't already, install the testing dependencies (Installing optional dependencies).
With pixi
Run the full test suite in the dev environment:
pixi run -e dev test
Run a single test module:
pixi run -e dev pytest rdtools/test/soiling_test.py
Run a single test function:
pixi run -e dev pytest rdtools/test/soiling_test.py::test_soiling_srr
Without pixi
If you installed RdTools and its test dependencies with pip, you can invoke pytest directly:
pytest rdtools/test/
pytest rdtools/test/soiling_test.py
pytest rdtools/test/soiling_test.py::test_soiling_srr
Measuring code coverage
You can evaluate code coverage when running the test suite using the coverage package:
coverage run -m pytest
coverage report
The first line runs the test suite and keeps track of exactly what lines of
code were run during test execution. The second line then prints out a
summary report showing how much of each source file was executed in the
test suite. If a percentage is below 100, that means a function isn't tested
or a branch inside a function isn't tested. To get specific details, you can
run coverage html to generate a detailed HTML report at
htmlcov/index.html to view in a browser.
Note that the pixi test task already includes --cov flags, so coverage
data is collected automatically when running pixi run -e dev test.
RdTools also uses Codecov to track coverage over time. Coverage reports are uploaded automatically by CI after each test run. Pull requests will show a Codecov status check indicating whether the change increases or decreases overall coverage.
Running the notebooks as tests
Re-running the example notebooks to see if their outputs have changed is another good check. Besides re-running and examining the notebook outputs manually, this command will automatically re-run the specified notebook and compare outputs for you:
pixi run -e dev pytest --nbval docs/system_availability_example.ipynb
A helpful option is --sanitize-with docs/nbval_sanitization_rules.cfg to
ignore nuisance differences like the username shown in warning messages:
pixi run -e dev pytest --nbval --sanitize-with docs/nbval_sanitization_rules.cfg docs/system_availability_example.ipynb
Or to run all notebooks at once using the pixi task:
pixi run -e dev nbval
Re-running and saving notebook outputs
If notebook outputs need to be refreshed (e.g. after a code change that
affects plots or printed results), you can re-execute all notebooks in place
using jupyter nbconvert:
pixi run -e dev jupyter nbconvert --to notebook --execute --inplace docs/*.ipynb
Or a single notebook:
pixi run -e dev jupyter nbconvert --to notebook --execute --inplace docs/TrendAnalysis_example.ipynb
This overwrites each notebook file with freshly executed outputs. Review the diffs before committing to make sure the changes look correct.
Checking for code style
RdTools uses flake8 to validate code style. To run this check locally you'll need to have flake8 installed (see Installing optional dependencies). Then navigate to the git repo folder and run
pixi run -e dev flake8
Or, for a more detailed report:
pixi run -e dev flake8 --count --statistics --show-source
Building documentation locally
RdTools uses Sphinx to build its documentation. If you haven't already, install the documentation dependencies (Installing optional dependencies).
Once the required packages are installed, change your console's working
directory to rdtools/docs/sphinx and run
make html
Note that on Windows, you don't actually need the make utility installed for
this to work because there is a make.bat in this directory. Building the
docs should result in output like this:
(venv)$ make html
Running Sphinx v1.8.5
making output directory...
[autosummary] generating autosummary for: api.rst, example.nblink, index.rst, readme_link.rst
[autosummary] generating autosummary for: C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.aggregation.aggregation_insol.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.aggregation.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.clearsky_temperature.get_clearsky_tamb.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.clearsky_temperature.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.degradation.degradation_classical_decomposition.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.degradation.degradation_ols.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.degradation.degradation_year_on_year.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.degradation.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.filtering.clip_filter.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.filtering.csi_filter.rst, ..., C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.normalization.normalize_with_pvwatts.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.normalization.normalize_with_sapm.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.normalization.pvwatts_dc_power.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.normalization.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.normalization.sapm_dc_power.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.normalization.t_step_nanoseconds.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.normalization.trapz_aggregate.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.soiling.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.soiling.soiling_srr.rst, C:\Users\KANDERSO\projects\rdtools\docs\sphinx\source\generated\rdtools.soiling.srr_analysis.rst
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 4 source files that are out of date
updating environment: 33 added, 0 changed, 0 removed
reading sources... [100%] readme_link
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
preparing documents... done
writing output... [100%] readme_link
generating indices... genindex py-modindex
writing additional pages... search
copying images... [100%] ../build/doctrees/nbsphinx/example_33_2.png
copying static files... done
copying extra files... done
dumping search index in English (code: en) ... done
dumping object inventory... done
build succeeded.
The HTML pages are in build\html.
If you get an error like Pandoc wasn't found, you can install it with conda:
conda install -c conda-forge pandoc
The built documentation should be in rdtools/docs/sphinx/build and opening
index.html with a web browser will display it.
Contributing
Community participation is welcome! New contributions should be based on the
development branch as the master branch is used only for releases.
RdTools follows the PEP 8 style guide. We recommend setting up your text editor to automatically highlight style violations because it's easy to miss some issues (trailing whitespace, etc) otherwise.
Additionally, our documentation is built in part from docstrings in the source code. These docstrings must be in NumpyDoc format to be rendered correctly in the documentation.
Finally, all code should be tested. Some older tests in RdTools use the unittest module, but new tests should all use pytest.