├── .DS_Store ├── LICENSE ├── MANIFEST.in ├── README.md ├── examples ├── .DS_Store ├── .ipynb_checkpoints │ ├── scGeneFit_example-checkpoint.ipynb │ ├── scGeneFit_functional_groups-checkpoint.ipynb │ └── scGeneFit_large_scale-checkpoint.ipynb ├── plot.pdf ├── scGeneFit_example.ipynb ├── scGeneFit_functional_groups.ipynb └── scGeneFit_large_scale.ipynb ├── imgs ├── .DS_Store ├── output_11_1.png ├── output_14_1.png ├── output_17_1.png ├── output_20_1.png ├── output_25_1.png ├── output_31_1.png ├── output_34_1.png ├── output_34_2.png ├── output_34_3.png ├── output_34_4.png ├── output_34_5.png ├── output_34_6.png ├── output_34_7.png └── output_38_1.png ├── scGeneFit ├── .DS_Store ├── __init__.py ├── data_files │ ├── .DS_Store │ ├── CITEseq-labels.mat │ ├── CITEseq.mat │ ├── CITEseq_names.mat │ ├── __init__.py │ ├── data source │ ├── zeisel_data.mat │ ├── zeisel_labels1.mat │ ├── zeisel_labels2.mat │ └── zeisel_names.mat └── functions.py └── setup.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/.DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Bianca Dumitrascu, Soledad Villar, Dustin Mixon, Barbara Engelhardt 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | include scGeneFit/data_files/CITEseq_names.mat 3 | include scGeneFit/data_files/CITEseq-labels.mat 4 | include scGeneFit/data_files/CITEseq.mat 5 | include scGeneFit/data_files/CITseq.mat 6 | include scGeneFit/data_files/zeisel_data.mat 7 | include scGeneFit/data_files/zeisel_labels1.mat 8 | include scGeneFit/data_files/zeisel_labels2.mat 9 | include scGeneFit/data_files/zeisel_names.mat 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scGeneFit 2 | 3 | Python code for genetic marker selection using linear programming. 4 | 5 | The algorithm is described in https://www.biorxiv.org/content/10.1101/599654v1 6 | 7 | Dependencies: numpy, matplotlib, scipy, sklearn. 8 | 9 | Examples and source code: https://github.com/solevillar/scGeneFit-python 10 | 11 | The package main function is scGeneFit.functions.get_markers() 12 | 13 | get_markers(data, labels, num_markers, method='centers', epsilon=1, sampling_rate=1, n_neighbors=3, max_constraints=1000, redundancy=0.01, verbose=True) 14 | 15 | 16 | - data: Nxd numpy array with point coordinates, N: number of points, d: dimension 17 | - labels: list with labels (N labels, one per point) 18 | - num_markers: target number of markers to select (num_markersDelta, where Delta is chosen to be epsilon times the norm of the smallest constraint (default 1) 24 | **This is the most important parameter in this problem, it determines the scale of the constraints, the rest the rest of the parameters only determine the size of the LP to adapt to limited computational resources. We include a function that finds the optimal value of epsilon given a classifier and a training/test set. We provide an example of the optimization in scGeneFit_functional_groups.ipynb** 25 | - sampling_rate: (if method=='pairwise' or 'pairwise_centers') selects constraints from a random sample of proportion sampling_rate (default 1) 26 | - n_neighbors: (if method=='pairwise') chooses the constraints from n_neighbors nearest neighbors (default 3) 27 | - max_constraints: maximum number of constraints to consider (default 1000) 28 | - redundancy: (if method=='centers') in this case not all pairwise constraints are considered but just between centers of consecutive labels plus a random fraction of constraints given by redundancy. If redundancy==1 all constraints between pairs of centers are considered 29 | - verbose: whether it prints information like size of the LP or elapsed time (default True) 30 | 31 | 32 | 33 | ```python 34 | from scGeneFit.functions import * 35 | 36 | %matplotlib inline 37 | import numpy as np 38 | np.random.seed(0) 39 | ``` 40 | 41 | 42 | ```python 43 | 44 | ``` 45 | 46 | #### Auxiliary functions 47 | 48 | 49 | ```python 50 | from sklearn.neighbors import NearestCentroid 51 | clf=NearestCentroid() 52 | 53 | def performance(X_train, y_train, X_test, y_test, clf): 54 | clf.fit(X_train, y_train) 55 | return clf.score(X_test, y_test) 56 | ``` 57 | 58 | # CITEseq example 59 | 60 | Data included in package, from 61 | 62 | [1] Marlon Stoeckius, Christoph Hafemeister, William Stephenson, Brian Houck-Loomis, Pratip K Chattopadhyay, Harold Swerdlow, Rahul Satija, and Peter Smibert. 63 | Simultaneous epitope and transcriptome measurement insingle cells. Nature Methods, 14(9):865, 2017. 64 | 65 | 66 | ```python 67 | #load data from files 68 | [data, labels, names]= load_example_data("CITEseq") 69 | N,d=data.shape 70 | ``` 71 | 72 | ## Use of scGeneFit (center based constraints) 73 | 74 | 75 | ```python 76 | num_markers=25 77 | method='centers' 78 | redundancy=0.25 79 | 80 | markers= get_markers(data, labels, num_markers, method=method, redundancy=redundancy) 81 | 82 | accuracy=performance(data, labels, data, labels, clf) 83 | accuracy_markers=performance(data[:,markers], labels, data[:,markers], labels, clf) 84 | 85 | print("Accuracy (whole data,", d, " markers): ", accuracy) 86 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 87 | ``` 88 | 89 | Solving a linear program with 500 variables and 45 constraints 90 | Time elapsed: 0.3295409679412842 seconds 91 | Accuracy (whole data, 500 markers): 0.8660786816757572 92 | Accuracy (selected 25 markers) 0.7863525588952072 93 | 94 | 95 | 96 | ```python 97 | #TSNE plot 98 | a=plot_marker_selection(data, markers, names) 99 | ``` 100 | 101 | Computing TSNE embedding 102 | Elapsed time: 117.06255102157593 seconds 103 | 104 | 105 | 106 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_11_1.png) 107 | 108 | 109 | ## Use of scGeneFit (pairwise distance constraints) 110 | 111 | 112 | ```python 113 | num_markers=25 114 | method='pairwise' 115 | sampling_rate=0.1 #use 10 percent of the data to generate constraints 116 | n_neighbors=3 #3 constraints per point 117 | epsilon=1 #Delta is 10*norm of the smallest constraint 118 | max_constraints=1000 #use at most 1000 constraints (for efficiency) 119 | 120 | markers= get_markers(data, labels, num_markers, method=method, sampling_rate=sampling_rate, 121 | n_neighbors=n_neighbors, epsilon=epsilon, max_constraints=max_constraints) 122 | 123 | accuracy=performance(data, labels, data, labels, clf) 124 | accuracy_markers=performance(data[:,markers], labels, data[:,markers], labels, clf) 125 | 126 | print("Accuracy (whole data,", d, " markers): ", accuracy) 127 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 128 | ``` 129 | 130 | Solving a linear program with 500 variables and 1000 constraints 131 | Time elapsed: 6.737841844558716 seconds 132 | Accuracy (whole data, 500 markers): 0.8660786816757572 133 | Accuracy (selected 25 markers) 0.7710340025530927 134 | 135 | 136 | 137 | ```python 138 | #TSNE plot 139 | a=plot_marker_selection(data, markers, names) 140 | ``` 141 | 142 | Computing TSNE embedding 143 | Elapsed time: 118.96086025238037 seconds 144 | 145 | 146 | 147 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_14_1.png) 148 | 149 | 150 | ## Use of scGeneFit (pairwise center based constraints) 151 | 152 | 153 | ```python 154 | num_markers=25 155 | method='pairwise_centers' 156 | sampling_rate=0.1 #use 10 percent of the data to generate constraints 157 | n_neighbors=0 #neighbors are not used for the center constraints 158 | epsilon=10 #Delta is 10*norm of the smallest constraint 159 | max_constraints=1000 #use at most 5000 constraints (for efficiency) 160 | 161 | markers= get_markers(data, labels, num_markers, method=method, 162 | sampling_rate=sampling_rate, n_neighbors=n_neighbors, epsilon=epsilon, 163 | max_constraints=max_constraints) 164 | 165 | accuracy=performance(data, labels, data, labels, clf) 166 | accuracy_markers=performance(data[:,markers], labels, data[:,markers], labels, clf) 167 | 168 | print("Accuracy (whole data,", d, " markers): ", accuracy) 169 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 170 | ``` 171 | 172 | Solving a linear program with 500 variables and 1000 constraints 173 | Time elapsed: 4.070271015167236 seconds 174 | Accuracy (whole data, 500 markers): 0.8660786816757572 175 | Accuracy (selected 25 markers) 0.7864686085644655 176 | 177 | 178 | 179 | ```python 180 | #TSNE plot 181 | a=plot_marker_selection(data, markers, names) 182 | ``` 183 | 184 | Computing TSNE embedding 185 | Elapsed time: 118.61988186836243 seconds 186 | 187 | 188 | 189 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_17_1.png) 190 | 191 | 192 | ## One vs all markers 193 | 194 | 195 | ```python 196 | markers2=one_vs_all_selection(data,labels) 197 | 198 | accuracy=performance(data, labels, data, labels, clf) 199 | accuracy_markers=performance(data[:,markers2], labels, data[:,markers2], labels, clf) 200 | 201 | print("Accuracy (whole data,", d, " markers): ", accuracy) 202 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 203 | ``` 204 | 205 | Accuracy (whole data, 500 markers): 0.8660786816757572 206 | Accuracy (selected 25 markers) 0.7537426018335848 207 | 208 | 209 | 210 | ```python 211 | a=plot_marker_selection(data, markers2, names) 212 | ``` 213 | 214 | Computing TSNE embedding 215 | Elapsed time: 115.60354685783386 seconds 216 | 217 | 218 | 219 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_20_1.png) 220 | 221 | 222 | # Zeisel example 223 | Zeisel data included in package, from 224 | 225 | [2] Amit Zeisel, Ana B Munoz-Manchado, Simone Codeluppi, Peter Lonnerberg, Gioele La Manno, Anna Jureus, Sueli Marques, Hermany Munguba, Liqun He, Christer Betsholtz, et al. 226 | Cell types in the mouse cortex and hippocampus revealed by single-cell RNA-seq. Science, 347(6226):1138–1142, 2015. 227 | 228 | This example exhibits a hierarchical clustering structure. We use the function get_markers_hierarchy that takes the hierarchical structure into consideration to select the constraints. 229 | 230 | 231 | 232 | ```python 233 | #load data from file 234 | [data, labels, names]=load_example_data("zeisel") 235 | N,d=data.shape 236 | ``` 237 | 238 | ## Use of scGeneFit (center based constraints) 239 | 240 | 241 | ```python 242 | num_markers=25 243 | method='centers' 244 | redundancy=0.1 245 | 246 | markers= get_markers_hierarchy(data, labels, num_markers, method=method, redundancy=redundancy) 247 | 248 | accuracy=performance(data, labels[0], data, labels[0], clf) 249 | accuracy_markers=performance(data[:,markers], labels[0], data[:,markers], labels[0], clf) 250 | 251 | print("Accuracy (whole data,", d, " markers): ", accuracy) 252 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 253 | 254 | ``` 255 | 256 | Solving a linear program with 4000 variables and 96 constraints 257 | Time elapsed: 67.69524931907654 seconds 258 | Accuracy (whole data, 4000 markers): 0.8745424292845257 259 | Accuracy (selected 25 markers) 0.8861896838602329 260 | 261 | 262 | 263 | ```python 264 | #TSNE plot 265 | a=plot_marker_selection(data, markers, names[0]) 266 | ``` 267 | 268 | Computing TSNE embedding 269 | Elapsed time: 71.29064297676086 seconds 270 | 271 | 272 | 273 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_25_1.png) 274 | 275 | 276 | ## Use of scGeneFit (pairwise distance constraints) 277 | 278 | 279 | ```python 280 | num_markers=25 281 | method='pairwise' 282 | sampling_rate=0.05 #use 5 percent of the data to generate constraints 283 | n_neighbors=3 #3 constraints per point 284 | epsilon=10 #Delta is 10*norm of the smallest constraint 285 | max_constraints=500 #use at most 500 constraints (for efficiency) 286 | use_centers=False #constraints given by pairwise distances 287 | 288 | markers= get_markers_hierarchy(data, labels, num_markers, method=method, 289 | sampling_rate=sampling_rate, n_neighbors=n_neighbors, epsilon=epsilon) 290 | 291 | accuracy=performance(data, labels[0], data, labels[0], clf) 292 | accuracy_markers=performance(data[:,markers], labels[0], data[:,markers], labels[0], clf) 293 | 294 | print("Accuracy (whole data,", d, " markers): ", accuracy) 295 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 296 | 297 | ``` 298 | 299 | Solving a linear program with 4000 variables and 1000 constraints 300 | Time elapsed: 40.95984506607056 seconds 301 | Accuracy (whole data, 4000 markers): 0.8745424292845257 302 | Accuracy (selected 25 markers) 0.8435940099833611 303 | 304 | 305 | 306 | ```python 307 | 308 | ``` 309 | 310 | ## Use of scGeneFit (pairwise center based constraints) 311 | 312 | 313 | ```python 314 | num_markers=25 315 | method='pairwise_centers' 316 | sampling_rate=0.05 #use 5 percent of the data to generate constraints 317 | n_neighbors=0 #neighbors are not used for the center constraints 318 | epsilon=10 #Delta is 10*norm of the smallest constraint 319 | max_constraints=500 #use at most 500 constraints (for efficiency) 320 | use_centers=True #constraints given by pairwise distances 321 | 322 | markers = get_markers_hierarchy(data, labels, num_markers, method=method, 323 | sampling_rate=sampling_rate, n_neighbors=n_neighbors, epsilon=epsilon) 324 | 325 | accuracy=performance(data, labels[0], data, labels[0], clf) 326 | accuracy_markers=performance(data[:,markers], labels[0], data[:,markers], labels[0], clf) 327 | 328 | print("Accuracy (whole data,", d, " markers): ", accuracy) 329 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 330 | ``` 331 | 332 | Solving a linear program with 4000 variables and 1000 constraints 333 | Time elapsed: 168.19283509254456 seconds 334 | Accuracy (whole data, 4000 markers): 0.8745424292845257 335 | Accuracy (selected 25 markers) 0.9237936772046589 336 | 337 | 338 | 339 | ```python 340 | #TSNE plot 341 | a=plot_marker_selection(data, markers, names[0]) 342 | ``` 343 | 344 | Computing TSNE embedding 345 | Elapsed time: 69.88537192344666 seconds 346 | 347 | 348 | 349 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_31_1.png) 350 | 351 | 352 | 353 | ```python 354 | 355 | ``` 356 | 357 | ### Example from second level of the hierarchy 358 | 359 | 360 | ```python 361 | for name in set(names[0]): 362 | idx=[s for s in range(len(names[0])) if names[0][s]==name] 363 | aux=plot_marker_selection(data[idx], markers, [names[1][s] for s in idx]) 364 | ``` 365 | 366 | Computing TSNE embedding 367 | Elapsed time: 8.925884008407593 seconds 368 | Computing TSNE embedding 369 | Elapsed time: 1.5634911060333252 seconds 370 | Computing TSNE embedding 371 | Elapsed time: 0.638862133026123 seconds 372 | Computing TSNE embedding 373 | Elapsed time: 7.366800785064697 seconds 374 | Computing TSNE embedding 375 | Elapsed time: 1.0175950527191162 seconds 376 | Computing TSNE embedding 377 | Elapsed time: 2.3961689472198486 seconds 378 | Computing TSNE embedding 379 | Elapsed time: 1.0149860382080078 seconds 380 | 381 | 382 | 383 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_34_1.png) 384 | 385 | 386 | 387 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_34_2.png) 388 | 389 | 390 | 391 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_34_3.png) 392 | 393 | 394 | 395 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_34_4.png) 396 | 397 | 398 | 399 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_34_5.png) 400 | 401 | 402 | 403 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_34_6.png) 404 | 405 | 406 | 407 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_34_7.png) 408 | 409 | 410 | 411 | ```python 412 | 413 | ``` 414 | 415 | ## One vs all markers 416 | 417 | 418 | ```python 419 | markers2=one_vs_all_selection(data,labels[0]) 420 | 421 | accuracy=performance(data, labels[0], data, labels[0], clf) 422 | accuracy_markers=performance(data[:,markers2], labels[0], data[:,markers2], labels[0], clf) 423 | 424 | print("Accuracy (whole data,", d, " markers): ", accuracy) 425 | print("Accuracy (selected", num_markers, "markers)", accuracy_markers) 426 | ``` 427 | 428 | Accuracy (whole data, 4000 markers): 0.8745424292845257 429 | Accuracy (selected 25 markers) 0.8569051580698835 430 | 431 | 432 | 433 | ```python 434 | a=plot_marker_selection(data, markers2, names[0]) 435 | ``` 436 | 437 | Computing TSNE embedding 438 | Elapsed time: 69.53578591346741 seconds 439 | 440 | 441 | 442 | ![png](https://raw.githubusercontent.com/solevillar/scGeneFit-python/master/imgs/output_38_1.png) 443 | 444 | 445 | 446 | ```python 447 | 448 | ``` 449 | -------------------------------------------------------------------------------- /examples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/examples/.DS_Store -------------------------------------------------------------------------------- /examples/.ipynb_checkpoints/scGeneFit_large_scale-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "colab_type": "text", 7 | "id": "view-in-github" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": { 17 | "colab": { 18 | "base_uri": "https://localhost:8080/", 19 | "height": 71 20 | }, 21 | "colab_type": "code", 22 | "id": "4mgHnCPFcOH9", 23 | "outputId": "c1d5321f-bbb3-4ce0-bf18-d8e74886513a" 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "%matplotlib inline\n", 28 | "import numpy as np\n", 29 | "import matplotlib.pyplot as plt\n", 30 | "import itertools\n", 31 | "from scGeneFit.functions import *\n", 32 | "np.random.seed(0)" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": { 39 | "colab": {}, 40 | "colab_type": "code", 41 | "id": "qyu6Z11fcUtF" 42 | }, 43 | "outputs": [], 44 | "source": [ 45 | "#Definition of functional groups\n", 46 | "#f_groups={functional_group_id: [mean1, mean2, ...], ...} where mean=[gene1,gene2, ...]\n", 47 | "f_groups={0:[[0,0], [1,0], [0,1], [1,1]], 1: [[0],[1]], 2: [[0,0], [0,1], [1,0], [1,1]], 3:[[0,0], [1,0], [0,1], [1,1]], 4: [[0],[1]], \n", 48 | " 5: [[0,0], [0,1], [1,0], [1,1]], 6:[[0,1], [1,0], [0,1], [1,1]], 7: [[2,2],[3,3]], 8: [[0,0], [0,4], [4,0], [4,4]],\n", 49 | " 9:[[0,0], [1,0], [0,1], [1,1]], 10: [[0],[1],[2],[4]], 11: [[0,0], [0,1], [1,0], [1,1]],\n", 50 | " 12:[[0,0], [1,0], [0,1], [1,1]], 13: [[0],[1]], 14: [[0,0], [0,1], [1,0], [1,1]]}\n" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 3, 56 | "metadata": { 57 | "colab": {}, 58 | "colab_type": "code", 59 | "id": "7VVDyFMAdmXA" 60 | }, 61 | "outputs": [], 62 | "source": [ 63 | "def create_data(f_groups, cell_types, sigma, n, repeat):\n", 64 | " aux=list(f_groups.keys())\n", 65 | " data=np.zeros( (0, sum([len(f_groups[aux[i]][0])*repeat[i] for i in range(len(aux))]) ))\n", 66 | " for cell in cell_types:\n", 67 | " expression=np.zeros((n, 0))\n", 68 | " for t in range(len(cell)):\n", 69 | " mean=f_groups[t][cell[t]]\n", 70 | " mean=np.concatenate([[mean[i]]*repeat[t] for i in range(len(mean))])\n", 71 | " expression=np.concatenate([expression, np.random.multivariate_normal(mean, sigma*np.identity(len(mean)), size=n)], axis=1)\n", 72 | " data=np.concatenate([data, expression])\n", 73 | " labels=np.concatenate([[i]*n for i in range(len(cell_types))])\n", 74 | " return data,labels" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 4, 80 | "metadata": { 81 | "colab": {}, 82 | "colab_type": "code", 83 | "id": "BcqQ7aNMNQ6Y" 84 | }, 85 | "outputs": [], 86 | "source": [ 87 | "#create data\n", 88 | "classes=40\n", 89 | "n=25\n", 90 | "n_groups=len(list(f_groups.keys()))\n", 91 | "cell_types = np.zeros((classes, n_groups))\n", 92 | "for i in range(n_groups):\n", 93 | " aux=np.random.permutation(classes)\n", 94 | " idx=list(f_groups.keys())[i]\n", 95 | " n_means=len(f_groups[idx])\n", 96 | " start=0\n", 97 | " offset=int(classes/n_means)\n", 98 | " for s in range(n_means):\n", 99 | " cell_types[aux[start:start+offset], i] = s\n", 100 | " start=start+offset+1\n", 101 | "cell_types=cell_types.astype(int)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 5, 107 | "metadata": { 108 | "colab": { 109 | "base_uri": "https://localhost:8080/", 110 | "height": 134 111 | }, 112 | "colab_type": "code", 113 | "id": "7PbXSbXY1ia0", 114 | "outputId": "d543d938-4523-479f-9720-a06eb1272751" 115 | }, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "Text(0, 0.5, 'synthetic cells')" 121 | ] 122 | }, 123 | "execution_count": 5, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | }, 127 | { 128 | "data": { 129 | "image/png": "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\n", 130 | "text/plain": [ 131 | "
" 132 | ] 133 | }, 134 | "metadata": { 135 | "needs_background": "light" 136 | }, 137 | "output_type": "display_data" 138 | } 139 | ], 140 | "source": [ 141 | "repeat=[10,10,10,10,10]+[np.random.randint(100, 800) for i in range(len(f_groups.keys())-5)]\n", 142 | "\n", 143 | "sc_gene, sc_labels=create_data(f_groups, cell_types, 0.5, n, repeat)\n", 144 | "plt.imshow(sc_gene)\n", 145 | "plt.xlabel('synthetic genes')\n", 146 | "plt.ylabel('synthetic cells')" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 6, 152 | "metadata": { 153 | "colab": { 154 | "base_uri": "https://localhost:8080/", 155 | "height": 34 156 | }, 157 | "colab_type": "code", 158 | "id": "G_DEw3soIhOw", 159 | "outputId": "4a8141fa-7295-4f7f-a2f4-d49bcbbd4bab" 160 | }, 161 | "outputs": [ 162 | { 163 | "name": "stdout", 164 | "output_type": "stream", 165 | "text": [ 166 | "(1000, 8798)\n" 167 | ] 168 | } 169 | ], 170 | "source": [ 171 | "#create data\n", 172 | "print(sc_gene.shape)\n", 173 | "X_train, y_train= sc_gene, sc_labels\n", 174 | "X_test, y_test= X_train, y_train\n" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 7, 180 | "metadata": { 181 | "colab": {}, 182 | "colab_type": "code", 183 | "id": "JuCRszrAjyMc" 184 | }, 185 | "outputs": [], 186 | "source": [ 187 | "#Choose an evaluation method (e.g. classification accuracy)\n", 188 | "from sklearn.neighbors import NearestCentroid\n", 189 | "clf=NearestCentroid()\n", 190 | "\n", 191 | "def performance(X_train, y_train, X_test, y_test, clf):\n", 192 | " clf.fit(X_train, y_train)\n", 193 | " return clf.score(X_test, y_test)" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": 8, 199 | "metadata": { 200 | "colab": { 201 | "base_uri": "https://localhost:8080/", 202 | "height": 34 203 | }, 204 | "colab_type": "code", 205 | "id": "JP7aMd9QuBDP", 206 | "outputId": "249774f5-9fc4-4ea2-8580-4c18a75f2250" 207 | }, 208 | "outputs": [ 209 | { 210 | "name": "stdout", 211 | "output_type": "stream", 212 | "text": [ 213 | "0.775\n" 214 | ] 215 | } 216 | ], 217 | "source": [ 218 | "markers_ova=one_vs_all_selection(X_train,y_train)\n", 219 | "one_vs_all_accuracy=performance(X_train[:,markers_ova], y_train, X_test[:,markers_ova], y_test, clf)\n", 220 | "print(one_vs_all_accuracy)" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 9, 226 | "metadata": { 227 | "colab": { 228 | "base_uri": "https://localhost:8080/", 229 | "height": 323 230 | }, 231 | "colab_type": "code", 232 | "id": "gFWlEWQUIhhZ", 233 | "outputId": "bd7805e9-192c-4c1d-f4e5-62eb626669ba" 234 | }, 235 | "outputs": [ 236 | { 237 | "name": "stdout", 238 | "output_type": "stream", 239 | "text": [ 240 | "Solving a linear program with 8798 variables and 43 constraints\n", 241 | "Time elapsed: 681.2142729759216 seconds\n", 242 | "markers: 25 accuracy: 0.623\n", 243 | "Solving a linear program with 8798 variables and 41 constraints\n", 244 | "Time elapsed: 908.7140011787415 seconds\n", 245 | "markers: 30 accuracy: 0.657\n", 246 | "Solving a linear program with 8798 variables and 40 constraints\n", 247 | "Time elapsed: 472.49677991867065 seconds\n", 248 | "markers: 35 accuracy: 0.782\n", 249 | "Solving a linear program with 8798 variables and 43 constraints\n", 250 | "Time elapsed: 451.2964618206024 seconds\n", 251 | "markers: 40 accuracy: 0.851\n", 252 | "Solving a linear program with 8798 variables and 42 constraints\n", 253 | "Time elapsed: 467.5282349586487 seconds\n", 254 | "markers: 45 accuracy: 0.912\n", 255 | "Solving a linear program with 8798 variables and 41 constraints\n", 256 | "Time elapsed: 444.65846705436707 seconds\n", 257 | "markers: 50 accuracy: 0.908\n" 258 | ] 259 | } 260 | ], 261 | "source": [ 262 | "m_range=range(25,55,5)\n", 263 | "\n", 264 | "#obtain markers\n", 265 | "#one vs all:\n", 266 | "opt_epsilon=[0.05 for i in m_range]\n", 267 | "\n", 268 | "\n", 269 | "#scGeneFit\n", 270 | "markers_lp=[]\n", 271 | "accuracy_list=[]\n", 272 | "for m, epsilon in zip(m_range, opt_epsilon):\n", 273 | " aux=get_markers(X_train, y_train, m, method='centers', redundancy=.002, epsilon=epsilon)\n", 274 | " markers_lp= markers_lp + [aux]\n", 275 | " \n", 276 | " accuracy = performance(X_train[:,aux], y_train, X_test[:,aux], y_test, clf)\n", 277 | " print(\"markers:\", m, \"accuracy:\", accuracy)\n", 278 | " accuracy_list+=[accuracy]\n", 279 | " " 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": 10, 285 | "metadata": { 286 | "colab": { 287 | "base_uri": "https://localhost:8080/", 288 | "height": 313 289 | }, 290 | "colab_type": "code", 291 | "id": "DiR-DQnF5cGE", 292 | "outputId": "cd167e0e-0bcd-4a0a-9263-6c5e6cbcc9e4" 293 | }, 294 | "outputs": [ 295 | { 296 | "data": { 297 | "image/png": "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6sTChQupWbMm3333HZGRkWzZsoVBgwaRmppKVFQUn376KY0bN87fXl5eHvXq1SMxMZFy5coBUL9+fX777TfmzZvHa6+9RnBwMGXLlmXevHmnxHL06FF69uzJwYMHOX78OG+88UZ+54DemDp1Km+88Ub+/Lfffku9evUoVepk1wdLliyhfv361KtXD4B+/frx3Xff0bTpqd1wXXfddbRp04aEhARSU1P5z3/+w5tvvsmqVavo27dv/vvcfvvtJCcnk5mZyZAhQxg4cCDgOuN56qmnmDVrFu+++27+djMyMujVqxd33nknDz/88BnHxChc/4cffmD69OmEhITQuXNn3nnnHaKiooiNjWXJkiW0b9/e69+TOWnPkUyenbqSXzek0rF+Rd6+qxU1y53e4aQpnuwMwocSEhL4/PPPWbx4MYsWLeLTTz9l+fLlAGzatIlBgwaxZs0aypUrx9SpUwEYOHAgf//730lISOCdd97hscceO2WbQUFB9OzZk2nTpgGuXl9jY2OpWrUqI0aMYNasWaxYsYLp06efFk9ERATTpk1j2bJlzJ07l2HDhuFtVyvbtm2jfPny+T3Hpqen89Zbb/HKK6+cUm7Hjh3UqnXy+ciYmBh27NjhcZthYWHMmzePRx55hJ49e/LBBx+wevVqxo0bx/79+wH47LPPSEhIID4+njFjxuQvT09Pp3nz5ixevDh/YKWjR49y2223cc899/Dwww+zbt26/DExEhMTCQ4OZvz48afVb9q0KdOmTWPNmjWsXLmSF198MT/GuLg45s+f79XvyJxq+oqddH5vHou27ufV25ryxUMdLDmUMIFzBnGOb/q+sGDBAnr16pX/DfuOO+5g/vz59OjRg7p169K6dWsA2rZtS1JSEkePHmXhwoX07t07fxtZWVmnbbdv376MGDGCBx98kAkTJuR3ptexY0f69+9Pnz59uOOOO06rp6q88MILzJs3j6CgIHbs2MGePXuoVu3c14F37dpF5cqV8+dfeeUVhg4dmn/vouB7FOape3OAHj16AK4xM5o1a0b16tUBqFevHsnJyVSsWJExY8bkJ8Pk5GQ2bdpExYoVCQ4O5s477zxlez179mT48OHce++9AGcdE6Ng/ejoaCIiIhgwYAC33nrrKfdZqlSpwvr168/5+zEnHUzP5qXvVvPDyl20rlWOUX1aUa9yEY6wYy6Z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\n", 298 | "text/plain": [ 299 | "
" 300 | ] 301 | }, 302 | "metadata": { 303 | "needs_background": "light" 304 | }, 305 | "output_type": "display_data" 306 | } 307 | ], 308 | "source": [ 309 | "l=accuracy_list\n", 310 | "\n", 311 | "#plot\n", 312 | "plt.plot(m_range, l)+plt.plot(m_range,[one_vs_all_accuracy for i in l])\n", 313 | "plt.legend([\"scGeneFit\", \"one vs all (40 markers)\"])\n", 314 | "plt.xlabel(\"number of markers\")\n", 315 | "plt.ylabel(\"accuracy\")\n", 316 | "plt.savefig(\"plot.pdf\")\n", 317 | "\n" 318 | ] 319 | } 320 | ], 321 | "metadata": { 322 | "colab": { 323 | "authorship_tag": "ABX9TyPCgLeiVLppCy8MLEQwaxj9", 324 | "collapsed_sections": [], 325 | "include_colab_link": true, 326 | "machine_shape": "hm", 327 | "name": "scGeneFit_large_scale.ipynb", 328 | "provenance": [] 329 | }, 330 | "kernelspec": { 331 | "display_name": "Python 3 (ipykernel)", 332 | "language": "python", 333 | "name": "python3" 334 | }, 335 | "language_info": { 336 | "codemirror_mode": { 337 | "name": "ipython", 338 | "version": 3 339 | }, 340 | "file_extension": ".py", 341 | "mimetype": "text/x-python", 342 | "name": "python", 343 | "nbconvert_exporter": "python", 344 | "pygments_lexer": "ipython3", 345 | "version": "3.11.5" 346 | } 347 | }, 348 | "nbformat": 4, 349 | "nbformat_minor": 1 350 | } 351 | -------------------------------------------------------------------------------- /examples/plot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/examples/plot.pdf -------------------------------------------------------------------------------- /examples/scGeneFit_large_scale.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "colab_type": "text", 7 | "id": "view-in-github" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": { 17 | "colab": { 18 | "base_uri": "https://localhost:8080/", 19 | "height": 71 20 | }, 21 | "colab_type": "code", 22 | "id": "4mgHnCPFcOH9", 23 | "outputId": "c1d5321f-bbb3-4ce0-bf18-d8e74886513a" 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "%matplotlib inline\n", 28 | "import numpy as np\n", 29 | "import matplotlib.pyplot as plt\n", 30 | "import itertools\n", 31 | "from scGeneFit.functions import *\n", 32 | "np.random.seed(0)" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": { 39 | "colab": {}, 40 | "colab_type": "code", 41 | "id": "qyu6Z11fcUtF" 42 | }, 43 | "outputs": [], 44 | "source": [ 45 | "#Definition of functional groups\n", 46 | "#f_groups={functional_group_id: [mean1, mean2, ...], ...} where mean=[gene1,gene2, ...]\n", 47 | "f_groups={0:[[0,0], [1,0], [0,1], [1,1]], 1: [[0],[1]], 2: [[0,0], [0,1], [1,0], [1,1]], 3:[[0,0], [1,0], [0,1], [1,1]], 4: [[0],[1]], \n", 48 | " 5: [[0,0], [0,1], [1,0], [1,1]], 6:[[0,1], [1,0], [0,1], [1,1]], 7: [[2,2],[3,3]], 8: [[0,0], [0,4], [4,0], [4,4]],\n", 49 | " 9:[[0,0], [1,0], [0,1], [1,1]], 10: [[0],[1],[2],[4]], 11: [[0,0], [0,1], [1,0], [1,1]],\n", 50 | " 12:[[0,0], [1,0], [0,1], [1,1]], 13: [[0],[1]], 14: [[0,0], [0,1], [1,0], [1,1]]}\n" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 3, 56 | "metadata": { 57 | "colab": {}, 58 | "colab_type": "code", 59 | "id": "7VVDyFMAdmXA" 60 | }, 61 | "outputs": [], 62 | "source": [ 63 | "def create_data(f_groups, cell_types, sigma, n, repeat):\n", 64 | " aux=list(f_groups.keys())\n", 65 | " data=np.zeros( (0, sum([len(f_groups[aux[i]][0])*repeat[i] for i in range(len(aux))]) ))\n", 66 | " for cell in cell_types:\n", 67 | " expression=np.zeros((n, 0))\n", 68 | " for t in range(len(cell)):\n", 69 | " mean=f_groups[t][cell[t]]\n", 70 | " mean=np.concatenate([[mean[i]]*repeat[t] for i in range(len(mean))])\n", 71 | " expression=np.concatenate([expression, np.random.multivariate_normal(mean, sigma*np.identity(len(mean)), size=n)], axis=1)\n", 72 | " data=np.concatenate([data, expression])\n", 73 | " labels=np.concatenate([[i]*n for i in range(len(cell_types))])\n", 74 | " return data,labels" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 4, 80 | "metadata": { 81 | "colab": {}, 82 | "colab_type": "code", 83 | "id": "BcqQ7aNMNQ6Y" 84 | }, 85 | "outputs": [], 86 | "source": [ 87 | "#create data\n", 88 | "classes=40\n", 89 | "n=25\n", 90 | "n_groups=len(list(f_groups.keys()))\n", 91 | "cell_types = np.zeros((classes, n_groups))\n", 92 | "for i in range(n_groups):\n", 93 | " aux=np.random.permutation(classes)\n", 94 | " idx=list(f_groups.keys())[i]\n", 95 | " n_means=len(f_groups[idx])\n", 96 | " start=0\n", 97 | " offset=int(classes/n_means)\n", 98 | " for s in range(n_means):\n", 99 | " cell_types[aux[start:start+offset], i] = s\n", 100 | " start=start+offset+1\n", 101 | "cell_types=cell_types.astype(int)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 5, 107 | "metadata": { 108 | "colab": { 109 | "base_uri": "https://localhost:8080/", 110 | "height": 134 111 | }, 112 | "colab_type": "code", 113 | "id": "7PbXSbXY1ia0", 114 | "outputId": "d543d938-4523-479f-9720-a06eb1272751" 115 | }, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "Text(0, 0.5, 'synthetic cells')" 121 | ] 122 | }, 123 | "execution_count": 5, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | }, 127 | { 128 | "data": { 129 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAB9CAYAAABESKIDAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB/NElEQVR4nO19ebheVXX3b5/zvndIchNCQhLCEJLITEAgLQQVZZBBtFhqnSjCZ/XTOgBFqjgUkDJYawXt4/A5gdYBHwUtKiqBIljDZABBpAEkDNqEEAiZc+99z1nfH2evfX57nfOGe0MQcnvW8yT3vOfsce211/rttScnIoJR0C9+8Qv85V/+JdasWYNTTz0VX/va1wAAH/nIR/Df//3fuPrqq0eTXEMNNdRQQw011NDzSm60YAcAsizDmjVrMHny5PDukUcewbhx4zBt2rStWsCGGmqooYYaaqih50JbBHYaaqihhhpqqKGGthVqjSTQgQceCOfciBK88847n1OBGmqooYYaaqihhrYmjQjsvP71r3+ei9FQQw011FBDDTX0/FAzjdVQQw011FBDDY1pSl7oAjTUUEMNNdRQQw09nzSiaazJkyePeM3O008//ZwK1FBDDTXUUEMNNbQ1aURg57LLLnuei9FQQw011FBDDTX0/FCzZqehhhpqqKGGGhrTtEVrdn7/+9/jYx/7GN7ylrdgxYoVAICf/exnuO+++7Zq4RpqqKGGGmqooYaeK40a7Nx0002YN28ebrvtNlx99dVYt24dAOCee+7Beeedt9ULOFL6/Oc/j9mzZ6Ovrw8HH3wwfvnLX75gZWmooYYaaqihhl48NGqwc8455+DCCy/EwoUL0dPTE94fccQRuOWWW7Zq4UZK3/3ud3HmmWfiox/9KO666y684hWvwPHHH4/HHnvsBSlPQw011FBDDTX04qFRr9mZMGEC7r33XsyePRsDAwP4zW9+gzlz5uCRRx7BXnvthU2bNj1fZe1KhxxyCA466CB84QtfCO/23ntvvP71r8cll1zyJy9PQw011FBDDTX04qER7cZi2m677bBs2TLMnj07en/XXXdhp5122moFGykNDQ1h8eLFOOecc6L3xxxzDBYtWlQbZ3BwEIODg+F3nud4+umnMWXKlBFvsW+ooYYaaqihhl5YEhGsXbsWM2fORJJ0n6waNdh561vfig996EP4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iRMnvtDFeV5orNexqd+2T2O9jmO9fsDYr+O2WD8Rwdq1azFz5kwkSc0cmqdRT2Ptsssuz+ou2tZIGTRp0qRtpoG3hCZOnDim6weM/To29dv2aazXcazXDxj7ddzW6jcSJ0V3GNSFLrvsMpxzzjl45JFHtqRMDTXUUEMNNdRQQ39SGrVn501vehM2bNiAuXPnYty4cWi329H3p59+eqsVrqGGGmqooYYaaui50qjBzqWXXlp7XcS2TL29vTjvvPOiU6HHEo31+gFjv45N/bZ9Gut1HOv1A8Z+Hcdy/Ua9QLmhhhpqqKGGGmpoW6JRr9l51atehW984xvYuHHj81GehhpqqKGGGmqooa1KowY7Bx98MD74wQ9ixowZeOc734lbb731+ShXQw011FBDDTXU0FahUYOdf/3Xf8Uf//hHfOMb38CTTz6Jww8/HPvssw8+9alP4Yknnng+ythQQw011FBDDTW0xfSc1+w8+eST+H//7//hoosuQpZleM1rXoPTTz8dRx555NYqY0MNNdRQQw011NAW06g9O0y33347zj33XHzqU5/CtGnT8OEPfxjTpk3D6173Opx99tlbq4zPK33+85/H7Nmz0dfXh4MPPhi//OUvX+gi1dLNN9+M173udZg5cyacc/jhD38YfRcRnH/++Zg5cyb6+/vxqle9Cvfdd18UZnBwEO9///sxdepUjB8/Hn/xF3+BP/zhD1GYVatW4ZRTTsGkSZMwadIknHLKKXjmmWee59oBl1xyCf7sz/4MAwMDmDZtGl7/+tdjyZIlUZhtuY5f+MIXsP/++4fDuhYsWICf/vSnY6JudXTJJZfAOYczzzwzvNvW63j++efDORf9mzFjxpipHwD88Y9/xN/8zd9gypQpGDduHF760pdi8eLF4fu2Xsfddtut0obOObz3ve8dE/XrdDr42Mc+htmzZ6O/vx9z5szBBRdcUNwN6Glbr+MWk4ySnnjiCfnUpz4l++67r/T09Mhf/dVfyU9/+lPJ8zyEWbhwoYwfP360Sf/J6corr5R2uy1f/vKX5Xe/+52cccYZMn78eHn00Udf6KJV6Nprr5WPfvSjctVVVwkA+cEPfhB9/8QnPiEDAwNy1VVXyb333itvetObZMcdd5Q1a9aEMO9+97tlp512koULF8qdd94pRxxxhBxwwAHS6XRCmOOOO072228/WbRo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RSIi8utf/1qmT5++RaukXyjSredf/epX5Xe/+52ceeaZMn78eHnkkUde6KJVaO3atXLXXXfJXXfdJQDk05/+tNx1111hm/wnPvEJmTRpklx99dVy7733ylve8pba7YQ777yzXH/99XLnnXfKkUceWbudcP/995dbbrlFbrnlFpk3b96fZDvh3/3d38mkSZPkF7/4RbQ1dMOGDSHMtlzHD3/4w3LzzTfL0qVL5Z577pGPfOQjkiSJXHfdddt83boR78YS2fbr+IEPfEB+8YtfyMMPPyy33nqrvPa1r5WBgYGgL7b1+t1+++3SarXkoosukgcffFC+9a1vybhx4+Sb3/xmCLOt11FEJMsy2XXXXeVDH/pQ5du2Xr9TTz1Vdtppp7D1/Oqrr5apU6fKBz/4wTFTxy2lUYOd733ve9JutyVJEnn1q18d3l988cVy3HHHbdXC/Snoc5/7nMyaNUt6enrkoIMOCludX2x04403CoDKv1NPPVVEii2F5513nsyYMUN6e3vl8MMPl3vvvTdKY+PGjfK+971Ptt9+e+nv75fXvva18thjj0VhnnrqKTn55JNlYGBABgYG5OSTT5ZVq1Y97/WrqxsAufzyy0OYbbmOb3/724Oc7bDDDnLUUUcFoLOt160bWbCzrddRzyNpt9syc+ZMOemkk+S+++4bM/UTEfnRj34k++23n/T29spee+0lX/rSl6LvY6GOP//5zwWALFmypPJtW6/fmjVr5IwzzpBdd91V+vr6ZM6cOfLRj35UBgcHx0wdt5S26LqI5cuXY9myZTjggAOCy+z222/HxIkTsddee20Nh1NDDTXUUEMNNdTQVqHnfDdWQw011FBDDTXU0IuZntPdWA011FBDDTXUUEMvdmrATkMNNdRQQw01NKapATsNNdRQQw011NCYpgbsNNRQQw011FBDY5oasNNQQw011FBDDY1pasBOQw011FBDDTU0pqkBOw011NALSo888gicc7j77ru3etpXXHEFtttuu62ebkMNNbRtUQN2GmqooT8ZnXbaaXj961//vKS922674bLLLovevelNb8IDDzzwvOTXUEMNbTvUeqEL0FBDDTX0fFF/fz/6+/tf6GI01FBDLzA1np2GGmoo0Pe//33MmzcP/f39mDJlCo4++misX78eN998M9rtNpYvXx6F/8AHPoDDDz8cQDll9POf/xx77703JkyYgOOOOw7Lli0DAJx//vn4+te/jv/4j/+Acw7OOfziF78IaT388MM44ogjMG7cOBxwwAG45ZZborwWLVqEww8/HP39/dhll11w+umnY/369QCAV73qVXj00Ufx93//9yFtLhPTNddcg/nz56Ovrw9Tp07FSSedtFmeXHjhhZg2bRoGBgbwjne8A+eccw5e+tKXRmEuv/xy7L333ujr68Nee+2Fz3/+8+GbTtNdffXVW1w/APj85z+P3XffHX19fZg+fTre8IY3bLbcDTXUENELezVXQw019GKh//mf/5FWqyWf/vSnw+3sn/vc52Tt2rUiIrLHHnvIJz/5yRB+eHhYpk2bJl/72tdEROTyyy+XdrstRx99tNxxxx2yePFi2XvvveWtb32riIisXbtW3vjGN8pxxx0XbrUfHByUpUuXCgDZa6+95Mc//rEsWbJE3vCGN8isWbNkeHhYRETuuecemTBhglx66aXywAMPyK9+9Ss58MAD5bTTThOR4lLCnXfeWS644IKQtpZp0qRJocw//vGPJU1TOffcc+V3v/ud3H333XLRRRd15ck3v/lN6evrk6997WuyZMkS+fjHPy4TJ06UAw44IIT50pe+JDvuuKNcddVV8vDDD8tVV10l22+/vVxxxRUiIlulfnfccYekaSrf/va35ZFHHpE777xTPvOZz2xxWzfU0P82asBOQw01JCIiixcvFgDyyCOP1H7/53/+Z9l7773D7x/+8IcyYcIEWbdunYgUwAKAPPTQQyHM5z73OZk+fXr4feqpp8qJJ54Ypatg4Ctf+Up4d9999wkAuf/++0VE5JRTTpH/+3//bxTvl7/8pSRJIhs3bhQRkVmzZsmll14ahbFgZ8GCBXLyySc/CydKOuSQQ+S9731v9O5lL3tZBHZ22WUX+fa3vx2F+ad/+idZsGDBVqvfVVddJRMnTpQ1a9aMuOwNNdRQSc00VkMNNQQAOOCAA3DUUUdh3rx5+Ou//mt8+ctfxqpVq8L30047DQ899BBuvfVWAMDXvvY1vPGNb8T48eNDmHHjxmHu3Lnh94477ogVK1aMKP/9998/igcgxF28eDGuuOIKTJgwIfw79thjkec5li5dOuI63n333TjqqKNGHH7JkiX48z//8+gd/37yySfx+OOP42//9m+jsl144YX4/e9/v9Xq9+pXvxqzZs3CnDlzcMopp+Bb3/oWNmzYMOJ6NNTQ/3ZqFig31FBDAIA0TbFw4UIsWrQI1113Hf7t3/4NH/3oR3Hbbbdh9uzZmDZtGl73utfh8ssvx5w5c3DttddGa24AoN1uR7+dcxCREeXPcXXNTZ7n4e+73vUunH766ZV4u+6664jruCWLlbUsSlwfLd+Xv/xlHHLIIVG4NE2j38+lfj09Pbjzzjvxi1/8Atdddx3OPfdcnH/++bjjjjuarfUNNTQCasBOQw01FMg5h5e97GV42ctehnPPPRezZs3CD37wA5x11lkAgHe84x1485vfjJ133hlz587Fy172slGl39PTgyzLRl2ugw46CPfddx9e8pKXPKe0999/f9xwww34P//n/4wo3z333BO33347TjnllPDu17/+dXiePn06dtppJzz88MM4+eSTR5RmHY2kfq1WC0cffTSOPvponHfeedhuu+3wn//5n8+6wLqhhhpqwE5DDTXk6bbbbsMNN9yAY445BtOmTcNtt92GJ598EnvvvXcIc+yxx2LSpEm48MILccEFF4w6j9122w0///nPsWTJEkyZMgWTJk0aUbwPfehDOPTQQ/He974X73znOzF+/Hjcf//9WLhwIf7t3/4tpH3zzTfjzW9+M3p7ezF16tRKOueddx6OOuoozJ07F29+85vR6XTw05/+FB/84Adr833/+9+Pd77znZg/fz4OO+wwfPe738U999yDOXPmhDDnn38+Tj/9dEycOBHHH388BgcH8etf/xqrVq0KIPG51u/HP/4xHn74YRx++OGYPHkyrr32WuR5jj333HNE6TfU0P92atbsNNRQQwCAiRMn4uabb8ZrXvMa7LHHHvjYxz6Gf/3Xf8Xxxx8fwiRJgtNOOw1ZluFtb3vbqPN45zvfiT333BPz58/HDjvsgF/96lcjirf//vvjpptuwoMPPohXvOIVOPDAA/GP//iPYe0LAFxwwQV45JFHMHfuXOywww616bzqVa/C9773PVxzzTV46UtfiiOPPBK33XZb13xPPvlkfPjDH8bZZ5+Ngw46CEuXLsVpp52Gvr6+EOYd73gHvvKVr+CKK67AvHnz8MpXvhJXXHEFZs+ePUKuPHv9tttuO1x99dU48sgjsffee+OLX/wivvOd72DfffcdcR4NNfS/mZyMdEK9oYYaaggFYHniiSdwzTXXvNBFeUHo1a9+NWbMmIF///d/f6GL0lBDDY2QmmmshhpqaES0evVq3HHHHfjWt76F//iP/3ihi/MnoQ0bNuCLX/wijj32WKRpiu985zu4/vrrsXDhwhe6aA011NAoqAE7DTXU0IjoxBNPxO233453vetdePWrX/1CF+dPQs45XHvttbjwwgsxODiIPffcE1dddRWOPvroF7poDTXU0CiomcZqqKGGGmqooYbGNDULlBtqqKGGGmqooTFNDdhpqKGGGmqooYbGNDVgp6GGGmqooYYaGtPUgJ2GGmqooYYaamhMUwN2GmqooYYaaqihMU0N2GmooYYaaqihhsY0NWCnoYYaaqihhhoa09SAnYYaaqihhhpqaExTA3YaaqihhhpqqKExTf8fcH3DPSox23AAAAAASUVORK5CYII=", 130 | "text/plain": [ 131 | "
" 132 | ] 133 | }, 134 | "metadata": {}, 135 | "output_type": "display_data" 136 | } 137 | ], 138 | "source": [ 139 | "repeat=[10,10,10,10,10]+[np.random.randint(100, 800) for i in range(len(f_groups.keys())-5)]\n", 140 | "\n", 141 | "sc_gene, sc_labels=create_data(f_groups, cell_types, 0.5, n, repeat)\n", 142 | "plt.imshow(sc_gene)\n", 143 | "plt.xlabel('synthetic genes')\n", 144 | "plt.ylabel('synthetic cells')" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 6, 150 | "metadata": { 151 | "colab": { 152 | "base_uri": "https://localhost:8080/", 153 | "height": 34 154 | }, 155 | "colab_type": "code", 156 | "id": "G_DEw3soIhOw", 157 | "outputId": "4a8141fa-7295-4f7f-a2f4-d49bcbbd4bab" 158 | }, 159 | "outputs": [ 160 | { 161 | "name": "stdout", 162 | "output_type": "stream", 163 | "text": [ 164 | "(1000, 8798)\n" 165 | ] 166 | } 167 | ], 168 | "source": [ 169 | "#create data\n", 170 | "print(sc_gene.shape)\n", 171 | "X_train, y_train= sc_gene, sc_labels\n", 172 | "X_test, y_test= X_train, y_train\n" 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": 7, 178 | "metadata": { 179 | "colab": {}, 180 | "colab_type": "code", 181 | "id": "JuCRszrAjyMc" 182 | }, 183 | "outputs": [], 184 | "source": [ 185 | "#Choose an evaluation method (e.g. classification accuracy)\n", 186 | "from sklearn.neighbors import NearestCentroid\n", 187 | "clf=NearestCentroid()\n", 188 | "\n", 189 | "def performance(X_train, y_train, X_test, y_test, clf):\n", 190 | " clf.fit(X_train, y_train)\n", 191 | " return clf.score(X_test, y_test)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": 8, 197 | "metadata": { 198 | "colab": { 199 | "base_uri": "https://localhost:8080/", 200 | "height": 34 201 | }, 202 | "colab_type": "code", 203 | "id": "JP7aMd9QuBDP", 204 | "outputId": "249774f5-9fc4-4ea2-8580-4c18a75f2250" 205 | }, 206 | "outputs": [ 207 | { 208 | "name": "stdout", 209 | "output_type": "stream", 210 | "text": [ 211 | "0.775\n" 212 | ] 213 | } 214 | ], 215 | "source": [ 216 | "markers_ova=one_vs_all_selection(X_train,y_train)\n", 217 | "one_vs_all_accuracy=performance(X_train[:,markers_ova], y_train, X_test[:,markers_ova], y_test, clf)\n", 218 | "print(one_vs_all_accuracy)" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": 9, 224 | "metadata": { 225 | "colab": { 226 | "base_uri": "https://localhost:8080/", 227 | "height": 323 228 | }, 229 | "colab_type": "code", 230 | "id": "gFWlEWQUIhhZ", 231 | "outputId": "bd7805e9-192c-4c1d-f4e5-62eb626669ba" 232 | }, 233 | "outputs": [ 234 | { 235 | "name": "stdout", 236 | "output_type": "stream", 237 | "text": [ 238 | "Solving a linear program with 8798 variables and 43 constraints\n", 239 | "Time elapsed: 1.456153154373169 seconds\n", 240 | "markers: 25 accuracy: 0.623\n", 241 | "Solving a linear program with 8798 variables and 41 constraints\n", 242 | "Time elapsed: 5.00743293762207 seconds\n", 243 | "markers: 30 accuracy: 0.657\n", 244 | "Solving a linear program with 8798 variables and 40 constraints\n", 245 | "Time elapsed: 1.5490071773529053 seconds\n", 246 | "markers: 35 accuracy: 0.782\n", 247 | "Solving a linear program with 8798 variables and 43 constraints\n", 248 | "Time elapsed: 6.25360369682312 seconds\n", 249 | "markers: 40 accuracy: 0.851\n", 250 | "Solving a linear program with 8798 variables and 42 constraints\n", 251 | "Time elapsed: 5.604511976242065 seconds\n", 252 | "markers: 45 accuracy: 0.912\n", 253 | "Solving a linear program with 8798 variables and 41 constraints\n", 254 | "Time elapsed: 5.980199098587036 seconds\n", 255 | "markers: 50 accuracy: 0.908\n" 256 | ] 257 | } 258 | ], 259 | "source": [ 260 | "m_range=range(25,55,5)\n", 261 | "\n", 262 | "#obtain markers\n", 263 | "#one vs all:\n", 264 | "opt_epsilon=[0.05 for i in m_range]\n", 265 | "\n", 266 | "\n", 267 | "#scGeneFit\n", 268 | "markers_lp=[]\n", 269 | "accuracy_list=[]\n", 270 | "for m, epsilon in zip(m_range, opt_epsilon):\n", 271 | " aux=get_markers(X_train, y_train, m, method='centers', redundancy=.002, epsilon=epsilon)\n", 272 | " markers_lp= markers_lp + [aux]\n", 273 | " \n", 274 | " accuracy = performance(X_train[:,aux], y_train, X_test[:,aux], y_test, clf)\n", 275 | " print(\"markers:\", m, \"accuracy:\", accuracy)\n", 276 | " accuracy_list+=[accuracy]\n", 277 | " " 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 10, 283 | "metadata": { 284 | "colab": { 285 | "base_uri": "https://localhost:8080/", 286 | "height": 313 287 | }, 288 | "colab_type": "code", 289 | "id": "DiR-DQnF5cGE", 290 | "outputId": "cd167e0e-0bcd-4a0a-9263-6c5e6cbcc9e4" 291 | }, 292 | "outputs": [ 293 | { 294 | "data": { 295 | "image/png": "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", 296 | "text/plain": [ 297 | "
" 298 | ] 299 | }, 300 | "metadata": {}, 301 | "output_type": "display_data" 302 | } 303 | ], 304 | "source": [ 305 | "l=accuracy_list\n", 306 | "\n", 307 | "#plot\n", 308 | "plt.plot(m_range, l)+plt.plot(m_range,[one_vs_all_accuracy for i in l])\n", 309 | "plt.legend([\"scGeneFit\", \"one vs all (40 markers)\"])\n", 310 | "plt.xlabel(\"number of markers\")\n", 311 | "plt.ylabel(\"accuracy\")\n", 312 | "plt.savefig(\"plot.pdf\")\n", 313 | "\n" 314 | ] 315 | } 316 | ], 317 | "metadata": { 318 | "colab": { 319 | "authorship_tag": "ABX9TyPCgLeiVLppCy8MLEQwaxj9", 320 | "collapsed_sections": [], 321 | "include_colab_link": true, 322 | "machine_shape": "hm", 323 | "name": "scGeneFit_large_scale.ipynb", 324 | "provenance": [] 325 | }, 326 | "kernelspec": { 327 | "display_name": "Python 3 (ipykernel)", 328 | "language": "python", 329 | "name": "python3" 330 | }, 331 | "language_info": { 332 | "codemirror_mode": { 333 | "name": "ipython", 334 | "version": 3 335 | }, 336 | "file_extension": ".py", 337 | "mimetype": "text/x-python", 338 | "name": "python", 339 | "nbconvert_exporter": "python", 340 | "pygments_lexer": "ipython3", 341 | "version": "3.11.5" 342 | } 343 | }, 344 | "nbformat": 4, 345 | "nbformat_minor": 1 346 | } 347 | -------------------------------------------------------------------------------- /imgs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/.DS_Store -------------------------------------------------------------------------------- /imgs/output_11_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_11_1.png -------------------------------------------------------------------------------- /imgs/output_14_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_14_1.png -------------------------------------------------------------------------------- /imgs/output_17_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_17_1.png -------------------------------------------------------------------------------- /imgs/output_20_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_20_1.png -------------------------------------------------------------------------------- /imgs/output_25_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_25_1.png -------------------------------------------------------------------------------- /imgs/output_31_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_31_1.png -------------------------------------------------------------------------------- /imgs/output_34_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_34_1.png -------------------------------------------------------------------------------- /imgs/output_34_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_34_2.png -------------------------------------------------------------------------------- /imgs/output_34_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_34_3.png -------------------------------------------------------------------------------- /imgs/output_34_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_34_4.png -------------------------------------------------------------------------------- /imgs/output_34_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_34_5.png -------------------------------------------------------------------------------- /imgs/output_34_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_34_6.png -------------------------------------------------------------------------------- /imgs/output_34_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_34_7.png -------------------------------------------------------------------------------- /imgs/output_38_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/imgs/output_38_1.png -------------------------------------------------------------------------------- /scGeneFit/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/.DS_Store -------------------------------------------------------------------------------- /scGeneFit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/__init__.py -------------------------------------------------------------------------------- /scGeneFit/data_files/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/.DS_Store -------------------------------------------------------------------------------- /scGeneFit/data_files/CITEseq-labels.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/CITEseq-labels.mat -------------------------------------------------------------------------------- /scGeneFit/data_files/CITEseq.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/CITEseq.mat -------------------------------------------------------------------------------- /scGeneFit/data_files/CITEseq_names.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/CITEseq_names.mat -------------------------------------------------------------------------------- /scGeneFit/data_files/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | try: 3 | import importlib.resources as importlib_resources 4 | except ImportError: 5 | # In PY<3.7 fall-back to backported `importlib_resources`. 6 | import importlib_resources 7 | 8 | def get_data(filename): 9 | with importlib_resources.path(__name__, filename) as foo: 10 | return str(foo) -------------------------------------------------------------------------------- /scGeneFit/data_files/data source: -------------------------------------------------------------------------------- 1 | CITE-seq data from 2 | Marlon Stoeckius, Christoph Hafemeister, William Stephenson, Brian Houck-Loomis, Pratip K Chattopadhyay, Harold Swerdlow, Rahul Satija, and Peter Smibert. 3 | Simultaneous epitope and transcriptome measurement insingle cells. Nature Methods, 14(9):865, 2017. 4 | 5 | Zeisel data from 6 | Amit Zeisel, Ana B Munoz-Manchado, Simone Codeluppi, Peter Lonnerberg, Gioele La Manno, Anna Jureus, Sueli Marques, Hermany Munguba, Liqun He, Christer Betsholtz, et al. 7 | Cell types in the mouse cortex and hippocampus revealed by single-cell RNA-seq. Science, 347(6226):1138–1142, 2015. 8 | -------------------------------------------------------------------------------- /scGeneFit/data_files/zeisel_data.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/zeisel_data.mat -------------------------------------------------------------------------------- /scGeneFit/data_files/zeisel_labels1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/zeisel_labels1.mat -------------------------------------------------------------------------------- /scGeneFit/data_files/zeisel_labels2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/zeisel_labels2.mat -------------------------------------------------------------------------------- /scGeneFit/data_files/zeisel_names.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solevillar/scGeneFit-python/19c8a697519ea3e247916696b8fbec3e86c0a6e8/scGeneFit/data_files/zeisel_names.mat -------------------------------------------------------------------------------- /scGeneFit/functions.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import scipy 4 | import time 5 | import sklearn 6 | import sklearn.manifold 7 | import scipy.io 8 | from . import data_files 9 | 10 | 11 | 12 | def get_markers(data, labels, num_markers, method='centers', epsilon=1, sampling_rate=1, n_neighbors=3, max_constraints=1000, redundancy=0.01, verbose=True): 13 | """marker selection algorithm 14 | data: Nxd numpy array with point coordinates, N: number of points, d: dimension 15 | labels: list with labels (N labels, one per point) 16 | num_markers: target number of markers to select. num_markersDelta, where Delta is chosen to be epsilon times the norm of the smallest constraint (default 1) 19 | (This is the most important parameter in this problem, it determines the scale of the constraints, 20 | the rest the rest of the parameters only determine the size of the LP) 21 | sampling_rate: (if method=='pairwise' or 'pairwise_centers') selects constraints from a random sample of proportion sampling_rate (default 1) 22 | n_neighbors: (if method=='pairwise') chooses the constraints from n_neighbors nearest neighbors (default 3) 23 | max_constraints: maximum number of constraints to consider (default 1000) 24 | redundancy: (if method=='centers') in this case not all pairwise constraints are considered 25 | but just between centers of consecutive labels plus a random fraction of constraints given by redundancy 26 | if redundancy==1 all constraints between pairs of centers are considered """ 27 | d = data.shape[1] 28 | t = time.time() 29 | samples, samples_labels, idx = __sample(data, labels, sampling_rate) 30 | 31 | if method == 'pairwise_centers': 32 | constraints, smallest_norm = __select_constraints_centers( 33 | data, labels, samples, samples_labels) 34 | elif method == 'pairwise': 35 | constraints, smallest_norm = __select_constraints_pairwise( 36 | data, labels, samples, samples_labels, n_neighbors) 37 | else: 38 | constraints, smallest_norm = __select_constraints_summarized(data, labels, redundancy) 39 | 40 | num_cons = constraints.shape[0] 41 | if num_cons > max_constraints: 42 | p = np.random.permutation(num_cons)[0:max_constraints] 43 | constraints = constraints[p, :] 44 | if verbose: 45 | print('Solving a linear program with {} variables and {} constraints'.format( 46 | constraints.shape[1], constraints.shape[0])) 47 | sol = __lp_markers(constraints, num_markers, smallest_norm * epsilon) 48 | if verbose: 49 | print('Time elapsed: {} seconds'.format(time.time() - t)) 50 | x = sol['x'][0:d] 51 | markers = sorted(range(len(x)), key=lambda i: x[i], reverse=True)[ 52 | : num_markers] 53 | return markers 54 | 55 | 56 | def get_markers_hierarchy(data, labels, num_markers, method='centers', sampling_rate=0.1, n_neighbors=3, epsilon=10, max_constraints=1000, redundancy=0.01, verbose=True): 57 | """marker selection algorithm with hierarchical labels 58 | data: Nxd numpy array with point coordinates, N: number of points, d: dimension 59 | labels: list with T lists of labels, where T is the number of layers in the hierarchy (N labels per list, one per point) 60 | num_markers: target number of markers to select. num_markers max_constraints: 106 | p = np.random.permutation(num_cons)[0:max_constraints] 107 | constraints = constraints[p, :] 108 | if verbose: 109 | print('Solving a linear program with {} variables and {} constraints'.format(constraints.shape[1], constraints.shape[0])) 110 | sol = __lp_markers(constraints, num_markers, smallest_norm * epsilon) 111 | if verbose: 112 | print('Time elapsed: {} seconds'.format(time.time() - t)) 113 | x = sol['x'][0:d] 114 | markers = sorted(range(len(x)), key=lambda i: x[i], reverse=True)[ 115 | : num_markers] 116 | return markers 117 | 118 | 119 | def __sample(data, labels, sampling_rate): 120 | """subsample data""" 121 | indices = [] 122 | for i in set(labels): 123 | idxs = [x for x in range(len(labels)) if labels[x] == i] 124 | n = len(idxs) 125 | s = int(np.ceil(len(idxs) * sampling_rate)) 126 | aux = np.random.permutation(n)[0:s] 127 | indices += [idxs[x] for x in aux] 128 | return [data[i] for i in indices], [labels[i] for i in indices], indices 129 | 130 | 131 | def __select_constraints_summarized(data, labels, redundancy=0.01): 132 | """selects constraints of the form c_a-c_(a+1) where c_i's are the empirical centers of different classes""" 133 | constraints = [] 134 | centers = {} 135 | smallest_norm = np.inf 136 | labels_set = list(set(labels)) 137 | k = len(labels_set) 138 | for idx in labels_set: 139 | X = [data[x, :] for x in range(len(labels)) if labels[x] == idx] 140 | centers[idx] = np.array(X).mean(axis=0) 141 | for i in range(len(labels_set)): 142 | v = centers[labels_set[i]]-centers[labels_set[(i+1) % k]] 143 | constraints += [v] 144 | if np.linalg.norm(v) ** 2 < smallest_norm: 145 | smallest_norm = np.linalg.norm(v) ** 2 146 | for j in range(len(labels_set)): 147 | if j != i and j != (i+1) % k: 148 | if np.random.rand() < redundancy: 149 | v = centers[labels_set[j]]-centers[labels_set[(j+1) % k]] 150 | constraints += [v] 151 | if np.linalg.norm(v) ** 2 < smallest_norm: 152 | smallest_norm = np.linalg.norm(v) ** 2 153 | constraints = np.array(constraints) 154 | return -constraints * constraints, smallest_norm 155 | 156 | 157 | def __select_constraints_pairwise(data, labels, samples, samples_labels, n_neighbors): 158 | """select constraints of the form x-y where x,y have different labels""" 159 | constraints = [] 160 | # nearest neighbors are selected from the entire set 161 | neighbors = {} 162 | data_by_label = {} 163 | smallest_norm = np.inf 164 | for i in set(labels): 165 | X = [data[x, :] for x in range(len(labels)) if labels[x] == i] 166 | data_by_label[i] = X 167 | neighbors[i] = sklearn.neighbors.NearestNeighbors( 168 | n_neighbors=n_neighbors).fit(np.array(X)) 169 | # compute nearest neighbor for samples 170 | for i in neighbors.keys(): 171 | Y = [samples[x] 172 | for x in range(len(samples_labels)) if samples_labels[x] == i] 173 | for j in neighbors.keys(): 174 | if i != j: 175 | idx = neighbors[j].kneighbors(Y)[1] 176 | for s in range(len(Y)): 177 | for t in idx[s]: 178 | v = Y[s] - data_by_label[j][t] 179 | constraints += [v] 180 | if np.linalg.norm(v) ** 2 < smallest_norm: 181 | smallest_norm = np.linalg.norm(v) ** 2 182 | constraints = np.array(constraints) 183 | return -constraints * constraints, smallest_norm 184 | 185 | 186 | def __select_constraints_centers(data, labels, samples, samples_labels): 187 | """select constraints of the form (x-ct')^2 - (x-ct)^2> Delta^2 y where x belongs to cluster with center ct""" 188 | constraints = [] 189 | # nearest neighbors are selected from the entire set 190 | centers_by_label = {} 191 | smallest_norm = np.inf 192 | for i in set(labels): 193 | X = np.array([data[x, :] 194 | for x in range(len(labels)) if labels[x] == i]) 195 | centers_by_label[i] = np.sum(X, axis=0) / X.shape[0] 196 | # compute nearest neighbor for samples 197 | for p in range(len(samples)): 198 | # distance to it's own center 199 | aux0 = (samples[p] - centers_by_label[samples_labels[p]]) * \ 200 | (samples[p] - centers_by_label[samples_labels[p]]) 201 | for i in set(labels): 202 | if samples_labels[p] != i: 203 | # distance to other centers 204 | aux1 = (samples[p] - centers_by_label[i]) * \ 205 | (samples[p] - centers_by_label[i]) 206 | constraints += [aux0 - aux1] 207 | if np.linalg.norm(aux0 - aux1) < smallest_norm: 208 | smallest_norm = np.linalg.norm(aux0-aux1) 209 | constraints = np.array(constraints) 210 | return constraints, smallest_norm 211 | 212 | 213 | def __lp_markers(constraints, num_markers, epsilon): 214 | m, d = constraints.shape 215 | c = np.concatenate((np.zeros(d), np.ones(m))) 216 | l = np.zeros(d + m) 217 | u = np.concatenate((np.ones(d), np.array([None for i in range(m)]))) 218 | aux1 = np.concatenate((constraints, -np.identity(m)), axis=1) 219 | aux2 = np.concatenate((np.ones((1, d)), np.zeros((1, m))), axis=1) 220 | A = np.concatenate((aux1, aux2), axis=0) 221 | b = np.concatenate((-epsilon * np.ones(m), np.array([num_markers]))) 222 | bounds = [(l[i], u[i]) for i in range(d + m)] 223 | sol = scipy.optimize.linprog(c, A, b, None, None, bounds) 224 | return sol 225 | 226 | 227 | def circles_example(N=30, d=5): 228 | num_markers = 2 229 | X = np.concatenate((np.array([[np.sin(2 * np.pi * i / N), np.cos(2 * np.pi * i / N)] for i in range(N)]), 230 | np.random.random((N, d - 2))), axis=1) 231 | Y = np.concatenate((np.array([[2 * np.sin(2 * np.pi * i / N), 2 * np.cos(2 * np.pi * i / N)] for i in range(N)]), 232 | np.random.random((N, d - 2))), axis=1) 233 | data = np.concatenate((X, Y), axis=0) 234 | labels = np.concatenate((np.zeros(10), np.ones(10))) 235 | fig = plt.figure() 236 | ax = fig.add_subplot(121, projection='3d') 237 | ax.scatter(data[0:N, 0], data[0:N, 1], data[0:N, 2], c='r', marker='o') 238 | ax.scatter(data[N + 1:2 * N, 0], data[N + 1:2 * N, 1], 239 | data[N + 1:2 * N, 2], c='g', marker='x') 240 | plt.show() 241 | sol = get_markers(data, labels, num_markers, 1, 3, 10) 242 | x = sol['x'][0:d] 243 | markers = sorted(range(len(x)), key=lambda i: x[i], reverse=True)[ 244 | :num_markers] 245 | for i in range(d): 246 | if i not in markers: 247 | data[:, i] = np.zeros(2 * N) 248 | ax2 = fig.add_subplot(122, projection='3d') 249 | ax2.scatter(data[0:N, 0], data[0:N, 1], data[0:N, 2], c='r', marker='o') 250 | ax2.scatter(data[N + 1:2 * N, 0], data[N + 1:2 * N, 1], 251 | data[N + 1:2 * N, 2], c='g', marker='x') 252 | plt.show() 253 | 254 | 255 | def plot_marker_selection(data, markers, names, perplexity=40): 256 | print('Computing TSNE embedding') 257 | # code fix to deal with exceptions if there is a particular cell class type with n < 40 258 | # automatically re-scales perplexity in these cases 259 | if len(data) < 40: 260 | perplexity = len(data) - 1 261 | else: 262 | perplexity = 40 263 | t = time.time() 264 | X_original = sklearn.manifold.TSNE( 265 | n_components=2, perplexity=perplexity).fit_transform(data) 266 | X_embedded = sklearn.manifold.TSNE(n_components=2, perplexity=perplexity).fit_transform( 267 | data[:, markers]) 268 | print('Elapsed time: {} seconds'.format(time.time() - t)) 269 | cmap = plt.cm.jet 270 | unique_names = list(set(names)) 271 | num_labels = len(unique_names) 272 | colors = [cmap(int(i * 256 / num_labels)) for i in range(num_labels)] 273 | aux = [colors[unique_names.index(name)] for name in names] 274 | 275 | fig = plt.figure() 276 | ax = fig.add_subplot(121) 277 | for g in unique_names: 278 | i = [s for s in range(len(names)) if names[s] == g] 279 | ax.scatter(X_original[i, 0], X_original[i, 1], 280 | c=[aux[i[0]]], s=5, label=names[i[0]]) 281 | ax.set_title('Original data') 282 | ax2 = fig.add_subplot(122) 283 | for g in np.unique(names): 284 | i = [s for s in range(len(names)) if names[s] == g] 285 | ax2.scatter(X_embedded[i, 0], X_embedded[i, 1], 286 | c=[aux[i[0]]], s=5, label=names[i[0]]) 287 | ax2.set_title('{} markers'.format(len(markers))) 288 | plt.legend(bbox_to_anchor=(1, 1)) 289 | plt.subplots_adjust(right=0.7) 290 | return fig 291 | 292 | 293 | def one_vs_all_selection(data, labels, num_bins=20): 294 | data_by_label = {} 295 | unique_labels = list(set(labels)) 296 | number_classes = len(unique_labels) 297 | [N, d] = data.shape 298 | for lab in unique_labels: 299 | X = [data[x, :] for x in range(len(labels)) if labels[x] == lab] 300 | data_by_label[lab] = X 301 | markers = [None for i in range(number_classes)] 302 | bins = data.max() / num_bins * range(num_bins + 1) 303 | for idx in range(number_classes): 304 | c = unique_labels[idx] 305 | current_class = np.array(data_by_label[c]) 306 | others = np.concatenate([data_by_label[lab] 307 | for lab in unique_labels if lab != c]) 308 | big_dist = 0 309 | for gene in range(d): 310 | if gene not in markers[0:idx]: 311 | [h1, b1] = np.histogram(current_class[:, gene], bins) 312 | h1 = np.array(h1).reshape(1, -1) / current_class.shape[0] 313 | [h2, b2] = np.histogram(others[:, gene], bins) 314 | h2 = np.array(h2).reshape(1, -1) / others.shape[0] 315 | dist = -sklearn.metrics.pairwise.additive_chi2_kernel(h1, h2) 316 | if dist > big_dist: 317 | markers[idx] = gene 318 | big_dist = dist 319 | return markers 320 | 321 | 322 | def optimize_epsilon(data_train, labels_train, data_test, labels_test, num_markers, method='centers', fixed_parameters={}, bounds=[(0.2 , 10)], x0=[1], max_fun_evaluations=20, n_experiments=5, clf=None, hierarchy=False, verbose=True): 323 | """ 324 | Finds the optimal value of epsilon using scipy.optimize.dual_annealing 325 | """ 326 | if clf==None: 327 | clf=sklearn.neighbors.NearestCentroid() 328 | Instance=__ScGeneInstance(data_train, labels_train, data_test, labels_test, clf, num_markers, method, fixed_parameters, n_experiments, hierarchy) 329 | print('Optimizing epsilon for', num_markers, 'markers and', method, 'method.') 330 | res = scipy.optimize.dual_annealing(Instance.error_epsilon, bounds=bounds, x0=x0, maxfun=max_fun_evaluations, no_local_search=True) 331 | return [res.x, 1-res.fun] 332 | 333 | class __ScGeneInstance: 334 | def __init__(self, X_train, y_train, X_test, y_test, clf, num_markers, method, fixed_parameters, n_experiments, hierarchy): 335 | self.X_train=X_train 336 | self.y_train=y_train 337 | self.X_test=X_test 338 | self.y_test=y_test 339 | self.clf=clf 340 | self.num_markers=num_markers 341 | self.method=method 342 | self.fixed_parameters=fixed_parameters 343 | self.n_experiments=n_experiments 344 | self.hierarchy=hierarchy 345 | def error_epsilon(self, epsilon): 346 | return 1-self.accuracy(epsilon) 347 | 348 | def accuracy(self, epsilon): 349 | #compute avg over n_experiments random samples for stability 350 | if self.hierarchy: 351 | markers=[get_markers_hierarchy(self.X_train, self.y_train, self.num_markers, self.method, epsilon=epsilon, verbose=False, **self.fixed_parameters) for i in range(self.n_experiments)] 352 | else: 353 | markers=[get_markers(self.X_train, self.y_train, self.num_markers, self.method, epsilon=epsilon, verbose=False, **self.fixed_parameters) for i in range(self.n_experiments)] 354 | val=[self.performance( markers[i] ) for i in range(self.n_experiments)] 355 | return np.mean(val) 356 | 357 | def performance(self, markers): 358 | if self.hierarchy: 359 | self.clf.fit(self.X_train[:,markers], self.y_train[0]) 360 | return self.clf.score(self.X_test[:,markers], self.y_test[0]) 361 | else: 362 | self.clf.fit(self.X_train[:,markers], self.y_train) 363 | return self.clf.score(self.X_test[:,markers], self.y_test) 364 | 365 | def load_example_data(name): 366 | if name=="CITEseq": 367 | a = scipy.io.loadmat(data_files.get_data("CITEseq.mat")) 368 | data= a['G'].T 369 | N,d=data.shape 370 | #transformation from integer entries 371 | data=np.log(data+np.ones(data.shape)) 372 | for i in range(N): 373 | data[i,:]=data[i,:]/np.linalg.norm(data[i,:]) 374 | #load labels from file 375 | a = scipy.io.loadmat(data_files.get_data("CITEseq-labels.mat")) 376 | l_aux = a['labels'] 377 | labels = np.array([i for [i] in l_aux]) 378 | #load names from file 379 | a = scipy.io.loadmat(data_files.get_data("CITEseq_names.mat")) 380 | names=[a['citeseq_names'][i][0][0] for i in range(N)] 381 | return [data, labels, names] 382 | elif name=="zeisel": 383 | #load data from file 384 | a = scipy.io.loadmat(data_files.get_data("zeisel_data.mat")) 385 | data= a['zeisel_data'].T 386 | N,d=data.shape 387 | 388 | #load labels (first level of the hierarchy) from file 389 | a = scipy.io.loadmat(data_files.get_data("zeisel_labels1.mat")) 390 | l_aux = a['zeisel_labels1'] 391 | l_0=[l_aux[i][0] for i in range(l_aux.shape[0])] 392 | #load labels (second level of the hierarchy) from file 393 | a = scipy.io.loadmat(data_files.get_data("zeisel_labels2.mat")) 394 | l_aux = a['zeisel_labels2'] 395 | l_1=[l_aux[i][0] for i in range(l_aux.shape[0])] 396 | #construct an array with hierarchy labels 397 | labels=np.array([l_0, l_1]) 398 | 399 | # load names from file 400 | a = scipy.io.loadmat(data_files.get_data("zeisel_names.mat")) 401 | names0=[a['zeisel_names'][i][0][0] for i in range(N)] 402 | names1=[a['zeisel_names'][i][1][0] for i in range(N)] 403 | return [data, labels, [names0,names1]] 404 | else: 405 | print("currently available options are only 'CITEseq' and 'zeisel'") 406 | 407 | 408 | 409 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name='scGeneFit', 8 | version='1.0.0', 9 | author="Soledad Villar", 10 | author_email="soledad.villar@nyu.edu", 11 | description="Genetic marker selection with linear programming", 12 | long_description=long_description, 13 | long_description_content_type="text/markdown", 14 | url="https://github.com/solevillar/scGeneFit-python", 15 | packages=setuptools.find_packages(), 16 | include_package_data=True, 17 | install_requires=['numpy', 'matplotlib', 'scipy', 'scikit-learn'], 18 | classifiers=[ 19 | "Programming Language :: Python :: 3", 20 | "License :: OSI Approved :: MIT License", 21 | "Operating System :: OS Independent", 22 | ], 23 | python_requires='>=3.6', 24 | ) 25 | --------------------------------------------------------------------------------