Skip to content

Spectrogram & PSD plot types, EEG datasource, other-source cleanup - #76

Merged
AlexisJanin merged 15 commits into
devfrom
new-plot-type-spectrogram
Aug 12, 2026
Merged

Spectrogram & PSD plot types, EEG datasource, other-source cleanup#76
AlexisJanin merged 15 commits into
devfrom
new-plot-type-spectrogram

Conversation

@AlexisJanin

@AlexisJanin AlexisJanin commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Covers #71, #72, #73, #74, #75.

#71 — Spectrogram plot type

Third plot type after time_series and loop: time × frequency, power as colour (go.Heatmap), built on a new spectral.py (pure numpy STFT, grid-uniformity validation, decimation refusal). Config in JSON and the xlsx spectrograms sheet, db_range User-option fallback, annotation support, demo EEG data.

  • 68edcf5 Spectrogram feature first implementation

#72 — EEG .edf datasource

New eeg datasource reading EDF headers and per-channel-rate int16 records directly, no dependency added. Replaces the other-as-CSV workaround #71 used to get EEG data in.

  • 45bf512 .edf datasource added
  • 74648bb Fixing bad eeg data in the example, keep good signals

#73 — PSD plot type

Power-vs-frequency line plot reusing spectral.py's Welch averaging; rendered as a go.Scatter (the Loop case, not the heatmap case).

  • fab5b1c psd plot type added

#75 — Per-file options for every other file (closed)

Each file inside other/ gets its own other::<stem> box in the patient-options UI (own time_shift, own group by file), instead of one flat box shared by the whole datasource.

  • 7601cca Extending other data source support by using database option specific to each of the source file

#74 — Remove datasources with no format-specific parsing

philips_waves, philips_numerics and syringe did no real parsing — with #75's per-file config in place, they were other with extra machinery and are now removed; their example data moved under other::<stem>. Per-file trace_options (mode/line_width/opacity/marker_symbol) was added so a removed source doesn't lose its distinct line style, then exposed on the xlsx sentinel row so it isn't JSON-only.

  • c7dfc58 Per-file trace style, source symlinks and stem dedup for the other datasource
  • 60a4adb Remove philips_waves, philips_numerics and syringe datasources
  • f7ee7ed Update docs, skills and the pushdown benchmark for the datasource removal
  • 4a234fa Add TraceOption exposure onto xlsx file

Also

  • a9d9d10 Improving contribution rules about ClinicalScope processing being light and focused on display

Test plan

  • pytest green (pre-existing modebardisable/plotly-version failures in signal_container.py:1086 aside, unrelated to this PR)
  • ruff check / ruff format --check clean on touched files
  • Manual review of rendered spectrogram/PSD against the demo patient

…tasource (issue 74)

- find_files keeps one file per stem, preferring parquet, so a folder holding both
  data.csv and data.parquet no longer loads the same signals twice
- 'other' now symlinks each source file into clinical_scope_output/, extending the
  traceability guarantee previously limited to philips_waves
- an other::<stem> section can carry a trace_options block (mode, line_width, ...)
  overriding the datasource default
- xlsx global groups emit qualified refs for other:: signals, which could not resolve before
… 74)

They performed no format-specific parsing, so they were 'other' with extra machinery.
Now that each file in other/ carries its own configuration and time_shift, they no
longer earn a module. Example data moved into other/, configs rekeyed to other::<stem>,
and a folder still named after a removed source is reported with a warning.

Also corrects signal names in the demo workbook that never matched the demo data
(a pre-existing mismatch this migration made visible).
@AlexisJanin AlexisJanin self-assigned this Aug 11, 2026
@AlexisJanin AlexisJanin added enhancement New feature or request status: todo Need to be done Code quality Improve overall code quality (maintainability, robustness, readability) datasource labels Aug 11, 2026
@AlexisJanin AlexisJanin changed the title New plot type spectrogram (and follows-up) Spectrogram & PSD plot types, EEG datasource, other-source cleanup Aug 11, 2026
alexisj-inria and others added 3 commits August 11, 2026 18:00
Extract shared type-check and window/overlap-override boilerplate from
Signal.spectrogram_from_signal/psd_from_signal; move hovertemplate dB/Hz
precision into constants.Spectral; drop an issue-number reference from a
comment; close test gaps around the sentinel-only-column warning loop
(only trace_mode was covered; timezone had no coverage at all), trace_options
isolation across datasources, and characterize today's unvalidated pass-through
of trace_mode/line_width/opacity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
example/ mixed shipped demo material with test-only fixtures. It now holds
only what a user or the release bundle touches; test fixtures moved under
tests/data/.

Moves (history preserved):
- Patient_difficult_format -> tests/data/patients/
- example_database_options.{json,xlsx} -> tests/data/option_files/

Removals:
- Patient_other: unreferenced; two files were byte-identical to demo_patient,
  and its stem-collision case is already covered synthetically in test_other.py
- example_database_options_other.{json,xlsx}: superseded by the demo config
- template_database_options.json: restated the tutorial reference with no
  consumer and had silently drifted three features behind

example/demo_database/database_options.json is new: a generated twin of the
xlsx, so library users who never launch the app have a runnable config to
point at. The xlsx gained sections for fluxmed_signals, fluxmed_parameters,
mindray_respi_waves and mindray_respi_numerics -- the demo shipped data for
these but never plotted them -- plus range/visible/display coverage. Every
column of the signals sheet is now exercised by a real example.

New guards in tests/unit/test_example_assets.py: the folder template matches
the registry (this is how edf/ went missing), each template folder keeps its
.gitkeep, the demo json matches its xlsx, and the demo config configures every
datasource it ships.

Docs: tutorial repointed at the demo configs and its display/visible rows now
state how they differ; CLAUDE.md corrects the database_options key name to
'signals'; README names a real config path; the new-datasource skill requires
a demo config section; the organize-patient-folder evals no longer target a
patient folder deleted a release ago.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The demo's anonymisation left two stamping conventions in the raw files
(naive 08:12:33 and 06:12:33 UTC), and each source's
DATA_SOURCE_DEFAULT_TIMEZONE read them differently, so one recording landed
in three clusters two hours apart. Loading the demo showed sources that
never overlapped.

Data shifted +2h so it agrees with the sources that were already right:
- mindray_scope: all seven CSVs re-stamped; filenames renamed to keep the
  range they advertise truthful (they only supply the signal name to the
  loader, which reads timestamps from the file contents)
- servo_u: the 'Log start' header of Curves_00000000.sta, which is the sole
  reference -- timestamps are built as Log start + Time(ms), and the
  T(h:m:s.ms) column is dropped
- other/numerics.parquet: tz-aware index 06:12:33Z -> 08:12:33Z, since an
  already-aware index ignores the database_options timezone override

Config instead of data where the stored index is naive: other::waves moves
from Europe/Paris to UTC. The demo now exercises four timezone paths at
once -- explicit UTC, explicit non-European (eit stays Asia/Karachi, landing
21 minutes after the others), implicit source default, and
already-aware-so-override-ignored.

Ten of eleven sources now start at 10:12:33 CEST; eit remains offset so the
demo still has something for time_shift to correct.

patient_options_example.json and the README quickstart now carry the demo's
real eit day and edf recording_start, so 'try it immediately' holds.

Snapshots regenerated for mindray_scope and servo_u. The naive/aware bound
equivalence test pinned two windows seven seconds into the servo_u
recording; both move +2h with the data, keeping the same instant expressed
two ways. Full suite green: 809 passed, ruff clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Code quality Improve overall code quality (maintainability, robustness, readability) datasource enhancement New feature or request status: todo Need to be done

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants