Releases: DrCytometer/AutoSpectral
Release list
Version 1.6.0
AutoSpectral 1.6.0 (2026-06-01)
New Features
- Automated spectral profile extraction using approaches developed by Nathan
Laniewski inflowState. This simplifies the workflow considerably, and
eliminates the need for gating, which was a key cause of stress. The new
automated approach employs projection orthogonalization to determine the peak
channel (which way is the control going that isn't like the autofluorescence?),
and uses cosine filtering (which events are least contaminated by AF?) to find
the clean spectral signatures. - New joint unmixing pipeline (
unmix.autospectral.joint()), implemented in C++,
using covariance-weighted spillover and residual alignment to solve autofluorescence
and fluorophore assignment together rather than sequentially. Structurally collinear
fluorophore pairs (e.g., APC/BUV661) are handled via joint-pair conflict resolution
so genuine double-positive signal isn't suppressed. Seven new tuning parameters
(n.af.passes,cell.weight,noise.floor,alpha,collinear.threshold,
joint.pair.resolution,refine.af.quantile) are now wired through both
unmix.fcs()andunmix.folder(). calculate.optimize.necessity()to determine which cells actually require
per-cell fluorophore optimization, avoiding unnecessary computation.- Multipass autofluorescence refinement using a matching-pursuit approach, with
fixed pass-1 baseline denominators to prevent noise from dominating the
highest-abundance cells in later passes. simulate.flow.data()generates synthetic ground-truth data by summing
single-stained controls, providing a benchmark for false-negative rates on
double-positive populations.- New AF autofluorescence comparison and benchmarking functions for evaluating
accuracy against ground truth. - A merging of the approaches for per-cell autofluorescence assignment using the
covariance structure:assign.af.joint.cov()to assess how autofluorescence
variation impacts fluorophore values, with joint scoring of residuals. This
improves on the existing residual- and projection-based AF assignment methods. - Extension of the variance-covariance error propagation plus residuals scoring
metric to per-cell fluorophore optimization. This avoids the previous need to
optimize in the reduced space of only positive fluorophores in each cell, which
was responsible for discontinuities appearing in several data sets around zero. - Legacy mode support. All pre-existing workflows remain intact, but some must
be accessed via alegacyargument in the function calls. - AutoSpectral landing page. Type
?AutoSpectralin your IDE to open a workflow
overview with links to key functions and articles. - FCS 3.1 compliance. Modified FCS files now carry the
$ORIGINALITY,
$LAST_MODIFIER, and$LAST_MODIFIEDkeywords per the FCS 3.1 standard.
Improvements
- C++ accelerated FCS reading and writing via
AutoSpectralRcpp. Adapted from
work by Samuel Granjeaud. - Much faster plotting throughout, using a combination of point downsampling,
raster rendering (ragg/scattermore), and C++ acceleration when
AutoSpectralRcppis available. - Faster variant and AF spectra determination via
EmbedSOMwhen
AutoSpectralRcppis installed. viridisadded as a dependency for improved colour scaling in density plots.- Support for
patchworkto allow manual faceting and combination of plots. - Spectral reference library updated with additional entries.
- Scatter-matching via k-nearest neighbours for higher precision.
- Cosine filtering of unstained samples against the fluorophore spectral profiles
to reduce potential errors when the "unstained" isn't actually completely
unstained. - Cosine filtering and kNN background matching for
get.spectra.variants()to
reduce undesireable influence of autofluorescence. - Non-negative clamping of spectral profiles to prevent artefactual negative
spectral values propagating into unmixing. - Type-checking and validation added at function entry (e.g.,
get.spectral.variants()) to guard against deprecated positional arguments
silently corrupting subsequent parameters, with explicit error messages. - Cell weighting is now enabled by default for the ID7000, and detection
thresholds have been relaxed for this platform. NAMESPACEinjection for optional dependencies (AutoSpectralRcpp,EmbedSOM)
replaced withrequireNamespace()calls for a safer, more portable pattern.- Removed the
cairoandmethodspackage dependencies. - Defensive
tryCatchwrapping around plotting calls, and guards against
unintended matrix-to-vector dropping. - Guards added for low cell count edge cases to prevent dimension errors.
- General function and code cleanup throughout.
Bug fixes
- Keywords issue causing files from BD instruments to occasionally emit scrambled
data should now be fixed. Only whitelisted channels are preserved from the
input raw FCS files. - Fixed handling of negative autofluorescence spectra in normalization and plotting.
- Fixed hexbin rendering in N x N plots.
- Fixed a typo (
applyshould have beenlapply). - Various fixes to get
unmix.fcs()passing its test suite again.
Version 1.5.7: patch for gating failure
Version 1.5.7 patches an issue that arises when users skip the recommended pre-gating steps, proceed directly to define.flow.control and include mismatched samples in the control file where one or more samples do not have any events in the auto-assigned gates. The patch is simply a warning to check the likely cause, which does not fix the underlying issue, but prevents an outright failure.
More fluorophores have been added to the database.
v1.5.6
Some new plotting features in version 1.5.6:
- M x N and N x N plotting of unmixed data using unmixed.mxn.plot() and
unmixed.nxn.plot() - Calculate the secondary stain index per "Evaluating the performance of Slingshot
- SpectraComp particles as universal single stain controls in flow cytometry" by
Oliveira et al. Call calculate.ssi(). - Plot the mismatch between two spectral profiles (e.g., beads vs. cells) as in
the pre-print by Konecny et al. on unmixing-dependent spread. Call spectral.mismatch.plot(). - Compare unmixing of the same data side-by-side with two different spectral mixing
matrices. Call compare.unmix().
See the New Features discussion for more detail.
Version 1.5.0: Gating improvements
Version 1.5.0 provides a new gating approach and more control over the gating process. It speeds up some of the slower points in the pipeline by using AutoSpectralRcpp in the background if that is installed. You get additional quality control checking on fluorophore and autofluorescence profiles.
- New gating approach adapted from
flowstate. This uses cellular landmarks to
identify the position of key populations on forward and side-scatter. Essentially,
we backgate. This means that you can use well-expressed markers on known cell
populations (think CD3, CD19, CD14) to define the location of your cells. This is
fast, appears to be pretty robust, and should be easy for you, the user, to change
how it works. Control over this is provided via the CSV control file spreadsheet
using two new columns: "gate.name" to define which controls should share the same
gate, and "gate.define" (TRUE/FALSE) to specify which samples should be used to
define the gate boundaries (e.g., we might use CD4 but not TIM-3 or IL-4). - To assist with the new gating, there is a
tune.gate()function that allows
you to put in a range of parameters to quickly see the impact on the gate boundary
prior to runningdefine.flow.control(). - Native, faster FCS read/write functionality adapted from
flowstate. - FCS file concatenation via
concatenateFCS(). - Faster gating by reducing
MASS::kde2dcalls and allowing C++ kernel density
estimation ifAutoSpectralRcppis installed. - Faster plotting along the same lines.
- Hopefully graceful error handling during
clean.controls(). - Hopefully graceful error handling with diagnostic plotting during gate definition,
both with the gate.define functions and directly indefine.flow.control(). - Success/failure reporting from
clean.controls(). - Reduced memory usage when unmixing.
- Chunking of files when unmixing to support unmixing of any size of file.
- Spectral signature QC when running
get.fluorophore.spectra(). - Autofluorescence profile QC when running
get.af.spectra(). - Faster processing in
get.af.spectra()through integration ofAutoSpectralRcpp,
when available. - Additional checks on FCS files when setting up and unmixing: consistency in the
spectral channels used for unmixing, both in the names and the voltages/gains.
Version 1.0.2: better memory management
Some small improvements to reduce spikes in memory usage while unmixing FCS files. To be improved further later.
Version 1.0.0: Faster unmixing
- Version 1.0.0 brings a revamp to how AutoSpectral identifies the best spectra on a per-cell basis. The theory behind it remains the same--we are still trying to identify the variation in the autofluorescence and fluorophores that best reduces the residual on a per-cell basis. Now, however, we do not need to do that using brute force. Instead, we can search only through variants (or autofluorescences) that align with a given cell's residual. Thus we can pre-screen the variants to a select few and then test just those. This means we can figure out the solution in way less time. It also means that a native R implementation of the algorithm is possible in R in a somewhat reasonable time frame. So, that may help for anyone struggling to use the fast C++ version in
AutoSpectralRcpp. - Since we can now quickly identify which variants are useful for a given cell, we can test more variants, allowing a finer-grained view of the variation, which may improve unmixing quality.
- Autofluorescence extraction and fluorophore variation extraction are now modified to allow searching for more variation, focusing on "problematic" cells that remain far from where they should be when the first batch of variation is applied. This is most helpful for extracting autofluorescence in complex tissue samples, where AutoSpectral previously struggled to deal with the last few messy cells. Use "refine = TRUE" for this.
- Speed in unmixing should be the biggest change, particularly if you run using
AutoSpectralRcpp. - When extracting autofluorescence using
get.af.spectra()with "refine = TRUE", you will now get a set of plots showing you the unmixed data for the channels most affected by the autofluorescence ("worst channels"). The same channels will be plotted after a single round of autofluorescence extraction per cell (as in AutoSpectral v0.9.2 and earlier) as well as after the second round, using data from more difficult
cells. To see this, run withrefine = TRUE. - Autofluorescence is now assigned to each cell using a shortcut to "project" where the AF will impact on fluorophore or residual space. This is especially fast for residual-based assignment.
- Perhaps most importantly, discontinuities that sometimes appeared in the data after unmixing using per-cell-fluorophore optimization, particularly with the "fast" approximation, should now be gone or at least greatly diminished.
Version 0.9.0: A bit faster
Version 0.9.0 implements a few modest changes to speed up the unmixing and general processing. Benchmarking suggests this can be about 2x faster.
The underlying parallelization now operates differently and enables switching depending on the type of operating system you're working on. Several bugs have been patched, including things affecting the reading of Opteon FCS files and processing of certain control:negative pairings in get.spectral.variants(). More checks have now been implemented in check.control.file() to counteract issues I hadn't considered.
New features include:
- Unmixing matrix can be saved via save.unmixing.matrix()
- Weights can be calculated via calculate.weights()
- Plotting of unmixing matrix in get.fluorophore.spectra
See the NEWS for more details.
Version 0.8.7: Support for A5SE and Cytek Northern Lights
Version 0.8.7 provides support for the BD FACSymphony A5SE spectral flow cytometer. Call get.autospectral.param( cytometer = "a5se" ). It also provides more explicit support for the 3-laser (violet, blue, red) Northern Lights version of the Cytek Aurora (get.autospectral.param( cytometer = "auroraNL" ).
New features include automatic plotting of the unmixing and hotspot matrices when get.fluorophore.spectra() is called.
There is a Shiny helper app to assist in the creation of the control files required to set up AutoSpectral runs. For this, visit: https://github.com/DrCytometer/AutoSpectralHelper
Finally, the weighting for unmixing Discover A8 and S8 files has been changed to fall in line with other cytometers and will no longer rely on QSPE values.
Version 0.8.6: improvements to plotting
Version 0.8.6 fixes issues with the plotting. It also allows more user control over the plotting using color palettes and gives more access to the plotting functions. spectral.ribbon.plot() should now be usable for any data you'd like.
Some issues that should be fixed:
-messy density/pseudocolor plots of the gates
-gaps in the spectral ribbon plots
-more control over the biexponential transform in create.biplot
Other changes:
-parallel arguments are now provided, rather than relying on asp$parallel
-several unused functions have been removed
-fluorophore matching for the creation of the control file should work better now
That should be the main stuff. There shouldn't be any changes in how the data are processed at present.
v0.8.5
This version has been tested for the basic workflow on simple datasets from all supported cytometers.