# ToFScope documentation
## Your first analysis
Source: https://datasophos.github.io/ToFScope/docs/getting-started/first-analysis.html
## Opening an acquisition
After [launching ToFScope](installation.qmd), you can choose a `.h5` acquisition from the file picker.
You can also open a previous analysis through **Saved files**, which shows the file system relative to whatever
`output-root` you used when running ToFScope. You can open multiple files simultaneously, and they will show in
separate tabs with their own separate analyses.
[]{#preparing-raw-acquisitions}If the acqusition file was never examined in the commercial software, it will contain only raw TOF events without
any stored ion maps. If this is the case, ToFScope will warn you upon opening the file and allow you to
[prepare](../using-tofscope/raw-preparation.qmd) the file before opening. The preview requires confirmation
before ToFScope creates a new copy for exploration, as it can potentially take a few minutes depending on the size
of the acquisition.

## Signals and views
When you open a file, the **Explore** screen displays its signals and linked views. For a new analysis, ToFScope
initially selects the stored signal with the greatest summed-spectrum intensity among peaks centered at m/z 20 or
higher (to avoid common organics at lower m/z values). If no stored peak meets that threshold, it considers all peaks.
In ToFScope, a **signal** represents ion intensity associated with a selected mass-to-charge range across the
acquisition's image pixels and depth frames. It can come from a channel already stored in the file or from one or more
mass windows you define with **Create from spectrum** tool. A mass range can include contributions from more than one
ion, so a signal is not necessarily unique to a particular element or isotope.
The ion image and front projection show the selected signal's spatial distribution, while its depth profile shows how
intensity changes across frames. The mass spectrum helps you examine peaks and define mass windows. Multiple signals
can be compared in the profile view.
The region of interest and viewing frame range can be changed to focus on part of the acquisition by clicking and dragging
across either the top view or front projection. Additional signals and their profile curves can be shown for comparison.
The [signals and views guide](../using-tofscope/signals-and-views.qmd) describes the controls and the distinction between
calculated coverage and viewing range.
## Additional analysis tools
The [depth calibration](../using-tofscope/depth-calibration.qmd) tool allows you to set known depth values in physical
units at one or more frames. The application can then interpolate between these "depth anchors" to provide an estimate of
physical depth in the profiles and 3D views. The [Peak identification](../using-tofscope/identification.qmd) tool compares
a peak with candidate isotope ions, and the [3D volume](../using-tofscope/3d-visualization.qmd) view allows you to
inspect the spatial distribution of selected signals in three dimensions.
## Saving and sharing results
After you have anlayzed your signal to satisfaction, clicking **Save as…** will creates a new HDF5 analysis copy. After
restarting ToFScope, you can reopen that copy through to resume or re-inspect the saved analysis.
CSV (for profiles) and PNG (for images) exports can be used to share selected results. The
[saving and exporting guide](../using-tofscope/saving-and-exports.qmd) describes what each output preserves and provides
more detail.
::: {#next-using-tofscope}
[Using ToFScope](../using-tofscope/signals-and-views.qmd){.pagination-link}
:::
```{=html}
```
## ToFScope user guide
Source: https://datasophos.github.io/ToFScope/docs/getting-started/index.html
ToFScope allows you to explore ToF-SIMS acquisitions using linked plots, named signals, and 3D views.
It runs as a headless Python service in your terminal with an interface in your browser.
The guides for [installation](installation.qmd) and [your first analysis](first-analysis.qmd) cover
the first steps. The installation guide also covers updates, uninstalling, and troubleshooting.
## Using ToFScope
- [Signals and views](../using-tofscope/signals-and-views.qmd): choosing ion channels, defining mass windows, and exploring regions and frame ranges.
- [Depth calibration](../using-tofscope/depth-calibration.qmd): connecting acquisition frames with known physical depths.
- [Peak identification](../using-tofscope/identification.qmd): searching isotope candidates and measuring selected signals.
- [3D visualization](../using-tofscope/3d-visualization.qmd): comparing spatial signals as overlays or tiles.
- [Saving and exports](../using-tofscope/saving-and-exports.qmd): preserving an analysis or sharing CSV and image results.
- [Preparing raw acquisitions](../using-tofscope/raw-preparation.qmd): creating initial ion maps when a file contains raw events.
## Technical documentation
The [architecture guide](../technical-documentation/architecture.qmd) explains the browser, service, calculations, and files through diagrams. [File compatibility and limitations](../technical-documentation/file-compatibility.qmd) describes supported files and how saved copies can be used in ToF-SIMS software. Developers and administrators can continue to [configuration](../technical-documentation/configuration.qmd), [building and testing](../technical-documentation/building-and-testing.qmd), and [deployment](../technical-documentation/deployment.qmd).
::: {.callout-note}
## Saving before stopping the service
Open analyses and in-progress jobs are held in memory. **Save as** creates a copy that can be reopened after a restart.
:::
## Install and launch
Source: https://datasophos.github.io/ToFScope/docs/getting-started/installation.html
## What you'll need
- Python 3.11 or newer and [*uv*](https://docs.astral.sh/uv/getting-started/installation/) to install and manage the application (you can also use `pip` directly, but *uv* makes things easy!).
- A folder containing supported *TOFWERK* *TOFexplorer* HDF5 (`.h5`) acquisitions.
- A writable folder with enough space for saved acquisition copies.
## Installation
After installing `uv` using the instructions for your operating system at the link above, you can open a new terminal window and check that it is available:
```sh
uv --version
```
The following command installs ToFScope from PyPI:
```sh
uv tool install tofscope
```
If your shell cannot find `tofscope`, you can run `uv tool update-shell` and open a new terminal window.
## Folder selection and launch
By default, ToFScope will only have access to whatever files are in the folder that you launch it from
(or any subfolders). You can use the `--data-root` argument to allow read-only access to another folder
(such as a network mount containing your instruments' data) and the `--output-root` argument to allow
for saving analysis results to a separate folder.
The example paths in this command should be replaced with your acquisition and saved-copy folders;
paths containing spaces need quotation marks:
```sh
tofscope --data-root "/path/to/acquisitions" --output-root "/path/to/saved-analyses"
```
The local service will start in your terminal and the app should open automatically in your browser.
The terminal process needs to remain open while you work. After saving your analysis, you can stop the
service by returning to the terminal and pressing **Ctrl-C**.
::: {.callout-warning}
## Saving before stopping the service
Heads up! Open analyses and in-progress jobs are held in memory until you explicitly save them.
Use the **Save as** feature to save your analysis before stopping the ToFScope process, or you will
lose your data!
:::
Original acquisitions opened by ToFScope are never edited directly; the applicaiton will only save copies
to protect the original integrity of the collected data.
## Updates and removal
Using *uv*, the app can be updated with the following command:
```sh
uv tool upgrade tofscope
```
The command `uv tool uninstall tofscope` uninstalls the app. This does not delete your acquisition or saved-analysis folders.
## Troubleshooting
| Problem | What to check |
| --- | --- |
| **`uv: command not found`** | A new terminal window and the PATH instructions printed by the uv installer may resolve the problem. |
| **`tofscope: command not found`** | You can run `uv tool update-shell`, open a new terminal window, and try again. `uv tool list` shows installed tools. |
| **No files in the picker** | `--data-root` must point to the folder containing the `.h5` files, and the service needs permission to read it. If `--data-root` is not given, ToFScope can only see files within the folder from which it was run. |
| **Browser did not open** | The terminal may contain an error message. If the service is running, `tofscope open` in another terminal window opens the existing local service. |
| **Cannot save** | The output folder must exist, be writable, and have enough free space for a full copy. Calculations must be finished or canceled and drafts finished or discarded before saving. ToFScope also will not overwrite a file, currently, so check if there is a duplicate file name in the selected folder. |
| **Port already in use** | The previous ToFScope process may need to be stopped before trying again. |
For help with startup problems, `tofscope doctor` loads the configuration and verifies the packaged frontend assets. It reports an error if either check fails; it does not diagnose every startup problem:
```sh
tofscope doctor --data-root "/path/to/acquisitions" --output-root "/path/to/saved-analyses"
```
## 3D visualization
Source: https://datasophos.github.io/ToFScope/docs/using-tofscope/3d-visualization.html
The **3D volume** view displays existing named signals through the acquisition, either together as an overlay or separately in tiles. Use it to explore spatial and depth patterns; the displayed volume is a downsampled preview.
## Choose signals and a layout
The [**3D signals**](#volume-signals) list contains all the named signals in your data. The current image signal is initially
shown. Select the signals to display, then open a signal's [settings](#volume-signal-settings) to adjust its
[colormap](#volume-colormap), [opacity](#volume-opacity), and [intensity threshold](#volume-percentile).
For example, a 70% threshold hides the weakest 70% of positive preview values, making stronger features easier to see while
potentially hiding weaker intensities within the signal.
By default, all signals are stacked on top of each other in the *Overlay* view. You can select [**Overlay** or **Tiles**](#volume-layout)
under **View** to change this setting. Tiles will show up to four signals per page side by side for comparison. Transparent overlays are
qualitative and can hide one signal behind another; inspect a single signal or use tiles to investigate occlusion.
You can choose [**Fast** or **Detailed**](#volume-quality) under **View** to control the level of detail in the 3D view.
```{=html}
Two signals are shown as an overlay in the 3D volume view.
```
```{=html}
Each signal has its own display settings.
```
## Adjust the display
Open [**Display settings**](#volume-display-settings) to choose the intensity scale, log colors, and depth exaggeration
or frame stretch.
- [**Independent** and **Shared**](#volume-intensity-scale) control the intensity scale. Independent scales are the default;
Shared uses one numerical range across visible signals, which can potentially cause strong signals to overwhelm weak ones.
- The upper display limit uses the 99.7th percentile of positive preview intensities. [**Log colors**](#volume-log-colors)
displays log(1 + intensity) to improve interpretability; depth profiles and exports retain their original numerical intensities.
- **Frame stretch** changes the displayed depth scale linearly. When depth is shown in frames, you can adjust the ratio of depth to X/Y to approximate a known feature's proportions.
```{=html}
Display settings apply across the 3D view; frame stretch is shown when depth uses frames.
```
The current ROI and **Viewing depths** apply to every layer. The 3D view offers **All frames** and **Frame range** to limit
what frames are shown in the 3D preview.
## Moving the camera
Click and drag or use the arrow keys to orbit the [volume](#volume-preview), scroll to zoom, and Shift-drag to pan.
The [**Camera** controls](#volume-camera) offer axis-aligned preset views, rotations in 15° steps,
a **Reset camera** feature, and a toggle between perspective or orthographic projection. Camera controls apply to all
tile cameras. The viewer also has a [maximize button](#volume-maximize) to increase the screen area of the 3D view.
## Technical details of the 3D preview
Fast previews are capped at 96 × 32 × 32; Detailed previews at 160 × 48 × 48. All visible layers share a
500,000-voxel budget, including layers on other tile pages (a voxel is a single cell in the 3D preview —
a three-dimensional pixel). These limitations are aimed at keeping the application responsive with large datasets.
The preview usually shows each signal as a continuous 3D volume. Some selections, such as a single thin layer or a
signal with missing data, are shown as individual points instead. When the preview combines nearby measurements,
it averages only the data that are available; missing data are not filled in.
If measurements are unevenly spaced, ToFScope may estimate values between them to draw the 3D preview and will
show a warning. Very wide, narrow, or deep views can also lose fine detail; a warning appears when detail may be missed.
When viewing data with calibrated depth, frames with unknown depths are left out of the preview. The preview combines
nearby frames and averages their known depths, including across calibration anchors. Profiles, measurements,
and exports still use the original-resolution data.
After customizing a 3D view, using the **Save as** button to save a ToFScope analysis will preserve layer styles,
layout, page, scale, cameras, and display settings.
## Depth calibration
Source: https://datasophos.github.io/ToFScope/docs/using-tofscope/depth-calibration.html
Depth calibration relates acquisition frames to known physical depths. Add one or more reference points, called *anchors*, then choose whether plots use frames or physical depth.
## Open the calibration editor
Select [**Depth calibration…**](#calibration-open) in the **Viewing depths** strip above the plots. The editor opens with a profile in original acquisition frames and controls for entering known depths.
```{=html}
The Viewing depths strip contains the depth-calibration and axis-unit controls.
```
## Add calibration anchors
1. Click a position on the editor's [calibration profile](#calibration-profile) to select an acquisition frame, or enter its exact number in [**Selected frame**](#calibration-frame).
2. Enter its [**Known depth**](#calibration-known-depth) in the displayed unit and select [**Add anchor**](#calibration-add-anchor).
3. Repeat for any additional reference points. Select [**Done**](#calibration-done) when finished.
```{=html}
The editor shows an anchor at frame 390 with a known depth of 1200 nm.
```
Frame 0 is fixed at depth 0. Both frame numbers and depths must increase strictly between anchors. To change or remove an anchor, use the controls in the [anchor table](#calibration-anchor-table); removing all positive anchors restores frame coordinates. When an existing anchor is selected, the editor shows **Update anchor** in place of **Add anchor**, as in the image above.
## Choose how depth is displayed
In the editor, [**Depth display unit**](#calibration-unit) selects nm, µm, or mm. In the main Viewing depths strip, use [**Frames** or **Physical depth**](#calibration-axis-units) to choose the coordinates shown on plots.
Physical profiles and front projections show only frames between the anchors; depths beyond the calibrated range remain unknown. Selection and keyboard navigation continue to use the original acquisition frames. Changing the display units does not resample the intensities.
## Export and interpret calibrated depths
The depth profile's [**CSV**](#calibration-csv) export includes `depth_nm` in nanometres, even when the plots display frames. Depth values are blank where they are unknown.
## Peak identification and isotope measurements
Source: https://datasophos.github.io/ToFScope/docs/using-tofscope/identification.html
The peak identification tool helps to identify a peak by comparing its measured mass-to-charge ratio (m/z) with a
catalog of atomic isotope ions. You can then associate a candidate with a signal or create a signal from the peak.
Isotope measurements compare selected signals within the current region and viewing frames.
::: {.callout-warning}
## Important Limitations
The catalog searches **single-atom isotope ions only**. It does not suggest molecular or cluster ions,
such as a dimer (two atoms of the same element), ions containing hydrogen or hydroxyl groups, or organic
molecular fragments. The charge and polarity filters do include multiply charged *single atoms*, which are
different from dimers.
Different species can have similar or overlapping m/z values. A listed atomic candidate is therefore a possible
match, not a confirmed identification, and an unlisted molecular ion could contribute to the same peak. Consider
other peaks, isotope patterns, mass resolution, and independent evidence when interpreting a result. Measured
signal shares are not quantitative composition. See this
[review of mass interference in FIB-TOF-SIMS](https://pmc.ncbi.nlm.nih.gov/articles/PMC10003971/) for more detail.
:::
## Open the identification tools
Use [**Identify peak**](#identification-open) or [**Isotope measurements**](#measurement-open) above the mass spectrum.
```{=html}
Open identification and isotope measurements from the mass spectrum header.
```
## Find isotope candidates
1. Open **Identify peak**, then click a peak in the [identification spectrum](#identification-spectrum) to search for potential matches.
Alternatively, enter an exact [**Measured m/z**](#identification-mz) and select [**Find candidates**](#identification-find).
2. Adjust the [tolerance and its unit](#identification-tolerance), or the [charge and polarity](#identification-charge), to change the search. The default absolute tolerance is 0.3 m/z; changing these settings refreshes the candidates.
3. Review the [candidate table](#identification-candidates), which shows predicted m/z, mass error, and natural abundance. Select a candidate to use it in the actions below.
By default, candidates with known natural abundance are ordered by abundance within the tolerance. Use [**Candidate order**](#identification-order) to choose closest-mass ordering, or include isotopes without tabulated natural abundance. The identification spectrum starts with a logarithmic intensity scale; source and reference information are available in the dialog.
```{=html}
The identification dialog compares a measured peak with isotope candidates.
```
## Assign or create a signal
After selecting a candidate, you can choose one of these actions:
- [**Assign an isotope to an existing signal**](#identification-assign): choose a signal and select **Assign isotope to signal**.
This records the candidate and reference information for isotope measurements and saved analyses; it does not change the signal's name,
mass window, or intensities, or confirm the identification.
- [**Create a signal from this peak**](#identification-create): enter the mass window and select **Apply window** to open an
assigned draft that you can tweak further, or **Add signal** to immediately calculate a new signal across all acquisition frames.
## Measure isotope signals
::: {.callout-warning}
Isotope measurement is a pre-alpha feature and has not been thoroughly tested.
If this is a feature you are interested in helping to test, please [contact us](https://github.com/datasophos/ToFScope/issues)!
:::
1. Open **Isotope measurements** and choose the [signals to measure](#measurement-signals).
2. Select [**Measure**](#measurement-run). Results use original-resolution data over the current ROI and viewing frames, restricted to the signals' common coverage.
3. Review the [percentage shares and results](#measurement-results), [region and frame summary](#measurement-scope), and any explanations for zero intensity or missing isotope assignments. Expand the [calculation details and provenance](#measurement-details) for more information.
```{=html}
A measurement compares two selected signals across the displayed region and frames.
```
The results describe ratios within the selected signal set; they are not quantitative composition. Fractions are suppressed
when mass windows overlap. If inputs change, captured measurements are marked out of date until you select **Measure** again.
[**Isotope CSV**](#measurement-csv) exports the measurement scope, mass errors, uncertainties, and provenance.
**Save as** and reopening the saved analysis also preserve isotope assignments and captured results.
## Preparing raw acquisitions
Source: https://datasophos.github.io/ToFScope/docs/using-tofscope/raw-preparation.html
Some *TOFWERK TOFexplorer* `.h5` files contain raw TOF detection events but no integrated ion maps. This is typically
the case if the raw acquisition has never been analyzed in *TOFexplorer*, which adds information about integrated
peak windows into the file. ToFScope can still read these "raw" files and prepare a new copy by integrating the peak
windows recorded in the file. The original acquisition remains unchanged.
## Prepare a copy
When you open a raw acquisition without ion maps, ToFScope shows a preparation preview before starting:
1. Review the [number of peak windows and frames](#preparation-scope) and the [required free space](#preparation-space). Preparation can take several minutes, and the final size depends on compression.
2. Check or change the [prepared filename](#preparation-filename) and review the displayed destination folder.
3. Select [**Prepare and open**](#preparation-start) to create and open the copy, or **Back to files** to return without preparing it. Progress and cancellation controls are shown while preparation is running.
```{=html}
The preparation preview describes the work, space required, and destination before creating a copy.
```
The prepared copy retains raw events and metadata. If the file lacks timing or channel metadata, the preview describes the
fallback assumptions; continue only if they are appropriate for the acquisition, because incorrect assumptions can produce
incorrect counts.
## Understand the limits
Only channels present in the raw peak table can be reconstructed automatically. Note: strict numerical equivalence with the
commercial software is not guaranteed.
::: {#next-technical-documentation}
[Technical documentation](../technical-documentation/architecture.qmd){.pagination-link}
:::
```{=html}
```
## Saving and exporting results
Source: https://datasophos.github.io/ToFScope/docs/using-tofscope/saving-and-exports.html
Use the **Save as…** button in the top right corner to create a self-contained analysis copy that you can reopen later.
If you want to share a specific profile, image, or plot, use the CSV or PNG buttons instead.
## Save an analysis copy
1. Finish or discard any signal drafts, and wait for calculations to finish or cancel them.
2. Select [**Save as…**](#save-button). Review the [destination](#save-destination) and choose [**Choose folder…**](#save-choose-folder) if you want a different available folder.
3. Enter a [filename](#save-filename) and select [**Save copy**](#save-confirm). Existing files are not allowed to be overwritten.
```{=html}
Save the analysis from the header, or export individual views from their plot controls.
```
```{=html}
Review the destination and filename before saving the analysis copy.
```
The new HDF5 copy includes the acquisition and committed analysis: signals and full-resolution custom results, including
hidden signals, along with names, colors, ROI, frame and depth selections, calibration, display settings, isotope results,
and 3D view state. The input file stays unchanged, even when it is itself a saved copy.
Saving first creates the copy on the server. After it finishes, [**Download copy**](#save-download) is available if you also
want to transfer it to your computer through a browser download (this is only really relevent if ToFScope is running on a
remote server). The copy remains on the server, and downloading a large file can take time.
```{=html}
After saving, the copy can optionally be downloaded.
```
## Choose where to save
The acquisition folder for opening files (`--data-root`) defaults to the current working directory. The saved-files
folder (`--output-root`) defaults to the acquisition folder. You should configure a different output root when you need to save
elsewhere or the acquisition folder is read-only.
In the **Save as…** dialog, [**Choose folder…**](#save-choose-folder) lets you browse or create a subfolder under `output-root`.
Local users can choose within the configured acquisition or saved-files folders; hosted users are limited to their private
saved-files folder. Check the full [destination](#save-destination) shown in the dialog before saving.
## Reopen or close an analysis
You can reopen a ToFScope analysis through the **Saved files** pane in the file picker. You can navigate subfolders and
reopen the copy after restarting ToFScope or on another machine. The top Open button opens another file in a new tab.
If you close an analysis with unsaved changes, choose **Save as**, **Discard**, or **Cancel** in the prompt.
## Export a profile or image
- [**CSV**](#save-profile-csv) beside the depth profile exports visible ROI profile curves at their original scale and
resolution. A selected frame range limits the exported rows.
- The image icon exports a PNG from the [ion map](#save-image-png) or [depth profile](#save-profile-png); profile PNGs
include labels. Other plot panels also provide PNG export controls.
## TOFexplorer compatibility
ToFScope attempts to save in a format that is cross-compatible with the commercial *TOFexplorer* software, though
this is not guaranteed. Custom signals defined in ToFScope should be readable as named regions in *TOFexplorer*.
For a signal with disjointed mass intervals, the *TOFexplorer* peak uses enclosing bounds and a midpoint that do not
accurately describe the gaps; ToFScope retains the exact intervals.
## Signals and views
Source: https://datasophos.github.io/ToFScope/docs/using-tofscope/signals-and-views.html
Explore brings signals, images, and plots together in one workspace. You can open multiple files, including the same file more than once, in independent file tabs. Each analysis keeps its own signals, region of interest (ROI), frame coverage, and viewing choices.
## Find your way around
Hover over, focus, or tap a number to see its description.
```{=html}
```
1. [**Signals**]{#overview-signals} selects the signal used for images and the curves shown in the profile.
2. [**Viewing depths**]{#overview-depths} selects the frames displayed in the images.
3. [**Ion map**]{#overview-ion-map} shows the selected signal across the sample; its controls include ROI and display settings.
4. [**Mass spectrum**]{#overview-spectrum} shows intensity by mass-to-charge ratio and lets you define a signal.
5. [**Front projection**]{#overview-projection} shows the selected signal across the sample and through the acquisition frames.
6. [**Depth profile**]{#overview-profile} shows signal intensity through the acquisition frames or calibrated depth.
## Choose or create a signal
The [**Signals**](#image-signals) tray lists stored channels and raw integrations. Choose one in the *Images* picker to
change which ion map and front projection is shown; use the *Profiles* picker to show or hide additional curves on the depth
profile. Signal names and colors stay with each signal when you switch views.
To add a signal:
1. Choose [**Add signal**](#image-add-signal) to search among the nominal channels (or ones previously defined with the
commercial software, or use [**Create signal**](#image-create-signal) above the spectrum to define a raw integration.
You can also choose **Create from spectrum** from the Add signal menu.
2. For a raw integration, name it and draw or enter exact inclusive mass intervals. Multiple disjointed intervals
can be used and will form a union, adding their intensities together.
3. Select [**Calculate signal**](#image-calculate-signal). The result is added to the tray and profile; it will then be available for you to select
it under **Images** to view that signal's intensity images.
```{=html}
The signal editor and spectrum: the numbered interval on the plot matches the bounds in the editor.
```
Select a [signal's profile chip](#image-signal-details) to open its details and see provenance and coverage, rename or
duplicate it, or edit a custom signal. Progress, cancellation, and errors appear beside the signal; a failed calculation
preserves the old result.
## Choose frames to calculate and view
[**Calculate over frames**](#image-calculate-frames) defines the depth range covered by a signal.
[**Viewing depths**](#image-viewing-depths) selects which available frames to display without recalculating it.
To customize the depths shown in the Explore view, choose [**All frames**](#image-all-frames),
[**Single frame**](#image-single-frame), or [**Frame range**](#image-frame-range) from the depth drawer.
The status next to the buttons describes what is being shown in the displayed image. Profiles use the full acquisition
domain, with gaps outside signal coverage.
You can also click the [front projection](#image-front-projection) or [depth profile](#image-depth-profile) to select a single frame,
or click and drag on either plot to select a frame range.
Use the [**CSV**](#image-profile-csv) button beside the depth profile controls to export the values shown in the plot to a CSV file.
If a frame range is selected, the export will be limited to that range.
## Adjust the image and plots
The ion map's [**ROI**](#image-roi) button allows you to select a region of interest. The ROI can also be set by clicking and
dragging directly on the ion map image. Setting an ROI will change the integrated intensity shown in the front projection and
depth profiles to only include ions from that region. The [**Display…**](#image-display) button allows you to customize display
settings, such as linear/log color scales, the colormap to use for SIMS data, and the choice to display SIMS ion counts or the
FIB-SE image.
Use the [**Relative profiles**](#image-relative-profiles) checkbox in the depth profile header to control how intensities are shown. When unchecked, the profiles share a mean-intensity scale, so weaker signals can be hard to see. Checking the box scales each profile to its own maximum, making their shapes easier to compare but potentially making noise more visible.
```{=html}
Relative profiles on: each curve is scaled to its own maximum.Relative profiles off: curves share a mean-intensity scale.
```
Use the [**Log y**](#image-log-y) button beside the spectrum to switch its vertical scale between linear and log scale.
Plot axes include labels, units, and tick marks. Hover over the [spectrum](#image-spectrum-plot) or
[profile](#image-depth-profile) to see the current x coordinate; calibrated profiles will also show the nearest frame.
### Using plot controls
::: {.plot-navigation}
| Action | Result |
|---|---|
| Drag on the mass spectrum | Zoom the view, or edit the active interval while a signal editor is open. |
| Double-click the mass spectrum | Reset its view. A single click preserves the current zoom. |
| Hold Cmd/Ctrl and drag a zoomed spectrum or profile | Pan horizontally. The **Pan** indicator lights on the hovered plot while the key is held. |
| Click the **Pan** button | Keep panning enabled without holding Cmd/Ctrl. |
| Use Ctrl/Cmd-wheel | Zoom a plot. Ordinary wheel scrolling moves the page. |
:::
## ToFScope architecture
Source: https://datasophos.github.io/ToFScope/docs/technical-documentation/architecture.html
::: {.callout-tip}
## Technical documentation
This section is for developers, administrators, and other readers who want to understand more details about how ToFScope is built,
deployed, and maintained. It covers the application architecture, file compatibility, building and testing, deployment,
and documentation maintenance. For instructions on actually using the application, start with the
[user guide](../getting-started/index.qmd).
:::
## Architecture overview
ToFScope allows users to analyze ToF-SIMS acquisitions through a convenient browser interface. This page describes how data
flows through the major parts of the application and explains how the application is built.
An **acquisition** is an HDF5 (`.h5`) file containing measurements from an instrument. A **signal** describes the ion data
being viewed; it can come from a stored channel in the original acquisition, or from a custom mass window. An **analysis**
is the current collection of signals, selections, calibration, and display settings for an open file.
## The whole system
```{mermaid}
flowchart TD
User[User] -->|selects and explores| Browser[Browser interface]
Browser <-->|requests and results| Service[ToFScope Python service]
Service -->|reads| Source[Acquisition HDF5 files]
Service -->|creates| Saved[Prepared or saved HDF5 copies]
Service -->|provides data for| Export[Downloads and exports]
Browser -->|renders| Views[Plots and 3D views]
```
In the usual local setup, the Python service (run via `tofscope`) and browser interface run on the same computer. This
server/client design will allow for future versions of ToFScope to run remotely while users access the tool with their local
browser. The service also supplies the browser's application files; no JavaScript development environment (Node) is needed
to run the packaged app. The browser displays results and communicates with the Python service, which runs the calculations.
The service reads acquisitions, coordinates calculations, and can create separate copies or exports. It keeps the original
acquisition unchanged.
ToFScope can also be configured for other deployments. Self-hosted server use is under development, and the container workflow is
untested. The [deployment guide](deployment.qmd) describes the current boundaries and setup.
## Typical analysis pipeline
```{mermaid}
flowchart TD
Start[Start ToFScope and open it in a browser] --> Pick[Choose an acquisition or saved file]
Pick --> Check{Needs preparation?}
Check -->|Yes| Prepare[Preview and confirm a prepared copy]
Prepare --> Explore
Check -->|No| Explore[Explore signals and linked views]
Explore --> Adjust[Choose regions, frames, and signals]
Adjust --> Explore
Explore --> More[Optional: calibrate depth, identify ions, or view in 3D]
More --> Explore
Explore --> Output[Export results or save an analysis copy]
Output --> Reopen[Reopen a saved copy later]
```
Some acquisition files need [preparation](../getting-started/first-analysis.qmd#preparing-raw-acquisitions) to create
initial ion maps from raw measurement events before they can be explored. ToFScope previews that operation and creates a
copy after the user confirms the action. In the *Explore* view, an ion image, mass spectrum, front projection, and depth
profile provide different perspectives on the same acquisition. A user can select a region of interest, change the depth
frame range, or compare signals; the views update to reflect those choices.
*Depth calibration* relates acquisition frames to physical depth when those depths are known. *Identify peak* helps
compare measured peaks with isotope candidates. The *3D volume* view shows spatial signal data. See the
[user guide](../getting-started/index.qmd) for much more detail on these points.
## Inside the application
The following diagram explains how the browser frontend communicates with the Python backend process:
```{mermaid}
flowchart TD
subgraph Frontend[Browser interface]
Screens[File picker, Explore, calibration, identification, 3D]
Plots[Plot and 3D renderers]
Client[API client and command queue]
Screens --> Client
Screens --> Plots
end
subgraph Backend[Python service]
API[FastAPI: requests, sessions, validation]
App[Application: analyses, commands, jobs, cache]
Present[Presentation: display data and exports]
Science[Science: integration, calibration, isotopes]
Storage[Storage: HDF5 reading, preparation, copies]
API --> App
API --> Present
App --> Science
App --> Storage
Present --> App
Present --> Storage
Storage --> Science
end
Client <-->|HTTP API| API
Storage <--> Files[HDF5 files]
```
The **frontend** is the interface in the browser that a user interacts with. It manages screens and interactions, sends
requests, and draws plots and 3D scenes using data returned by the service. The **API** handles requests and session
access between the browser and service. The application layer manages open analyses, commands, background jobs,
and cached arrays. Presentation code prepares data for displays and exports, science code implements calculations,
and storage code works with acquisition and saved files. Arrows in this figure show major relationships, not every dependency.
Readers who want to follow the code can start with the
[frontend screens](https://github.com/datasophos/ToFScope/tree/main/frontend/src/app),
[frontend API code](https://github.com/datasophos/ToFScope/tree/main/frontend/src/api),
and the backend's [API](https://github.com/datasophos/ToFScope/tree/main/src/tofscope/api),
[application](https://github.com/datasophos/ToFScope/tree/main/src/tofscope/application),
[presentation](https://github.com/datasophos/ToFScope/tree/main/src/tofscope/presentation),
[science](https://github.com/datasophos/ToFScope/tree/main/src/tofscope/science), and
[storage](https://github.com/datasophos/ToFScope/tree/main/src/tofscope/storage) modules.
## Following a selection
This example follows the data flows that cascade from a change to an Explore selection, such as the region of interest.
It shows the common path; individual actions can use different endpoints.
After a change, the service sends the browser an **analysis snapshot**: a record of the analysis settings at that
moment, including the selected signals, region, depth range, and display settings. It also includes a revision number
that identifies that version of the analysis. The snapshot describes the current state; the plotted data is requested
separately.
```{mermaid}
sequenceDiagram
actor Person
participant UI as Browser
participant API as Service API
participant Analysis as Analysis state
participant Data as View data
Person->>UI: Change a selection
UI->>API: Send an analysis command
API->>Analysis: Validate and update the analysis
Analysis-->>UI: Updated snapshot
UI->>API: Request affected display panels
API->>Data: Prepare panel data
Data->>Data: Read or reuse arrays
Data->>Data: Calculate views
Data-->>UI: Panel data and revision
UI->>UI: Check revision and redraw
UI-->>Person: Display updated views
```
The browser uses the snapshot to decide which panels need fresh data and avoids displaying a response for an older
revision. The service may reuse arrays from a memory cache to avoid repeated work; the cache is bounded and is not
permanent storage.
Some operations take longer and use a background job instead of this immediate display path. Examples include custom signal integration, raw preparation, isotope measurements, and saving. The interface can report job progress and results while the service schedules the work.
## Data, saving, and exports
```{mermaid}
flowchart TD
Original[Original acquisition] -->|read| Session[Open analysis in service memory]
Original -->|optional preparation creates| Prepared[Prepared HDF5 copy]
Prepared -->|open| Session
Session -->|Save as| Copy[Saved HDF5 analysis copy]
Original -->|acquisition data copied into| Copy
Copy -->|reopen| Session
Session -->|export| Results[CSV or other downloadable results]
Session -->|browser plot export| Image[PNG image]
```
The open analysis and in-progress jobs live in the service's memory; unsaved work is lost when it restarts.
The **Save as** action creates a new HDF5 copy with the acquisition and committed analysis, so it can be reopened
later. If the opened file is itself a prepared or saved copy, that file is the source for the new copy.
CSV and image exports are sent directly through the browser to the user's Downlods and can be used to share results;
**Save as** preserves the analysis for further work.
[Configuration and storage](deployment.qmd#configuration-and-storage) covers service resources and locking.
## Building a development version
```{mermaid}
flowchart TD
TS[React and TypeScript source] -->|Node and Vite build| Assets[Built browser assets]
Assets -->|copied into| Static[Python package static directory]
Python[Python service source] --> Package[Python distribution]
Static --> Package
Package -->|install and run| Server[Local Python service]
Server -->|serves assets and API| Browser[Browser]
```
Developers can use the [`scripts/build_frontend.py`](https://github.com/datasophos/ToFScope/blob/main/scripts/build_frontend.py)
script via `uv run python scripts/build_frontend.py`. It runs the frontend build defined in
[`frontend/package.json`](https://github.com/datasophos/ToFScope/blob/main/frontend/package.json), copies the resulting
files into `src/tofscope/static/`, and records a manifest. Running `uv build` creates the Python distributions;
[`setup.py`](https://github.com/datasophos/ToFScope/blob/main/setup.py) checks the bundled assets during the package build.
At runtime, the local service serves those prebuilt assets and the API; the browser runs the interface.
The [building and testing instructions](building-and-testing.qmd) list the commands, and
[deployment](deployment.qmd) describes other configurations.
## Building and testing
Source: https://datasophos.github.io/ToFScope/docs/technical-documentation/building-and-testing.html
This page will help you get started developing on ToFScope. All commands should be run from the repository root.
Python dependencies are managed with [`uv`](https://docs.astral.sh/uv/); [Node](https://nodejs.org/en) is needed
to develop or rebuild the frontend. For more details on how the application is designed, see
[ToFScope architecture](architecture.qmd) for an overview of the application's architecture and its build.
## Install the development version of the Python package
```sh
git clone https://github.com/datasophos/ToFScope.git
cd ToFScope
uv sync --frozen
```
## Install frontend dependencies
Install the exact versions in `frontend/package-lock.json` before working on the React and TypeScript interface:
```sh
npm --prefix frontend ci
```
This installs the frontend tools and dependencies into `frontend/node_modules/`. You will need to run it again
if the lockfile changes.
## Update the frontend API types
When the Python API changes, regenerate its OpenAPI schema and the TypeScript types used by the frontend:
```sh
npm --prefix frontend run generate:api
```
This updates `frontend/openapi.json` and `frontend/src/api/generated.ts`. Review and commit the generated changes with
the API change. The command uses the Python environment created by `uv sync` above.
## Check and test the frontend
```sh
npm --prefix frontend run typecheck
npm --prefix frontend test
```
The first command checks TypeScript without producing files; the second runs the Vitest frontend tests.
For browser workflows, run the Playwright suite:
```sh
npm --prefix frontend run test:e2e
```
These tests use Google Chrome and start local frontend and test backend servers by default. Install Chrome if it is not
already available; the CI setup uses `npm --prefix frontend exec -- playwright install --with-deps chrome` on Linux.
## Build the packaged frontend
The frontend application is bundled into the Python package, so users only need to install from PyPI and run `tofscope`
to start the app. On the developer side, this requires rebuilding the frontend assets into the Python package
and committing these files:
```sh
uv run python scripts/build_frontend.py
```
This script runs the frontend TypeScript and Vite build, replaces the generated files in `src/tofscope/static/`, and writes an
asset manifest. Rebuild after changing frontend sources so the Python package includes up-to-date browser assets.
During development, you will need to run this script to update what you see in the browser when testing manually.
## Test the Python application
```sh
uv run python -m unittest discover -s tests -v
```
This discovers and runs the Python test suite, including scientific calculations, storage, the API, and service behavior.
## Build and check distributions
After building the frontend assets, create the wheel and source distribution using `uv`. This example uses a
temporary directory to ensure a fresh context separate from the source directory:
```sh
artifact_dir=$(mktemp -d)
uv build --out-dir "$artifact_dir"
```
The wheel and source distribution both include the prebuilt browser assets. A source build will fail if those assets are
missing or stale. In the same terminal, install each artifact in a temporary environment and exercise the packaged
service and browser without Node:
```sh
uv run python scripts/check_distribution.py --artifacts "$artifact_dir" --output /tmp/tofscope-distribution
```
The script checks each artifact's version against the checkout, installs it in a temporary Python environment, and
creates disposable test acquisitions. It starts the installed service and uses Chrome to exercise preparation, plots,
identification, calibration, saving, reopening, and exports. It also checks that the packaged app runs without Node and
that the browser makes no unexpected external requests. These are smoke tests, not a replacement for the full test suites.
The goal of the script is to build ToFScope as a user would install it, then test both package formats in clean environments,
catching packaging problems that ordinary tests run from the source checkout might miss.
The temporary installations and test data are removed afterward. Results in `distribution.json` and screenshots are
written to the specified output directory; use a disposable location.
## Prepare a release
The repository includes a [`tofscope-release` agent skill](https://github.com/datasophos/ToFScope/blob/main/.agents/skills/tofscope-release/SKILL.md)
for preparing and publishing releases. Ask a compatible coding agent to use the skill when preparing a ToFScope release.
The agent proposes a version based on semantic versioning and asks for confirmation before updating the version and
generated assets, writing release notes, running the relevant checks, and opening a draft pull request.
The agent waits for release approval at the draft pull request. Once approved, it completes the merge, tags the merged
commit to trigger PyPI publishing, creates the GitHub Release from the prepared notes, and starts a documentation rebuild
so the changelog includes the release. A tag triggers publication; it does not by itself confirm that publishing succeeded.
## Check the container
Container deployment is in early stages, but the `check_container.py` script will build a local Docker image and
run a non-root smoke test with read-only acquisition files and writable temporary
storage. It requires Docker and uses disposable test data:
```sh
uv run python scripts/check_container.py
```
The repository's CI workflow runs these checks and verifies that regenerated API files have no unexpected changes.
See [Maintaining the documentation](documentation.qmd) for information on building and previewing the documentation
site.
## Configuration
Source: https://datasophos.github.io/ToFScope/docs/technical-documentation/configuration.html
This reference describes ToFScope configuration sources, environment variables, and defaults. For launch methods and
storage requirements, see [deployment](deployment.qmd). Most users won't need to change any of these settings,
and many are mostly intended for multi-user deployments, which are not completely tested yet. Regardless,
they are all documented here.
## Configuration sources
Settings can come from command-line options, environment variables, or a TOML file supplied with `--config`.
When more than one source sets the same option, command-line options take precedence over environment variables,
which take precedence over the TOML file; otherwise the defaults below apply. ToFScope does not automatically load
a configuration file. For example, to use the following config:
```toml
# tofscope.toml
[tofscope]
data_root = "/path/to/acquisitions"
output_root = "/path/to/saved-analyses"
port = 8765
```
You must explicitly pass `--config` when you start ToFScope:
```sh
tofscope --config tofscope.toml
```
Every TOML setting below also has an environment variable formed by uppercasing its name and adding `TOFSCOPE_`;
for example, `data_root` corresponds to `TOFSCOPE_DATA_ROOT`. Boolean environment variables accept `true` or `false`.
`trusted_proxies` is an array of strings in TOML and a comma-separated list in the environment. `TOF_FILE` is an
additional name for `initial_file` and takes precedence over `TOFSCOPE_INITIAL_FILE` when both are set. The repository's
[`tofscope.example.toml`](https://github.com/datasophos/ToFScope/blob/main/tofscope.example.toml) provides a starting
point for configuration.
For example, to use environment variables instead of a TOML file:
```sh
export TOFSCOPE_DATA_ROOT=/path/to/acquisitions
export TOFSCOPE_OUTPUT_ROOT=/path/to/saved-analyses
tofscope
```
These variables apply to the current shell and programs started from it. A command-line option such as
`--data-root /another/path` overrides the corresponding environment variable.
## Paths and networking
| Setting | Default | Purpose |
| --- | --- | --- |
| `data_root` | Current working directory | Root folder the file picker uses for acquisitions; must be accessible. CLI: `--data-root`. |
| `output_root` | `data_root` | Root folder for saved copies; its filesystem must support hard links. CLI: `--output-root`. |
| `runtime_dir` | `tofscope-` in the system temporary directory | Private runtime files for the local service. CLI: `--runtime-dir`. |
| `lock_dir` | `locks` inside `runtime_dir` | Writable directory for acquisition locks. CLI: `--lock-dir`. |
| `initial_file` | None | Acquisition to open at launch; its resolved path must be inside `data_root`. Also settable via `TOF_FILE`. |
| `host`, `port` | `127.0.0.1`, `8765` | Service bind address and port. CLI: `--host`, `--port`. Local mode requires a loopback host. |
| `mode` | `local` | `local` for desktop use or `proxy` for the experimental trusted-proxy setup. CLI: `--mode`. |
| `trusted_proxies` | Empty | Proxy peer IP addresses accepted in `proxy` mode; at least one is required in that mode. |
| `identity_header` | `x-tofscope-user` | Header containing the authenticated user identity in proxy mode. |
| `public_origin` | None | Public origin used for hosted access, such as `https://tofscope.example.org`. |
## Resource limits and lifecycle
Numeric values are positive integers. Byte limits govern managed arrays and response buffers, not total process or
browser memory; allow additional headroom.
| Setting | Default | Purpose |
| --- | --- | --- |
| `global_bytes` | `4294967296` (4 GiB) | Global managed-memory budget. |
| `user_bytes` | `2147483648` (2 GiB) | Managed-memory budget per user. |
| `analysis_bytes` | `1073741824` (1 GiB) | Managed-memory budget per analysis. |
| `response_bytes` | `33554432` (32 MiB) | Limit used for response and transport buffers. |
| `analyses_per_user`, `analyses_global` | `8`, `32` | Limits on open analyses per user and across the service. |
| `signals_per_analysis`, `signals_per_user`, `signals_global` | `129`, `512`, `2048` | Limits on signals per analysis, per user, and across the service. |
| `jobs_per_analysis`, `jobs_per_user`, `jobs_global` | `4`, `8`, `32` | Limits on active jobs per analysis, per user, and across the service. |
| `workers` | `2` | Number of background job worker threads. |
| `lease_seconds` | `45` | Lifetime of a browser-view lease without a heartbeat, in seconds. |
| `reconnect_seconds` | `120` | Time without a live view before the service closes the analysis's jobs, in seconds. |
| `idle_seconds` | `900` | Time without a live view before an analysis is closed, in seconds. |
The `allow_writes` and `allow_unverified_native` settings both default to `false`. They guard experimental native
acquisition writes; the supported **Save as…** workflow creates a separate copy instead.
## Inspect the effective configuration
The `tofscope doctor` command loads the configuration and verifies packaged frontend assets. The `--json` option prints the effective settings as JSON. It reports configuration and asset errors but does not diagnose every startup problem. The `/healthz` and `/readyz` endpoints provide service health checks.
## Deployment
Source: https://datasophos.github.io/ToFScope/docs/technical-documentation/deployment.html
These instructions cover local, server, and Docker deployments of ToFScope. Currently, only local deployment
is fully supported, but the server and Docker approaches are in *testing* status.
[Install and launch](../getting-started/installation.qmd) covers installation from PyPI and local setup.
## Local desktop
The following commands clone the ToFScope repository and install ToFScope from the checkout:
```sh
git clone https://github.com/datasophos/ToFScope.git
cd ToFScope
uv tool install .
```
The repository includes built frontend assets, so installation does not require Node or JavaScript tooling.
One Uvicorn API process serves React, chart scripts, scientific data, and downloads from one port. No CDN,
external account service, or runtime Node is used in local mode.
To install from PyPI instead of from source, you can use `uv tool install tofscope`.
The desktop launcher can be started with:
```sh
tofscope --data-root /path/to/acquisitions --output-root /path/to/saved-analyses
```
The default launch address is `http://127.0.0.1:8765`. If the acquisition folder contains no `.h5` files,
the file picker will show “No `.h5` files in this folder.” The acquisition folder defaults to the current
working directory if `--data-root` is not supplied; the saved copies folder defaults to whatever is set as
the acquisition folder unless `--output-root` is set (meaning the default for both is the current working directory
if neither are set. You can use the `TOF_FILE` environment variable to specify a file to open on first launch.
The path may be relative to `data-root` or absolute, but must resolve inside `data-root`.
### Local service without automatic browser launch
The `--no-browser` flag starts the service without opening a browser immediately,
for example when starting it from a script or using an API client. You can open its
local interface later from another terminal while the service is running:
```sh
tofscope serve --no-browser --data-root /path/to/acquisitions --runtime-dir /path/to/private/runtime
tofscope open --runtime-dir /path/to/private/runtime
```
The second command opens the running service on the same computer. A randomly generated launch secret
protects the local web server. The runtime folder and launch address should remain private. If you switch browsers or
access expires after 24 hours, the service needs to be restarted before it can be opened again.
## Self-hosted service
*Self-hosted, multi-user deployment is under development and will be documented
further when it is ready.*
## Configuration and storage
See the [configuration reference](configuration.qmd) for command-line options, environment variables, TOML settings,
and defaults. The `tofscope doctor` command checks configuration and packaged frontend assets; `/healthz` and `/readyz`
provide service health checks.
ToFScope supports one API process; analysis state is held in memory. Its managed
memory limits do not include all Python, HDF5, or browser memory, so the system needs extra memory headroom. Acquisition reads use a writable lock directory; processes accessing the
same files through ToFScope must share it.
## Docker container
> **Untested:** This container deployment workflow has not been verified end to end.
> Self-hosted authentication and proxy configuration are still under development.
The container serves ToFScope behind an authenticating reverse proxy. The image can be built from a clone of the repository using Docker and `uv`:
```sh
git clone https://github.com/datasophos/ToFScope.git
cd ToFScope
uv build
docker build -t tofscope .
```
The following example starts it with the acquisition folder mounted read-only and a persistent volume for saved analyses. The acquisition path, public URL, and proxy address are placeholders for your setup:
```sh
docker volume create tofscope-saved
docker run -d --name tofscope \
-p 127.0.0.1:8765:8765 \
--mount type=bind,src=/path/to/acquisitions,dst=/data,readonly \
--mount type=volume,src=tofscope-saved,dst=/saved \
-e TOFSCOPE_TRUSTED_PROXIES="" \
-e TOFSCOPE_PUBLIC_ORIGIN=https://tofscope.example.org \
tofscope
```
The `` value is the proxy's IP address **as seen by the container**; it may differ from the proxy's host address. The proxy must provide HTTPS, authenticate users, overwrite `X-ToFScope-User` with the authenticated username, and forward the original `Host` and `Origin` headers. The configured public URL opens the application in a browser. ToFScope grants authenticated users access to the mounted acquisition
folder; it does not manage accounts.
The `docker logs tofscope` command shows startup errors, and `docker stop tofscope` stops the service. The named volume preserves saved analyses when the container is
removed. Restarting discards unsaved work.
## NFS-backed acquisitions
NFS deployments have not been validated. An NFS mount requires testing with representative data and workloads, including concurrent reads and file replacement. Acquisition files should remain read-only, and processes should use a shared lock directory.
## Maintaining the documentation
Source: https://datasophos.github.io/ToFScope/docs/technical-documentation/documentation.html
The site is built with [Great Docs](https://posit-dev.github.io/great-docs/) and Quarto. Narrative pages live in the
directories under `docs/`; `docs/index.qmd` is the homepage. The root `index.qmd` is a symbolic link that lets Great
Docs find it (since it requires the index in the repo root). The root `great-docs.yml` configures branding and navigation.
Python API reference generation is disabled because ToFScope's internal modules are not intended as a public library interface.
## Building and previewing
From the repository root, the following commands install the regular dependencies together with the documentation
group and build the site:
```sh
uv sync --group docs
uv run great-docs build
```
For rapid editing, the local preview script watches documentation sources, rebuilds the site automatically,
and refreshes the browser after a successful build:
```sh
uv run scripts/preview_docs.py
```
The docs preview should open at `http://127.0.0.1:3000/`. The `--port` option selects another port,
and `--no-browser` starts the server without opening a tab. Pressing **Ctrl-C** stops the preview.
If a build fails, the script reports the error and waits for the next source change.
For a static preview of an existing build, `uv run --group docs great-docs preview` remains available. After a build,
`python scripts/check_docs.py great-docs/_site` can be used to check local links, anchors, and image paths.
The pinned version of Great Docs (*0.17.0*) uses a root-level `great-docs.yml`. Its generated Quarto project
is `great-docs/`, with the deployable site in `great-docs/_site/`. The pre-render hook `scripts/prepare_docs.py`
copies shared images into that generated project and creates narrative `llms.txt` and `llms-full.txt` exports.
This fills a gap in that release when API reference generation is disabled.
## Editing a page
Section pages use `.qmd` files with a `title` in their YAML frontmatter. Numeric filename prefixes control order;
Great Docs removes them from published URLs. Links between guide pages use the original prefixed filename,
such as `30-architecture.qmd`; Great Docs rewrites those links during the build.
Diagrams use `{mermaid}` code fences. Rendered diagrams should be inspected in the browser in both light and
dark modes to ensure they look okay. Shared screenshots and logos live in `docs/assets/` and can be referenced
from guide pages with `../assets/` paths.
### Interactive screenshots
Some user-guide screenshots link explanatory text to a highlighted area of the image. The page places an image and
empty, uniquely identified `explore-highlight` spans inside an `explore-overview` container using a raw HTML block.
Each span's `left`, `top`, `width`, and `height` are percentages of the image container. A regular Markdown link to
the span's ID scrolls to that area; `docs/styles.css` uses `:target` to draw the highlight.
For example, a guide can use this pattern:
~~~~markdown
[Open the control](#example-control).
```{=html}
```
~~~~
The numbered Explore overview in [Signals and views](../using-tofscope/signals-and-views.qmd) also overlays
`explore-marker` buttons on the image. These provide descriptions on hover or keyboard focus. Make sure to give
each button an accessible label and associate its tooltip with `aria-describedby`. When replacing an image,
update the percentage positions and check the links, highlights, and
tooltips at different viewport sizes and with keyboard navigation. Keep useful alt text and written instructions so the
guide does not depend on the image alone.
The source pages, assets, configuration, workflow, and dependency lockfile are committed to the repository.
Generated `great-docs/`, standalone HTML previews, and Quarto `*_files/` folders are ignored.
## Publishing
The Documentation workflow (`.github/workflows/docs.yml`) builds documentation previews on pull requests and builds and
deploys on merges or pushes to `main`. It uses the locked documentation dependencies and pinned Quarto version, and uploads
`great-docs/_site/` to GitHub Pages.
To activate publishing, a repository administrator must select **GitHub Actions** in
**Settings → Pages → Build and deployment → Source**. Once the workflow is merged and deployed, the site will be available
at . Local builds do not change repository settings or publish the site.
### Pull request previews
The Git-connected Cloudflare Pages project `tofscope-docs` builds branch previews separately from the GitHub Pages
production site. These builds are controlled by the workflow in `.github/workflows/cloudflare-previews.yml`. Its root
directory is the repository root, build command is `sh scripts/build_cloudflare_docs.sh`, and
output directory is `great-docs/_site`. Its build variables are `PYTHON_VERSION=3.12` and `SKIP_DEPENDENCY_INSTALL=1`.
The script installs documentation dependencies, checks local links, and adds a `noindex` header. Automatic Cloudflare
production deployments are disabled; GitHub Pages remains the canonical production site.
Preview builds watch `docs/*`, `great-docs.yml`, `index.qmd`, the documentation build and checking scripts,
`pyproject.toml`, and `uv.lock`. Cloudflare evaluates these paths for each push, so a code-only push to an existing
documentation pull request does not refresh the preview. Cloudflare attaches preview URLs to pull requests from
branches in the same repository; it does not automatically create them for pull requests from forks.
Cloudflare posts its `pages.dev` preview links directly to pull requests. When a pull request closes, the cleanup
workflow requests deletion of its branch's preview deployments, unless another open pull request uses that branch.
It runs on pull request events and every 15 minutes to retry cleanup. Cloudflare documents restrictions on deleting
the latest branch deployment; check the workflow if deletion is rejected. Preview URLs remain available until their
deployments are deleted. They are public and return a `noindex` header.
The cleanup workflow uses trusted code from the default branch, never code from a pull request, and requires
the GitHub Actions repository secret `CLOUDFLARE_PREVIEW_TOKEN` with account **Pages Write** permission.
The Cloudflare account and project are defined in `scripts/cloudflare_previews.py`; update them there if
the hosting account changes. To troubleshoot, inspect the Pages deployment and the cleanup workflow separately.
The workflow becomes active after it is merged into the default branch.
## File compatibility and limitations
Source: https://datasophos.github.io/ToFScope/docs/technical-documentation/file-compatibility.html
## Supported files and preparation
ToFScope reads acquisitions from the *TOFWERK* *TOFexplorer*[^trademark] software in the HDF5 (`.h5`) format.
These files may contain stored ion maps or raw events, depending on the analysis history in the vendor software.
For raw files without ion maps, the [preparation](../using-tofscope/raw-preparation.qmd) process creates
a new copy with integrated peak data while retaining raw events and metadata.
If the file has missing timing or channel metadata, it requires explicit acknowledgment of reconstruction assumptions.
## Saving files with ToFScope
ToFScope's [Save as](../using-tofscope/saving-and-exports.qmd) functionality stores the original acquisition,
committed analysis settings, and full-resolution custom results in a new HDF5 file. The original acquisition remains
unchanged. ToFScope restores its own analysis metadata, including signals and display settings, when the saved copy is
reopened.
## Using a ToFScope file in *TOFexplorer*1
ToFScope attempts to add eligible named signals as vendor peaks and reports any exclusions. Some saved copies have
opened in *TOFexplorer*1, but ToFScope analysis names and custom signals may
not appear in the vendor interface. ToFScope stores its analysis metadata separately, and the vendor software does not
necessarily interpret it.
For a signal made from disjoint mass intervals, vendor peak bounds may span the gaps between intervals. Those bounds do
not fully describe the signal; ToFScope retains the exact intervals in its analysis metadata.
::: {.callout-warning}
## Limits of compatibility
Opening a file in *TOFexplorer*1 does not necessarily mean that all metadata
is interchangeable or that the applications produce identical numerical results. ToFScope does not claim full
interoperability with *TOFexplorer*.
:::
## Current limitations
Live analyses are held in memory and do not survive a service restart unless the data is saved to disk.
Shared use requires a trusted authenticated proxy; self-hosted authentication and container deployment remain
under development, and NFS deployment has not yet been tested or qualified. The [deployment guide](deployment.qmd)
covers different hosted configurations.
3D rendering is qualitative and uses bounded display previews. The [3D guide](../using-tofscope/3d-visualization.qmd)
explains pooling, coverage, interpolation, and rendering limits. Profiles, measurements, and CSV exports use
original-resolution data.
[^trademark]: []{#trademark-notice}*TOFWERK* and *TOFexplorer* are names owned by [*TOFWERK AG*](https://www.tofwerk.com/). ToFScope is an independent project and is not affiliated with, endorsed by, or sponsored by *TOFWERK AG*.