Basic extension structure

An extension starts as a simple instance of labthings.extensions.BaseExtension. Each extension is described by a single BaseExtension instance, containing any number of methods, API views, and additional hardware components.

In order to access the currently running microscope object, use the labthings.find_component() function, with the argument "org.openflexure.microscope". Likewise, any new components attached by other extensions can be found using their full name, as above.

A simple extension file, with no API views but application-available methods may look like:

from labthings import find_component
from labthings.extensions import BaseExtension


def identify():
    """
    Demonstrate access to Microscope.camera, and Microscope.stage
    """
    microscope = find_component("org.openflexure.microscope")

    response = (
        f"My name is {microscope.name}. "
        f"My parent camera is {microscope.camera}, "
        f"and my parent stage is {microscope.stage}."
    )

    return response


def rename(new_name):
    """
    Rename the microscope
    """

    microscope = find_component("org.openflexure.microscope")

    microscope.name = new_name
    microscope.save_settings()


# Create your extension object
my_extension = BaseExtension("com.myname.myextension", version="0.0.0")

# Add methods to your extension
my_extension.add_method(identify, "identify")
my_extension.add_method(rename, "rename")

Once this extension is loaded, any other extensions will have access to your methods:

from labthings import find_extension

def test_extension_method():
    # Find your extension. Returns None if it hasn't been found.
    my_found_extension = find_extension("com.myname.myextension")

    # Call a function from your extension
    if my_found_extension:
        my_found_extension.identify()

Subclassing BaseExtension

The syntax used above allows novice programmers to easily start building extensions, without having to deal with subclassing. However, for more complex extensions which require persistent state, subclassing labthings.extensions.BaseExtension is recommended.

The same simple extension as seen above can be written using subclassing:

from labthings import find_component
from labthings.extensions import BaseExtension


# Create the extension class
class MyExtension(BaseExtension):
    def __init__(self):

        # Create some instance variable
        self.state_variable = "An example of a persistant instance variable"

        # Superclass init function
        super().__init__("com.myname.myextension", version="0.0.0")

    def identify(self):
        """
        Demonstrate access to Microscope.camera, and Microscope.stage
        """
        microscope = find_component("org.openflexure.microscope")

        response = (
            f"My name is {microscope.name}. "
            f"My parent camera is {microscope.camera}, "
            f"and my parent stage is {microscope.stage}."
        )

        return response

    def rename(self, new_name):
        """
        Rename the microscope
        """

        microscope = find_component("org.openflexure.microscope")

        microscope.name = new_name
        microscope.save_settings()


# Create your extension object
my_extension = MyExtension()