PICASSO 3-color example
=======================
This tutorial documents the interactive script
``user_scripts/unmix_picasso_3color_example.py``.
It is the most direct comparison point between:
- the original 3-channel MATLAB PICASSO workflow,
- the explicit N-channel generalization,
- and the source-sink formulation.
The PICASSO-family methods documented here are motivated by the original
PICASSO paper:
Seo, J., Sim, Y., Kim, J. et al. *PICASSO allows ultra-multiplexed
fluorescence imaging of spatially overlapping proteins without reference
spectra measurements*. Nature Communications 13, 2475 (2022).
https://doi.org/10.1038/s41467-022-30168-z
How to use this tutorial
------------------------
The script is designed for interactive execution.
The recommended workflow is:
1. open ``user_scripts/unmix_picasso_3color_example.py``,
2. inspect the measured channels first,
3. compare the three different blind-unmixing implementations on the same
stack.
The subsections below follow the same order as the script.
Imports
-------
.. literalinclude:: ../../user_scripts/unmix_picasso_3color_example.py
:language: python
:start-after: # %% IMPORTS
:end-before: # %% INPUT AND OUTPUT PATHS
Define input and output paths
-----------------------------
.. literalinclude:: ../../user_scripts/unmix_picasso_3color_example.py
:language: python
:start-after: # define the input path to the example dataset:
:end-before: # %% INSPECT PREPARED STACKS IN NAPARI
Inspect the measured channels
-----------------------------
.. literalinclude:: ../../user_scripts/unmix_picasso_3color_example.py
:language: python
:start-after: # inspect the stack in Napari:
:end-before: # %% PICASSO MATLAB-N EXAMPLE
Before any unmixing is applied, the script opens the measured stack in napari.
This is useful for confirming channel order and for building intuition about
which channels appear to contaminate which others.
.. raw:: html
.. figure:: _static/picasso_3c_raw.jpg
:alt: Raw composite view of the three-channel stack.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_raw_ch0.jpg
:alt: Channel 0 of the raw three-channel stack.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_raw_ch1.jpg
:alt: Channel 1 of the raw three-channel stack.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_raw_ch2.jpg
:alt: Channel 2 of the raw three-channel stack.
:align: center
:figwidth: 100%
.. raw:: html
Composite view of the raw three-channel stack (top). Channel 0
is shown in cyan (top center), Channel 1 in magenta (bottom center), and Channel 2
in yellow (bottom). The channels are clearly contaminated by each other.
``matlab_n`` blind unmixing
---------------------------
.. literalinclude:: ../../user_scripts/unmix_picasso_3color_example.py
:language: python
:start-after: # define the output path for the PICASSO MATLAB-N unmixing result:
:end-before: # %% PICASSO MATLAB-3C EXAMPLE
This method keeps the MATLAB-style iterative logic, but uses the generalized
``matlab_n`` implementation rather than the strict 3-channel port.
The settings that matter most are:
- ``channels``:
selects which measured channels participate in the blind-unmixing run.
- ``implementation="matlab_n"``:
chooses the generalized MATLAB-style path rather than the strict
three-channel port.
- ``background_percentile``:
low-percentile background estimate used during preprocessing before the
update sequence is estimated.
- ``preprocess_alpha_inputs``:
enables or disables that shared preprocessing step.
- ``mi_bins``:
retained in the shared API and JSON report for compatibility, but not used by
the MATLAB-like implementation itself.
- ``alpha_max``:
likewise retained in the shared API and JSON report, but not used directly by
the MATLAB-like implementation.
- ``max_iter``:
number of iterative updates. More iterations can unmix more strongly but may
also become less stable.
- ``tolerance``:
convergence threshold for the iterative update sequence.
- ``max_alpha_voxels``:
optional voxel cap for large stacks. Lower values speed up the run; higher
values use more of the measured image data.
- ``step_size``:
strength of each update step. Larger values are more aggressive; smaller
values are more conservative.
- ``qN``:
quantization parameter for the MATLAB-style mutual-information estimate.
- ``pixel_bin_size``:
spatial binning factor before the mutual-information calculation. Larger
values smooth more strongly; smaller values preserve more detail.
- ``alpha_clip``:
clipping bound for pairwise coefficients. Larger values allow stronger
pairwise subtraction.
- optional ``negativity_threshold`` and ``clip_every_n_iterations``:
control how intermediate negativity is monitored and how often positivity
enforcement is applied.
- ``random_state``:
random seed used whenever voxel subsampling is needed.
- ``clip_negative``:
clips final negative values in the written output to zero.
- ``output_dtype``:
controls the saved data type of the unmixed stack.
- ``verbose``:
enables terminal progress output during the run.
- ``alpha_mode`` and ``alpha_reference_t``:
become relevant for real multi-time-point stacks. ``reference_t`` estimates
one update sequence from one chosen time point; ``per_t`` estimates one
sequence per time point.
This is the best choice when you want MATLAB-like behavior but also want the
same conceptual workflow to scale to larger channel counts.
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlabn.jpg
:alt: Composite view of the unmixed three-channel stack after the MATLAB-N blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlabn_ch0.jpg
:alt: Channel 0 of the unmixed three-channel stack after the MATLAB-N blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlabn_ch1.jpg
:alt: Channel 1 of the unmixed three-channel stack after the MATLAB-N blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlabn_ch2.jpg
:alt: Channel 2 of the unmixed three-channel stack after the MATLAB-N blind-unmixing run.
:align: center
:figwidth: 100%
Composite view of the unmixed three-channel stack after the MATLAB-N blind-unmixing
run (top). The MATLAB-N implementation has successfully removed most of the cross-talk
between the channels, which are now cleanly separated.
``matlab_3c`` blind unmixing
----------------------------
.. literalinclude:: ../../user_scripts/unmix_picasso_3color_example.py
:language: python
:start-after: # define the output path for the PICASSO MATLAB-3C unmixing result:
:end-before: # %% PICASSO SOURCE-SINK-N EXAMPLE
This is the closest available Python analogue of the original MATLAB
three-channel workflow.
Use this mode when exact three-channel comparison to the classic PICASSO logic
is more important than having a unified N-channel code path.
The main settings remain the MATLAB-style iteration parameters:
- ``channels``:
same role as above, but here exactly three selected channels are required.
- ``implementation="matlab_3c"``
- ``background_percentile``
- ``preprocess_alpha_inputs``
- ``mi_bins`` and ``alpha_max``:
same shared API parameters as above; recorded but not used directly by the
MATLAB-like implementation
- ``max_iter``
- ``tolerance``
- ``max_alpha_voxels``
- ``step_size``
- ``qN``
- ``pixel_bin_size``
- ``alpha_clip``
- optional ``negativity_threshold`` and ``clip_every_n_iterations``
- ``random_state``
- ``clip_negative``
- ``output_dtype``
- ``verbose``
- ``alpha_mode`` and ``alpha_reference_t`` for multi-time-point stacks:
same behavior as in the ``matlab_n`` example above
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlab3c.jpg
:alt: Composite view of the unmixed three-channel stack after the MATLAB-3C blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlab3c_ch0.jpg
:alt: Channel 0 of the unmixed three-channel stack after the MATLAB-3C blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlab3c_ch1.jpg
:alt: Channel 1 of the unmixed three-channel stack after the MATLAB-3C blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_matlab3c_ch2.jpg
:alt: Channel 2 of the unmixed three-channel stack after the MATLAB-3C blind-unmixing run.
:align: center
:figwidth: 100%
Also the MATLAB-3C implementation has successfully removed most of the cross-talk
between the channels, which are now cleanly separated. The results are very similar
to the MATLAB-N run above. In fact, the latter is a generalized version of the former,
so the results are expected to be nearly identical.
``source_sink_n`` blind unmixing
--------------------------------
.. literalinclude:: ../../user_scripts/unmix_picasso_3color_example.py
:language: python
:start-after: # define the output path for the PICASSO source-sink-N unmixing result:
:end-before: # %% END
This variant uses an explicit source-sink description of the expected bleed-
through graph.
In the current implementation, all sources contributing to one sink are
optimized jointly by default, and the workflow can additionally estimate a
small background offset for each modeled source-sink relation. This brings the
method closer to the source-sink formulation used by the napari PICASSO plugin,
while still relying on histogram-based mutual information rather than the
plugin's neural MINE estimator.
The most relevant settings are:
- ``channels``:
as above, selects which measured channels participate in the explicit
source-sink run.
- ``implementation="source_sink_n"``:
chooses the source-sink PICASSO-family workflow rather than the MATLAB-like
implementations.
- ``sink_channels``:
defines which channels should be corrected as sinks.
- ``neutral_channels``:
defines which channels should remain untouched and not act as sinks.
- optional ``source_sink_matrix``:
gives explicit manual control over the allowed bleed-through graph.
- ``background_percentile``:
same role as above, but now used in source-sink coefficient estimation.
- ``preprocess_alpha_inputs``:
same shared preprocessing switch as above.
- ``alpha_max``:
now actively used as the upper bound for source-to-sink coefficients.
- ``mi_bins``:
now actively used as the histogram resolution for the mutual-information
objective.
- ``max_iter``:
controls the maximum number of optimizer iterations for each sink.
- ``tolerance``:
stopping tolerance for the numerical optimizer.
- ``max_alpha_voxels``:
same optional voxel cap as above.
- ``source_sink_optimize_background``:
if enabled, estimate one small background offset ``beta`` per modeled
source-sink relation before subtracting the source contribution.
- ``source_sink_max_background``:
upper bound for these optimized background offsets on normalized intensities.
- ``source_sink_joint_optimization``:
if enabled, optimize all sources contributing to the same sink together
instead of fitting them greedily one after another.
- ``source_sink_n_restarts``:
number of multi-start optimizer initializations used for each sink.
- ``random_state``:
same random seed used for optional voxel subsampling.
- ``clip_negative``:
same final clipping behavior as above.
- ``output_dtype``:
same output dtype control as above.
- ``verbose``:
same terminal verbosity control as above.
- ``alpha_mode`` and ``alpha_reference_t``:
same time-axis controls as above for real multi-time-point stacks.
This is often the easiest mode to reason about biologically, because the user
can describe which channels should actually be cleaned and which channels
should remain untouched or act only as sources. In the specific example script,
``channel 1`` is treated as the sink, while ``channel 0`` and ``channel 2``
are allowed to act as sources by default. If only the
``channel 0 \rightarrow channel 1`` relation should be modeled, ``channel 2``
can be moved into ``neutral_channels``.
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_sinkn.jpg
:alt: Composite view of the unmixed three-channel stack after the source-sink-N blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_sinkn_ch0.jpg
:alt: Channel 0 of the unmixed three-channel stack after the source-sink-N blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_sinkn_ch1.jpg
:alt: Channel 1 of the unmixed three-channel stack after the source-sink-N blind-unmixing run.
:align: center
:figwidth: 100%
.. raw:: html
.. figure:: _static/picasso_3c_unmixed_sinkn_ch2.jpg
:alt: Channel 2 of the unmixed three-channel stack after the source-sink-N blind-unmixing run.
:align: center
:figwidth: 100%
By setting the sink-channel equal to all channels, the source-sink-N implementation has
successfully removed most of the cross-talk. This is just because we, by doing so, have allowed
the algorithm to model all possible pairwise relations. The results are very similar to the
MATLAB-N and MATLAB-3C runs above. However, the power of the source-sink-N implementation is
its ability to restrict the modeled relations to only those that are biologically relevant.
For highly multiplexed experiments, allowing all-to-all relations here may lead to
less satisfactory results and other methods such as ``matlab_n`` should be preferred.