diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0cd4e3e5..ec8741d9 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,8 @@ **Pull request recommendations:** -- [ ] Name your pull request _your-development-type/short-description_. Ex: _feature/validate_floc_ -- [ ] Link to any relevant issue in the PR description. Ex: _Resolves [gh-12], adds flocculator validation_ -- [ ] Provide context of changes. -- [ ] Provide relevant tests for your feature or bug fix. -- [ ] Provide or update documentation for any feature added by your pull request. +- Name your pull request {your development type}: {short description}. Ex: _Feature: flocculator validation_ +- Link to any relevant issue in the PR description. Ex: _Resolves #12, adds flocculator validation_ +- Provide context of changes. +- Provide relevant tests for your feature or bug fix. +- Provide or update documentation for any feature added by your pull request. Thanks for contributing! diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a360f88e..9a1859b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,13 +51,12 @@ jobs: python -m pip install --upgrade pip pip install pipenv pipenv install --dev - pip install sphinx_rtd_theme - name: Run doctests and build html files run: | cd docs pipenv run make doctest - make html + pipenv run make html - name: Run html-proofer uses: chabad360/htmlproofer@master diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f26cef6a..2f266f1b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,9 +1,8 @@ name: Documentation on: - push: - branches: - - 'master' + release: + types: [published] jobs: publish_docs: @@ -20,12 +19,13 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install sphinx_rtd_theme + pip install pipenv + pipenv install --dev - name: Build Sphinx documentation run: | cd docs - make html + pipenv run make html - name: Publish Sphinx documentation uses: peaceiris/actions-gh-pages@v3 diff --git a/.gitignore b/.gitignore index bc66deff..d5e8792c 100644 --- a/.gitignore +++ b/.gitignore @@ -104,6 +104,7 @@ cov_html # Sphinx documentation docs/_build/ +docs/source/_build/ venv/ *.iml .idea/ diff --git a/README.md b/README.md index 23b6fa6d..62b82148 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,94 @@ -# aguaclara [![Build Status](https://github.com/AguaClara/aguaclara/workflows/Build/badge.svg)](https://github.com/AguaClara/aguaclara/actions) [![Documentation](https://github.com/AguaClara/aguaclara/workflows/Documentation/badge.svg)](https://aguaclara.github.io/aguaclara/) [![codecov](https://codecov.io/gh/AguaClara/aguaclara/branch/master/graph/badge.svg)](https://codecov.io/gh/AguaClara/aguaclara) +# `aguaclara` +[![Pypi Version](https://img.shields.io/pypi/v/aguaclara?color=blue&label=PyPI)](https://pypi.org/project/aguaclara/) +[![Documentation](https://github.com/AguaClara/aguaclara/workflows/Documentation/badge.svg)](https://aguaclara.github.io/aguaclara/) +[![Build Status](https://github.com/AguaClara/aguaclara/workflows/Build/badge.svg)](https://github.com/AguaClara/aguaclara/actions) +[![Code Coverage](https://codecov.io/gh/AguaClara/aguaclara/branch/master/graph/badge.svg)](https://app.codecov.io/gh/AguaClara/aguaclara/) +`aguaclara` is a Python package developed by [AguaClara Cornell](http://aguaclara.cornell.edu/) and [AguaClara Reach](https://www.aguaclarareach.org/) for designing and performing research on AguaClara water treatment plants. The package has several main functionalities: -Design an AguaClara Water Treatment Plant with just a couple lines of code! Or just design a few components - your choice with aguaclara. aguaclara parametrically designs plant components from basic physics equations. In a nutshell, you can generate a design yaml for a whole plant and print it to your console stream like so: +* **DESIGN** of AguaClara water treatment plant components +* **MODELING** of physical, chemical, and hydraulic processes in water treatment +* **PLANNING** of experimental setup for water treatment research +* **ANALYSIS** of data collected by [ProCoDA](https://monroews.github.io/EnvEngLabTextbook/ProCoDA/ProCoDA.html) (process control and data acquisition tool) -```python -from aguaclara.play import * -from aide_render import render -import sys -my_plant = Plant(HP(30, u.L/u.s)) -render(my_plant, sys.stdout) -``` ## Installing +The `aguaclara` package can be installed from Pypi by running the following command in the command line: + ```bash pip install aguaclara ``` +To upgrade an existing installation, run -## Installing as a developer -If you want to make pushes to aguaclara, then you should clone this repo and make the package available locally, using the following commands: ```bash -git clone https://github.com/AguaClara/aguaclara.git -cd aguaclara -pip install --editable . -U --user +pip install aguaclara --upgrade ``` -The editable flag makes it so that you don't have to continuously install with pip to make the changes you just made visible. -### Running Tests -To run the test suite, you'll have to install the dev dependencies with pipenv from the repo root directory: -```bash -pipenv install +## Using `aguaclara` +`aguaclara`'s main functionalities come from several sub-packages. + +1. **Core**: fundamental physical, chemical, and hydraulic functions and values +2. **Design**: modules for designing components of an AguaClara water treatment plant +3. **Research**: modules for process modeling, experimental design, and data analysis in AguaClara research + +To use `aguaclara`'s registry of scientific units (based on the [Pint package](https://pint.readthedocs.io/en/latest/)), use `from aguaclara.core.units import u`. Any other function or value in a sub-package can be accessed by importing the package itself: + +### Example Usage: Design +```python +import aguaclara as ac +from aguaclara.core.units import u + +# Design a water treatment plant +plant = ac.Plant( + q = 40 * u.L / u.s, + cdc = ac.CDC(coag_type = 'pacl'), + floc = ac.Flocculator(hl = 40 * u.cm), + sed = ac.Sedimentor(temp = 20 * u.degC), + filter = ac.Filter(q = 20 * u.L / u.s) +) ``` -If pipenv reports you need to install a different version of python, please do so. After pipenv runs successfully, you'll have a fully provisioned testing environment. To run all the tests, now just type: -```bash -pipenv run pytest + +### Example Usage: Core +```python +# continued from Example Usage: Design + +# Model physical, chemical, and hydraulic properties +cdc = plant.cdc +coag_tube_reynolds_number = ac.re_pipe( + FlowRate = cdc.coag_q_max, + Diam = cdc.coag_tube_id, + Nu = cdc.coag_nu(cdc.coag_stock_conc, cdc.coag_type) +) +``` + +### Example Usage: Research +```python +import aguaclara as ac +from aguaclara.core.units import u +import matplotlib.pyplot as plt + +# Plan a research experiment +reactor = ac.Variable_C_Stock( + Q_sys = 2 * u.mL / u.s, + C_sys = 1.4 * u.mg / u.L, + Q_stock = 0.01 * u.mL / u.s +) +C_stock_PACl = reactor.C_stock() + +# Visualize and analyze ProCoDA data +ac.iplot_columns( + path = "https://raw.githubusercontent.com/AguaClara/team_resources/master/Data/datalog%206-14-2018.xls", + columns = [3, 4], + x_axis = 0 +) +plt.ylabel("Turbidity (NTU)") +plt.xlabel("Time (hr)") +plt.legend(("Influent", "Effluent")) ``` -The tests should all pass. If they don't, check in with the latest Travis build of master to see what the difference between the Travis environment and your local environment could make the tests not pass. - -## Contributing: (v0.0.1 -> v0.1.0) -1. Write your code! -2. When you are ready to commit it, make a new branch that describes your changes and push it to github: - ```bash - $ git add . #add local files to staging area - $ git checkout -b the_name_of_my_new_branch #create new branch locally and move to it - $ git commit -m "my detailed commit message describing what I did" #commit to the new branch - $ git push -u origin the_name_of_my_new_branch #push the new branch and all the commits you made to GitHub. - ``` -3. Keep making changes and committing them as you finish your feature. Once you are ready to push your code to the master branch, go online and make a pull request to the master branch. -4. The pull request will initiate several 'checks.' This will take about 5 minutes to run. The first is the Travis CI check. Travis is a cloud-based continuous integration tool that automatically runs all defined tests. Once the tests pass, Travis generates a coverage report. This report analyzed what percentage of the code was "hit" during the testing process, also known as what percentage was 'covered'. -5. If all the checks passed, you can ping a repo manager to ask them to accept your pull request. -6. If the repo manager accepts the request, then the next time a version of master is tagged as a release version, the code will be packaged as a source distribution (sdist) and sent off to [pypi](https://pypi.org/search/?q=aguaclara). - -## Changelog -**aguaclara design is in RAPID development. Things will shange significantly!** - -We're not tracking changes at the moment here. Once development is at a more reasonable pace, we'll start tracking improvements and bug fixes more carefully! - -## Structure -The aguaclara package has three distinct levels that work together to design a plant. The first level is composed of base classes that define chemicals, quantities, and other parameters. These classes are created and used within the functional layer to define some basic engineering equations. Lastly, the component classes correspond to objects that are modeled in Fusion 360. - - +----------------------------+ - | COMPONENT CLASSES (.parts) | - +-------------+ | - | Classes that correspond to | - | Fusion components. | ^ - +------------+---------------+ | - ^ | - | | - +-----------------------+ | - | FUNCTIONAL|LAYER | | Each layer - +--------------+ | | depends on the - | This layer has only | | layers below - | functions that rely | | it to function. - | on quantity class | | - | inputs. | | - +------------+----------+ | - ^ | - | | - +------------+---------------+ | - |BASE CLASSES | | - +----------- | | - |Classes needed to make the | | - |functional and component | + - |class layers work. Such as | - |Quantity, HP and DP. | - +----------------------------+ + +The package is still undergoing rapid development. As it becomes more stable, a user guide will be written with more detailed tutorials. At the moment, you can find some more examples in specific pages of the [API reference](https://aguaclara.github.io/aguaclara/api.html). + +## Contributing +Bug reports, features requests, documentation updates, and any other enhancements are welcome! To suggest a change, [make an issue](https://github.com/AguaClara/aguaclara/issues/new/choose) in the [`aguaclara` Github repository](https://github.com/AguaClara/aguaclara>). + +To contribute to the package as a developer, refer to the [Developer Guide](https://aguaclara.github.io/aguaclara/guide-dev/guide-dev.html). diff --git a/codecov.yml b/codecov.yml index 00914192..2ddc06af 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,5 @@ ignore: - - "docs" - - "aguaclara/play.py" \ No newline at end of file + - docs + - tests + - aguaclara/play.py + - setup.py \ No newline at end of file diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 00000000..2d8d1ae9 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,14 @@ +.. _api: + +============= +API Reference +============= + +The following pages document the modules, functions, and values available in each sub-package. + +.. toctree:: + :maxdepth: 2 + + core/core + design/design + research/research \ No newline at end of file diff --git a/docs/source/core/constants.rst b/docs/source/core/constants.rst index 83381616..c4e5f441 100644 --- a/docs/source/core/constants.rst +++ b/docs/source/core/constants.rst @@ -1,3 +1,5 @@ +.. _constants: + Constants ========= diff --git a/docs/source/core/units.rst b/docs/source/core/units.rst index 58c6ea34..39f484e6 100644 --- a/docs/source/core/units.rst +++ b/docs/source/core/units.rst @@ -1,3 +1,5 @@ +.. _units: + Units ===== diff --git a/docs/source/guide-dev.rst b/docs/source/guide-dev.rst new file mode 100644 index 00000000..ae320225 --- /dev/null +++ b/docs/source/guide-dev.rst @@ -0,0 +1,443 @@ +.. |aguaclara Github| replace:: ``aguaclara`` Github repository +.. _aguaclara Github: https://github.com/AguaClara/aguaclara + +.. |aguaclara issues| replace:: ``aguaclara`` Github repository issues +.. _aguaclara issues: https://github.com/AguaClara/aguaclara/issues + +.. |aguaclara actions| replace:: ``aguaclara``'s Github Actions page +.. _aguaclara actions: https://github.com/AguaClara/aguaclara/actions + +.. |flake8| replace:: ``flake8``, a Python linter (code style checker), +.. _flake8: https://flake8.pycqa.org/en/latest/ + +.. |black| replace:: ``black``, an automatic code formatter, +.. _black: https://black.readthedocs.io/en/stable/ + +.. |Sphinx autodoc extension| replace:: Sphinx ``autodoc`` extension +.. _Sphinx autodoc extension: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html + +.. |html-proofer package| replace:: ``html-proofer`` package +.. _html-proofer package: https://github.com/gjtorikian/html-proofer + +.. |pytest package| replace:: ``pytest`` package +.. _pytest package: https://docs.pytest.org/en/stable/ + +.. |unittest package| replace:: ``unittest`` package +.. _unittest package: https://docs.python.org/3/library/unittest.html + +.. |test_physchem.py| replace:: ``tests/core/test_physchem.py`` +.. _test_physchem.py: https://github.com/AguaClara/aguaclara/blob/master/tests/core/test_physchem.py + +.. |test_cdc.py| replace:: ``tests/design/test_cdc.py`` +.. _test_cdc.py: https://github.com/AguaClara/aguaclara/blob/master/tests/design/test_cdc.py + +.. _guide-dev: + +=============== +Developer Guide +=============== + +Where to Start +-------------- +Whether you're are maintainer of ``aguaclara`` or a user with a bug fix, feature, or enhancement in mind, the |aguaclara issues|_ are a great place to start. + +Before working, **browse the issues to check if the update you have in mind has already been documented and assigned to a developer**. If a relevant issue doesn't exist, go ahead and make one with the button labeled "New Issue". If/once an issue does exist, there a few ways to proceed: + +* if you're a collaborator of the ``aguaclara`` repository, assign yourself to the issue. +* if you're not a collaborator, either ask a collaborator to make you a collaborator as well, or ask the collaborator to assign you to the issue. + +Feel free to use the issue for commenting on your progress or asking other users or collaborators for help with your development. + + +Setting Up Your Local Environment +--------------------------------- +If you want to make changes to ``aguaclara``, you should make the package available locally. + +#. Make sure to have Python, ``pip``, and Git installed (for guidance, see :ref:`install-software`). Check the package's `Pypi `_ page for the required Python version. If you must have a different version on your computer for another project, you can use `pyenv `_ to manage multiple Python versions. + +#. Install `Pipenv `_, a package management and virtual environment tool, by running the following command in the command line: + + .. code:: + + pip install pipenv + +#. In the command line, navigate to the directory in which you'll keep your local copy of the ``aguaclara`` Git repository. + + * If you're not a collaborator, you'll need to first fork the repository on Github. + +#. Clone the repository or your fork of the repository into that directory: + + .. code:: + + (Cloning original repository) + git clone https://github.com/AguaClara/aguaclara.git + + (Cloning forked repository) + git clone https://github.com/{your_username_here}/aguaclara.git + +#. Navigate into the newly cloned repository and install it in editable mode, so that your environment uses this repository as your ``aguaclara`` package, even as you edit it: + + .. code:: + + cd aguaclara + pip install --editable . -U --user + + To install the package in editable mode in a virtual environment only, replace the second line with ``pipenv install --dev -e .`` (``.`` passes the current directory as an argument to the ``-e`` flag, short for "editable"). + +#. Install the package's user dependencies and development dependencies: + + .. code:: + + pipenv install --dev + + Pipenv is used to install the dependencies from the file called ``Pipfile`` into a virtual environment. See the :ref:`envs` for more details. + +#. You can check whether you have a fully provisioned testing environment now by running: + + .. code:: + + pipenv run pytest + + The tests should all pass. If they don't, check in with the latest `Github Actions build of the master branch `_ to see what difference between the Github Actions environment and your local environment could make the tests fail. + + +Branching +--------- +Before you develop, it's important to understand the branching conventions for the ``aguaclara`` repository. + +The Master Branch +***************** +The master branch is the branch that houses ``aguaclara``'s published releases. Therefore, the master branch is a *protected* with rules (on Github) that + +* pull requests are required before merging into the branch, +* only administrators and maintainers can push to the branch, and +* status checks are required before merging or pushing to the branch. + +Your Development Branch +*********************** +This means that all work starts on *development branches*, or task or feature branches. (Check out this `article `_ if you want to learn more.) +It is recommended that you name your branch ``{your_development_type}/short-description``. Some examples of development type are + +.. hlist:: + :columns: 2 + + * ``feature`` + * ``bugfix`` + * ``enhancement`` + * ``documentation`` + * ``test`` (for additions/updates to tests) + * ``build`` (for updates to the build process) + +To make and switch to your new branch, run: + +.. code:: + + git checkout -b {your_development_type}/short-description + +Documentation and Test Driven Development +----------------------------------------- +1. Write Documentation +********************** +Your development should begin with documentation -- that is, creating a blueprint of the code you plan to write. **In this blueprint, each new or modified module, function, class, or method should be defined with a documentation string (i.e. comments, specifications, docstring) that describes its purpose and functionality, before any code is written**. +You can read more about documentation driven development (DDD) in this short `blog `_. + +.. Commented out: The primary purpose of the documentation is to inform users how the code is intended to be used and behave. The purpose of the documentation process is to make you, as the developer, consider the best interface for the user. Plus, it lays a clearer roadmap to the end product and is crucial for helping others (and yourself!) to understand and debug the code. + +For docstring syntax, see :ref:`sphinx-docs`. For style, see :ref:`doc-conventions`. + +**If possible, gather feedback from likely users after writing the documentation.** Modifications are much more easily made to documentation than to code. + +2. Write a Test +*************** +Next, write a unit test for your code based on the documentation. A unit test tests a basic unit, e.g. function or method, of your code. **If a unit of code produces the expected (documented) outputs for accepted inputs, its test should pass. If it behaves any differently from what is described in its documentation, its test should fail.** +Make sure to test all types and/or edge cases of accepted inputs (this last part is known as `black box testing `_). You can read more about test driven development (TDD) `here `_. + +.. Commented out: Like DDD, test driven development (TDD) focuses on specifying the code most optimally for the user by putting the developer in the user's shoes. TDD also leads to cleaner and better designed code than traditional testing. + +For details on writing tests, see :ref:`testing`. + +All test files should be located in the ``tests/`` directory. To execute the tests in a test file, run the following command in the command line: + +.. code:: + + pipenv run pytest path/to/file -v + +where the ``-v`` flag gives a verbose (more descriptive) output. To execute specific tests in a test file, run: + +.. code:: + + pipenv run pytest path/to/file -v -k name_of_test + +3. Write Code to Pass Failing Test +********************************** +Since you haven't written any code yet, your test should fail. Now write just enough code to pass the failing test. + +For code style conventions, refer to `Python's Style Guide `_. You can also use |flake8|_ and |black|_ to achieve proper style. + +4. Refactor +*********** +If your test still fails, refactor (modify) your code, still keeping it as simple as possible, until the test passes. + +5. Repeat +********* +Repeat steps 3 and 4 until tests cover all the functionalities described in the documentation. + +.. _sphinx-docs: + +Sphinx Documentation +-------------------- +Sphinx and RST +************** +``aguaclara``'s documentation, including this page, is built using a tool called `Sphinx `_, which uses reStructuredText (RST, ReST, or reST) as its markup language. RST files have the extension ``.rst``. The source files for ``aguaclara``'s documentation are found in the ``docs/source`` directory. +For a brief introduction to RST concepts and syntax, see `Sphinx's reStructuredText Primer `_. + +Automated Documentation +*********************** +You may have noticed that ``aguaclara``'s modules, classes, functions, and constants are not manually documented in the API Reference pages. Instead, they are automatically documented using an RST directive, ``.. automodule::``, which reads the docstrings in the source code. **Hence, docstrings must be written in correst RST and can include all the usual RST markup (e.g. headers, code blocks).** +For more details on including documentation from docstrings, see the |Sphinx autodoc extension|_. + +Previewing Documentation +************************ +Some IDEs offer extensions for previewing the HTML pages that Sphinx generates from the RST files. (One great extension is `reStructuredText by LexStudio, Inc. `_ for `Visual Studio Code `_.) You can also build the documentation from the command line: + +.. code:: + + cd docs + pipenv run make html + +The resulting HTML files will be written to the ``docs/build/html`` directory. You can then open and interact with them in a browser. + +Validating Documentation +************************ +The |html-proofer package|_ can be used to check the correctness of the rendered HTML pages (e.g., that there are not broken links). To install the package, `download RubyGems `_ and then run: + +.. code:: + + gem install html-proofer + cd docs + htmlproofer build/html --allow_hash_href --file_ignore "build/html/search.html" + +Alternatively, you can commit your changes, push them to Github, and check the "Build" workflow for your commit in |aguaclara actions|_ (or that of your forked repository). See :ref:`github-actions` for more details. + + +Committing and Pushing +---------------------- +It's a good idea to **commit your work early and commit often**. Saving more snapshots of your work through Git facilitates debugging and resetting code while logging your progress. + +#. Before committing, check if your work generated any user, operating system, or IDE specific or other otherwise unnecessary developer files in your ``aguaclara`` repository. If so, add their files names or directories to the ``.gitignore`` file. + +#. If you have files in a directory named ``tests/rst_files``, run in the command line: + + .. code:: + + git update-index --skip-worktree tests/rst_files/* + +#. Now, stage your changes and commit them with a short but descriptive commit message. From the ``aguaclara`` root directory, run: + + .. code:: + + git add . + git commit -m "your message here" + +#. Make sure to also occasionally pull commits from the remote Github repository, if anyone else is working on your branch, and to push your commits: + + .. code:: + + git pull + git push + +For more guidance on using Git in the command line, see the `AguaClara Tutorial Wiki `_. + + +.. _github-actions: + +Continuous Integration via Github Actions +----------------------------------------- +Continuous integration (CI) is a software development practice that allows multiple developers to frequently merge code into a shared repository. CI usually involves automated tests and builds of the code to make sure it is correct before integration. +The ``aguaclara`` package uses Github Actions for continuous integration. More specifically, several "workflows" have been defined in the ``.github/workflows`` directory to accomplish various tasks: + +.. list-table:: + :header-rows: 1 + + * - Workflow + - Trigger + - Tasks + * - Build + - Push, pull request + - Validate code and documentation, check code coverage + * - Documentation + - Push to master branch + - Build and publish Sphinx documentation + * - Publish to Pypi + - Publishing of release + - Build and publish the package to Pypi + +The `Github Actions documentation `_ is a great place to learn more about workflows and other aspects of Github's CI platform. + +Checking Workflow Results +************************* +Results of workflow runs can be viewed in the `Actions `_ tab of the ``aguaclara`` Github repository. If a job fails in the "Build" workflow for your latest push, find the error in the job's log and debug from there. + +Checking Code Coverage +********************** +Code coverage is a measure of the amount of source code that has been executed by tests. **Whenever possible, all new or modified code should be covered by tests, so code coverage should either remain the same or increase with each contribution.** +If you add a file of code that *cannot reasonably be tested*, you may add it to the list of files and directories ignored by Codecov in ``codecov.yml``. (Note: such files are rare!) + +The "Build" workflow calculates code coverage and uploads a report to `Codecov `_. The actual change in coverage can then be viewed on Codecov or in the dropdown of status checks next to the commit ID on Github (click on either a green ✓ or a red ✕). + +.. image:: images/status_checks.png + :align: center + :alt: Status Checks Dropdown + :scale: 40% + +If you're a collaborator of ``aguaclara``, you can also log in to Codecov through your Github account and view the "hit" and "missed" lines of code on Codecov (or directly on Github with a `browser extension `_). + + +Preparing for Release +--------------------- +If you code has been fully documented, tested, and implemented and is passing all status checks (see previous section), you're ready to prepare for a release. + +Semantic Versioning +******************* +The ``aguaclara`` package follows `semantic versioning `_, meaning that its version numbers take the form of ``vMAJOR.MINOR.PATCH``. + +**Currently, the package is still in major version 0** (``v0.MINOR.PATCH``), i.e. in beta, so it is NOT considered stable. Version numbers during this stage are generally incremented as follows: + +#. ``MINOR`` is incremented with incompatible API changes +#. ``PATCH`` is incremented with backwards compatible features and bug fixes + +**Once the package is stable, the package version number can be incremented to** ``v1.0.0``. (This will most likely happen after the ``onshape_parser`` tool and the AguaClara Infrastructure Design Engine, AIDE, and become stable.) From then on, versioning should adhere to the following rules: + +#. ``MAJOR`` is incremented with incompatible API changes +#. ``MINOR`` is incremented with backwards compatible feature additions +#. ``PATCH`` is incremented with backwards compatible bug fixes + +Determine what version number is most appropriate for your release and update ``setup.py`` accordingly: + +.. code:: python + + # ... + setup( + name = 'aguaclara', + version = '0.3.0', # Edit the version number here + # ... + ) + +Merging from Master +******************* +To ensure that your code can safely integrate with the ``aguaclara`` package, pull any new changes that were made to the master branch and merge them into your development branch. + +.. code:: + + git checkout master + git pull + git checkout name_of_your_branch + git merge master + +.. note:: Follow Github's instructions for `Syncing a fork `_ if you're working in a forked repository. + +.. Commented out: For slighlty more experienced Git users, `think twice before rebasing `_. + +If the merge is successful, your command line may automatically take you to a text editor to edit or accept a default commit message for the merge. If using the Vi text editor, type ``:x`` and hit Enter to save and exit. + +If the command line alerts you of merge conflicts, open the files with conflicts in your IDE and manually resolve them. Many IDE's, such as Visual Studio Code, also have built-in support for handling them. For a better understanding of merge conflicts, check out this `article by Atlassian `_. + +Pull Requests +************* +Once you're finally ready to merge your code into the master branch... + +#. Push any final commits on your branch. +#. `Create a pull request `_ (PR) on Gitub to merge your development branch with the master branch. +#. Follow the pull request template to write a title and description for your PR. +#. Add at least one reviewer who is a maintainer of ``aguaclara``. You can also tag, message, or email them to make sure they know to give a review. +#. Wait for the reviewer to approve and merge the PR or request changes. + +Publishing a Release +-------------------- +If your PR has been merged into the master branch, publish your release (or ask a collaborator to) as follows: + +#. Go to the `Releases `_ on the ``aguaclara`` Github. +#. Click "Draft a new release". +#. Create a new tag with the same name as the new version number (e.g. v0.3.0). +#. Give your release a title and description. +#. Publish the release! + +Now, the "Publish to Pypi" workflow will trigger in Github Actions to make the new release available on `Pypi `_. +The "Documentation" workflow will be running as well to update this documentation website. + +Make sure to close relevant issues if they were not automatically closed. + +Congratulations on making a release, and thanks for contributing to AguaClara! + + +Additional Topics +----------------- + +.. _envs: + +Dependencies, Virtual Environments, and Pipenv +********************************************** +Every Python project must specify the exact names and versions of its **dependencies**, i.e. other libraries and programs it depends on, so as to not fail on users' and other developers' computers. +**Virtual environments** are used to prevent dependency conflicts between Python projects. According to the `Python Standard Library documentation `_, + + "A virtual environment is a Python environment such that the Python interpreter, libraries and scripts installed into it are isolated from those installed in other virtual environments, and (by default) any libraries installed in a “system” Python, i.e., one which is installed as part of your operating system." + +**Pipenv** wraps over ``pip`` and ``virtualenv`` to manage dependency specifications and virtual environments. It does so with the help of two files: + +* ``Pipfile`` - where developers specify user/default dependencies and developer dependencies. These should include only top-level dependencies (no sub-dependencies). +* ``Pipfile.lock`` - an auto-generated file that specifies the exact requirements for reproducing an environment (including sub-dependencies). Do not edit manually! + +Some important commands for Pipenv are: + +* ``pipenv install`` - installs default dependencies from ``Pipfile`` into a virtual environment. +* ``pipenv install --dev`` - install default *and* developer dependencies from ``Pipfile`` into a virtual environment. +* ``pipenv install `` - installs a package into the virtual environment and updates ``Pipfile``. +* ``pipenv lock`` - creates or updates ``Pipfile.lock`` to specify all dependencies and sub-dependencies and their current versions in the virtual environment. +* ``pipenv sync`` - installs packages into the virtual environment exactly as specified in ``Pipfile.lock``. +* ``pipenv run `` - runs any terminal command in the virtual environment. + +Refer to `Real Python's guide `_ or `Pipenv's documentation `_ for more information. + + +.. _doc-conventions: + +Docstring Conventions +********************* +The ``aguaclara`` package has used the `Sphinx format `_ and the `NumPy format `_ for documenting modules, classes, functions, and constants. Regardless of which you use, the NumPy documentation is a good conceptual and technical resource. + +Exceptions: + * Descriptions of parameters and return values usually report data types. For some parameters and return values in ``aguaclara`` that are clearly numeric (of type int, float, or complex), the data type is replaced with the scientific unit of the value, e.g. ``u.degC`` for ``Temperature``. See the :ref:`units` module for a list of frequently used units. + * In some cases, it's more appropriate to include an example of code as a static RST code block rather than as a doctest. For more information on doctests, see :ref:`testing`. + * A constant can be documented by comments starting with ``#:`` in the lines immediately above it. See the source code of the :ref:`constants` module for examples. + + +.. _testing: + +Python Testing +************** +``aguaclara`` uses the |pytest package|_ and the |unittest package|_ for testing Python code. See |test_physchem.py|_ for examples of using ``pytest`` and |test_cdc.py|_ for examples of using ``unittest``. + +Some modules also use Python tests that are written directly in the docstrings -- that is, doctests. Here's an example from ``design/cdc.py``: + +.. code:: python + + """ + ... + >>> from aguaclara.design.cdc import * + >>> cdc = CDC(q = 20 * u.L/u.s, coag_type = 'pacl') + >>> cdc.coag_stock_vol + + """ + +**All doctests must pass**, i.e. the lines of code following the ``>>>`` must yield the value immediately after. One way to execute the doctests is to run: + +.. code:: + + pipenv run pytest path/to/file -v --doctest-modules + +To check all doctests in the package at once, run: + +.. code:: + + cd docs + pipenv run make doctest diff --git a/docs/source/guide-user/data.rst b/docs/source/guide-user/data.rst new file mode 100644 index 00000000..24cf04bb --- /dev/null +++ b/docs/source/guide-user/data.rst @@ -0,0 +1,33 @@ +========================================= +Data Parsing, Analysis, and Visualization +========================================= + +Reading and visualizing data from a ProCoDA data file +----------------------------------------------------- +.. code:: python + + import aguaclara as ac + from aguaclara.core.units import u + import matplotlib.pyplot as plt + + path = "https://raw.githubusercontent.com/AguaClara/team_resources/master/Data/datalog%206-14-2018.xls" + + time = ac.column_of_time(path=path, start=2250, end=5060).to(u.hr) + influent_turbidity = ac.column_of_data(path=path, start=2250, column=3, end=5060) + effluent_turbidity = ac.column_of_data(path=path, start=2250, column=4, end=5060) + + # set up multiple subplots with same x-axis + fig, ax1 = plt.subplots() + ax2 = ax1.twinx() + + # make the first subplot (Effluent Turbidity vs Time) + ax1.set_xlabel("Time (hours)") + ax1.set_ylabel("Effluent Turbidity (NTU)") + line1, = ax1.plot(time, effluent_turbidity, color="blue") + + # make the second subplot (Influent Turbidity vs Time) + ax2.set_ylabel("Influent Turbidity (NTU)") + ax2.set_ylim(60,120) + line2, = ax2.plot(time, influent_turbidity, color="green") + + plt.legend((line1, line2), ("Effluent", "Influent")) diff --git a/docs/source/guide-user/experimental-design.rst b/docs/source/guide-user/experimental-design.rst new file mode 100644 index 00000000..7b112b8d --- /dev/null +++ b/docs/source/guide-user/experimental-design.rst @@ -0,0 +1,40 @@ +=================== +Experimental Design +=================== + +Designing an experiment with a contaminant and a coagulant of unknown concentration +----------------------------------------------------------------------------------- +.. code:: python + + import aguaclara as ac + from aguaclara.core.units import u + + # volume per revolution flowing from the pump for PACl (coagulant) stock + vol_per_rev_PACl = ac.vol_per_rev_3_stop("yellow-blue") + # revolutions per minute of PACl stock pump + rpm_PACl = 3 * u.rev/u.min + # flow rate from the PACl stock pump + Q_PACl = ac.flow_rate(vol_per_rev_PACl, rpm_PACl) + + # desired system flow rate + Q_sys = 2 * u.mL/u.s + # desired system concentration of PACl + C_sys = 1.4 * u.mg/u.L + # a variable representing the reactor and its parameters + reactor = ac.Variable_C_Stock(Q_sys, C_sys, Q_PACl) + + # required concentration of PACl stock + C_stock_PACl = reactor.C_stock() + # concentration of purchased PACl super stock in lab + C_super_PACl = 70.28 * u.g/u.L + # dilution factor of PACl super stock necessary to achieve PACl stock + # concentration (in L of super stock per L water) + dilution = reactor.dilution_factor(C_super_PACl) + mL_per_L = dilution * 1000 + + print("A reactor with a system flow rate of", Q_sys, ",") + print("a system PACl concentration of", C_sys, ",") + print("and a PACl stock flow rate of", Q_PACl) + print("will require a dilution factor of", round(mL_per_L.magnitude, 3), + "milliliters of PACl super") + print("stock per liter of water for the PACl stock.") \ No newline at end of file diff --git a/docs/source/guide-user/guide-user.rst b/docs/source/guide-user/guide-user.rst new file mode 100644 index 00000000..8881ed22 --- /dev/null +++ b/docs/source/guide-user/guide-user.rst @@ -0,0 +1,12 @@ +.. _guide-user: + +========== +User Guide +========== + +.. toctree:: + :maxdepth: 1 + + install + data + experimental-design \ No newline at end of file diff --git a/docs/source/guide-user/install.rst b/docs/source/guide-user/install.rst new file mode 100644 index 00000000..c8a6925a --- /dev/null +++ b/docs/source/guide-user/install.rst @@ -0,0 +1,49 @@ +.. _install-software: + +=================== +Installing Software +=================== + +.. _install-python-pip: + +Installing Python and ``pip`` +----------------------------- +1. Download the `Anaconda installer `_ and double-click it to begin installation. +2. When the installer displays Advanced Options, select "Add Anaconda to my PATH environment variable". + + * Aside from this, you can just click "Next" through the entire installation. + +**If the installer did not give the option to "Add Anaconda to my PATH environment variable", follow the steps below after the installation:** + +On MacOS: + 3. Open the Terminal and enter ``which python`` + 4. Copy the directory the terminal outputs. (This is the directory Python has been installed in.) + 5. Enter the command ``export PATH=$PATH``, replacing ```` with the directory you copied above. + +On Windows: + 3. Open the Command Prompt (not PowerShell) and enter ``where python`` + 4. Copy the path the terminal outputs. (This is the folder Python has been installed in.) + 5. Enter the command ``set PATH=%PATH%;C:\path\to\python``, replacing ``C:\path\to\python`` with the path you copied above. + + +.. _install-git: + +Installing Git +-------------- +On MacOS: + 1. Open the Terminal/Command Prompt and enter the following command: + + * ``git --version`` + + 2. If you don't alread have Git, Xcode will prompt you to install it. Follow the prompts to install Git. + +On Windows: + 1. Download the `Git installer `_ and double-click it to begin installation. + 2. When the installer asks which text editor you would like to use with Git (the default is Vim), select Nano instead. While powerful, Vim is difficult to use and not necessary for Git. + + * Aside from this, you can just click "Next" through the entire installation. + +3. After the installation is complete, open Terminal, PowerShell, or Command Prompt and run the two following commands with your name and the email associated with your Github account, carefully observing spaces and punctuation (including quotation marks): + + * ``git config --global user.name "Firstname Lastname"`` + * ``git config --global user.email "example@email.com"`` \ No newline at end of file diff --git a/docs/source/images/acc_logo.png b/docs/source/images/acc_logo.png new file mode 100644 index 00000000..3564c4b3 Binary files /dev/null and b/docs/source/images/acc_logo.png differ diff --git a/docs/source/images/acr_logo.png b/docs/source/images/acr_logo.png new file mode 100644 index 00000000..6da30209 Binary files /dev/null and b/docs/source/images/acr_logo.png differ diff --git a/docs/source/images/logo.png b/docs/source/images/logo.png deleted file mode 100644 index 3f905ce7..00000000 Binary files a/docs/source/images/logo.png and /dev/null differ diff --git a/docs/source/images/status_checks.png b/docs/source/images/status_checks.png new file mode 100644 index 00000000..4d1817ae Binary files /dev/null and b/docs/source/images/status_checks.png differ diff --git a/docs/source/index.rst b/docs/source/index.rst index 16b876d1..bc5cf10d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,43 +2,121 @@ Welcome to the AguaClara Package Documentation! =============================================== -.. image:: images/logo.png - :align: center +.. centered:: |ACC| |ACR| -``aguaclara`` is a Python package built by `AguaClara Cornell `_ for AguaClara water treatment plant design and research. +.. |ACC| image:: images/acc_logo.png + :width: 250 px + +.. |ACR| image:: images/acr_logo.png + :width: 250 px + +``aguaclara`` is a Python package developed by `AguaClara Cornell `_ and `AguaClara Reach `_ for designing and performing research on AguaClara water treatment plants. The package has several main functionalities: + +* **DESIGN** of AguaClara water treatment plant components +* **MODELING** of physical, chemical, and hydraulic processes in water treatment +* **PLANNING** of experimental setup for water treatment research +* **ANALYSIS** of data collected by `ProCoDA `_ (process control and data acquisition tool) Installing ---------- -The ``aguaclara`` package can be installed by running ``pip install aguaclara`` in the command line. To upgrade an existing installation, run ``pip install aguaclara --upgrade``. +The ``aguaclara`` package can be installed from Pypi by running the following command in the command line: -Contributing ------------- -To report a bug or request or feature, make an issue in the `AguaClara package Github repository `_. +.. code:: + + pip install aguaclara + +To upgrade an existing installation, run + +.. code:: + + pip install aguaclara --upgrade + +Click here for :ref:`more software installation instructions` if you don't have Python or ``pip``. Using ``aguaclara`` ------------------- -``aguaclara`` is organized into three sub-packages. +``aguaclara``'s main functionalities come from several sub-packages. 1. **Core**: fundamental physical, chemical, and hydraulic functions and values -2. **Design**: modules for creating a parameterized design of an AguaClara water treatment plant +2. **Design**: modules for designing components of an AguaClara water treatment plant 3. **Research**: modules for process modeling, experimental design, and data analysis in AguaClara research -To use ``aguaclara``'s registry of scientific units (based on the `Pint package `_), use ``from aguaclara.core.units import u``. Any other function or value in a sub-package can be accessed by importing the package itself: +To use ``aguaclara``'s registry of scientific units (based on the `Pint package `_), use ``from aguaclara.core.units import u``. Any other function or value in a sub-package can be accessed by importing the package itself. +Example Usage: Design +********************* .. code-block:: python import aguaclara as ac from aguaclara.core.units import u - ac.viscosity_kinematic(20 * u.degC) + # Design a water treatment plant + plant = ac.Plant( + q = 40 * u.L / u.s, + cdc = ac.CDC(coag_type = 'pacl'), + floc = ac.Flocculator(hl = 40 * u.cm), + sed = ac.Sedimentor(temp = 20 * u.degC), + filter = ac.Filter(q = 20 * u.L / u.s) + ) + +Example Usage: Core +******************* +.. code-block:: python + + # continued from Example Usage: Design + + # Model physical, chemical, and hydraulic properties + cdc = plant.cdc + coag_tube_reynolds_number = ac.re_pipe( + FlowRate = cdc.coag_q_max, + Diam = cdc.coag_tube_id, + Nu = cdc.coag_nu(cdc.coag_stock_conc, cdc.coag_type) + ) + +Example Usage: Research +*********************** +.. code-block:: python + + import aguaclara as ac + from aguaclara.core.units import u + import matplotlib.pyplot as plt + + # Plan a research experiment + reactor = ac.Variable_C_Stock( + Q_sys = 2 * u.mL / u.s, + C_sys = 1.4 * u.mg / u.L, + Q_stock = 0.01 * u.mL / u.s + ) + C_stock_PACl = reactor.C_stock() + + # Visualize and analyze ProCoDA data + ac.iplot_columns( + path = "https://raw.githubusercontent.com/AguaClara/team_resources/master/Data/datalog%206-14-2018.xls", + columns = [3, 4], + x_axis = 0 + ) + plt.ylabel("Turbidity (NTU)") + plt.xlabel("Time (hr)") + plt.legend(("Influent", "Effluent")) + +.. For more detailed tutorials and examples on using the package, refer to the :ref:`User Guide `. + +The package is still undergoing rapid development. As it becomes more stable, a user guide will be written with more detailed tutorials. +At the moment, you can find some more examples in specific pages of the :ref:`API reference `. + +Contributing +------------ +.. |aguaclara Github| replace:: ``aguaclara`` Github repository +.. _aguaclara Github: https://github.com/AguaClara/aguaclara + +Bug reports, features requests, documentation updates, and any other enhancements are welcome! To suggest a change, `make an issue `_ in the |aguaclara Github|_. -``aguaclara`` Reference ------------------------ -The following pages document the modules, functions, and values available in each sub-package. +To contribute to the package as a developer, refer to the :ref:`Developer Guide `. +Table of Contents +----------------- .. toctree:: - :maxdepth: 2 + :maxdepth: 1 - core/core - design/design - research/research + api + guide-dev \ No newline at end of file diff --git a/setup.py b/setup.py index 4160f6e3..7c058fb0 100644 --- a/setup.py +++ b/setup.py @@ -1,18 +1,30 @@ from setuptools import setup, find_packages +with open("README.md") as readme_file: + readme = readme_file.read() + setup( name = 'aguaclara', - version = '0.3.0', + version = '0.3.1', description = ( 'An open-source Python package for designing and performing research ' 'on AguaClara water treatment plants.' ), + long_description = readme, + long_description_content_type="text/markdown", url = 'https://github.com/AguaClara/aguaclara', + project_urls = { + "Documentation": "https://aguaclara.github.io/aguaclara/" + }, author = 'AguaClara Cornell', author_email = 'aguaclara@cornell.edu', license = 'MIT', + classifiers = [ + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + ], packages = find_packages(), - + # Ensure that this matches Pipfile > [packages] install_requires = [ 'matplotlib', @@ -30,4 +42,3 @@ test_suite="tests", zip_safe=False ) -# test