How to write a custom PyZeta plugin

Imports

[1]:
# some standard library imports
from json import load
from os.path import dirname, join
from typing import Callable, Optional, Tuple, Type

# the core imports for writing your custom logic and the plugin
from pyzeta.core.pyzeta_types.special import tGroupElement
from pyzeta.core.symmetries.symmetry_group import SymmetryGroup
from pyzeta.core.symmetries.trivial_group import TrivialGroup
from pyzeta.framework.plugins.installation_helper import InstallationHelper
from pyzeta.framework.plugins.pyzeta_plugin import PyZetaPlugin

Implement your custom logic

[2]:
class TestGroup(TrivialGroup):
    "Custom (trivial) symmetry group implementation to supply as a plugin."

    def __init__(self, arg1: str, arg2: int) -> None:
        "Initialize our custom symmetry group implementation."
        super().__init__()
        self.arg1 = arg1
        self.arg2 = arg2

    def getElements(self) -> Tuple[tGroupElement, ...]:
        "Override this in our custom symmetry group."
        raise NotImplementedError(
            f"test group[{self.arg1} | {self.arg2}] is not fully implemented!"
        )

    def __str__(self) -> str:
        "Just for printing - generic plugins don't actually need this."
        return f"TestGroup({self.arg1}, {self.arg2})"

How to include custom configuration data

[3]:
# here is an example of how to include custom configuration data with your
# plugin (once the data file is installed!):
configFile = InstallationHelper.returnDataPath("group_data.json")
with open(configFile, "r", encoding="utf-8") as f:
    customData = load(f)

The actual plugin class

[4]:
class GroupPlugin(PyZetaPlugin[SymmetryGroup]):
    "Test plugin providing a simple custom symmetry group to PyZeta."

    _instance: Optional[PyZetaPlugin[SymmetryGroup]] = None

    @staticmethod
    def initialize() -> Callable[..., SymmetryGroup]:
        "This is the hook of plugins into `PyZeta`."
        arg1, arg2 = customData["arg1"], customData["arg2"]
        return lambda: TestGroup(arg1=arg1, arg2=arg2)

    @staticmethod
    def getInstance() -> PyZetaPlugin[SymmetryGroup]:
        "Plugins should be realized as singletons."
        if GroupPlugin._instance is None:
            GroupPlugin._instance = GroupPlugin()
        return GroupPlugin._instance

    @property
    def pluginType(self) -> Type[SymmetryGroup]:
        "The type provided by the plugin."
        return SymmetryGroup

    @property
    def pluginName(self) -> str:
        "The name of the plugin."
        return "TestGroupPlugin"

    @property
    def pluginVersion(self) -> Tuple[int, int, int]:
        """
        The version of the plugin (the combination of version and name should
        be unique). The semantics are (`major`, `minor`, `patch`).
        """
        return (22, 1, 0)


if __name__ == "__main__":
    print(f"the plugin itself:     {GroupPlugin.getInstance()}")
    print(f"the provided service:  {GroupPlugin.initialize()()}")
the plugin itself:     MyTestAlgorithmPlugin           @ v22.1.0
the provided service:  TestAlgorithm(hi from algorithm_data.json!, 9)...! :)

Installing the plugin

With the prerequisits above placed in a single .py source file named group_plugin.py you can now install your plugin as follows:

$ pyzeta plugin --install group_plugin.py
$ pyzeta plugin --install group_data.json

Your group can now be used e.g. in conjunction with symmetry reduction! If you would like to change the configuration data provided via group_data.json, simple adjust the file contents and issue the second command again.

Note that your plugin overrides the default groups contained in PyZeta. To restore these defaults simply --uninstall your plugin. By adapting the example above it is also quite straightforward to replace a given default group with your custom plugin and leave the remaining ones untouched. To achieve this the return value of your plugin’s initialize must accept a groupType parameter of type pyzeta.core.pyzeta_types.group_types.GroupType. You may then return any group of your choosing upon a given value of groupType.