Writing plugins#
By writing a plugin, you can define your own analysis routines and specify them in your configuration file.
Note
If you are not familiar with plugins and entrypoints, you may want to read Python packaging guide and Setuptools documentation first.
Analyzers#
Let us suppose that we want to implement an analysis type Foo for the
following configuration file entry:
foo:
type: Foo
...
For this, we can write a simple plugin named finitedepth-foo.
The package structure will be:
finitedepth-foo
├── pyproject.toml
└── foo.py
In foo.py we define:
def foo_analyzer(name: str, data: dict):
... # do whatever you want
The signature of analyzers is specified in analyze_files().
Then, in pyproject.toml we define a table to register
foo_analyzer() to Foo:
[project.entry-points."finitedepth.analyzers"]
Foo = "foo:foo_analyzer"
Now, by installing the finitedepth-foo package, the analysis type Foo
will be recognized.
Samples#
As shown in Tutorial, DipCoatImage-FiniteDepth supports ‘finitedepth samples’ command to print the path to the directory where sample files are stored. If your plugin has its own sample directory, you can register it to the same API.
To distribute the sample files as package data, the finitedepth-foo
needs to be a little more complicated:
finitedepth-foo
├── pyproject.toml
├── MANIFEST.in
└── src
└── foo
├── samples
└── __init__.py
Make sure that the sample directory is included in MANIFEST.in.
Then, in __init__.py we define:
from importlib.resources import files
def sample_path():
return str(files("finitedepth-foo").joinpath("samples"))
And in pyproject.toml we define a table:
[project.entry-points."finitedepth.samples"]
foo = "foo:sample_path"
Then, invoking finitedepth samples foo will print the path to
the samples directory.
Note that sample_path() can have different signature as long as it
returns the correct path when called with empty argument.
References, Substrates, and Coating layers#
As explained in Background, analysis is based on reference object, substrate object, and coating layer object. For analyzers to access these classes defined by plugins, entry points “finitedepth.references”, “finitedepth.substrates”, and “finitedepth.coatinglayers” are reserved.
Let’s assume that we have defined a substrate class in foo.__init__.py.
from finitedepth import SubstrateBase
class MySubstrate(SubstrateBase):
def __init__(self, reference, *args):
super().__init__(reference)
...
In pyproject.toml we define a table:
[project.entry-points."finitedepth.substrates"]
MySubstrate = "foo:MySubstrate"
After defining your own class in your plugin, register its constructor to the corresponding entry point. Note that the constructor should be able to return the instance from primitive variable passed from the configuration file.