|
1 | 1 | import numpy as np |
2 | 2 | import matplotlib.pyplot as plt |
3 | 3 |
|
| 4 | +from scipy.ndimage import gaussian_filter |
| 5 | + |
| 6 | +from matplotlib.cm import ScalarMappable |
4 | 7 | from matplotlib.ticker import AutoLocator |
5 | 8 | from matplotlib.colorbar import ColorbarBase |
6 | | -from matplotlib.colors import ListedColormap, NoNorm |
| 9 | +from matplotlib.colors import ListedColormap, Normalize, NoNorm |
7 | 10 |
|
8 | 11 |
|
9 | | -def chromosome_viewer(chrom_lengths, |
| 12 | +def chromosome_viewer(chrom_lengths, |
10 | 13 | colors=None, |
11 | 14 | height=0.5, |
12 | 15 | width=10.): |
13 | 16 | """ |
14 | | - Simple matplotlib-based visualization of individual chromosomes |
| 17 | + Simple matplotlib-based visualization of individual chromosomes |
15 | 18 | |
16 | 19 | Parameters |
17 | 20 | ---------- |
18 | 21 | chrom_lengths : Cx1 int array |
19 | 22 | List of the sizes of each chromosome |
20 | 23 | colors : Nx4 float array or None |
21 | | - Colors to be assigned to each monomer. |
22 | | - If omitted, random colors will be attributed to each chromosome |
| 24 | + Colors to be assigned to each monomer. |
| 25 | + If omitted, random colors will be attributed to each chromosome |
23 | 26 | height : float |
24 | 27 | Per-chromosome height of the output figure (in inches) |
25 | 28 | width : float |
@@ -63,3 +66,90 @@ def chromosome_viewer(chrom_lengths, |
63 | 66 | cb.update_ticks() |
64 | 67 |
|
65 | 68 | plt.show() |
| 69 | + |
| 70 | + |
| 71 | +def rasterize(positions, |
| 72 | + box_size, |
| 73 | + resolution=100, |
| 74 | + length_unit=50, |
| 75 | + gaussian_width=250): |
| 76 | + """ |
| 77 | + 3D positions rasterizer for numerical microscopy analysis |
| 78 | + |
| 79 | + Parameters |
| 80 | + ---------- |
| 81 | + positions : Nx3 float array |
| 82 | + List of X,Y,Z particle positions to be rasterize. |
| 83 | + Assumes particle coordinates are wrapped in PBCs within the range [-box_size/2,+box_size/2] |
| 84 | + box_size : float |
| 85 | + Linear dimension of periodic box |
| 86 | + resolution : float |
| 87 | + Linear dimension of output voxels (in nm) |
| 88 | + length_unit : float |
| 89 | + Model unit of length (in nm) |
| 90 | + gaussian_width : float |
| 91 | + Width of Gaussian point-spread function to be used. |
| 92 | + If gaussian_width<=0, returns the raw (undiffracted) raster |
| 93 | + """ |
| 94 | + |
| 95 | + n_voxels = int(box_size / (resolution/length_unit)) |
| 96 | + bins = np.linspace(-box_size/2., box_size/2., num=n_voxels+1) |
| 97 | + |
| 98 | + digitized_x = np.digitize(positions[:,0], bins) - 1 |
| 99 | + digitized_y = np.digitize(positions[:,1], bins) - 1 |
| 100 | + digitized_z = np.digitize(positions[:,2], bins) - 1 |
| 101 | + |
| 102 | + digitized = digitized_x + digitized_y*n_voxels + digitized_z*n_voxels**2 |
| 103 | + bincounts = np.bincount(digitized, minlength=n_voxels**3) |
| 104 | + |
| 105 | + raster = bincounts.reshape((n_voxels,n_voxels,n_voxels)) |
| 106 | + |
| 107 | + if gaussian_width > 0: |
| 108 | + smoothed_raster = gaussian_filter(raster/raster.max(), sigma=gaussian_width/resolution, mode='wrap') |
| 109 | + |
| 110 | + return smoothed_raster |
| 111 | + |
| 112 | + return raster/raster.max() |
| 113 | + |
| 114 | + |
| 115 | +def raster_map_2D(raster, |
| 116 | + cmap, |
| 117 | + vmin=None, |
| 118 | + vmax=None, |
| 119 | + mode='max', |
| 120 | + axis=2): |
| 121 | + """ |
| 122 | + RGB mapping of 2D raster projection |
| 123 | + |
| 124 | + Parameters |
| 125 | + ---------- |
| 126 | + raster : Mx3 float array |
| 127 | + 3D normalized raster to visualize. |
| 128 | + cmap : matplotlib colormap object or str |
| 129 | + Colormap to be used |
| 130 | + vmin, vmax : float or None |
| 131 | + Color dynamic range. |
| 132 | + If set to None, use full data range |
| 133 | + mode : str |
| 134 | + Projection mode to be used. |
| 135 | + Set to either 'max' for maximum intensity or 'sum' for summed intensity projection |
| 136 | + axis : int |
| 137 | + Index of projection axis |
| 138 | + """ |
| 139 | + |
| 140 | + if mode == 'max': |
| 141 | + raster_2D = raster.max(axis=axis) |
| 142 | + elif mode == 'sum': |
| 143 | + raster_2D = raster.sum(axis=axis) |
| 144 | + else: |
| 145 | + raise RuntimeError(f"Unsupported projection mode {mode}") |
| 146 | + |
| 147 | + vmin = vmin if vmin else raster_2D.min() |
| 148 | + vmax = vmax if vmax else raster_2D.max() |
| 149 | + |
| 150 | + norm = Normalize(vmin=vmin, vmax=vmax) |
| 151 | + cm = ScalarMappable(norm=norm, cmap=cmap) |
| 152 | + |
| 153 | + im = cm.to_rgba(raster_2D) |
| 154 | + |
| 155 | + return im[:, :, :3] |
0 commit comments