Installation ============ ``pybmodes`` requires **Python ≥ 3.11**. The runtime depends only on ``numpy`` and ``scipy``; everything optional — plotting, notebook execution, WindIO ingestion, this documentation site — is gated behind an extra so the default install footprint stays small. From PyPI --------- .. code-block:: bash pip install pybmodes This pulls in the runtime dependencies (``numpy>=1.26``, ``scipy>=1.11``) and exposes: - The Python package: ``import pybmodes`` - The CLI: ``pybmodes`` on ``PATH`` (seven subcommands — see :doc:`quickstart`). - The bundled example library (vendored as package-data, reachable via ``pybmodes examples --copy ``). To pin a specific release in a requirements file or a ``pyproject.toml``: .. code-block:: text pybmodes ==1.9.0 # exact pin pybmodes ~=1.9 # latest 1.9.x, blocks 2.x pybmodes >=1.9,<2 # 1.9+ but never a major bump From conda-forge ---------------- ``pybmodes`` is also packaged on `conda-forge `_: .. code-block:: bash conda install -c conda-forge pybmodes This pulls the runtime core (``numpy``, ``scipy``) and the ``pybmodes`` CLI, exactly like the PyPI wheel. The pip-style extras (``[plots]``, ``[windio]``, ...) are a pip concept and have no conda equivalent, so for the optional features add the matching conda-forge packages alongside it, ``matplotlib`` for ``pybmodes.plots`` and ``pyyaml`` for the WindIO path. .. code-block:: bash conda install -c conda-forge pybmodes matplotlib pyyaml From source (editable) ---------------------- For contributors and anyone tracking ``master``: .. code-block:: bash git clone https://github.com/SMI-Lab-Inha/pyBModes.git cd pyBModes pip install -e ".[dev,plots]" ``-e`` installs in editable mode — changes to ``src/pybmodes/*.py`` take effect on the next import without re-installing. End users who don't need the test/lint extras can install the runtime core alone with ``pip install .``. Optional extras --------------- .. list-table:: :header-rows: 1 :widths: 15 30 55 * - Extra - Pulls in - When you need it * - ``[dev]`` - ``pytest``, ``pytest-cov``, ``ruff``, ``mypy``, ``pyyaml`` - Run the test suite, lint, and type-check the package. Pulled into editable installs by default; not needed for end users. * - ``[plots]`` - ``matplotlib>=3.7`` - Every plotting helper (``pybmodes.plots``): Campbell, MAC, mode-shape, fit-quality, and environmental-loading figures. ``pybmodes.plots.apply_style()`` applies the project's standard engineering-paper palette. * - ``[windio]`` - ``pyyaml>=6`` - ``Tower.from_windio(...)``, ``RotatingBlade.from_windio(...)``, ``Tower.from_windio_floating(...)``, and the ``pybmodes windio`` one-click CLI. * - ``[notebook]`` - ``nbclient``, ``nbformat``, ``ipykernel``, ``matplotlib`` - Headless execution of bundled walkthrough notebooks under :file:`tests/test_notebooks.py`. Test-only — not imported by ``pybmodes`` itself. * - ``[docs]`` - ``sphinx<9``, ``sphinx-rtd-theme``, ``myst-parser``, ``sphinx-copybutton`` - Build this documentation site locally. Combine extras with commas: .. code-block:: bash pip install -e ".[dev,plots,windio]" Windows + conda quickstart -------------------------- The lowest-friction path on Windows. The user-facing maintainer runs this exact sequence: .. code-block:: bat :: 1. install Miniconda or Anaconda first if you don't have it. :: https://docs.conda.io/en/latest/miniconda.html :: Open "Anaconda Prompt" from the Start menu (not regular :: CMD or PowerShell -- the Anaconda Prompt has `conda` :: already on PATH). :: 2. create and activate a dedicated env conda create -n pybmodes python=3.11 -y conda activate pybmodes :: 3. clone and install in editable mode with dev + plotting extras git clone https://github.com/SMI-Lab-Inha/pyBModes.git cd pyBModes pip install -e ".[dev,plots]" :: 4. verify the install pytest .. note:: Don't try to invoke the conda env's ``python.exe`` directly from PowerShell — it errors with ``STATUS_DLL_INIT_FAILED`` because the env relies on conda's ``PATH`` manipulations. Use Anaconda Prompt, or wrap the call in ``cmd /c "call activate.bat pybmodes && python ..."``. Updating to a new release ------------------------- New versions are published to PyPI (see the `releases `_ and the :doc:`changelog`). To upgrade an existing PyPI install to the latest release, run .. code-block:: bash pip install --upgrade pybmodes # add the same extras you use, # e.g. -U "pybmodes[plots,windio]" Check the installed version, and pin one if you need reproducibility. .. code-block:: bash python -c "import pybmodes; print(pybmodes.__version__)" pip install "pybmodes==1.14.1" # install or pin a specific release For a source checkout, pull and reinstall so new dependencies are picked up too. .. code-block:: bash git pull pip install -e ".[dev,plots]" Inside a conda environment ^^^^^^^^^^^^^^^^^^^^^^^^^^^ pyBmodes is on conda-forge, so inside a conda env you can install and upgrade it with conda directly. .. code-block:: bash conda install -c conda-forge pybmodes # install conda update -c conda-forge pybmodes # upgrade python -c "import pybmodes; print(pybmodes.__version__)" .. note:: The conda-forge package ships the runtime core only. For the optional features add the matching conda-forge packages (``matplotlib`` for ``pybmodes.plots``, ``pyyaml`` for the WindIO path), since the pip-style extras have no conda equivalent. If you installed pyBmodes with ``pip`` inside a conda env instead of from conda-forge, keep upgrading it with ``pip``, not ``conda update``, so the two package managers don't both try to manage it. Activate the env first, then upgrade with pip. .. code-block:: bash conda activate pybmodes # the env you installed it into pip install --upgrade pybmodes # or -U "pybmodes[plots,windio]" python -c "import pybmodes; print(pybmodes.__version__)" .. note:: A ``pip``-installed pyBmodes won't respond to ``conda update pybmodes``, because conda doesn't track a pip-installed package. If you're unsure which env has it, ``conda env list`` shows every env and ``pip show pybmodes`` confirms the version installed in the currently active one. For a source checkout living in a conda env, ``git pull`` then re-run the editable ``pip install -e ".[dev,plots]"`` with the env active. Verifying the install --------------------- After installing, run the **self-contained** test suite — every test that doesn't need external data: .. code-block:: bash python -c "import pybmodes; print(pybmodes.__version__)" pytest A fresh clone or a fresh PyPI install both pass this with no external data on the filesystem. Tests that need upstream OpenFAST / BModes data are gated behind the ``integration`` marker; see :doc:`data_sources` for what to clone and where. To run the full suite including the integration track once the upstream data is staged under ``external/``: .. code-block:: bash pytest -m integration CI runs both steps on every PR. The integration step tolerates ``pytest`` exit code 5 ("no tests collected") so the job stays green on a runner without the data, but fails on any other non-zero exit so a custom workflow run that *does* have the data surfaces real failures immediately. IDE setup --------- VS Code ^^^^^^^ Recommended workspace settings (``./.vscode/settings.json``): .. code-block:: json { "python.analysis.typeCheckingMode": "basic", "python.testing.pytestEnabled": true, "python.testing.pytestArgs": ["tests", "--no-cov"], "[python]": { "editor.formatOnSave": false, "editor.codeActionsOnSave": {"source.organizeImports": "explicit"} }, "ruff.lint.select": ["E", "F", "W", "I"] } The ``--no-cov`` flag in ``pytestArgs`` is a quality-of-life choice — coverage reports clutter the Test Explorer output. PyCharm ^^^^^^^ - **Interpreter**: point at the ``pybmodes`` conda env. - **Test runner**: ``Settings → Tools → Python Integrated Tools → Default test runner → pytest``. - **Ruff plugin**: install ``Ruff`` from the marketplace; the project's ``pyproject.toml`` carries the rules. Common errors ------------- ``ModuleNotFoundError: No module named 'pybmodes'`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You ran ``python`` from outside the install's environment, **or** you cloned the source but didn't ``pip install -e .``. From the repo root either install editably or set ``PYTHONPATH``: .. code-block:: bash # one-time install pip install -e . # or one-off invocation PYTHONPATH=src python -c "import pybmodes" ``UserWarning: matplotlib is required for plot_campbell`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ``[plots]`` extra wasn't pulled in. Add it: .. code-block:: bash pip install "pybmodes[plots]" ``KeyError: 'floating_platform'`` (WindIO yaml) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You're calling ``Tower.from_windio_floating(...)`` on a yaml that lacks a ``components.floating_platform`` block — a land-based or monopile-only ontology. Use ``Tower.from_windio(...)`` instead, or supply a ``floating_platform``-bearing yaml. ``FileNotFoundError: ... external/OpenFAST_files/...`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ An integration test or a case script needs upstream data that isn't present. See :doc:`data_sources` for the layout and clone the required upstream repository under ``external/``. ``MemoryError`` or eigensolver hangs on large towers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a smaller ``n_modes`` (only the lowest few are usually interesting), or check ``hub_conn`` — a free-free root (``hub_conn = 2``) without a ``PlatformSupport`` 6×6 matrix is singular and will hang the solver. The pre-solve sanity checks (:func:`pybmodes.checks.check_model`) catch this. Uninstalling ------------ .. code-block:: bash pip uninstall pybmodes The editable install also clears with ``pip uninstall``; ``rm -rf`` on the cloned repo handles the source.