Skip to content

Merging master into jtb (documentation branch)#54

Open
jtbabicz wants to merge 136 commits into
jtbfrom
master
Open

Merging master into jtb (documentation branch)#54
jtbabicz wants to merge 136 commits into
jtbfrom
master

Conversation

@jtbabicz

Copy link
Copy Markdown
Collaborator

Docs are out of date compared to master. Need to merge master changes into jtb to build docs.

Leland Bruce Gee and others added 30 commits May 4, 2025 09:32
…dex for the darks (eg below the first 10 time bins use that as the dark spectrum)
…ization also IRF fitting that is dubious right now but fits something
merging master to the current experiment to capture the recent PR for the dark shot changes.
…rence_spectrum-should-have-a-feature-to-make-difference-based-on-indices

21 xspectvisualizationplot 2d difference spectrum should have a feature to make difference based on indices
…. Scaled fast_delay_key values by 1e12 in time_binning method in XSpect_Analysis.py. Created a current clean and working notebook XSpect_XES_dehe_on_demand_05022025.ipynb
…n_demand, etc. Renamed the notebooks so that they are unique and they don't conflict with merges from others. It would be good to come up with a system/protocol for git and notebook.
…heritance chain. It doesn't seem to break anything. I just think it is neater that way.
Merging code changes from Dehe for Follmer experiment
…eys are unique and not duplicates in the final set of attributed.
This commit introduces a new method, `primary_analysis_static_laser`, specifically designed for analyzing data with static laser conditions.  This method now separates shots based on laser presence and applies hitfinding and spatial reduction steps individually to the resulting shot subsets: 'epix', 'epix_simultaneous_laser', and 'epix_xray_not_laser'.  This allows for a more granular analysis of laser-related effects.

Key changes:

*   Added `primary_analysis_static_laser` method for laser analysis.
*   Modified the laser analysis method to filter shots and handle hitfinding, transposition, patching, rotation and spatial reduction for different shot types to enable laser-specific filtering and analysis.
*   Updated `keys_to_save` to include results from laser-specific analysis.
…zation taking the absolute value of the trapz because the energy axis direction changes the values of the trapezoidal integrals.
lbgee and others added 30 commits July 1, 2026 00:34
…d_rotation_angle

patch_pixels gains auto_detect mode for ASIC panel-gap columns.
A two-method approach handles the full range of defect severity:

  Method 1 (ratio): compares column profile against median-filtered
  baseline.  Columns with ratio > threshold (spikes) or < 1/threshold
  within the signal band (dead gaps) are flagged.  Catches extreme
  charge-sharing spikes that dwarf the spectral signal.

  Method 2 (z-score + width filter): computes a robust z-score using
  MAD-based local sigma.  Bright and dark outliers above nsigma are
  separately clustered and kept only when cluster width <= max_gap_width.
  Separating bright/dark prevents merging a dark gap with its bright
  charge-sharing neighbors into a single wide cluster that would be
  rejected as a signal gradient.  This catches subtle 50%-reduced dead
  columns that the ratio method misses.

The polynomial fit is vectorised: instead of calling np.polyfit for every
(shot, row) pair, the Vandermonde matrix is solved once via np.linalg.solve
to get a projection vector, then all rows are evaluated with a single dot
product.  The fit region now also excludes the ±patch_range neighborhood
of every known bad column, not just the target pixel, so elevated
charge-sharing neighbors don't bias the polynomial anchor.

find_rotation_angle wraps XSpectDetectorProcessor to auto-detect the tilt
of a dispersed spectral signal via Canny edge detection → DBSCAN clustering
→ per-cluster PCA.  Stores the angle on the run for use by rotate_detector.

XSpectDetectorProcessor.find_optimal_rotation_angle: fix arctan2 argument
order (was arctan2(dy,dx), should be arctan2(dx,dy) for row-dominant
principal vector); weight cluster angles by cluster size so small
edge-detection artifacts don't bias the result.

filter_detector_adu: guard getattr with a None check so the step skips
gracefully when the detector key is absent on the pre-pipeline pass.
…gies length

reduce_detector_ccm previously only handled 1D (scalar) and 2D (spectrum)
detectors.  A new 3D branch accumulates full 2D images per energy bin —
producing a (n_energy, rows, cols) stack — enabling RIXS-plane pipelines
where the detector is a 2D spectrometer image not yet collapsed spatially.

Off-by-one in bin count: both reduce_detector_ccm and
reduce_detector_ccm_temporal were allocating n_bins = len(ccm_bins) where
ccm_bins is the n+1-element edge array from make_ccm_axis.  They now use
len(ccm_energies) (= n edges - 1) so the output axis length matches the
energy axis.

NaN-guarded accumulation: shots that produce NaN values (e.g. empty bins,
missing HDF5 rows) are now skipped rather than poisoning the running sum.
For 2D/3D detectors np.where(np.isnan(...), 0.0, ...) replaces NaN pixels
element-wise so a single bad shot doesn't zero an entire spectrum row.

reduce_detector_ccm_temporal gets the same ccm_energies length fix and
NaN guarding for both 1D and 2D detector dims.

make_energy_axis and normalize_xes: minor formatting only.
…erance

Four new test cases cover the full auto_detect surface:
  - test_auto_detect_spike: confirms a 100× bright column is flagged and
    patched via the ratio method (Method 1)
  - test_auto_detect_subtle_gap: confirms a 50%-reduced narrow 2-col dip
    is caught by the z-score method (Method 2) which the ratio threshold misses
  - test_auto_detect_ignores_wide_gradient: verifies that a smooth
    intensity gradient across 200 columns produces zero flagged pixels
  - test_auto_detect_merges_manual: checks that auto-detected and
    manually specified pixel lists are both applied

test_patch_interpolate tolerance relaxed from exact equality to atol=1e-3
because the vectorized polynomial fit (Vandermonde + np.linalg.solve)
differs from np.polyfit in numerical precision by ~1e-10 — the test was
comparing against a specific polyfit rounding, not a scientific threshold.
…nalysis notebook

Three YAML pipeline configs for the polariton / FeNO pump-probe XAS
experiment at XCS (LCLS run 26, runs 187-216 and 339-347):

  xcs101591326_ultrafast_xas.yaml  — static DCCM energy scan, auto CCM
    axis from setpoints, laser-on vs laser-off, 1D XAS with reduce_detector_ccm

  xcs101591326_temporal_xas.yaml  — time-delay scan at fixed DCCM energy,
    enc/lasDelay binning (-10 to 25 ps, 35 bins), reduce_detector_temporal,
    combine_runs reduction across 7 runs with uncertainty propagation

  xcs101591326_2d_xas.yaml  — simultaneous DCCM energy × time-delay scan,
    21-bin time axis (-2 to 8 ps), 2D binning via reduce_detector_ccm_temporal,
    produces transient absorption map Δμ(E,t)

Analysis notebook (xcs101591326_temporal_xas_analysis.ipynb) computes
mu = If/I0 per delay bin from the pipeline output and plots normalised
difference spectra for kinetic analysis.
…eline configs

mfx101609126_pershot_xes.yaml  — stochastic RIXS input preparation:
  filters to xray shots, ADU thresholds both detectors, patches ASIC
  gap columns (manual on epix100_0; auto_detect on epix100_1 SEER),
  rotates -2.0° (spec) / -1.6° (SEER), projects rows → 1D per-shot
  spectra for spook correlation.  Produces:
    xrt_hproj (N×2048) and epix_spec_ROI_1 / epix_seer_ROI_1 (N×n_cols)

mfx101609126_seer_xrt.yaml  — static comparison of both spectrometers
  across runs 78-82: sums all xray shots to 2D image then collapses
  rows → 1D spectrum for each detector independently.

mfx101609126_static_rixs.yaml  — RIXS plane for run 97 DCCM scan:
  reduce_detector_ccm accumulates full 2D epix images at each incident
  energy → (n_energy, 60, 300) stack, then reduce_detector_spatial
  collapses the cross-dispersion axis → (n_energy, 300) RIXS plane.

mfx101609126_droplet_pershot_xes.yaml  — per-shot XES using photon-
  counting via droplet_reconstruction (epix100_0 fixed-length sparse
  format), same downstream steps as pershot_xes.

mfx101609126_droplet_recon_test.yaml  — 100-shot smoke test for
  droplet_reconstruction; max_shots: 100 avoids materialising the full
  ~36k-shot array during development.
rotation_diagnostic — finds optimal detector tilt angle by running the
  pipeline on a subset of shots and inspecting the 2D sum image with
  overlaid rotation angle estimates from XSpectDetectorProcessor.  Fixed
  angles (-2.0° / -1.6°) were determined here and hardcoded into YAMLs.

pixel_patch_diagnostic — compares raw vs patched column profiles for
  epix100_0 and epix100_1, visualises the ASIC gap positions and the
  effect of auto_detect patching on the baseline ratio and z-score.

seer_shot_browser — per-shot SEER image browser: scan forward/backward
  through individual shots to inspect photon distributions and confirm
  the ASIC gap correction is working correctly.

seer_vs_xrt — quantifies SEER as an alternative incident-energy monitor
  for stochastic RIXS.  Computes correlation between SEER and XRT per-
  shot total-intensity and center-of-mass energy.  Conclusion: SEER
  tracks intensity well (r=0.90) but has low COM energy correlation (0.41)
  because it encodes sample transmission/emission, not purely the incident
  beam.  Gap patching dramatically improves the spook AtA condition number.

spook_rixs — stochastic RIXS extraction using the spook library: builds
  A (XRT hproj) and B (epix_spec per-shot spectra) matrices and solves
  for the RIXS cross-section X via regularised least squares.

droplet_spook_rixs — same as spook_rixs but using photon-counted spectra
  from droplet_reconstruction instead of raw ADU integration.

droplet_spook_transmission — stochastic RIXS using SEER (transmission
  geometry) as the B matrix; photon-counted for improved S/N.

rixs_plane — static RIXS plane visualisation for the DCCM scan run.
regenerate_run0079.py — runs mfx101609126_pershot_xes.yaml (standard ADU
  integration) and saves per-shot spectra to examples/results/; used as
  the baseline to compare against droplet-reconstructed spectra.

regenerate_droplet_pershot.py — runs mfx101609126_droplet_pershot_xes.yaml
  for runs 78-82 sequentially, saving one HDF5 per run to results/.
  Measures reconstruction throughput (shots/sec) and reports memory usage.

droplet_reconstruct.py — standalone utility script that reconstructs a
  single run's sparse photon data without the full pipeline framework;
  used for rapid iteration and debugging of the reconstruction step.

droplet_reconstruction.ipynb — step-by-step walkthrough of the sparse
  format: reads raw HDF5, shows fixed-length vs variable-length layouts,
  runs _scatter and _scatter_roi helpers manually, compares output images
  against the pre-processed ROI_area dataset for bit-identity verification.

droplet_recon_pipeline_eval.ipynb — end-to-end comparison of ADU
  integration vs photon-counting via the pipeline API.  Runs both YAMLs
  on run 79, overlays 1D emission spectra, and evaluates peak S/N ratios
  to quantify the photon-counting improvement for spook inputs.
…c assets

mfx101080524_static_xes.yaml: remove hitfinding step.  The hit-finder was
removing shots that had low per-frame median signal, which is expected for
single-photon-level XES data.  Removing it recovers the correct shot count
and avoids discarding weak-signal runs.

seer_full_detector_run78.png: full-panel SEER detector image from run 78
showing the spatial distribution of signal across all ASIC tiles; used in
rotation_diagnostic.ipynb and seer_shot_browser.ipynb to orient the
cross-dispersion ROI selection.

c.ipynb: scratch notebook for static RIXS pipeline diagnostics (run 97);
shows RIXS plane shape, energy range, and 2D sum-image ROI inspection.

xcs101591326.ipynb, Untitled.ipynb: updated experiment analysis notebooks.
…MFX pipelines

Droplet reconstruction, patch_pixels auto-detect, XAS fixes, and XCS/MFX pipelines
…, and analysis notebooks

Adds the full mfx102101026 (ferricyanide) static XES analysis workflow and the
supporting XSpect engine changes needed to run it at scale, plus the earlier
mfx100895324 static-XES artifacts.

XSpect engine changes
----------------------
* model/run.py, controller/{config_parser,pipeline,batch_manager}.py:
  Add an import-time row-range crop for detector keys (`row_range: [start, end]`
  in the YAML `detector_keys` block). The slice is applied at HDF5 read time in
  both the single-run (`load_run_key_delayed`) and batched (`_load_batch_data`)
  paths, so the full detector frame is never materialized. For epix100_0 this
  cuts per-batch memory ~5-7x and was necessary to stop the pipeline dying in
  silent OOM. The crop origin is recorded on the run (`run._row_offset`) so that
  downstream ROIs stay in absolute (full-frame) coordinates.

* analysis/spectroscopy.py:
  - reduce_detector_spatial now auto-translates absolute ROI coordinates into
    the cropped-array frame using the recorded row_range offset (stripping
    _reduced/_ROI_* suffixes so derived keys inherit the parent offset). This
    fixes ROIs silently reading out of bounds (Ka summing to zero) after a crop.
  - hitfinding gains an absolute `min_sum` mode to reject genuinely dark shots
    (sum == 0 after ADU threshold); the old relative median-cutoff mode is kept
    as a fallback for signal-dominated data.

* controller/pipeline.py, pipeline_runner.py, __init__.py:
  Add a real `logging`-based progress system on the "XSpect" logger, exposed via
  `enable_logging(level, log_file=None)` (stderr and/or file). The batched path
  now reports per-batch completion via imap_unordered and raises an explicit
  OOM-hint error if a worker dies, replacing the previous silent hang. Per-step
  debug logging and full tracebacks are emitted from run_pipeline.

mfx102101026 experiment (experiments/mfx102101026/)
---------------------------------------------------
* mfx102101026_static_xes.yaml: static Fe Ka/Kb pipeline on epix100_0
  (transpose=true, row_range crop, hitfinding min_sum, ferricyanide ROIs).
* mfx102101026_static_xes_visualization.ipynb: per-run pipeline + diagnostics.
* mfx102101026_aggregate_xes.ipynb: cross-run aggregation from saved results.
* mfx102101026_ferricyanide_reference.ipynb: aggregates runs 9+10, minimum
  subtraction then area normalization, saves the ferric (Fe3+) reference.
* mfx102101026_run9_baseline_speciation.ipynb: crop -> baseline -> normalize ->
  speciation on the fixed windows (Ka 6380-6410, Kb 7031-7075 eV); baseline
  subtraction currently disabled (passthrough) pending a robust routine.
* mfx102101026_speciation_simple.ipynb: non-expert runner. User lists runs;
  runs are XSpect-processed only if not already cached (per-run HDF5), then
  combined -> min-subtract -> normalize -> speciation vs the ferric reference,
  with a difference spectrum and an eLog beamline-summary section (compiles the
  figures, labeled by run, into stats/summary/XSpect_speciation via SummaryPost).
* mfx102101026_droplet_visualization.ipynb: droplet sparse-data viewer. Reads
  only ROI droplets by streaming contiguous slabs of the first N sparse columns
  (avoids the 28 GB full-array read that hung the notebook); documents that
  droplet coordinates are in the raw, non-transposed detector frame.
* runs.csv: run bookkeeping; runs 4/5/8 flagged as no-beam, run 9 first 30 Hz.
* results/*.h5: cached per-run and aggregate spectra, ferric reference.
* FeIIICN6_*.dat: exported Ka/Kb reference spectra.

mfx100895324 (experiments/mfx100895324/) and examples/
------------------------------------------------------
Adds the static-XES notebooks, YAML, runs.csv, manifest/README, and saved
results that the mfx102101026 work was derived from, plus a spike-finder
example notebook.

Note: the LUTE smalldata configs and epix common-mode diagnosis for
mfx102101026 live in the experiment data area (not this repo); summary_post.py
lives alongside the notebooks in results/lbgee/ for the same reason.
…r mfx102101026

Adds a repository skill documenting how to stand up a new XES experiment
end-to-end, plus the droplet-reconstruction pieces it references.

skills/XSpect-setup-XES/SKILL.md
- Phased guide (experiment-type triage -> LUTE smalldata pipeline -> geometry
  discovery -> XSpect YAML -> diagnostic/analysis notebooks -> issue tracking).
- Decision questions to classify the analysis: static, time-resolved pump-probe,
  CCM-scanned/RIXS, or droplet/photon-counted XES.
- YAML templates for each type, memory (row_range) guidance, the ePix100
  common-mode gotcha, droplet vs droplet2photon distinction, and the LUTE
  droplet2photon template gap (issue #97).
- Guardrails: never invent step names, verify units (ADU vs keV) and the
  transpose/ROI coordinate frame, confirm beam-on before debugging.
- README links to the skill and the YAML pipeline guide.

experiments/mfx102101026/
- mfx102101026_droplet_recon_xes.yaml: native photon-counted workflow using the
  droplet_reconstruction step (ROI applied on sparse arrays) -> union -> sum ->
  rotate -> reduce, modeled on the working mfx101609126 droplet pipeline.
- droplet_visualization.ipynb: Section 7 reconstruction now uses the native
  XSpect droplet_reconstruction step instead of an external helper script.
…ing conventions

Adds Phase 0.5 (Identify the HDF5 keys) and strengthens the guardrails so the
skill enumerates datasets and asks the user when a role is ambiguous rather than
guessing paths.

- Role -> naming conventions: emission = ePix100 (epix100_0/1, epix_0/1 and
  variants); scattering = epix10k2m / jungfrau16m (usually not the XES signal);
  I0 monitor = ipm<N>/sum in standard hutches but MfxDg*BmMon/... at MFX;
  lightStatus masks, timing keys, CCM scan variable, von Hamos geometry PVs.
- Ambiguity protocol: 0 candidates -> ask / offer to skip; >1 -> list with
  shapes and ask; always echo the final key->role mapping for confirmation.
- Notes that with two ePix100s (spectrometer + SEER) the agent must ask which
  is which instead of assuming _0 is the spectrometer.
…ring

Zeros low-variance detector pixels via sklearn VarianceThreshold instead of a
hand-tuned ADU cutoff. Pixels that barely change across shots (dead, static
hot, constant background) are dropped; signal-bearing pixels are kept. Writes
back to the same detector key and stores the retained mask as
<key>_variance_mask. Handles 3D and 2D detectors.

Closes #36
…itecture

Brings in the mfx102101026 static + droplet Fe Kα/Kβ XES analysis and the
XSpect engine features developed for it:

- Import-time detector row_range crop with automatic ROI offset translation
  (model/run.py, controller/batch_manager.py, analysis/spectroscopy.py) — the
  memory fix that prevents OOM in batched runs.
- hitfinding min_sum absolute mode to reject dark shots.
- logging system with enable_logging() and per-batch progress (controller).
- experiments/mfx102101026/: static XES YAML, droplet recon YAML, and
  visualization/aggregate/reference/speciation/droplet notebooks.
- experiments/mfx100895324/: predecessor static-XES artifacts.
- skills/XSpect-setup-XES/: repository skill for standing up a new XES
  experiment (LUTE + XSpect YAML + diagnostics), with HDF5 key identification.

Run 26 tracking: experiment #98, tracked under #99; open dev items #97, #96,
#70, #55, #45.
…ne-architecture

# Conflicts:
#	XSpect_XES_mfx101080524.ipynb
YAML-driven pipeline ar Here's an extended merge description you can paste into the GitHub merge box.

  Merge YAML-driven pipeline architecture into master (#100)

  Replaces the monolithic controller with a declarative pipeline. Analysis is
  defined in a YAML config as an ordered list of steps; a registry maps each step
  name to a stateless function step(run, **kwargs). Model, controller, and
  analysis layers are separated so the same steps run across XES, XAS, RIXS, and
  droplet workflows.

  Architecture (issue #82, Phase 1A)
  - Step and reduction registry (XSpect/analysis/registry.py) with decorator
    registration and lookup by name.
  - Config parser that reads the data and pipeline sections of a YAML file.
  - Batch manager with multiprocessing, scalar pre-pipeline pass, max_shots limit,
    and absolute HDF5 index handling.
  - Pipeline runner that executes steps in order and writes results onto the run.

  Registered steps (Phases 1B/1C and time-resolved XES: #85, #86, #87)
  - Loading: load_run_keys, load_detector (ROI, transpose, combine).
  - Shot and pixel filtering: filter_shots, filter_detector_adu,
    filter_detector_variance.
  - Combination: union_shots, separate_shots.
  - Spatial and temporal reduction, time binning, CCM binning (3D detector
    support, NaN handling).
  - Energy calibration: make_energy_axis, make_ccm_axis.
  - Normalization, rotation detection (find_rotation_angle), rotate_detector.

  New capabilities
  - droplet_reconstruction for sparse photon-counting HDF5 layouts.
  - patch_pixels with auto-detection (ratio and z-score methods) and vectorized
    polynomial fitting.
  - filter_detector_variance: sklearn VarianceThreshold as a data-driven
    alternative to a hand-tuned ADU cutoff. Zeros pixels whose value barely
    changes across shots and stores the retained mask as <key>_variance_mask.
    Closes #36.

  Examples and docs
  - YAML configs and analysis notebooks for mfx101080524, mfx101609126,
    mfxl1027922, xcs101591326, and mfx102101026 beamtimes.
  - User guide at docs/YAML_PIPELINE_GUIDE.md.
  - New XSpect-setup-XES skill for HDF5 key identification and detector naming.

  Testing
  - Regression suite with saved reference arrays for static and ultrafast XES.
  - Unit tests for pipeline steps (32 pass locally for the step and spectroscopy
    suites).
  - Pre-existing failures in test_xas_steps.py (CCM off-by-one) and
    test_batch_manager.py are unrelated to this branch and predate the merge.

  Compatibility and conflict resolution
  - Old imports still work (from XSpect.XSpect_Analysis import spectroscopy_run).
  - origin/master (XAS foil-scan and derivative-analyzer work, PR #90) was merged
    into the branch first. One conflict resolved: the root-level
    XSpect_XES_mfx101080524.ipynb was deleted per master's reorg; the canonical
    copy remains at examples/XSpect_XES_mfx101080524.ipynb. XSpect_Analysis.py
    auto-merged and should get a review pass.chitecture with MVC separation
Quarterly review (2026-04-16 to 2026-07-16) covering the YAML pipeline
overhaul, new analysis steps, bug fixes, and LUTE work for discussion.

README now describes the model/controller/analysis layers, the step
registry pattern, data flow, and per-mode use cases with example configs.
Move the four pipeline-YAML templates out of SKILL.md into templates/,
reached by a Phase 3 pointer keyed to the experiment type, so a run reads
only the one it needs. Thin the Guardrails section to a failure-mode
checklist that points at each rule's canonical phase instead of restating
it. Trim the description to identity plus triggers and add the droplet type.
Port the MkDocs Material + mkdocstrings site off the stranded jtb branch
onto master and retire the parallel Sphinx/Read the Docs setup, so there is
one documentation source.

- mkdocs.yml: mkdocstrings pointed at XSpect.model/controller/analysis via
  new source pages, plus the legacy top-level modules; nav includes the YAML
  pipeline guide. Drop the logo/favicon refs (files never existed in source).
- .github/workflows/docs.yml: build and gh-deploy on push to master (the old
  workflow only triggered on jtb, so the live site froze at 2025-10-10). Install
  requirements.txt so mkdocstrings can import the package in CI.
- Remove docs/_build, conf.py, *.rst, Makefile/make.bat, docs/requirements.txt,
  and .readthedocs.yaml.
- Fix index.md links (.html -> .md) and a pipeline.py docstring that griffe read
  as a bogus parameter. Build verified locally.

Refs #101
common_mode_correction subtracts per-row, per-column, or per-bank
electronic baseline estimated from a signal-free reference band, on 3D
detector data before shot reduction, preserving shape.

subtract_polynomial_background fits a low-order polynomial to signal-free
regions along the spatial axis and subtracts it, writing a non-destructive
<key>_bkgsub. peak_mask accepts multiple ranges so several emission lines
dispersed on one detector can be masked at once. Per-row weighting excludes
NaNs from the fit. Reuses the vectorized weighted-polyfit approach from
patch_pixels.

Adds unit tests for both steps and documents them in the YAML guide and
README step lists.

Closes #102
…kgsub

Add common_mode_correction and subtract_polynomial_background steps
Hand-written reference for all 28 steps plus combine_runs. One index page
(step contract, array-shape vocabulary, master table) and four category
pages: loading & filtering, detector & spatial, binning, spectra &
reductions. Each entry lists what the step reads, what it writes, and every
tunable parameter with its default.

Wire a Step reference nav section into mkdocs.yml after the YAML guide;
keep source_analysis.md as the source-linked API.
Add detailed step reference docs
Each step and the combine_runs reduction now carries a short YAML snippet
showing a typical invocation, so every entry has one.
…gs page

Group the guide, a new Example configs page, the step reference, and the
source-linked API under one "YAML pipeline" nav section. The example configs
page embeds the six analysis-mode YAML files live via snippets, so the docs
track the real files in examples/.
Add YAML example to every step reference entry
Nest pipeline docs and add example configs page
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants