[![pre-commit.ci Status][pre-commit-ci-image]][pre-commit-ci-url]
[![Build Status][build-image]][build-url]
[![PyPI Version][pypi-image]][pypi-url]
<!-- Badges -->
[pre-commit-ci-image]: https://results.pre-commit.ci/badge/github/azogue/psychrochart/master.svg
[pre-commit-ci-url]: https://results.pre-commit.ci/latest/github/azogue/psychrochart/master
[build-image]: https://github.com/azogue/psychrochart/actions/workflows/main.yml/badge.svg
[build-url]: https://github.com/azogue/psychrochart/actions/workflows/main.yml
[pypi-image]: https://img.shields.io/pypi/v/psychrochart
[pypi-url]: https://pypi.org/project/psychrochart/
# Psychrochart
A python 3 library to make **[psychrometric charts](https://en.wikipedia.org/wiki/Psychrometrics)** and overlay information on them.
It implements a useful collection of psychrometric equations for moisture and humid air calculations, and the generation of beautiful and high customizable **psychrometric charts in SVG** with [`matplotlib`](https://matplotlib.org).
**Psychrometric calculations to make the chart data are done with [`PsychroLib`](https://github.com/psychrometrics/psychrolib)** (summary paper in https://doi.org/10.21105/joss.01137).
<img src="./tests/example-charts/chart_overlay_style_minimal.svg" width="100%" height="100%">
## Install
Get it **[from pypi](https://pypi.python.org/pypi?:action=display&name=psychrochart)** or **[clone it](https://github.com/azogue/psychrochart.git)** if you want to run the tests.
```shell
pip install psychrochart
```
## Features
- **SI** units (with temperatures in celsius for better readability), with _partial_ compatibility with IP system (imperial units)
- Easy style customization based on [**pydantic**](https://docs.pydantic.dev/latest/) models and config presets for full customization of **chart limits**, included lines and labels, colors, line styles, line widths, etc..
- Psychrometric charts within temperature and humidity ratio ranges, for any pressure\*, with:
- **Saturation line**
- **Constant RH lines**
- **Constant enthalpy lines**
- **Constant wet-bulb temperature lines**
- **Constant specific volume lines**
- **Constant dry-bulb temperature lines** (internal orthogonal grid, vertical)
- **Constant humidity ratio lines** (internal orthogonal grid, horizontal)
- Plot legend for each family of lines, labeled zones and annotations
- Specify labels for each family of lines
- Overlay points, arrows, **data-series** (numpy arrays or pandas series), and convex hulls around points
- Define multiple kinds of **zones limited by psychrometric values**:
- 'dbt-rh' for areas between dry-bulb temperature and relative humidity values,
- 'enthalpy-rh' for areas between constant enthalpy and relative humidity values
- 'volume-rh' for areas between constant volume and relative humidity values
- 'dbt-wmax' for an area between dry-bulb temperature and water vapor content values (:= a rectangle cut by the saturation line),
- 'xy-points' to define arbitrary closed paths in plot coordinates (dbt, abs humidity)
- **Export as SVG, PNG files**, or generate dynamic SVGs with extra CSS and <defs> with `chart.make_svg(...)`
> NOTE: The ranges of temperature, humidity and pressure where this library should provide good results are within the normal environments for people to live in.
>
> Don't expect right results if doing other type of thermodynamic calculations.
>
> ⚠️ **Over saturated water vapor states are not implemented**. This library is intended for HVAC applications only ⚠️
## Usage
```python
from psychrochart import PsychroChart
# Load default style:
chart_default = PsychroChart.create()
# customize anything
chart_default.limits.range_temp_c = (15.0, 35.0)
chart_default.limits.range_humidity_g_kg = (5, 25)
chart_default.config.saturation.linewidth = 1
chart_default.config.constant_wet_temp.color = "darkblue"
# plot
axes = chart_default.plot()
axes.get_figure()
# or store on disk
chart_default.save("my-custom-chart.svg")
```
Called from the terminal (`python psychrochart`), it plots and shows the default chart using the default matplotlib backend, equivalent to this python script:
```python
from psychrochart import PsychroChart
import matplotlib.pyplot as plt
PsychroChart.create().plot(ax=plt.gca())
plt.show()
```
### Chart customization
The default styling for charts is defined in JSON files that you can change, or you can pass a path of a file in JSON, or a dict, when you create the psychrometric chart object.
Included styles are: `default`, `ashrae`, `ashrae_ip` (adjusted for IP units), `interior`, and `minimal`.
```python
from pathlib import Path
from psychrochart import load_config, PsychroChart
# Load preconfigured styles:
chart_ashrae_style = PsychroChart.create('ashrae')
chart_ashrae_style.plot()
chart_minimal = PsychroChart.create('minimal')
chart_minimal.plot()
# Get a preconfigured style model and customize it
chart_config = load_config('interior')
chart_config.limits.range_temp_c = (18.0, 32.0)
chart_config.limits.range_humidity_g_kg = (1.0, 40.0)
chart_config.limits.altitude_m = 3000
custom_chart = PsychroChart.create(chart_config)
custom_chart.save("custom-chart.svg")
# serialize the config for future uses
assert chart_config.json() == custom_chart.config.json()
Path('path/to/chart_config_file.json').write_text(chart_config.json())
custom_chart_bis = PsychroChart.create('path/to/chart_config_file.json')
# or even the full psychrochart
Path('path/to/chart_file.json').write_text(custom_chart.json())
custom_chart_bis_2 = PsychroChart.parse_file('path/to/chart_file.json')
# Specify the styles JSON file:
chart_custom = PsychroChart.create('/path/to/json_file.json')
chart_custom.plot()
# Pass a dict with the changes wanted:
custom_style = {
"figure": {
"figsize": [12, 8],
"base_fontsize": 12,
"title": "My chart",
"x_label": None,
"y_label": None,
"partial_axis": False
},
"limits": {
"range_temp_c": [15, 30],
"range_humidity_g_kg": [0, 25],
"altitude_m": 900,
"step_temp": .5
},
"saturation": {"color": [0, .3, 1.], "linewidth": 2},
"constant_rh": {"color": [0.0, 0.498, 1.0, .7], "linewidth": 2.5,
"linestyle": ":"},
"chart_params": {
"with_constant_rh": True,
"constant_rh_curves": [25, 50, 75],
"constant_rh_labels": [25, 50, 75],
"with_constant_v": False,
"with_constant_h": False,
"with_constant_wet_temp": False,
"with_zones": False
},
"constant_v_annotation": {
"color":[0.2, 0.2, 0.2],
"fontsize":7,
"bbox": dict(boxstyle="square,pad=-0.2", color=[1, 1, 1, 0.9], lw=0.5)
},
"constant_h_annotation": {
"color":[0.2, 0.2, 0.2],
"fontsize":6,
"bbox": dict(boxstyle="square,pad=-0.1", color=[1, 1, 1, 0.9], lw=0.5)
},
"constant_wet_temp_annotation": {
"color":[0.2, 0.2, 0.2],
"fontsize":7,
"bbox": dict(boxstyle="square,pad=0", color=[1, 1, 1, 0.9], lw=0.5)
},
"constant_rh_annotation": {
"color":[0.2, 0.2, 0.2],
"fontsize":7,
"bbox": dict(boxstyle="square,pad=0", color=[1, 1, 1, 0.9], lw=0.5)
}
}
chart_custom_2 = PsychroChart.create(custom_style)
chart_custom_2.plot()
```
The custom configuration does not need to include all fields, but only the fields you want to change.
To play with it and see the results, look at this **[notebook with usage examples](https://github.com/azogue/psychrochart/blob/master/notebooks/Usage%20example%20of%20psychrochart.ipynb)**.
## Development and testing
To run the tests, clone the repository, `poetry install` it, and run `poetry run pytest`.
Run `poetry run pre-commit run --all-files` to apply linters for changes in the code 😜.
## License
[MIT license](https://github.com/azogue/psychrochart/blob/master/LICENSE), so do with it as you like ;-)
## Included styling examples
**Default style**:
<img src="./tests/example-charts/test_default_psychrochart.svg" width="100%" height="100%">
**ASHRAE Handbook black and white style**: (preset: `ashrae`)
<img src="./tests/example-charts/test_ashrae_psychrochart.svg" width="100%" height="100%">
**ASHRAE Handbook black and white style (IP units)**: (preset: `ashrae_ip`)
<img src="./tests/example-charts/test_ashrae_psychrochart_ip.svg" width="100%" height="100%">
**Minimal style**: (preset: `minimal`)
<img src="./tests/example-charts/test_minimal_psychrochart.svg" width="100%" height="100%">
Raw data
{
"_id": null,
"home_page": "https://github.com/azogue/psychrochart",
"name": "psychrochart",
"maintainer": null,
"docs_url": null,
"requires_python": "<3.13,>=3.10",
"maintainer_email": null,
"keywords": "psychrometrics, moist, humid air, climate control, matplotlib",
"author": "Eugenio Panadero",
"author_email": "eugenio.panadero@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/5b/c2/2352d920305b1d3ab55cf353aee0eaad962adf664f91f52915f45d601571/psychrochart-0.11.0.tar.gz",
"platform": null,
"description": "[![pre-commit.ci Status][pre-commit-ci-image]][pre-commit-ci-url]\n[![Build Status][build-image]][build-url]\n[![PyPI Version][pypi-image]][pypi-url]\n\n<!-- Badges -->\n\n[pre-commit-ci-image]: https://results.pre-commit.ci/badge/github/azogue/psychrochart/master.svg\n[pre-commit-ci-url]: https://results.pre-commit.ci/latest/github/azogue/psychrochart/master\n[build-image]: https://github.com/azogue/psychrochart/actions/workflows/main.yml/badge.svg\n[build-url]: https://github.com/azogue/psychrochart/actions/workflows/main.yml\n[pypi-image]: https://img.shields.io/pypi/v/psychrochart\n[pypi-url]: https://pypi.org/project/psychrochart/\n\n# Psychrochart\n\nA python 3 library to make **[psychrometric charts](https://en.wikipedia.org/wiki/Psychrometrics)** and overlay information on them.\n\nIt implements a useful collection of psychrometric equations for moisture and humid air calculations, and the generation of beautiful and high customizable **psychrometric charts in SVG** with [`matplotlib`](https://matplotlib.org).\n\n**Psychrometric calculations to make the chart data are done with [`PsychroLib`](https://github.com/psychrometrics/psychrolib)** (summary paper in https://doi.org/10.21105/joss.01137).\n\n<img src=\"./tests/example-charts/chart_overlay_style_minimal.svg\" width=\"100%\" height=\"100%\">\n\n## Install\n\nGet it **[from pypi](https://pypi.python.org/pypi?:action=display&name=psychrochart)** or **[clone it](https://github.com/azogue/psychrochart.git)** if you want to run the tests.\n\n```shell\npip install psychrochart\n```\n\n## Features\n\n- **SI** units (with temperatures in celsius for better readability), with _partial_ compatibility with IP system (imperial units)\n- Easy style customization based on [**pydantic**](https://docs.pydantic.dev/latest/) models and config presets for full customization of **chart limits**, included lines and labels, colors, line styles, line widths, etc..\n- Psychrometric charts within temperature and humidity ratio ranges, for any pressure\\*, with:\n - **Saturation line**\n - **Constant RH lines**\n - **Constant enthalpy lines**\n - **Constant wet-bulb temperature lines**\n - **Constant specific volume lines**\n - **Constant dry-bulb temperature lines** (internal orthogonal grid, vertical)\n - **Constant humidity ratio lines** (internal orthogonal grid, horizontal)\n- Plot legend for each family of lines, labeled zones and annotations\n- Specify labels for each family of lines\n- Overlay points, arrows, **data-series** (numpy arrays or pandas series), and convex hulls around points\n- Define multiple kinds of **zones limited by psychrometric values**:\n - 'dbt-rh' for areas between dry-bulb temperature and relative humidity values,\n - 'enthalpy-rh' for areas between constant enthalpy and relative humidity values\n - 'volume-rh' for areas between constant volume and relative humidity values\n - 'dbt-wmax' for an area between dry-bulb temperature and water vapor content values (:= a rectangle cut by the saturation line),\n - 'xy-points' to define arbitrary closed paths in plot coordinates (dbt, abs humidity)\n- **Export as SVG, PNG files**, or generate dynamic SVGs with extra CSS and <defs> with `chart.make_svg(...)`\n\n> NOTE: The ranges of temperature, humidity and pressure where this library should provide good results are within the normal environments for people to live in.\n>\n> Don't expect right results if doing other type of thermodynamic calculations.\n>\n> \u26a0\ufe0f **Over saturated water vapor states are not implemented**. This library is intended for HVAC applications only \u26a0\ufe0f\n\n## Usage\n\n```python\nfrom psychrochart import PsychroChart\n\n# Load default style:\nchart_default = PsychroChart.create()\n# customize anything\nchart_default.limits.range_temp_c = (15.0, 35.0)\nchart_default.limits.range_humidity_g_kg = (5, 25)\nchart_default.config.saturation.linewidth = 1\nchart_default.config.constant_wet_temp.color = \"darkblue\"\n# plot\naxes = chart_default.plot()\naxes.get_figure()\n# or store on disk\nchart_default.save(\"my-custom-chart.svg\")\n```\n\nCalled from the terminal (`python psychrochart`), it plots and shows the default chart using the default matplotlib backend, equivalent to this python script:\n\n```python\nfrom psychrochart import PsychroChart\nimport matplotlib.pyplot as plt\n\nPsychroChart.create().plot(ax=plt.gca())\nplt.show()\n```\n\n### Chart customization\n\nThe default styling for charts is defined in JSON files that you can change, or you can pass a path of a file in JSON, or a dict, when you create the psychrometric chart object.\nIncluded styles are: `default`, `ashrae`, `ashrae_ip` (adjusted for IP units), `interior`, and `minimal`.\n\n```python\nfrom pathlib import Path\nfrom psychrochart import load_config, PsychroChart\n\n# Load preconfigured styles:\nchart_ashrae_style = PsychroChart.create('ashrae')\nchart_ashrae_style.plot()\n\nchart_minimal = PsychroChart.create('minimal')\nchart_minimal.plot()\n\n# Get a preconfigured style model and customize it\nchart_config = load_config('interior')\nchart_config.limits.range_temp_c = (18.0, 32.0)\nchart_config.limits.range_humidity_g_kg = (1.0, 40.0)\nchart_config.limits.altitude_m = 3000\n\ncustom_chart = PsychroChart.create(chart_config)\ncustom_chart.save(\"custom-chart.svg\")\n\n# serialize the config for future uses\nassert chart_config.json() == custom_chart.config.json()\nPath('path/to/chart_config_file.json').write_text(chart_config.json())\ncustom_chart_bis = PsychroChart.create('path/to/chart_config_file.json')\n# or even the full psychrochart\nPath('path/to/chart_file.json').write_text(custom_chart.json())\ncustom_chart_bis_2 = PsychroChart.parse_file('path/to/chart_file.json')\n\n# Specify the styles JSON file:\nchart_custom = PsychroChart.create('/path/to/json_file.json')\nchart_custom.plot()\n\n# Pass a dict with the changes wanted:\ncustom_style = {\n \"figure\": {\n \"figsize\": [12, 8],\n \"base_fontsize\": 12,\n \"title\": \"My chart\",\n \"x_label\": None,\n \"y_label\": None,\n \"partial_axis\": False\n },\n \"limits\": {\n \"range_temp_c\": [15, 30],\n \"range_humidity_g_kg\": [0, 25],\n \"altitude_m\": 900,\n \"step_temp\": .5\n },\n \"saturation\": {\"color\": [0, .3, 1.], \"linewidth\": 2},\n \"constant_rh\": {\"color\": [0.0, 0.498, 1.0, .7], \"linewidth\": 2.5,\n \"linestyle\": \":\"},\n \"chart_params\": {\n \"with_constant_rh\": True,\n \"constant_rh_curves\": [25, 50, 75],\n \"constant_rh_labels\": [25, 50, 75],\n \"with_constant_v\": False,\n \"with_constant_h\": False,\n \"with_constant_wet_temp\": False,\n \"with_zones\": False\n },\n \"constant_v_annotation\": {\n \"color\":[0.2, 0.2, 0.2],\n \"fontsize\":7,\n \"bbox\": dict(boxstyle=\"square,pad=-0.2\", color=[1, 1, 1, 0.9], lw=0.5)\n },\n \"constant_h_annotation\": {\n \"color\":[0.2, 0.2, 0.2],\n \"fontsize\":6,\n \"bbox\": dict(boxstyle=\"square,pad=-0.1\", color=[1, 1, 1, 0.9], lw=0.5)\n },\n \"constant_wet_temp_annotation\": {\n \"color\":[0.2, 0.2, 0.2],\n \"fontsize\":7,\n \"bbox\": dict(boxstyle=\"square,pad=0\", color=[1, 1, 1, 0.9], lw=0.5)\n },\n \"constant_rh_annotation\": {\n \"color\":[0.2, 0.2, 0.2],\n \"fontsize\":7,\n \"bbox\": dict(boxstyle=\"square,pad=0\", color=[1, 1, 1, 0.9], lw=0.5)\n }\n}\n\nchart_custom_2 = PsychroChart.create(custom_style)\nchart_custom_2.plot()\n```\n\nThe custom configuration does not need to include all fields, but only the fields you want to change.\n\nTo play with it and see the results, look at this **[notebook with usage examples](https://github.com/azogue/psychrochart/blob/master/notebooks/Usage%20example%20of%20psychrochart.ipynb)**.\n\n## Development and testing\n\nTo run the tests, clone the repository, `poetry install` it, and run `poetry run pytest`.\n\nRun `poetry run pre-commit run --all-files` to apply linters for changes in the code \ud83d\ude1c.\n\n## License\n\n[MIT license](https://github.com/azogue/psychrochart/blob/master/LICENSE), so do with it as you like ;-)\n\n## Included styling examples\n\n**Default style**:\n\n<img src=\"./tests/example-charts/test_default_psychrochart.svg\" width=\"100%\" height=\"100%\">\n\n**ASHRAE Handbook black and white style**: (preset: `ashrae`)\n\n<img src=\"./tests/example-charts/test_ashrae_psychrochart.svg\" width=\"100%\" height=\"100%\">\n\n**ASHRAE Handbook black and white style (IP units)**: (preset: `ashrae_ip`)\n\n<img src=\"./tests/example-charts/test_ashrae_psychrochart_ip.svg\" width=\"100%\" height=\"100%\">\n\n**Minimal style**: (preset: `minimal`)\n\n<img src=\"./tests/example-charts/test_minimal_psychrochart.svg\" width=\"100%\" height=\"100%\">\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A python 3 library to make psychrometric charts and overlay information on them",
"version": "0.11.0",
"project_urls": {
"Homepage": "https://github.com/azogue/psychrochart",
"Repository": "https://github.com/azogue/psychrochart"
},
"split_keywords": [
"psychrometrics",
" moist",
" humid air",
" climate control",
" matplotlib"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "635f6fd28f5210604d0a22132332d87efbb65f409798a71a4f89827a7ec1cfdb",
"md5": "6f3590394bf47f5ab0c93e912555dc37",
"sha256": "5f7ecc4ed4bcdc208b379ac8ed2e006500e7d0120c96d661a54edb786a233e4e"
},
"downloads": -1,
"filename": "psychrochart-0.11.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6f3590394bf47f5ab0c93e912555dc37",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<3.13,>=3.10",
"size": 47097,
"upload_time": "2024-04-08T17:39:07",
"upload_time_iso_8601": "2024-04-08T17:39:07.744571Z",
"url": "https://files.pythonhosted.org/packages/63/5f/6fd28f5210604d0a22132332d87efbb65f409798a71a4f89827a7ec1cfdb/psychrochart-0.11.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5bc22352d920305b1d3ab55cf353aee0eaad962adf664f91f52915f45d601571",
"md5": "8c96bac3333d7735d53f9036e209d3a3",
"sha256": "5672ec7143a88300bed3f02e9f448baa577c46222b21b3dfb232d055fb82b012"
},
"downloads": -1,
"filename": "psychrochart-0.11.0.tar.gz",
"has_sig": false,
"md5_digest": "8c96bac3333d7735d53f9036e209d3a3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<3.13,>=3.10",
"size": 40536,
"upload_time": "2024-04-08T17:39:09",
"upload_time_iso_8601": "2024-04-08T17:39:09.299897Z",
"url": "https://files.pythonhosted.org/packages/5b/c2/2352d920305b1d3ab55cf353aee0eaad962adf664f91f52915f45d601571/psychrochart-0.11.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-08 17:39:09",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "azogue",
"github_project": "psychrochart",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "psychrochart"
}