-
Notifications
You must be signed in to change notification settings - Fork 10
09. Extending Peakaboo
Peakaboo allows users who are familiar with the Java programming language to extend its functionality by creating custom filters and adding support for new file formats. Users who are interested in developing extensions for Peakaboo will need to make sure they have the Java Development Kit (JDK) installed on their computer (available from Java.com). A dedicated code editor is also recommended.
Plugins in Peababoo are classes which implement a specific interface.
The interface in question depends on the kind of plugin being created.
These plugin classes should be bundled in .jar
files and placed in the
correct plugin folder inside of the user’s application data directory.
For example, on Linux, this path is ~/.config/Peakaboo5/
. You can
access this folder by selecting Menu
→ Plugins
→ Open Folder
.
In order to know which classes to load without scanning each class in
every jar file, a jar containing a plugin must include a manifest file,
located at META-INF/services/
under the root of the jar file. The file
name must be the qualified name of the interface that this type of
plugin implements, and the contents of the file must be the qualified
names of each class to be loaded as a plugin, one per line.
The specific interfaces used for different types of plugins are:
-
Data Source:
org.peakaboo.dataset.source.plugin.DataSourcePlugin
-
Data Sink:
org.peakaboo.dataset.sink.plugin.DataSinkPlugin
-
Filter:
org.peakaboo.filter.model.Filter
, although see alsoorg.peakaboo.filter.model.AbstractFilter
-
Map Filter:
org.peakaboo.mapping.filter.plugin.MapFilterPlugin
Plugins should also define a public
no-argument constructor.
Example plugins for both filters and data sources are available online, along with a jar file containing Peakaboo for building against.
Filters define a series of Parameter
s, each with an
associated data type. These parameters are displayed in the filter’s
settings panel, using the associated data types and class information to
determine what kind of widgets should be used. These parameters should
be created and initialized in the filter’s initialize
method.
Once constructed, the parameter should be passed to the addParameter
method of the superclass. This method returns an integer value which you
can use to retrieve the parameter later using getParameter(int index)
.
The alternative is to simply keep local references to all your Parameter
s.
Here is an example of the initialize
method of the Addition
filter:
@Override
public void initialize()
{
Parameter<Float> add = new Parameter<>(
"Amount to Add", //Human-readable name
new RealStyle(), //Style hint for UI generation
1.0f, //Starting value
this::validate); //validation function
addParameter(add);
}
This creates a new Parameter
called Amount to Add
with
a Float data type, a default value of 1.0, and a validation function
defined elsewhere in the class body. It then adds it to this filter’s
set of parameters.
Whenever the user makes changes to a filter’s parameter value in the
Settings
dialog, the new parameter value is validated in a
call to the parameter’s validator method. In the example above, the
parameter’s validate method is in the filter itself, and could be used
by other parameters to validate combinations of values.
If the parameter values do not validate, then the input fields are reset to their old values.
An active filter’s filter(SpectrumView data, Optional<FilterContext> ctx)
method is called repeatedly. This method should return a modified SpectrumView
containing the results of filtering the input SpectrumView
.
The Spectrum
and SpectrumView
classes have a rough List
-like interface,
but use a fixed-size float
array to store the actual data for memory and
performance reasons. If you prefer to work with the float[]
data directly,
the backingArray
method provides direct access to it.
Adding support for new file formats in Peakaboo is accomplished by creating a
new Data Source. When creating a new data source, the DataSourcePlugin
interface must be implemented. The implementation should define a public
no-argument constructor. A Data Source has a number of methods to retrieve
other data structures, some of which are Optional
.
The FileFormat
interface is how a Data Source describes
the type of files it reads and tests if it can read specific files. When
the user opens one or more files, Peakaboo must determine which Data
Source plugin(s) may be used, and it relies on the Data Source’s
FileFormat
to inform it.
For convenience, the SimpleFileFormat
class provides an
easy way to get started, with file-extension based testing and the
ability to specify single or multi-file support. Because many data
sources use very common file extentions (e.g. .dat
) or container files
(e.g. HDF
), developers should consider implementing proper testing
through an examination of a file’s contents.
Once your data source has been selected, the void read(DataSourceContext ctx)
method will be called at most once. The paths given here will have already been
checked for compatibility through the supplied FileFormat
, so there is no
need to recheck the files.
Because Peakaboo is an interactive desktop application, progress should be
reported to the user through the Interaction
class. The Data Source interface
defines get/set methods for this object, and an instance will be provided by
Peakaboo before the data is read. It contains several methods which can be used
to report progress or allow user control.
boolean checkReadAborted()
void notifyScanCount(int scanCount)
void notifyScanRead(int number)
The checkReadAborted
method checks to see if the user has decided to abort the
read operation. This method should be checked periodically -- perhaps once per
second. If it ever returns true
, the read operation should be halted. The data
source instance will not be used after the user has requested the read to be
aborted, so there is no need to worry about any inconsistent state caused by
aborting the read. Any open files should still be closed.
The notifyScanCount
method reports the number of scans in the data set
to the user interface. The notifyScanRead
method reports that a
certain number of new scans have been read since it was last called.
These two methods used together allow Peakaboo to show the progress of
the read operation to the user. In some file formats, it is not feasible
to determine the number of scans in advance of reading them. In this
case, simply do not call either of these methods, and the interface will
show a "busy" indicator instead.
Once the read
method has been called, your data source will need to
provide access to the data. This is achieved through the ScanData
interface. For convenience, the SimpleScanData
and PipelineScanData
classes
are provided. The former is indented for ease of use, while the latter is
intended for best performance.
Each data source reads from different kinds of files, which contain
different kinds of information about the scan. Further information can
be exposed through the DataSize
, PhysicalSize
, and Metadata
interfaces, which are all access through the DataSource
interface as
Optional
values.