{ "cells": [ { "cell_type": "markdown", "id": "f3dc7bfc", "metadata": {}, "source": [ "# Wolf_Param & Project — Parameter management\n", "\n", "- **`Wolf_Param`** — hierarchical parameter container (groups → keys → typed values)\n", "- **`key_Param`** / **`Type_Param`** — enums for parameter structure and typing\n", "- **`Wolf2D_Project`** — project files linking simulations, vectors, and palettes\n", "\n", "> `Wolf_Param` inherits from `wx.Frame` but works **headlessly** when no `wx.App`\n", "> is running (or when `init_GUI=False`). All examples below run without GUI." ] }, { "cell_type": "markdown", "id": "fca3e4b0", "metadata": {}, "source": [ "## Internal structure\n", "\n", "Each parameter is a `dict` keyed by `key_Param` enum values:\n", "\n", "```python\n", "{\n", " key_Param.NAME: \"dt\",\n", " key_Param.TYPE: Type_Param.Float,\n", " key_Param.VALUE: \"0.5\", # always stored as str\n", " key_Param.COMMENT: \"Time step [s]\",\n", " key_Param.ADDED_JSON: None,\n", " key_Param.ENUM_CHOICES: None,\n", "}\n", "```\n", "\n", "Parameters are organized in groups. `Wolf_Param.myparams` is a `dict[str, dict]`:\n", "\n", "```\n", "myparams = {\n", " \"simulation\": { \"dt\": {...}, \"duration\": {...} },\n", " \"mesh\": { \"dx\": {...}, \"nx\": {...} },\n", "}\n", "```\n", "\n", "Available types (`Type_Param`): `Integer`, `Float`, `Double`, `Logical`,\n", "`String`, `File`, `Directory`, `Color`, `Enum`, `Empty`, …" ] }, { "cell_type": "code", "execution_count": 1, "id": "d2212fc1", "metadata": {}, "outputs": [], "source": [ "from wolfhece.PyParams import Wolf_Param, Type_Param, key_Param" ] }, { "cell_type": "markdown", "id": "bd3ad5e7", "metadata": {}, "source": [ "## Creating parameters from scratch (headless)" ] }, { "cell_type": "code", "execution_count": 2, "id": "b7f68e42", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Groups: ['simulation', 'mesh']\n", "Params in 'simulation': ['duration', 'dt', 'nsteps', 'verbose']\n", "Params in 'mesh': ['dx', 'dy', 'nx', 'ny']\n" ] } ], "source": [ "# Create an empty Wolf_Param (no file, no GUI)\n", "p = Wolf_Param(to_read=False, init_GUI=False, title='My simulation')\n", "\n", "# Add a group with typed parameters\n", "p.addparam('simulation', 'duration', '3600', Type_Param.Float, 'Simulation duration [s]')\n", "p.addparam('simulation', 'dt', '0.5', Type_Param.Float, 'Time step [s]')\n", "p.addparam('simulation', 'nsteps', '100', Type_Param.Integer, 'Output steps')\n", "p.addparam('simulation', 'verbose', '1', Type_Param.Logical, 'Verbose output')\n", "\n", "# Add another group\n", "p.addparam('mesh', 'dx', '1.0', Type_Param.Float, 'Cell size X [m]')\n", "p.addparam('mesh', 'dy', '1.0', Type_Param.Float, 'Cell size Y [m]')\n", "p.addparam('mesh', 'nx', '200', Type_Param.Integer, 'Number of cells X')\n", "p.addparam('mesh', 'ny', '150', Type_Param.Integer, 'Number of cells Y')\n", "\n", "# List groups\n", "print(\"Groups:\", p.get_group_keys())\n", "print(\"Params in 'simulation':\", p.get_param_keys('simulation'))\n", "print(\"Params in 'mesh':\", p.get_param_keys('mesh'))" ] }, { "cell_type": "markdown", "id": "931c9afc", "metadata": {}, "source": [ "## Reading and modifying parameters\n", "\n", "Values are accessed via `__getitem__` with a `(group, key)` tuple.\n", "The return is **automatically typed** (int, float, bool, str) according to `Type_Param`." ] }, { "cell_type": "code", "execution_count": 14, "id": "08f1160b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dt = 0.25 (type: float)\n", "nsteps = 100 (type: int)\n", "verbose = 1 (type: str)\n", "manning = 0.035 (from default, group doesn't exist yet)\n", "\n", "dt after modification: 0.25\n", "\n", "Full dict for 'dt': {'name': 'dt', 'type': , 'value': 0.25, 'comment': 'Time step [s]', 'added_json': None, 'enum_choices': None}\n" ] } ], "source": [ "# --- Read values (auto-typed) ---\n", "dt = p[('simulation', 'dt')]\n", "print(f\"dt = {dt} (type: {type(dt).__name__})\")\n", "\n", "nsteps = p[('simulation', 'nsteps')]\n", "print(f\"nsteps = {nsteps} (type: {type(nsteps).__name__})\")\n", "\n", "verbose = p[('simulation', 'verbose')]\n", "print(f\"verbose = {verbose} (type: {type(verbose).__name__})\")\n", "\n", "# --- Alternative: get_param with default fallback ---\n", "manning = p.get_param('physics', 'manning', default_value=0.035)\n", "print(f\"manning = {manning} (from default, group doesn't exist yet)\")\n", "\n", "# --- Modify a value ---\n", "p[('simulation', 'dt')] = 0.25\n", "print(f\"\\ndt after modification: {p[('simulation', 'dt')]}\")\n", "\n", "# --- Get the full parameter dict ---\n", "dt_dict = p.get_param_dict('simulation', 'dt')\n", "print(f\"\\nFull dict for 'dt': { {k.value: v for k, v in dt_dict.items()} }\")" ] }, { "cell_type": "markdown", "id": "7a95c15c", "metadata": {}, "source": [ "## Iterating over all groups and parameters" ] }, { "cell_type": "code", "execution_count": 15, "id": "ab2f8722", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "[simulation] (5 active params)\n", " duration = 3600.0 (Float ) # Simulation duration [s]\n", " dt = 0.25 (Float ) # Time step [s]\n", " nsteps = 100 (Integer ) # Output steps\n", " verbose = 1 (Logical ) # Verbose output\n", " solver = Solver.EXPLICIT (Enum ) # Numerical solver\n", "\n", "[mesh] (4 active params)\n", " dx = 1.0 (Float ) # Cell size X [m]\n", " dy = 1.0 (Float ) # Cell size Y [m]\n", " nx = 200 (Integer ) # Number of cells X\n", " ny = 150 (Integer ) # Number of cells Y\n" ] } ], "source": [ "for group in p.get_group_keys():\n", " nb_active, nb_default = p.get_nb_params(group)\n", " print(f\"\\n[{group}] ({nb_active} active params)\")\n", " for key in p.get_param_keys(group):\n", " val = p[(group, key)]\n", " typ = p.get_type(group, key)\n", " comment = p.get_help(group, key)[0]\n", " print(f\" {key:15s} = {str(val):10s} ({typ.value:8s}) # {comment}\")" ] }, { "cell_type": "markdown", "id": "1a21c1b2", "metadata": {}, "source": [ "## Saving and loading parameter files\n", "\n", "The file format is tab-separated: `group_name:` on its own line,\n", "then `key\\tvalue\\tcomment (Type)` for each parameter." ] }, { "cell_type": "code", "execution_count": 16, "id": "ef2d3de2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Saved file content:\n", " simulation:\n", "duration\t3600\n", "dt\t0.25\n", "nsteps\t100\n", "verbose\t1\n", "solver\tSolver.EXPLICIT\n", " mesh:\n", "dx\t1.0\n", "dy\t1.0\n", "nx\t200\n", "ny\t150\n", "\n", "\n", "Reloaded groups: ['simulation', 'mesh']\n", "dt = 0.25\n" ] } ], "source": [ "import tempfile\n", "from pathlib import Path\n", "\n", "tmpdir = Path(tempfile.mkdtemp())\n", "param_file = tmpdir / 'simulation.param'\n", "\n", "# Save to file\n", "p.Save(str(param_file))\n", "print(\"Saved file content:\")\n", "print(param_file.read_text())\n", "\n", "# Reload from file\n", "p2 = Wolf_Param(filename=str(param_file), to_read=True, init_GUI=False)\n", "print(f\"\\nReloaded groups: {p2.get_group_keys()}\")\n", "print(f\"dt = {p2[('simulation', 'dt')]}\")" ] }, { "cell_type": "markdown", "id": "9ce9c8e4", "metadata": {}, "source": [ "## Active vs Default values\n", "\n", "`Wolf_Param` maintains **two parallel dictionaries**:\n", "\n", "| Dict | Role |\n", "|------|------|\n", "| `myparams` | **Active** values — what the simulation actually uses |\n", "| `myparams_default` | **Default** values — reference / factory settings |\n", "\n", "When reading a `.param` file, the code also looks for a `.param.default`\n", "companion file. If none exists, the current values are copied as defaults.\n", "\n", "The `whichdict` argument of `addparam()` controls where a parameter is stored:\n", "\n", "| `whichdict` | Stored in |\n", "|-------------|-----------|\n", "| `''` or `'All'` | **Both** active and default |\n", "| `'Active'` | Active only |\n", "| `'Default'` | Default only |\n", "\n", "**Reading** with `p[(group, key)]` (i.e. `get_param`) checks active first,\n", "then falls back to default. This means you can delete a param from active\n", "and the default value will transparently take over." ] }, { "cell_type": "code", "execution_count": 17, "id": "60681421", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Active groups: ['physics']\n", "Default groups: ['physics']\n", "\n", "gravity (active) = 9.81\n", "manning active = 0.05\n", "manning default = 0.035\n", "\n", "is_in_active('physics', 'manning')? True\n", "is_in_default('physics', 'manning')? True\n", "\n", "physics: 2 active params, 2 default params\n", "\n", "rho in active? True\n", "rho in default? False\n", "\n", "manning after cleanup = 0.035 (falls back to default)\n" ] } ], "source": [ "# --- Add params to different dicts ---\n", "pd = Wolf_Param(to_read=False, init_GUI=False, title='Active vs Default demo')\n", "\n", "# By default (whichdict=''), params go to BOTH active and default\n", "pd.addparam('physics', 'gravity', '9.81', Type_Param.Float, 'Gravitational acceleration')\n", "pd.addparam('physics', 'manning', '0.035', Type_Param.Float, 'Manning coefficient')\n", "\n", "print(\"Active groups:\", pd.get_group_keys())\n", "print(\"Default groups:\", pd.get_default_group_keys())\n", "\n", "# Read from active (primary)\n", "print(f\"\\ngravity (active) = {pd[('physics', 'gravity')]}\")\n", "\n", "# Modify only the active value\n", "pd[('physics', 'manning')] = 0.05\n", "print(f\"manning active = {pd[('physics', 'manning')]}\")\n", "print(f\"manning default = {pd._get_param_def('physics', 'manning')}\")\n", "\n", "# --- Check membership ---\n", "print(f\"\\nis_in_active('physics', 'manning')? {pd.is_in_active('physics', 'manning')}\")\n", "print(f\"is_in_default('physics', 'manning')? {pd.is_in_default('physics', 'manning')}\")\n", "\n", "# --- Count active vs default ---\n", "nb_a, nb_d = pd.get_nb_params('physics')\n", "print(f\"\\nphysics: {nb_a} active params, {nb_d} default params\")\n", "\n", "# --- Add a param only to Active ---\n", "pd.addparam('physics', 'rho', '1000', Type_Param.Float, 'Water density',\n", " whichdict='Active')\n", "print(f\"\\nrho in active? {pd.is_in_active('physics', 'rho')}\")\n", "print(f\"rho in default? {pd.is_in_default('physics', 'rho')}\")\n", "\n", "# --- compare_active_to_default: remove active entries that match default ---\n", "# Reset manning to its default value first\n", "pd[('physics', 'manning')] = 0.035\n", "pd.compare_active_to_default(remove_from_active_if_same=True)\n", "# manning is now removed from active (same as default), but still readable via fallback\n", "print(f\"\\nmanning after cleanup = {pd[('physics', 'manning')]} (falls back to default)\")" ] }, { "cell_type": "markdown", "id": "41d021a2", "metadata": {}, "source": [ "## Incrementable groups\n", "\n", "Some simulations need a **variable number of parameter groups** — e.g. one\n", "group per cross-section, per boundary condition, or per material layer.\n", "`Wolf_Param` handles this with **incrementable groups**.\n", "\n", "### How it works\n", "\n", "1. A **reference parameter** (e.g. `nb_sections` in group `Config`) holds the\n", " current count.\n", "2. A **template group** named with `$n$` (e.g. `Section$n$`) defines the\n", " parameters each instance should contain.\n", "3. When `update_incremental_groups_params()` is called (or when the GUI\n", " refreshes), the template is expanded into `Section1`, `Section2`, …\n", " up to the current count. Extra groups are saved internally and restored\n", " if the count is later increased.\n", "\n", "### Declaring syntax\n", "\n", "The full form embeds everything in the group name:\n", "\n", "```\n", "\"Section$n(Config, nb_sections, 1, 10)$\"\n", "│ │ │ │ │ │\n", "│ │ │ │ │ └── max instances\n", "│ │ │ │ └── min instances\n", "│ │ │ └── reference parameter name\n", "│ │ └── reference group name\n", "│ └── placeholder for the index\n", "└── base group name\n", "```\n", "\n", "Or use `add_IncGroup()` explicitly and then add params with\n", "`whichdict='IncGroup'`." ] }, { "cell_type": "code", "execution_count": 18, "id": "533039c6", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:WARNING : group is incrementable. -- You must use 'IncGroup' for whichdict\n", "WARNING:root:WARNING : group is incrementable. -- You must use 'IncGroup' for whichdict\n", "WARNING:root:WARNING : group is incrementable. -- You must use 'IncGroup' for whichdict\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Incrementable groups registered: 1\n", "\n", "Active groups after expansion: ['Config', 'Section1', 'Section2', 'Section3']\n", " [Section1] params: ['name', 'manning', 'width']\n", " [Section2] params: ['name', 'manning', 'width']\n", " [Section3] params: ['name', 'manning', 'width']\n", "\n", "Section2 manning = 0.05\n", "Section3 manning = 0.035 (still default)\n", "\n", "After increasing to 5: ['Config', 'Section1', 'Section2', 'Section3', 'Section4', 'Section5']\n", "Section2 manning = 0.05 (preserved)\n", "\n", "After decreasing to 2: ['Config', 'Section1', 'Section2']\n", "Section2 manning after restore = 0.05 (restored)\n" ] } ], "source": [ "# --- Incrementable groups: compact syntax ---\n", "pi = Wolf_Param(to_read=False, init_GUI=False, title='Incrementable demo')\n", "\n", "# Reference parameter: how many sections do we have?\n", "pi.addparam('Config', 'nb_sections', '3', Type_Param.Integer, 'Number of sections')\n", "\n", "# Template group — the $n(...)$ syntax auto-registers the incrementable group\n", "pi.addparam('Section$n(Config, nb_sections, 1, 10)$', 'name',\n", " 'default', Type_Param.String, 'Section name')\n", "pi.addparam('Section$n(Config, nb_sections, 1, 10)$', 'manning',\n", " '0.035', Type_Param.Float, 'Manning coefficient')\n", "pi.addparam('Section$n(Config, nb_sections, 1, 10)$', 'width',\n", " '5.0', Type_Param.Float, 'Section width [m]')\n", "\n", "print(f\"Incrementable groups registered: {pi.get_nb_inc_groups()}\")\n", "\n", "# Expand: creates Section1, Section2, Section3 from the template\n", "pi.update_incremental_groups_params()\n", "\n", "print(f\"\\nActive groups after expansion: {pi.get_group_keys()}\")\n", "for g in pi.get_group_keys():\n", " if g.startswith('Section'):\n", " keys = pi.get_param_keys(g)\n", " print(f\" [{g}] params: {keys}\")\n", "\n", "# Modify one instance\n", "pi[('Section2', 'manning')] = 0.05\n", "print(f\"\\nSection2 manning = {pi[('Section2', 'manning')]}\")\n", "print(f\"Section3 manning = {pi[('Section3', 'manning')]} (still default)\")\n", "\n", "# --- Change the count: increase to 5 ---\n", "pi[('Config', 'nb_sections')] = 5\n", "pi.update_incremental_groups_params()\n", "print(f\"\\nAfter increasing to 5: {pi.get_group_keys()}\")\n", "\n", "# Section2's modified value is preserved\n", "print(f\"Section2 manning = {pi[('Section2', 'manning')]} (preserved)\")\n", "\n", "# --- Decrease back to 2: extra groups are saved internally ---\n", "pi[('Config', 'nb_sections')] = 2\n", "pi.update_incremental_groups_params()\n", "print(f\"\\nAfter decreasing to 2: {pi.get_group_keys()}\")\n", "\n", "# Increase again: saved values come back\n", "pi[('Config', 'nb_sections')] = 5\n", "pi.update_incremental_groups_params()\n", "print(f\"Section2 manning after restore = {pi[('Section2', 'manning')]} (restored)\")" ] }, { "cell_type": "markdown", "id": "7c536014", "metadata": {}, "source": [ "## Building from a raw string\n", "\n", "`fill_from_strings` parses parameter text directly — useful for tests or\n", "embedding default configurations in code." ] }, { "cell_type": "code", "execution_count": 6, "id": "ef345555", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Groups: ['physics', 'boundary']\n", "manning = 0.035 (type: str)\n", "upstream_Q = 120.0\n" ] } ], "source": [ "raw = \"\"\"\\\n", "physics:\n", "manning\\t0.035\\tManning coefficient (Float)\n", "gravity\\t9.81\\tGravitational acceleration (Float)\n", "boundary:\n", "upstream_Q\\t120.0\\tUpstream discharge [m3/s] (Float)\n", "downstream_h\\t2.5\\tDownstream water level [m] (Float)\n", "\"\"\"\n", "\n", "p3 = Wolf_Param(to_read=False, init_GUI=False)\n", "p3.fill_from_strings(raw)\n", "\n", "print(f\"Groups: {p3.get_group_keys()}\")\n", "print(f\"manning = {p3[('physics', 'manning')]} (type: {type(p3[('physics', 'manning')]).__name__})\")\n", "print(f\"upstream_Q = {p3[('boundary', 'upstream_Q')]}\")" ] }, { "cell_type": "markdown", "id": "5045ba50", "metadata": {}, "source": [ "## Copying and comparing" ] }, { "cell_type": "code", "execution_count": 19, "id": "933e86b4", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:ERROR : cannot find the following file : \n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Original dt = 0.25\n", "Copy dt = 1.0\n", "\n", "Identical? False\n", " [simulation] dt: {: 'dt', : , : 0.25, : 'Time step [s]', : None, : None} -> {: 'dt', : , : 1.0, : 'Time step [s]', : None, : None}\n" ] } ], "source": [ "# Deep copy (data only, no GUI)\n", "p_copy = p.copy()\n", "p_copy[('simulation', 'dt')] = 1.0\n", "\n", "print(f\"Original dt = {p[('simulation', 'dt')]}\")\n", "print(f\"Copy dt = {p_copy[('simulation', 'dt')]}\")\n", "\n", "# Compare two param sets\n", "same = p.is_like(p_copy)\n", "print(f\"\\nIdentical? {same}\")\n", "\n", "# Show differences\n", "diffs = p.diff(p_copy)\n", "if diffs:\n", " for k, (val_a, val_b) in diffs.items():\n", " if isinstance(k, tuple):\n", " group, key = k\n", " print(f\" [{group}] {key}: {val_a} -> {val_b}\")\n", " else:\n", " print(f\" {k}: {val_a} -> {val_b}\")" ] }, { "cell_type": "markdown", "id": "95ee06b0", "metadata": {}, "source": [ "## Checking existence and using Enum parameters" ] }, { "cell_type": "code", "execution_count": 13, "id": "e5839c60", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "'simulation' group exists? True\n", "'simulation/dt' exists? True\n", "'physics' group exists? False\n", "\n", "solver = Solver.EXPLICIT\n" ] } ], "source": [ "# --- Existence checks ---\n", "print(f\"'simulation' group exists? {p.is_in_active('simulation')}\")\n", "print(f\"'simulation/dt' exists? {p.is_in_active('simulation', 'dt')}\")\n", "print(f\"'physics' group exists? {p.is_in_active('physics')}\")\n", "\n", "# --- Enum-typed parameter (dropdown in GUI) ---\n", "from enum import Enum\n", "\n", "class Solver(Enum):\n", " EXPLICIT = 'explicit'\n", " IMPLICIT = 'implicit'\n", " SEMIIMPLICIT = 'semi-implicit'\n", "\n", "# Value must be the Enum member itself (not .value),\n", "# because __getitem__ checks isinstance(value, enum_choices).\n", "p.addparam('simulation', 'solver', Solver.EXPLICIT,\n", " Type_Param.Enum, 'Numerical solver',\n", " enum_choices=Solver)\n", "\n", "print(f\"\\nsolver = {p[('simulation', 'solver')]}\")" ] }, { "cell_type": "markdown", "id": "dc7e6e04", "metadata": {}, "source": [ "## Wolf2D_Project — linking simulations, vectors, and palettes\n", "\n", "`Wolf2D_Project` is a specialized `Project` that organizes:\n", "\n", "- **Simulations** (WOLF2D CPU/GPU) with their file paths\n", "- **Vectors** (polygons for zone-based analysis)\n", "- **Palettes** (color maps for visualization)\n", "- **Links** between simulations ↔ vectors, simulations ↔ palettes\n", "\n", "### Project file format\n", "\n", "```\n", "wolf2d:\n", "SimName_A .\\Q25\\sim_A\\simul\n", "SimName_B .\\Q25\\sim_B\\simul\n", "vector:\n", "zone1 ..\\Vectors\\zone1.vec\n", "vector_array_link:\n", "SimName_A zone1\n", "SimName_B zone1\n", "palette:\n", "Q25 q25.pal\n", "palette-array:\n", "SimName_A Q25\n", "SimName_B Q25\n", "```\n", "\n", "### Creating a project in the GUI\n", "\n", "```python\n", "from wolfhece.multiprojects import Wolf2D_Project\n", "\n", "proj = Wolf2D_Project(\n", " wdir='path/to/project/',\n", " filename='my_project.param',\n", " toShow=True # opens the parameter editor\n", ")\n", "\n", "# Load all linked simulations\n", "proj.load_all()\n", "\n", "# Get a specific simulation result\n", "res = proj['wolf2d', 'SimName_A']\n", "```" ] }, { "cell_type": "markdown", "id": "d02c9724", "metadata": {}, "source": [ "## Summary\n", "\n", "| Task | Code |\n", "|------|------|\n", "| Create empty | `Wolf_Param(to_read=False, init_GUI=False)` |\n", "| Add parameter | `p.addparam(group, key, value, Type_Param.Float, comment)` |\n", "| Read value (typed) | `p[('group', 'key')]` |\n", "| Set value | `p[('group', 'key')] = val` |\n", "| Read with default | `p.get_param('group', 'key', default_value=0)` |\n", "| List groups | `p.get_group_keys()` / `get_default_group_keys()` |\n", "| List params in group | `p.get_param_keys('group')` |\n", "| Check existence | `p.is_in_active(g, k)` / `p.is_in_default(g, k)` |\n", "| Count params | `p.get_nb_params('group')` → `(nb_active, nb_default)` |\n", "| Get type / comment | `p.get_type(g, k)`, `p.get_help(g, k)` |\n", "| Save to file | `p.Save('path.param')` |\n", "| Load from file | `Wolf_Param(filename=f, init_GUI=False)` |\n", "| Load from string | `p.fill_from_strings(text)` |\n", "| Deep copy | `p.copy()` |\n", "| Compare / diff | `p.is_like(other)`, `p.diff(other)` |\n", "| **Active vs Default** | |\n", "| Add to active only | `p.addparam(..., whichdict='Active')` |\n", "| Add to default only | `p.addparam(..., whichdict='Default')` |\n", "| Read from default | `p._get_param_def('group', 'key')` |\n", "| Cleanup active=default | `p.compare_active_to_default(remove_from_active_if_same=True)` |\n", "| **Incrementable groups** | |\n", "| Declare template group | `p.addparam('Grp$n(ref_g, ref_p, min, max)$', ...)` |\n", "| Expand instances | `p.update_incremental_groups_params()` |\n", "| Query inc. group count | `p.get_nb_inc_groups()` |\n", "\n", "See also:\n", "- [Factory methods](factory_methods.ipynb) — quick object creation patterns\n", "- [WolfArray tutorial](wolfarray.ipynb) — arrays use `Wolf_Param` for simulation configs" ] } ], "metadata": { "kernelspec": { "display_name": "python311", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 5 }