(1) Overview
Introduction
Nanopores are tiny holes in thin membranes with a nanometer-scale diameter similar to that of single biomolecules, such as proteins and DNA. They operate on a simple premise: a molecule (such as nucleic acids like DNA or RNA, or proteins) passes through a nanopore immersed in an electrolyte solution. When a voltage is applied, ionic current flows through the pore [1, 2, 3] and is transiently disrupted by the translocating molecule. These current blockages act as molecular signatures that provide insights into the polymer’s properties, including its size, charge, and structure.
There are two primary types of nanopores. Biological nanopores are typically engineered variants of naturally occurring membrane porins, and are widely used for sequencing [4]. Solid-state nanopores are biomimetic structures that consist of holes in solid-state membranes, such as silicon nitride. While they are less precise than their biological counterparts, they are more robust and tunable to a wider variety of targets and sensing conditions. After three decades of research, nanopore technology has become a promising tool in biophysics and proteomics, with numerous applications in life sciences, medicine, and information storage [5]. However, as the variety and complexity of applications increase, so does the complexity of the data that must be analyzed.
Nanopore data analysis refers to the process of analyzing the changes in the ionic current signal generated during the passage of a molecule through the nanopore. The goal is to identify, characterize, and interpret single-molecule translocation events to extract some physical insight into the target molecule. Various research groups have contributed tools and frameworks for this purpose. Collectively, these frameworks (see Table 1 for a non-exhaustive list) outline an analytical pipeline that encompasses data acquisition, digital signal filtering (or other preprocessing), event detection, feature extraction and segmentation, postprocessing, visualization and physical interpretation. Irrespective of the actual insight sought or details of the nanopore system being used, this series of steps forms the basis for all nanopore signal-processing pipelines.
Table 1
Tools and frameworks previously published for nanopore data analysis, included as Data plugins with Poriscope version 1.5.0.
| PLUGIN FUNCTION | PLUGIN NAME | FUNCTION |
|---|---|---|
| Load raw data | ABF2Reader | Read ABF files that conform to the TCossaLab standard (to be deprecated and renamed TCossaLabABFReader in version 1.6.0) |
| BinaryReader | Map any arbitrary binary file format that contains interleaved signal arrays | |
| BinaryReader1X | Map any arbitrary binary format that contains a single data channel | |
| ChimeraReader20240101 | Read data written by the ChimeraVC400 | |
| ChimeraReader20240501 | Read data written by the ChimeraVC400 | |
| ChimeraReaderVC100 | Read data written by the ChimeraVC100 | |
| SingleBinaryDecoder | Map a single binary file that conforms to the TCossaLab standard | |
| Filter time series data | BesselFilter | Apply a digital low-pass Bessel filter [14, 18] |
| WaveletFilter | Apply a wavelet filter [19] | |
| Find events | ClassicBlockageFinder | Find events that deviate from the local baseline by a preset amount [12] |
| BoundedBlockageFinder | Find events that deviate from the local baseline by a preset amount, only if the local baseline is within bounds | |
| Write event data to disk | SQLiteEventWriter | Store information about events found in SQLite format |
| Load events from disk | SQLiteEventLoader | Load information about events written by SQLiteEventWriter |
| Fit events | CUSUM | Fit events using the CUSUM algorithm [12, 14] |
| IntraCUSUM | Same as CUSUM, but also extracts additional event metadata | |
| NanoTrees | Fit events using Nano Trees [20] | |
| PeakFinder | Find and characterize sharp peaks in events | |
| Write event metadata | SQLiteDBWriter | Write event fit metadata to SQLite format |
| Load event metadata | SQLiteDBLoader | Load event fit metadata written by SQLiteDBWriter |
Despite the existence of a common workflow, each of these programs is based on entirely different data formats and fitting methods, and are rarely interoperable as a result. Even though the overall process remains the same, critical details differ, and the statement by Plesa et al. that ‘the majority of data analysis is done on custom software that differs from lab to lab’ remains valid over a decade later [6].
In addition to fragmentation of methods in the field, most papers proposing new analysis tools tend to focus on improving just one or a few of the above steps rather than considering how they could fit into other analysis pipelines. Notably, recently proposed methods tend to focus on refinement of event detection algorithms [7] or finding new ways to fit translocation events [6, 8]. These algorithms are often embedded within custom frameworks that do not necessarily lend themselves to use outside of the lab in which they originated. In this respect, Forstater et al.’s MOSAIC framework is an exception that sought to introduce the kind of modularity we discuss here. Although the authors of these tools often acknowledge the lack of standardization, research consistently shows that no single method, even with tunable parameters, performs optimally across all experimental contexts [9].
Analysis tools such as OpenNanopore, AutoNanopore, and Pulse Detection Transformer (PETR) operate as specialized methods targeting specific stages of the nanopore analysis pipeline, rather than as comprehensive platforms. OpenNanopore focuses on multilevel event fitting [8], AutoNanopore introduces an automated adaptive algorithm for fast and accurate event detection [10], and PETR employs a transformer-based deep learning architecture to detect current pulses [11]. Although these tools represent significant advances within the context of individual processing steps, they remain isolated components within the larger workflow and do not provide full pipeline functionality as defined above.
Some tools approach a full nanopore analysis pipeline, including MOSAIC, EventPro, Transalyzer, and Nanolyzer. MOSAIC focuses on the introduction of two complementary algorithms for event fitting: ADEPT and an enhanced version of the Cumulative Sum (CUSUM) algorithm [12]. EventPro emphasizes multilevel fitting [13]. Transalyzer implements a detection algorithm to address moving-average detection [6] and uses a slight modification to the MOSAIC version of CUSUM for event fitting. Nanolyzer, sold by Northern Nanopore but recently discontinued, implemented CUSUM for event fitting as well [14, 15]. While these platforms offer the most extensive pipeline coverage to date, they still depend on custom, in-house routines for each processing stage, meaning that their workflows (though in some cases comprehensive) still lack cross-laboratory standardization and, with the exception of MOSAIC, cannot easily be extended to incorporate new functionality. None are parallelized to allow for the analysis of the multi-channel data that is becoming more common in nanopore research. Of the available frameworks, MOSAIC is most similar in scope and function to Poriscope, allowing for the definition of new plugins that can interoperate with existing ones through application programming interface (API) compliance. The primary differences between Poriscope and MOSAIC lie in the way plugins are integrated within the overall framework, with Poriscope automatically detecting new plugins on the fly and requiring no user knowledge of the Poriscope backend in order to develop plugins. Poriscope also ships with a larger variety of plugins by default, and is in principle not limited to analysis of nanopore data, but rather can be used to analyze almost any time series data through the addition of an appropriate plugin.
Addressing this need is a non-trivial challenge. A system that responds to the need should do several things. It must:
Implement a complete analysis pipeline without sacrificing modularity and extensibility,
Allow users to easily customize each analytical stage to suit their experimental context, and
Be usable by someone without much programming background.
Poriscope, the software presented herein, is a unifying framework that addresses the above requirements. It provides scaffolding for a modular nanopore data analysis pipeline in which each step is serviced by a dedicated plugin that conforms to a well-defined and documented class interface, constituting Poriscope’s API. Any existing analysis component, be it reading a new data format, preprocessing or filtering data, fitting events, and more, can be implemented as an isolated plugin that, through Poriscope’s architecture, can interoperate seamlessly with any other part of the analysis pipeline.
Figure 1 highlights the modular approach used by Poriscope. Self-contained plugins manage each of the following steps, which are further subdivided into three broad segments of the analysis pipeline, each comprising sub-elements that are also implemented as plugins:

Figure 1
Poriscope Analysis Pipeline. First, raw data is loaded into the Event Finding Module. Preprocessing (e.g., digital low-pass filtering) can be performed before the events are identified (e.g., using a simple thresholding) and stored in a database. Second, the data from this database is loaded, and preprocessing can be performed prior to event fitting (e.g., using CUSUM), followed by storing of the fit metadata in a database. Finally, for visualization, the fit metadata is loaded and specific subsets can be selected (e.g., via SQL queries) before the data is displayed, labeled, and classified.
Event finding, which includes:
loading raw data from any file format,
filtering or pre-processing that raw data by any method,
finding events in the processed data, and
storing these events to disk;
Event fitting, which includes:
reloading these events from disk,
filtering or pre-processing the event data,
fitting events or otherwise extracting event metadata,
saving event metadata to disk; and
Visualization and post-processing, which includes:
loading event metadata from disk,
postprocessing event metadata,
clustering events, and
visualizing event metadata.
Poriscope can operate either as a graphical desktop application, or its component plugins can be used directly in Python code as elements of custom analysis scripts. Its architecture distinguishes between two plugin types: frontend plugins (or ‘analysis tabs’), which define self-contained graphical interfaces that present a single section of the nanopore analysis pipeline (the three segments noted above), and backend plugins (or ‘data plugins’), which implement the distinct methods for loading data, filtering, detecting, fitting, saving, and loading results from previous steps (sub-elements in the list above). The analysis pipeline implemented by default is fully parallelized (aside from some serial write operations), can analyze any number of data channels concurrently, and can, in principle, perform any analysis task that can be applied to a 1D time series, including those beyond nanopore data.
These steps capture both the iterative nature of event analysis and the decision points at which methodological variations can be introduced.
The framework also supports dynamic plugin discovery: new plugins are automatically recognized at startup and integrated into the graphical user interface (GUI) without any action from the developer other than API compliance. Poriscope is open source (under the MIT license), features quick deployment, and includes a comprehensive online repository containing documentation, tutorials, and a complete set of API references to facilitate adoption and community-driven extension.
1. Implementation and Architecture
Poriscope is implemented in Python 3.12.10 with a PySide6 frontend and a combination of Python and C for the backend. The framework is designed to be an extensible, plugin-based application that respects strict Model–View–Controller (MVC) architecture. The primary advantage of this architecture lies in the clear separation of concerns (SoC) among the user interface, data management, and control logic, which enhances code reusability, scalability, and testability.
This architecture is used to allow dynamic incorporation of new capabilities through plugins that respect a well-defined and documented API that is enforced using base classes and connected using a flexible signal-based communication layer.
1.1 MVC Architecture
The Poriscope framework is structured around a hierarchical MVC architecture in which views and models are subordinate to controllers. The main interface consists of a Main Controller, Main View, and Main Model that serve to provide the core functionality through which all plugins interact and communicate. The high-level architecture is shown in Figure 2.

Figure 2
System Architecture Overview showing the nested MVC structure in which Controllers handle communication between the frontend and backend, and plugins are isolated from one another to enforce a high degree of modularity and extensibility.
MainView manages the GUI layout, including persistent elements such as the top and side menus, as well as the integrated logging console. It provides a top-level set of menus to interact with the rest of the software, a status box that displays helpful messages and errors, and a canvas space on which Analysis Tab plugins, detailed shortly, are used to provide additional capabilities to the user.
MainModel handles the application’s shared data structures and global resources. It is responsible for managing available plugins and maintaining the details of the internal state of the program.
MainController serves as the central coordinator, mediating communication and logic flow between models and views, and providing a central switchboard through which signals are passed between different plugins and between plugins and the main application.
1.2 Two plugin types
Poriscope has two plugin types: AnalysisTab plugins, which provide a GUI for user interaction, and Data plugins, which manage a single part of a nanopore analysis workflow and can be used both as part of the GUI or as standalone Python objects for scripting.
1.2.1 AnalysisTab plugins
AnalysisTab plugins belong to the frontend layer of Poriscope, extending the GUI by adding new analysis or visualization elements that exist inside the graphical display of MainView. These plugins are directly managed by the Main MVC, meaning they are dynamically instantiated at runtime. This dynamic instantiation allows the application to expand seamlessly as a single, cohesive system, with new analysis modules integrated without modification into the core architecture. The primary purpose of an AnalysisTab plugin is to provide a graphical interface to one or sometimes several data plugins, encapsulating a self-contained segment of a nanopore analysis workflow into visual element to facilitate user interaction.
Each AnalysisTab plugin implements its own nested MVC architecture, consisting of a View that appears in the canvas area of the MainView. An AnalysisTab View typically implements a control panel and a visualizing area (a matplotlib plot canvas, in the case of the default AnalysisTabs that ship with Poriscope), though in principle there are no constraints on visual elements shown. The AnalysisTab controller serves as a relay layer between the visual elements and both the AnalysisTab Model and the main application layer, and the AnalysisTab Model maintains any details of the internal state of the AnalysisTab that are independent from the main application. These elements must conform to a well-defined API implemented in the base classes MetaView, MetaController, and MetaModel, respectively. Only a single instance of each AnalysisTab type can exist concurrently within Poriscope.
At the time of writing, Poriscope includes four AnalysisTab plugins:
RawDataTab, which houses elements required to preprocess, find, and store events in raw data;
EventAnalysisTab, which loads event data stored by RawDataTab, fits the events, and stores event metadata;
MetadataTab, which loads event metadata databases and provides Structured Query Language (SQL) filtering and visualization capabilities; and
ClusteringTab, which loads metadata databases and provides an interface to several common unsupervised clustering tools for event classification.
Additional AnalysisTab plugins are planned as part of ongoing Poriscope development.
1.2.2 Data plugins
Data plugins belong to the backend layer of Poriscope and are responsible for handling one step of data analysis. These plugins are logic-only components that do not include a graphical interface, resulting in a simpler structure typically consisting of a single class. Like AnalysisTabs, Data plugins inherit from a set of base classes that collectively define the API appropriate to that type of Data plugin. Each of these base classes inherits in turn from BaseDataPlugin, an overarching base class that defines interface elements common to all Data plugins irrespective of function.
All data plugins are managed by a dedicated MVC structure, as shown in Figure 2. This consists of a DataPluginView that provides a set of widgets with which Poriscope can prompt the user for input relating to the instantiation of a Data Plugin, a DataPluginController that handles signal relay between data plugins and the rest of Poriscope, and a DataPluginModel that holds and manages all available data plugin types and instances.
1.3 Extensibility mechanisms
1.3.1 Base classes
Base classes define common structures and behaviors that other classes may inherit, providing a reusable template for specialized implementations and a way to define and enforce an API. Beyond its MVC foundation, Poriscope makes extensive use of base classes to enforce architectural consistency and facilitate the creation of custom plugins to extend the application’s analysis pipeline. If a plugin fully conforms to the API defined by the appropriate base class and related naming conventions, Poriscope will automatically detect and incorporate new plugins without any further user input. This process is further facilitated by the extensive documentation (available at https://tcossalab.github.io/poriscope/), which provides a detailed walkthrough for both users and plugin developers.
Base classes underlie all plugin capabilities of Poriscope, which ships with 12 such base classes, out of which the user should be familiarized with up to 11 if they wish to create a new API-compliant plugin: MetaReader, MetaFilter, MetaEventFinder, MetaWriter, MetaEventLoader, MetaEventFitter, MetaDatabaseWriter, MetaDatabaseLoader, MetaModel, MetaView, and MetaController.
1.4 Signals
In PySide6 (and consequently in Poriscope), signals are used by a graphical interface to indicate that an event has occurred (for example, the user clicking a button). Poriscope uses this communication model to promote modularity and low inter-component dependency. Because all signal connections are handled in the main Poriscope architecture and not in the plugin layer, plugins can react dynamically to events caused by other plugins without requiring, for example, that the developer of a new Data plugin think about how an AnalysisTab might interact with it, and vice versa. Such an approach is particularly effective in applications like Poriscope, where independence between modules is critical for extensibility, and the capabilities of new plugins must be accessible to the overall system without knowledge of what that might mean in practice in the future.
The only signal that is necessary for a plugin developer to use, called the global_signal, is available in AnalysisTab plugins. It is used to call functions in Data plugins from the context of an AnalysisTab plugin.
1.4.1 Global signal
In Poriscope, many operations, such as data processing, analysis, or filtering, require coordination between multiple components that do not directly reference one another. To achieve this, Poriscope employs a signal-driven workflow, ensuring that each module performs its designated function while maintaining architectural independence.
The Global Signal facilitates general actions across the system that involves invoking the method in an instance of a Data Plugin from inside an instance of an AnalysisTab. The process works as follows:
Signal Emission: When a user initiates an action within an AnalysisTab View (for example, requesting data filtering or analysis based on selected parameters), the view emits a global_signal containing the details of the Data plugin for which the request is being sent, the name and arguments of the function defined in that Data plugin to be called, instructions for where to relay the return value of that function call, and any additional data needed to complete the command.
Signal Routing: The signal is received by the appropriate AnalysisTab Controller, which forwards it to the MainController, and from there to the Data Plugin Controller. The Data Plugin Controller relays it to the Data Plugin Model, which identifies the correct Data Plugin instance with which to interact.
Task Execution: The Data Plugin Controller invokes the relevant method of the targeted plugin, calling it with the argument provided to the original global_signal.
Result Propagation: The return value of the call is relayed back along the reverse of the path taken by the inbound signal. Upon reaching the MainController, the method of the AnalysisTabController specified in the original global signal invocation is called with this return value and any additional data provided to the global signal. The programmer can then either have the AnalysisTabController instance process it directly or relay it to either or both the AnalysisTab View or Model as appropriate. Practically speaking, this means that a user can create an AnalysisTab instance and have full access to the API of all Data plugins.
Without this global signal mechanism, every new plugin introduced into Poriscope would require explicit references and hard-coded connections within the controllers and views to trigger its functionalities. In particular, the MainController would need to maintain direct knowledge of all available plugins. Such coupling would significantly increase maintenance complexity, reduce flexibility, and ultimately undermine the modular design that enables Poriscope’s scalability. Use of the global signal allows for full independence of all plugins from the main MVC architecture and from other plugins. This design promotes extensibility, maintainability, and a clear separation of concerns across the entire framework.
Quality control
Quality control in Poriscope is established through both Continuous Integration (CI) and Continuous Delivery (CD) pipelines implemented through GitHub Actions. Additionally, a defensive quality assurance approach was enforced during development through local Git Hooks, which required key checks to pass locally before changes could be pushed to the remote repository.
The CI pipeline serves as a quality control mechanism to ensure stability for every commit and Pull Request (PR). The depth of testing performed depends on the origin of the change and its associated risk, with test coverage spanning one or more of the following levels: static analysis (linting, formatting, and type checking), unit testing for validation of individual components, integration testing to verify interactions between components (covering the core workflow), and end-to-end (E2E) testing to validate complete system behaviour (currently covering the Raw Data step).
The current overall test coverage is approximately 44%. While a coverage level of 80% is often cited as a benchmark [16, 17] (and remains our objective), the overall codebase includes a substantial number of widgets and utility functions. However, when considering the core functional components, particularly the base classes powering the plugin architecture, test coverage reaches approximately 62%. In addition, E2E tests validate that the defined subclasses behave as expected, thereby further supporting the robustness of the implementation.
The correct operation of the software can be verified by running the automated test suite locally using pytest, with successful completion indicating that the core functionality behaves as expected. The steps to do this can be found in the documentation, along with a quality assurance (QA) checklist for contributors, which includes how to set up the local hooks to ensure constant and consistent QA. Additionally, the ‘Running the Software’ section provides a practical example demonstrating execution with sample input and corresponding output data. The dataset used is the same as that featured in the Youtube series (available here: https://www.youtube.com/@TCossaLAB/playlists, can be found at the following DOI: https://doi.org/10.20383/103.01599).
As of publication, Poriscope provides plugins to implement several analysis methods, all of which have previously been published or are components of methods that have previously been published. Table 1 below summarizes the methods that ship as Data plugins with Poriscope currently. These methods have been verified against existing implementations to ensure correctness.
(2) Availability
Operating system
Windows 10 or later. Linux support is available in the develop branch and is scheduled for release in version 1.6.0 in May 2026.
Programming language
Python 3.12.10, C, ReStructured Text.
Additional system requirements
Memory requirements scale with the size of the dataset being analyzed but any computer that can run Windows 10 will suffice.
Dependencies
PySide6==6.9.0
numpy==2.2.6
matplotlib==3.10.3
pandas==2.2.3
platformdirs==4.3.8
scipy==1.15.3
kneed==0.8.5
fast-histogram==0.14
sphinx==8.2.3
sphinx-tabs==3.4.7
furo==2024.8.6
scikit-learn==1.6.1
hdbscan==0.8.40
List of contributors
Same as author list.
Software location
Archive: Zenodo
Name: Poriscope 1.5.0
Persistent identifier: https://doi.org/10.5281/zenodo.17860300
Licence: MIT License
Publisher: The Tabard-Cossa Lab
Version published: 1.5.0
Date published: 27/08/2025
Code repository Name: GitHub
Identifier: https://github.com/TCossaLab/poriscope
Licence: MIT
Date published: 27/08/2025
Language
English
(3) Reuse Potential
Nanopore research is currently characterized by a fragmented ecosystem of lab-specific tools, which limits interoperability, reuse, and long-term sustainability. Poriscope addresses these limitations through a plugin-based architecture that decouples core functionality from specialized domain logic. Rather than introducing standalone tools, researchers can contribute plugins that integrate directly into a shared and extensible framework, letting Poriscope handle translation between the inputs and outputs of each step.
Under this premise, Poriscope can be adapted by introducing new plugins that augment any of the existing analysis steps (Figure 1), such as implementing alternative event detection or fitting algorithms, without needing to change anything about adjacent workflow steps. Detailed implementation details are provided in the ‘Plugin Development’ section of the Poriscope documentation.
Overall, Poriscope’s dynamic architecture allows contributors to focus on domain-specific behavior while relying on the framework for orchestration and interoperability, enabling researchers to adapt the software to new experimental contexts with minimal effort and more efficient collaboration between labs.
The Table 2 maps existing software tools to the base classes that a user would have to subclass if they were to implement these tools as Poriscope plugins.
Table 2
Map of existing nanopore analysis tools to possible future Poriscope plugins.
| EXISTING SOFTWARE TOOL | BASE CLASS | METHOD/PURPOSE |
|---|---|---|
| AutoNanopore [10] | MetaEventFinder | Automated adaptive event detection with trace segmentation, statistical outlier identification, and baseline variation handling |
| OpenNanopore [8] | MetaEventFinder, MetaEventFitter | Adaptive threshold-based event detection with baseline tracking; multi-level current blockade fitting using CUSUM algorithm for dwell time and amplitude extraction |
| PETR (Pulse Detection Transformer) [9] | MetaEventFinder | Machine learning-based threshold-free pulse detection using transformer architecture for start/end point determination |
| EventPro [13] | MetaEventFinder, MetaEventFitter | Event detection with adaptive baseline methods (mean, linear, Gaussian, regression-mixed); multilevel fitting via DBSCAN clustering and iterative level refinement |
| MOSAIC [12] | MetaEventFinder, MetaEventFitter, MetaWriter, MetaDatabaseWriter, MetaLoader, MetaDatabaseLoader | ADEPT: physical model for transient sub-steady-state events; CUSUM+: optimized for longer steady-state events; other modular pipeline segments can translate directly to Poriscope plugins |
| Transalyzer [6] | MetaEventFinder, MetaEventFitter, | Iterative baseline reconstruction via event removal; current spike extraction within events; unfolded event separation |
All the Data plugins distributed with Poriscope, as well as user-defined Data plugins, are not limited to use within Poriscope’s GUI. Poriscope’s Data plugins can also be used as standalone Python objects in custom workflow scripts. The ‘Getting Started’ section of the documentation describes how to install Poriscope to function as an importable command-line tool and Python module using pip or another similar package manager.
Support for new users is provided in the form of extensive documentation and a detailed YouTube Tutorial series, available here: https://www.youtube.com/@TCossaLAB/playlists. Users can contribute plugins by forking the repository, then opening a pull request to the main GitHub repository, or flag bugs by raising GitHub issues. Pull requests will be required to pass CI checks detailed above before acceptance.
Finally, while Poriscope is designed for the analysis of nanopore experimental data, its plugin-based architecture and general approach to time series analysis allow it, in principle, to be applied to the analysis of other forms of time series data outside the nanopore field. Any time series analysis task that involves isolating segments of interest from a larger time series and extracting physical insight from those segments (such as single-molecule FRET data) could be implemented as a Poriscope pipeline.
Acknowledgements
The developers would like to thank members of the Tabard-Cossa lab for taking the time to alpha test new functions and provide feedback on the evolution of Poriscope.
