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
18 changes: 18 additions & 0 deletions examples/pycuc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# pycuc Examples

Each sub-directory contains a self-contained example. The order in
which the examples are to appear is specified in `order.json` (an
array of directory names in the expected order).

In each example directory you'll find:

* `config.toml` - must conform to the specification outlined here:
https://docs.pyscript.net/latest/user-guide/configuration/ This is
parsed and ultimately turned into a JSON representation as part of
the package's API object.
* `setup.py` - Python code for contextual and environmental setup,
NOT SEEN BY THE END USER, but is run before the `code.py` code is
evaluated. Allows us to create useful (IPython) shims, avoid
repeating boilerplate and whatnot.
* `code.py` - the actual code added to the editor which forms the
practical example of using the package.
48 changes: 48 additions & 0 deletions examples/pycuc/converter_objects/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# ---------------------------------------------------------------------
# Reusable converter objects with create_cuc()
# ---------------------------------------------------------------------
import pycuc


heading("Carry a value around as a converter object")
note(
"When the same quantity is expressed in many units, "
"pycuc.create_cuc(value, unit) wraps it in a small object whose "
".convert(target) method returns the value in any compatible unit."
)

# A weather station logged a gust of 22 m/s. Let's express it in a few
# transport-friendly units without retyping the value each time.
wind_gust = pycuc.create_cuc(22, "m/s")

reports = {
"km/h": wind_gust.convert("km/h"),
"mph": wind_gust.convert("mph"),
"knot": wind_gust.convert("knot"),
"ft/s": wind_gust.convert("ft/s"),
}

note("A 22 m/s gust, in several velocity units:")
for unit, value in reports.items():
note(f"&nbsp;&nbsp;<strong>{value:7.2f}</strong> {unit}")

heading("A small conversion table")
note(
"Build a tidy table of energy values by looping over a list of "
"target units. The same pattern works for any PyCUC category."
)

battery_energy = pycuc.create_cuc(1.5, "kWh")
energy_units = ["J", "kJ", "Wh", "kWh", "cal", "kcal", "BTU"]

rows = "".join(
f"<tr><td>{unit}</td>"
f"<td style='text-align:right'>{battery_energy.convert(unit):,.3f}</td></tr>"
for unit in energy_units
)
table_html = (
"<table border='1' cellpadding='6' style='border-collapse:collapse'>"
"<tr><th>Unit</th><th>1.5 kWh as...</th></tr>"
f"{rows}</table>"
)
display(HTML(table_html), append=True)
1 change: 1 addition & 0 deletions examples/pycuc/converter_objects/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
packages = ["pycuc"]
20 changes: 20 additions & 0 deletions examples/pycuc/converter_objects/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Lightweight setup for the second example. Mirrors the names from cell 1."""
import js
from pyscript import window, HTML, display as _display

js.alert = window.alert


def display(*args, **kwargs):
return _display(
*args, **kwargs, target=__pyscript_display_target__,
)


def heading(text, level=2):
display(HTML(f"<h{level}>{text}</h{level}>"), append=True)


def note(text):
display(HTML(f"<p>{text}</p>"), append=True)

42 changes: 42 additions & 0 deletions examples/pycuc/custom_units/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ---------------------------------------------------------------------
# Defining your own units with add_custom_unit()
# ---------------------------------------------------------------------
import pycuc


heading("Teaching PyCUC a new unit")
note(
"Suppose your team measures heat capacity in J/mol.K and kJ/mol.K, "
"and you'd like PyCUC to handle that family. add_custom_unit(name, "
"factor) registers each unit relative to a chosen reference value "
"of 1."
)

# Start from a measured heat capacity in J/(mol.K).
heat_capacity = pycuc.create_cuc(75.3, "J/mol.K")

# Register the family. The factor is "how many of the reference unit
# (J/mol.K, factor 1) make up one of this unit". So 1 kJ/mol.K is
# 1000 J/mol.K.
heat_capacity.add_custom_unit("J/mol.K", 1)
heat_capacity.add_custom_unit("kJ/mol.K", 1000)
heat_capacity.add_custom_unit("cal/mol.K", 4.184)

note("The same value, expressed across our newly defined units:")
for unit in ["J/mol.K", "kJ/mol.K", "cal/mol.K"]:
note(f"&nbsp;&nbsp;<strong>{heat_capacity.convert(unit):.4f}</strong> {unit}")

heading("Inspecting the custom registry")
note(
"check_reference('custom') returns the units you have added on "
"this converter object, alongside their conversion factors."
)
display(heat_capacity.check_reference("custom"), append=True)

heading("Mixing built-in and custom units")
note(
"Built-in references stay available on the same object. Here we "
"ask the same converter about pressure units, which PyCUC ships "
"with out of the box."
)
display(heat_capacity.check_reference("pressure"), append=True)
1 change: 1 addition & 0 deletions examples/pycuc/custom_units/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
packages = ["pycuc"]
20 changes: 20 additions & 0 deletions examples/pycuc/custom_units/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Lightweight setup for the third example."""
import js
from pyscript import window, HTML, display as _display

js.alert = window.alert


def display(*args, **kwargs):
return _display(
*args, **kwargs, target=__pyscript_display_target__,
)


def heading(text, level=2):
display(HTML(f"<h{level}>{text}</h{level}>"), append=True)


def note(text):
display(HTML(f"<p>{text}</p>"), append=True)

5 changes: 5 additions & 0 deletions examples/pycuc/order.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[
"quick_conversions",
"converter_objects",
"custom_units"
]
56 changes: 56 additions & 0 deletions examples/pycuc/quick_conversions/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
A first look at PyCUC: convert quantities between units in a single
line, using either a from/to pair or a compact "MPa => Pa" string.

PyCUC bundles conversions for many physical quantities (pressure,
temperature, energy, length, mass, volume, ...). See the project
docs at https://github.com/sinagilassi/pycuc for the full list.
"""
from IPython.core.display import display, HTML
import pycuc


heading("Reactor pressure: from megapascals to friendlier units")
note(
"An engineer recorded a reactor pressure of 2.5 MPa and wants "
"to share it in pascals, bar, and psi for different audiences."
)

reactor_pressure_mpa = 2.5

# convert_from_to(value, from_unit, to_unit) is the most explicit form.
in_pascals = pycuc.convert_from_to(reactor_pressure_mpa, "MPa", "Pa")
in_bar = pycuc.convert_from_to(reactor_pressure_mpa, "MPa", "bar")
in_psi = pycuc.convert_from_to(reactor_pressure_mpa, "MPa", "psi")

note(
f"{reactor_pressure_mpa} MPa is "
f"<strong>{in_pascals:,.0f} Pa</strong>, "
f"<strong>{in_bar:.2f} bar</strong>, "
f"and <strong>{in_psi:.2f} psi</strong>."
)

heading("The shorthand: pycuc.to(value, 'from => to')")
note(
"If you prefer something terser, pycuc.to() takes a single "
"string describing the conversion."
)

oven_temperature_c = 180.0
oven_in_kelvin = pycuc.to(oven_temperature_c, "C => K")
oven_in_fahrenheit = pycuc.to(oven_temperature_c, "C => F")

note(
f"An oven at {oven_temperature_c} &deg;C is "
f"<strong>{oven_in_kelvin:.2f} K</strong> or "
f"<strong>{oven_in_fahrenheit:.1f} &deg;F</strong>."
)

heading("Discovering what units are available")
note(
"pycuc.check_reference(category) lists the units PyCUC knows "
"about for a given quantity. Here are the pressure units:"
)

pressure_units = pycuc.check_reference("pressure")
display(pressure_units, append=True)
1 change: 1 addition & 0 deletions examples/pycuc/quick_conversions/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
packages = ["pycuc"]
42 changes: 42 additions & 0 deletions examples/pycuc/quick_conversions/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
Shim IPython's display API onto PyScript so example code written in a
Jupyter/IPython idiom runs unmodified in the browser.
"""

import sys
import types
import js
from pyscript import window, HTML, display as _display

js.alert = window.alert


def display(*args, **kwargs):
"""Wrap pyscript.display so output lands in the example target."""
return _display(
*args, **kwargs, target=__pyscript_display_target__,
)


ipython = types.ModuleType("IPython")
core = types.ModuleType("IPython.core")
core_display = types.ModuleType("IPython.core.display")
core_display.display = display
core_display.HTML = HTML
ipython.core = core
core.display = core_display
ipython.get_ipython = lambda: None
ipython.display = core_display
sys.modules["IPython"] = ipython
sys.modules["IPython.core"] = core
sys.modules["IPython.core.display"] = core_display
sys.modules["IPython.display"] = core_display


def heading(text, level=2):
display(HTML(f"<h{level}>{text}</h{level}>"), append=True)


def note(text):
display(HTML(f"<p>{text}</p>"), append=True)