# 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. ![The raw acquisition preparation dialog shows the proposed filename, required disk space, and preparation options.](../assets/tofscope-raw-preparation.png) ## 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}
The 3D volume view with two signals overlaid, a signal list and view and camera controls on the left, and a volume preview on the right.
Two signals are shown as an overlay in the 3D volume view.
``` ```{=html}
Settings for an aluminum signal, including colormap, opacity, and intensity threshold controls.
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}
Expanded 3D display settings with independent or shared intensity scale, log colors, and frame stretch.
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 Explore workspace, with viewing-depth and depth-calibration controls above the plots.
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}
Depth calibration editor with a profile, a frame 390 anchor at 1200 nm, and an anchor table.
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}
The Explore workspace, with identification controls above the mass spectrum.
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}
Atomic identification dialog with measured m/z, search settings, a spectrum, isotope candidates, and signal actions.
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}
Isotope measurements dialog showing two selected signals, their summed intensities and percentage shares, and the measurement region and frame range.
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}
Raw acquisition preparation preview with the number of windows and frames, required space, prepared filename, destination, and Prepare and open button.
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}
The Explore workspace, with Save as in the upper right and export controls on the plots.
Save the analysis from the header, or export individual views from their plot controls.
``` ```{=html}
Save a copy dialog showing the save folder and destination, a Choose folder button, a filename field, and a Save copy button.
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 dialog shows Copy saved, the saved filename, and a Download copy link.
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}
The Explore workspace, with six numbered controls and plots described below.
``` 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 New signal editor beside the mass spectrum. It shows a name, mass interval, frame range, and Calculate signal button; the interval is also marked on the spectrum.
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}
Three depth profiles, each scaled to its own maximum, with weaker signals and their noise visible.
Relative profiles on: each curve is scaled to its own maximum.
The same three depth profiles on a shared mean-intensity scale; the weaker curves lie close to zero.
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}
Description of the interface.
``` ~~~~ 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*.