mmodel


Namemmodel JSON
Version 0.6.2 PyPI version JSON
download
home_pagehttps://peterhs73.github.io/mmodel-docs/
SummaryModular modeling framework for scientific modeling and prototyping.
upload_time2023-06-24 15:20:56
maintainerPeter Sun
docs_urlNone
authorPeter Sun
requires_python>=3.8
licenseBSD-3-Clause
keywords python scientific-modeling prototyping
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            MModel
======

|GitHub version| |PyPI version shields.io| |PyPI pyversions| |Unittests|
|Docs|

MModel is a lightweight and modular model-building framework
for small-scale and nonlinear models. The package aims to solve
scientific program prototyping and distribution difficulties, making
it easier to create modular, fast, and user-friendly packages.

For using mmodel in a complex scientific workflow, please refer to
the `mrfmsim <https://marohn-group.github.io/mrfmsim-docs/overview.html>`__
on how mmodel improves the development of magnetic resonance force
microscopy (MRFM) experiments.

Quickstart
----------

To create a nonlinear model that has the result of
`(x + y)log(x + y, base)`:

.. code-block:: python

    import math
    import numpy as np

    def func(sum_xy, log_xy):
        """Function that adds a value to the multiplied inputs."""

        return sum_xy * log_xy + 6

The graph is defined using grouped edges (the ``networkx`` syntax of edge
the definition also works.)

.. code-block:: python

    from mmodel import ModelGraph, Model, MemHandler
    # create graph edges
    grouped_edges = [
        ("add", ["log", "function node"]),
        ("log", "function node"),
    ]

The functions are then added to node attributes. The order of definition
is node_name, node_func, output, input (if different from original function),
and modifiers.

.. code-block:: python

    # define note objects
    node_objects = [
        ("add", np.add, "sum_xy", ["x", "y"]),
        ("log", math.log, "log_xy", ["sum_xy", "log_base"]),
        ("function node", func, "result"),
    ]

    G = ModelGraph(name="example_graph")
    G.add_grouped_edges_from(grouped_edges)
    G.set_node_objects_from(node_objects)

To define the model, the name, graph, and handler need to be specified. Additional
parameters include modifiers, descriptions, and returns lists. The input parameters
of the model are determined based on the node information.

.. code-block:: python

    example_model = Model("example_model", G, handler=MemHandler, description="Test model.")

The model behaves like a Python function, with additional metadata. The graph can
be plotted using the ``draw`` method.

.. code-block:: python

    >>> print(example_model)
    example_model(log_base, x, y)
    returns: z
    graph: example_graph
    handler: MemHandler

    Test model.

    >>> example_model(2, 5, 3) # (5 + 3)log(5 + 3, 2) + 6
    30.0

    >>> example_model.draw()

The resulting graph contains the model metadata and detailed node information.

.. .. |br| raw:: html
    
..     <br/>

.. .. image:: example.png
..   :width: 300
..   :alt: example model graph

One key feature of ``mmodel`` that differs from other workflow is modifiers, 
which modify callables post definition. Modifiers work on both the node level
and model level.

Example: Use ``loop_input`` modifier on the graph to loop the nodes that require the
"log_base" parameter.

.. code-block:: python 

    from mmodel import loop_input

    H = G.subgraph(inputs=["log_base"])
    H.name = "example_subgraph"
    loop_node = Model("submodel", H, handler=MemHandler)

    looped_G = G.replace_subgraph(
        H,
        "loop_node",
        loop_node,
        output="looped_z",
        modifiers=[loop_input("log_base")],
    )
    looped_G.name = "looped_graph"

    looped_model = Model("looped_model", looped_G, loop_node.handler)


We can inspect the loop node as well as the new model.

.. code-block:: python 

    >>> print(looped_model)
    looped_model(log_base, x, y)
    returns: looped_z
    graph: looped_graph
    handler: MemHandler()
    
    >>> print(looped_model.node_metadata("loop_node"))
    submodel(log_base, sum_xy)
    return: looped_z
    functype: mmodel.Model
    modifiers:
      - loop_input('log_base')

    >>> looped_model([2, 4], 5, 3) # (5 + 3)log(5 + 3, 2) + 6
    [30.0, 18.0]


Use the ``draw`` method to draw the graph. There are three styles
"plain", "short", and "verbose", which differ by the level of detail of the
node information. A graph output is displayed in Jupyter Notebook
or can be saved using the export option.

.. code-block:: python

    G.draw(style="short")
    example_model.draw(style="plain", export="example.pdf") # default to draw_graph

Installation
------------

Graphviz installation
^^^^^^^^^^^^^^^^^^^^^

To view the graph, Graphviz needs to be installed:
`Graphviz Installation <https://graphviz.org/download/>`_
For windows installation, please choose "add Graphviz to the
system PATH for all users/current users" during the setup.

MModel installation
^^^^^^^^^^^^^^^^^^^^^^^

.. code-block::

    pip install mmodel

Development installation
^^^^^^^^^^^^^^^^^^^^^^^^
MModel uses `poetry <https://python-poetry.org/docs/>`_ as
the build system. The package works with both pip and poetry
installation. For macos systems, sometimes `brew install` results
in unexpected installation path, it is recommended to install
with conda::

    conda install -c conda-forge pygraphviz

To install test and docs, despondencies run::

    pip install .[test] .[docs]

To run the tests in different python environments and cases 
(py38, py39, py310, py311, coverage and docs)::

    tox

To create the documentation, run under the "/docs" directory::

    make html


.. |GitHub version| image:: https://badge.fury.io/gh/peterhs73%2FMModel.svg
   :target: https://github.com/Marohn-Group/mmodel

.. |PyPI version shields.io| image:: https://img.shields.io/pypi/v/mmodel.svg
   :target: https://pypi.python.org/pypi/mmodel/

.. |PyPI pyversions| image:: https://img.shields.io/pypi/pyversions/mmodel.svg

.. |Unittests| image:: https://github.com/Marohn-Group/mmodel/actions/workflows/tox.yml/badge.svg
    :target: https://github.com/Marohn-Group/mmodel/actions

.. |Docs| image:: https://img.shields.io/badge/Documentation--brightgreen.svg
    :target: https://github.com/Marohn-Group/mmodel-docs/

            

Raw data

            {
    "_id": null,
    "home_page": "https://peterhs73.github.io/mmodel-docs/",
    "name": "mmodel",
    "maintainer": "Peter Sun",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "hs859@cornell.edu",
    "keywords": "python,scientific-modeling,prototyping",
    "author": "Peter Sun",
    "author_email": "hs859@cornell.edu",
    "download_url": "https://files.pythonhosted.org/packages/a9/c8/3b190bed679a580a103d930504df94a8644d535d03d3d5e53a447cb7f560/mmodel-0.6.2.tar.gz",
    "platform": null,
    "description": "MModel\n======\n\n|GitHub version| |PyPI version shields.io| |PyPI pyversions| |Unittests|\n|Docs|\n\nMModel is a lightweight and modular model-building framework\nfor small-scale and nonlinear models. The package aims to solve\nscientific program prototyping and distribution difficulties, making\nit easier to create modular, fast, and user-friendly packages.\n\nFor using mmodel in a complex scientific workflow, please refer to\nthe `mrfmsim <https://marohn-group.github.io/mrfmsim-docs/overview.html>`__\non how mmodel improves the development of magnetic resonance force\nmicroscopy (MRFM) experiments.\n\nQuickstart\n----------\n\nTo create a nonlinear model that has the result of\n`(x + y)log(x + y, base)`:\n\n.. code-block:: python\n\n    import math\n    import numpy as np\n\n    def func(sum_xy, log_xy):\n        \"\"\"Function that adds a value to the multiplied inputs.\"\"\"\n\n        return sum_xy * log_xy + 6\n\nThe graph is defined using grouped edges (the ``networkx`` syntax of edge\nthe definition also works.)\n\n.. code-block:: python\n\n    from mmodel import ModelGraph, Model, MemHandler\n    # create graph edges\n    grouped_edges = [\n        (\"add\", [\"log\", \"function node\"]),\n        (\"log\", \"function node\"),\n    ]\n\nThe functions are then added to node attributes. The order of definition\nis node_name, node_func, output, input (if different from original function),\nand modifiers.\n\n.. code-block:: python\n\n    # define note objects\n    node_objects = [\n        (\"add\", np.add, \"sum_xy\", [\"x\", \"y\"]),\n        (\"log\", math.log, \"log_xy\", [\"sum_xy\", \"log_base\"]),\n        (\"function node\", func, \"result\"),\n    ]\n\n    G = ModelGraph(name=\"example_graph\")\n    G.add_grouped_edges_from(grouped_edges)\n    G.set_node_objects_from(node_objects)\n\nTo define the model, the name, graph, and handler need to be specified. Additional\nparameters include modifiers, descriptions, and returns lists. The input parameters\nof the model are determined based on the node information.\n\n.. code-block:: python\n\n    example_model = Model(\"example_model\", G, handler=MemHandler, description=\"Test model.\")\n\nThe model behaves like a Python function, with additional metadata. The graph can\nbe plotted using the ``draw`` method.\n\n.. code-block:: python\n\n    >>> print(example_model)\n    example_model(log_base, x, y)\n    returns: z\n    graph: example_graph\n    handler: MemHandler\n\n    Test model.\n\n    >>> example_model(2, 5, 3) # (5 + 3)log(5 + 3, 2) + 6\n    30.0\n\n    >>> example_model.draw()\n\nThe resulting graph contains the model metadata and detailed node information.\n\n.. .. |br| raw:: html\n    \n..     <br/>\n\n.. .. image:: example.png\n..   :width: 300\n..   :alt: example model graph\n\nOne key feature of ``mmodel`` that differs from other workflow is modifiers, \nwhich modify callables post definition. Modifiers work on both the node level\nand model level.\n\nExample: Use ``loop_input`` modifier on the graph to loop the nodes that require the\n\"log_base\" parameter.\n\n.. code-block:: python \n\n    from mmodel import loop_input\n\n    H = G.subgraph(inputs=[\"log_base\"])\n    H.name = \"example_subgraph\"\n    loop_node = Model(\"submodel\", H, handler=MemHandler)\n\n    looped_G = G.replace_subgraph(\n        H,\n        \"loop_node\",\n        loop_node,\n        output=\"looped_z\",\n        modifiers=[loop_input(\"log_base\")],\n    )\n    looped_G.name = \"looped_graph\"\n\n    looped_model = Model(\"looped_model\", looped_G, loop_node.handler)\n\n\nWe can inspect the loop node as well as the new model.\n\n.. code-block:: python \n\n    >>> print(looped_model)\n    looped_model(log_base, x, y)\n    returns: looped_z\n    graph: looped_graph\n    handler: MemHandler()\n    \n    >>> print(looped_model.node_metadata(\"loop_node\"))\n    submodel(log_base, sum_xy)\n    return: looped_z\n    functype: mmodel.Model\n    modifiers:\n      - loop_input('log_base')\n\n    >>> looped_model([2, 4], 5, 3) # (5 + 3)log(5 + 3, 2) + 6\n    [30.0, 18.0]\n\n\nUse the ``draw`` method to draw the graph. There are three styles\n\"plain\", \"short\", and \"verbose\", which differ by the level of detail of the\nnode information. A graph output is displayed in Jupyter Notebook\nor can be saved using the export option.\n\n.. code-block:: python\n\n    G.draw(style=\"short\")\n    example_model.draw(style=\"plain\", export=\"example.pdf\") # default to draw_graph\n\nInstallation\n------------\n\nGraphviz installation\n^^^^^^^^^^^^^^^^^^^^^\n\nTo view the graph, Graphviz needs to be installed:\n`Graphviz Installation <https://graphviz.org/download/>`_\nFor windows installation, please choose \"add Graphviz to the\nsystem PATH for all users/current users\" during the setup.\n\nMModel installation\n^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block::\n\n    pip install mmodel\n\nDevelopment installation\n^^^^^^^^^^^^^^^^^^^^^^^^\nMModel uses `poetry <https://python-poetry.org/docs/>`_ as\nthe build system. The package works with both pip and poetry\ninstallation. For macos systems, sometimes `brew install` results\nin unexpected installation path, it is recommended to install\nwith conda::\n\n    conda install -c conda-forge pygraphviz\n\nTo install test and docs, despondencies run::\n\n    pip install .[test] .[docs]\n\nTo run the tests in different python environments and cases \n(py38, py39, py310, py311, coverage and docs)::\n\n    tox\n\nTo create the documentation, run under the \"/docs\" directory::\n\n    make html\n\n\n.. |GitHub version| image:: https://badge.fury.io/gh/peterhs73%2FMModel.svg\n   :target: https://github.com/Marohn-Group/mmodel\n\n.. |PyPI version shields.io| image:: https://img.shields.io/pypi/v/mmodel.svg\n   :target: https://pypi.python.org/pypi/mmodel/\n\n.. |PyPI pyversions| image:: https://img.shields.io/pypi/pyversions/mmodel.svg\n\n.. |Unittests| image:: https://github.com/Marohn-Group/mmodel/actions/workflows/tox.yml/badge.svg\n    :target: https://github.com/Marohn-Group/mmodel/actions\n\n.. |Docs| image:: https://img.shields.io/badge/Documentation--brightgreen.svg\n    :target: https://github.com/Marohn-Group/mmodel-docs/\n",
    "bugtrack_url": null,
    "license": "BSD-3-Clause",
    "summary": "Modular modeling framework for scientific modeling and prototyping.",
    "version": "0.6.2",
    "project_urls": {
        "Documentation": "https://peterhs73.github.io/mmodel-docs/",
        "Homepage": "https://peterhs73.github.io/mmodel-docs/",
        "Repository": "https://github.com/peterhs73/MModel"
    },
    "split_keywords": [
        "python",
        "scientific-modeling",
        "prototyping"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "27dd070a5467ffd7d0f0c989902c34d5decd8ef3063119ff96f27dcad05eda0c",
                "md5": "0e00b4725ad2f078317a6f23a711bec4",
                "sha256": "36d00d7c65ca3b560f3669aa5c6a82399b910cb1fe1b9394a13f841ef6957b42"
            },
            "downloads": -1,
            "filename": "mmodel-0.6.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0e00b4725ad2f078317a6f23a711bec4",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 23507,
            "upload_time": "2023-06-24T15:20:54",
            "upload_time_iso_8601": "2023-06-24T15:20:54.711486Z",
            "url": "https://files.pythonhosted.org/packages/27/dd/070a5467ffd7d0f0c989902c34d5decd8ef3063119ff96f27dcad05eda0c/mmodel-0.6.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a9c83b190bed679a580a103d930504df94a8644d535d03d3d5e53a447cb7f560",
                "md5": "2df62ca2430639f73f8995adb462abfd",
                "sha256": "3edef332260696947f730392a3950789c66f56324cd1a20f6b3aadbb009ba14b"
            },
            "downloads": -1,
            "filename": "mmodel-0.6.2.tar.gz",
            "has_sig": false,
            "md5_digest": "2df62ca2430639f73f8995adb462abfd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 22190,
            "upload_time": "2023-06-24T15:20:56",
            "upload_time_iso_8601": "2023-06-24T15:20:56.675180Z",
            "url": "https://files.pythonhosted.org/packages/a9/c8/3b190bed679a580a103d930504df94a8644d535d03d3d5e53a447cb7f560/mmodel-0.6.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-24 15:20:56",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "peterhs73",
    "github_project": "MModel",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "mmodel"
}
        
Elapsed time: 0.09817s