pax_global_header 0000666 0000000 0000000 00000000064 15244251443 0014516 g ustar 00root root 0000000 0000000 52 comment=5c38985d0de5a81167e6e8d8a564874b73f39cb1
DataLab-Platform-SigimaX-0182bf4/ 0000775 0000000 0000000 00000000000 15244251443 0016457 5 ustar 00root root 0000000 0000000 DataLab-Platform-SigimaX-0182bf4/.coveragerc 0000664 0000000 0000000 00000001105 15244251443 0020575 0 ustar 00root root 0000000 0000000 [run]
#--- Ignore this warning because the process isolation feature
#--- causes coverage to report 0% coverage when no computation is performed
#--- in the isolated process during the session.
disable_warnings = no-data-collected
parallel = True
concurrency = multiprocessing,thread
omit =
*/sigimax/tests/*
*/guidata/*
#--- Workaround for certain builds of python-opencv package:
./config-3.py
./config.py
#---
[report]
exclude_also =
def __repr__
if __name__ == .__main__.:
if TYPE_CHECKING:
if DEBUG[\s]*:
if self.__debug[\s]*:
DataLab-Platform-SigimaX-0182bf4/.env.template 0000664 0000000 0000000 00000000513 15244251443 0021061 0 ustar 00root root 0000000 0000000 # Python interpreter (explicit path, e.g. WinPython). Auto-detected if empty.
PYTHON=
# WinPython base directory (legacy, prefer PYTHON instead)
# WINPYDIRBASE=
# Virtual environment directory (e.g. .venv39). Auto-discovered if empty.
VENV_DIR=
# Python path for development (sibling packages)
PYTHONPATH=.
# Locale (e.g. fr)
LANG= DataLab-Platform-SigimaX-0182bf4/.github/ 0000775 0000000 0000000 00000000000 15244251443 0020017 5 ustar 00root root 0000000 0000000 DataLab-Platform-SigimaX-0182bf4/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15244251443 0022202 5 ustar 00root root 0000000 0000000 DataLab-Platform-SigimaX-0182bf4/.github/ISSUE_TEMPLATE/bug_report.md 0000664 0000000 0000000 00000001263 15244251443 0024676 0 ustar 00root root 0000000 0000000 ---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Installation information**
Describe how you installed SigimaX (e.g., via pip, conda, or from source) and provide the version of SigimaX you are using.
**Additional context**
Add any other context about the problem here.
DataLab-Platform-SigimaX-0182bf4/.github/ISSUE_TEMPLATE/doc_request.md 0000664 0000000 0000000 00000001141 15244251443 0025036 0 ustar 00root root 0000000 0000000 ---
name: Documentation request
about: Ask for documentation about a specific topic
title: ''
labels: documentation
assignees: ''
---
**Is your documentation request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the topic you would like to be covered**
A clear and concise description of what you want to be documented.
**Describe the nature of the documentation you would like to see**
Tutorial, reference, etc.
**Additional context**
Add any other context or screenshots about the feature request here.
DataLab-Platform-SigimaX-0182bf4/.github/ISSUE_TEMPLATE/feature_request.md 0000664 0000000 0000000 00000001134 15244251443 0025726 0 ustar 00root root 0000000 0000000 ---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
DataLab-Platform-SigimaX-0182bf4/.github/ISSUE_TEMPLATE/tutorial_request.md 0000664 0000000 0000000 00000001457 15244251443 0026146 0 ustar 00root root 0000000 0000000 ---
name: Tutorial request
about: Ask for a tutorial on a specific topic
title: ''
labels: documentation
assignees: ''
---
**Describe the context and technical field of the tutorial you would like to see**
A clear and concise description of your technical field, and of the specific application.
**Describe the topic you would like to be covered**
A clear and concise description of what you want to be documented.
**Describe the features you would like to see in the tutorial**
A clear and concise description of the features you would like to see in the tutorial.
**Additional context**
Add any other context or screenshots about the feature request here.
_Please attach an example data set, if possible.
And please confirm that you are willing to share this data set under the terms of DataLab's license._
DataLab-Platform-SigimaX-0182bf4/.github/copilot-instructions.md 0000664 0000000 0000000 00000030000 15244251443 0024545 0 ustar 00root root 0000000 0000000 # SigimaX AI Coding Agent Instructions
## Project Overview
**SigimaX** is a reusable GUI application framework extracted from DataLab. It provides the generic "application skeleton" that any scientific computing Qt application can build upon by subclassing its main window and configuration system.
### Position in the Stack
```
End-user apps (DataLab, custom scientific apps)
↓ subclass / configure
SigimaX � THIS PROJECT (framework layer)
↓ depends on
Sigima (computation) + PlotPy + guidata + PythonQwt
↓
NumPy / SciPy / Qt
```
### Technology Stack
- **Python**: 3.9+ (`from __future__ import annotations`)
- **Core**: guidata (≥3.13.4), PlotPy (≥2.8.2), Sigima (≥1.1.0), psutil (≥5.7)
- **GUI**: Qt via QtPy (PyQt5/PyQt6/PySide6)
- **Testing**: pytest
- **Linting**: Ruff (preferred), Pylint
### Architecture
```
sigimax/
├── app.py # Application launcher (create / run)
├── config.py # Configuration system (SigimaXOptions, CONF singleton)
├── env.py # ExecEnv runtime environment (verbosity, unattended)
├── mainwindow.py # SGMXMainWindow (generic main window)
├── widgets/ # Reusable Qt widgets
│ ├── plotdock.py # DockablePlotWidget
│ ├── splashscreen.py # Configurable splash screen
│ ├── h5browser.py # HDF5 file browser
│ ├── logviewer.py # Log viewer dialog
│ ├── status.py # Status bar widgets (memory, console)
│ ├── warningerror.py # Warning/error message box
│ ├── wizard.py # Multi-page wizard dialog
│ ├── fitdialog.py # Curve fitting dialogs
│ ├── filedialog.py # File dialog with multi-selection
│ ├── fileviewer.py # Read-only file viewer
│ ├── imagebackground.py # Image background selection
│ ├── signalbaseline.py # Signal baseline selection
│ ├── signalcursor.py # Signal cursor selection
│ ├── signaldeltax.py # Signal delta-X measurement
│ └── signalpeak.py # Signal peak detection
├── h5/ # HDF5 I/O (read/write/import)
├── adapters_plotpy/ # Converters between PlotPy/guidata and Sigima objects
├── utils/ # Qt helpers, config dir resolution
├── data/ # Icons, resources
├── locale/ # Translations (EN, FR)
└── tests/ # pytest suite
```
## Development Workflows
### Running Commands
**ALWAYS use `scripts/run_with_env.py`** to load `.env` before running Python commands:
```powershell
# ✅ CORRECT
python scripts/run_with_env.py python -m pytest
# � WRONG - Misses local PYTHONPATH
python -m pytest
```
### Testing
```powershell
# Run all tests
python scripts/run_with_env.py python -m pytest --ff
# Run specific test
python scripts/run_with_env.py python -m pytest sigimax/tests/derivated_app_test.py
# Show Qt windows during tests (default is offscreen)
python scripts/run_with_env.py python -m pytest --show-windows
```
**Pytest Configuration** (`conftest.py`):
- `execenv.unattended = True` (no GUI interaction by default)
- `set_validation_mode(ValidationMode.STRICT)` for tests
- `QT_QPA_PLATFORM=offscreen` unless `--show-windows` is passed
- Custom marker: `@pytest.mark.validation`
### Linting and Formatting
```powershell
# Ruff (preferred)
python scripts/run_with_env.py python -m ruff format
python scripts/run_with_env.py python -m ruff check --fix
# Pylint
python scripts/run_with_env.py python -m pylint sigimax \
--disable=duplicate-code,fixme,too-many-arguments, \
too-many-branches,too-many-instance-attributes,too-many-lines, \
too-many-locals,too-many-public-methods,too-many-statements
```
### Translations
```powershell
# Scan and update .po files
python scripts/run_with_env.py python -m guidata.utils.translations scan \
--name sigimax --directory . --copyright-holder "DataLab Platform Developers" \
--languages fr
# Compile .mo files
python scripts/run_with_env.py python -m guidata.utils.translations compile \
--name sigimax --directory .
```
## Core Patterns
### 1. The Derivation Pattern (Subclassing)
SigimaX is designed around **subclassing**. Derived applications follow three steps:
**Step 1 — Subclass `SigimaXOptions`** for app-specific configuration:
```python
from sigimax.config import EnumOptionField, SigimaXOptions, TypedOptionField
class MyAppOptions(SigimaXOptions):
ENV_VAR = "MYAPP_OPTIONS_JSON"
APP_NAME = "MyApp"
def __init__(self):
super().__init__()
self.app_name.set("MyApp")
self.greeting = TypedOptionField(
self,
"greeting",
default="Hello!",
expected_type=str,
description="Startup message",
)
self.unit_system = EnumOptionField(
self,
"unit_system",
default="metric",
choices=["metric", "imperial"],
description="Default units",
)
```
**Step 2 — Subclass `SGMXMainWindow`** for custom UI:
```python
from sigimax.mainwindow import SGMXMainWindow
from sigimax.config import CONF as Conf
class MyAppMainWindow(SGMXMainWindow):
def __init__(self, console=None, hide_on_close=False):
Conf.app_name.set("MyApp")
super().__init__(console=console, hide_on_close=hide_on_close)
self._add_custom_menus()
self._add_custom_docks()
```
**Step 3 — Launch with `sigimax.app.run()`**:
```python
from sigimax.app import run
from sigimax.widgets.splashscreen import SplashScreenConfig
run(
window_class=MyAppMainWindow,
splash_config=SplashScreenConfig(
image_path="myapp/data/splash.png",
app_name="MyApp",
app_version="1.0.0",
),
)
```
### 2. Configuration System
The configuration system follows Sigima's `OptionField` pattern extended for GUI apps:
```python
from sigimax.config import CONF as Conf
# Get/set options
colormap = Conf.ima_def_colormap.get()
Conf.ima_def_colormap.set("gray")
# Context manager for temporary overrides
with Conf.fft_shift_enabled.context(False):
# FFT shift disabled in this block
...
# JSON persistence
Conf.save() # Save to config file
Conf.load() # Load from config file
```
**Custom option field types**:
- `TypedOptionField` — type-checked (int, str, bool, float)
- `EnumOptionField` — constrained to a set of choices
- `TupleOptionField` — fixed-length tuples
- `ImageIOOptionField` — image I/O settings (inherited from Sigima)
### 3. Widgets Package
Common widgets are re-exported from `sigimax.widgets` for convenience:
```python
# Tier 1 — direct import from package
from sigimax.widgets import H5Browser, Wizard, LogViewerWindow, SplashScreenConfig
# Tier 2 — specialized dialogs via submodule
from sigimax.widgets.fitdialog import gaussian_fit
from sigimax.widgets.signalpeak import SignalPeakDetectionDialog
```
### 4. DockablePlotWidget
Embeds PlotPy plots in dock widgets:
```python
from sigimax.widgets.plotdock import DockablePlotWidget
dock = DockablePlotWidget(self, plot_type=PlotType.CURVE, title="My Plot")
self.addDockWidget(Qt.RightDockWidgetArea, dock)
```
### 5. HDF5 Workspace
The main window provides built-in HDF5 workspace management:
- `open_h5_files()` — open HDF5 files
- `save_to_h5_file()` — save workspace
- `browse_h5_files()` — browse HDF5 files with `H5BrowserDialog`
### 6. Application Launcher
```python
from sigimax.app import create, run
# create() — instantiate window with splash, return it (for embedding)
window = create(window_class=MyWindow, splash=True, console=True)
# run() — create() + enter Qt event loop (for standalone apps)
run(window_class=MyWindow, splash_config=config)
```
## What SigimaX Provides vs What Stays in DataLab
| **In SigimaX** | **Stays in DataLab** |
|---|---|
| Configuration system (`config.py`) | Signal/Image panels, processors |
| Generic main window (`mainwindow.py`) | Action handler, plugin system |
| Dockable plot widgets (`widgets/plotdock.py`) | Remote control (XML-RPC, Web API) |
| HDF5 I/O + browser (`h5/`, `widgets/h5browser.py`) | Macro editor, new-object dialogs |
| Scientific dialogs (fit, baseline, peak, cursor…) | DataLab-specific UI and processing |
| Log viewer, status bar, splash screen, wizard | Object model, plot handler |
| PlotPy adapters (`adapters_plotpy/`) | Processor registration pattern |
| Environment/exec utilities (`env.py`) | Tour/tutorial features |
## Coding Conventions
### Type Annotations
```python
from __future__ import annotations
```
Always use `from __future__ import annotations` for forward references.
### Qt Imports
Use QtPy for Qt binding abstraction:
```python
from qtpy.QtCore import Qt, QSize
from qtpy.QtGui import QPen, QBrush, QColor
from qtpy.QtWidgets import QWidget
```
### Imports
**Order**: Standard library → Third-party → SigimaX
```python
from __future__ import annotations
import os
from typing import TYPE_CHECKING
import numpy as np
from guidata.qthelpers import create_action
from sigimax.config import CONF as Conf
from sigimax.config import _
from sigimax.mainwindow import SGMXMainWindow
if TYPE_CHECKING:
from sigima.objects import SignalObj
```
### Module Exports
**Always define `__all__`** in every module:
```python
__all__ = [
"MyClass",
"my_function",
]
```
### Docstrings
Google-style with Args/Returns:
```python
def my_function(x: np.ndarray, param: int) -> np.ndarray:
"""One-line summary.
Longer description if needed.
Args:
x: Input array description
param: Parameter description, with long description that
continues on next line.
Returns:
Output array description
"""
```
For continued lines in enumerations (args, returns), indent subsequent lines by 1 space.
### Internationalization
Wrap UI strings with `_()`:
```python
from sigimax.config import _
menu_title = _("Processing")
action_text = _("Open HDF5 files")
```
### Naming
- **Functions**: `snake_case` (e.g., `get_log_filenames`)
- **Classes**: `PascalCase` (e.g., `SGMXMainWindow`)
- **Constants**: `UPPER_SNAKE_CASE` (e.g., `MOD_NAME`, `DEBUG`)
- **Private methods**: `_snake_case` or `__snake_case`
## Key Files Reference
| File | Purpose |
|------|---------|
| `sigimax/__init__.py` | Package metadata (`__version__`, URLs) |
| `sigimax/app.py` | Application launcher (`create()`, `run()`) |
| `sigimax/config.py` | Configuration system (`SigimaXOptions`, `CONF`) |
| `sigimax/env.py` | Runtime environment (`ExecEnv`, `execenv` singleton) |
| `sigimax/mainwindow.py` | `SGMXMainWindow` — generic main window |
| `sigimax/widgets/plotdock.py` | `DockablePlotWidget` — embeddable plot docks |
| `sigimax/widgets/__init__.py` | Convenience re-exports of common widgets |
| `sigimax/widgets/splashscreen.py` | `SplashScreenConfig`, `SigimaXSplashScreen` |
| `sigimax/widgets/h5browser.py` | HDF5 browser widget and dialog |
| `sigimax/h5/__init__.py` | HDF5 I/O handler |
| `sigimax/adapters_plotpy/__init__.py` | PlotPy/Sigima object converters |
| `sigimax/tests/derivated_app_test.py` | Reference example of derived application |
| `scripts/run_with_env.py` | Environment loader (loads `.env`) |
| `.env` | Local PYTHONPATH for development |
## VS Code Tasks
`.vscode/tasks.json` provides shortcuts:
- **🧽 Ruff Formatter**: Format code
- **🔦 Ruff Linter**: Lint with auto-fix
- **🧽🔦 Ruff**: Format + lint (sequential)
- **🔦 Pylint**: Pylint checks
- **🚀 Pytest**: Run tests (`--ff` flag)
- **📚 Compile translations**: Build .mo files
- **🔎 Scan translations**: Update .po files
## Related Projects
- **Sigima**: Headless computation library (sibling, upstream)
- **guidata**: Dataset/parameter framework (upstream)
- **PlotPy**: Interactive plotting (upstream)
- **PythonQwt**: Low-level Qt plotting (upstream)
- **DataLab**: Primary downstream application using SigimaX
---
**Remember**: Always use `scripts/run_with_env.py` for Python commands, wrap UI strings with `_()`, define `__all__` in every module, and follow the subclassing pattern for derived applications.
DataLab-Platform-SigimaX-0182bf4/.github/workflows/ 0000775 0000000 0000000 00000000000 15244251443 0022054 5 ustar 00root root 0000000 0000000 DataLab-Platform-SigimaX-0182bf4/.github/workflows/_build.yml 0000664 0000000 0000000 00000016164 15244251443 0024045 0 ustar 00root root 0000000 0000000 # ============================================================================
# Reusable build workflow for SigimaX release artifacts.
#
# Decomposed into modular jobs so each artifact is uploaded independently
# and any individual job can be re-run from the GitHub UI on failure:
#
# preflight - tag/version check, exports `version` output
# compile-translations - UI + docs .mo files (ubuntu)
# build-python-dists - sdist + wheel (ubuntu)
#
# Each job uploads its own artifact (see "Artifacts produced" below) so
# they can be downloaded individually from the workflow run page even when
# the workflow as a whole fails.
#
# Artifacts produced:
# translations-mo compiled .mo files (sigimax/locale/**, doc/locale/**)
# python-dists *.whl, *.tar.gz
# ============================================================================
name: _build (reusable)
on:
workflow_call:
inputs:
ref:
description: "Git ref to build (default: github.ref)"
type: string
required: false
default: ""
skip-tag-check:
description: "Skip the tag vs __version__ consistency check"
type: boolean
required: false
default: false
skip-tag-branch-check:
description: "Skip the 'tag is on main' check"
type: boolean
required: false
default: false
artifact-retention-days:
description: "Retention period for uploaded artifacts (days)"
type: number
required: false
default: 14
python-version:
description: "Python version used to build the release artifacts"
type: string
required: false
default: "3.11"
outputs:
version:
description: "Version that was built (without leading v)"
value: ${{ jobs.preflight.outputs.version }}
permissions:
contents: read
jobs:
# ---------------------------------------------------------------------------
# 0. Preflight: derive version from tag or __version__, optional checks.
# ---------------------------------------------------------------------------
preflight:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
- name: Verify tag is on main branch
if: ${{ !inputs.skip-tag-branch-check && startsWith(github.ref, 'refs/tags/') }}
run: |
git fetch origin main --depth=200
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
echo "::error::Tag ${GITHUB_REF_NAME} (commit $GITHUB_SHA) is not reachable from origin/main."
exit 1
fi
echo "Tag commit is on main branch ✔"
- name: Verify tag matches sigimax.__version__ and export version
id: version
run: |
if [ "${{ inputs.skip-tag-check }}" = "true" ] || [ "${GITHUB_REF_TYPE}" != "tag" ]; then
VERSION=$(python -c "import re; t=open('sigimax/_metadata.py').read(); print(re.search(r'__version__\s*=\s*\"([^\"]+)\"', t).group(1))")
echo "Using sigimax.__version__=$VERSION (no tag check)"
else
python scripts/ci_release_helpers.py check-tag "$GITHUB_REF_NAME"
VERSION="${GITHUB_REF_NAME#v}"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
# ---------------------------------------------------------------------------
# 1. Compile UI + documentation translations.
# ---------------------------------------------------------------------------
compile-translations:
needs: preflight
runs-on: ubuntu-latest
env:
DISPLAY: ":99.0"
QT_QPA_PLATFORM: offscreen
UNATTENDED: "1"
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
cache: pip
# `sphinx -b gettext` parses doc/conf.py which transitively imports
# `sigimax.*` -> `qtpy`. Without a Qt binding installed `qtpy` raises
# `QtBindingsNotFoundError` and the build aborts. Installing PyQt5
# (no graphical session required thanks to QT_QPA_PLATFORM=offscreen)
# is enough to let imports succeed.
- name: Install system dependencies (Qt offscreen)
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade PythonQwt guidata PlotPy Sigima
python -m pip install .[doc,qt]
- name: Compile docs gettext + sphinx_intl + UI .mo
run: |
python -m sphinx build doc build/gettext -b gettext -W
python -m sphinx_intl build -d doc/locale
python -m guidata.utils.translations compile --name sigimax --directory .
- name: List produced .mo files
run: find sigimax/locale doc/locale -name '*.mo' | sort
- name: Upload compiled translations
uses: actions/upload-artifact@v4
with:
name: translations-mo
path: |
sigimax/locale/**/*.mo
doc/locale/**/*.mo
retention-days: ${{ inputs.artifact-retention-days }}
# ---------------------------------------------------------------------------
# 2. Build sdist + wheel (both embed the compiled .mo files).
# ---------------------------------------------------------------------------
build-python-dists:
needs: [preflight, compile-translations]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
cache: pip
- name: Install build tool
run: python -m pip install --upgrade pip build
- name: Download compiled translations
uses: actions/download-artifact@v4
with:
name: translations-mo
path: .
- name: Build sdist + wheel
run: |
python -m build --sdist
python -m build --wheel
ls -lh dist/
- name: Sanity-check that wheel embeds compiled translations
run: |
WHL=$(ls dist/*.whl | head -n1)
echo "Inspecting $WHL"
python -m zipfile -l "$WHL" | grep -E 'sigimax/locale/.*\.mo' \
|| { echo "::error::Compiled translations missing from wheel"; exit 1; }
- name: Upload Python distributions
uses: actions/upload-artifact@v4
with:
name: python-dists
path: dist/*
retention-days: ${{ inputs.artifact-retention-days }}
DataLab-Platform-SigimaX-0182bf4/.github/workflows/release.yml 0000664 0000000 0000000 00000011430 15244251443 0024216 0 ustar 00root root 0000000 0000000 # ============================================================================
# Build and publish a SigimaX release.
#
# The build itself is delegated to the reusable `_build.yml` workflow
# (modular, one artifact per stage). This file only adds the test gate and
# the publication jobs: PyPI Trusted Publishing + draft GitHub Release.
#
# Documentation is NOT deployed here: SigimaX docs (HTML + PDF) are built
# and hosted by Read the Docs, which rebuilds automatically on push/tag
# through its own webhook (see `.readthedocs.yaml`).
#
# Triggers:
# * push of a tag matching vX.Y.Z (no pre-release suffix) on `main`.
#
# Prerequisites (one-time, off-CI):
# - Configure PyPI Trusted Publishing for `sigimax` -> environment `pypi`.
# ============================================================================
name: Release
on:
push:
tags:
- "v[0-9]*.[0-9]*.[0-9]*"
- "!v*-*" # exclude pre-release tags
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
# ---------------------------------------------------------------------------
# Test gate: the release is only built if both Qt bindings pass.
# ---------------------------------------------------------------------------
test_pyqt5:
uses: ./.github/workflows/test_pyqt5.yml
test_pyqt6:
uses: ./.github/workflows/test_pyqt6.yml
# ---------------------------------------------------------------------------
# Modular build (translations / dists) via reusable workflow.
# ---------------------------------------------------------------------------
build:
needs: [test_pyqt5, test_pyqt6]
uses: ./.github/workflows/_build.yml
with:
artifact-retention-days: 30
# ---------------------------------------------------------------------------
# Publish sdist + wheel to PyPI via Trusted Publishing (OIDC).
# ---------------------------------------------------------------------------
publish-pypi:
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/sigimax
permissions:
id-token: write
steps:
- name: Download Python distributions
uses: actions/download-artifact@v4
with:
name: python-dists
path: dist
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
# ---------------------------------------------------------------------------
# Create a draft GitHub Release with all public artifacts.
# ---------------------------------------------------------------------------
github-release:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write # required by attest-build-provenance (OIDC)
attestations: write # required by attest-build-provenance
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Download Python distributions
uses: actions/download-artifact@v4
with:
name: python-dists
path: assets/dists
- name: Generate SHA256SUMS
# Single checksums file covering every artifact published in the
# release. Users verify with: `sha256sum -c SHA256SUMS`.
run: |
cd assets
# Published release assets are flat, so SHA256SUMS must reference bare
# filenames. Run sha256sum from each file's own directory so the
# checksum line contains the basename (not dists/…).
find dists -type f \( -name '*.whl' -o -name '*.tar.gz' \) \
-printf '%p\n' | sort | while read -r f; do
( cd "$(dirname "$f")" && sha256sum "$(basename "$f")" )
done > SHA256SUMS
echo "--- SHA256SUMS ---"
cat SHA256SUMS
- name: Attest build provenance
# Produces a Sigstore-backed attestation linking each artifact to
# this exact workflow run. Verifiable with `gh attestation verify`.
uses: actions/attest-build-provenance@v2
with:
subject-path: |
assets/dists/*.whl
assets/dists/*.tar.gz
- name: Extract release notes
run: |
python scripts/ci_release_helpers.py release-notes \
"$GITHUB_REF_NAME" -o release-notes.md
echo "--- release notes preview ---"
head -n 20 release-notes.md
- name: Create draft GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: SigimaX ${{ github.ref_name }}
body_path: release-notes.md
draft: true
fail_on_unmatched_files: true
files: |
assets/dists/*.whl
assets/dists/*.tar.gz
assets/SHA256SUMS
DataLab-Platform-SigimaX-0182bf4/.github/workflows/test_pyqt5.yml 0000664 0000000 0000000 00000016472 15244251443 0024732 0 ustar 00root root 0000000 0000000 # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
# Inspired from https://pytest-qt.readthedocs.io/en/latest/troubleshooting.html#github-actions
name: Install and Test on Ubuntu (latest) with PyQt5
on:
push:
branches: [ "main", "develop", "release" ]
pull_request:
branches: [ "main", "develop", "release" ]
workflow_call:
workflow_dispatch:
inputs:
job_to_run:
description: 'Which job to run'
required: true
type: choice
options:
- 'all'
- 'build'
- 'build_latest'
default: 'all'
schedule:
# Only the "build_latest" job runs on schedule (see execution conditions below)
- cron: "0 5 * * 1"
jobs:
build:
if: ${{ (github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'release') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.job_to_run == 'all' || github.event.inputs.job_to_run == 'build')) }}
env:
DISPLAY: ':99.0'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.14"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 x11-utils
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1920x1200x24 -ac +extension GLX
python -m pip install --upgrade pip
python -m pip install ruff pytest
pip install PyQt5
if [ "${{ github.ref_name }}" = "develop" ]; then
# Clone and install development versions of key dependencies with editable install
cd ..
git clone --depth 1 https://github.com/PlotPyStack/PythonQwt.git
git clone --depth 1 --branch develop https://github.com/PlotPyStack/guidata.git
git clone --depth 1 --branch develop https://github.com/PlotPyStack/plotpy.git
git clone --depth 1 --branch develop https://github.com/DataLab-Platform/sigima.git
cd SigimaX
pip install -e ../guidata
pip install -e ../PythonQwt
pip install -e ../plotpy
pip install -e ../sigima
# Install tomli for TOML parsing (safe if already present)
pip install tomli
# Extract dependencies and save to file, then install
python -c "import tomli; f=open('pyproject.toml','rb'); data=tomli.load(f); deps=[d for d in data['project']['dependencies'] if not any(p in d for p in ['guidata','PlotPy','Sigima'])]; open('deps.txt','w').write('\n'.join(deps))"
pip install -r deps.txt
# Install SigimaX without dependencies
pip install --no-deps .
elif [ "${{ github.ref_name }}" = "release" ]; then
# Clone dependencies from release branches (with fallback to main/master)
cd ..
# Try cloning PythonQwt from main or master
git clone --depth 1 https://github.com/PlotPyStack/PythonQwt.git || git clone --depth 1 --branch master https://github.com/PlotPyStack/PythonQwt.git
# Try cloning guidata from release, fallback to main or master
git clone --depth 1 --branch release https://github.com/PlotPyStack/guidata.git || git clone --depth 1 https://github.com/PlotPyStack/guidata.git || git clone --depth 1 --branch master https://github.com/PlotPyStack/guidata.git
# Try cloning plotpy from release, fallback to main or master
git clone --depth 1 --branch release https://github.com/PlotPyStack/plotpy.git || git clone --depth 1 https://github.com/PlotPyStack/plotpy.git || git clone --depth 1 --branch master https://github.com/PlotPyStack/plotpy.git
# Try cloning sigima from release, fallback to main
git clone --depth 1 --branch release https://github.com/DataLab-Platform/sigima.git || git clone --depth 1 https://github.com/DataLab-Platform/sigima.git
cd SigimaX
pip install -e ../guidata
pip install -e ../PythonQwt
pip install -e ../plotpy
pip install -e ../sigima
# Install tomli for TOML parsing (safe if already present)
pip install tomli
# Extract dependencies and save to file, then install
python -c "import tomli; f=open('pyproject.toml','rb'); data=tomli.load(f); deps=[d for d in data['project']['dependencies'] if not any(p in d for p in ['guidata','PlotPy','Sigima'])]; open('deps.txt','w').write('\n'.join(deps))"
pip install -r deps.txt
# Install SigimaX without dependencies
pip install --no-deps .
else
# Install from PyPI normally for main branch
pip install .
fi
- name: Lint with Ruff
run: ruff check --output-format=github sigimax
- name: Test with pytest
run: pytest -v --tb=long
build_latest:
if: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (github.event.inputs.job_to_run == 'all' || github.event.inputs.job_to_run == 'build_latest')) }}
env:
DISPLAY: ':99.0'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Install dependencies (latest)
run: |
set -euxo pipefail
sudo apt-get update
sudo apt-get install -y \
libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 x11-utils
/sbin/start-stop-daemon --start --quiet \
--pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background \
--exec /usr/bin/Xvfb -- :99 -screen 0 1920x1200x24 -ac +extension GLX
python -m pip install --upgrade pip
python -m pip install ruff pytest
python -m pip install PyQt5
# Clone and install Sigima from the same branch as SigimaX
cd ..
git clone --depth 1 --branch ${{ github.ref_name }} https://github.com/DataLab-Platform/sigima.git || git clone --depth 1 https://github.com/DataLab-Platform/sigima.git
cd SigimaX
# Install SigimaX itself, but do NOT install its pinned deps
python -m pip install -e . --no-deps
# Install Sigima from local clone
python -m pip install -e ../sigima
# Extract dependency names from pyproject.toml (excluding Sigima) and install latest versions
python -m pip install -U --upgrade-strategy eager $(python -c "import tomllib, re; print(' '.join(re.sub(r'[\[\]<>=!~,.\s].*$', '', d).strip() for d in tomllib.loads(open('pyproject.toml', 'rb').read().decode())['project']['dependencies'] if 'Sigima' not in d))")
- name: Lint with Ruff (latest)
run: ruff check --output-format=github sigimax
- name: Test with pytest (latest)
run: pytest -v --tb=long DataLab-Platform-SigimaX-0182bf4/.github/workflows/test_pyqt6.yml 0000664 0000000 0000000 00000016512 15244251443 0024726 0 ustar 00root root 0000000 0000000 # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
# Inspired from https://pytest-qt.readthedocs.io/en/latest/troubleshooting.html#github-actions
name: Install and Test on Ubuntu (latest) with PyQt6
on:
push:
branches: [ "main", "develop", "release" ]
pull_request:
branches: [ "main", "develop", "release" ]
workflow_call:
workflow_dispatch:
inputs:
job_to_run:
description: 'Which job to run'
required: true
type: choice
options:
- 'all'
- 'build'
- 'build_latest'
default: 'all'
schedule:
# Only the "build_latest" job runs on schedule (see execution conditions below)
- cron: "0 5 * * 1"
jobs:
build:
if: ${{ (github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'release') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.job_to_run == 'all' || github.event.inputs.job_to_run == 'build')) }}
env:
DISPLAY: ':99.0'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.14"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 x11-utils libegl1
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1920x1200x24 -ac +extension GLX
python -m pip install --upgrade pip
python -m pip install ruff pytest
pip install PyQt6
if [ "${{ github.ref_name }}" = "develop" ]; then
# Clone and install development versions of key dependencies with editable install
cd ..
git clone --depth 1 https://github.com/PlotPyStack/PythonQwt.git
git clone --depth 1 --branch develop https://github.com/PlotPyStack/guidata.git
git clone --depth 1 --branch develop https://github.com/PlotPyStack/plotpy.git
git clone --depth 1 --branch develop https://github.com/DataLab-Platform/sigima.git
cd SigimaX
pip install -e ../guidata
pip install -e ../PythonQwt
pip install -e ../plotpy
pip install -e ../sigima
# Install tomli for TOML parsing (safe if already present)
pip install tomli
# Extract dependencies and save to file, then install
python -c "import tomli; f=open('pyproject.toml','rb'); data=tomli.load(f); deps=[d for d in data['project']['dependencies'] if not any(p in d for p in ['guidata','PlotPy','Sigima'])]; open('deps.txt','w').write('\n'.join(deps))"
pip install -r deps.txt
# Install SigimaX without dependencies
pip install --no-deps .
elif [ "${{ github.ref_name }}" = "release" ]; then
# Clone dependencies from release branches (with fallback to main/master)
cd ..
# Try cloning PythonQwt from main or master
git clone --depth 1 https://github.com/PlotPyStack/PythonQwt.git || git clone --depth 1 --branch master https://github.com/PlotPyStack/PythonQwt.git
# Try cloning guidata from release, fallback to main or master
git clone --depth 1 --branch release https://github.com/PlotPyStack/guidata.git || git clone --depth 1 https://github.com/PlotPyStack/guidata.git || git clone --depth 1 --branch master https://github.com/PlotPyStack/guidata.git
# Try cloning plotpy from release, fallback to main or master
git clone --depth 1 --branch release https://github.com/PlotPyStack/plotpy.git || git clone --depth 1 https://github.com/PlotPyStack/plotpy.git || git clone --depth 1 --branch master https://github.com/PlotPyStack/plotpy.git
# Try cloning sigima from release, fallback to main
git clone --depth 1 --branch release https://github.com/DataLab-Platform/sigima.git || git clone --depth 1 https://github.com/DataLab-Platform/sigima.git
cd SigimaX
pip install -e ../guidata
pip install -e ../PythonQwt
pip install -e ../plotpy
pip install -e ../sigima
# Install tomli for TOML parsing (safe if already present)
pip install tomli
# Extract dependencies and save to file, then install
python -c "import tomli; f=open('pyproject.toml','rb'); data=tomli.load(f); deps=[d for d in data['project']['dependencies'] if not any(p in d for p in ['guidata','PlotPy','Sigima'])]; open('deps.txt','w').write('\n'.join(deps))"
pip install -r deps.txt
# Install SigimaX without dependencies
pip install --no-deps .
else
# Install from PyPI normally for main branch
pip install .
fi
- name: Lint with Ruff
run: ruff check --output-format=github sigimax
- name: Test with pytest
run: pytest -v --tb=long
build_latest:
if: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (github.event.inputs.job_to_run == 'all' || github.event.inputs.job_to_run == 'build_latest')) }}
env:
DISPLAY: ':99.0'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Install dependencies (latest)
run: |
set -euxo pipefail
sudo apt-get update
sudo apt-get install -y \
libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 x11-utils libegl1
/sbin/start-stop-daemon --start --quiet \
--pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background \
--exec /usr/bin/Xvfb -- :99 -screen 0 1920x1200x24 -ac +extension GLX
python -m pip install --upgrade pip
python -m pip install ruff pytest
python -m pip install PyQt6
# Clone and install Sigima from the same branch as SigimaX
cd ..
git clone --depth 1 --branch ${{ github.ref_name }} https://github.com/DataLab-Platform/sigima.git || git clone --depth 1 https://github.com/DataLab-Platform/sigima.git
cd SigimaX
# Install SigimaX itself, but do NOT install its pinned deps
python -m pip install -e . --no-deps
# Install Sigima from local clone
python -m pip install -e ../sigima
# Extract dependency names from pyproject.toml (excluding Sigima) and install latest versions
python -m pip install -U --upgrade-strategy eager $(python -c "import tomllib, re; print(' '.join(re.sub(r'[\[\]<>=!~,.\s].*$', '', d).strip() for d in tomllib.loads(open('pyproject.toml', 'rb').read().decode())['project']['dependencies'] if 'Sigima' not in d))")
- name: Lint with Ruff (latest)
run: ruff check --output-format=github sigimax
- name: Test with pytest (latest)
run: pytest -v --tb=long DataLab-Platform-SigimaX-0182bf4/.gitignore 0000664 0000000 0000000 00000002366 15244251443 0020456 0 ustar 00root root 0000000 0000000 winpython.env
.spyderproject
doc.zip
Thumbs.db
doctmp/
.vs/
*.pyproj
*.sln
releases/
.doctrees/
doc/install_requires.txt
doc/extras_require-dev.txt
doc/extras_require-doc.txt
*.bak
/tutorialnotes*.md
doc/locale/pot/_sphinx_design_static/
doc/contributing/changelog.md
# Visual Studio Code
.venv
.env
.venv*
.*venv*
#AI instructions
*.ai
*.ai*
# Created by https://www.gitignore.io/api/python
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
_build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
# *.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
cdl/data/doc/
doc/auto_examples/
doc/sg_execution_times.rst
# PyBuilder
target/
# Files generated by tests
scenario_*.h5
# Image resources
resources/*.png DataLab-Platform-SigimaX-0182bf4/.pre-commit-config.yaml 0000664 0000000 0000000 00000000325 15244251443 0022740 0 ustar 00root root 0000000 0000000 repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.12.2
hooks:
# Run the linter.
- id: ruff-check
args: [ --fix ]
# Run the formatter.
- id: ruff-format DataLab-Platform-SigimaX-0182bf4/.pylintrc 0000664 0000000 0000000 00000001010 15244251443 0020314 0 ustar 00root root 0000000 0000000 [FORMAT]
# Essential to be able to compare code side-by-side (`black` default setting)
# and best compromise to minimize file size
max-line-length=88
[TYPECHECK]
ignored-modules=qtpy.QtWidgets,qtpy.QtCore,qtpy.QtGui,plotpy._scaler
[MESSAGES CONTROL]
disable=wrong-import-order
[DESIGN]
max-args=10 # default: 5
max-positional-arguments=11 # default: 5
max-attributes=12 # default: 7
max-branches=20 # default: 12
max-locals=20 # default: 15
min-public-methods=0 # default: 2
max-public-methods=25 # default: 20 DataLab-Platform-SigimaX-0182bf4/.readthedocs.yaml 0000664 0000000 0000000 00000001274 15244251443 0021712 0 ustar 00root root 0000000 0000000 # Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
apt_packages:
- xvfb
- libxkbcommon-x11-0
- libxcb-icccm4
- libxcb-image0
- libxcb-keysyms1
- libxcb-randr0
- libxcb-render-util0
- libxcb-xinerama0
- libxcb-xfixes0
jobs:
pre_build:
# Start Xvfb before building docs
- "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &"
- "export DISPLAY=:99"
sphinx:
configuration: doc/conf.py
formats:
- pdf
python:
install:
- method: pip
path: .
extra_requirements:
- doc
DataLab-Platform-SigimaX-0182bf4/.vscode/ 0000775 0000000 0000000 00000000000 15244251443 0020020 5 ustar 00root root 0000000 0000000 DataLab-Platform-SigimaX-0182bf4/.vscode/launch.json 0000664 0000000 0000000 00000003241 15244251443 0022165 0 ustar 00root root 0000000 0000000 {
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Run current file",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"envFile": "${workspaceFolder}/.env",
"justMyCode": false,
},
{
"name": "Run current file (unattended)",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"envFile": "${workspaceFolder}/.env",
"pythonArgs": [
"-W error::DeprecationWarning",
"-W error::RuntimeWarning",
],
"justMyCode": false,
"args": [
"--unattended",
],
"env": {
// "DEBUG": "1", // ☣� Debug mode will reset .ini settings
// "QT_QPA_PLATFORM": "offscreen",
// "SIGIMAX_DATA": "${workspaceFolder}/sigimax/data/tests", // TODO : Use test data folder
}
},
{
"name": "Profile current file",
"type": "debugpy",
"request": "launch",
"module": "cProfile",
"console": "integratedTerminal",
"envFile": "${workspaceFolder}/.env",
"args": [
"-o",
"${file}.prof",
"${file}"
],
},
]
} DataLab-Platform-SigimaX-0182bf4/.vscode/settings.json 0000664 0000000 0000000 00000002014 15244251443 0022550 0 ustar 00root root 0000000 0000000 {
"[bat]": {
"files.encoding": "cp850"
},
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
},
"[restructuredtext]": {
"editor.wordWrap": "on"
},
"editor.codeActionsOnSave": {
"source.organizeImports.ruff": "explicit"
},
"editor.formatOnSave": true,
"editor.rulers": [
88
],
"files.exclude": {
"**/__pycache__": true,
"**/*.pyc": true,
"**/*.pyo": true
},
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
"python.analysis.autoFormatStrings": true,
"python.testing.pytestArgs": [],
"python.testing.pytestEnabled": true,
"python.testing.pytestPath": "pytest",
"python.testing.unittestEnabled": false,
"terminal.integrated.tabs.description": "${workspaceFolder}",
"python-envs.pythonProjects": [
{
"path": ".",
"envManager": "ms-python.python:venv",
"packageManager": "ms-python.python:pip"
}
],
} DataLab-Platform-SigimaX-0182bf4/.vscode/tasks.json 0000664 0000000 0000000 00000063422 15244251443 0022047 0 ustar 00root root 0000000 0000000 {
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "🧽 Ruff Formatter",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"ruff",
"format",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": true,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
},
{
"label": "🔦 Ruff Linter",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"ruff",
"check",
"--fix",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": true,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
},
{
"label": "🧽🔦 Ruff",
"dependsOrder": "sequence",
"dependsOn": [
"🧽 Ruff Formatter",
"🔦 Ruff Linter",
],
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
},
{
"label": "🔦 Pylint",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"pylint",
"sigimax",
"--disable=duplicate-code",
"--disable=fixme",
"--disable=too-many-arguments",
"--disable=too-many-branches",
"--disable=too-many-instance-attributes",
"--disable=too-many-lines",
"--disable=too-many-locals",
"--disable=too-many-public-methods",
"--disable=too-many-statements",
],
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": true,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
},
{
"label": "🚀 Pytest",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"pytest",
"--ff",
// "--gui",
// "--show-windows",
],
"options": {
"cwd": "${workspaceFolder}",
"env": {
// "DEBUG": "1", // ☣� Debug mode will reset .ini settings
"UNATTENDED": "1",
},
},
"group": {
"kind": "build",
"isDefault": true,
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": true,
},
"type": "shell",
},
{
"label": "sphinx-build",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"sphinx",
"build",
"doc",
"build/gettext",
"-b",
"gettext",
"-W",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
},
{
"label": "sphinx-intl update",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"sphinx_intl",
"update",
"-d",
"doc/locale",
"-p",
"build/gettext",
"-l",
"fr",
"--no-obsolete",
"-w",
"0",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
"dependsOrder": "sequence",
"dependsOn": [
"sphinx-build",
],
},
{
"label": "cleanup-doc-translations",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"guidata.utils.translations",
"cleanup-doc",
"--directory",
".",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
"dependsOrder": "sequence",
"dependsOn": [
"sphinx-intl update",
],
},
{
"label": "sphinx-intl build",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"sphinx_intl",
"build",
"-d",
"doc/locale",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
},
{
"label": "🔎 Scan translations",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"guidata.utils.translations",
"scan",
"--name",
"sigimax",
"--directory",
".",
"--copyright-holder",
"DataLab Platform Developers",
"--languages",
"fr",
],
"group": {
"kind": "build",
"isDefault": false,
},
"options": {
"cwd": "${workspaceFolder}",
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
"dependsOrder": "sequence",
"dependsOn": [
"cleanup-doc-translations",
],
},
{
"label": "📚 Compile translations",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"guidata.utils.translations",
"compile",
"--name",
"sigimax",
"--directory",
".",
],
"group": {
"kind": "build",
"isDefault": false,
},
"options": {
"cwd": "${workspaceFolder}",
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
"dependsOrder": "sequence",
"dependsOn": [
"sphinx-intl build",
],
},
{
"label": "Generate requirements",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"guidata.utils.genreqs",
"all",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
},
{
"label": "🧪 Coverage tests",
"type": "shell",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"coverage",
"run",
"-m",
"pytest",
"sigimax",
],
"options": {
"cwd": "${workspaceFolder}",
"env": {
"COVERAGE_PROCESS_START": "${workspaceFolder}/.coveragerc",
},
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"panel": "dedicated",
},
"problemMatcher": [],
},
{
"label": "📊 Coverage full",
"type": "shell",
"windows": {
"command": "${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m coverage combine; if ($?) { ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m coverage html; if ($?) { start htmlcov\\index.html } }",
},
"linux": {
"command": "${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m coverage combine && ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m coverage html && xdg-open htmlcov/index.html",
},
"osx": {
"command": "${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m coverage combine && ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m coverage html && open htmlcov/index.html",
},
"options": {
"cwd": "${workspaceFolder}",
"env": {
"COVERAGE_PROCESS_START": "${workspaceFolder}/.coveragerc",
},
},
"presentation": {
"panel": "dedicated",
},
"problemMatcher": [],
"dependsOrder": "sequence",
"dependsOn": [
"🧪 Coverage tests",
],
},
{
"label": "Upgrade PlotPyStack",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"pip",
"install",
"--upgrade",
"pip",
"PythonQwt",
"guidata",
"PlotPy",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"group": {
"kind": "build",
"isDefault": true,
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": false,
},
"type": "shell",
},
{
"label": "� Reinstall guidata/plotpy/sigima dev",
"type": "shell",
"command": "${config:python.defaultInterpreterPath}",
"args": [
"scripts/run_with_env.py",
"${config:python.defaultInterpreterPath}",
"${workspaceFolder}/scripts/reinstall_dev.py",
],
"options": {
"cwd": "${workspaceFolder}",
"statusbar": {
"hide": true,
},
},
"presentation": {
"panel": "dedicated",
"reveal": "always",
},
"problemMatcher": [],
},
{
"label": "🧹 Clean Up",
"type": "shell",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"guidata.utils.cleanup"
],
"options": {
"cwd": "${workspaceFolder}"
},
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": false,
},
},
{
"label": "📚 Build doc",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"sphinx",
"build",
"doc",
"${workspaceFolder}/build/doc",
"-b",
"html",
"-D",
"language=fr",
// "-W",
],
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": true,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
"showReuseMessage": true,
},
"type": "shell",
"dependsOrder": "sequence",
"dependsOn": [
"Generate requirements",
],
},
{
"label": "� Open HTML doc",
"type": "shell",
"windows": {
"command": "start build/doc/index.html",
},
"linux": {
"command": "xdg-open build/doc/index.html",
},
"osx": {
"command": "open build/doc/index.html",
},
"options": {
"cwd": "${workspaceFolder}",
},
"problemMatcher": [],
},
{
"label": "📦 Build package",
"type": "shell",
"command": "${command:python.interpreterPath}",
"args": [
"scripts/run_with_env.py",
"${command:python.interpreterPath}",
"-m",
"guidata.utils.securebuild",
"--prebuild",
"python -m guidata.utils.translations compile --name sigimax --directory .",
],
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"panel": "dedicated",
},
"problemMatcher": [],
"dependsOrder": "sequence",
"dependsOn": [
"🧹 Clean Up",
],
},
{
"label": "� Untracked files",
"type": "shell",
"command": "git ls-files --others | Where-Object { $_ -notmatch '^\\.' -and $_ -notmatch '^(build|dist|releases)/' -and $_ -notmatch '.(pyc|mo)$'}",
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": true,
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": true,
},
},
{
"label": "🔄 Switch to PyQt5",
"type": "shell",
"command": "${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m pip uninstall -y PyQt5 PyQt5-sip PyQt5-Qt5 PyQt6 PyQt6-sip PyQt6-Qt6 PySide6 shiboken6; ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m pip install --quiet PyQt5>=5.15.6; ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -c 'import qtpy; print(qtpy.API_NAME, qtpy.QT_VERSION)'",
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
},
},
{
"label": "🔄 Switch to PyQt6",
"type": "shell",
"command": "${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m pip uninstall -y PyQt5 PyQt5-sip PyQt5-Qt5 PyQt6 PyQt6-sip PyQt6-Qt6 PySide6 shiboken6; ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m pip install --quiet PyQt6; ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -c 'import qtpy; print(qtpy.API_NAME, qtpy.QT_VERSION)'",
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
},
},
{
"label": "🔄 Switch to PySide6",
"type": "shell",
"command": "${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m pip uninstall -y PyQt5 PyQt5-sip PyQt5-Qt5 PyQt6 PyQt6-sip PyQt6-Qt6 PySide6 shiboken6; ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -m pip install --quiet PySide6; ${command:python.interpreterPath} scripts/run_with_env.py ${command:python.interpreterPath} -c 'import qtpy; print(qtpy.API_NAME, qtpy.QT_VERSION)'",
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
},
},
{
"label": "🔄🗑� Uninstall Qt bindings",
"type": "shell",
"command": "${command:python.interpreterPath} scripts/run_with_env.py python -m pip uninstall -y PyQt5 PyQt5-sip PyQt5-Qt5 PyQt6 PyQt6-sip PyQt6-Qt6 PySide6 shiboken6",
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "build",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
},
},
{
"label": "🧪 GitHub Actions local: list jobs (act)",
"type": "shell",
"command": "act",
"args": [
"-l",
],
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "test",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
},
},
{
"label": "🧪 GitHub Actions local: test_pyqt5.yml (pull_request)",
"type": "shell",
"command": "act",
"args": [
"pull_request",
"-W",
".github/workflows/test_pyqt5.yml",
"-P",
"ubuntu-latest=ghcr.io/catthehacker/ubuntu:full-latest",
"-v",
],
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "test",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
},
},
{
"label": "🧪 GitHub Actions local: test_pyqt6.yml (pull_request)",
"type": "shell",
"command": "act",
"args": [
"pull_request",
"-W",
".github/workflows/test_pyqt6.yml",
"-P",
"ubuntu-latest=ghcr.io/catthehacker/ubuntu:full-latest",
"-v",
],
"options": {
"cwd": "${workspaceFolder}",
},
"group": {
"kind": "test",
"isDefault": false,
},
"presentation": {
"clear": true,
"echo": true,
"focus": false,
"panel": "dedicated",
"reveal": "always",
},
},
],
} DataLab-Platform-SigimaX-0182bf4/LICENSE 0000664 0000000 0000000 00000003000 15244251443 0017455 0 ustar 00root root 0000000 0000000 BSD 3-Clause License
Copyright (c) 2023, DataLab Platform Developers.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
DataLab-Platform-SigimaX-0182bf4/MANIFEST.in 0000664 0000000 0000000 00000000067 15244251443 0020220 0 ustar 00root root 0000000 0000000 graft doc
graft sigimax/locale
include requirements.txt DataLab-Platform-SigimaX-0182bf4/README.md 0000664 0000000 0000000 00000021405 15244251443 0017740 0 ustar 00root root 0000000 0000000 # SigimaX - Reusable GUI Framework for Scientific Applications

[](./LICENSE)
[](https://pypi.org/project/sigimax/)
**SigimaX** is an **open-source Python framework for building Qt-based scientific desktop applications**. It provides a reusable application skeleton — main window, configuration system, embedded widgets, and HDF5 infrastructure — so that developers can focus on domain-specific features.
🔬 Developed by the [DataLab Platform Developers](https://github.com/DataLab-Platform), SigimaX is extracted from [DataLab](https://datalab-platform.com/) and powers its GUI layer.
---
## 🌟 Project & Sponsors
| Project/Sponsor | Description |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| Open-source platform for scientific signal and image processing, built on SigimaX. |
|
| European non-profit supporting open-source and internet projects. SigimaX has received funding from NLnet for its development, through the DataLab project. |
---
## ✨ Highlights
- **Extensible configuration system** — `OptionField`-based settings with `get()`/`set()`/`context()` API and JSON persistence
- **Rich widget catalog** — 15 ready-to-use scientific widgets: curve fitting, peak detection, signal baseline, HDF5 browser, log viewer, wizard dialogs, and more
- **Complete HDF5 infrastructure** — built-in file browser, importer, and workspace save/load
- **Embedded Python console** — `DockableConsole` with error-to-console routing and configurable namespace
- **Production-grade status bar** — memory usage monitoring with alarm threshold, console toggle
- **PlotPy integration** — `DockablePlotWidget` and adapters for signal/image/ROI objects
- **Derivation pattern** — subclass `SigimaXOptions` + `SGMXMainWindow` + call `run()` to build a full app in minutes
---
## 💡 Use Cases
SigimaX is meant to be:
- A **framework for building scientific desktop apps** with Qt
- A **reusable main window** with menus, toolbars, docks, and HDF5 workspace management
- A **widget library** for signal/image analysis dialogs (fitting, peak detection, baseline, cursor, delta-X)
- A **configuration backbone** for apps that need persistent user preferences
---
## 📖 Design Philosophy
SigimaX separates the **generic application skeleton** from **domain-specific logic**. Derived applications follow a three-step pattern:
1. **Subclass `SigimaXOptions`** to add application-specific configuration fields
2. **Subclass `SGMXMainWindow`** to customize menus, toolbars, and dock widgets
3. **Call `sigimax.app.run()`** to launch the application with splash screen support
This architecture is proven in production: [DataLab](https://datalab-platform.com/) is built entirely on this derivation pattern.
### Position in the Stack
```text
End-user apps (DataLab, custom scientific apps)
↓ subclass / configure
SigimaX � THIS PROJECT (framework layer)
↓ depends on
Sigima (computation) + PlotPy + guidata + PythonQwt
↓
NumPy / SciPy / Qt
```
---
## 🚀 Quick Start
```python
from sigimax.app import run
from sigimax.config import CONF as Conf, SigimaXOptions, EnumOptionField, _
from sigimax.mainwindow import SGMXMainWindow
from sigimax.widgets.plotdock import DockablePlotWidget
from sigimax.config import TypedOptionField
from plotpy.constants import PlotType
# A missing option may be initialized on first read:
color_mode = Conf.color_mode.get("auto")
# 1. Define custom options
class MyAppOptions(SigimaXOptions):
def __init__(self):
super().__init__()
self.app_name.set("MyApp")
self.greeting = TypedOptionField(
self,
"greeting",
default="Hello!",
expected_type=str,
description="Startup message",
)
# 2. Customize the main window
class MyAppMainWindow(SGMXMainWindow):
def __init__(self, console=None, hide_on_close=False):
Conf.app_name.set("MyApp")
super().__init__(console=console, hide_on_close=hide_on_close)
# Add a dockable curve plot
self.curve_dock = DockablePlotWidget(self, PlotType.CURVE)
dock, loc = self.curve_dock.create_dockwidget(_("Curve Viewer"))
self.addDockWidget(loc, dock)
# 3. Launch
run(window_class=MyAppMainWindow)
```
---
## ⚙� Architecture
```text
sigimax/
├── app.py # Application launcher (create / run)
├── config.py # Configuration system (SigimaXOptions, CONF singleton)
├── env.py # Runtime environment (verbosity, unattended mode)
├── mainwindow.py # SGMXMainWindow (generic main window)
├── widgets/ # Reusable Qt widgets
│ ├── plotdock.py # DockablePlotWidget
│ ├── splashscreen.py # Configurable splash screen
│ ├── h5browser.py # HDF5 file browser
│ ├── logviewer.py # Log viewer dialog
│ ├── status.py # Status bar widgets (memory, console)
│ ├── fitdialog.py # Curve fitting dialogs
│ ├── signalpeak.py # Signal peak detection
│ ├── signalbaseline.py # Signal baseline selection
│ ├── signalcursor.py # Signal cursor selection
│ ├── signaldeltax.py # Signal delta-X measurement
│ ├── wizard.py # Multi-page wizard dialog
│ └── ... # File dialogs, warning/error boxes
├── h5/ # HDF5 I/O (read/write/import)
├── adapters_plotpy/ # Converters between PlotPy/guidata and Sigima objects
├── utils/ # Qt helpers, config dir resolution
├── data/ # Icons, resources
└── locale/ # Translations (EN, FR)
```
---
## 📦 Installation
```bash
pip install sigimax
```
Or in a development environment:
```bash
git clone https://github.com/DataLab-Platform/SigimaX.git
cd SigimaX
pip install -e .
```
---
## 📚 Documentation
📖 Full documentation (in progress) is available at:
👉
> Want to use SigimaX as part of the full DataLab platform?
> Check out: [DataLab](https://datalab-platform.com/)
---
## 🧪 Testing
SigimaX comes with a comprehensive test suite based on `pytest` (155 tests).
### ✅ Validated Environments
The test suite has been checked with the following matrix:
- **Python**: 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
- **Operating systems**: Windows, Linux
- **Qt bindings**: PyQt5, PyQt6, PySide6 (future fix needed)
> ⚠� Note: PySide6 is currently known to be not fully working in this matrix.
```bash
# Run all tests (offscreen, no GUI)
python scripts/run_with_env.py python -m pytest
# Show Qt windows during tests
python scripts/run_with_env.py python -m pytest --show-windows
```
---
## 🧠License
SigimaX is distributed under the terms of the BSD 3-Clause license.
See [LICENSE](./LICENSE) for details.
---
## � Contributing
Bug reports, feature requests and pull requests are welcome!
See the [CONTRIBUTING](https://datalab-platform.com/en/contributing) guide to get started.
---





---
© DataLab Platform Developers
DataLab-Platform-SigimaX-0182bf4/babel.cfg 0000664 0000000 0000000 00000000132 15244251443 0020201 0 ustar 00root root 0000000 0000000 # This file is used to configure Babel for the project.
[python: **.py]
encoding = utf-8
DataLab-Platform-SigimaX-0182bf4/doc/ 0000775 0000000 0000000 00000000000 15244251443 0017224 5 ustar 00root root 0000000 0000000 DataLab-Platform-SigimaX-0182bf4/doc/_static/ 0000775 0000000 0000000 00000000000 15244251443 0020652 5 ustar 00root root 0000000 0000000 DataLab-Platform-SigimaX-0182bf4/doc/_static/DataLab-Banner.svg 0000664 0000000 0000000 00000113677 15244251443 0024105 0 ustar 00root root 0000000 0000000
DataLab-Platform-SigimaX-0182bf4/doc/_static/DataLab-Title.svg 0000664 0000000 0000000 00000112725 15244251443 0023752 0 ustar 00root root 0000000 0000000
DataLab-Platform-SigimaX-0182bf4/doc/_static/DataLab.svg 0000664 0000000 0000000 00000111100 15244251443 0022655 0 ustar 00root root 0000000 0000000
DataLab-Platform-SigimaX-0182bf4/doc/_static/Sigima-Frontpage.png 0000664 0000000 0000000 00000167637 15244251443 0024540 0 ustar 00root root 0000000 0000000 ‰PNG
IHDR è ¯fr° pHYs a a•ø¶ tEXtSoftware www.inkscape.org›î< IDATxœìÝK“\çyØñ§{®¸ A
$%Y’m‰²c[R¹*©¤²Ë&•UªRY¤²Ï*•|}…l²É2‹¤*—J줢8)ÛRÙE†âE$
wæ>=3}?·,zf0€äŠÀLÏü~E�éÓ§ßî {þýž÷´š¦‰ˆ˜‰ˆÿ,"Þˆˆù κqD|ÿ&"þuDT¦if"â?EÄ?<Α 'Ú‰ˆÜjšæ_FÄ¿:îÑ 'Þ¿h5MónDüÁq� 8ñ~ÑjšfÖL >ߨÕì�• àó´�{ Àô €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H €4A H›=î Çg\T1•1•Q”u”UUÕDU7ÑjEÌδc¦ÝŠÙÙ™˜Ÿ›‰Åù™8¿8ív븇Ξ¦i¢(ë¨ê&ªªŽ¦‰¨›&šfrY»ÝŠv«ívkòœÎÎÄl»å9€§Ðì¿¶>òû½/ì}m¢õÈuÑÚÿú“÷tã']ÿðíìßÒã×ÝÿÚã¯õMÓùòn'3žÖÑíZ�ìöÉû|ìKOϧ_ÿ �q4�ÝË'ÝÎãû