├── .gitattributes ├── .gitignore ├── .readthedocs.yml ├── LICENSE ├── README.md ├── build └── lib │ └── paste │ ├── PASTE.py │ ├── __init__.py │ ├── helper.py │ └── visualization.py ├── dist ├── paste-bio-1.4.0.tar.gz └── paste_bio-1.4.0-py3-none-any.whl ├── docs ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── _static │ └── images │ │ ├── breast_stack_2d.png │ │ └── paste_overview.png │ ├── api.rst │ ├── conf.py │ ├── index.rst │ ├── installation.md │ ├── notebooks │ └── getting-started.ipynb │ └── tutorial.rst ├── paste-cmd-line.py ├── pyproject.toml ├── requirements.txt ├── sample_data ├── slice1.csv ├── slice1_coor.csv ├── slice1_uniform_weights.csv ├── slice2.csv ├── slice2_coor.csv ├── slice2_uniform_weights.csv ├── slice3.csv ├── slice3_coor.csv ├── slice3_uniform_weights.csv ├── slice4.csv ├── slice4_coor.csv └── slice4_uniform_weights.csv ├── setup.cfg ├── setup.py └── src ├── __init__.py ├── paste ├── PASTE.py ├── __init__.py ├── __pycache__ │ └── helper.cpython-38.pyc ├── helper.py └── visualization.py └── paste_bio.egg-info ├── PKG-INFO ├── SOURCES.txt ├── dependency_links.txt ├── not-zip-safe └── top_level.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ipynb linguist-language=Python 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | paste_output/ 2 | .DS_Store 3 | AD.ipynb 4 | BC.ipynb 5 | cortex.ipynb 6 | DH.ipynb 7 | sample_data/adpolb* 8 | sample_data/dh* 9 | sample_data/DLPFC 10 | sample_data/SlideSeq2 11 | sample_data/her2st-master 12 | sample_data/151507* 13 | sample_data/Developmental* 14 | sample_data/expr* 15 | sample_data/RA-and-SP* 16 | .ipynb_checkpoints/ 17 | !Tutorial-checkpoint.ipynp 18 | ST_sim.ipynb 19 | src/__pycache__/visualization.cpython-37.pyc 20 | __pycache__/paste.cpython-37.pyc 21 | src/helper_ron.py 22 | src/PASTE_ron.py 23 | cortex_ron.ipynb 24 | sample_data/slice4_random_weights.csv 25 | sample_data/slice3_random_weights.csv 26 | sample_data/slice2_random_weights.csv 27 | sample_data/slice1_random_weights.csv 28 | SlideSeq2.ipynb 29 | her2.ipynb 30 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | sphinx: 4 | builder: html 5 | configuration: docs/source/conf.py 6 | fail_on_warning: false 7 | 8 | build: 9 | image: latest 10 | 11 | python: 12 | version: 3.8 13 | install: 14 | - method: pip 15 | path: . 16 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Princeton University 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![PyPI](https://img.shields.io/pypi/v/paste-bio.svg)](https://pypi.org/project/paste-bio) 2 | [![Downloads](https://pepy.tech/badge/paste-bio)](https://pepy.tech/project/paste-bio) 3 | [![Documentation Status](https://readthedocs.org/projects/paste-bio/badge/?version=latest)](https://paste-bio.readthedocs.io/en/stable/?badge=stable) 4 | [![Anaconda](https://anaconda.org/bioconda/paste-bio/badges/version.svg)](https://anaconda.org/bioconda/paste-bio/badges/version.svg) 5 | [![bioconda-downloads](https://anaconda.org/bioconda/paste-bio/badges/downloads.svg)](https://anaconda.org/bioconda/paste-bio/badges/downloads.svg) 6 | 7 | # PASTE 8 | 9 | ![PASTE Overview](https://github.com/raphael-group/paste/blob/main/docs/source/_static/images/paste_overview.png) 10 | 11 | 12 | > [!IMPORTANT] 13 | > **Please see the [Paste3](https://github.com/raphael-group/paste3) repository with updated code that handles both the PASTE and PASTE2 algorithms.** 14 | 15 | 16 | PASTE is a computational method that leverages both gene expression similarity and spatial distances between spots to align and integrate spatial transcriptomics data. In particular, there are two methods: 17 | 1. `pairwise_align`: align spots across pairwise slices. 18 | 2. `center_align`: integrate multiple slices into one center slice. 19 | 20 | You can read full paper [here](https://www.nature.com/articles/s41592-022-01459-6). 21 | 22 | Additional examples and the code to reproduce the paper's analyses can be found [here](https://github.com/raphael-group/paste_reproducibility). Preprocessed datasets used in the paper can be found on [zenodo](https://doi.org/10.5281/zenodo.6334774). 23 | 24 | ### Recent News 25 | 26 | * Please see the [Paste3](https://github.com/raphael-group/paste3) repository with updated code that handles both the PASTE and PASTE2 algorithms. 27 | 28 | * PASTE is now published in [Nature Methods](https://www.nature.com/articles/s41592-022-01459-6)! 29 | 30 | * The code to reproduce the analisys can be found [here](https://github.com/raphael-group/paste_reproducibility). 31 | 32 | * As of version 1.2.0, PASTE now supports GPU implementation via Pytorch. For more details, see the GPU section of the [Tutorial notebook](docs/source/notebooks/getting-started.ipynb). 33 | 34 | ### Installation 35 | 36 | The easiest way is to install PASTE on pypi: https://pypi.org/project/paste-bio/. 37 | 38 | `pip install paste-bio` 39 | 40 | Or you can install PASTE on bioconda: https://anaconda.org/bioconda/paste-bio. 41 | 42 | `conda install -c bioconda paste-bio` 43 | 44 | Check out Tutorial.ipynb for an example of how to use PASTE. 45 | 46 | Alternatively, you can clone the respository and try the following example in a 47 | notebook or the command line. 48 | 49 | ### Quick Start 50 | 51 | To use PASTE we require at least two slices of spatial-omics data (both 52 | expression and coordinates) that are in 53 | anndata format (i.e. read in by scanpy/squidpy). We have included a breast 54 | cancer dataset from [1] in the [sample_data folder](sample_data/) of this repo 55 | that we will use as an example below to show how to use PASTE. 56 | 57 | ```python 58 | import matplotlib.pyplot as plt 59 | import matplotlib.patches as mpatches 60 | import numpy as np 61 | import scanpy as sc 62 | import paste as pst 63 | 64 | # Load Slices 65 | data_dir = './sample_data/' # change this path to the data you wish to analyze 66 | 67 | # Assume that the coordinates of slices are named slice_name + "_coor.csv" 68 | def load_slices(data_dir, slice_names=["slice1", "slice2"]): 69 | slices = [] 70 | for slice_name in slice_names: 71 | slice_i = sc.read_csv(data_dir + slice_name + ".csv") 72 | slice_i_coor = np.genfromtxt(data_dir + slice_name + "_coor.csv", delimiter = ',') 73 | slice_i.obsm['spatial'] = slice_i_coor 74 | # Preprocess slices 75 | sc.pp.filter_genes(slice_i, min_counts = 15) 76 | sc.pp.filter_cells(slice_i, min_counts = 100) 77 | slices.append(slice_i) 78 | return slices 79 | 80 | slices = load_slices(data_dir) 81 | slice1, slice2 = slices 82 | 83 | # Pairwise align the slices 84 | pi12 = pst.pairwise_align(slice1, slice2) 85 | 86 | # To visualize the alignment you can stack the slices 87 | # according to the alignment pi 88 | slices, pis = [slice1, slice2], [pi12] 89 | new_slices = pst.stack_slices_pairwise(slices, pis) 90 | 91 | slice_colors = ['#e41a1c','#377eb8'] 92 | plt.figure(figsize=(7,7)) 93 | for i in range(len(new_slices)): 94 | pst.plot_slice(new_slices[i],slice_colors[i],s=400) 95 | plt.legend(handles=[mpatches.Patch(color=slice_colors[0], label='1'),mpatches.Patch(color=slice_colors[1], label='2')]) 96 | plt.gca().invert_yaxis() 97 | plt.axis('off') 98 | plt.show() 99 | 100 | # Center align slices 101 | ## We have to reload the slices as pairwise_alignment modifies the slices. 102 | slices = load_slices(data_dir) 103 | slice1, slice2 = slices 104 | 105 | # Construct a center slice 106 | ## choose one of the slices as the coordinate reference for the center slice, 107 | ## i.e. the center slice will have the same number of spots as this slice and 108 | ## the same coordinates. 109 | initial_slice = slice1.copy() 110 | slices = [slice1, slice2] 111 | lmbda = len(slices)*[1/len(slices)] # set hyperparameter to be uniform 112 | 113 | ## Possible to pass in an initial pi (as keyword argument pis_init) 114 | ## to improve performance, see Tutorial.ipynb notebook for more details. 115 | center_slice, pis = pst.center_align(initial_slice, slices, lmbda) 116 | 117 | ## The low dimensional representation of our center slice is held 118 | ## in the matrices W and H, which can be used for downstream analyses 119 | W = center_slice.uns['paste_W'] 120 | H = center_slice.uns['paste_H'] 121 | ``` 122 | 123 | ### GPU implementation 124 | PASTE now is compatible with gpu via Pytorch. All we need to do is add the following two parameters to our main functions: 125 | ``` 126 | pi12 = pst.pairwise_align(slice1, slice2, backend = ot.backend.TorchBackend(), use_gpu = True) 127 | 128 | center_slice, pis = pst.center_align(initial_slice, slices, lmbda, backend = ot.backend.TorchBackend(), use_gpu = True) 129 | ``` 130 | For more details, see the GPU section of the [Tutorial notebook](docs/source/notebooks/getting-started.ipynb). 131 | 132 | ### Command Line 133 | 134 | We provide the option of running PASTE from the command line. 135 | 136 | First, clone the repository: 137 | 138 | `git clone https://github.com/raphael-group/paste.git` 139 | 140 | Next, when providing files, you will need to provide two separate files: the gene expression data followed by spatial data (both as .csv) for the code to initialize one slice object. 141 | 142 | Sample execution (based on this repo): `python paste-cmd-line.py -m center -f ./sample_data/slice1.csv ./sample_data/slice1_coor.csv ./sample_data/slice2.csv ./sample_data/slice2_coor.csv ./sample_data/slice3.csv ./sample_data/slice3_coor.csv` 143 | 144 | Note: `pairwise` will return pairwise alignment between each consecutive pair of slices (e.g. \[slice1,slice2\], \[slice2,slice3\]). 145 | 146 | | Flag | Name | Description | Default Value | 147 | | --- | --- | --- | --- | 148 | | -m | mode | Select either `pairwise` or `center` | (str) `pairwise` | 149 | | -f | files | Path to data files (.csv) | None | 150 | | -d | direc | Directory to store output files | Current Directory | 151 | | -a | alpha | Alpha parameter for PASTE | (float) `0.1` | 152 | | -c | cost | Expression dissimilarity cost (`kl` or `Euclidean`) | (str) `kl` | 153 | | -p | n_components | n_components for NMF step in `center_align` | (int) `15` | 154 | | -l | lmbda | Lambda parameter in `center_align` | (floats) probability vector of length `n` | 155 | | -i | intial_slice | Specify which file is also the intial slice in `center_align` | (int) `1` | 156 | | -t | threshold | Convergence threshold for `center_align` | (float) `0.001` | 157 | | -x | coordinates | Output new coordinates (toggle to turn on) | `False` | 158 | | -w | weights | Weights files of spots in each slice (.csv) | None | 159 | | -s | start | Initial alignments for OT. If not given uses uniform (.csv structure similar to alignment output) | None | 160 | 161 | `pairwise_align` outputs a (.csv) file containing mapping of spots between each consecutive pair of slices. The rows correspond to spots of the first slice, and cols the second. 162 | 163 | `center_align` outputs two files containing the low dimensional representation (NMF decomposition) of the center slice gene expression, and files containing a mapping of spots between the center slice (rows) to each input slice (cols). 164 | 165 | ### Sample Dataset 166 | 167 | Added sample spatial transcriptomics dataset consisting of four breast cancer slice courtesy of: 168 | 169 | [1] Ståhl, Patrik & Salmén, Fredrik & Vickovic, Sanja & Lundmark, Anna & Fernandez Navarro, Jose & Magnusson, Jens & Giacomello, Stefania & Asp, Michaela & Westholm, Jakub & Huss, Mikael & Mollbrink, Annelie & Linnarsson, Sten & Codeluppi, Simone & Borg, Åke & Pontén, Fredrik & Costea, Paul & Sahlén, Pelin Akan & Mulder, Jan & Bergmann, Olaf & Frisén, Jonas. (2016). Visualization and analysis of gene expression in tissue sections by spatial transcriptomics. Science. 353. 78-82. 10.1126/science.aaf2403. 170 | 171 | Note: Original data is (.tsv), but we converted it to (.csv). 172 | 173 | ### References 174 | 175 | Ron Zeira, Max Land, Alexander Strzalkowski and Benjamin J. Raphael. "Alignment and integration of spatial transcriptomics data". Nature Methods (2022). https://doi.org/10.1038/s41592-022-01459-6 176 | -------------------------------------------------------------------------------- /build/lib/paste/PASTE.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple, Optional 2 | import numpy as np 3 | from anndata import AnnData 4 | import ot 5 | from sklearn.decomposition import NMF 6 | from .helper import intersect, kl_divergence_backend, to_dense_array, extract_data_matrix 7 | 8 | def pairwise_align( 9 | sliceA: AnnData, 10 | sliceB: AnnData, 11 | alpha: float = 0.1, 12 | dissimilarity: str ='kl', 13 | use_rep: Optional[str] = None, 14 | G_init = None, 15 | a_distribution = None, 16 | b_distribution = None, 17 | norm: bool = False, 18 | numItermax: int = 200, 19 | backend = ot.backend.NumpyBackend(), 20 | use_gpu: bool = False, 21 | return_obj: bool = False, 22 | verbose: bool = False, 23 | gpu_verbose: bool = True, 24 | **kwargs) -> Tuple[np.ndarray, Optional[int]]: 25 | """ 26 | Calculates and returns optimal alignment of two slices. 27 | 28 | Args: 29 | sliceA: Slice A to align. 30 | sliceB: Slice B to align. 31 | alpha: Alignment tuning parameter. Note: 0 <= alpha <= 1. 32 | dissimilarity: Expression dissimilarity measure: ``'kl'`` or ``'euclidean'``. 33 | use_rep: If ``None``, uses ``slice.X`` to calculate dissimilarity between spots, otherwise uses the representation given by ``slice.obsm[use_rep]``. 34 | G_init (array-like, optional): Initial mapping to be used in FGW-OT, otherwise default is uniform mapping. 35 | a_distribution (array-like, optional): Distribution of sliceA spots, otherwise default is uniform. 36 | b_distribution (array-like, optional): Distribution of sliceB spots, otherwise default is uniform. 37 | numItermax: Max number of iterations during FGW-OT. 38 | norm: If ``True``, scales spatial distances such that neighboring spots are at distance 1. Otherwise, spatial distances remain unchanged. 39 | backend: Type of backend to run calculations. For list of backends available on system: ``ot.backend.get_backend_list()``. 40 | use_gpu: If ``True``, use gpu. Otherwise, use cpu. Currently we only have gpu support for Pytorch. 41 | return_obj: If ``True``, additionally returns objective function output of FGW-OT. 42 | verbose: If ``True``, FGW-OT is verbose. 43 | gpu_verbose: If ``True``, print whether gpu is being used to user. 44 | 45 | Returns: 46 | - Alignment of spots. 47 | 48 | If ``return_obj = True``, additionally returns: 49 | 50 | - Objective function output of FGW-OT. 51 | """ 52 | 53 | # Determine if gpu or cpu is being used 54 | if use_gpu: 55 | try: 56 | import torch 57 | except: 58 | print("We currently only have gpu support for Pytorch. Please install torch.") 59 | 60 | if isinstance(backend,ot.backend.TorchBackend): 61 | if torch.cuda.is_available(): 62 | if gpu_verbose: 63 | print("gpu is available, using gpu.") 64 | else: 65 | if gpu_verbose: 66 | print("gpu is not available, resorting to torch cpu.") 67 | use_gpu = False 68 | else: 69 | print("We currently only have gpu support for Pytorch, please set backend = ot.backend.TorchBackend(). Reverting to selected backend cpu.") 70 | use_gpu = False 71 | else: 72 | if gpu_verbose: 73 | print("Using selected backend cpu. If you want to use gpu, set use_gpu = True.") 74 | 75 | # subset for common genes 76 | common_genes = intersect(sliceA.var.index, sliceB.var.index) 77 | sliceA = sliceA[:, common_genes] 78 | sliceB = sliceB[:, common_genes] 79 | 80 | # Backend 81 | nx = backend 82 | 83 | # Calculate spatial distances 84 | coordinatesA = sliceA.obsm['spatial'].copy() 85 | coordinatesA = nx.from_numpy(coordinatesA) 86 | coordinatesB = sliceB.obsm['spatial'].copy() 87 | coordinatesB = nx.from_numpy(coordinatesB) 88 | 89 | if isinstance(nx,ot.backend.TorchBackend): 90 | coordinatesA = coordinatesA.float() 91 | coordinatesB = coordinatesB.float() 92 | D_A = ot.dist(coordinatesA,coordinatesA, metric='euclidean') 93 | D_B = ot.dist(coordinatesB,coordinatesB, metric='euclidean') 94 | 95 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 96 | D_A = D_A.cuda() 97 | D_B = D_B.cuda() 98 | 99 | # Calculate expression dissimilarity 100 | A_X, B_X = nx.from_numpy(to_dense_array(extract_data_matrix(sliceA,use_rep))), nx.from_numpy(to_dense_array(extract_data_matrix(sliceB,use_rep))) 101 | 102 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 103 | A_X = A_X.cuda() 104 | B_X = B_X.cuda() 105 | 106 | if dissimilarity.lower()=='euclidean' or dissimilarity.lower()=='euc': 107 | M = ot.dist(A_X,B_X) 108 | else: 109 | s_A = A_X + 0.01 110 | s_B = B_X + 0.01 111 | M = kl_divergence_backend(s_A, s_B) 112 | M = nx.from_numpy(M) 113 | 114 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 115 | M = M.cuda() 116 | 117 | # init distributions 118 | if a_distribution is None: 119 | a = nx.ones((sliceA.shape[0],))/sliceA.shape[0] 120 | else: 121 | a = nx.from_numpy(a_distribution) 122 | 123 | if b_distribution is None: 124 | b = nx.ones((sliceB.shape[0],))/sliceB.shape[0] 125 | else: 126 | b = nx.from_numpy(b_distribution) 127 | 128 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 129 | a = a.cuda() 130 | b = b.cuda() 131 | 132 | if norm: 133 | D_A /= nx.min(D_A[D_A>0]) 134 | D_B /= nx.min(D_B[D_B>0]) 135 | 136 | # Run OT 137 | if G_init is not None: 138 | G_init = nx.from_numpy(G_init) 139 | if isinstance(nx,ot.backend.TorchBackend): 140 | G_init = G_init.float() 141 | if use_gpu: 142 | G_init.cuda() 143 | pi, logw = my_fused_gromov_wasserstein(M, D_A, D_B, a, b, G_init = G_init, loss_fun='square_loss', alpha= alpha, log=True, numItermax=numItermax,verbose=verbose, use_gpu = use_gpu) 144 | pi = nx.to_numpy(pi) 145 | obj = nx.to_numpy(logw['fgw_dist']) 146 | if isinstance(backend,ot.backend.TorchBackend) and use_gpu: 147 | torch.cuda.empty_cache() 148 | 149 | if return_obj: 150 | return pi, obj 151 | return pi 152 | 153 | 154 | def center_align( 155 | A: AnnData, 156 | slices: List[AnnData], 157 | lmbda = None, 158 | alpha: float = 0.1, 159 | n_components: int = 15, 160 | threshold: float = 0.001, 161 | max_iter: int = 10, 162 | dissimilarity: str ='kl', 163 | norm: bool = False, 164 | random_seed: Optional[int] = None, 165 | pis_init: Optional[List[np.ndarray]] = None, 166 | distributions = None, 167 | backend = ot.backend.NumpyBackend(), 168 | use_gpu: bool = False, 169 | verbose: bool = False, 170 | gpu_verbose: bool = True) -> Tuple[AnnData, List[np.ndarray]]: 171 | """ 172 | Computes center alignment of slices. 173 | 174 | Args: 175 | A: Slice to use as the initialization for center alignment; Make sure to include gene expression and spatial information. 176 | slices: List of slices to use in the center alignment. 177 | lmbda (array-like, optional): List of probability weights assigned to each slice; If ``None``, use uniform weights. 178 | alpha: Alignment tuning parameter. Note: 0 <= alpha <= 1. 179 | n_components: Number of components in NMF decomposition. 180 | threshold: Threshold for convergence of W and H during NMF decomposition. 181 | max_iter: Maximum number of iterations for our center alignment algorithm. 182 | dissimilarity: Expression dissimilarity measure: ``'kl'`` or ``'euclidean'``. 183 | norm: If ``True``, scales spatial distances such that neighboring spots are at distance 1. Otherwise, spatial distances remain unchanged. 184 | random_seed: Set random seed for reproducibility. 185 | pis_init: Initial list of mappings between 'A' and 'slices' to solver. Otherwise, default will automatically calculate mappings. 186 | distributions (List[array-like], optional): Distributions of spots for each slice. Otherwise, default is uniform. 187 | backend: Type of backend to run calculations. For list of backends available on system: ``ot.backend.get_backend_list()``. 188 | use_gpu: If ``True``, use gpu. Otherwise, use cpu. Currently we only have gpu support for Pytorch. 189 | verbose: If ``True``, FGW-OT is verbose. 190 | gpu_verbose: If ``True``, print whether gpu is being used to user. 191 | 192 | Returns: 193 | - Inferred center slice with full and low dimensional representations (W, H) of the gene expression matrix. 194 | - List of pairwise alignment mappings of the center slice (rows) to each input slice (columns). 195 | """ 196 | 197 | # Determine if gpu or cpu is being used 198 | if use_gpu: 199 | try: 200 | import torch 201 | except: 202 | print("We currently only have gpu support for Pytorch. Please install torch.") 203 | 204 | if isinstance(backend,ot.backend.TorchBackend): 205 | if torch.cuda.is_available(): 206 | if gpu_verbose: 207 | print("gpu is available, using gpu.") 208 | else: 209 | if gpu_verbose: 210 | print("gpu is not available, resorting to torch cpu.") 211 | use_gpu = False 212 | else: 213 | print("We currently only have gpu support for Pytorch, please set backend = ot.backend.TorchBackend(). Reverting to selected backend cpu.") 214 | use_gpu = False 215 | else: 216 | if gpu_verbose: 217 | print("Using selected backend cpu. If you want to use gpu, set use_gpu = True.") 218 | 219 | if lmbda is None: 220 | lmbda = len(slices)*[1/len(slices)] 221 | 222 | if distributions is None: 223 | distributions = len(slices)*[None] 224 | 225 | # get common genes 226 | common_genes = A.var.index 227 | for s in slices: 228 | common_genes = intersect(common_genes, s.var.index) 229 | 230 | # subset common genes 231 | A = A[:, common_genes] 232 | for i in range(len(slices)): 233 | slices[i] = slices[i][:, common_genes] 234 | print('Filtered all slices for common genes. There are ' + str(len(common_genes)) + ' common genes.') 235 | 236 | # Run initial NMF 237 | if dissimilarity.lower()=='euclidean' or dissimilarity.lower()=='euc': 238 | model = NMF(n_components=n_components, init='random', random_state = random_seed, verbose = verbose) 239 | else: 240 | model = NMF(n_components=n_components, solver = 'mu', beta_loss = 'kullback-leibler', init='random', random_state = random_seed, verbose = verbose) 241 | 242 | if pis_init is None: 243 | pis = [None for i in range(len(slices))] 244 | W = model.fit_transform(A.X) 245 | else: 246 | pis = pis_init 247 | W = model.fit_transform(A.shape[0]*sum([lmbda[i]*np.dot(pis[i], to_dense_array(slices[i].X)) for i in range(len(slices))])) 248 | H = model.components_ 249 | center_coordinates = A.obsm['spatial'] 250 | 251 | if not isinstance(center_coordinates, np.ndarray): 252 | print("Warning: A.obsm['spatial'] is not of type numpy array.") 253 | 254 | # Initialize center_slice 255 | center_slice = AnnData(np.dot(W,H)) 256 | center_slice.var.index = common_genes 257 | center_slice.obs.index = A.obs.index 258 | center_slice.obsm['spatial'] = center_coordinates 259 | 260 | # Minimize R 261 | iteration_count = 0 262 | R = 0 263 | R_diff = 100 264 | while R_diff > threshold and iteration_count < max_iter: 265 | print("Iteration: " + str(iteration_count)) 266 | pis, r = center_ot(W, H, slices, center_coordinates, common_genes, alpha, backend, use_gpu, dissimilarity = dissimilarity, norm = norm, G_inits = pis, distributions=distributions, verbose = verbose) 267 | W, H = center_NMF(W, H, slices, pis, lmbda, n_components, random_seed, dissimilarity = dissimilarity, verbose = verbose) 268 | R_new = np.dot(r,lmbda) 269 | iteration_count += 1 270 | R_diff = abs(R - R_new) 271 | print("Objective ",R_new) 272 | print("Difference: " + str(R_diff) + "\n") 273 | R = R_new 274 | center_slice = A.copy() 275 | center_slice.X = np.dot(W, H) 276 | center_slice.uns['paste_W'] = W 277 | center_slice.uns['paste_H'] = H 278 | center_slice.uns['full_rank'] = center_slice.shape[0]*sum([lmbda[i]*np.dot(pis[i], to_dense_array(slices[i].X)) for i in range(len(slices))]) 279 | center_slice.uns['obj'] = R 280 | return center_slice, pis 281 | 282 | #--------------------------- HELPER METHODS ----------------------------------- 283 | 284 | def center_ot(W, H, slices, center_coordinates, common_genes, alpha, backend, use_gpu, dissimilarity = 'kl', norm = False, G_inits = None, distributions=None, verbose = False): 285 | center_slice = AnnData(np.dot(W,H)) 286 | center_slice.var.index = common_genes 287 | center_slice.obsm['spatial'] = center_coordinates 288 | 289 | if distributions is None: 290 | distributions = len(slices)*[None] 291 | 292 | pis = [] 293 | r = [] 294 | print('Solving Pairwise Slice Alignment Problem.') 295 | for i in range(len(slices)): 296 | p, r_q = pairwise_align(center_slice, slices[i], alpha = alpha, dissimilarity = dissimilarity, norm = norm, return_obj = True, G_init = G_inits[i], b_distribution=distributions[i], backend = backend, use_gpu = use_gpu, verbose = verbose, gpu_verbose = False) 297 | pis.append(p) 298 | r.append(r_q) 299 | return pis, np.array(r) 300 | 301 | def center_NMF(W, H, slices, pis, lmbda, n_components, random_seed, dissimilarity = 'kl', verbose = False): 302 | print('Solving Center Mapping NMF Problem.') 303 | n = W.shape[0] 304 | B = n*sum([lmbda[i]*np.dot(pis[i], to_dense_array(slices[i].X)) for i in range(len(slices))]) 305 | if dissimilarity.lower()=='euclidean' or dissimilarity.lower()=='euc': 306 | model = NMF(n_components=n_components, init='random', random_state = random_seed, verbose = verbose) 307 | else: 308 | model = NMF(n_components=n_components, solver = 'mu', beta_loss = 'kullback-leibler', init='random', random_state = random_seed, verbose = verbose) 309 | W_new = model.fit_transform(B) 310 | H_new = model.components_ 311 | return W_new, H_new 312 | 313 | def my_fused_gromov_wasserstein(M, C1, C2, p, q, G_init = None, loss_fun='square_loss', alpha=0.5, armijo=False, log=False,numItermax=200, use_gpu = False, **kwargs): 314 | """ 315 | Adapted fused_gromov_wasserstein with the added capability of defining a G_init (inital mapping). 316 | Also added capability of utilizing different POT backends to speed up computation. 317 | 318 | For more info, see: https://pythonot.github.io/gen_modules/ot.gromov.html 319 | """ 320 | 321 | p, q = ot.utils.list_to_array(p, q) 322 | 323 | p0, q0, C10, C20, M0 = p, q, C1, C2, M 324 | nx = ot.backend.get_backend(p0, q0, C10, C20, M0) 325 | 326 | constC, hC1, hC2 = ot.gromov.init_matrix(C1, C2, p, q, loss_fun) 327 | 328 | if G_init is None: 329 | G0 = p[:, None] * q[None, :] 330 | else: 331 | G0 = (1/nx.sum(G_init)) * G_init 332 | if use_gpu: 333 | G0 = G0.cuda() 334 | 335 | def f(G): 336 | return ot.gromov.gwloss(constC, hC1, hC2, G) 337 | 338 | def df(G): 339 | return ot.gromov.gwggrad(constC, hC1, hC2, G) 340 | 341 | if log: 342 | res, log = ot.gromov.cg(p, q, (1 - alpha) * M, alpha, f, df, G0, armijo=armijo, C1=C1, C2=C2, constC=constC, log=True, **kwargs) 343 | 344 | fgw_dist = log['loss'][-1] 345 | 346 | log['fgw_dist'] = fgw_dist 347 | log['u'] = log['u'] 348 | log['v'] = log['v'] 349 | return res, log 350 | 351 | else: 352 | return ot.gromov.cg(p, q, (1 - alpha) * M, alpha, f, df, G0, armijo=armijo, C1=C1, C2=C2, constC=constC, **kwargs) -------------------------------------------------------------------------------- /build/lib/paste/__init__.py: -------------------------------------------------------------------------------- 1 | from .PASTE import pairwise_align, center_align 2 | from .helper import match_spots_using_spatial_heuristic, filter_for_common_genes, apply_trsf 3 | from .visualization import plot_slice, stack_slices_pairwise, stack_slices_center -------------------------------------------------------------------------------- /build/lib/paste/helper.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from anndata import AnnData 3 | import numpy as np 4 | import scipy 5 | import ot 6 | 7 | def filter_for_common_genes( 8 | slices: List[AnnData]) -> None: 9 | """ 10 | Filters for the intersection of genes between all slices. 11 | 12 | Args: 13 | slices: List of slices. 14 | """ 15 | assert len(slices) > 0, "Cannot have empty list." 16 | 17 | common_genes = slices[0].var.index 18 | for s in slices: 19 | common_genes = intersect(common_genes, s.var.index) 20 | for i in range(len(slices)): 21 | slices[i] = slices[i][:, common_genes] 22 | print('Filtered all slices for common genes. There are ' + str(len(common_genes)) + ' common genes.') 23 | 24 | def match_spots_using_spatial_heuristic( 25 | X, 26 | Y, 27 | use_ot: bool = True) -> np.ndarray: 28 | """ 29 | Calculates and returns a mapping of spots using a spatial heuristic. 30 | 31 | Args: 32 | X (array-like, optional): Coordinates for spots X. 33 | Y (array-like, optional): Coordinates for spots Y. 34 | use_ot: If ``True``, use optimal transport ``ot.emd()`` to calculate mapping. Otherwise, use Scipy's ``min_weight_full_bipartite_matching()`` algorithm. 35 | 36 | Returns: 37 | Mapping of spots using a spatial heuristic. 38 | """ 39 | n1,n2=len(X),len(Y) 40 | X,Y = norm_and_center_coordinates(X),norm_and_center_coordinates(Y) 41 | dist = scipy.spatial.distance_matrix(X,Y) 42 | if use_ot: 43 | pi = ot.emd(np.ones(n1)/n1, np.ones(n2)/n2, dist) 44 | else: 45 | row_ind, col_ind = scipy.sparse.csgraph.min_weight_full_bipartite_matching(scipy.sparse.csr_matrix(dist)) 46 | pi = np.zeros((n1,n2)) 47 | pi[row_ind, col_ind] = 1/max(n1,n2) 48 | if n1i',X,log_X) 95 | X_log_X = nx.reshape(X_log_X,(1,X_log_X.shape[0])) 96 | D = X_log_X.T - nx.dot(X,log_Y.T) 97 | return nx.to_numpy(D) 98 | 99 | 100 | def intersect(lst1, lst2): 101 | """ 102 | Gets and returns intersection of two lists. 103 | 104 | Args: 105 | lst1: List 106 | lst2: List 107 | 108 | Returns: 109 | lst3: List of common elements. 110 | """ 111 | 112 | temp = set(lst2) 113 | lst3 = [value for value in lst1 if value in temp] 114 | return lst3 115 | 116 | def norm_and_center_coordinates(X): 117 | """ 118 | Normalizes and centers coordinates at the origin. 119 | 120 | Args: 121 | X: Numpy array 122 | 123 | Returns: 124 | X_new: Updated coordiantes. 125 | """ 126 | return (X-X.mean(axis=0))/min(scipy.spatial.distance.pdist(X)) 127 | 128 | def apply_trsf( 129 | M: np.ndarray, 130 | translation: List[float], 131 | points: np.ndarray) -> np.ndarray: 132 | """ 133 | Apply a rotation from a 2x2 rotation matrix `M` together with 134 | a translation from a translation vector of length 2 `translation` to a list of 135 | `points`. 136 | 137 | Args: 138 | M (nd.array): a 2x2 rotation matrix. 139 | translation (nd.array): a translation vector of length 2. 140 | points (nd.array): a nx2 array of `n` points 2D positions. 141 | 142 | Returns: 143 | (nd.array) a nx2 matrix of the `n` points transformed. 144 | """ 145 | if not isinstance(translation, np.ndarray): 146 | translation = np.array(translation) 147 | trsf = np.identity(3) 148 | trsf[:-1, :-1] = M 149 | tr = np.identity(3) 150 | tr[:-1, -1] = -translation 151 | trsf = trsf @ tr 152 | 153 | flo = points.T 154 | flo_pad = np.pad(flo, ((0, 1), (0, 0)), constant_values=1) 155 | return ((trsf @ flo_pad)[:-1]).T 156 | 157 | ## Covert a sparse matrix into a dense np array 158 | to_dense_array = lambda X: X.toarray() if isinstance(X,scipy.sparse.csr.spmatrix) else np.array(X) 159 | 160 | ## Returns the data matrix or representation 161 | extract_data_matrix = lambda adata,rep: adata.X if rep is None else adata.obsm[rep] -------------------------------------------------------------------------------- /build/lib/paste/visualization.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple, Optional 2 | from anndata import AnnData 3 | import numpy as np 4 | import seaborn as sns 5 | import matplotlib.pyplot as plt 6 | 7 | """ 8 | Functions to plot slices and align spatial coordinates after obtaining a mapping from PASTE. 9 | """ 10 | 11 | def stack_slices_pairwise( 12 | slices: List[AnnData], 13 | pis: List[np.ndarray], 14 | output_params: bool = False, 15 | matrix: bool = False 16 | ) -> Tuple[List[AnnData], Optional[List[float]], Optional[List[np.ndarray]]]: 17 | """ 18 | Align spatial coordinates of sequential pairwise slices. 19 | 20 | In other words, align: 21 | 22 | slices[0] --> slices[1] --> slices[2] --> ... 23 | 24 | Args: 25 | slices: List of slices. 26 | pis: List of pi (``pairwise_align()`` output) between consecutive slices. 27 | output_params: If ``True``, addtionally return angles of rotation (theta) and translations for each slice. 28 | matrix: if ``True`` and output_params is also ``True``, the rotation is 29 | return as a matrix instead of an angle for each slice. 30 | 31 | Returns: 32 | - List of slices with aligned spatial coordinates. 33 | 34 | If ``output_params = True``, additionally return: 35 | 36 | - List of angles of rotation (theta) for each slice. 37 | - List of translations [x_translation, y_translation] for each slice. 38 | """ 39 | assert len(slices) == len(pis) + 1, "'slices' should have length one more than 'pis'. Please double check." 40 | assert len(slices) > 1, "You should have at least 2 layers." 41 | new_coor = [] 42 | thetas = [] 43 | translations = [] 44 | if not output_params: 45 | S1, S2 = generalized_procrustes_analysis(slices[0].obsm['spatial'], slices[1].obsm['spatial'], pis[0]) 46 | else: 47 | S1, S2,theta,tX,tY = generalized_procrustes_analysis(slices[0].obsm['spatial'], slices[1].obsm['spatial'], pis[0],output_params=output_params, matrix=matrix) 48 | thetas.append(theta) 49 | translations.append(tX) 50 | translations.append(tY) 51 | new_coor.append(S1) 52 | new_coor.append(S2) 53 | for i in range(1, len(slices) - 1): 54 | if not output_params: 55 | x, y = generalized_procrustes_analysis(new_coor[i], slices[i+1].obsm['spatial'], pis[i]) 56 | else: 57 | x, y,theta,tX,tY = generalized_procrustes_analysis(new_coor[i], slices[i+1].obsm['spatial'], pis[i],output_params=output_params, matrix=matrix) 58 | thetas.append(theta) 59 | translations.append(tY) 60 | new_coor.append(y) 61 | 62 | new_slices = [] 63 | for i in range(len(slices)): 64 | s = slices[i].copy() 65 | s.obsm['spatial'] = new_coor[i] 66 | new_slices.append(s) 67 | 68 | if not output_params: 69 | return new_slices 70 | else: 71 | return new_slices, thetas, translations 72 | 73 | 74 | def stack_slices_center( 75 | center_slice: AnnData, 76 | slices: List[AnnData], 77 | pis: List[np.ndarray], 78 | matrix: bool = False, 79 | output_params: bool = False) -> Tuple[AnnData, List[AnnData], Optional[List[float]], Optional[List[np.ndarray]]]: 80 | """ 81 | Align spatial coordinates of a list of slices to a center_slice. 82 | 83 | In other words, align: 84 | 85 | slices[0] --> center_slice 86 | 87 | slices[1] --> center_slice 88 | 89 | slices[2] --> center_slice 90 | 91 | ... 92 | 93 | Args: 94 | center_slice: Inferred center slice. 95 | slices: List of original slices to be aligned. 96 | pis: List of pi (``center_align()`` output) between center_slice and slices. 97 | output_params: If ``True``, additionally return angles of rotation (theta) and translations for each slice. 98 | matrix: if ``True`` and output_params is also ``True``, the rotation is 99 | return as a matrix instead of an angle for each slice. 100 | 101 | Returns: 102 | - Center slice with aligned spatial coordinates. 103 | - List of other slices with aligned spatial coordinates. 104 | 105 | If ``output_params = True``, additionally return: 106 | 107 | - List of angles of rotation (theta) for each slice. 108 | - List of translations [x_translation, y_translation] for each slice. 109 | """ 110 | assert len(slices) == len(pis), "'slices' should have the same length 'pis'. Please double check." 111 | new_coor = [] 112 | thetas = [] 113 | translations = [] 114 | 115 | for i in range(len(slices)): 116 | if not output_params: 117 | c, y = generalized_procrustes_analysis(center_slice.obsm['spatial'], slices[i].obsm['spatial'], pis[i]) 118 | else: 119 | c, y,theta,tX,tY = generalized_procrustes_analysis(center_slice.obsm['spatial'], slices[i].obsm['spatial'], pis[i],output_params=output_params, matrix=matrix) 120 | thetas.append(theta) 121 | translations.append(tY) 122 | new_coor.append(y) 123 | 124 | new_slices = [] 125 | for i in range(len(slices)): 126 | s = slices[i].copy() 127 | s.obsm['spatial'] = new_coor[i] 128 | new_slices.append(s) 129 | 130 | new_center = center_slice.copy() 131 | new_center.obsm['spatial'] = c 132 | if not output_params: 133 | return new_center, new_slices 134 | else: 135 | return new_center, new_slices, thetas, translations 136 | 137 | def plot_slice( 138 | sliceX: AnnData, 139 | color, 140 | ax: Optional[plt.Axes] = None, 141 | s: float = 100) -> None: 142 | """ 143 | Plots slice spatial coordinates. 144 | 145 | Args: 146 | sliceX: Slice to be plotted. 147 | color: Scatterplot color, any format accepted by ``matplotlib``. 148 | ax: Pre-existing axes for the plot. Otherwise, call ``matplotlib.pyplot.gca()`` internally. 149 | s: Size of spots. 150 | """ 151 | sns.scatterplot(x = sliceX.obsm['spatial'][:,0],y = sliceX.obsm['spatial'][:,1],linewidth=0,s=s, marker=".",color=color,ax=ax) 152 | if ax: 153 | ax.invert_yaxis() 154 | ax.axis('off') 155 | 156 | 157 | def generalized_procrustes_analysis(X, Y, pi, output_params = False, matrix = False): 158 | """ 159 | Finds and applies optimal rotation between spatial coordinates of two layers (may also do a reflection). 160 | 161 | Args: 162 | X: np array of spatial coordinates (ex: sliceA.obs['spatial']) 163 | Y: np array of spatial coordinates (ex: sliceB.obs['spatial']) 164 | pi: mapping between the two layers output by PASTE 165 | output_params: Boolean of whether to return rotation angle and translations along with spatial coordiantes. 166 | matrix: Boolean of whether to return the rotation as a matrix or an angle 167 | 168 | 169 | Returns: 170 | Aligned spatial coordinates of X, Y, rotation angle, translation of X, translation of Y 171 | """ 172 | assert X.shape[1] == 2 and Y.shape[1] == 2 173 | 174 | tX = pi.sum(axis=1).dot(X) 175 | tY = pi.sum(axis=0).dot(Y) 176 | X = X - tX 177 | Y = Y - tY 178 | H = Y.T.dot(pi.T.dot(X)) 179 | U, S, Vt = np.linalg.svd(H) 180 | R = Vt.T.dot(U.T) 181 | Y = R.dot(Y.T).T 182 | if output_params and not matrix: 183 | M = np.array([[0,-1],[1,0]]) 184 | theta = np.arctan(np.trace(M.dot(H))/np.trace(H)) 185 | return X,Y,theta,tX,tY 186 | elif output_params and matrix: 187 | return X, Y, R, tX, tY 188 | else: 189 | return X,Y 190 | -------------------------------------------------------------------------------- /dist/paste-bio-1.4.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphael-group/paste/5f0d58c67c7ad2b51ccdf67bad3c31df761fd9bc/dist/paste-bio-1.4.0.tar.gz -------------------------------------------------------------------------------- /dist/paste_bio-1.4.0-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphael-group/paste/5f0d58c67c7ad2b51ccdf67bad3c31df761fd9bc/dist/paste_bio-1.4.0-py3-none-any.whl -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | -r ../requirements.txt 2 | sphinx>=2.0.1 3 | myst-parser 4 | nbsphinx 5 | sphinx-autodoc-typehints 6 | sphinx-autodoc-annotation 7 | sphinx_rtd_theme 8 | sphinx_gallery 9 | -------------------------------------------------------------------------------- /docs/source/_static/images/breast_stack_2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphael-group/paste/5f0d58c67c7ad2b51ccdf67bad3c31df761fd9bc/docs/source/_static/images/breast_stack_2d.png -------------------------------------------------------------------------------- /docs/source/_static/images/paste_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphael-group/paste/5f0d58c67c7ad2b51ccdf67bad3c31df761fd9bc/docs/source/_static/images/paste_overview.png -------------------------------------------------------------------------------- /docs/source/api.rst: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | Import Paste as:: 5 | 6 | import paste as pst 7 | 8 | .. automodule:: src.paste 9 | 10 | Alignment 11 | ~~~~~~~~~ 12 | 13 | .. autosummary:: 14 | :toctree: api 15 | 16 | pairwise_align 17 | center_align 18 | 19 | Visualization 20 | ~~~~~~~~~~~~~ 21 | 22 | .. autosummary:: 23 | :toctree: api 24 | 25 | stack_slices_pairwise 26 | stack_slices_center 27 | plot_slice 28 | 29 | Miscellaneous 30 | ~~~~~~~~~~~~~ 31 | 32 | .. autosummary:: 33 | :toctree: api 34 | 35 | filter_for_common_genes 36 | match_spots_using_spatial_heuristic 37 | apply_trsf 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | from pathlib import Path 10 | 11 | 12 | # If extensions (or modules to document with autodoc) are in another directory, 13 | # add these directories to sys.path here. If the directory is relative to the 14 | # documentation root, use os.path.abspath to make it absolute, like shown here. 15 | # 16 | 17 | import sys 18 | HERE = Path(__file__).parent 19 | sys.path.insert(0, str(HERE.parent.parent)) 20 | 21 | import src 22 | 23 | # -- Project information ----------------------------------------------------- 24 | 25 | project = 'paste' 26 | copyright = '2022, Raphael Lab' 27 | author = 'Ron Zeira, Max Land, Alexander Strzalkowski, Benjamin J. Raphael' 28 | 29 | # The full version, including alpha/beta/rc tags 30 | release = '1.2.0' 31 | 32 | 33 | # -- General configuration --------------------------------------------------- 34 | 35 | # Add any Sphinx extension module names here, as strings. They can be 36 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 37 | # ones. 38 | extensions = [ 39 | "myst_parser", 40 | 'sphinx.ext.autosummary', 41 | "sphinx.ext.autodoc", 42 | 'sphinx.ext.napoleon', 43 | "sphinx_autodoc_typehints", 44 | "nbsphinx", 45 | "sphinx_gallery.load_style", 46 | "sphinx.ext.viewcode" 47 | ] 48 | 49 | # Moves Type hints from function header into description 50 | autodoc_typehints = "description" 51 | 52 | 53 | # Add any paths that contain templates here, relative to this directory. 54 | templates_path = ['_templates'] 55 | 56 | # List of patterns, relative to source directory, that match files and 57 | # directories to ignore when looking for source files. 58 | # This pattern also affects html_static_path and html_extra_path. 59 | exclude_patterns = [] 60 | 61 | # If true, the current module name will be prepended to all description 62 | # unit titles (such as .. function::). 63 | add_module_names = False 64 | 65 | 66 | 67 | # -- Options for HTML output ------------------------------------------------- 68 | 69 | # The theme to use for HTML and HTML Help pages. See the documentation for 70 | # a list of builtin themes. 71 | # 72 | html_theme = 'sphinx_rtd_theme' 73 | 74 | # Add any paths that contain custom static files (such as style sheets) here, 75 | # relative to this directory. They are copied after the builtin static files, 76 | # so a file named "default.css" will overwrite the builtin "default.css". 77 | html_static_path = ['_static'] 78 | 79 | html_show_sourcelink = False 80 | html_show_sphinx = False 81 | 82 | 83 | 84 | nbsphinx_thumbnails = { 85 | "notebooks/getting-started": "_static/images/breast_stack_2d.png", 86 | } -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | |PyPI| |Downloads| 2 | 3 | PASTE: Probabilistic Alignment of Spatial Transcriptomics Experiments 4 | ===================================================================== 5 | 6 | **PASTE** is a computational method that leverages both gene expression similarity and spatial distances between spots to align and integrate spatial transcriptomics data. 7 | In particular, PASTE provides two main functionalities: 8 | 9 | 1. Pairwise Alignment: align spots across pairwise slices. 10 | 2. Center Alignment: integrate multiple slices into one center slice. 11 | 12 | .. image:: _static/images/paste_overview.png 13 | :alt: PASTE Overview Figure 14 | :width: 800px 15 | :align: center 16 | 17 | | 18 | 19 | Manuscript 20 | ---------- 21 | 22 | You can view our `preprint `_ on **bioRxiv**. 23 | 24 | .. toctree:: 25 | :maxdepth: 2 26 | :caption: Contents: 27 | :hidden: 28 | 29 | installation 30 | api 31 | tutorial 32 | 33 | 34 | .. |PyPI| image:: https://img.shields.io/pypi/v/paste-bio.svg 35 | :target: https://pypi.org/project/paste-bio/ 36 | :alt: PyPI 37 | 38 | .. |Downloads| image:: https://pepy.tech/badge/paste-bio 39 | :target: https://pepy.tech/project/paste-bio 40 | :alt: Downloads -------------------------------------------------------------------------------- /docs/source/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | The easiest way is to install PASTE on pypi: https://pypi.org/project/paste-bio/. 4 | 5 | `pip install paste-bio` 6 | 7 | Or you can install PASTE on bioconda: https://anaconda.org/bioconda/paste-bio. 8 | 9 | `conda install -c bioconda paste-bio` 10 | 11 | Note: `pip` is our recommended choice of installation. -------------------------------------------------------------------------------- /docs/source/tutorial.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ========= 3 | 4 | These notebook(s) should serve examples of how to use PASTE for your data analysis. 5 | 6 | .. nbgallery:: 7 | notebooks/getting-started 8 | 9 | -------------------------------------------------------------------------------- /paste-cmd-line.py: -------------------------------------------------------------------------------- 1 | import math 2 | import scanpy as sc 3 | import numpy as np 4 | import pandas as pd 5 | import argparse 6 | import os 7 | from src.paste import pairwise_align, center_align, stack_slices_pairwise, stack_slices_center 8 | 9 | def main(args): 10 | # print(args) 11 | n_slices = int(len(args.filename)/2) 12 | # Error check arguments 13 | if args.mode != 'pairwise' and args.mode != 'center': 14 | raise(ValueError("Please select either 'pairwise' or 'center' mode.")) 15 | 16 | if args.alpha < 0 or args.alpha > 1: 17 | raise(ValueError("alpha specified outside [0, 1]")) 18 | 19 | if args.initial_slice < 1 or args.initial_slice > n_slices: 20 | raise(ValueError("Initial slice specified outside [1, n]")) 21 | 22 | if len(args.lmbda) == 0: 23 | lmbda = n_slices*[1./n_slices] 24 | elif len(args.lmbda) != n_slices: 25 | raise(ValueError("Length of lambda does not equal number of files")) 26 | else: 27 | if not all(i >= 0 for i in args.lmbda): 28 | raise(ValueError("lambda includes negative weights")) 29 | else: 30 | print("Normalizing lambda weights into probability vector.") 31 | lmbda = args.lmbda 32 | lmbda = [float(i)/sum(lmbda) for i in lmbda] 33 | 34 | # create slices 35 | slices = [] 36 | for i in range(n_slices): 37 | s = sc.read_csv(args.filename[2*i]) 38 | s.obsm['spatial'] = np.genfromtxt(args.filename[2*i+1], delimiter = ',') 39 | slices.append(s) 40 | 41 | if len(args.weights)==0: 42 | for i in range(n_slices): 43 | slices[i].obsm['weights'] = np.ones((slices[i].shape[0],))/slices[i].shape[0] 44 | elif len(args.weights)!=n_slices: 45 | raise(ValueError("Number of slices {0} != number of weight files {1}".format(n_slices,len(args.weights)))) 46 | else: 47 | for i in range(n_slices): 48 | slices[i].obsm['weights'] = np.genfromtxt(args.weights[i], delimiter = ',') 49 | slices[i].obsm['weights'] = slices[i].obsm['weights']/np.sum(slices[i].obsm['weights']) 50 | 51 | if len(args.start)==0: 52 | pis_init = (n_slices-1)*[None] if args.mode == 'pairwise' else None 53 | elif (args.mode == 'pairwise' and len(args.start)!=n_slices-1) or (args.mode == 'center' and len(args.start)!=n_slices): 54 | raise(ValueError("Number of slices {0} != number of start pi files {1}".format(n_slices,len(args.start)))) 55 | else: 56 | pis_init = [pd.read_csv(args.start[i],index_col=0).to_numpy() for i in range(len(args.start))] 57 | 58 | # create output folder 59 | output_path = os.path.join(args.direc, "paste_output") 60 | if not os.path.exists(output_path): 61 | os.mkdir(output_path) 62 | 63 | if args.mode == 'pairwise': 64 | print("Computing pairwise alignment.") 65 | # compute pairwise align 66 | pis = [] 67 | for i in range(n_slices - 1): 68 | pi = pairwise_align(slices[i], slices[i+1], args.alpha, dissimilarity=args.cost, a_distribution=slices[i].obsm['weights'], b_distribution=slices[i+1].obsm['weights'], G_init=pis_init[i]) 69 | pis.append(pi) 70 | pi = pd.DataFrame(pi, index = slices[i].obs.index, columns = slices[i+1].obs.index) 71 | output_filename = "paste_output/slice" + str(i+1) + "_slice" + str(i+2) + "_pairwise.csv" 72 | pi.to_csv(os.path.join(args.direc, output_filename)) 73 | if args.coordinates: 74 | new_slices = stack_slices_pairwise(slices, pis) 75 | for i in range(n_slices): 76 | output_filename = "paste_output/slice" + str(i+1) + "_new_coordinates.csv" 77 | np.savetxt(os.path.join(args.direc, output_filename), new_slices[i].obsm['spatial'], delimiter=",") 78 | elif args.mode == 'center': 79 | print("Computing center alignment.") 80 | initial_slice = slices[args.initial_slice - 1].copy() 81 | # compute center align 82 | center_slice, pis = center_align(initial_slice, slices, lmbda, args.alpha, args.n_components, args.threshold, dissimilarity=args.cost, distributions=[slices[i].obsm['weights'] for i in range(n_slices)], pis_init=pis_init) 83 | W = pd.DataFrame(center_slice.uns['paste_W'], index = center_slice.obs.index) 84 | H = pd.DataFrame(center_slice.uns['paste_H'], columns = center_slice.var.index) 85 | W.to_csv(os.path.join(args.direc,"paste_output/W_center")) 86 | H.to_csv(os.path.join(args.direc,"paste_output/H_center")) 87 | for i in range(len(pis)): 88 | output_filename = "paste_output/slice_center_slice" + str(i+1) + "_pairwise.csv" 89 | pi = pd.DataFrame(pis[i], index = center_slice.obs.index, columns = slices[i].obs.index) 90 | pi.to_csv(os.path.join(args.direc, output_filename)) 91 | if args.coordinates: 92 | center, new_slices = stack_slices_center(center_slice, slices, pis) 93 | for i in range(n_slices): 94 | output_filename = "paste_output/slice" + str(i+1) + "_new_coordinates.csv" 95 | np.savetxt(os.path.join(args.direc, output_filename), new_slices[i].obsm['spatial'], delimiter=",") 96 | np.savetxt(os.path.join(args.direc, "paste_output/center_new_coordinates.csv"), center.obsm['spatial'], delimiter=",") 97 | return 98 | 99 | 100 | if __name__ == "__main__": 101 | parser = argparse.ArgumentParser() 102 | parser.add_argument("-f","--filename", help="path to data files (.csv). Alternate between gene expression and spatial data. Ex: slice1_gene.csv, slice1_coor.csv, slice2_gene.csv, slice2_coor.csv",type=str, default=[], nargs='+') 103 | parser.add_argument("-m","--mode", help="either 'pairwise' or 'center' ", type=str, default="pairwise") 104 | parser.add_argument("-d","--direc", help="directory to save files",default='') 105 | parser.add_argument("-a","--alpha", help="alpha param for PASTE (float from [0,1])",type=float, default = 0.1) 106 | parser.add_argument("-c","--cost", help="expression dissimilarity cost, either 'kl' or 'euclidean' ", type=str, default="kl") 107 | parser.add_argument("-p","--n_components", help="n_components for NMF step in center_align",type=int, default = 15) 108 | parser.add_argument("-l", "--lmbda", help="lambda param in center_align (weight vector of length n) ",type=float, default = [], nargs='+') 109 | parser.add_argument("-i", "--initial_slice", help="specify which slice is the intial slice for center_align (int from 1-n)",type=int, default = 1) 110 | parser.add_argument("-t","--threshold", help="convergence threshold for center_align",type=float, default = 0.001) 111 | parser.add_argument("-x","--coordinates", help="output new coordinates", action='store_true', default = False) 112 | parser.add_argument("-w","--weights", help="path to files containing weights of spots in each slice. The format of the files is the same as the coordinate files used as input",type=str, default=[], nargs='+') 113 | parser.add_argument("-s","--start", help="path to files containing initial starting alignmnets. If not given the OT starts the search with uniform alignments. The format of the files is the same as the alignments files output by PASTE",type=str, default=[], nargs='+') 114 | args = parser.parse_args() 115 | main(args) 116 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=42", 4 | "wheel" 5 | ] 6 | build-backend = "setuptools.build_meta" -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | anndata>=0.7.6 2 | scanpy>=1.7.2 3 | POT=0.9.0 4 | numpy 5 | scipy 6 | scikit-learn>=0.24.0 7 | IPython>=7.18.1 -------------------------------------------------------------------------------- /sample_data/slice1_coor.csv: -------------------------------------------------------------------------------- 1 | 1.306400000000000006e+01,6.086000000000000298e+00 2 | 1.211599999999999966e+01,7.014999999999999680e+00 3 | 1.394500000000000028e+01,6.998999999999999666e+00 4 | 1.298700000000000010e+01,7.011000000000000121e+00 5 | 1.501099999999999923e+01,7.983999999999999986e+00 6 | 1.205000000000000071e+01,8.018000000000000682e+00 7 | 1.304800000000000004e+01,7.991999999999999993e+00 8 | 1.391699999999999982e+01,7.990000000000000213e+00 9 | 1.797899999999999920e+01,8.976000000000000867e+00 10 | 1.208699999999999974e+01,9.010999999999999233e+00 11 | 1.303500000000000014e+01,8.987999999999999545e+00 12 | 1.896000000000000085e+01,8.987999999999999545e+00 13 | 1.400600000000000023e+01,8.990999999999999659e+00 14 | 1.695899999999999963e+01,8.987000000000000099e+00 15 | 1.502599999999999980e+01,9.034000000000000696e+00 16 | 1.589100000000000001e+01,9.021000000000000796e+00 17 | 1.083200000000000074e+01,9.842000000000000526e+00 18 | 2.001699999999999946e+01,9.935000000000000497e+00 19 | 1.888100000000000023e+01,9.944000000000000838e+00 20 | 1.398900000000000077e+01,9.976000000000000867e+00 21 | 1.794699999999999918e+01,9.973000000000000753e+00 22 | 1.305000000000000071e+01,9.980999999999999872e+00 23 | 1.208699999999999974e+01,9.968999999999999417e+00 24 | 1.708299999999999841e+01,9.984999999999999432e+00 25 | 1.593200000000000038e+01,9.990999999999999659e+00 26 | 1.502299999999999969e+01,9.994999999999999218e+00 27 | 1.083900000000000041e+01,1.082499999999999929e+01 28 | 2.190099999999999980e+01,1.086500000000000021e+01 29 | 1.205199999999999960e+01,1.096499999999999986e+01 30 | 1.796099999999999852e+01,1.095199999999999996e+01 31 | 2.097800000000000153e+01,1.094299999999999962e+01 32 | 2.002199999999999847e+01,1.095599999999999952e+01 33 | 1.695299999999999940e+01,1.096100000000000030e+01 34 | 1.499000000000000021e+01,1.096899999999999942e+01 35 | 1.593800000000000061e+01,1.097300000000000075e+01 36 | 1.302299999999999969e+01,1.097100000000000009e+01 37 | 1.394400000000000084e+01,1.097100000000000009e+01 38 | 1.896300000000000097e+01,1.098300000000000054e+01 39 | 1.077100000000000080e+01,1.182799999999999940e+01 40 | 2.191900000000000048e+01,1.183099999999999952e+01 41 | 9.929999999999999716e+00,1.189700000000000024e+01 42 | 1.207600000000000051e+01,1.194599999999999973e+01 43 | 2.005699999999999861e+01,1.190700000000000003e+01 44 | 1.400699999999999967e+01,1.192900000000000027e+01 45 | 1.801599999999999824e+01,1.191399999999999970e+01 46 | 2.092399999999999949e+01,1.192999999999999972e+01 47 | 1.501299999999999990e+01,1.194599999999999973e+01 48 | 1.294699999999999918e+01,1.194400000000000084e+01 49 | 1.897700000000000031e+01,1.193999999999999950e+01 50 | 1.692000000000000171e+01,1.195899999999999963e+01 51 | 1.598499999999999943e+01,1.195899999999999963e+01 52 | 2.317299999999999827e+01,1.199399999999999977e+01 53 | 1.082499999999999929e+01,1.281900000000000084e+01 54 | 2.194800000000000040e+01,1.282900000000000063e+01 55 | 9.839999999999999858e+00,1.290499999999999936e+01 56 | 1.794999999999999929e+01,1.291399999999999970e+01 57 | 1.203299999999999947e+01,1.295299999999999940e+01 58 | 1.700300000000000011e+01,1.292999999999999972e+01 59 | 2.096799999999999997e+01,1.292300000000000004e+01 60 | 1.398900000000000077e+01,1.292900000000000027e+01 61 | 1.305599999999999916e+01,1.295100000000000051e+01 62 | 1.596700000000000053e+01,1.293999999999999950e+01 63 | 1.494999999999999929e+01,1.294699999999999918e+01 64 | 1.895799999999999841e+01,1.295199999999999996e+01 65 | 2.005799999999999983e+01,1.295800000000000018e+01 66 | 2.316300000000000026e+01,1.299099999999999966e+01 67 | 2.404700000000000060e+01,1.298000000000000043e+01 68 | 1.085599999999999987e+01,1.381600000000000072e+01 69 | 2.193599999999999994e+01,1.383600000000000030e+01 70 | 2.001899999999999835e+01,1.392699999999999960e+01 71 | 2.404799999999999827e+01,1.391799999999999926e+01 72 | 9.868999999999999773e+00,1.392500000000000071e+01 73 | 2.318599999999999994e+01,1.395400000000000063e+01 74 | 1.207900000000000063e+01,1.397499999999999964e+01 75 | 2.100199999999999889e+01,1.395700000000000074e+01 76 | 1.405599999999999916e+01,1.398300000000000054e+01 77 | 1.898600000000000065e+01,1.395599999999999952e+01 78 | 1.297700000000000031e+01,1.398399999999999999e+01 79 | 1.598799999999999955e+01,1.399099999999999966e+01 80 | 1.794600000000000151e+01,1.398700000000000010e+01 81 | 8.961000000000000298e+00,1.399900000000000055e+01 82 | 1.493299999999999983e+01,1.401399999999999935e+01 83 | 1.696799999999999997e+01,1.401800000000000068e+01 84 | 1.080400000000000027e+01,1.481199999999999939e+01 85 | 2.192899999999999849e+01,1.481499999999999950e+01 86 | 9.900000000000000355e+00,1.490099999999999980e+01 87 | 1.397400000000000020e+01,1.491999999999999993e+01 88 | 1.207300000000000040e+01,1.494299999999999962e+01 89 | 8.986000000000000654e+00,1.492399999999999949e+01 90 | 1.903699999999999903e+01,1.493900000000000006e+01 91 | 1.300900000000000034e+01,1.493900000000000006e+01 92 | 2.002599999999999980e+01,1.493900000000000006e+01 93 | 2.096199999999999974e+01,1.493699999999999939e+01 94 | 1.503200000000000003e+01,1.495400000000000063e+01 95 | 1.789799999999999969e+01,1.496100000000000030e+01 96 | 2.314699999999999847e+01,1.498900000000000077e+01 97 | 2.406500000000000128e+01,1.496000000000000085e+01 98 | 2.508800000000000097e+01,1.497000000000000064e+01 99 | 1.698100000000000165e+01,1.497700000000000031e+01 100 | 1.596100000000000030e+01,1.500200000000000067e+01 101 | 1.081300000000000061e+01,1.581300000000000061e+01 102 | 2.193299999999999983e+01,1.583200000000000074e+01 103 | 9.023999999999999133e+00,1.589199999999999946e+01 104 | 9.858999999999999986e+00,1.589100000000000001e+01 105 | 1.702599999999999980e+01,1.590399999999999991e+01 106 | 2.094000000000000128e+01,1.590300000000000047e+01 107 | 2.005799999999999983e+01,1.590499999999999936e+01 108 | 1.898600000000000065e+01,1.592200000000000060e+01 109 | 2.406500000000000128e+01,1.591399999999999970e+01 110 | 1.208699999999999974e+01,1.593599999999999994e+01 111 | 1.790399999999999991e+01,1.592999999999999972e+01 112 | 2.315099999999999980e+01,1.595700000000000074e+01 113 | 7.838000000000000078e+00,1.594800000000000040e+01 114 | 1.300900000000000034e+01,1.592800000000000082e+01 115 | 1.396299999999999919e+01,1.593099999999999916e+01 116 | 2.512500000000000000e+01,1.594699999999999918e+01 117 | 1.588599999999999923e+01,1.593299999999999983e+01 118 | 1.502800000000000047e+01,1.594500000000000028e+01 119 | 1.080499999999999972e+01,1.679700000000000060e+01 120 | 2.191600000000000037e+01,1.686199999999999832e+01 121 | 9.916000000000000369e+00,1.690299999999999869e+01 122 | 1.702599999999999980e+01,1.693700000000000117e+01 123 | 2.006700000000000017e+01,1.693700000000000117e+01 124 | 8.903999999999999915e+00,1.694399999999999906e+01 125 | 1.206400000000000006e+01,1.696999999999999886e+01 126 | 2.092800000000000082e+01,1.694500000000000028e+01 127 | 7.875000000000000000e+00,1.696799999999999997e+01 128 | 1.305599999999999916e+01,1.696999999999999886e+01 129 | 1.502899999999999991e+01,1.696600000000000108e+01 130 | 1.393200000000000038e+01,1.698300000000000054e+01 131 | 1.898699999999999832e+01,1.698199999999999932e+01 132 | 1.790299999999999869e+01,1.698799999999999955e+01 133 | 2.403000000000000114e+01,1.698199999999999932e+01 134 | 1.593200000000000038e+01,1.699099999999999966e+01 135 | 2.318199999999999861e+01,1.702199999999999847e+01 136 | 2.516199999999999903e+01,1.700300000000000011e+01 137 | 2.195200000000000173e+01,1.776500000000000057e+01 138 | 1.081400000000000006e+01,1.781400000000000006e+01 139 | 2.088899999999999935e+01,1.784499999999999886e+01 140 | 1.705799999999999983e+01,1.788800000000000168e+01 141 | 2.006599999999999895e+01,1.787500000000000000e+01 142 | 1.205199999999999960e+01,1.792399999999999949e+01 143 | 1.785200000000000031e+01,1.790599999999999881e+01 144 | 1.299600000000000044e+01,1.793299999999999983e+01 145 | 8.993999999999999773e+00,1.792399999999999949e+01 146 | 1.401200000000000045e+01,1.792699999999999960e+01 147 | 7.871999999999999886e+00,1.792699999999999960e+01 148 | 1.597499999999999964e+01,1.793400000000000105e+01 149 | 1.494200000000000017e+01,1.793700000000000117e+01 150 | 2.416499999999999915e+01,1.794200000000000017e+01 151 | 9.881000000000000227e+00,1.794999999999999929e+01 152 | 1.891300000000000026e+01,1.794399999999999906e+01 153 | 2.316700000000000159e+01,1.796000000000000085e+01 154 | 2.518700000000000117e+01,1.795299999999999940e+01 155 | 1.082699999999999996e+01,1.887099999999999866e+01 156 | 2.200100000000000122e+01,1.887800000000000011e+01 157 | 1.691499999999999915e+01,1.890500000000000114e+01 158 | 1.601000000000000156e+01,1.889900000000000091e+01 159 | 1.206300000000000061e+01,1.893700000000000117e+01 160 | 2.000300000000000011e+01,1.890500000000000114e+01 161 | 2.088800000000000168e+01,1.891300000000000026e+01 162 | 1.799200000000000088e+01,1.890599999999999881e+01 163 | 1.392500000000000071e+01,1.892099999999999937e+01 164 | 1.500099999999999945e+01,1.891400000000000148e+01 165 | 9.836000000000000298e+00,1.892399999999999949e+01 166 | 1.893400000000000105e+01,1.893900000000000006e+01 167 | 8.964000000000000412e+00,1.895400000000000063e+01 168 | 6.857999999999999652e+00,1.895799999999999841e+01 169 | 7.895999999999999908e+00,1.897500000000000142e+01 170 | 2.418400000000000105e+01,1.898100000000000165e+01 171 | 2.316799999999999926e+01,1.899699999999999989e+01 172 | 2.505099999999999838e+01,1.901200000000000045e+01 173 | 1.082499999999999929e+01,1.985300000000000153e+01 174 | 2.198799999999999955e+01,1.991499999999999915e+01 175 | 9.023999999999999133e+00,1.991300000000000026e+01 176 | 1.697700000000000031e+01,1.991400000000000148e+01 177 | 1.798100000000000165e+01,1.992299999999999827e+01 178 | 1.204100000000000037e+01,1.995100000000000051e+01 179 | 1.305199999999999960e+01,1.994699999999999918e+01 180 | 1.595299999999999940e+01,1.994500000000000028e+01 181 | 2.007799999999999940e+01,1.994999999999999929e+01 182 | 9.826000000000000512e+00,1.995499999999999829e+01 183 | 1.893199999999999861e+01,1.995599999999999952e+01 184 | 7.850999999999999979e+00,1.997100000000000009e+01 185 | 1.494400000000000084e+01,1.997700000000000031e+01 186 | 2.090200000000000102e+01,2.000100000000000122e+01 187 | 6.820000000000000284e+00,2.000000000000000000e+01 188 | 2.317000000000000171e+01,2.003099999999999881e+01 189 | 2.416100000000000136e+01,2.005099999999999838e+01 190 | 2.503000000000000114e+01,2.006599999999999895e+01 191 | 1.082900000000000063e+01,2.083899999999999864e+01 192 | 2.190500000000000114e+01,2.085900000000000176e+01 193 | 5.783000000000000362e+00,2.087800000000000011e+01 194 | 9.891999999999999460e+00,2.092399999999999949e+01 195 | 8.993999999999999773e+00,2.091700000000000159e+01 196 | 2.005600000000000094e+01,2.092200000000000060e+01 197 | 6.913000000000000256e+00,2.092899999999999849e+01 198 | 7.865000000000000213e+00,2.092599999999999838e+01 199 | 1.307600000000000051e+01,2.093299999999999983e+01 200 | 1.204100000000000037e+01,2.094900000000000162e+01 201 | 1.596700000000000053e+01,2.093100000000000094e+01 202 | 1.794099999999999895e+01,2.093499999999999872e+01 203 | 1.892099999999999937e+01,2.094600000000000151e+01 204 | 1.697100000000000009e+01,2.094099999999999895e+01 205 | 1.394299999999999962e+01,2.095200000000000173e+01 206 | 2.098600000000000065e+01,2.094900000000000162e+01 207 | 1.497199999999999953e+01,2.096000000000000085e+01 208 | 2.316300000000000026e+01,2.099599999999999866e+01 209 | 2.410600000000000165e+01,2.098999999999999844e+01 210 | 1.083500000000000085e+01,2.181700000000000017e+01 211 | 2.193100000000000094e+01,2.192800000000000082e+01 212 | 9.843999999999999417e+00,2.194800000000000040e+01 213 | 2.314000000000000057e+01,2.197700000000000031e+01 214 | 1.792200000000000060e+01,2.196600000000000108e+01 215 | 2.412999999999999901e+01,2.196099999999999852e+01 216 | 1.694800000000000040e+01,2.197200000000000131e+01 217 | 2.099699999999999989e+01,2.197800000000000153e+01 218 | 1.602299999999999969e+01,2.198499999999999943e+01 219 | 2.002299999999999969e+01,2.199399999999999977e+01 220 | 1.905499999999999972e+01,2.199599999999999866e+01 221 | 1.491399999999999970e+01,2.201399999999999935e+01 222 | 1.401500000000000057e+01,2.201800000000000068e+01 223 | 1.213599999999999923e+01,2.204700000000000060e+01 224 | 1.299300000000000033e+01,2.202400000000000091e+01 225 | 1.085200000000000031e+01,2.283599999999999852e+01 226 | 2.193499999999999872e+01,2.286499999999999844e+01 227 | 1.398799999999999955e+01,2.292699999999999960e+01 228 | 1.693900000000000006e+01,2.291600000000000037e+01 229 | 1.798300000000000054e+01,2.292200000000000060e+01 230 | 1.207300000000000040e+01,2.296300000000000097e+01 231 | 2.098600000000000065e+01,2.293499999999999872e+01 232 | 1.303500000000000014e+01,2.294500000000000028e+01 233 | 2.002799999999999869e+01,2.296199999999999974e+01 234 | 1.599699999999999989e+01,2.295499999999999829e+01 235 | 1.500099999999999945e+01,2.297200000000000131e+01 236 | 1.898400000000000176e+01,2.300000000000000000e+01 237 | 2.410600000000000165e+01,2.302499999999999858e+01 238 | 2.319900000000000162e+01,2.304899999999999949e+01 239 | 1.898600000000000065e+01,2.391600000000000037e+01 240 | 2.195499999999999829e+01,2.382700000000000173e+01 241 | 1.393099999999999916e+01,2.389699999999999847e+01 242 | 1.698000000000000043e+01,2.388899999999999935e+01 243 | 1.799399999999999977e+01,2.390299999999999869e+01 244 | 1.304800000000000004e+01,2.391000000000000014e+01 245 | 2.013700000000000045e+01,2.392099999999999937e+01 246 | 1.595100000000000051e+01,2.391700000000000159e+01 247 | 1.505300000000000082e+01,2.392299999999999827e+01 248 | 2.094900000000000162e+01,2.395700000000000074e+01 249 | 2.315800000000000125e+01,2.400199999999999889e+01 250 | 2.195299999999999940e+01,2.484700000000000131e+01 251 | 2.098000000000000043e+01,2.496300000000000097e+01 252 | 2.006299999999999883e+01,2.496399999999999864e+01 253 | 1.900700000000000145e+01,2.504500000000000171e+01 254 | 2.195700000000000074e+01,2.587099999999999866e+01 255 | -------------------------------------------------------------------------------- /sample_data/slice1_uniform_weights.csv: -------------------------------------------------------------------------------- 1 | 3.937007874015747977e-03 2 | 3.937007874015747977e-03 3 | 3.937007874015747977e-03 4 | 3.937007874015747977e-03 5 | 3.937007874015747977e-03 6 | 3.937007874015747977e-03 7 | 3.937007874015747977e-03 8 | 3.937007874015747977e-03 9 | 3.937007874015747977e-03 10 | 3.937007874015747977e-03 11 | 3.937007874015747977e-03 12 | 3.937007874015747977e-03 13 | 3.937007874015747977e-03 14 | 3.937007874015747977e-03 15 | 3.937007874015747977e-03 16 | 3.937007874015747977e-03 17 | 3.937007874015747977e-03 18 | 3.937007874015747977e-03 19 | 3.937007874015747977e-03 20 | 3.937007874015747977e-03 21 | 3.937007874015747977e-03 22 | 3.937007874015747977e-03 23 | 3.937007874015747977e-03 24 | 3.937007874015747977e-03 25 | 3.937007874015747977e-03 26 | 3.937007874015747977e-03 27 | 3.937007874015747977e-03 28 | 3.937007874015747977e-03 29 | 3.937007874015747977e-03 30 | 3.937007874015747977e-03 31 | 3.937007874015747977e-03 32 | 3.937007874015747977e-03 33 | 3.937007874015747977e-03 34 | 3.937007874015747977e-03 35 | 3.937007874015747977e-03 36 | 3.937007874015747977e-03 37 | 3.937007874015747977e-03 38 | 3.937007874015747977e-03 39 | 3.937007874015747977e-03 40 | 3.937007874015747977e-03 41 | 3.937007874015747977e-03 42 | 3.937007874015747977e-03 43 | 3.937007874015747977e-03 44 | 3.937007874015747977e-03 45 | 3.937007874015747977e-03 46 | 3.937007874015747977e-03 47 | 3.937007874015747977e-03 48 | 3.937007874015747977e-03 49 | 3.937007874015747977e-03 50 | 3.937007874015747977e-03 51 | 3.937007874015747977e-03 52 | 3.937007874015747977e-03 53 | 3.937007874015747977e-03 54 | 3.937007874015747977e-03 55 | 3.937007874015747977e-03 56 | 3.937007874015747977e-03 57 | 3.937007874015747977e-03 58 | 3.937007874015747977e-03 59 | 3.937007874015747977e-03 60 | 3.937007874015747977e-03 61 | 3.937007874015747977e-03 62 | 3.937007874015747977e-03 63 | 3.937007874015747977e-03 64 | 3.937007874015747977e-03 65 | 3.937007874015747977e-03 66 | 3.937007874015747977e-03 67 | 3.937007874015747977e-03 68 | 3.937007874015747977e-03 69 | 3.937007874015747977e-03 70 | 3.937007874015747977e-03 71 | 3.937007874015747977e-03 72 | 3.937007874015747977e-03 73 | 3.937007874015747977e-03 74 | 3.937007874015747977e-03 75 | 3.937007874015747977e-03 76 | 3.937007874015747977e-03 77 | 3.937007874015747977e-03 78 | 3.937007874015747977e-03 79 | 3.937007874015747977e-03 80 | 3.937007874015747977e-03 81 | 3.937007874015747977e-03 82 | 3.937007874015747977e-03 83 | 3.937007874015747977e-03 84 | 3.937007874015747977e-03 85 | 3.937007874015747977e-03 86 | 3.937007874015747977e-03 87 | 3.937007874015747977e-03 88 | 3.937007874015747977e-03 89 | 3.937007874015747977e-03 90 | 3.937007874015747977e-03 91 | 3.937007874015747977e-03 92 | 3.937007874015747977e-03 93 | 3.937007874015747977e-03 94 | 3.937007874015747977e-03 95 | 3.937007874015747977e-03 96 | 3.937007874015747977e-03 97 | 3.937007874015747977e-03 98 | 3.937007874015747977e-03 99 | 3.937007874015747977e-03 100 | 3.937007874015747977e-03 101 | 3.937007874015747977e-03 102 | 3.937007874015747977e-03 103 | 3.937007874015747977e-03 104 | 3.937007874015747977e-03 105 | 3.937007874015747977e-03 106 | 3.937007874015747977e-03 107 | 3.937007874015747977e-03 108 | 3.937007874015747977e-03 109 | 3.937007874015747977e-03 110 | 3.937007874015747977e-03 111 | 3.937007874015747977e-03 112 | 3.937007874015747977e-03 113 | 3.937007874015747977e-03 114 | 3.937007874015747977e-03 115 | 3.937007874015747977e-03 116 | 3.937007874015747977e-03 117 | 3.937007874015747977e-03 118 | 3.937007874015747977e-03 119 | 3.937007874015747977e-03 120 | 3.937007874015747977e-03 121 | 3.937007874015747977e-03 122 | 3.937007874015747977e-03 123 | 3.937007874015747977e-03 124 | 3.937007874015747977e-03 125 | 3.937007874015747977e-03 126 | 3.937007874015747977e-03 127 | 3.937007874015747977e-03 128 | 3.937007874015747977e-03 129 | 3.937007874015747977e-03 130 | 3.937007874015747977e-03 131 | 3.937007874015747977e-03 132 | 3.937007874015747977e-03 133 | 3.937007874015747977e-03 134 | 3.937007874015747977e-03 135 | 3.937007874015747977e-03 136 | 3.937007874015747977e-03 137 | 3.937007874015747977e-03 138 | 3.937007874015747977e-03 139 | 3.937007874015747977e-03 140 | 3.937007874015747977e-03 141 | 3.937007874015747977e-03 142 | 3.937007874015747977e-03 143 | 3.937007874015747977e-03 144 | 3.937007874015747977e-03 145 | 3.937007874015747977e-03 146 | 3.937007874015747977e-03 147 | 3.937007874015747977e-03 148 | 3.937007874015747977e-03 149 | 3.937007874015747977e-03 150 | 3.937007874015747977e-03 151 | 3.937007874015747977e-03 152 | 3.937007874015747977e-03 153 | 3.937007874015747977e-03 154 | 3.937007874015747977e-03 155 | 3.937007874015747977e-03 156 | 3.937007874015747977e-03 157 | 3.937007874015747977e-03 158 | 3.937007874015747977e-03 159 | 3.937007874015747977e-03 160 | 3.937007874015747977e-03 161 | 3.937007874015747977e-03 162 | 3.937007874015747977e-03 163 | 3.937007874015747977e-03 164 | 3.937007874015747977e-03 165 | 3.937007874015747977e-03 166 | 3.937007874015747977e-03 167 | 3.937007874015747977e-03 168 | 3.937007874015747977e-03 169 | 3.937007874015747977e-03 170 | 3.937007874015747977e-03 171 | 3.937007874015747977e-03 172 | 3.937007874015747977e-03 173 | 3.937007874015747977e-03 174 | 3.937007874015747977e-03 175 | 3.937007874015747977e-03 176 | 3.937007874015747977e-03 177 | 3.937007874015747977e-03 178 | 3.937007874015747977e-03 179 | 3.937007874015747977e-03 180 | 3.937007874015747977e-03 181 | 3.937007874015747977e-03 182 | 3.937007874015747977e-03 183 | 3.937007874015747977e-03 184 | 3.937007874015747977e-03 185 | 3.937007874015747977e-03 186 | 3.937007874015747977e-03 187 | 3.937007874015747977e-03 188 | 3.937007874015747977e-03 189 | 3.937007874015747977e-03 190 | 3.937007874015747977e-03 191 | 3.937007874015747977e-03 192 | 3.937007874015747977e-03 193 | 3.937007874015747977e-03 194 | 3.937007874015747977e-03 195 | 3.937007874015747977e-03 196 | 3.937007874015747977e-03 197 | 3.937007874015747977e-03 198 | 3.937007874015747977e-03 199 | 3.937007874015747977e-03 200 | 3.937007874015747977e-03 201 | 3.937007874015747977e-03 202 | 3.937007874015747977e-03 203 | 3.937007874015747977e-03 204 | 3.937007874015747977e-03 205 | 3.937007874015747977e-03 206 | 3.937007874015747977e-03 207 | 3.937007874015747977e-03 208 | 3.937007874015747977e-03 209 | 3.937007874015747977e-03 210 | 3.937007874015747977e-03 211 | 3.937007874015747977e-03 212 | 3.937007874015747977e-03 213 | 3.937007874015747977e-03 214 | 3.937007874015747977e-03 215 | 3.937007874015747977e-03 216 | 3.937007874015747977e-03 217 | 3.937007874015747977e-03 218 | 3.937007874015747977e-03 219 | 3.937007874015747977e-03 220 | 3.937007874015747977e-03 221 | 3.937007874015747977e-03 222 | 3.937007874015747977e-03 223 | 3.937007874015747977e-03 224 | 3.937007874015747977e-03 225 | 3.937007874015747977e-03 226 | 3.937007874015747977e-03 227 | 3.937007874015747977e-03 228 | 3.937007874015747977e-03 229 | 3.937007874015747977e-03 230 | 3.937007874015747977e-03 231 | 3.937007874015747977e-03 232 | 3.937007874015747977e-03 233 | 3.937007874015747977e-03 234 | 3.937007874015747977e-03 235 | 3.937007874015747977e-03 236 | 3.937007874015747977e-03 237 | 3.937007874015747977e-03 238 | 3.937007874015747977e-03 239 | 3.937007874015747977e-03 240 | 3.937007874015747977e-03 241 | 3.937007874015747977e-03 242 | 3.937007874015747977e-03 243 | 3.937007874015747977e-03 244 | 3.937007874015747977e-03 245 | 3.937007874015747977e-03 246 | 3.937007874015747977e-03 247 | 3.937007874015747977e-03 248 | 3.937007874015747977e-03 249 | 3.937007874015747977e-03 250 | 3.937007874015747977e-03 251 | 3.937007874015747977e-03 252 | 3.937007874015747977e-03 253 | 3.937007874015747977e-03 254 | 3.937007874015747977e-03 255 | -------------------------------------------------------------------------------- /sample_data/slice2_coor.csv: -------------------------------------------------------------------------------- 1 | 1.790700000000000003e+01,4.966999999999999638e+00 2 | 1.896499999999999986e+01,5.003000000000000114e+00 3 | 1.895400000000000063e+01,5.995000000000000107e+00 4 | 1.784600000000000009e+01,5.993000000000000327e+00 5 | 2.001599999999999824e+01,6.019000000000000128e+00 6 | 2.088899999999999935e+01,6.956000000000000405e+00 7 | 2.006200000000000117e+01,6.974000000000000199e+00 8 | 1.698000000000000043e+01,6.988999999999999879e+00 9 | 1.791799999999999926e+01,6.990999999999999659e+00 10 | 1.887699999999999889e+01,6.983999999999999986e+00 11 | 2.184700000000000131e+01,7.895999999999999908e+00 12 | 2.090099999999999980e+01,7.964999999999999858e+00 13 | 2.311799999999999855e+01,7.985000000000000320e+00 14 | 1.997400000000000020e+01,7.988000000000000433e+00 15 | 1.790399999999999991e+01,8.003000000000000114e+00 16 | 1.894800000000000040e+01,8.031000000000000583e+00 17 | 1.675300000000000011e+01,8.019999999999999574e+00 18 | 2.184900000000000020e+01,8.887000000000000455e+00 19 | 2.093599999999999994e+01,8.944000000000000838e+00 20 | 1.792800000000000082e+01,8.983999999999999986e+00 21 | 2.309700000000000131e+01,9.010999999999999233e+00 22 | 2.407600000000000051e+01,8.990999999999999659e+00 23 | 1.893900000000000006e+01,9.000000000000000000e+00 24 | 1.992500000000000071e+01,8.992000000000000881e+00 25 | 1.490099999999999980e+01,9.039999999999999147e+00 26 | 1.597100000000000009e+01,9.013999999999999346e+00 27 | 1.678300000000000125e+01,9.018000000000000682e+00 28 | 2.189199999999999946e+01,9.869999999999999218e+00 29 | 2.080600000000000094e+01,9.928000000000000824e+00 30 | 2.493100000000000094e+01,9.980999999999999872e+00 31 | 2.315200000000000102e+01,1.000000000000000000e+01 32 | 1.792200000000000060e+01,9.987000000000000099e+00 33 | 2.005000000000000071e+01,9.970000000000000639e+00 34 | 1.396100000000000030e+01,1.001099999999999923e+01 35 | 2.408500000000000085e+01,9.990000000000000213e+00 36 | 1.882400000000000162e+01,9.984999999999999432e+00 37 | 1.602899999999999991e+01,1.001200000000000045e+01 38 | 1.690899999999999892e+01,1.001699999999999946e+01 39 | 1.490700000000000003e+01,1.004599999999999937e+01 40 | 2.185999999999999943e+01,1.087400000000000055e+01 41 | 2.303900000000000148e+01,1.098000000000000043e+01 42 | 2.087000000000000099e+01,1.095199999999999996e+01 43 | 2.405699999999999861e+01,1.096700000000000053e+01 44 | 2.000300000000000011e+01,1.097199999999999953e+01 45 | 2.594900000000000162e+01,1.098499999999999943e+01 46 | 2.491700000000000159e+01,1.097700000000000031e+01 47 | 1.789699999999999847e+01,1.098799999999999955e+01 48 | 1.688899999999999935e+01,1.100200000000000067e+01 49 | 1.494699999999999918e+01,1.102599999999999980e+01 50 | 1.889900000000000091e+01,1.101600000000000001e+01 51 | 1.389400000000000013e+01,1.101999999999999957e+01 52 | 1.593599999999999994e+01,1.102599999999999980e+01 53 | 2.184199999999999875e+01,1.185200000000000031e+01 54 | 2.092599999999999838e+01,1.191099999999999959e+01 55 | 2.403800000000000026e+01,1.193299999999999983e+01 56 | 1.995100000000000051e+01,1.194100000000000072e+01 57 | 2.700199999999999889e+01,1.194500000000000028e+01 58 | 1.894800000000000040e+01,1.194800000000000040e+01 59 | 2.306200000000000117e+01,1.197400000000000020e+01 60 | 1.792000000000000171e+01,1.196499999999999986e+01 61 | 1.393599999999999994e+01,1.197600000000000087e+01 62 | 1.495500000000000007e+01,1.198000000000000043e+01 63 | 1.298700000000000010e+01,1.197600000000000087e+01 64 | 1.690500000000000114e+01,1.197700000000000031e+01 65 | 2.495899999999999963e+01,1.197199999999999953e+01 66 | 1.593399999999999928e+01,1.199000000000000021e+01 67 | 2.596099999999999852e+01,1.198300000000000054e+01 68 | 2.186799999999999855e+01,1.287599999999999945e+01 69 | 2.089000000000000057e+01,1.293200000000000038e+01 70 | 2.001399999999999935e+01,1.294699999999999918e+01 71 | 2.307199999999999918e+01,1.297300000000000075e+01 72 | 1.200500000000000078e+01,1.298199999999999932e+01 73 | 1.888599999999999923e+01,1.296400000000000041e+01 74 | 2.405999999999999872e+01,1.294599999999999973e+01 75 | 1.303599999999999959e+01,1.296199999999999974e+01 76 | 2.701300000000000168e+01,1.296000000000000085e+01 77 | 2.598799999999999955e+01,1.297100000000000009e+01 78 | 1.495599999999999952e+01,1.298600000000000065e+01 79 | 1.596199999999999974e+01,1.298399999999999999e+01 80 | 2.492999999999999972e+01,1.297000000000000064e+01 81 | 1.685399999999999920e+01,1.300099999999999945e+01 82 | 1.390300000000000047e+01,1.300600000000000023e+01 83 | 2.181700000000000017e+01,1.386500000000000021e+01 84 | 2.092699999999999960e+01,1.392399999999999949e+01 85 | 2.596600000000000108e+01,1.395299999999999940e+01 86 | 1.202100000000000080e+01,1.398199999999999932e+01 87 | 1.303500000000000014e+01,1.395599999999999952e+01 88 | 1.896099999999999852e+01,1.395899999999999963e+01 89 | 1.996199999999999974e+01,1.395899999999999963e+01 90 | 2.303999999999999915e+01,1.397499999999999964e+01 91 | 2.405699999999999861e+01,1.396299999999999919e+01 92 | 1.786499999999999844e+01,1.395899999999999963e+01 93 | 2.797299999999999898e+01,1.397100000000000009e+01 94 | 2.496699999999999875e+01,1.395599999999999952e+01 95 | 2.698199999999999932e+01,1.397700000000000031e+01 96 | 1.389400000000000013e+01,1.398199999999999932e+01 97 | 1.495899999999999963e+01,1.398700000000000010e+01 98 | 1.687399999999999878e+01,1.401299999999999990e+01 99 | 1.597600000000000087e+01,1.403700000000000081e+01 100 | 2.184400000000000119e+01,1.483500000000000085e+01 101 | 2.089600000000000080e+01,1.489400000000000013e+01 102 | 1.999599999999999866e+01,1.491799999999999926e+01 103 | 1.206199999999999939e+01,1.496400000000000041e+01 104 | 1.890899999999999892e+01,1.495199999999999996e+01 105 | 2.304899999999999949e+01,1.496799999999999997e+01 106 | 2.406599999999999895e+01,1.494200000000000017e+01 107 | 2.498499999999999943e+01,1.495100000000000051e+01 108 | 2.594999999999999929e+01,1.495400000000000063e+01 109 | 1.300600000000000023e+01,1.496400000000000041e+01 110 | 1.689300000000000068e+01,1.496599999999999930e+01 111 | 1.792899999999999849e+01,1.495100000000000051e+01 112 | 1.394100000000000072e+01,1.497799999999999976e+01 113 | 2.699899999999999878e+01,1.496599999999999930e+01 114 | 1.594699999999999918e+01,1.498499999999999943e+01 115 | 2.786499999999999844e+01,1.497100000000000009e+01 116 | 1.082099999999999973e+01,1.585500000000000043e+01 117 | 2.190800000000000125e+01,1.585699999999999932e+01 118 | 2.306500000000000128e+01,1.594400000000000084e+01 119 | 2.700400000000000134e+01,1.593099999999999916e+01 120 | 2.895599999999999952e+01,1.592600000000000016e+01 121 | 2.404299999999999926e+01,1.593599999999999994e+01 122 | 2.794000000000000128e+01,1.592900000000000027e+01 123 | 2.086899999999999977e+01,1.594100000000000072e+01 124 | 9.810000000000000497e+00,1.593900000000000006e+01 125 | 2.501800000000000068e+01,1.594100000000000072e+01 126 | 1.998499999999999943e+01,1.595700000000000074e+01 127 | 1.892899999999999849e+01,1.597000000000000064e+01 128 | 1.386599999999999966e+01,1.596199999999999974e+01 129 | 1.198700000000000010e+01,1.598499999999999943e+01 130 | 1.306799999999999962e+01,1.596700000000000053e+01 131 | 1.497899999999999920e+01,1.597799999999999976e+01 132 | 1.590900000000000070e+01,1.598099999999999987e+01 133 | 1.692500000000000071e+01,1.600199999999999889e+01 134 | 2.593400000000000105e+01,1.602299999999999969e+01 135 | 1.784600000000000009e+01,1.611299999999999955e+01 136 | 1.082499999999999929e+01,1.683200000000000074e+01 137 | 2.184900000000000020e+01,1.684900000000000020e+01 138 | 9.852000000000000313e+00,1.692800000000000082e+01 139 | 1.491200000000000081e+01,1.696499999999999986e+01 140 | 2.308200000000000074e+01,1.693599999999999994e+01 141 | 2.094600000000000151e+01,1.692999999999999972e+01 142 | 2.798600000000000065e+01,1.694600000000000151e+01 143 | 1.898199999999999932e+01,1.695400000000000063e+01 144 | 8.932000000000000384e+00,1.696499999999999986e+01 145 | 1.202200000000000024e+01,1.699500000000000099e+01 146 | 2.694500000000000028e+01,1.696499999999999986e+01 147 | 2.890800000000000125e+01,1.696999999999999886e+01 148 | 1.788700000000000045e+01,1.697599999999999909e+01 149 | 1.592399999999999949e+01,1.698900000000000077e+01 150 | 2.596900000000000119e+01,1.698699999999999832e+01 151 | 1.690899999999999892e+01,1.699399999999999977e+01 152 | 1.989799999999999969e+01,1.699699999999999989e+01 153 | 2.405000000000000071e+01,1.700000000000000000e+01 154 | 1.299600000000000044e+01,1.701000000000000156e+01 155 | 2.496699999999999875e+01,1.701099999999999923e+01 156 | 2.181500000000000128e+01,1.783599999999999852e+01 157 | 2.094500000000000028e+01,1.789600000000000080e+01 158 | 7.924000000000000377e+00,1.792800000000000082e+01 159 | 9.861000000000000654e+00,1.793100000000000094e+01 160 | 2.697400000000000020e+01,1.792599999999999838e+01 161 | 2.795899999999999963e+01,1.792299999999999827e+01 162 | 1.994699999999999918e+01,1.792399999999999949e+01 163 | 1.202899999999999991e+01,1.796699999999999875e+01 164 | 1.892000000000000171e+01,1.793199999999999861e+01 165 | 2.303099999999999881e+01,1.795599999999999952e+01 166 | 2.404200000000000159e+01,1.794500000000000028e+01 167 | 1.690800000000000125e+01,1.795100000000000051e+01 168 | 1.789499999999999957e+01,1.794900000000000162e+01 169 | 8.948000000000000398e+00,1.795499999999999829e+01 170 | 1.593399999999999928e+01,1.795899999999999963e+01 171 | 1.299900000000000055e+01,1.796399999999999864e+01 172 | 1.394999999999999929e+01,1.796699999999999875e+01 173 | 2.594300000000000139e+01,1.797299999999999898e+01 174 | 2.499299999999999855e+01,1.797200000000000131e+01 175 | 1.493599999999999994e+01,1.798699999999999832e+01 176 | 2.184100000000000108e+01,1.884499999999999886e+01 177 | 1.304899999999999949e+01,1.894000000000000128e+01 178 | 2.094699999999999918e+01,1.892999999999999972e+01 179 | 2.406700000000000017e+01,1.893400000000000105e+01 180 | 2.000199999999999889e+01,1.894300000000000139e+01 181 | 2.305199999999999960e+01,1.895599999999999952e+01 182 | 2.794000000000000128e+01,1.894200000000000017e+01 183 | 1.199900000000000055e+01,1.898199999999999932e+01 184 | 1.786400000000000077e+01,1.895100000000000051e+01 185 | 2.696799999999999997e+01,1.895200000000000173e+01 186 | 1.692099999999999937e+01,1.896300000000000097e+01 187 | 2.497700000000000031e+01,1.894999999999999929e+01 188 | 2.594800000000000040e+01,1.895899999999999963e+01 189 | 1.888700000000000045e+01,1.895899999999999963e+01 190 | 1.390900000000000070e+01,1.896499999999999986e+01 191 | 1.594800000000000040e+01,1.898699999999999832e+01 192 | 1.492600000000000016e+01,1.899899999999999878e+01 193 | 2.188599999999999923e+01,1.982999999999999829e+01 194 | 2.305799999999999983e+01,1.995599999999999952e+01 195 | 1.896399999999999864e+01,1.994500000000000028e+01 196 | 2.694600000000000151e+01,1.995499999999999829e+01 197 | 1.394400000000000084e+01,1.996199999999999974e+01 198 | 1.785500000000000043e+01,1.995599999999999952e+01 199 | 2.406500000000000128e+01,1.996399999999999864e+01 200 | 2.595700000000000074e+01,1.996999999999999886e+01 201 | 2.091300000000000026e+01,2.000400000000000134e+01 202 | 1.295100000000000051e+01,2.001000000000000156e+01 203 | 1.998000000000000043e+01,2.000799999999999912e+01 204 | 1.498799999999999955e+01,2.000400000000000134e+01 205 | 1.589600000000000080e+01,2.004400000000000048e+01 206 | 2.501999999999999957e+01,2.015299999999999869e+01 207 | 2.307700000000000173e+01,2.096999999999999886e+01 208 | 2.011599999999999966e+01,2.096199999999999974e+01 209 | 1.786700000000000088e+01,2.095400000000000063e+01 210 | 1.894600000000000151e+01,2.096199999999999974e+01 211 | 2.699699999999999989e+01,2.095499999999999829e+01 212 | 1.598900000000000077e+01,2.098300000000000054e+01 213 | 2.404599999999999937e+01,2.098199999999999932e+01 214 | 2.596399999999999864e+01,2.098400000000000176e+01 215 | 1.390499999999999936e+01,2.100799999999999912e+01 216 | 1.487700000000000067e+01,2.102799999999999869e+01 217 | 2.498499999999999943e+01,2.102799999999999869e+01 218 | 2.096399999999999864e+01,2.173000000000000043e+01 219 | 2.187999999999999901e+01,2.182199999999999918e+01 220 | 2.001800000000000068e+01,2.192399999999999949e+01 221 | 1.789300000000000068e+01,2.195299999999999940e+01 222 | 1.895700000000000074e+01,2.195200000000000173e+01 223 | 2.412000000000000099e+01,2.195200000000000173e+01 224 | 1.691900000000000048e+01,2.197599999999999909e+01 225 | 2.302599999999999980e+01,2.198900000000000077e+01 226 | 2.495100000000000051e+01,2.195899999999999963e+01 227 | 1.597000000000000064e+01,2.198600000000000065e+01 228 | 1.498099999999999987e+01,2.200400000000000134e+01 229 | 2.592099999999999937e+01,2.197599999999999909e+01 230 | 1.391799999999999926e+01,2.202199999999999847e+01 231 | 2.187399999999999878e+01,2.284700000000000131e+01 232 | 2.098499999999999943e+01,2.291000000000000014e+01 233 | 1.789799999999999969e+01,2.293199999999999861e+01 234 | 1.896300000000000097e+01,2.295200000000000173e+01 235 | 1.995200000000000173e+01,2.295499999999999829e+01 236 | 2.309900000000000020e+01,2.297700000000000031e+01 237 | 1.598399999999999999e+01,2.296999999999999886e+01 238 | 1.693299999999999983e+01,2.296699999999999875e+01 239 | 2.602100000000000080e+01,2.297700000000000031e+01 240 | 2.408800000000000097e+01,2.298999999999999844e+01 241 | 2.495700000000000074e+01,2.301899999999999835e+01 242 | 2.189399999999999835e+01,2.385099999999999909e+01 243 | 1.893700000000000117e+01,2.395200000000000173e+01 244 | 2.092500000000000071e+01,2.392399999999999949e+01 245 | 2.001899999999999835e+01,2.393400000000000105e+01 246 | 2.405499999999999972e+01,2.394600000000000151e+01 247 | 2.309400000000000119e+01,2.397500000000000142e+01 248 | 2.498100000000000165e+01,2.396399999999999864e+01 249 | 2.187399999999999878e+01,2.485200000000000031e+01 250 | 2.309600000000000009e+01,2.492999999999999972e+01 251 | 2.407600000000000051e+01,2.595100000000000051e+01 252 | -------------------------------------------------------------------------------- /sample_data/slice2_uniform_weights.csv: -------------------------------------------------------------------------------- 1 | 3.984063745019920250e-03 2 | 3.984063745019920250e-03 3 | 3.984063745019920250e-03 4 | 3.984063745019920250e-03 5 | 3.984063745019920250e-03 6 | 3.984063745019920250e-03 7 | 3.984063745019920250e-03 8 | 3.984063745019920250e-03 9 | 3.984063745019920250e-03 10 | 3.984063745019920250e-03 11 | 3.984063745019920250e-03 12 | 3.984063745019920250e-03 13 | 3.984063745019920250e-03 14 | 3.984063745019920250e-03 15 | 3.984063745019920250e-03 16 | 3.984063745019920250e-03 17 | 3.984063745019920250e-03 18 | 3.984063745019920250e-03 19 | 3.984063745019920250e-03 20 | 3.984063745019920250e-03 21 | 3.984063745019920250e-03 22 | 3.984063745019920250e-03 23 | 3.984063745019920250e-03 24 | 3.984063745019920250e-03 25 | 3.984063745019920250e-03 26 | 3.984063745019920250e-03 27 | 3.984063745019920250e-03 28 | 3.984063745019920250e-03 29 | 3.984063745019920250e-03 30 | 3.984063745019920250e-03 31 | 3.984063745019920250e-03 32 | 3.984063745019920250e-03 33 | 3.984063745019920250e-03 34 | 3.984063745019920250e-03 35 | 3.984063745019920250e-03 36 | 3.984063745019920250e-03 37 | 3.984063745019920250e-03 38 | 3.984063745019920250e-03 39 | 3.984063745019920250e-03 40 | 3.984063745019920250e-03 41 | 3.984063745019920250e-03 42 | 3.984063745019920250e-03 43 | 3.984063745019920250e-03 44 | 3.984063745019920250e-03 45 | 3.984063745019920250e-03 46 | 3.984063745019920250e-03 47 | 3.984063745019920250e-03 48 | 3.984063745019920250e-03 49 | 3.984063745019920250e-03 50 | 3.984063745019920250e-03 51 | 3.984063745019920250e-03 52 | 3.984063745019920250e-03 53 | 3.984063745019920250e-03 54 | 3.984063745019920250e-03 55 | 3.984063745019920250e-03 56 | 3.984063745019920250e-03 57 | 3.984063745019920250e-03 58 | 3.984063745019920250e-03 59 | 3.984063745019920250e-03 60 | 3.984063745019920250e-03 61 | 3.984063745019920250e-03 62 | 3.984063745019920250e-03 63 | 3.984063745019920250e-03 64 | 3.984063745019920250e-03 65 | 3.984063745019920250e-03 66 | 3.984063745019920250e-03 67 | 3.984063745019920250e-03 68 | 3.984063745019920250e-03 69 | 3.984063745019920250e-03 70 | 3.984063745019920250e-03 71 | 3.984063745019920250e-03 72 | 3.984063745019920250e-03 73 | 3.984063745019920250e-03 74 | 3.984063745019920250e-03 75 | 3.984063745019920250e-03 76 | 3.984063745019920250e-03 77 | 3.984063745019920250e-03 78 | 3.984063745019920250e-03 79 | 3.984063745019920250e-03 80 | 3.984063745019920250e-03 81 | 3.984063745019920250e-03 82 | 3.984063745019920250e-03 83 | 3.984063745019920250e-03 84 | 3.984063745019920250e-03 85 | 3.984063745019920250e-03 86 | 3.984063745019920250e-03 87 | 3.984063745019920250e-03 88 | 3.984063745019920250e-03 89 | 3.984063745019920250e-03 90 | 3.984063745019920250e-03 91 | 3.984063745019920250e-03 92 | 3.984063745019920250e-03 93 | 3.984063745019920250e-03 94 | 3.984063745019920250e-03 95 | 3.984063745019920250e-03 96 | 3.984063745019920250e-03 97 | 3.984063745019920250e-03 98 | 3.984063745019920250e-03 99 | 3.984063745019920250e-03 100 | 3.984063745019920250e-03 101 | 3.984063745019920250e-03 102 | 3.984063745019920250e-03 103 | 3.984063745019920250e-03 104 | 3.984063745019920250e-03 105 | 3.984063745019920250e-03 106 | 3.984063745019920250e-03 107 | 3.984063745019920250e-03 108 | 3.984063745019920250e-03 109 | 3.984063745019920250e-03 110 | 3.984063745019920250e-03 111 | 3.984063745019920250e-03 112 | 3.984063745019920250e-03 113 | 3.984063745019920250e-03 114 | 3.984063745019920250e-03 115 | 3.984063745019920250e-03 116 | 3.984063745019920250e-03 117 | 3.984063745019920250e-03 118 | 3.984063745019920250e-03 119 | 3.984063745019920250e-03 120 | 3.984063745019920250e-03 121 | 3.984063745019920250e-03 122 | 3.984063745019920250e-03 123 | 3.984063745019920250e-03 124 | 3.984063745019920250e-03 125 | 3.984063745019920250e-03 126 | 3.984063745019920250e-03 127 | 3.984063745019920250e-03 128 | 3.984063745019920250e-03 129 | 3.984063745019920250e-03 130 | 3.984063745019920250e-03 131 | 3.984063745019920250e-03 132 | 3.984063745019920250e-03 133 | 3.984063745019920250e-03 134 | 3.984063745019920250e-03 135 | 3.984063745019920250e-03 136 | 3.984063745019920250e-03 137 | 3.984063745019920250e-03 138 | 3.984063745019920250e-03 139 | 3.984063745019920250e-03 140 | 3.984063745019920250e-03 141 | 3.984063745019920250e-03 142 | 3.984063745019920250e-03 143 | 3.984063745019920250e-03 144 | 3.984063745019920250e-03 145 | 3.984063745019920250e-03 146 | 3.984063745019920250e-03 147 | 3.984063745019920250e-03 148 | 3.984063745019920250e-03 149 | 3.984063745019920250e-03 150 | 3.984063745019920250e-03 151 | 3.984063745019920250e-03 152 | 3.984063745019920250e-03 153 | 3.984063745019920250e-03 154 | 3.984063745019920250e-03 155 | 3.984063745019920250e-03 156 | 3.984063745019920250e-03 157 | 3.984063745019920250e-03 158 | 3.984063745019920250e-03 159 | 3.984063745019920250e-03 160 | 3.984063745019920250e-03 161 | 3.984063745019920250e-03 162 | 3.984063745019920250e-03 163 | 3.984063745019920250e-03 164 | 3.984063745019920250e-03 165 | 3.984063745019920250e-03 166 | 3.984063745019920250e-03 167 | 3.984063745019920250e-03 168 | 3.984063745019920250e-03 169 | 3.984063745019920250e-03 170 | 3.984063745019920250e-03 171 | 3.984063745019920250e-03 172 | 3.984063745019920250e-03 173 | 3.984063745019920250e-03 174 | 3.984063745019920250e-03 175 | 3.984063745019920250e-03 176 | 3.984063745019920250e-03 177 | 3.984063745019920250e-03 178 | 3.984063745019920250e-03 179 | 3.984063745019920250e-03 180 | 3.984063745019920250e-03 181 | 3.984063745019920250e-03 182 | 3.984063745019920250e-03 183 | 3.984063745019920250e-03 184 | 3.984063745019920250e-03 185 | 3.984063745019920250e-03 186 | 3.984063745019920250e-03 187 | 3.984063745019920250e-03 188 | 3.984063745019920250e-03 189 | 3.984063745019920250e-03 190 | 3.984063745019920250e-03 191 | 3.984063745019920250e-03 192 | 3.984063745019920250e-03 193 | 3.984063745019920250e-03 194 | 3.984063745019920250e-03 195 | 3.984063745019920250e-03 196 | 3.984063745019920250e-03 197 | 3.984063745019920250e-03 198 | 3.984063745019920250e-03 199 | 3.984063745019920250e-03 200 | 3.984063745019920250e-03 201 | 3.984063745019920250e-03 202 | 3.984063745019920250e-03 203 | 3.984063745019920250e-03 204 | 3.984063745019920250e-03 205 | 3.984063745019920250e-03 206 | 3.984063745019920250e-03 207 | 3.984063745019920250e-03 208 | 3.984063745019920250e-03 209 | 3.984063745019920250e-03 210 | 3.984063745019920250e-03 211 | 3.984063745019920250e-03 212 | 3.984063745019920250e-03 213 | 3.984063745019920250e-03 214 | 3.984063745019920250e-03 215 | 3.984063745019920250e-03 216 | 3.984063745019920250e-03 217 | 3.984063745019920250e-03 218 | 3.984063745019920250e-03 219 | 3.984063745019920250e-03 220 | 3.984063745019920250e-03 221 | 3.984063745019920250e-03 222 | 3.984063745019920250e-03 223 | 3.984063745019920250e-03 224 | 3.984063745019920250e-03 225 | 3.984063745019920250e-03 226 | 3.984063745019920250e-03 227 | 3.984063745019920250e-03 228 | 3.984063745019920250e-03 229 | 3.984063745019920250e-03 230 | 3.984063745019920250e-03 231 | 3.984063745019920250e-03 232 | 3.984063745019920250e-03 233 | 3.984063745019920250e-03 234 | 3.984063745019920250e-03 235 | 3.984063745019920250e-03 236 | 3.984063745019920250e-03 237 | 3.984063745019920250e-03 238 | 3.984063745019920250e-03 239 | 3.984063745019920250e-03 240 | 3.984063745019920250e-03 241 | 3.984063745019920250e-03 242 | 3.984063745019920250e-03 243 | 3.984063745019920250e-03 244 | 3.984063745019920250e-03 245 | 3.984063745019920250e-03 246 | 3.984063745019920250e-03 247 | 3.984063745019920250e-03 248 | 3.984063745019920250e-03 249 | 3.984063745019920250e-03 250 | 3.984063745019920250e-03 251 | 3.984063745019920250e-03 252 | -------------------------------------------------------------------------------- /sample_data/slice3_coor.csv: -------------------------------------------------------------------------------- 1 | 2.319000000000000128e+01,8.029999999999999361e+00 2 | 2.191000000000000014e+01,8.945000000000000284e+00 3 | 2.314000000000000057e+01,9.057000000000000384e+00 4 | 1.694000000000000128e+01,9.035999999999999588e+00 5 | 1.508000000000000007e+01,9.051999999999999602e+00 6 | 1.592300000000000004e+01,9.061999999999999389e+00 7 | 2.195299999999999940e+01,9.916999999999999815e+00 8 | 2.321699999999999875e+01,1.003100000000000058e+01 9 | 1.506600000000000072e+01,1.002599999999999980e+01 10 | 1.797500000000000142e+01,1.002299999999999969e+01 11 | 1.399699999999999989e+01,1.002899999999999991e+01 12 | 1.306700000000000017e+01,1.003200000000000003e+01 13 | 1.890500000000000114e+01,1.001399999999999935e+01 14 | 1.697800000000000153e+01,1.003200000000000003e+01 15 | 1.603500000000000014e+01,1.004199999999999982e+01 16 | 2.006400000000000006e+01,1.002899999999999991e+01 17 | 1.898799999999999955e+01,1.088199999999999967e+01 18 | 2.189399999999999835e+01,1.088199999999999967e+01 19 | 1.090000000000000036e+01,1.096599999999999930e+01 20 | 2.097800000000000153e+01,1.096000000000000085e+01 21 | 2.002599999999999980e+01,1.098099999999999987e+01 22 | 2.314399999999999835e+01,1.100699999999999967e+01 23 | 9.878000000000000114e+00,1.102500000000000036e+01 24 | 1.796099999999999852e+01,1.099699999999999989e+01 25 | 1.209699999999999953e+01,1.102999999999999936e+01 26 | 1.694500000000000028e+01,1.101299999999999990e+01 27 | 1.298799999999999955e+01,1.101999999999999957e+01 28 | 1.404899999999999949e+01,1.101999999999999957e+01 29 | 1.497000000000000064e+01,1.103899999999999970e+01 30 | 1.599600000000000044e+01,1.102899999999999991e+01 31 | 2.190200000000000102e+01,1.187599999999999945e+01 32 | 1.081900000000000084e+01,1.190600000000000058e+01 33 | 2.012699999999999889e+01,1.194899999999999984e+01 34 | 1.894800000000000040e+01,1.198199999999999932e+01 35 | 9.917999999999999261e+00,1.198000000000000043e+01 36 | 1.209999999999999964e+01,1.202699999999999925e+01 37 | 1.400799999999999912e+01,1.200500000000000078e+01 38 | 1.305100000000000016e+01,1.200099999999999945e+01 39 | 9.025999999999999801e+00,1.200000000000000000e+01 40 | 1.796600000000000108e+01,1.199699999999999989e+01 41 | 1.503400000000000070e+01,1.200900000000000034e+01 42 | 2.095899999999999963e+01,1.200399999999999956e+01 43 | 1.699399999999999977e+01,1.201500000000000057e+01 44 | 2.319800000000000040e+01,1.204100000000000037e+01 45 | 2.191600000000000037e+01,1.289499999999999957e+01 46 | 1.089400000000000013e+01,1.291300000000000026e+01 47 | 2.006099999999999994e+01,1.295299999999999940e+01 48 | 1.791499999999999915e+01,1.295100000000000051e+01 49 | 2.097899999999999920e+01,1.295599999999999952e+01 50 | 9.041000000000000369e+00,1.295700000000000074e+01 51 | 1.898900000000000077e+01,1.297499999999999964e+01 52 | 2.319099999999999895e+01,1.300600000000000023e+01 53 | 5.921000000000000263e+00,1.299099999999999966e+01 54 | 1.700199999999999889e+01,1.298000000000000043e+01 55 | 1.211100000000000065e+01,1.301699999999999946e+01 56 | 9.872999999999999332e+00,1.298900000000000077e+01 57 | 1.400799999999999912e+01,1.299200000000000088e+01 58 | 6.943999999999999950e+00,1.300300000000000011e+01 59 | 7.852999999999999758e+00,1.299300000000000033e+01 60 | 1.302800000000000047e+01,1.300600000000000023e+01 61 | 1.598199999999999932e+01,1.300699999999999967e+01 62 | 2.404899999999999949e+01,1.300699999999999967e+01 63 | 1.497400000000000020e+01,1.301099999999999923e+01 64 | 2.193499999999999872e+01,1.391499999999999915e+01 65 | 1.083200000000000074e+01,1.396499999999999986e+01 66 | 6.929999999999999716e+00,1.398799999999999955e+01 67 | 2.410399999999999920e+01,1.398499999999999943e+01 68 | 2.315800000000000125e+01,1.401099999999999923e+01 69 | 2.095700000000000074e+01,1.400000000000000000e+01 70 | 2.012800000000000011e+01,1.400399999999999956e+01 71 | 7.918999999999999595e+00,1.402699999999999925e+01 72 | 9.022999999999999687e+00,1.401999999999999957e+01 73 | 9.925000000000000711e+00,1.402999999999999936e+01 74 | 1.899099999999999966e+01,1.406199999999999939e+01 75 | 1.699399999999999977e+01,1.404800000000000004e+01 76 | 1.209500000000000064e+01,1.406900000000000084e+01 77 | 1.600700000000000145e+01,1.405100000000000016e+01 78 | 1.495599999999999952e+01,1.406300000000000061e+01 79 | 1.791700000000000159e+01,1.406700000000000017e+01 80 | 1.404100000000000037e+01,1.407799999999999940e+01 81 | 1.307099999999999973e+01,1.409299999999999997e+01 82 | 2.195799999999999841e+01,1.485100000000000087e+01 83 | 1.086200000000000010e+01,1.489199999999999946e+01 84 | 2.091600000000000037e+01,1.496299999999999919e+01 85 | 7.878999999999999559e+00,1.497799999999999976e+01 86 | 9.063000000000000611e+00,1.497600000000000087e+01 87 | 1.797700000000000031e+01,1.497300000000000075e+01 88 | 6.958999999999999631e+00,1.497400000000000020e+01 89 | 1.693400000000000105e+01,1.497700000000000031e+01 90 | 9.913999999999999702e+00,1.498900000000000077e+01 91 | 1.211100000000000065e+01,1.502599999999999980e+01 92 | 1.599799999999999933e+01,1.499799999999999933e+01 93 | 2.009299999999999997e+01,1.499300000000000033e+01 94 | 1.300600000000000023e+01,1.500900000000000034e+01 95 | 2.316400000000000148e+01,1.502100000000000080e+01 96 | 1.504499999999999993e+01,1.501900000000000013e+01 97 | 2.412900000000000134e+01,1.504700000000000060e+01 98 | 2.192200000000000060e+01,1.587899999999999956e+01 99 | 1.082000000000000028e+01,1.589199999999999946e+01 100 | 2.098300000000000054e+01,1.593200000000000038e+01 101 | 2.001800000000000068e+01,1.594100000000000072e+01 102 | 1.899899999999999878e+01,1.595899999999999963e+01 103 | 9.025999999999999801e+00,1.595800000000000018e+01 104 | 9.952999999999999403e+00,1.594899999999999984e+01 105 | 6.958999999999999631e+00,1.595899999999999963e+01 106 | 2.318900000000000006e+01,1.599799999999999933e+01 107 | 2.411400000000000077e+01,1.597700000000000031e+01 108 | 1.701399999999999935e+01,1.597799999999999976e+01 109 | 1.800499999999999901e+01,1.596199999999999974e+01 110 | 7.902999999999999581e+00,1.597799999999999976e+01 111 | 1.399600000000000044e+01,1.598000000000000043e+01 112 | 1.307000000000000028e+01,1.598399999999999999e+01 113 | 1.207399999999999984e+01,1.601399999999999935e+01 114 | 1.502999999999999936e+01,1.598900000000000077e+01 115 | 1.597799999999999976e+01,1.599699999999999989e+01 116 | 2.192699999999999960e+01,1.689799999999999969e+01 117 | 1.088499999999999979e+01,1.693299999999999983e+01 118 | 1.699200000000000088e+01,1.696300000000000097e+01 119 | 2.091700000000000159e+01,1.697700000000000031e+01 120 | 7.915000000000000036e+00,1.698699999999999832e+01 121 | 1.794900000000000162e+01,1.698900000000000077e+01 122 | 6.937999999999999723e+00,1.699500000000000099e+01 123 | 9.016999999999999460e+00,1.699099999999999966e+01 124 | 2.317999999999999972e+01,1.700700000000000145e+01 125 | 9.862999999999999545e+00,1.700499999999999901e+01 126 | 1.897500000000000142e+01,1.701300000000000168e+01 127 | 2.009700000000000131e+01,1.700600000000000023e+01 128 | 1.401200000000000045e+01,1.702899999999999991e+01 129 | 1.597400000000000020e+01,1.702700000000000102e+01 130 | 1.210100000000000087e+01,1.705799999999999983e+01 131 | 1.303500000000000014e+01,1.704200000000000159e+01 132 | 1.498700000000000010e+01,1.705199999999999960e+01 133 | 2.402799999999999869e+01,1.706700000000000017e+01 134 | 2.189900000000000091e+01,1.787300000000000111e+01 135 | 1.086599999999999966e+01,1.789699999999999847e+01 136 | 1.791600000000000037e+01,1.795799999999999841e+01 137 | 2.096099999999999852e+01,1.794200000000000017e+01 138 | 9.938000000000000611e+00,1.796999999999999886e+01 139 | 1.700100000000000122e+01,1.797500000000000142e+01 140 | 2.008899999999999864e+01,1.797100000000000009e+01 141 | 8.973000000000000753e+00,1.798199999999999932e+01 142 | 7.964999999999999858e+00,1.798499999999999943e+01 143 | 6.875000000000000000e+00,1.800400000000000134e+01 144 | 1.897800000000000153e+01,1.800300000000000011e+01 145 | 1.398700000000000010e+01,1.801000000000000156e+01 146 | 1.500900000000000034e+01,1.801399999999999935e+01 147 | 1.598499999999999943e+01,1.801599999999999824e+01 148 | 2.317299999999999827e+01,1.802299999999999969e+01 149 | 1.307300000000000040e+01,1.801699999999999946e+01 150 | 1.209200000000000053e+01,1.805300000000000082e+01 151 | 2.403600000000000136e+01,1.803000000000000114e+01 152 | 2.190899999999999892e+01,1.884499999999999886e+01 153 | 9.006000000000000227e+00,1.892500000000000071e+01 154 | 1.083200000000000074e+01,1.895799999999999841e+01 155 | 2.010300000000000153e+01,1.895200000000000173e+01 156 | 2.097800000000000153e+01,1.895400000000000063e+01 157 | 1.705000000000000071e+01,1.895899999999999963e+01 158 | 1.790299999999999869e+01,1.896099999999999852e+01 159 | 1.894500000000000028e+01,1.898199999999999932e+01 160 | 1.211299999999999955e+01,1.900400000000000134e+01 161 | 2.317299999999999827e+01,1.898999999999999844e+01 162 | 9.910000000000000142e+00,1.897100000000000009e+01 163 | 1.399000000000000021e+01,1.897599999999999909e+01 164 | 1.303599999999999959e+01,1.898999999999999844e+01 165 | 1.595899999999999963e+01,1.898499999999999943e+01 166 | 2.409400000000000119e+01,1.898400000000000176e+01 167 | 1.502200000000000024e+01,1.899299999999999855e+01 168 | 7.889999999999999680e+00,1.902799999999999869e+01 169 | 2.194800000000000040e+01,1.990099999999999980e+01 170 | 1.084200000000000053e+01,1.990700000000000003e+01 171 | 2.095100000000000051e+01,1.998400000000000176e+01 172 | 2.006899999999999906e+01,1.998799999999999955e+01 173 | 9.057999999999999829e+00,1.999800000000000111e+01 174 | 1.901000000000000156e+01,2.001000000000000156e+01 175 | 1.692599999999999838e+01,2.001500000000000057e+01 176 | 2.317599999999999838e+01,2.002499999999999858e+01 177 | 1.405199999999999960e+01,2.001099999999999923e+01 178 | 7.870000000000000107e+00,2.001800000000000068e+01 179 | 1.601500000000000057e+01,2.002199999999999847e+01 180 | 1.298700000000000010e+01,2.003600000000000136e+01 181 | 1.211299999999999955e+01,2.005600000000000094e+01 182 | 2.412800000000000011e+01,2.004100000000000037e+01 183 | 1.495500000000000007e+01,2.005300000000000082e+01 184 | 1.796099999999999852e+01,2.006200000000000117e+01 185 | 9.967000000000000526e+00,2.011100000000000065e+01 186 | 2.193199999999999861e+01,2.088100000000000023e+01 187 | 1.087700000000000067e+01,2.091600000000000037e+01 188 | 9.910999999999999588e+00,2.096399999999999864e+01 189 | 9.044999999999999929e+00,2.096900000000000119e+01 190 | 1.902599999999999980e+01,2.097400000000000020e+01 191 | 1.703699999999999903e+01,2.096999999999999886e+01 192 | 2.008200000000000074e+01,2.097299999999999898e+01 193 | 1.789600000000000080e+01,2.098199999999999932e+01 194 | 1.306199999999999939e+01,2.098900000000000077e+01 195 | 2.314799999999999969e+01,2.100400000000000134e+01 196 | 1.397499999999999964e+01,2.099599999999999866e+01 197 | 1.596400000000000041e+01,2.099899999999999878e+01 198 | 2.092399999999999949e+01,2.100000000000000000e+01 199 | 1.506199999999999939e+01,2.101200000000000045e+01 200 | 1.212199999999999989e+01,2.103300000000000125e+01 201 | 2.417500000000000071e+01,2.101999999999999957e+01 202 | 2.497200000000000131e+01,2.107199999999999918e+01 203 | 2.195700000000000074e+01,2.190299999999999869e+01 204 | 1.085500000000000043e+01,2.194900000000000162e+01 205 | 1.795100000000000051e+01,2.194500000000000028e+01 206 | 1.705399999999999849e+01,2.196999999999999886e+01 207 | 1.902599999999999980e+01,2.197700000000000031e+01 208 | 2.316000000000000014e+01,2.199800000000000111e+01 209 | 2.093599999999999994e+01,2.198600000000000065e+01 210 | 1.216499999999999915e+01,2.201699999999999946e+01 211 | 2.010000000000000142e+01,2.198799999999999955e+01 212 | 9.929000000000000270e+00,2.199800000000000111e+01 213 | 2.407400000000000162e+01,2.199800000000000111e+01 214 | 1.605399999999999849e+01,2.201399999999999935e+01 215 | 1.406700000000000017e+01,2.201599999999999824e+01 216 | 1.301600000000000001e+01,2.202400000000000091e+01 217 | 1.491600000000000037e+01,2.203000000000000114e+01 218 | 9.003999999999999559e+00,2.202899999999999991e+01 219 | 2.193900000000000006e+01,2.289600000000000080e+01 220 | 1.092999999999999972e+01,2.291400000000000148e+01 221 | 2.317999999999999972e+01,2.302299999999999969e+01 222 | 2.095899999999999963e+01,2.297400000000000020e+01 223 | 2.008999999999999986e+01,2.298799999999999955e+01 224 | 9.071999999999999176e+00,2.299899999999999878e+01 225 | 9.894000000000000128e+00,2.300900000000000034e+01 226 | 1.900499999999999901e+01,2.301200000000000045e+01 227 | 1.802100000000000080e+01,2.301899999999999835e+01 228 | 1.400000000000000000e+01,2.302499999999999858e+01 229 | 1.603600000000000136e+01,2.302400000000000091e+01 230 | 1.698400000000000176e+01,2.303099999999999881e+01 231 | 1.501800000000000068e+01,2.303099999999999881e+01 232 | 2.414699999999999847e+01,2.302899999999999991e+01 233 | 1.212400000000000055e+01,2.306800000000000139e+01 234 | 2.509100000000000108e+01,2.307000000000000028e+01 235 | 1.307199999999999918e+01,2.307999999999999829e+01 236 | 1.901399999999999935e+01,2.393100000000000094e+01 237 | 2.194800000000000040e+01,2.387199999999999989e+01 238 | 1.088899999999999935e+01,2.388100000000000023e+01 239 | 2.096799999999999997e+01,2.396000000000000085e+01 240 | 9.910999999999999588e+00,2.398199999999999932e+01 241 | 1.609499999999999886e+01,2.398000000000000043e+01 242 | 1.701699999999999946e+01,2.397899999999999920e+01 243 | 1.798999999999999844e+01,2.397899999999999920e+01 244 | 2.013800000000000168e+01,2.398799999999999955e+01 245 | 1.401299999999999990e+01,2.398699999999999832e+01 246 | 1.497799999999999976e+01,2.399399999999999977e+01 247 | 1.309099999999999930e+01,2.400199999999999889e+01 248 | 2.410999999999999943e+01,2.401800000000000068e+01 249 | 1.210999999999999943e+01,2.404299999999999926e+01 250 | 2.506500000000000128e+01,2.402700000000000102e+01 251 | 2.316499999999999915e+01,2.407000000000000028e+01 252 | 2.192800000000000082e+01,2.492599999999999838e+01 253 | 1.401099999999999923e+01,2.499399999999999977e+01 254 | 2.104400000000000048e+01,2.499899999999999878e+01 255 | 2.321399999999999864e+01,2.502700000000000102e+01 256 | 2.005999999999999872e+01,2.502299999999999969e+01 257 | 1.317399999999999949e+01,2.502700000000000102e+01 258 | 1.900199999999999889e+01,2.503099999999999881e+01 259 | 1.798000000000000043e+01,2.503699999999999903e+01 260 | 2.505600000000000094e+01,2.504200000000000159e+01 261 | 1.603399999999999892e+01,2.504500000000000171e+01 262 | 1.500000000000000000e+01,2.505600000000000094e+01 263 | 1.703900000000000148e+01,2.505799999999999983e+01 264 | 2.419200000000000017e+01,2.505799999999999983e+01 265 | -------------------------------------------------------------------------------- /sample_data/slice3_uniform_weights.csv: -------------------------------------------------------------------------------- 1 | 3.787878787878787984e-03 2 | 3.787878787878787984e-03 3 | 3.787878787878787984e-03 4 | 3.787878787878787984e-03 5 | 3.787878787878787984e-03 6 | 3.787878787878787984e-03 7 | 3.787878787878787984e-03 8 | 3.787878787878787984e-03 9 | 3.787878787878787984e-03 10 | 3.787878787878787984e-03 11 | 3.787878787878787984e-03 12 | 3.787878787878787984e-03 13 | 3.787878787878787984e-03 14 | 3.787878787878787984e-03 15 | 3.787878787878787984e-03 16 | 3.787878787878787984e-03 17 | 3.787878787878787984e-03 18 | 3.787878787878787984e-03 19 | 3.787878787878787984e-03 20 | 3.787878787878787984e-03 21 | 3.787878787878787984e-03 22 | 3.787878787878787984e-03 23 | 3.787878787878787984e-03 24 | 3.787878787878787984e-03 25 | 3.787878787878787984e-03 26 | 3.787878787878787984e-03 27 | 3.787878787878787984e-03 28 | 3.787878787878787984e-03 29 | 3.787878787878787984e-03 30 | 3.787878787878787984e-03 31 | 3.787878787878787984e-03 32 | 3.787878787878787984e-03 33 | 3.787878787878787984e-03 34 | 3.787878787878787984e-03 35 | 3.787878787878787984e-03 36 | 3.787878787878787984e-03 37 | 3.787878787878787984e-03 38 | 3.787878787878787984e-03 39 | 3.787878787878787984e-03 40 | 3.787878787878787984e-03 41 | 3.787878787878787984e-03 42 | 3.787878787878787984e-03 43 | 3.787878787878787984e-03 44 | 3.787878787878787984e-03 45 | 3.787878787878787984e-03 46 | 3.787878787878787984e-03 47 | 3.787878787878787984e-03 48 | 3.787878787878787984e-03 49 | 3.787878787878787984e-03 50 | 3.787878787878787984e-03 51 | 3.787878787878787984e-03 52 | 3.787878787878787984e-03 53 | 3.787878787878787984e-03 54 | 3.787878787878787984e-03 55 | 3.787878787878787984e-03 56 | 3.787878787878787984e-03 57 | 3.787878787878787984e-03 58 | 3.787878787878787984e-03 59 | 3.787878787878787984e-03 60 | 3.787878787878787984e-03 61 | 3.787878787878787984e-03 62 | 3.787878787878787984e-03 63 | 3.787878787878787984e-03 64 | 3.787878787878787984e-03 65 | 3.787878787878787984e-03 66 | 3.787878787878787984e-03 67 | 3.787878787878787984e-03 68 | 3.787878787878787984e-03 69 | 3.787878787878787984e-03 70 | 3.787878787878787984e-03 71 | 3.787878787878787984e-03 72 | 3.787878787878787984e-03 73 | 3.787878787878787984e-03 74 | 3.787878787878787984e-03 75 | 3.787878787878787984e-03 76 | 3.787878787878787984e-03 77 | 3.787878787878787984e-03 78 | 3.787878787878787984e-03 79 | 3.787878787878787984e-03 80 | 3.787878787878787984e-03 81 | 3.787878787878787984e-03 82 | 3.787878787878787984e-03 83 | 3.787878787878787984e-03 84 | 3.787878787878787984e-03 85 | 3.787878787878787984e-03 86 | 3.787878787878787984e-03 87 | 3.787878787878787984e-03 88 | 3.787878787878787984e-03 89 | 3.787878787878787984e-03 90 | 3.787878787878787984e-03 91 | 3.787878787878787984e-03 92 | 3.787878787878787984e-03 93 | 3.787878787878787984e-03 94 | 3.787878787878787984e-03 95 | 3.787878787878787984e-03 96 | 3.787878787878787984e-03 97 | 3.787878787878787984e-03 98 | 3.787878787878787984e-03 99 | 3.787878787878787984e-03 100 | 3.787878787878787984e-03 101 | 3.787878787878787984e-03 102 | 3.787878787878787984e-03 103 | 3.787878787878787984e-03 104 | 3.787878787878787984e-03 105 | 3.787878787878787984e-03 106 | 3.787878787878787984e-03 107 | 3.787878787878787984e-03 108 | 3.787878787878787984e-03 109 | 3.787878787878787984e-03 110 | 3.787878787878787984e-03 111 | 3.787878787878787984e-03 112 | 3.787878787878787984e-03 113 | 3.787878787878787984e-03 114 | 3.787878787878787984e-03 115 | 3.787878787878787984e-03 116 | 3.787878787878787984e-03 117 | 3.787878787878787984e-03 118 | 3.787878787878787984e-03 119 | 3.787878787878787984e-03 120 | 3.787878787878787984e-03 121 | 3.787878787878787984e-03 122 | 3.787878787878787984e-03 123 | 3.787878787878787984e-03 124 | 3.787878787878787984e-03 125 | 3.787878787878787984e-03 126 | 3.787878787878787984e-03 127 | 3.787878787878787984e-03 128 | 3.787878787878787984e-03 129 | 3.787878787878787984e-03 130 | 3.787878787878787984e-03 131 | 3.787878787878787984e-03 132 | 3.787878787878787984e-03 133 | 3.787878787878787984e-03 134 | 3.787878787878787984e-03 135 | 3.787878787878787984e-03 136 | 3.787878787878787984e-03 137 | 3.787878787878787984e-03 138 | 3.787878787878787984e-03 139 | 3.787878787878787984e-03 140 | 3.787878787878787984e-03 141 | 3.787878787878787984e-03 142 | 3.787878787878787984e-03 143 | 3.787878787878787984e-03 144 | 3.787878787878787984e-03 145 | 3.787878787878787984e-03 146 | 3.787878787878787984e-03 147 | 3.787878787878787984e-03 148 | 3.787878787878787984e-03 149 | 3.787878787878787984e-03 150 | 3.787878787878787984e-03 151 | 3.787878787878787984e-03 152 | 3.787878787878787984e-03 153 | 3.787878787878787984e-03 154 | 3.787878787878787984e-03 155 | 3.787878787878787984e-03 156 | 3.787878787878787984e-03 157 | 3.787878787878787984e-03 158 | 3.787878787878787984e-03 159 | 3.787878787878787984e-03 160 | 3.787878787878787984e-03 161 | 3.787878787878787984e-03 162 | 3.787878787878787984e-03 163 | 3.787878787878787984e-03 164 | 3.787878787878787984e-03 165 | 3.787878787878787984e-03 166 | 3.787878787878787984e-03 167 | 3.787878787878787984e-03 168 | 3.787878787878787984e-03 169 | 3.787878787878787984e-03 170 | 3.787878787878787984e-03 171 | 3.787878787878787984e-03 172 | 3.787878787878787984e-03 173 | 3.787878787878787984e-03 174 | 3.787878787878787984e-03 175 | 3.787878787878787984e-03 176 | 3.787878787878787984e-03 177 | 3.787878787878787984e-03 178 | 3.787878787878787984e-03 179 | 3.787878787878787984e-03 180 | 3.787878787878787984e-03 181 | 3.787878787878787984e-03 182 | 3.787878787878787984e-03 183 | 3.787878787878787984e-03 184 | 3.787878787878787984e-03 185 | 3.787878787878787984e-03 186 | 3.787878787878787984e-03 187 | 3.787878787878787984e-03 188 | 3.787878787878787984e-03 189 | 3.787878787878787984e-03 190 | 3.787878787878787984e-03 191 | 3.787878787878787984e-03 192 | 3.787878787878787984e-03 193 | 3.787878787878787984e-03 194 | 3.787878787878787984e-03 195 | 3.787878787878787984e-03 196 | 3.787878787878787984e-03 197 | 3.787878787878787984e-03 198 | 3.787878787878787984e-03 199 | 3.787878787878787984e-03 200 | 3.787878787878787984e-03 201 | 3.787878787878787984e-03 202 | 3.787878787878787984e-03 203 | 3.787878787878787984e-03 204 | 3.787878787878787984e-03 205 | 3.787878787878787984e-03 206 | 3.787878787878787984e-03 207 | 3.787878787878787984e-03 208 | 3.787878787878787984e-03 209 | 3.787878787878787984e-03 210 | 3.787878787878787984e-03 211 | 3.787878787878787984e-03 212 | 3.787878787878787984e-03 213 | 3.787878787878787984e-03 214 | 3.787878787878787984e-03 215 | 3.787878787878787984e-03 216 | 3.787878787878787984e-03 217 | 3.787878787878787984e-03 218 | 3.787878787878787984e-03 219 | 3.787878787878787984e-03 220 | 3.787878787878787984e-03 221 | 3.787878787878787984e-03 222 | 3.787878787878787984e-03 223 | 3.787878787878787984e-03 224 | 3.787878787878787984e-03 225 | 3.787878787878787984e-03 226 | 3.787878787878787984e-03 227 | 3.787878787878787984e-03 228 | 3.787878787878787984e-03 229 | 3.787878787878787984e-03 230 | 3.787878787878787984e-03 231 | 3.787878787878787984e-03 232 | 3.787878787878787984e-03 233 | 3.787878787878787984e-03 234 | 3.787878787878787984e-03 235 | 3.787878787878787984e-03 236 | 3.787878787878787984e-03 237 | 3.787878787878787984e-03 238 | 3.787878787878787984e-03 239 | 3.787878787878787984e-03 240 | 3.787878787878787984e-03 241 | 3.787878787878787984e-03 242 | 3.787878787878787984e-03 243 | 3.787878787878787984e-03 244 | 3.787878787878787984e-03 245 | 3.787878787878787984e-03 246 | 3.787878787878787984e-03 247 | 3.787878787878787984e-03 248 | 3.787878787878787984e-03 249 | 3.787878787878787984e-03 250 | 3.787878787878787984e-03 251 | 3.787878787878787984e-03 252 | 3.787878787878787984e-03 253 | 3.787878787878787984e-03 254 | 3.787878787878787984e-03 255 | 3.787878787878787984e-03 256 | 3.787878787878787984e-03 257 | 3.787878787878787984e-03 258 | 3.787878787878787984e-03 259 | 3.787878787878787984e-03 260 | 3.787878787878787984e-03 261 | 3.787878787878787984e-03 262 | 3.787878787878787984e-03 263 | 3.787878787878787984e-03 264 | 3.787878787878787984e-03 265 | -------------------------------------------------------------------------------- /sample_data/slice4_coor.csv: -------------------------------------------------------------------------------- 1 | 1.889000000000000057e+01,8.958000000000000185e+00 2 | 1.790200000000000102e+01,8.961999999999999744e+00 3 | 1.302899999999999991e+01,9.007999999999999119e+00 4 | 1.682400000000000162e+01,8.994999999999999218e+00 5 | 1.394800000000000040e+01,9.022000000000000242e+00 6 | 1.595500000000000007e+01,9.009000000000000341e+00 7 | 1.208300000000000018e+01,9.045999999999999375e+00 8 | 1.487500000000000000e+01,9.054999999999999716e+00 9 | 2.189600000000000080e+01,9.877000000000000668e+00 10 | 2.085500000000000043e+01,9.923999999999999488e+00 11 | 1.995799999999999841e+01,9.955999999999999517e+00 12 | 1.789399999999999835e+01,9.980000000000000426e+00 13 | 2.311499999999999844e+01,1.000399999999999956e+01 14 | 1.396599999999999930e+01,1.000000000000000000e+01 15 | 1.889000000000000057e+01,9.980000000000000426e+00 16 | 1.689300000000000068e+01,9.996000000000000441e+00 17 | 1.598900000000000077e+01,1.000399999999999956e+01 18 | 1.488100000000000023e+01,1.001200000000000045e+01 19 | 2.189600000000000080e+01,1.086700000000000088e+01 20 | 2.087300000000000111e+01,1.093099999999999916e+01 21 | 1.893499999999999872e+01,1.095100000000000051e+01 22 | 2.406500000000000128e+01,1.095599999999999952e+01 23 | 1.993499999999999872e+01,1.097899999999999920e+01 24 | 1.789399999999999835e+01,1.096199999999999974e+01 25 | 1.198199999999999932e+01,1.100099999999999945e+01 26 | 1.290600000000000058e+01,1.098300000000000054e+01 27 | 1.592399999999999949e+01,1.098300000000000054e+01 28 | 2.307100000000000151e+01,1.101099999999999923e+01 29 | 1.486700000000000088e+01,1.099399999999999977e+01 30 | 1.688200000000000145e+01,1.099200000000000088e+01 31 | 1.401699999999999946e+01,1.099399999999999977e+01 32 | 2.184600000000000009e+01,1.185800000000000054e+01 33 | 2.090899999999999892e+01,1.191499999999999915e+01 34 | 1.899299999999999855e+01,1.195299999999999940e+01 35 | 2.997100000000000009e+01,1.194800000000000040e+01 36 | 1.295599999999999952e+01,1.196199999999999974e+01 37 | 1.689999999999999858e+01,1.196400000000000041e+01 38 | 1.787000000000000099e+01,1.196400000000000041e+01 39 | 2.596600000000000108e+01,1.196799999999999997e+01 40 | 1.392999999999999972e+01,1.197899999999999920e+01 41 | 2.311199999999999832e+01,1.197899999999999920e+01 42 | 1.594500000000000028e+01,1.198499999999999943e+01 43 | 2.501099999999999923e+01,1.197499999999999964e+01 44 | 1.201299999999999990e+01,1.203500000000000014e+01 45 | 1.493900000000000006e+01,1.200999999999999979e+01 46 | 2.403800000000000026e+01,1.199499999999999922e+01 47 | 2.187800000000000011e+01,1.286400000000000077e+01 48 | 2.089699999999999847e+01,1.291200000000000081e+01 49 | 1.894800000000000040e+01,1.293800000000000061e+01 50 | 2.900199999999999889e+01,1.294800000000000040e+01 51 | 1.783999999999999986e+01,1.294599999999999973e+01 52 | 1.997800000000000153e+01,1.295700000000000074e+01 53 | 2.597800000000000153e+01,1.294899999999999984e+01 54 | 1.389799999999999969e+01,1.295400000000000063e+01 55 | 1.693100000000000094e+01,1.295500000000000007e+01 56 | 2.411799999999999855e+01,1.294999999999999929e+01 57 | 2.798100000000000165e+01,1.295299999999999940e+01 58 | 2.995899999999999963e+01,1.294599999999999973e+01 59 | 1.295800000000000018e+01,1.296100000000000030e+01 60 | 2.702899999999999991e+01,1.296000000000000085e+01 61 | 1.201699999999999946e+01,1.299099999999999966e+01 62 | 2.499599999999999866e+01,1.294500000000000028e+01 63 | 1.492099999999999937e+01,1.297300000000000075e+01 64 | 1.592699999999999960e+01,1.298000000000000043e+01 65 | 2.304899999999999949e+01,1.299900000000000055e+01 66 | 2.188400000000000034e+01,1.391099999999999959e+01 67 | 2.601899999999999835e+01,1.393200000000000038e+01 68 | 2.890099999999999980e+01,1.391799999999999926e+01 69 | 2.698600000000000065e+01,1.393800000000000061e+01 70 | 2.307700000000000173e+01,1.396000000000000085e+01 71 | 2.406700000000000017e+01,1.394200000000000017e+01 72 | 2.801699999999999946e+01,1.394599999999999973e+01 73 | 1.790399999999999991e+01,1.396599999999999930e+01 74 | 2.086199999999999832e+01,1.395100000000000051e+01 75 | 2.498699999999999832e+01,1.394999999999999929e+01 76 | 1.688599999999999923e+01,1.396400000000000041e+01 77 | 2.002199999999999847e+01,1.397799999999999976e+01 78 | 1.892599999999999838e+01,1.400799999999999912e+01 79 | 1.595899999999999963e+01,1.402100000000000080e+01 80 | 1.296299999999999919e+01,1.401999999999999957e+01 81 | 1.391099999999999959e+01,1.403100000000000058e+01 82 | 1.201500000000000057e+01,1.406300000000000061e+01 83 | 1.495500000000000007e+01,1.404199999999999982e+01 84 | 2.187199999999999989e+01,1.484800000000000075e+01 85 | 1.078800000000000026e+01,1.486200000000000010e+01 86 | 2.090500000000000114e+01,1.490300000000000047e+01 87 | 2.000400000000000134e+01,1.494699999999999918e+01 88 | 2.898999999999999844e+01,1.491499999999999915e+01 89 | 1.300699999999999967e+01,1.495500000000000007e+01 90 | 1.692099999999999937e+01,1.494599999999999973e+01 91 | 1.785099999999999909e+01,1.494500000000000028e+01 92 | 1.895100000000000051e+01,1.495400000000000063e+01 93 | 2.703999999999999915e+01,1.494299999999999962e+01 94 | 1.594599999999999973e+01,1.495700000000000074e+01 95 | 2.500799999999999912e+01,1.496199999999999974e+01 96 | 1.488299999999999912e+01,1.497000000000000064e+01 97 | 2.592800000000000082e+01,1.496000000000000085e+01 98 | 2.793299999999999983e+01,1.495899999999999963e+01 99 | 1.201500000000000057e+01,1.500099999999999945e+01 100 | 1.393800000000000061e+01,1.497499999999999964e+01 101 | 2.304700000000000060e+01,1.500200000000000067e+01 102 | 2.186299999999999955e+01,1.582900000000000063e+01 103 | 1.078800000000000026e+01,1.585299999999999976e+01 104 | 2.087300000000000111e+01,1.589799999999999969e+01 105 | 2.411100000000000065e+01,1.591399999999999970e+01 106 | 2.000000000000000000e+01,1.591999999999999993e+01 107 | 2.605199999999999960e+01,1.592600000000000016e+01 108 | 1.301900000000000013e+01,1.593800000000000061e+01 109 | 1.787800000000000011e+01,1.593599999999999994e+01 110 | 2.495499999999999829e+01,1.593299999999999983e+01 111 | 2.798000000000000043e+01,1.593999999999999950e+01 112 | 1.400500000000000078e+01,1.593399999999999928e+01 113 | 1.597400000000000020e+01,1.593800000000000061e+01 114 | 1.692200000000000060e+01,1.594200000000000017e+01 115 | 1.890299999999999869e+01,1.595100000000000051e+01 116 | 1.482099999999999973e+01,1.595899999999999963e+01 117 | 2.699299999999999855e+01,1.596400000000000041e+01 118 | 2.305499999999999972e+01,1.598099999999999987e+01 119 | 1.195299999999999940e+01,1.601500000000000057e+01 120 | 1.076500000000000057e+01,1.686100000000000065e+01 121 | 2.189699999999999847e+01,1.689000000000000057e+01 122 | 1.496599999999999930e+01,1.687199999999999989e+01 123 | 2.796199999999999974e+01,1.695299999999999940e+01 124 | 2.008800000000000097e+01,1.694999999999999929e+01 125 | 1.791700000000000159e+01,1.695400000000000063e+01 126 | 2.084499999999999886e+01,1.696699999999999875e+01 127 | 2.703900000000000148e+01,1.696499999999999986e+01 128 | 1.690399999999999991e+01,1.698400000000000176e+01 129 | 1.887300000000000111e+01,1.698300000000000054e+01 130 | 1.593099999999999916e+01,1.699500000000000099e+01 131 | 1.198700000000000010e+01,1.704500000000000171e+01 132 | 2.593799999999999883e+01,1.701999999999999957e+01 133 | 2.312000000000000099e+01,1.704400000000000048e+01 134 | 2.504700000000000060e+01,1.702100000000000080e+01 135 | 2.399399999999999977e+01,1.703800000000000026e+01 136 | 1.301699999999999946e+01,1.703399999999999892e+01 137 | 1.384299999999999997e+01,1.703800000000000026e+01 138 | 1.080400000000000027e+01,1.784100000000000108e+01 139 | 2.185999999999999943e+01,1.785500000000000043e+01 140 | 2.001899999999999835e+01,1.791400000000000148e+01 141 | 2.089799999999999969e+01,1.791700000000000159e+01 142 | 1.788899999999999935e+01,1.792299999999999827e+01 143 | 1.201299999999999990e+01,1.798300000000000054e+01 144 | 2.707700000000000173e+01,1.793400000000000105e+01 145 | 1.890700000000000003e+01,1.794399999999999906e+01 146 | 2.792999999999999972e+01,1.794999999999999929e+01 147 | 2.410200000000000031e+01,1.795400000000000063e+01 148 | 1.297899999999999920e+01,1.796300000000000097e+01 149 | 1.490799999999999947e+01,1.795799999999999841e+01 150 | 1.597100000000000009e+01,1.796399999999999864e+01 151 | 1.391999999999999993e+01,1.797599999999999909e+01 152 | 2.496900000000000119e+01,1.797700000000000031e+01 153 | 1.686799999999999855e+01,1.800300000000000011e+01 154 | 2.596499999999999986e+01,1.799200000000000088e+01 155 | 2.308800000000000097e+01,1.804500000000000171e+01 156 | 2.187399999999999878e+01,1.885800000000000054e+01 157 | 1.079899999999999949e+01,1.891600000000000037e+01 158 | 1.786400000000000077e+01,1.889099999999999824e+01 159 | 1.996399999999999864e+01,1.891499999999999915e+01 160 | 2.089699999999999847e+01,1.892099999999999937e+01 161 | 1.896699999999999875e+01,1.892399999999999949e+01 162 | 2.307400000000000162e+01,1.894399999999999906e+01 163 | 1.695700000000000074e+01,1.892899999999999849e+01 164 | 1.295299999999999940e+01,1.894500000000000028e+01 165 | 1.586400000000000077e+01,1.894200000000000017e+01 166 | 2.599699999999999989e+01,1.893599999999999994e+01 167 | 2.701800000000000068e+01,1.893599999999999994e+01 168 | 1.393599999999999994e+01,1.894800000000000040e+01 169 | 2.501800000000000068e+01,1.894600000000000151e+01 170 | 1.200699999999999967e+01,1.898699999999999832e+01 171 | 1.494800000000000040e+01,1.896000000000000085e+01 172 | 2.404100000000000037e+01,1.897599999999999909e+01 173 | 1.079199999999999982e+01,1.983899999999999864e+01 174 | 2.189199999999999946e+01,1.987900000000000134e+01 175 | 2.089199999999999946e+01,1.992899999999999849e+01 176 | 1.787300000000000111e+01,1.994500000000000028e+01 177 | 1.998999999999999844e+01,1.994999999999999929e+01 178 | 1.894500000000000028e+01,1.996000000000000085e+01 179 | 2.695499999999999829e+01,1.996300000000000097e+01 180 | 2.409600000000000009e+01,1.997100000000000009e+01 181 | 1.595599999999999952e+01,1.998499999999999943e+01 182 | 1.492300000000000004e+01,1.999599999999999866e+01 183 | 2.304299999999999926e+01,2.000799999999999912e+01 184 | 1.687199999999999989e+01,1.999500000000000099e+01 185 | 1.388199999999999967e+01,2.001500000000000057e+01 186 | 2.504299999999999926e+01,2.001899999999999835e+01 187 | 2.593599999999999994e+01,2.002100000000000080e+01 188 | 1.199699999999999989e+01,2.005199999999999960e+01 189 | 1.301200000000000045e+01,2.003800000000000026e+01 190 | 2.189399999999999835e+01,2.082400000000000162e+01 191 | 2.092200000000000060e+01,2.091000000000000014e+01 192 | 1.790399999999999991e+01,2.093199999999999861e+01 193 | 1.896000000000000085e+01,2.093499999999999872e+01 194 | 1.994800000000000040e+01,2.093599999999999994e+01 195 | 1.597100000000000009e+01,2.094600000000000151e+01 196 | 1.298499999999999943e+01,2.096600000000000108e+01 197 | 2.601099999999999923e+01,2.094699999999999918e+01 198 | 1.686899999999999977e+01,2.094800000000000040e+01 199 | 1.397400000000000020e+01,2.096300000000000097e+01 200 | 1.486599999999999966e+01,2.097599999999999909e+01 201 | 2.497299999999999898e+01,2.097800000000000153e+01 202 | 1.198199999999999932e+01,2.103699999999999903e+01 203 | 2.304899999999999949e+01,2.104299999999999926e+01 204 | 2.093799999999999883e+01,2.188899999999999935e+01 205 | 2.410800000000000054e+01,2.191199999999999903e+01 206 | 2.188500000000000156e+01,2.194399999999999906e+01 207 | 2.498199999999999932e+01,2.192800000000000082e+01 208 | 1.788500000000000156e+01,2.194200000000000017e+01 209 | 2.597899999999999920e+01,2.192800000000000082e+01 210 | 1.694999999999999929e+01,2.194800000000000040e+01 211 | 2.303000000000000114e+01,2.196199999999999974e+01 212 | 2.000000000000000000e+01,2.196799999999999997e+01 213 | 1.899200000000000088e+01,2.197500000000000142e+01 214 | 1.397899999999999920e+01,2.199399999999999977e+01 215 | 1.590300000000000047e+01,2.199899999999999878e+01 216 | 1.293500000000000050e+01,2.201000000000000156e+01 217 | 1.493299999999999983e+01,2.201699999999999946e+01 218 | 2.189600000000000080e+01,2.282700000000000173e+01 219 | 1.787099999999999866e+01,2.291400000000000148e+01 220 | 2.092099999999999937e+01,2.291600000000000037e+01 221 | 1.896699999999999875e+01,2.293100000000000094e+01 222 | 1.695299999999999940e+01,2.294399999999999906e+01 223 | 1.997800000000000153e+01,2.297800000000000153e+01 224 | 1.596199999999999974e+01,2.298199999999999932e+01 225 | 1.392699999999999960e+01,2.298600000000000065e+01 226 | 1.491999999999999993e+01,2.299800000000000111e+01 227 | 2.499399999999999977e+01,2.300300000000000011e+01 228 | 2.406700000000000017e+01,2.301999999999999957e+01 229 | 2.314099999999999824e+01,2.305499999999999972e+01 230 | 2.189600000000000080e+01,2.382799999999999940e+01 231 | 1.894699999999999918e+01,2.394699999999999918e+01 232 | 2.091400000000000148e+01,2.388700000000000045e+01 233 | 1.689499999999999957e+01,2.392200000000000060e+01 234 | 1.797100000000000009e+01,2.391700000000000159e+01 235 | 1.996099999999999852e+01,2.392000000000000171e+01 236 | 2.407100000000000151e+01,2.392599999999999838e+01 237 | 1.595800000000000018e+01,2.394900000000000162e+01 238 | 1.490000000000000036e+01,2.395799999999999841e+01 239 | 2.310699999999999932e+01,2.396600000000000108e+01 240 | 2.507199999999999918e+01,2.400000000000000000e+01 241 | 2.191600000000000037e+01,2.487600000000000122e+01 242 | 2.087800000000000011e+01,2.495299999999999940e+01 243 | 1.790700000000000003e+01,2.495700000000000074e+01 244 | 2.503500000000000014e+01,2.499399999999999977e+01 245 | 2.001099999999999923e+01,2.499500000000000099e+01 246 | 1.895299999999999940e+01,2.499899999999999878e+01 247 | 2.313299999999999912e+01,2.502899999999999991e+01 248 | 1.688200000000000145e+01,2.502700000000000102e+01 249 | 2.402700000000000102e+01,2.501300000000000168e+01 250 | 2.192200000000000060e+01,2.582700000000000173e+01 251 | 2.091900000000000048e+01,2.591900000000000048e+01 252 | 1.790700000000000003e+01,2.592500000000000071e+01 253 | 1.896600000000000108e+01,2.594300000000000139e+01 254 | 1.995299999999999940e+01,2.595799999999999841e+01 255 | 2.414000000000000057e+01,2.601399999999999935e+01 256 | 2.305600000000000094e+01,2.604500000000000171e+01 257 | 2.192800000000000082e+01,2.684799999999999898e+01 258 | 2.096699999999999875e+01,2.692599999999999838e+01 259 | 2.412699999999999889e+01,2.697200000000000131e+01 260 | 2.306200000000000117e+01,2.705199999999999960e+01 261 | 2.192399999999999949e+01,2.786499999999999844e+01 262 | 2.314900000000000091e+01,2.803900000000000148e+01 263 | -------------------------------------------------------------------------------- /sample_data/slice4_uniform_weights.csv: -------------------------------------------------------------------------------- 1 | 3.816793893129770843e-03 2 | 3.816793893129770843e-03 3 | 3.816793893129770843e-03 4 | 3.816793893129770843e-03 5 | 3.816793893129770843e-03 6 | 3.816793893129770843e-03 7 | 3.816793893129770843e-03 8 | 3.816793893129770843e-03 9 | 3.816793893129770843e-03 10 | 3.816793893129770843e-03 11 | 3.816793893129770843e-03 12 | 3.816793893129770843e-03 13 | 3.816793893129770843e-03 14 | 3.816793893129770843e-03 15 | 3.816793893129770843e-03 16 | 3.816793893129770843e-03 17 | 3.816793893129770843e-03 18 | 3.816793893129770843e-03 19 | 3.816793893129770843e-03 20 | 3.816793893129770843e-03 21 | 3.816793893129770843e-03 22 | 3.816793893129770843e-03 23 | 3.816793893129770843e-03 24 | 3.816793893129770843e-03 25 | 3.816793893129770843e-03 26 | 3.816793893129770843e-03 27 | 3.816793893129770843e-03 28 | 3.816793893129770843e-03 29 | 3.816793893129770843e-03 30 | 3.816793893129770843e-03 31 | 3.816793893129770843e-03 32 | 3.816793893129770843e-03 33 | 3.816793893129770843e-03 34 | 3.816793893129770843e-03 35 | 3.816793893129770843e-03 36 | 3.816793893129770843e-03 37 | 3.816793893129770843e-03 38 | 3.816793893129770843e-03 39 | 3.816793893129770843e-03 40 | 3.816793893129770843e-03 41 | 3.816793893129770843e-03 42 | 3.816793893129770843e-03 43 | 3.816793893129770843e-03 44 | 3.816793893129770843e-03 45 | 3.816793893129770843e-03 46 | 3.816793893129770843e-03 47 | 3.816793893129770843e-03 48 | 3.816793893129770843e-03 49 | 3.816793893129770843e-03 50 | 3.816793893129770843e-03 51 | 3.816793893129770843e-03 52 | 3.816793893129770843e-03 53 | 3.816793893129770843e-03 54 | 3.816793893129770843e-03 55 | 3.816793893129770843e-03 56 | 3.816793893129770843e-03 57 | 3.816793893129770843e-03 58 | 3.816793893129770843e-03 59 | 3.816793893129770843e-03 60 | 3.816793893129770843e-03 61 | 3.816793893129770843e-03 62 | 3.816793893129770843e-03 63 | 3.816793893129770843e-03 64 | 3.816793893129770843e-03 65 | 3.816793893129770843e-03 66 | 3.816793893129770843e-03 67 | 3.816793893129770843e-03 68 | 3.816793893129770843e-03 69 | 3.816793893129770843e-03 70 | 3.816793893129770843e-03 71 | 3.816793893129770843e-03 72 | 3.816793893129770843e-03 73 | 3.816793893129770843e-03 74 | 3.816793893129770843e-03 75 | 3.816793893129770843e-03 76 | 3.816793893129770843e-03 77 | 3.816793893129770843e-03 78 | 3.816793893129770843e-03 79 | 3.816793893129770843e-03 80 | 3.816793893129770843e-03 81 | 3.816793893129770843e-03 82 | 3.816793893129770843e-03 83 | 3.816793893129770843e-03 84 | 3.816793893129770843e-03 85 | 3.816793893129770843e-03 86 | 3.816793893129770843e-03 87 | 3.816793893129770843e-03 88 | 3.816793893129770843e-03 89 | 3.816793893129770843e-03 90 | 3.816793893129770843e-03 91 | 3.816793893129770843e-03 92 | 3.816793893129770843e-03 93 | 3.816793893129770843e-03 94 | 3.816793893129770843e-03 95 | 3.816793893129770843e-03 96 | 3.816793893129770843e-03 97 | 3.816793893129770843e-03 98 | 3.816793893129770843e-03 99 | 3.816793893129770843e-03 100 | 3.816793893129770843e-03 101 | 3.816793893129770843e-03 102 | 3.816793893129770843e-03 103 | 3.816793893129770843e-03 104 | 3.816793893129770843e-03 105 | 3.816793893129770843e-03 106 | 3.816793893129770843e-03 107 | 3.816793893129770843e-03 108 | 3.816793893129770843e-03 109 | 3.816793893129770843e-03 110 | 3.816793893129770843e-03 111 | 3.816793893129770843e-03 112 | 3.816793893129770843e-03 113 | 3.816793893129770843e-03 114 | 3.816793893129770843e-03 115 | 3.816793893129770843e-03 116 | 3.816793893129770843e-03 117 | 3.816793893129770843e-03 118 | 3.816793893129770843e-03 119 | 3.816793893129770843e-03 120 | 3.816793893129770843e-03 121 | 3.816793893129770843e-03 122 | 3.816793893129770843e-03 123 | 3.816793893129770843e-03 124 | 3.816793893129770843e-03 125 | 3.816793893129770843e-03 126 | 3.816793893129770843e-03 127 | 3.816793893129770843e-03 128 | 3.816793893129770843e-03 129 | 3.816793893129770843e-03 130 | 3.816793893129770843e-03 131 | 3.816793893129770843e-03 132 | 3.816793893129770843e-03 133 | 3.816793893129770843e-03 134 | 3.816793893129770843e-03 135 | 3.816793893129770843e-03 136 | 3.816793893129770843e-03 137 | 3.816793893129770843e-03 138 | 3.816793893129770843e-03 139 | 3.816793893129770843e-03 140 | 3.816793893129770843e-03 141 | 3.816793893129770843e-03 142 | 3.816793893129770843e-03 143 | 3.816793893129770843e-03 144 | 3.816793893129770843e-03 145 | 3.816793893129770843e-03 146 | 3.816793893129770843e-03 147 | 3.816793893129770843e-03 148 | 3.816793893129770843e-03 149 | 3.816793893129770843e-03 150 | 3.816793893129770843e-03 151 | 3.816793893129770843e-03 152 | 3.816793893129770843e-03 153 | 3.816793893129770843e-03 154 | 3.816793893129770843e-03 155 | 3.816793893129770843e-03 156 | 3.816793893129770843e-03 157 | 3.816793893129770843e-03 158 | 3.816793893129770843e-03 159 | 3.816793893129770843e-03 160 | 3.816793893129770843e-03 161 | 3.816793893129770843e-03 162 | 3.816793893129770843e-03 163 | 3.816793893129770843e-03 164 | 3.816793893129770843e-03 165 | 3.816793893129770843e-03 166 | 3.816793893129770843e-03 167 | 3.816793893129770843e-03 168 | 3.816793893129770843e-03 169 | 3.816793893129770843e-03 170 | 3.816793893129770843e-03 171 | 3.816793893129770843e-03 172 | 3.816793893129770843e-03 173 | 3.816793893129770843e-03 174 | 3.816793893129770843e-03 175 | 3.816793893129770843e-03 176 | 3.816793893129770843e-03 177 | 3.816793893129770843e-03 178 | 3.816793893129770843e-03 179 | 3.816793893129770843e-03 180 | 3.816793893129770843e-03 181 | 3.816793893129770843e-03 182 | 3.816793893129770843e-03 183 | 3.816793893129770843e-03 184 | 3.816793893129770843e-03 185 | 3.816793893129770843e-03 186 | 3.816793893129770843e-03 187 | 3.816793893129770843e-03 188 | 3.816793893129770843e-03 189 | 3.816793893129770843e-03 190 | 3.816793893129770843e-03 191 | 3.816793893129770843e-03 192 | 3.816793893129770843e-03 193 | 3.816793893129770843e-03 194 | 3.816793893129770843e-03 195 | 3.816793893129770843e-03 196 | 3.816793893129770843e-03 197 | 3.816793893129770843e-03 198 | 3.816793893129770843e-03 199 | 3.816793893129770843e-03 200 | 3.816793893129770843e-03 201 | 3.816793893129770843e-03 202 | 3.816793893129770843e-03 203 | 3.816793893129770843e-03 204 | 3.816793893129770843e-03 205 | 3.816793893129770843e-03 206 | 3.816793893129770843e-03 207 | 3.816793893129770843e-03 208 | 3.816793893129770843e-03 209 | 3.816793893129770843e-03 210 | 3.816793893129770843e-03 211 | 3.816793893129770843e-03 212 | 3.816793893129770843e-03 213 | 3.816793893129770843e-03 214 | 3.816793893129770843e-03 215 | 3.816793893129770843e-03 216 | 3.816793893129770843e-03 217 | 3.816793893129770843e-03 218 | 3.816793893129770843e-03 219 | 3.816793893129770843e-03 220 | 3.816793893129770843e-03 221 | 3.816793893129770843e-03 222 | 3.816793893129770843e-03 223 | 3.816793893129770843e-03 224 | 3.816793893129770843e-03 225 | 3.816793893129770843e-03 226 | 3.816793893129770843e-03 227 | 3.816793893129770843e-03 228 | 3.816793893129770843e-03 229 | 3.816793893129770843e-03 230 | 3.816793893129770843e-03 231 | 3.816793893129770843e-03 232 | 3.816793893129770843e-03 233 | 3.816793893129770843e-03 234 | 3.816793893129770843e-03 235 | 3.816793893129770843e-03 236 | 3.816793893129770843e-03 237 | 3.816793893129770843e-03 238 | 3.816793893129770843e-03 239 | 3.816793893129770843e-03 240 | 3.816793893129770843e-03 241 | 3.816793893129770843e-03 242 | 3.816793893129770843e-03 243 | 3.816793893129770843e-03 244 | 3.816793893129770843e-03 245 | 3.816793893129770843e-03 246 | 3.816793893129770843e-03 247 | 3.816793893129770843e-03 248 | 3.816793893129770843e-03 249 | 3.816793893129770843e-03 250 | 3.816793893129770843e-03 251 | 3.816793893129770843e-03 252 | 3.816793893129770843e-03 253 | 3.816793893129770843e-03 254 | 3.816793893129770843e-03 255 | 3.816793893129770843e-03 256 | 3.816793893129770843e-03 257 | 3.816793893129770843e-03 258 | 3.816793893129770843e-03 259 | 3.816793893129770843e-03 260 | 3.816793893129770843e-03 261 | 3.816793893129770843e-03 262 | 3.816793893129770843e-03 263 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = paste-bio 3 | version = 1.4.0 4 | author = Max Land 5 | author_email = max.ruikang.land@gmail.com 6 | description = A computational method to align and integrate spatial transcriptomics experiments. 7 | long_description = file: README.md 8 | long_description_content_type = text/markdown 9 | url = https://github.com/raphael-group/paste 10 | project_urls = 11 | Bug Tracker = https://github.com/raphael-group/paste/issues 12 | classifiers = 13 | Programming Language :: Python :: 3 14 | License :: OSI Approved :: BSD License 15 | Operating System :: OS Independent 16 | 17 | [options] 18 | package_dir = 19 | = src 20 | packages = find: 21 | python_requires = >=3.6 22 | zip_safe = False 23 | 24 | [options.packages.find] 25 | where = src -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup() -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- 1 | from .paste import * -------------------------------------------------------------------------------- /src/paste/PASTE.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple, Optional 2 | import numpy as np 3 | from anndata import AnnData 4 | import ot 5 | from sklearn.decomposition import NMF 6 | from .helper import intersect, kl_divergence_backend, to_dense_array, extract_data_matrix 7 | 8 | def pairwise_align( 9 | sliceA: AnnData, 10 | sliceB: AnnData, 11 | alpha: float = 0.1, 12 | dissimilarity: str ='kl', 13 | use_rep: Optional[str] = None, 14 | G_init = None, 15 | a_distribution = None, 16 | b_distribution = None, 17 | norm: bool = False, 18 | numItermax: int = 200, 19 | backend = ot.backend.NumpyBackend(), 20 | use_gpu: bool = False, 21 | return_obj: bool = False, 22 | verbose: bool = False, 23 | gpu_verbose: bool = True, 24 | **kwargs) -> Tuple[np.ndarray, Optional[int]]: 25 | """ 26 | Calculates and returns optimal alignment of two slices. 27 | 28 | Args: 29 | sliceA: Slice A to align. 30 | sliceB: Slice B to align. 31 | alpha: Alignment tuning parameter. Note: 0 <= alpha <= 1. 32 | dissimilarity: Expression dissimilarity measure: ``'kl'`` or ``'euclidean'``. 33 | use_rep: If ``None``, uses ``slice.X`` to calculate dissimilarity between spots, otherwise uses the representation given by ``slice.obsm[use_rep]``. 34 | G_init (array-like, optional): Initial mapping to be used in FGW-OT, otherwise default is uniform mapping. 35 | a_distribution (array-like, optional): Distribution of sliceA spots, otherwise default is uniform. 36 | b_distribution (array-like, optional): Distribution of sliceB spots, otherwise default is uniform. 37 | numItermax: Max number of iterations during FGW-OT. 38 | norm: If ``True``, scales spatial distances such that neighboring spots are at distance 1. Otherwise, spatial distances remain unchanged. 39 | backend: Type of backend to run calculations. For list of backends available on system: ``ot.backend.get_backend_list()``. 40 | use_gpu: If ``True``, use gpu. Otherwise, use cpu. Currently we only have gpu support for Pytorch. 41 | return_obj: If ``True``, additionally returns objective function output of FGW-OT. 42 | verbose: If ``True``, FGW-OT is verbose. 43 | gpu_verbose: If ``True``, print whether gpu is being used to user. 44 | 45 | Returns: 46 | - Alignment of spots. 47 | 48 | If ``return_obj = True``, additionally returns: 49 | 50 | - Objective function output of FGW-OT. 51 | """ 52 | 53 | # Determine if gpu or cpu is being used 54 | if use_gpu: 55 | try: 56 | import torch 57 | except: 58 | print("We currently only have gpu support for Pytorch. Please install torch.") 59 | 60 | if isinstance(backend,ot.backend.TorchBackend): 61 | if torch.cuda.is_available(): 62 | if gpu_verbose: 63 | print("gpu is available, using gpu.") 64 | else: 65 | if gpu_verbose: 66 | print("gpu is not available, resorting to torch cpu.") 67 | use_gpu = False 68 | else: 69 | print("We currently only have gpu support for Pytorch, please set backend = ot.backend.TorchBackend(). Reverting to selected backend cpu.") 70 | use_gpu = False 71 | else: 72 | if gpu_verbose: 73 | print("Using selected backend cpu. If you want to use gpu, set use_gpu = True.") 74 | 75 | # subset for common genes 76 | common_genes = intersect(sliceA.var.index, sliceB.var.index) 77 | sliceA = sliceA[:, common_genes] 78 | sliceB = sliceB[:, common_genes] 79 | 80 | # check if slices are valid 81 | for s in [sliceA, sliceB]: 82 | if not len(s): 83 | raise ValueError(f"Found empty `AnnData`:\n{sliceA}.") 84 | 85 | 86 | # Backend 87 | nx = backend 88 | 89 | # Calculate spatial distances 90 | coordinatesA = sliceA.obsm['spatial'].copy() 91 | coordinatesA = nx.from_numpy(coordinatesA) 92 | coordinatesB = sliceB.obsm['spatial'].copy() 93 | coordinatesB = nx.from_numpy(coordinatesB) 94 | 95 | if isinstance(nx,ot.backend.TorchBackend): 96 | coordinatesA = coordinatesA.float() 97 | coordinatesB = coordinatesB.float() 98 | D_A = ot.dist(coordinatesA,coordinatesA, metric='euclidean') 99 | D_B = ot.dist(coordinatesB,coordinatesB, metric='euclidean') 100 | 101 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 102 | D_A = D_A.cuda() 103 | D_B = D_B.cuda() 104 | 105 | # Calculate expression dissimilarity 106 | A_X, B_X = nx.from_numpy(to_dense_array(extract_data_matrix(sliceA,use_rep))), nx.from_numpy(to_dense_array(extract_data_matrix(sliceB,use_rep))) 107 | 108 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 109 | A_X = A_X.cuda() 110 | B_X = B_X.cuda() 111 | 112 | if dissimilarity.lower()=='euclidean' or dissimilarity.lower()=='euc': 113 | M = ot.dist(A_X,B_X) 114 | else: 115 | s_A = A_X + 0.01 116 | s_B = B_X + 0.01 117 | M = kl_divergence_backend(s_A, s_B) 118 | M = nx.from_numpy(M) 119 | 120 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 121 | M = M.cuda() 122 | 123 | # init distributions 124 | if a_distribution is None: 125 | a = nx.ones((sliceA.shape[0],))/sliceA.shape[0] 126 | else: 127 | a = nx.from_numpy(a_distribution) 128 | 129 | if b_distribution is None: 130 | b = nx.ones((sliceB.shape[0],))/sliceB.shape[0] 131 | else: 132 | b = nx.from_numpy(b_distribution) 133 | 134 | if isinstance(nx,ot.backend.TorchBackend) and use_gpu: 135 | a = a.cuda() 136 | b = b.cuda() 137 | 138 | if norm: 139 | D_A /= nx.min(D_A[D_A>0]) 140 | D_B /= nx.min(D_B[D_B>0]) 141 | 142 | # Run OT 143 | if G_init is not None: 144 | G_init = nx.from_numpy(G_init) 145 | if isinstance(nx,ot.backend.TorchBackend): 146 | G_init = G_init.float() 147 | if use_gpu: 148 | G_init.cuda() 149 | pi, logw = my_fused_gromov_wasserstein(M, D_A, D_B, a, b, G_init = G_init, loss_fun='square_loss', alpha= alpha, log=True, numItermax=numItermax,verbose=verbose, use_gpu = use_gpu) 150 | pi = nx.to_numpy(pi) 151 | obj = nx.to_numpy(logw['fgw_dist']) 152 | if isinstance(backend,ot.backend.TorchBackend) and use_gpu: 153 | torch.cuda.empty_cache() 154 | 155 | if return_obj: 156 | return pi, obj 157 | return pi 158 | 159 | 160 | def center_align( 161 | A: AnnData, 162 | slices: List[AnnData], 163 | lmbda = None, 164 | alpha: float = 0.1, 165 | n_components: int = 15, 166 | threshold: float = 0.001, 167 | max_iter: int = 10, 168 | dissimilarity: str ='kl', 169 | norm: bool = False, 170 | random_seed: Optional[int] = None, 171 | pis_init: Optional[List[np.ndarray]] = None, 172 | distributions = None, 173 | backend = ot.backend.NumpyBackend(), 174 | use_gpu: bool = False, 175 | verbose: bool = False, 176 | gpu_verbose: bool = True) -> Tuple[AnnData, List[np.ndarray]]: 177 | """ 178 | Computes center alignment of slices. 179 | 180 | Args: 181 | A: Slice to use as the initialization for center alignment; Make sure to include gene expression and spatial information. 182 | slices: List of slices to use in the center alignment. 183 | lmbda (array-like, optional): List of probability weights assigned to each slice; If ``None``, use uniform weights. 184 | alpha: Alignment tuning parameter. Note: 0 <= alpha <= 1. 185 | n_components: Number of components in NMF decomposition. 186 | threshold: Threshold for convergence of W and H during NMF decomposition. 187 | max_iter: Maximum number of iterations for our center alignment algorithm. 188 | dissimilarity: Expression dissimilarity measure: ``'kl'`` or ``'euclidean'``. 189 | norm: If ``True``, scales spatial distances such that neighboring spots are at distance 1. Otherwise, spatial distances remain unchanged. 190 | random_seed: Set random seed for reproducibility. 191 | pis_init: Initial list of mappings between 'A' and 'slices' to solver. Otherwise, default will automatically calculate mappings. 192 | distributions (List[array-like], optional): Distributions of spots for each slice. Otherwise, default is uniform. 193 | backend: Type of backend to run calculations. For list of backends available on system: ``ot.backend.get_backend_list()``. 194 | use_gpu: If ``True``, use gpu. Otherwise, use cpu. Currently we only have gpu support for Pytorch. 195 | verbose: If ``True``, FGW-OT is verbose. 196 | gpu_verbose: If ``True``, print whether gpu is being used to user. 197 | 198 | Returns: 199 | - Inferred center slice with full and low dimensional representations (W, H) of the gene expression matrix. 200 | - List of pairwise alignment mappings of the center slice (rows) to each input slice (columns). 201 | """ 202 | 203 | # Determine if gpu or cpu is being used 204 | if use_gpu: 205 | try: 206 | import torch 207 | except: 208 | print("We currently only have gpu support for Pytorch. Please install torch.") 209 | 210 | if isinstance(backend,ot.backend.TorchBackend): 211 | if torch.cuda.is_available(): 212 | if gpu_verbose: 213 | print("gpu is available, using gpu.") 214 | else: 215 | if gpu_verbose: 216 | print("gpu is not available, resorting to torch cpu.") 217 | use_gpu = False 218 | else: 219 | print("We currently only have gpu support for Pytorch, please set backend = ot.backend.TorchBackend(). Reverting to selected backend cpu.") 220 | use_gpu = False 221 | else: 222 | if gpu_verbose: 223 | print("Using selected backend cpu. If you want to use gpu, set use_gpu = True.") 224 | 225 | if lmbda is None: 226 | lmbda = len(slices)*[1/len(slices)] 227 | 228 | if distributions is None: 229 | distributions = len(slices)*[None] 230 | 231 | # get common genes 232 | common_genes = A.var.index 233 | for s in slices: 234 | common_genes = intersect(common_genes, s.var.index) 235 | 236 | # subset common genes 237 | A = A[:, common_genes] 238 | for i in range(len(slices)): 239 | slices[i] = slices[i][:, common_genes] 240 | print('Filtered all slices for common genes. There are ' + str(len(common_genes)) + ' common genes.') 241 | 242 | # Run initial NMF 243 | if dissimilarity.lower()=='euclidean' or dissimilarity.lower()=='euc': 244 | model = NMF(n_components=n_components, init='random', random_state = random_seed, verbose = verbose) 245 | else: 246 | model = NMF(n_components=n_components, solver = 'mu', beta_loss = 'kullback-leibler', init='random', random_state = random_seed, verbose = verbose) 247 | 248 | if pis_init is None: 249 | pis = [None for i in range(len(slices))] 250 | W = model.fit_transform(A.X) 251 | else: 252 | pis = pis_init 253 | W = model.fit_transform(A.shape[0]*sum([lmbda[i]*np.dot(pis[i], to_dense_array(slices[i].X)) for i in range(len(slices))])) 254 | H = model.components_ 255 | center_coordinates = A.obsm['spatial'] 256 | 257 | if not isinstance(center_coordinates, np.ndarray): 258 | print("Warning: A.obsm['spatial'] is not of type numpy array.") 259 | 260 | # Initialize center_slice 261 | center_slice = AnnData(np.dot(W,H)) 262 | center_slice.var.index = common_genes 263 | center_slice.obs.index = A.obs.index 264 | center_slice.obsm['spatial'] = center_coordinates 265 | 266 | # Minimize R 267 | iteration_count = 0 268 | R = 0 269 | R_diff = 100 270 | while R_diff > threshold and iteration_count < max_iter: 271 | print("Iteration: " + str(iteration_count)) 272 | pis, r = center_ot(W, H, slices, center_coordinates, common_genes, alpha, backend, use_gpu, dissimilarity = dissimilarity, norm = norm, G_inits = pis, distributions=distributions, verbose = verbose) 273 | W, H = center_NMF(W, H, slices, pis, lmbda, n_components, random_seed, dissimilarity = dissimilarity, verbose = verbose) 274 | R_new = np.dot(r,lmbda) 275 | iteration_count += 1 276 | R_diff = abs(R - R_new) 277 | print("Objective ",R_new) 278 | print("Difference: " + str(R_diff) + "\n") 279 | R = R_new 280 | center_slice = A.copy() 281 | center_slice.X = np.dot(W, H) 282 | center_slice.uns['paste_W'] = W 283 | center_slice.uns['paste_H'] = H 284 | center_slice.uns['full_rank'] = center_slice.shape[0]*sum([lmbda[i]*np.dot(pis[i], to_dense_array(slices[i].X)) for i in range(len(slices))]) 285 | center_slice.uns['obj'] = R 286 | return center_slice, pis 287 | 288 | #--------------------------- HELPER METHODS ----------------------------------- 289 | 290 | def center_ot(W, H, slices, center_coordinates, common_genes, alpha, backend, use_gpu, dissimilarity = 'kl', norm = False, G_inits = None, distributions=None, verbose = False): 291 | center_slice = AnnData(np.dot(W,H)) 292 | center_slice.var.index = common_genes 293 | center_slice.obsm['spatial'] = center_coordinates 294 | 295 | if distributions is None: 296 | distributions = len(slices)*[None] 297 | 298 | pis = [] 299 | r = [] 300 | print('Solving Pairwise Slice Alignment Problem.') 301 | for i in range(len(slices)): 302 | p, r_q = pairwise_align(center_slice, slices[i], alpha = alpha, dissimilarity = dissimilarity, norm = norm, return_obj = True, G_init = G_inits[i], b_distribution=distributions[i], backend = backend, use_gpu = use_gpu, verbose = verbose, gpu_verbose = False) 303 | pis.append(p) 304 | r.append(r_q) 305 | return pis, np.array(r) 306 | 307 | def center_NMF(W, H, slices, pis, lmbda, n_components, random_seed, dissimilarity = 'kl', verbose = False): 308 | print('Solving Center Mapping NMF Problem.') 309 | n = W.shape[0] 310 | B = n*sum([lmbda[i]*np.dot(pis[i], to_dense_array(slices[i].X)) for i in range(len(slices))]) 311 | if dissimilarity.lower()=='euclidean' or dissimilarity.lower()=='euc': 312 | model = NMF(n_components=n_components, init='random', random_state = random_seed, verbose = verbose) 313 | else: 314 | model = NMF(n_components=n_components, solver = 'mu', beta_loss = 'kullback-leibler', init='random', random_state = random_seed, verbose = verbose) 315 | W_new = model.fit_transform(B) 316 | H_new = model.components_ 317 | return W_new, H_new 318 | 319 | def my_fused_gromov_wasserstein(M, C1, C2, p, q, G_init = None, loss_fun='square_loss', alpha=0.5, armijo=False, log=False,numItermax=200, tol_rel=1e-9, tol_abs=1e-9, use_gpu = False, **kwargs): 320 | """ 321 | Adapted fused_gromov_wasserstein with the added capability of defining a G_init (inital mapping). 322 | Also added capability of utilizing different POT backends to speed up computation. 323 | 324 | For more info, see: https://pythonot.github.io/gen_modules/ot.gromov.html 325 | """ 326 | 327 | p, q = ot.utils.list_to_array(p, q) 328 | 329 | p0, q0, C10, C20, M0 = p, q, C1, C2, M 330 | nx = ot.backend.get_backend(p0, q0, C10, C20, M0) 331 | 332 | constC, hC1, hC2 = ot.gromov.init_matrix(C1, C2, p, q, loss_fun) 333 | 334 | if G_init is None: 335 | G0 = p[:, None] * q[None, :] 336 | else: 337 | G0 = (1/nx.sum(G_init)) * G_init 338 | if use_gpu: 339 | G0 = G0.cuda() 340 | 341 | def f(G): 342 | return ot.gromov.gwloss(constC, hC1, hC2, G) 343 | 344 | def df(G): 345 | return ot.gromov.gwggrad(constC, hC1, hC2, G) 346 | 347 | if loss_fun == 'kl_loss': 348 | armijo = True # there is no closed form line-search with KL 349 | 350 | if armijo: 351 | def line_search(cost, G, deltaG, Mi, cost_G, **kwargs): 352 | return ot.optim.line_search_armijo(cost, G, deltaG, Mi, cost_G, nx=nx, **kwargs) 353 | else: 354 | def line_search(cost, G, deltaG, Mi, cost_G, **kwargs): 355 | return solve_gromov_linesearch(G, deltaG, cost_G, C1, C2, M=0., reg=1., nx=nx, **kwargs) 356 | 357 | if log: 358 | res, log = ot.optim.cg(p, q, (1 - alpha) * M, alpha, f, df, G0, line_search, log=True, numItermax=numItermax, stopThr=tol_rel, stopThr2=tol_abs, **kwargs) 359 | 360 | fgw_dist = log['loss'][-1] 361 | 362 | log['fgw_dist'] = fgw_dist 363 | log['u'] = log['u'] 364 | log['v'] = log['v'] 365 | return res, log 366 | 367 | else: 368 | return ot.optim.cg(p, q, (1 - alpha) * M, alpha, f, df, G0, line_search, numItermax=numItermax, stopThr=tol_rel, stopThr2=tol_abs, **kwargs) 369 | 370 | def solve_gromov_linesearch(G, deltaG, cost_G, C1, C2, M, reg, 371 | alpha_min=None, alpha_max=None, nx=None, **kwargs): 372 | """ 373 | Solve the linesearch in the FW iterations 374 | 375 | Parameters 376 | ---------- 377 | 378 | G : array-like, shape(ns,nt) 379 | The transport map at a given iteration of the FW 380 | deltaG : array-like (ns,nt) 381 | Difference between the optimal map found by linearization in the FW algorithm and the value at a given iteration 382 | cost_G : float 383 | Value of the cost at `G` 384 | C1 : array-like (ns,ns), optional 385 | Structure matrix in the source domain. 386 | C2 : array-like (nt,nt), optional 387 | Structure matrix in the target domain. 388 | M : array-like (ns,nt) 389 | Cost matrix between the features. 390 | reg : float 391 | Regularization parameter. 392 | alpha_min : float, optional 393 | Minimum value for alpha 394 | alpha_max : float, optional 395 | Maximum value for alpha 396 | nx : backend, optional 397 | If let to its default value None, a backend test will be conducted. 398 | Returns 399 | ------- 400 | alpha : float 401 | The optimal step size of the FW 402 | fc : int 403 | nb of function call. Useless here 404 | cost_G : float 405 | The value of the cost for the next iteration 406 | 407 | 408 | .. _references-solve-linesearch: 409 | References 410 | ---------- 411 | .. [24] Vayer Titouan, Chapel Laetitia, Flamary Rémi, Tavenard Romain and Courty Nicolas 412 | "Optimal Transport for structured data with application on graphs" 413 | International Conference on Machine Learning (ICML). 2019. 414 | """ 415 | if nx is None: 416 | G, deltaG, C1, C2, M = ot.utils.list_to_array(G, deltaG, C1, C2, M) 417 | 418 | if isinstance(M, int) or isinstance(M, float): 419 | nx = ot.backend.get_backend(G, deltaG, C1, C2) 420 | else: 421 | nx = ot.backend.get_backend(G, deltaG, C1, C2, M) 422 | 423 | dot = nx.dot(nx.dot(C1, deltaG), C2.T) 424 | a = -2 * reg * nx.sum(dot * deltaG) 425 | b = nx.sum(M * deltaG) - 2 * reg * (nx.sum(dot * G) + nx.sum(nx.dot(nx.dot(C1, G), C2.T) * deltaG)) 426 | 427 | alpha = ot.optim.solve_1d_linesearch_quad(a, b) 428 | if alpha_min is not None or alpha_max is not None: 429 | alpha = np.clip(alpha, alpha_min, alpha_max) 430 | 431 | # the new cost is deduced from the line search quadratic function 432 | cost_G = cost_G + a * (alpha ** 2) + b * alpha 433 | 434 | return alpha, 1, cost_G -------------------------------------------------------------------------------- /src/paste/__init__.py: -------------------------------------------------------------------------------- 1 | from .PASTE import pairwise_align, center_align 2 | from .helper import match_spots_using_spatial_heuristic, filter_for_common_genes, apply_trsf 3 | from .visualization import plot_slice, stack_slices_pairwise, stack_slices_center -------------------------------------------------------------------------------- /src/paste/__pycache__/helper.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphael-group/paste/5f0d58c67c7ad2b51ccdf67bad3c31df761fd9bc/src/paste/__pycache__/helper.cpython-38.pyc -------------------------------------------------------------------------------- /src/paste/helper.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from anndata import AnnData 3 | import numpy as np 4 | import scipy 5 | import ot 6 | 7 | def filter_for_common_genes( 8 | slices: List[AnnData]) -> None: 9 | """ 10 | Filters for the intersection of genes between all slices. 11 | 12 | Args: 13 | slices: List of slices. 14 | """ 15 | assert len(slices) > 0, "Cannot have empty list." 16 | 17 | common_genes = slices[0].var.index 18 | for s in slices: 19 | common_genes = intersect(common_genes, s.var.index) 20 | for i in range(len(slices)): 21 | slices[i] = slices[i][:, common_genes] 22 | print('Filtered all slices for common genes. There are ' + str(len(common_genes)) + ' common genes.') 23 | 24 | def match_spots_using_spatial_heuristic( 25 | X, 26 | Y, 27 | use_ot: bool = True) -> np.ndarray: 28 | """ 29 | Calculates and returns a mapping of spots using a spatial heuristic. 30 | 31 | Args: 32 | X (array-like, optional): Coordinates for spots X. 33 | Y (array-like, optional): Coordinates for spots Y. 34 | use_ot: If ``True``, use optimal transport ``ot.emd()`` to calculate mapping. Otherwise, use Scipy's ``min_weight_full_bipartite_matching()`` algorithm. 35 | 36 | Returns: 37 | Mapping of spots using a spatial heuristic. 38 | """ 39 | n1,n2=len(X),len(Y) 40 | X,Y = norm_and_center_coordinates(X),norm_and_center_coordinates(Y) 41 | dist = scipy.spatial.distance_matrix(X,Y) 42 | if use_ot: 43 | pi = ot.emd(np.ones(n1)/n1, np.ones(n2)/n2, dist) 44 | else: 45 | row_ind, col_ind = scipy.sparse.csgraph.min_weight_full_bipartite_matching(scipy.sparse.csr_matrix(dist)) 46 | pi = np.zeros((n1,n2)) 47 | pi[row_ind, col_ind] = 1/max(n1,n2) 48 | if n1i',X,log_X) 95 | X_log_X = nx.reshape(X_log_X,(1,X_log_X.shape[0])) 96 | D = X_log_X.T - nx.dot(X,log_Y.T) 97 | return nx.to_numpy(D) 98 | 99 | 100 | def intersect(lst1, lst2): 101 | """ 102 | Gets and returns intersection of two lists. 103 | 104 | Args: 105 | lst1: List 106 | lst2: List 107 | 108 | Returns: 109 | lst3: List of common elements. 110 | """ 111 | 112 | temp = set(lst2) 113 | lst3 = [value for value in lst1 if value in temp] 114 | return lst3 115 | 116 | def norm_and_center_coordinates(X): 117 | """ 118 | Normalizes and centers coordinates at the origin. 119 | 120 | Args: 121 | X: Numpy array 122 | 123 | Returns: 124 | X_new: Updated coordiantes. 125 | """ 126 | return (X-X.mean(axis=0))/min(scipy.spatial.distance.pdist(X)) 127 | 128 | def apply_trsf( 129 | M: np.ndarray, 130 | translation: List[float], 131 | points: np.ndarray) -> np.ndarray: 132 | """ 133 | Apply a rotation from a 2x2 rotation matrix `M` together with 134 | a translation from a translation vector of length 2 `translation` to a list of 135 | `points`. 136 | 137 | Args: 138 | M (nd.array): A 2x2 rotation matrix. 139 | translation (nd.array): A translation vector of length 2. 140 | points (nd.array): A nx2 array of `n` points 2D positions. 141 | 142 | Returns: 143 | (nd.array) A nx2 matrix of the `n` points transformed. 144 | """ 145 | if not isinstance(translation, np.ndarray): 146 | translation = np.array(translation) 147 | trsf = np.identity(3) 148 | trsf[:-1, :-1] = M 149 | tr = np.identity(3) 150 | tr[:-1, -1] = -translation 151 | trsf = trsf @ tr 152 | 153 | flo = points.T 154 | flo_pad = np.pad(flo, ((0, 1), (0, 0)), constant_values=1) 155 | return ((trsf @ flo_pad)[:-1]).T 156 | 157 | ## Covert a sparse matrix into a dense np array 158 | to_dense_array = lambda X: X.toarray() if isinstance(X,scipy.sparse.csr.spmatrix) else np.array(X) 159 | 160 | ## Returns the data matrix or representation 161 | extract_data_matrix = lambda adata,rep: adata.X if rep is None else adata.obsm[rep] -------------------------------------------------------------------------------- /src/paste/visualization.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple, Optional 2 | from anndata import AnnData 3 | import numpy as np 4 | import seaborn as sns 5 | import matplotlib.pyplot as plt 6 | 7 | """ 8 | Functions to plot slices and align spatial coordinates after obtaining a mapping from PASTE. 9 | """ 10 | 11 | def stack_slices_pairwise( 12 | slices: List[AnnData], 13 | pis: List[np.ndarray], 14 | output_params: bool = False, 15 | matrix: bool = False 16 | ) -> Tuple[List[AnnData], Optional[List[float]], Optional[List[np.ndarray]]]: 17 | """ 18 | Align spatial coordinates of sequential pairwise slices. 19 | 20 | In other words, align: 21 | 22 | slices[0] --> slices[1] --> slices[2] --> ... 23 | 24 | Args: 25 | slices: List of slices. 26 | pis: List of pi (``pairwise_align()`` output) between consecutive slices. 27 | output_params: If ``True``, addtionally return angles of rotation (theta) and translations for each slice. 28 | matrix: If ``True`` and output_params is also ``True``, the rotation is 29 | return as a matrix instead of an angle for each slice. 30 | 31 | Returns: 32 | - List of slices with aligned spatial coordinates. 33 | 34 | If ``output_params = True``, additionally return: 35 | 36 | - List of angles of rotation (theta) for each slice. 37 | - List of translations [x_translation, y_translation] for each slice. 38 | """ 39 | assert len(slices) == len(pis) + 1, "'slices' should have length one more than 'pis'. Please double check." 40 | assert len(slices) > 1, "You should have at least 2 layers." 41 | new_coor = [] 42 | thetas = [] 43 | translations = [] 44 | if not output_params: 45 | S1, S2 = generalized_procrustes_analysis(slices[0].obsm['spatial'], slices[1].obsm['spatial'], pis[0]) 46 | else: 47 | S1, S2,theta,tX,tY = generalized_procrustes_analysis(slices[0].obsm['spatial'], slices[1].obsm['spatial'], pis[0],output_params=output_params, matrix=matrix) 48 | thetas.append(theta) 49 | translations.append(tX) 50 | translations.append(tY) 51 | new_coor.append(S1) 52 | new_coor.append(S2) 53 | for i in range(1, len(slices) - 1): 54 | if not output_params: 55 | x, y = generalized_procrustes_analysis(new_coor[i], slices[i+1].obsm['spatial'], pis[i]) 56 | else: 57 | x, y,theta,tX,tY = generalized_procrustes_analysis(new_coor[i], slices[i+1].obsm['spatial'], pis[i],output_params=output_params, matrix=matrix) 58 | thetas.append(theta) 59 | translations.append(tY) 60 | new_coor.append(y) 61 | 62 | new_slices = [] 63 | for i in range(len(slices)): 64 | s = slices[i].copy() 65 | s.obsm['spatial'] = new_coor[i] 66 | new_slices.append(s) 67 | 68 | if not output_params: 69 | return new_slices 70 | else: 71 | return new_slices, thetas, translations 72 | 73 | 74 | def stack_slices_center( 75 | center_slice: AnnData, 76 | slices: List[AnnData], 77 | pis: List[np.ndarray], 78 | matrix: bool = False, 79 | output_params: bool = False) -> Tuple[AnnData, List[AnnData], Optional[List[float]], Optional[List[np.ndarray]]]: 80 | """ 81 | Align spatial coordinates of a list of slices to a center_slice. 82 | 83 | In other words, align: 84 | 85 | slices[0] --> center_slice 86 | 87 | slices[1] --> center_slice 88 | 89 | slices[2] --> center_slice 90 | 91 | ... 92 | 93 | Args: 94 | center_slice: Inferred center slice. 95 | slices: List of original slices to be aligned. 96 | pis: List of pi (``center_align()`` output) between center_slice and slices. 97 | output_params: If ``True``, additionally return angles of rotation (theta) and translations for each slice. 98 | matrix: If ``True`` and output_params is also ``True``, the rotation is 99 | return as a matrix instead of an angle for each slice. 100 | 101 | Returns: 102 | - Center slice with aligned spatial coordinates. 103 | - List of other slices with aligned spatial coordinates. 104 | 105 | If ``output_params = True``, additionally return: 106 | 107 | - List of angles of rotation (theta) for each slice. 108 | - List of translations [x_translation, y_translation] for each slice. 109 | """ 110 | assert len(slices) == len(pis), "'slices' should have the same length 'pis'. Please double check." 111 | new_coor = [] 112 | thetas = [] 113 | translations = [] 114 | 115 | for i in range(len(slices)): 116 | if not output_params: 117 | c, y = generalized_procrustes_analysis(center_slice.obsm['spatial'], slices[i].obsm['spatial'], pis[i]) 118 | else: 119 | c, y,theta,tX,tY = generalized_procrustes_analysis(center_slice.obsm['spatial'], slices[i].obsm['spatial'], pis[i],output_params=output_params, matrix=matrix) 120 | thetas.append(theta) 121 | translations.append(tY) 122 | new_coor.append(y) 123 | 124 | new_slices = [] 125 | for i in range(len(slices)): 126 | s = slices[i].copy() 127 | s.obsm['spatial'] = new_coor[i] 128 | new_slices.append(s) 129 | 130 | new_center = center_slice.copy() 131 | new_center.obsm['spatial'] = c 132 | if not output_params: 133 | return new_center, new_slices 134 | else: 135 | return new_center, new_slices, thetas, translations 136 | 137 | def plot_slice( 138 | sliceX: AnnData, 139 | color, 140 | ax: Optional[plt.Axes] = None, 141 | s: float = 100) -> None: 142 | """ 143 | Plots slice spatial coordinates. 144 | 145 | Args: 146 | sliceX: Slice to be plotted. 147 | color: Scatterplot color, any format accepted by ``matplotlib``. 148 | ax: Pre-existing axes for the plot. Otherwise, call ``matplotlib.pyplot.gca()`` internally. 149 | s: Size of spots. 150 | """ 151 | sns.scatterplot(x = sliceX.obsm['spatial'][:,0],y = sliceX.obsm['spatial'][:,1],linewidth=0,s=s, marker=".",color=color,ax=ax) 152 | if ax: 153 | ax.invert_yaxis() 154 | ax.axis('off') 155 | 156 | 157 | def generalized_procrustes_analysis(X, Y, pi, output_params = False, matrix = False): 158 | """ 159 | Finds and applies optimal rotation between spatial coordinates of two layers (may also do a reflection). 160 | 161 | Args: 162 | X: np array of spatial coordinates (ex: sliceA.obs['spatial']) 163 | Y: np array of spatial coordinates (ex: sliceB.obs['spatial']) 164 | pi: mapping between the two layers output by PASTE 165 | output_params: Boolean of whether to return rotation angle and translations along with spatial coordiantes. 166 | matrix: Boolean of whether to return the rotation as a matrix or an angle. 167 | 168 | 169 | Returns: 170 | Aligned spatial coordinates of X, Y, rotation angle, translation of X, translation of Y. 171 | """ 172 | assert X.shape[1] == 2 and Y.shape[1] == 2 173 | 174 | tX = pi.sum(axis=1).dot(X) 175 | tY = pi.sum(axis=0).dot(Y) 176 | X = X - tX 177 | Y = Y - tY 178 | H = Y.T.dot(pi.T.dot(X)) 179 | U, S, Vt = np.linalg.svd(H) 180 | R = Vt.T.dot(U.T) 181 | Y = R.dot(Y.T).T 182 | if output_params and not matrix: 183 | M = np.array([[0,-1],[1,0]]) 184 | theta = np.arctan(np.trace(M.dot(H))/np.trace(H)) 185 | return X,Y,theta,tX,tY 186 | elif output_params and matrix: 187 | return X, Y, R, tX, tY 188 | else: 189 | return X,Y 190 | -------------------------------------------------------------------------------- /src/paste_bio.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.1 2 | Name: paste-bio 3 | Version: 1.4.0 4 | Summary: A computational method to align and integrate spatial transcriptomics experiments. 5 | Home-page: https://github.com/raphael-group/paste 6 | Author: Max Land 7 | Author-email: max.ruikang.land@gmail.com 8 | Project-URL: Bug Tracker, https://github.com/raphael-group/paste/issues 9 | Classifier: Programming Language :: Python :: 3 10 | Classifier: License :: OSI Approved :: BSD License 11 | Classifier: Operating System :: OS Independent 12 | Requires-Python: >=3.6 13 | Description-Content-Type: text/markdown 14 | License-File: LICENSE 15 | 16 | [![PyPI](https://img.shields.io/pypi/v/paste-bio.svg)](https://pypi.org/project/paste-bio) 17 | [![Downloads](https://pepy.tech/badge/paste-bio)](https://pepy.tech/project/paste-bio) 18 | [![Documentation Status](https://readthedocs.org/projects/paste-bio/badge/?version=latest)](https://paste-bio.readthedocs.io/en/stable/?badge=stable) 19 | [![Anaconda](https://anaconda.org/bioconda/paste-bio/badges/version.svg)](https://anaconda.org/bioconda/paste-bio/badges/version.svg) 20 | [![bioconda-downloads](https://anaconda.org/bioconda/paste-bio/badges/downloads.svg)](https://anaconda.org/bioconda/paste-bio/badges/downloads.svg) 21 | 22 | # PASTE 23 | 24 | ![PASTE Overview](https://github.com/raphael-group/paste/blob/main/docs/source/_static/images/paste_overview.png) 25 | 26 | PASTE is a computational method that leverages both gene expression similarity and spatial distances between spots to align and integrate spatial transcriptomics data. In particular, there are two methods: 27 | 1. `pairwise_align`: align spots across pairwise slices. 28 | 2. `center_align`: integrate multiple slices into one center slice. 29 | 30 | You can read full paper [here](https://www.nature.com/articles/s41592-022-01459-6). 31 | 32 | Additional examples and the code to reproduce the paper's analyses can be found [here](https://github.com/raphael-group/paste_reproducibility). Preprocessed datasets used in the paper can be found on [zenodo](https://doi.org/10.5281/zenodo.6334774). 33 | 34 | ### Recent News 35 | 36 | * PASTE is now published in [Nature Methods](https://www.nature.com/articles/s41592-022-01459-6)! 37 | 38 | * The code to reproduce the analisys can be found [here](https://github.com/raphael-group/paste_reproducibility). 39 | 40 | * As of version 1.2.0, PASTE now supports GPU implementation via Pytorch. For more details, see the GPU section of the [Tutorial notebook](docs/source/notebooks/getting-started.ipynb). 41 | 42 | ### Installation 43 | 44 | The easiest way is to install PASTE on pypi: https://pypi.org/project/paste-bio/. 45 | 46 | `pip install paste-bio` 47 | 48 | Or you can install PASTE on bioconda: https://anaconda.org/bioconda/paste-bio. 49 | 50 | `conda install -c bioconda paste-bio` 51 | 52 | Check out Tutorial.ipynb for an example of how to use PASTE. 53 | 54 | Alternatively, you can clone the respository and try the following example in a 55 | notebook or the command line. 56 | 57 | ### Quick Start 58 | 59 | To use PASTE we require at least two slices of spatial-omics data (both 60 | expression and coordinates) that are in 61 | anndata format (i.e. read in by scanpy/squidpy). We have included a breast 62 | cancer dataset from [1] in the [sample_data folder](sample_data/) of this repo 63 | that we will use as an example below to show how to use PASTE. 64 | 65 | ```python 66 | import matplotlib.pyplot as plt 67 | import matplotlib.patches as mpatches 68 | import numpy as np 69 | import scanpy as sc 70 | import paste as pst 71 | 72 | # Load Slices 73 | data_dir = './sample_data/' # change this path to the data you wish to analyze 74 | 75 | # Assume that the coordinates of slices are named slice_name + "_coor.csv" 76 | def load_slices(data_dir, slice_names=["slice1", "slice2"]): 77 | slices = [] 78 | for slice_name in slice_names: 79 | slice_i = sc.read_csv(data_dir + slice_name + ".csv") 80 | slice_i_coor = np.genfromtxt(data_dir + slice_name + "_coor.csv", delimiter = ',') 81 | slice_i.obsm['spatial'] = slice_i_coor 82 | # Preprocess slices 83 | sc.pp.filter_genes(slice_i, min_counts = 15) 84 | sc.pp.filter_cells(slice_i, min_counts = 100) 85 | slices.append(slice_i) 86 | return slices 87 | 88 | slices = load_slices(data_dir) 89 | slice1, slice2 = slices 90 | 91 | # Pairwise align the slices 92 | pi12 = pst.pairwise_align(slice1, slice2) 93 | 94 | # To visualize the alignment you can stack the slices 95 | # according to the alignment pi 96 | slices, pis = [slice1, slice2], [pi12] 97 | new_slices = pst.stack_slices_pairwise(slices, pis) 98 | 99 | slice_colors = ['#e41a1c','#377eb8'] 100 | plt.figure(figsize=(7,7)) 101 | for i in range(len(new_slices)): 102 | pst.plot_slice(new_slices[i],slice_colors[i],s=400) 103 | plt.legend(handles=[mpatches.Patch(color=slice_colors[0], label='1'),mpatches.Patch(color=slice_colors[1], label='2')]) 104 | plt.gca().invert_yaxis() 105 | plt.axis('off') 106 | plt.show() 107 | 108 | # Center align slices 109 | ## We have to reload the slices as pairwise_alignment modifies the slices. 110 | slices = load_slices(data_dir) 111 | slice1, slice2 = slices 112 | 113 | # Construct a center slice 114 | ## choose one of the slices as the coordinate reference for the center slice, 115 | ## i.e. the center slice will have the same number of spots as this slice and 116 | ## the same coordinates. 117 | initial_slice = slice1.copy() 118 | slices = [slice1, slice2] 119 | lmbda = len(slices)*[1/len(slices)] # set hyperparameter to be uniform 120 | 121 | ## Possible to pass in an initial pi (as keyword argument pis_init) 122 | ## to improve performance, see Tutorial.ipynb notebook for more details. 123 | center_slice, pis = pst.center_align(initial_slice, slices, lmbda) 124 | 125 | ## The low dimensional representation of our center slice is held 126 | ## in the matrices W and H, which can be used for downstream analyses 127 | W = center_slice.uns['paste_W'] 128 | H = center_slice.uns['paste_H'] 129 | ``` 130 | 131 | ### GPU implementation 132 | PASTE now is compatible with gpu via Pytorch. All we need to do is add the following two parameters to our main functions: 133 | ``` 134 | pi12 = pst.pairwise_align(slice1, slice2, backend = ot.backend.TorchBackend(), use_gpu = True) 135 | 136 | center_slice, pis = pst.center_align(initial_slice, slices, lmbda, backend = ot.backend.TorchBackend(), use_gpu = True) 137 | ``` 138 | For more details, see the GPU section of the [Tutorial notebook](docs/source/notebooks/getting-started.ipynb). 139 | 140 | ### Command Line 141 | 142 | We provide the option of running PASTE from the command line. 143 | 144 | First, clone the repository: 145 | 146 | `git clone https://github.com/raphael-group/paste.git` 147 | 148 | Next, when providing files, you will need to provide two separate files: the gene expression data followed by spatial data (both as .csv) for the code to initialize one slice object. 149 | 150 | Sample execution (based on this repo): `python paste-cmd-line.py -m center -f ./sample_data/slice1.csv ./sample_data/slice1_coor.csv ./sample_data/slice2.csv ./sample_data/slice2_coor.csv ./sample_data/slice3.csv ./sample_data/slice3_coor.csv` 151 | 152 | Note: `pairwise` will return pairwise alignment between each consecutive pair of slices (e.g. \[slice1,slice2\], \[slice2,slice3\]). 153 | 154 | | Flag | Name | Description | Default Value | 155 | | --- | --- | --- | --- | 156 | | -m | mode | Select either `pairwise` or `center` | (str) `pairwise` | 157 | | -f | files | Path to data files (.csv) | None | 158 | | -d | direc | Directory to store output files | Current Directory | 159 | | -a | alpha | Alpha parameter for PASTE | (float) `0.1` | 160 | | -c | cost | Expression dissimilarity cost (`kl` or `Euclidean`) | (str) `kl` | 161 | | -p | n_components | n_components for NMF step in `center_align` | (int) `15` | 162 | | -l | lmbda | Lambda parameter in `center_align` | (floats) probability vector of length `n` | 163 | | -i | intial_slice | Specify which file is also the intial slice in `center_align` | (int) `1` | 164 | | -t | threshold | Convergence threshold for `center_align` | (float) `0.001` | 165 | | -x | coordinates | Output new coordinates (toggle to turn on) | `False` | 166 | | -w | weights | Weights files of spots in each slice (.csv) | None | 167 | | -s | start | Initial alignments for OT. If not given uses uniform (.csv structure similar to alignment output) | None | 168 | 169 | `pairwise_align` outputs a (.csv) file containing mapping of spots between each consecutive pair of slices. The rows correspond to spots of the first slice, and cols the second. 170 | 171 | `center_align` outputs two files containing the low dimensional representation (NMF decomposition) of the center slice gene expression, and files containing a mapping of spots between the center slice (rows) to each input slice (cols). 172 | 173 | ### Sample Dataset 174 | 175 | Added sample spatial transcriptomics dataset consisting of four breast cancer slice courtesy of: 176 | 177 | [1] Ståhl, Patrik & Salmén, Fredrik & Vickovic, Sanja & Lundmark, Anna & Fernandez Navarro, Jose & Magnusson, Jens & Giacomello, Stefania & Asp, Michaela & Westholm, Jakub & Huss, Mikael & Mollbrink, Annelie & Linnarsson, Sten & Codeluppi, Simone & Borg, Åke & Pontén, Fredrik & Costea, Paul & Sahlén, Pelin Akan & Mulder, Jan & Bergmann, Olaf & Frisén, Jonas. (2016). Visualization and analysis of gene expression in tissue sections by spatial transcriptomics. Science. 353. 78-82. 10.1126/science.aaf2403. 178 | 179 | Note: Original data is (.tsv), but we converted it to (.csv). 180 | 181 | ### References 182 | 183 | Ron Zeira, Max Land, Alexander Strzalkowski and Benjamin J. Raphael. "Alignment and integration of spatial transcriptomics data". Nature Methods (2022). https://doi.org/10.1038/s41592-022-01459-6 184 | -------------------------------------------------------------------------------- /src/paste_bio.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | LICENSE 2 | README.md 3 | pyproject.toml 4 | setup.cfg 5 | setup.py 6 | src/paste/PASTE.py 7 | src/paste/__init__.py 8 | src/paste/helper.py 9 | src/paste/visualization.py 10 | src/paste_bio.egg-info/PKG-INFO 11 | src/paste_bio.egg-info/SOURCES.txt 12 | src/paste_bio.egg-info/dependency_links.txt 13 | src/paste_bio.egg-info/not-zip-safe 14 | src/paste_bio.egg-info/top_level.txt -------------------------------------------------------------------------------- /src/paste_bio.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/paste_bio.egg-info/not-zip-safe: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/paste_bio.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | paste 2 | --------------------------------------------------------------------------------