Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre-Condensation 3- activity #458

Merged
merged 38 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5e3f732
moved atmo
Gorkowski May 25, 2024
60d3662
added test
Gorkowski May 25, 2024
94bd0c1
updated species and test
Gorkowski May 25, 2024
3857332
add species/test
Gorkowski May 25, 2024
2f1b60d
test imports fixed
Gorkowski May 25, 2024
f73497a
update aerosol and runnables so they work with atmosphere
Gorkowski May 25, 2024
69d811c
update aerosol for atmo
Gorkowski May 25, 2024
dfe9fc3
clean up
Gorkowski May 25, 2024
ae8f689
update vapor example
Gorkowski May 25, 2024
355c4b4
abstracted builder checks and added draft examples
Gorkowski May 25, 2024
fa3b45a
refactored out abc builder
Gorkowski May 25, 2024
02b052c
adding species builder
Gorkowski May 25, 2024
72849f1
removed example to add in different pr
Gorkowski May 25, 2024
a997416
added species build test
Gorkowski May 25, 2024
0a55c28
added species builder tests
Gorkowski May 25, 2024
8f938b7
added atmosphere builder
Gorkowski May 25, 2024
dbe3e73
extending test on atmo builder
Gorkowski May 25, 2024
2bf9139
fixed temperature unit convert, added optional value param
Gorkowski May 25, 2024
3e08c72
expanded atmo builder docs
Gorkowski May 26, 2024
2c1d578
clean builder imports
Gorkowski May 26, 2024
1f4304b
changed similar
Gorkowski May 26, 2024
1a628f3
updated builder example
Gorkowski May 26, 2024
62f6933
rename gas species in tests
Gorkowski May 26, 2024
f7f9f54
update suffix atmo
Gorkowski May 26, 2024
ebc3e11
change abc builder to named expressions
Gorkowski May 26, 2024
6727202
updates in species and convert
Gorkowski May 26, 2024
18afdc0
fixed lint
Gorkowski May 26, 2024
6801c45
added particle activity
Gorkowski May 26, 2024
d8b4a73
add mass conc to mole frac in convert
Gorkowski May 26, 2024
e93d455
reorg layout, strat, builder, factory
Gorkowski May 26, 2024
6485f48
lint edit
Gorkowski May 26, 2024
9f72b7c
fixed temp convert in vapor pressure, and started build activity
Gorkowski May 26, 2024
71740e1
drafted activity builder
Gorkowski May 26, 2024
2c7b241
clean pyright ignore
Gorkowski May 26, 2024
70e2322
activity builder tested
Gorkowski May 26, 2024
93be826
update imports in builder test
Gorkowski May 26, 2024
26ce31f
test added for activity factories
Gorkowski May 26, 2024
51e6eb6
fixed type in builder test
Gorkowski May 26, 2024
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
60 changes: 35 additions & 25 deletions docs/documentation/next/next_vapor_pressure.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -103,7 +103,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 6,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -168,19 +168,27 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[ERROR|vapor_pressure_builders|L120]: Required parameter(s) not set: b, c\n"
]
},
{
"ename": "ValueError",
"evalue": "Missing coefficients: c",
"evalue": "Required parameter(s) not set: b, c",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[3], line 6\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# failed build due to missing parameters\u001b[39;00m\n\u001b[0;32m 2\u001b[0m styrene_fail \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m 3\u001b[0m \u001b[43mvapor_pressure_builders\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mAntoineBuilder\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mset_a\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstyrene_coefficients\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43ma\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 5\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mset_b\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstyrene_coefficients\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mb\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m----> 6\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbuild\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 7\u001b[0m )\n",
"File \u001b[1;32mC:\\GitHub\\particula\\particula\\next\\gas\\vapor_pressure_builders.py:89\u001b[0m, in \u001b[0;36mAntoineBuilder.build\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 87\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m [\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39ma, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mb, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mc]:\n\u001b[0;32m 88\u001b[0m missing \u001b[38;5;241m=\u001b[39m [p \u001b[38;5;28;01mfor\u001b[39;00m p \u001b[38;5;129;01min\u001b[39;00m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ma\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mc\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, p) \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m]\n\u001b[1;32m---> 89\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mMissing coefficients: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(missing)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 90\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m AntoineVaporPressureStrategy(\n\u001b[0;32m 91\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39ma, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mb, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mc)\n",
"\u001b[1;31mValueError\u001b[0m: Missing coefficients: c"
"Cell \u001b[1;32mIn[7], line 5\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# failed build due to missing parameters\u001b[39;00m\n\u001b[0;32m 2\u001b[0m styrene_fail \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m 3\u001b[0m \u001b[43mvapor_pressure_builders\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mAntoineBuilder\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mset_a\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstyrene_coefficients\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43ma\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m----> 5\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbuild\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 6\u001b[0m )\n",
"File \u001b[1;32mC:\\GitHub\\particula\\particula\\next\\gas\\vapor_pressure_builders.py:191\u001b[0m, in \u001b[0;36mAntoineBuilder.build\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 188\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mbuild\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m 189\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Build the AntoineVaporPressureStrategy object with the set\u001b[39;00m\n\u001b[0;32m 190\u001b[0m \u001b[38;5;124;03m coefficients.\"\"\"\u001b[39;00m\n\u001b[1;32m--> 191\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpre_build_check\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 192\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m AntoineVaporPressureStrategy(\n\u001b[0;32m 193\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39ma, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mb, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mc)\n",
"File \u001b[1;32mC:\\GitHub\\particula\\particula\\next\\gas\\vapor_pressure_builders.py:122\u001b[0m, in \u001b[0;36mBuilderBase.pre_build_check\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 119\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m missing:\n\u001b[0;32m 120\u001b[0m logger\u001b[38;5;241m.\u001b[39merror(\n\u001b[0;32m 121\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRequired parameter(s) not set: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(missing))\n\u001b[1;32m--> 122\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 123\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRequired parameter(s) not set: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(missing)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
"\u001b[1;31mValueError\u001b[0m: Required parameter(s) not set: b, c"
]
}
],
Expand All @@ -189,7 +197,6 @@
"styrene_fail = (\n",
" vapor_pressure_builders.AntoineBuilder()\n",
" .set_a(styrene_coefficients['a'])\n",
" .set_b(styrene_coefficients['b'])\n",
" .build()\n",
")"
]
Expand Down Expand Up @@ -473,7 +480,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -553,7 +560,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -585,7 +592,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -615,7 +622,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -727,46 +734,49 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on function vapor_pressure_factory in module particula.next.gas.vapor_pressure:\n",
"Help on function vapor_pressure_factory in module particula.next.gas.vapor_pressure_factories:\n",
"\n",
"vapor_pressure_factory(strategy: str, **kwargs) -> particula.next.gas.vapor_pressure.VaporPressureStrategy\n",
" Factory method to create a concrete VaporPressureStrategy object.\n",
"vapor_pressure_factory(strategy: str, parameters: Optional[dict] = None) -> particula.next.gas.vapor_pressure_strategies.VaporPressureStrategy\n",
" Factory method to create a concrete VaporPressureStrategy object using\n",
" builders.\n",
" \n",
" Args:\n",
" ----\n",
" - strategy (str): The strategy to use for vapor pressure calculations.\n",
" options: \"constant\", \"antoine\", \"clausius_clapeyron\", \"water_buck\".\n",
" - **kwargs: Additional keyword arguments required for the strategy.\n",
" Options: \"constant\", \"antoine\", \"clausius_clapeyron\", \"water_buck\".\n",
" - parameters (dict): A dictionary containing the necessary parameters for\n",
" the strategy. If no parameters are needed, this can be left as None.\n",
" \n",
" Returns:\n",
" -------\n",
" - vapor_pressure_strategy (VaporPressureStrategy): A concrete\n",
" implementation of the VaporPressureStrategy.\n",
" implementation of the VaporPressureStrategy built using the appropriate\n",
" builder.\n",
"\n"
]
}
],
"source": [
"help(vapor_pressure_strategies.vapor_pressure_factory)"
"help(vapor_pressure_factory)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on class ConstantVaporPressureStrategy in module particula.next.gas.vapor_pressure:\n",
"Help on class ConstantVaporPressureStrategy in module particula.next.gas.vapor_pressure_strategies:\n",
"\n",
"class ConstantVaporPressureStrategy(VaporPressureStrategy)\n",
" | ConstantVaporPressureStrategy(vapor_pressure: Union[float, numpy.ndarray[Any, numpy.dtype[numpy.float64]]])\n",
Expand Down Expand Up @@ -885,7 +895,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -1019,7 +1029,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -1166,7 +1176,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": null,
"metadata": {},
"outputs": [
{
Expand Down
141 changes: 141 additions & 0 deletions particula/next/abc_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""Abstract Base Class for Builder classes"""

from abc import ABC, abstractmethod
from typing import Any, Optional
import logging

logger = logging.getLogger("particula")


class BuilderABC(ABC):
"""Abstract base class for builders with common methods to check keys and
set parameters from a dictionary.

Attributes:
----------
- required_parameters (list): List of required parameters for the builder.

Methods:
-------
- check_keys(parameters): Check if the keys you want to set are
present in the parameters dictionary.
- set_parameters(parameters): Set parameters from a dictionary including
optional suffix for units as '_units'.
- pre_build_check(): Check if all required attribute parameters are set
before building.

Abstract Methods:
-----------------
- build(): Build and return the strategy object with the set parameters.

Raises:
------
- ValueError: If any required key is missing during check_keys or
pre_build_check, or if trying to set an invalid parameter.
- Warning: If using default units for any parameter.
"""

def __init__(self, required_parameters: Optional[list[str]] = None):
self.required_parameters = required_parameters or []

def check_keys(self, parameters: dict[str, Any]):
"""Check if the keys you want to set are present in the
parameters dictionary and if all keys are valid.

Args:
----
- parameters (dict): The parameters dictionary to check.

Returns:
-------
- None

Raises:
------
- ValueError: If any required key is missing or if trying to set an
invalid parameter.
"""

# Check if all required keys are present
if missing := [p for p in self.required_parameters
if p not in parameters]:
error_message = (
f"Missing required parameter(s): {', '.join(missing)}"
)
logger.error(error_message)
raise ValueError(error_message)

# Generate a set of all valid keys
valid_keys = set(
self.required_parameters +
[f"{key}_units" for key in self.required_parameters]
)
# Check for any invalid keys and handle them within the if condition
if invalid_keys := [key for key in parameters
if key not in valid_keys]:
error_message = (
f"Trying to set an invalid parameter(s) '{invalid_keys}'. "
f"The valid parameter(s) '{valid_keys}'."
)
logger.error(error_message)
raise ValueError(error_message)

def set_parameters(self, parameters: dict[str, Any]):
"""Set parameters from a dictionary including optional suffix for
units as '_units'.

Args:
----
- parameters (dict): The parameters dictionary to set.

Returns:
-------
- self: The builder object with the set parameters.

Raises:
------
- ValueError: If any required key is missing.
- Warning: If using default units for any parameter.
"""
self.check_keys(parameters)
for key in self.required_parameters:
unit_key = f'{key}_units'
if unit_key in parameters:
# Call set method with units
getattr(
self,
f'set_{key}')(
parameters[key],
parameters[unit_key])
else:
logger.warning("Using default units for parameter: '%s'.", key)
# Call set method without units
getattr(self, f'set_{key}')(parameters[key])
return self

def pre_build_check(self):
"""Check if all required attribute parameters are set before building.

Returns:
-------
- None

Raises:
------
- ValueError: If any required parameter is missing.
"""
if missing := [p for p in self.required_parameters
if getattr(self, p) is None]:
error_message = (
f"Required parameter(s) not set: {', '.join(missing)}")
logger.error(error_message)
raise ValueError(error_message)

@abstractmethod
def build(self) -> Any:
"""Build and return the strategy object with the set parameters.

Returns:
-------
- strategy: The built strategy object.
"""
Loading