Tutorial about rendering LocData#

from pathlib import Path

%matplotlib inline
# %matplotlib widget

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

import locan as lc
/tmp/ipykernel_1947/3690890720.py:7: DeprecationWarning: 
Pyarrow will become a required dependency of pandas in the next major release of pandas (pandas 3.0),
(to allow more performant data types, such as the Arrow string type, and better interoperability with other libraries)
but was not found to be installed on your system.
If this would cause problems for you,
please provide us feedback at https://github.com/pandas-dev/pandas/issues/54466
        
  import pandas as pd
lc.show_versions(system=False, dependencies=False, verbose=False)
Locan:
   version: 0.20.0.dev41+g755b969

Python:
   version: 3.11.6

Synthetic data#

Localizations are simulated that are distributed according to a Neyman-Scott distribution (blobs).

rng = np.random.default_rng(seed=1)
locdata = lc.simulate_Thomas(parent_intensity=1e-5, region=((0, 1000), (0, 1000)), cluster_mu=100, cluster_std=10, seed=rng)

locdata.print_summary()
Jupyter environment detected. Enabling Open3D WebVisualizer.
[Open3D INFO] WebRTC GUI backend enabled.
[Open3D INFO] WebRTCWindowSystem: HTTP handshake server disabled.
identifier: "1"
comment: ""
source: SIMULATION
state: RAW
element_count: 705
frame_count: 0
creation_time {
  2024-03-14T11:09:47.243568Z
}

Since localization data is kept as a pandas dataframe standard plotting routines from pandas or matplotlip can be used.

fig, ax = plt.subplots(nrows=1, ncols=1)
locdata.data.plot.scatter(x='position_x', y='position_y', ax=ax, color='Blue', label='locdata')
plt.show()
../../_images/f6cd3420c3f9e28086d3c7b4c2598b987bcfc61dce631722ce9831409bc2a04e.png

Render by simple 2D binning#

A method for simply binning localization data in 2D pixels is provided.

img, bins, label = lc.histogram(locdata, bin_size=10)

The intensity values of the binned locdata are distributed as:

plt.hist(img.ravel(), bins=256, range=(1, 50), fc='k', ec='k');
../../_images/bff16385fa2176c195fc0d1bad9239ffd298e979e79605d9d4a214224f0ceb31.png

The intensity values can be rescaled in many ways. There are normalization classes and a convenience function in the locan.render.transformation module with predefined transformations as listed in locan.Trafo:

list(lc.Trafo)
[<Trafo.NONE: 0>,
 <Trafo.STANDARDIZE: 1>,
 <Trafo.STANDARDIZE_UINT8: 2>,
 <Trafo.ZERO: 3>,
 <Trafo.ZERO_UINT8: 4>,
 <Trafo.EQUALIZE: 5>,
 <Trafo.EQUALIZE_UINT8: 6>,
 <Trafo.EQUALIZE_ALL: 7>,
 <Trafo.EQUALIZE_ALL_UINT8: 8>,
 <Trafo.EQUALIZE_0P3: 9>,
 <Trafo.EQUALIZE_0P3_UINT8: 10>,
 <Trafo.EQUALIZE_0P3_ALL: 11>,
 <Trafo.EQUALIZE_0P3_ALL_UINT8: 12>]
img_new = lc.adjust_contrast(img, rescale=lc.Trafo.STANDARDIZE)
epsilon = np.finfo(float).resolution
plt.hist(img_new.ravel(), bins=256, range=(epsilon, 1), fc='k', ec='k');
../../_images/beb964e3a4fa1a2ddf74ce0e6425898195564a45c282bb6649b13f0b1e9e4c0b.png
norm = lc.HistogramEqualization(power=1, mask=img>0)
img_new = norm(img)
plt.hist(img_new.ravel(), bins=256, range=(epsilon, 1), fc='k', ec='k');
../../_images/95740b867e06d8b842824903cd8a9dc5f185e3ab998538e267c2b45980e394d2.png

The render_2d method can directly provide a new figure as output.

lc.render_2d(locdata, bin_size=10);
../../_images/a3028d2f3d25335e3391b99824744ecd791d9a6cb53bb55130d662a79ba6630e.png

Or it can be used within the matplotlib environment.

fig, ax = plt.subplots(nrows=1, ncols=1)
lc.render_2d(locdata, ax = ax, bin_size=10, cmap='viridis')
plt.show()
../../_images/4ecd77f2b35b6533a500d1a0aa00628f0465c6062b9d14dce26af02bb9d92d05.png

Intensity is per default scaled to the min and max intensity values but can be rescaled by applying any norm function as described for matplotlib.imshow:

norm = plt.Normalize(vmax=10)
lc.render_2d(locdata, bin_size=10, norm=norm);
../../_images/dbf21bc9e61e44a33908bdbe02ce8e562aba5dbacc6f8269d773d28812c77c86.png

Intensity can also be rescaled by normalization functions as defined in locan.Trafo. Histogram equlization yields this image:

lc.render_2d(locdata, bin_size=10, rescale=lc.Trafo.EQUALIZE);
../../_images/11c594d9bfc21823fc6892ff914ef52fc607683f0ee765f50548c7c7c66366a5.png

Histogram equlization with a power-intensification of p=0.3 yields this image:

lc.render_2d(locdata, bin_size=10, rescale=lc.Trafo.EQUALIZE_0P3);
../../_images/2adaceec23fc059a3e84f660c9299939f5826a2d8dae867b26965cd85741b73c.png

Any callable normalization object can be passed into the rescale kwarg:

norm = lc.HistogramEqualization(power=0.3)
lc.render_2d(locdata, bin_size=10, rescale=norm);
../../_images/68cfae7c25052bf50023a8089b23a479cb0e89ccdde2a6328e34d9573815de4c.png

The image size is set automatically to the min and max coordinates but can be set to (0, max) or an arbitrary range.

lc.render_2d(locdata, bin_size=10, bin_range='zero');
../../_images/4099d038ddea8e282bcf7f8c49375a1b1e2be02056bb3ed6b08d6dea587511d2.png
lc.render_2d(locdata, bin_size=10, bin_range=((0, 300),(200, 500)));
../../_images/1ae604bce4add26d426caacda1a3877143d2a52c7f7c0a9d891346c9ed909ea3.png

Use different libraries for rendering#

Rendering can also be carried out with a different render engine. Choose one of the following (MPL is the standard matplotlib):

list(lc.RenderEngine)
[<RenderEngine.MPL: 0>,
 <RenderEngine.MPL_SCATTER_DENSITY: 1>,
 <RenderEngine.NAPARI: 2>]

napari#

As external viewer you can use napari.

For napari the qt gui interface has to be activated. Make sure to run the following command manually in a single cell and give enough time for this procedure to complete in the background.

or alternatively:

mpl-scatter-density#

For interactive viewing with variable binning, mpl-scatter-density is helpful. To run this the notebook has to be run with a new kernel applying the magic command %matplotlib widget before matplotib is imported.

lc.render_2d(locdata, render_engine=lc.RenderEngine.MPL_SCATTER_DENSITY);
/home/docs/checkouts/readthedocs.org/user_builds/locan/envs/latest/lib/python3.11/site-packages/mpl_scatter_density/generic_density_artist.py:77: RuntimeWarning: All-NaN slice encountered
  vmin = self._density_vmin(array)
/home/docs/checkouts/readthedocs.org/user_builds/locan/envs/latest/lib/python3.11/site-packages/mpl_scatter_density/generic_density_artist.py:82: RuntimeWarning: All-NaN slice encountered
  vmax = self._density_vmax(array)
../../_images/ca4482f7cda9854ce1bcba74396762d1e1029f7b08e75022a2a0023d2a6191d7.png

Choose colormaps#

Colormaps can be chosen in matplotlib, napari and other visualization tools.

Colormaps are identified through specific class instances or by a name.

locan.Colormap serves as adapter class for the various visualization tools.

A Colormap instance can be created with the get_colormap function:

colormap = lc.get_colormap("viridis")
colormap.name
'viridis'
colormap.matplotlib
viridis
viridis colormap
under
bad
over

A mapping of names on Colormap instances is provided and can be extended by users. If a colormap name is provided to any rendering function, first the colormap_registry is searched, then the maplotlib registry and finally napari colormap names.

lc.colormap_registry
{'viridis': <locan.visualize.colormap.Colormap at 0x7f4028ed7750>,
 'viridis_r': <locan.visualize.colormap.Colormap at 0x7f4028df7d90>,
 'gray': <locan.visualize.colormap.Colormap at 0x7f4028df7d50>,
 'gray_r': <locan.visualize.colormap.Colormap at 0x7f4027feab10>,
 'turbo': <locan.visualize.colormap.Colormap at 0x7f4027feb190>,
 'coolwarm': <locan.visualize.colormap.Colormap at 0x7f4027feacd0>,
 'tab20': <locan.visualize.colormap.Colormap at 0x7f4027fead90>,
 'cet_fire': <locan.visualize.colormap.Colormap at 0x7f4027feae90>,
 'cet_fire_r': <locan.visualize.colormap.Colormap at 0x7f4027feaf50>,
 'cet_gray': <locan.visualize.colormap.Colormap at 0x7f4027feb010>,
 'cet_gray_r': <locan.visualize.colormap.Colormap at 0x7f4027feb0d0>,
 'cet_coolwarm': <locan.visualize.colormap.Colormap at 0x7f4027feb250>,
 'cet_glasbey_dark': <locan.visualize.colormap.Colormap at 0x7f4027feb310>}

Default colormaps are defined for use with locan and can be accessed through a mapping or an enum:

lc.COLORMAP_DEFAULTS
{'CONTINUOUS': 'cet_fire',
 'CONTINUOUS_REVERSE': 'cet_fire_r',
 'CONTINUOUS_GRAY': 'cet_gray',
 'CONTINUOUS_GRAY_REVERSE': 'cet_gray_r',
 'DIVERGING': 'cet_coolwarm',
 'CATEGORICAL': 'cet_glasbey_dark',
 'TURBO': 'turbo'}
list(lc.Colormaps)
[<Colormaps.CONTINUOUS: 'cet_fire'>,
 <Colormaps.CONTINUOUS_REVERSE: 'cet_fire_r'>,
 <Colormaps.CONTINUOUS_GRAY: 'cet_gray'>,
 <Colormaps.CONTINUOUS_GRAY_REVERSE: 'cet_gray_r'>,
 <Colormaps.DIVERGING: 'cet_coolwarm'>,
 <Colormaps.CATEGORICAL: 'cet_glasbey_dark'>,
 <Colormaps.TURBO: 'turbo'>]
lc.render_2d(locdata, bin_size=10, cmap=lc.Colormaps.CONTINUOUS_GRAY_REVERSE);
../../_images/eb3eb2d6ccb92b6ee37b4b1819448351790746d9eb96decc81e678a2b7575808.png