Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
056124d
added function for pairwise distance compared to reference
jonas-fuchs Mar 13, 2026
ea61e3d
planned simplot
jonas-fuchs Mar 13, 2026
178e56f
added simplot and new pairwise distance calculations
jonas-fuchs Mar 15, 2026
76a3a83
made refernce displaying id optional
jonas-fuchs Mar 15, 2026
cb34f4a
moved stuff
jonas-fuchs Mar 15, 2026
ab3cce3
finalized integration into app
jonas-fuchs Mar 17, 2026
45bce68
implemented data class for stats
jonas-fuchs Mar 18, 2026
0647056
implemented smaller helpers to alignment class
jonas-fuchs Mar 18, 2026
2c33483
finalized dunder methods intergration
jonas-fuchs Mar 19, 2026
0c2ef3c
added tests for output functions
jonas-fuchs Mar 19, 2026
56dccae
added orf class
jonas-fuchs Mar 19, 2026
8b9dc15
added Variant class
jonas-fuchs Mar 20, 2026
56445a3
added project specific copilot instructions
jonas-fuchs Mar 20, 2026
98b76f2
updated version
jonas-fuchs Mar 20, 2026
f374400
added test suite for drawing and populating axis for the different plots
jonas-fuchs Mar 20, 2026
d5b60b1
simplified variant collection building
jonas-fuchs Mar 20, 2026
df57b7e
introduced dataclass for length stats
jonas-fuchs Mar 20, 2026
14feabd
Update tests/test_export.py
jonas-fuchs Mar 21, 2026
a73ee96
Update msaexplorer/_data_classes.py
jonas-fuchs Mar 21, 2026
b59da24
finalized copilot review
jonas-fuchs Mar 21, 2026
efa4efd
fixed zoom bug
jonas-fuchs Mar 21, 2026
7355c5f
removed todo
jonas-fuchs Mar 22, 2026
6aa68bc
smaller cleanup
jonas-fuchs Mar 22, 2026
4238d6b
updated examples in init.py
jonas-fuchs Mar 22, 2026
b03f0a2
fixed logo bug
jonas-fuchs Mar 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Copilot Instructions for MSAexplorer

This file defines repository-specific standards for AI-assisted edits.
Use these rules for all code, tests, and documentation changes.

## 1) Core Principles

- Keep changes small, readable, and reviewable.
- Prefer simple and explicit code over clever abstractions.
- Avoid overengineering: introduce new classes/indirection only when they clearly improve maintainability.
- Keep behavior stable unless the task explicitly requests a breaking change.
- Preserve existing architecture and naming patterns.

## 2) Repository Structure and Interaction

This repository contains two Python packages with different roles:

- `msaexplorer/` (core library)
- Analysis and data model (`explore.py`, `_data_classes.py`)
- Plotting (`draw.py`)
- Export helpers (`export.py`)
- CLI entrypoint (`cli.py`)
- `app_src/` (Shiny app frontend)
- UI/server glue for interactive exploration (`shiny_user_interface.py`, `shiny_server.py`, `shiny_plots.py`)

How they interact:

- `app_src` should consume stable APIs from `msaexplorer`.
- `msaexplorer` must remain independently usable without the app.
- Feature work starts in `msaexplorer`; `app_src` is adapted afterwards if needed.
- Keep app-only concerns out of core modules.

## 3) Code Cleanliness Standards

- Use single quotes for normal strings: `'text'`.
- Use double quotes only when required (e.g., quote escaping readability) or for docstrings.
- Keep functions focused on one task; split long functions when logic becomes hard to scan.
- Prefer descriptive names over abbreviations.
- Remove dead code, unused imports, and outdated comments.
- Add comments only for non-obvious reasoning, not for trivial operations.
- Keep public APIs typed (input and return types) where practical.
- Reuse existing helpers/dataclasses before adding new structures.

## 4) Naming Conventions

- Functions/methods: `snake_case`
- Variables: `snake_case`
- Classes/dataclasses: `PascalCase`
- Constants: `UPPER_SNAKE_CASE`
- Internal helpers: prefix with `_` (module-private intent)
- Boolean names should read naturally (`include_ambig`, `show_legend`, `is_valid`)

## 5) Docstring Standards

Use concise, practical docstrings.

- Use triple double quotes for docstrings.
- First line: short summary sentence in imperative/present style.
- Describe parameters, return values, and raised exceptions when relevant.
- Keep docstrings short and precise; avoid tutorial-length blocks in function docstrings.
- Document every public class and public function.
- For internal/private helpers, add docstrings when behavior is not obvious.

Recommended structure:

```python
"""
Calculate pairwise distances against the current reference.

:param distance_type: Distance metric key.
:return: Pairwise distances container.
:raises ValueError: If the metric is unsupported.
"""
```

## 6) Documentation Guidelines (pdoc-oriented)

- API docs are generated primarily from docstrings (pdoc).
- Keep module/class/function docstrings accurate and synchronized with behavior.
- Prefer small executable examples over long narrative snippets.
- Any example added to docs (including package `__init__.py` examples) must be tested locally before integration.
- Do not document planned behavior as if already implemented.
- When refactoring signatures or return types, update related docstrings in the same change.

## 7) Testing Requirements

Every code change should be validated before merge.

Minimum expectations:

- Run targeted tests for edited modules.
- Add/adjust tests when behavior, output format, or API contracts change.
- Ensure export/plot/stat outputs are validated with deterministic assertions.

Typical commands:

```bash
pytest -q
```

For local source verification during development:

```bash
PYTHONPATH="/absolute/path/to/MSAexplorer" pytest -q
```

Guidance:

- Prefer explicit regression tests over broad smoke-only checks.
- If a bug is fixed, include a test that fails before and passes after.
- Keep fixtures minimal and representative.

## 8) Change Discipline

Before submitting changes:

- Confirm naming and style consistency.
- Confirm docstrings match implementation.
- Confirm tests pass.
- Confirm no unrelated edits were introduced.

If uncertain, prefer the simpler design.

26 changes: 12 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ options:
--version show program's version number and exit
```

- :white_check_mark: The app runs solely in your browser. No need to install anything, just might take a few seconds to load.
- :white_check_mark: Use the app offline (after loading it).
- :white_check_mark: Analyse alignments on your smartphone or tablet.
- :white_check_mark: Download alignment statistics (e.g. entropy, SNPs, coverage, consensus, ORFs and more).
- :white_check_mark: Annotate the alignment by additionally reading in gb, gff or bed files.
- :white_check_mark: Flexibility to customize plots and colors.
- :white_check_mark: Easily export the plot as pdf.
- :white_check_mark: Generate plots of the whole alignment as well as just parts of it.
- :white_check_mark: Publication ready figures with just a few clicks.
- The app runs solely in your browser. No need to install anything, just might take a few seconds to load.
- Use the app offline (after loading it).
- Analyse alignments on your smartphone or tablet.
- Download alignment statistics (e.g. entropy, SNPs, coverage, consensus, ORFs and more).
- Annotate the alignment by additionally reading in gb, gff or bed files.
- Flexibility to customize plots and colors.
- Easily export the plot as pdf.
- Generate plots of the whole alignment as well as just parts of it.
- Publication ready figures with just a few clicks.

| ![](readme_assets/upload_tab.png) | ![](readme_assets/plot_tab.png) | ![](readme_assets/plot2_tab.png) | ![](readme_assets/analysis_tab.png) |
|-----------------------------------|---------------------------------|----------------------------------|-------------------------------------|
Expand All @@ -112,11 +112,9 @@ shinylive export ./ site/ # you should now have a new 'site' folder with the ap
```

## Features of MSAexplorer as a python package ([full documentation](https://jonas-fuchs.github.io/MSAexplorer/docs/msaexplorer.html))
- :white_check_mark: Access MSAexplorer as a python package
- :white_check_mark: Seamlessly integrates with Biopython.
- :white_check_mark: Maximum flexibility for the plotting and analysis features while retaining minimal syntax.
- :white_check_mark: Integrates seamlessly with matplotlib.
- :white_check_mark: Minimal requirements.
- Access MSAexplorer as a python package
- Seamlessly integrates with Biopython and matplotlib.
- Maximum flexibility for the plotting and analysis features while retaining minimal syntax.

```python
### Minimal analysis example ###
Expand Down
25 changes: 21 additions & 4 deletions app_src/shiny_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def set_aln(aln, inputs):
# set the reference sequence
if 'reference' in inputs:
if inputs['reference'] == 'first':
aln.reference_id = list(aln.alignment.keys())[0]
aln.reference_id = next(iter(aln))
elif inputs['reference'] == 'consensus':
aln.reference_id = None
else:
Expand Down Expand Up @@ -44,7 +44,7 @@ def create_msa_plot(aln, ann, inputs, fig_size=None) -> plt.Figure | None:
plot_functions = []

# First plot
if inputs['stat_type'] not in ['Off', 'sequence logo']:
if inputs['stat_type'] not in ['Off', 'sequence logo', 'simplot-like similarity']:
height_ratios.append(inputs['plot_1_size'])
plot_functions.append(
lambda ax: draw.stat_plot(
Expand All @@ -66,6 +66,23 @@ def create_msa_plot(aln, ann, inputs, fig_size=None) -> plt.Figure | None:
color_scheme = inputs['logo_coloring']
)
)
elif inputs['stat_type'] == 'simplot-like similarity':
height_ratios.append(inputs['plot_1_size'])
# define window size and step size automatically
if aln.length > 100:
window_size = 50
else:
window_size = 2
window_step = int(max([window_size/10, 1]))
plot_functions.append(
lambda ax: draw.simplot(
aln, ax=ax, ref=aln.reference_id,
window_size=window_size,
step_size=window_step,
distance_calculation='ged' if aln.aln_type == 'AA' else 'k2p',
colors=None
)
)

# Second plot
if inputs['alignment_type'] != 'Off':
Expand Down Expand Up @@ -182,8 +199,8 @@ def create_analysis_custom_heatmap(aln, inputs):
else:
figure_size = int(inputs['dimensions']['width'] * 0.7)

matrix = aln.calc_pairwise_identity_matrix(inputs['additional_analysis_options_left'])
labels = [x.split(' ')[0] for x in list(aln.alignment.keys())]
matrix = aln.calc_pairwise_identity_matrix(inputs['additional_analysis_options_left']).distances
labels = [x.split(' ')[0] for x in list(aln)]

# generate hover text
hover_text = [
Expand Down
Loading
Loading