Skip to content

Repository files navigation

CurrentView

A Python package for visualizing nanopore sequencing signals at specific reference positions. This tool enables researchers to plot and compare signal patterns from POD5 files aligned to reference genomes via BAM files.

Features

  • Signal Visualization: Plot nanopore signals from POD5 files at specific reference positions
  • Multi-condition Comparison: Overlay multiple conditions/samples for direct comparison
  • Statistical Analysis: Calculate and visualize statistics across positions
  • GMM Fitting: Fit Gaussian Mixture Models for advanced analysis

Output sample

'Signals sample''KDE sample'

Table of Contents

Installation

git clone https://github.com/genometechlab/currentview.git
cd currentview
pip install -e .

Dependencies

  • numpy>=1.20.0
  • matplotlib>=3.5.0
  • plotly>=5.14.0
  • kaleido>=0.2.0
  • nbformat>=5.10.4
  • pysam>=0.22.0
  • scikit-learn<2.0,>=1.4
  • umap-learn>=0.5.11
  • pod5>=0.3.23
  • dash>=2.14.0
  • dash-bootstrap-components>=1.5.0
  • scipy>=1.10.0
  • pandas>=1.5.0

CurrentView is implemented and tested with Python 3.12.8.

Quick Start

fromcurrentviewimportCurrentView, PlotStyle# Create visualizer for a 9-base window with statisticscv=CurrentView(K=9, stats=['mean', 'std', 'median'])
# Add signals aligned to a reference positioncv.add_condition(
bam_path="sample1.bam",
pod5_path="sample1.pod5",
contig="chr1",
target_position=100,
label="IVT"
)
# Add another condition for comparisoncv.add_condition(
bam_path="sample2.bam",
pod5_path="sample2.pod5",
contig="chr1",
target_position=100,
label="Canonical",
color="red"
)
# Display the signal plotcv.show_signals()
# Display the stats plotcv.show_stats()
# Or display bothcv.show()

Implementation examples are provided under example folder

Core API

CurrentView

The main class for visualization.

CurrentView(
K: int=9,
kmer: Optional[List[Union[str, int]]] =None,
stats: Optional[List[Union[str, Callable]]] =None,
signal_processing_fn: Optional[callable] =None,
signals_plot_style: Optional[PlotStyle] =None,
stats_plot_style: Optional[PlotStyle] =None,
color_palette: Optional[Union[str, ColorPalette]] =None,
title: Optional[str] =None,
verbosity: VerbosityLevel=VerbosityLevel.SILENT,
logger: Optional[logging.Logger] =None
)

Parameters:

  • K: Window size (will be made odd if even). Default: 9
  • kmer: Optional custom k-mer labels for x-axis. Should be an iterable with size K
  • stats: List of statistics to include. Supports 'mean', 'median', 'std', 'variance', 'min', 'max', 'skewness', 'kurtosis', and user-defined callables
  • signal_processing_fn: Optional callable for custom signal processing
  • signals_plot_style: PlotStyle object for signal visualization customization
  • stats_plot_style: PlotStyle object for stats visualization customization
  • color_palette: Color palette name (string) or ColorPalette instance
  • title: Plot title
  • verbosity: Logging level (0-4 or VerbosityLevel enum):
    • 0 = SILENT: No output
    • 1 = ERROR: Only errors
    • 2 = WARNING: Errors and warnings
    • 3 = INFO: Errors, warnings, and info
    • 4 = DEBUG: Everything including debug messages
  • logger: Optional custom logger instance

Main Methods

add_condition()

Add and process a new condition from BAM and POD5 files.

cv.add_condition(
bam_path: Union[str, Path],
pod5_path: Union[str, Path],
contig: str,
target_position: int,
*,
molecule_type: str="RNA",
matched_query_base: Optional[str] =None,
read_ids: Optional[Union[Set[str], List[str]]] =None,
max_reads: Optional[int] =None,
exclude_reads_with_indels: bool=False,
label: Optional[str] =None,
color: Optional[str] =None,
alpha: Optional[float] =None,
line_width: Optional[float] =None,
line_style: Optional[str] =None
) ->CurrentView

Parameters:

  • bam_path: Path to BAM alignment file (required)
  • pod5_path: Path to POD5 signal file (required)
  • contig: Chromosome/contig name, e.g., "chr1" (required)
  • target_position: 1-based reference position (required)
  • molecule_type: Type of molecule, "RNA" or "DNA" (default: "RNA")
  • matched_query_base: Expected base at target position for validation (default: None)
  • read_ids: Specific read IDs to include (default: None - all aligned reads)
  • max_reads: Maximum number of reads to process (default: None - no limit)
  • exclude_reads_with_indels: Skip reads with insertions/deletions (default: False)
  • label: Condition name (default: {contig}:{target_position})
  • color: Line color (default: auto-assigned from palette)
  • alpha: Line transparency 0-1 (default: auto-calculated based on read count)
  • line_width: Line thickness (default: from style)
  • line_style: Line style: "solid", "dash", "dot", "dashdot" (default: from style)
update_condition()

Update visualization parameters of an existing condition.

cv.update_condition(
label: str,
*,
color: Optional[str] =None,
alpha: Optional[float] =None,
line_width: Optional[float] =None,
line_style: Optional[str] =None
) ->CurrentView
show(), show_signals(), and show_stats()
# Display both signals and stats plotscv.show()
# Display only the signals plotcv.show_signals()
# Display only the stats plotcv.show_stats()
save(), save_signals(), and save_stats()
# Save both plots (adds _signals and _stats suffixes)cv.save(path="output.png", format='png', scale=1)
# Save only signals plotcv.save_signals(path="signals.png", format='png', scale=1)
# Save only stats plotcv.save_stats(path="stats.png", format='png', scale=1)

Other Methods

# Highlight a position in the windowcv.highlight_position(window_idx=4, color='red', alpha=0.2)
# Highlight the center positioncv.highlight_center(color='red', alpha=0.2)
# Remove all highlightscv.clear_highlights()
# Add text annotationcv.add_annotation(window_idx=4, text="SNP", y_position=150)
# Remove annotationscv.clear_annotations()
# Set plot titlecv.set_title("Signal comparison at chr1:1000000")
# Set y-axis limitscv.set_ylim(bottom=50, top=200)
# Get/print summarysummary=cv.get_summary()
cv.print_summary()
# Remove a conditioncv.remove_condition("Control")
# Clear all conditionscv.clear()
# Get condition namesnames=cv.get_condition_names()
# Get specific conditioncond=cv.get_condition("Control")
# Change verbositycv.set_verbosity(3) # Set to INFO level# Update stylescv.set_signals_style(new_style)
cv.set_stats_style(new_style)
UMAP dimensionality reduction
umap_handler=cv.fit_umap(
stats=['median', 'std'], # Alist of stats to extract feature for umapoffset_window, # Optional: span of signal, should be a tuple (stat_window_index, end_window_index), inclusiven_neighbors=10, min_dist=0.1
)
# plot UMAP scattersumap_viz=umap_handler.visualize(
style, #Plotstyle Object
)
GMM Methods

Fit and visualize Gaussian Mixture Models:

# Fit GMMs and get resultsgmm_results=cv.fit_gmms(
stat1='mean',
stat2='std',
offset_window, # Optional: span of signal, should be a tuple (stat_window_index, end_window_index), inclusivegmm_config=GMMConfig(...),
preprocess_config=PreprocessConfig(...)
)
# Fit and plot GMMsgmm_viz=gmm_handler.visualize()
# orgmm_viz=cv.plot_gmms(
stat1='mean',
stat2='std',
offset_window, # Optional: span of signal, should be a tuple (stat_window_index, end_window_index), inclusivegmm_style=PlotStyle(...),
gmm_config=GMMConfig(...),
preprocess_config=PreprocessConfig(...)
)
# Kolmogorov–Smirnov testks_result=gmm_handler.ks_test(
label_p='label_p', # Label of the first conditionlabel_p='label_q', # Label of the second conditioncorrection='bonferroni',
mode='auto',
drop_nonfinite=True,
verbose=True)
# Jensen-shannon divergencejs_result=gmm_handler.js_divergence(
label_p='label_p', # Label of the first conditionlabel_p='label_q', # Label of the second conditionn_samples=20000,
base=2,
randon_sate=None, # controls the sampling seedverbose=True)

Styling and Customization

The appearance of plots can be customized using the PlotStyle class:

fromcurrentview.utils.plotly_utilsimportPlotStylefromcurrentview.utils.color_utilsimportColorPalette# Create custom stylestyle=PlotStyle(
width=1200, # pixelsheight=800, # pixelsline_width=2.0,
line_style="solid", # "solid", "dash", "dot", "dashdot"opacity_mode='auto', # 'auto' or 'fixed'fixed_opacity=0.8,
fill_opacity=0.3,
# ... more options
)
cv=CurrentView(
K=9,
signals_plot_style=style,
stats_plot_style=style,
color_palette="colorblind"# or ColorPalette instance
)

A complete guide to PlotStyle can be found in plotstyle_guide.md.

Examples

Implementation examples are provided under example folder

Example 1: Basic Single Condition

fromcurrentviewimportCurrentViewcv=CurrentView(K=9, verbosity=3)
cv.add_condition(
bam_path="sample.bam",
pod5_path="sample.pod5",
contig="chr1",
target_position=100
)
cv.set_title("Nanopore Signals at chr1:1000000")
cv.show_signals()

Example 2: Comparing Multiple Conditions

fromcurrentviewimportCurrentViewfromcurrentview.utils.plotly_utilsimportPlotStylestyle=PlotStyle(width=1400, height=800)
cv=CurrentView(K=9, signals_plot_style=style)
conditions= [
("control.bam", "control.pod5", "Control", "blue"),
("treated.bam", "treated.pod5", "Treatment", "red"),
("knockout.bam", "knockout.pod5", "Knockout", "green"),
]
forbam, pod5, label, colorinconditions:
cv.add_condition(
bam_path=bam,
pod5_path=pod5,
contig="chr1",
target_position=100,
label=label,
color=color,
max_reads=50
)
cv.highlight_center(color='yellow', alpha=0.3)
cv.add_annotation(window_idx=4, text="Target")
cv.set_title("Signal Comparison at chr1:1000000")
cv.save("comparison.png")

Example 3: With Statistics

cv=CurrentView(
K=9,
stats=['mean', 'median', 'std', 'skewness']
)
cv.add_condition(
bam_path="sample.bam",
pod5_path="sample.pod5",
contig="chr1",
target_position=100,
label="Sample"
)
# View signalscv.show_signals()
# View statisticscv.show_stats()
# Print summarycv.print_summary()

Example 4: Filtering Specific Reads

target_reads= ["read_001", "read_002", "read_003"]
cv=CurrentView(K=11)
cv.add_condition(
bam_path="sample.bam",
pod5_path="sample.pod5",
contig="chr2",
target_position=5000000,
read_ids=target_reads,
exclude_reads_with_indels=True,
label="Selected Reads"
)
cv.print_summary()
cv.show()

Example 5: Method Chaining

(CurrentView(K=9, stats=['mean'])
.add_condition("sample.bam", "sample.pod5", "chr1", 12345, label="Sample")
.highlight_center(color='red')
.set_title("My Analysis")
.show())

Practical Considerations

Performance Optimization

Processing BAM and POD5 files can be computationally expensive. For better performance:

  1. Limit reads for large datasets:

    cv.add_condition(..., max_reads=100)
  2. Filter out reads with indels:

    cv.add_condition(..., exclude_reads_with_indels=True)
  3. Use appropriate verbosity:

    cv=CurrentView(K=9, verbosity=0) # Silent for productioncv.set_verbosity(4) # Debug for troubleshooting

Visual Clarity

  1. Adjust alpha for overlapping signals:

    style=PlotStyle(opacity_mode='auto') # Auto-adjusts based on read countcv.add_condition(..., alpha=0.5) # Or set manually
  2. Use contrasting colors:

    cv=CurrentView(color_palette="colorblind")
  3. Limit window size for clarity: K=9 or K=11 work well for most cases

Common Issues

  1. No reads found at position:

    • Verify correct contig name (e.g., "chr1" vs "1")
    • Check position is correct (1-based in this API)
    • Increase verbosity to see detailed logs
  2. Memory issues with large files:

    • Use max_reads parameter
    • Filter reads by specific read IDs
  3. Overlapping signals hard to see:

    • Adjust alpha transparency
    • Reduce number of reads
    • Use different colors
    • Increase figure size
  4. Label "already exists" error:

    • Each condition needs a unique label
    • Use remove_condition() first, or specify a unique label

Web-application

Currentview is also available as a web application. After completing the installation, activate your environment and run:

currentview-app

Once the application has initialized, it will automatically open the Currentview web interface in your default browser.

On the landing page, users can configure general visualization parameters, including the k-mer window size and the statistics to be displayed. This functionality is largely equivalent to the CurrentView component of the Python API.

'Application landing page'

On the subsequent page, the interface is organized into three panels:

  • Add Condition Panel: This panel allows users to define condition-specific parameters, including the path to the BAM file, the POD5 directory, the target genomic position, and the maximum number of reads. It also provides controls for condition-level visualization settings such as color opacity, line style, and line width. This panel is equivalent to the add_condition method of the Python API.

  • Conditions Panel: This panel displays all previously added conditions in the order they were added. Visualization attributes for each condition can be modified directly within this panel. This panel is equivalent to the update_condition method of the Python API.

  • Visualization Panel: This panel presents the signal plots and, if requested, the associated statistical summaries.

'Application'

License

This project is licensed under the MIT License - see the LICENSE file for details.

Citation

If you use this tool in your research, please cite:

Pooria Daneshvar Kakhaki, Neda Ghohabi Esfahani, Stuart Akeson, Miten Jain, CurrentView: A tool for visualization and comparison of nanopore ionic current signals, Bioinformatics, 2026;, btag161, https://doi.org/10.1093/bioinformatics/btag161

https://academic.oup.com/bioinformatics/advance-article/doi/10.1093/bioinformatics/btag161/8651103

About

CurrentView: A tool for visualization and comparison of nanopore ionic current signals

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages