Recipe Development

There may be cases where your Compounds and/or building scripts can be generalized to support a broad range of systems. Such objects would be a valuable resource for many researchers, and might justify development of a Python package that could be distributed to the community.

mBuild has been developed with this in mind, in the form of a plug-in system. Detailed below are the specifications of this system, how to convert an existing Python project into an mBuild-discoverable plug-in, and an example.

Entry Points

The basis of the plug-in system in mBuild is the setuptools.entry_points package. This allows other packages to register themselves with the entry_point group we defined in mBuild, so they are accessible through the mbuild.recipes location. Imagine you have a class named my_foo that inherits from mb.Compound. It is currently inside of a project my_project and is accessed via a direct import, i.e. from my_project import my_foo. You can register this class as an entry point associated with mbuild.recipes. It will then be accessible from inside mBuild as a plug-in via mbuild.recipes.my_foo and a direct import will be unncessary. The call import mbuild discovers all plug-ins that fit the entry_point group specification and makes them available under mbuild.recipes.

Registering a Recipe

Here we consider the case that a user already has a Python project set up with a structure similar to the layout below.

This project can be found here.

mbuild_fcc
├── LICENSE
├── README.md
├── mbuild_fcc
│   ├── mbuild_fcc.py
│   └── tests
│       ├── __init__.py
│       └── test_fcc.py
└── setup.py

The two important files for the user to convert their mBuild plug-in to a discoverable plug-in are setup.py and mbuild_fcc.py.

To begin, lets first inspect the mbuild_fcc.py file, a shortened snippet is below.

import mbuild


class FCC(mbuild.Compound):
    """Create a mBuild Compound with a repeating unit of the FCC unit cell.

    ... (shortened for viewability)

    """

    def __init__(self, lattice_spacing=None, compound_to_add=None, x=1, y=1, z=1):
        super(FCC, self).__init__()

        # ... (shortened for viewability)

if __name__ == "__main__":
    au_fcc_lattice = FCC(lattice_spacing=0.40782,
                         compound_to_add=mbuild.Compound(name="Au"),
                         x=5, y=5, z=1)
    print(au_fcc_lattice)

There are two notable lines in this file that we need to focus on when developing this as a plug-in for mBuild.

The first is the import statement import mbuild. We must make sure that mbuild is installed since we are inheriting from mbuild.Compound. When you decide to distribute your plug-in, the dependencies must be listed.

The second is to select the name of the plug-in itself. It is considered good practice to name it the name of your class. In this case, we will name the plug-in FCC.

The last step is to edit the setup.py file such that the plug-in can be registered under the entry_point group mbuild.plugins.

from setuptools import setup

setup(
    ...
    entry_points={ "mbuild.plugins":[ "FCC = mbuild_fcc.mbuild_fcc:FCC"]},
    ...
)

The important section is the entry_points argument. Here we define the entry_point group we want to register with: "mbuild.plugins". Finally, we tell Python what name to use when accessing this plug-in. Earlier, we decided to call it FCC. This is denoted here by the name before the assignment operator FCC =. Next, we pass the location of the file with our plug-in: mbuild_fcc.mbuild_fcc as if we were located at the setup.py file. Then, we provide the name of the class within that Python file we want to make discoverable :FCC.

Since the setup.py file is located in the top folder of the python project, the first mbuild_fcc is the name of the folder, and the second is the name of the python file. The colon (:) is used when accessing the class that is in the python file itself.

Putting it all together

Finally, we have FCC = mbuild_fcc.mbuild_fcc:FCC.

To test this feature, you should clone the mbuild-fcc project listed above.

git clone https://github.com/justinGilmer/mbuild-fcc

Make sure you have mBuild installed, then run the command below after changing into the mbuild-fcc directory.

cd mbuild-fcc

pip install -e .

Note that this command will install this example from source in an editable format.

Trying it Out

To test that you set up your plug-in correctly, try importing mBuild:

import mbuild

If you do not receive error messages, your plug-in should be discoverable!

help(mbuild.recipes.FCC) `