aboutsummaryrefslogtreecommitdiff
path: root/notebooks/SVM.ipynb
diff options
context:
space:
mode:
authorChristian C <cc@localhost>2024-11-11 12:29:32 -0800
committerChristian C <cc@localhost>2024-11-11 12:29:32 -0800
commitb85ee9d64a536937912544c7bbd5b98b635b7e8d (patch)
treecef7bc17d7b29f40fc6b1867d0ce0a742d5583d0 /notebooks/SVM.ipynb
Initial commit
Diffstat (limited to 'notebooks/SVM.ipynb')
-rw-r--r--notebooks/SVM.ipynb560
1 files changed, 560 insertions, 0 deletions
diff --git a/notebooks/SVM.ipynb b/notebooks/SVM.ipynb
new file mode 100644
index 0000000..e1255b5
--- /dev/null
+++ b/notebooks/SVM.ipynb
@@ -0,0 +1,560 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "2a386f10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sunlab.globals import FILES"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "6eab6d52-54ac-44ed-9bda-7117cba37c87",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "os.environ['TF_CPP_MIN_LOG_LEVEL'] = \"3\"\n",
+ "os.environ['CUDA_VISIBLE_DEVICES'] = \"-1\"\n",
+ "\n",
+ "# import tensorflow as tf\n",
+ "# tf.autograph.set_verbosity(0, False)\n",
+ "# from matplotlib import pyplot as plt\n",
+ "\n",
+ "import joblib\n",
+ "try:\n",
+ " import sklearn.externals.joblib as extjoblib\n",
+ "except:\n",
+ " pass"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "4ff998f7-2bd5-41d6-a397-b74f7238d225",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def load_model(model_pkl_path, scaler_pkl_path):\n",
+ " clf = joblib.load(model_pkl_path)\n",
+ " scaler = joblib.load(scaler_pkl_path)\n",
+ " return clf, scaler"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "ce9834f6-1787-409d-85c5-fea51e130368",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def load_test_data(data, d=1, pixel2dist = 1.075268):\n",
+ " from transform_data import Add_Measures, Exclude_Measures\n",
+ " \"\"\"\n",
+ " Encapsulates SVM_csv.py\n",
+ "\n",
+ " Inputs:\n",
+ " data_path: path to CSV data you wish to be evaluated\n",
+ " write_txt: write text file with probabilities etc.\n",
+ " d: dimensionality to which increase features. If d=2, quadratic, cross features are included.\n",
+ "\n",
+ " Outputs:\n",
+ " Nothing, as of yet.\n",
+ " \"\"\"\n",
+ "# data = dataset.dataframe[dataset.data_columns].to_numpy()\n",
+ "# pixel2dist = 1.075268\n",
+ " #pixel2dist=0.53763672 #microns/pixel using 20x oil objective lens on confocal\n",
+ " #pixel2dist=0.656265 #using 20x oil lens, microns/pixel on dark room microscope\n",
+ " #pixel2dist=1.075268 #using 10x air objective on the confocal\n",
+ "\n",
+ " print('Data is being converted to correct micrometers, assuming measured in pixels')\n",
+ " #scale columns by following\n",
+ " data[:,0] =data[:,0]*pixel2dist*pixel2dist#area\n",
+ " data[:,1] = data[:,1]*pixel2dist#majoraxislength\n",
+ " data[:,2] = data[:,2]*pixel2dist#minoraxislength\n",
+ " #3 is eccentricity, unitless\n",
+ " data[:,4] =data[:,4]*pixel2dist*pixel2dist#4 convex area,\n",
+ " data[:,5] = data[:,5]*pixel2dist#5 Equiv diam\n",
+ " #6 solidity, unitless\n",
+ " #7 extent, unitless\n",
+ " data[:,8] = data[:,8]*pixel2dist#8 Perimeter\n",
+ " data[:,9] = data[:,9]*pixel2dist#9 Convex Perimeter\n",
+ " data[:,10] = data[:,10]*pixel2dist#10 Fiber Length\n",
+ " data[:,11] = data[:,11]*pixel2dist#11 Max Inscribed Radius\n",
+ " data[:,12] = data[:,12]*pixel2dist#12 Bleb_length\n",
+ "\n",
+ "\n",
+ " #add form factor as last column of data?\n",
+ " #Form factor is added inside the Processing data when doing SVM. See \"Transform_data.py\"\n",
+ "\n",
+ " #if len(Measure_Delete)>0:\n",
+ " #\tdata = np.delete(data, Measure_Delete, axis = 1) #delete time column and cellnumber column, since we already have them.\n",
+ "\n",
+ " #so now data should look just like other data used in SVM\n",
+ "\n",
+ " #add aspect ratio as last column of data\n",
+ " X_data = Add_Measures(data, add_AR=True, add_FF=True, add_convexity=True,\n",
+ " add_curl_old=True, add_curl=True, add_sphericity=True,\n",
+ " add_InscribedArea=True, add_BlebRel=True)\n",
+ " #if you wish to exclude certain measures:\n",
+ " #Area,MjrAxis,MnrAxis,Ecc,ConA,EqD,Sol,Ext,Per,conPer,FL,InR,bleb_M\n",
+ " X_data = Exclude_Measures(X_data, ex_Area=False,\n",
+ " ex_MjrAxis=False, ex_MnrAxis=False, ex_Ecc=False,\n",
+ " ex_ConA=False, ex_EqD=False, ex_Sol=False, ex_Ext=False,\n",
+ " ex_Per=False,ex_conPer=False,ex_FL=False,ex_InR=False,\n",
+ " ex_bleb=False)\n",
+ "\n",
+ " ####IF THE DATA WAS POLYNOMIAL BEFORE SCALED, DO THAT NOW!\n",
+ " #frameinfo = getframeinfo(currentframe())\n",
+ " #print(\"IF YOUR SCALER IS A POLYNOMIAL, YOU NEED TO EDIT THE POLYNOMIAL FEATURES, LINE %d CODE\" % (frameinfo.lineno + 2))\n",
+ " #d = 1\n",
+ " if d==2:\n",
+ " print(\"Expanding feature set to include quadratic, cross terms.\")\n",
+ " poly=preprocessing.PolynomialFeatures(degree = d, interaction_only = True)\n",
+ " X_data_exp = poly.fit_transform(X_data)\n",
+ "\n",
+ " #FIRST, SCALE THE DATA USING THE SCALER\n",
+ " X_data_scaled = scaler.transform(X_data_exp)\n",
+ " else:\n",
+ " X_data_scaled = scaler.transform(X_data)\n",
+ "\n",
+ " #GATHER PROBABILITIES\n",
+ " Probs = clf.predict_proba(X_data_scaled)\n",
+ "\n",
+ " #Gather Predictions\n",
+ " Predictions = clf.predict(X_data_scaled)\n",
+ "\n",
+ " Descriptors = ['frame', 'cellnumber','x-cent','y-cent','actinedge','filopodia','bleb','lamellipodia']\n",
+ " return Probs"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "ee0a154e-4a09-44a9-b32a-2793f513d632",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:35: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " eps=np.finfo(np.float).eps,\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:597: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " eps=np.finfo(np.float).eps, copy_X=True, fit_path=True,\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:836: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " eps=np.finfo(np.float).eps, copy_X=True, fit_path=True,\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:862: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " eps=np.finfo(np.float).eps, positive=False):\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1097: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps,\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1344: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps,\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/least_angle.py:1480: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " eps=np.finfo(np.float).eps, copy_X=True, positive=False):\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/randomized_l1.py:152: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " precompute=False, eps=np.finfo(np.float).eps,\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/randomized_l1.py:320: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " eps=np.finfo(np.float).eps, random_state=None,\n",
+ "/home/physics/cunnichr/.micromamba/envs/svm/lib/python3.7/site-packages/sklearn/linear_model/randomized_l1.py:580: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
+ "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+ " eps=4 * np.finfo(np.float).eps, n_jobs=None,\n"
+ ]
+ }
+ ],
+ "source": [
+ "model_pkl_path = FILES[\"SVM\"][\"MODEL\"]\n",
+ "scaler_pkl_path = FILES[\"SVM\"][\"SCALER\"]\n",
+ "clf, scaler = load_model(model_pkl_path, scaler_pkl_path)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f54208e2",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b84f9486",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "f6287849",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sunlab.common.data import *\n",
+ "from numpy import savetxt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "id": "a44df4f5",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Data is being converted to correct micrometers, assuming measured in pixels\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/physics/cunnichr/NewKeras/sunlab/code/sunlab/common/data/dataset.py:72: RuntimeWarning: No classification labels found for the dataset\n",
+ " RuntimeWarning)\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "p2d = 1.075268/4\n",
+ "fname = FILES[\"HISTOLOGIES\"][\"J1\"]\n",
+ "data = import_dataset(fname, 40, scaler=None)\n",
+ "# Ignore dirty masks from brush effects in masking process\n",
+ "df = data.dataframe[data.dataframe['Area']>350]\n",
+ "ds = df[data.data_columns].to_numpy()\n",
+ "out_data = load_test_data(ds, pixel2dist=p2d)\n",
+ "columns = [\"frame\", \"cellnumber\", \"x-cent\", \"y-cent\", \"actinedge\", \"filopodia\", \"bleb\", \"lamellipodia\"]\n",
+ "out = np.hstack([df[['Frames','CellNum','CenterX','CenterY']].to_numpy(), out_data])\n",
+ "savetxt(fname[:-3] + \"txt\", out, comments=\"\", header=\" \".join(columns))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 52,
+ "id": "f3df960c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/physics/cunnichr/NewKeras/sunlab/code/sunlab/common/data/dataset.py:72: RuntimeWarning: No classification labels found for the dataset\n",
+ " RuntimeWarning)\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Data is being converted to correct micrometers, assuming measured in pixels\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "p2d = 1.075268/4\n",
+ "fname = FILES[\"HISTOLOGIES\"][\"H9\"]\n",
+ "data = import_dataset(fname, 40, scaler=None)\n",
+ "df = data.dataframe\n",
+ "ds = df[data.data_columns].to_numpy()\n",
+ "out_data = load_test_data(ds, pixel2dist=p2d)\n",
+ "columns = [\"frame\", \"cellnumber\", \"x-cent\", \"y-cent\", \"actinedge\", \"filopodia\", \"bleb\", \"lamellipodia\"]\n",
+ "out = np.hstack([df[['Frames','CellNum','CenterX','CenterY']].to_numpy(), out_data])\n",
+ "savetxt(fname[:-3] + \"txt\", out, comments=\"\", header=\" \".join(columns))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "9adcb164",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Data is being converted to correct micrometers, assuming measured in pixels\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/physics/cunnichr/NewKeras/sunlab/code/sunlab/common/data/dataset.py:72: RuntimeWarning: No classification labels found for the dataset\n",
+ " RuntimeWarning)\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "p2d = 1.075268/4\n",
+ "fname = FILES[\"HISTOLOGIES\"][\"H4\"]\n",
+ "data = import_dataset(fname, 40, scaler=None)\n",
+ "df = data.dataframe\n",
+ "ds = df[data.data_columns].to_numpy()\n",
+ "out_data = load_test_data(ds, pixel2dist=p2d)\n",
+ "columns = [\"frame\", \"cellnumber\", \"x-cent\", \"y-cent\", \"actinedge\", \"filopodia\", \"bleb\", \"lamellipodia\"]\n",
+ "out = np.hstack([df[['Frames','CellNum','CenterX','CenterY']].to_numpy(), out_data])\n",
+ "savetxt(fname[:-3] + \"txt\", out, comments=\"\", header=\" \".join(columns))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "id": "546563f6",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Data is being converted to correct micrometers, assuming measured in pixels\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/physics/cunnichr/NewKeras/sunlab/code/sunlab/common/data/dataset.py:72: RuntimeWarning: No classification labels found for the dataset\n",
+ " RuntimeWarning)\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "p2d = 1.075268/4\n",
+ "fname = FILES[\"HISTOLOGIES\"][\"image001\"]\n",
+ "data = import_dataset(fname, 40, scaler=None)\n",
+ "df = data.dataframe\n",
+ "# Ignore bad mask\n",
+ "df = df[df['Perimeter'] < 8500]\n",
+ "ds = df[data.data_columns].to_numpy()\n",
+ "out_data = load_test_data(ds, pixel2dist=p2d)\n",
+ "columns = [\"frame\", \"cellnumber\", \"x-cent\", \"y-cent\", \"actinedge\", \"filopodia\", \"bleb\", \"lamellipodia\"]\n",
+ "out = np.hstack([df[['Frames','CellNum','CenterX','CenterY']].to_numpy(), out_data])\n",
+ "savetxt(fname[:-3] + \"txt\", out, comments=\"\", header=\" \".join(columns))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "602386e0",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "46571673",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1df5e089",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "104272f1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "SAVE_OUT = False"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "321d7062-e2e0-4fed-bf48-ea8f96901be4",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Data is being converted to correct micrometers, assuming measured in pixels\n"
+ ]
+ }
+ ],
+ "source": [
+ "from numpy import loadtxt, savetxt\n",
+ "data = loadtxt(FILES[\"PHENOTYPE_GRID\"][\"IN\"])\n",
+ "classes = load_test_data(data)\n",
+ "if SAVE_OUT:\n",
+ " savetxt(FILES[\"PHENOTYPE_GRID\"][\"OUT\"], classes)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "b0669eb5",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(250000,)"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from numpy import argmax\n",
+ "im_classes = argmax(classes, axis=-1)\n",
+ "im_classes.shape"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "cb4b0a78",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<matplotlib.image.AxesImage at 0x2aabb1036d10>"
+ ]
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 640x480 with 1 Axes>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "from matplotlib import pyplot as plt\n",
+ "from sunlab.common.plotting.colors import Pmap\n",
+ "plt.imshow(im_classes.reshape((500,500)).T, cmap=Pmap, origin='lower')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "394f4fdc",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{\n",
+ " \"TRAINING_DATASET\": \"../../data/spheroid26_011523_filtered.csv\",\n",
+ " \"TRAINING_DATASET_WIDE_BERTH\": \"../../data/spheroid26_011523_exc.csv\",\n",
+ " \"PRETRAINED_MODEL_DIR\": \"../../models/current_model/\",\n",
+ " \"PEN_TRACKED\": {\n",
+ " \"AUTO\": \"../../data/PEN_automatically_tracked.csv\",\n",
+ " \"MANUAL\": \"../../data/PEN_manually_tracked.csv\"\n",
+ " },\n",
+ " \"RHO\": {\n",
+ " \"3\": \"../../data/Rho_act_Cell3.csv\",\n",
+ " \"4\": \"../../data/Rho_act_Cell4.csv\",\n",
+ " \"6\": \"../../data/Rho_act_Cell6.csv\",\n",
+ " \"7\": \"../../data/Rho_act_Cell7.csv\",\n",
+ " \"8\": \"../../data/Rho_act_Cell8.csv\",\n",
+ " \"9\": \"../../data/Rho_act_Cell9.csv\",\n",
+ " \"10\": \"../../data/Rho_act_Cell10.csv\",\n",
+ " \"11\": \"../../data/Rho_act_Cell11.csv\"\n",
+ " },\n",
+ " \"SPHEROID\": {\n",
+ " \"1p5mgml\": \"../../data/spheroid26_011523_filtered.csv\",\n",
+ " \"3mgml\": \"../../data/spheroid20_011923_filtered.csv\",\n",
+ " \"4mgml\": \"../../data/spheroid22_012323_filtered.csv\",\n",
+ " \"6mgml\": \"../../data/spheroid26_012423_filtered.csv\"\n",
+ " },\n",
+ " \"FIGURES\": {\n",
+ " \"2\": {\n",
+ " \"PHENOTYPES_SMOOTHED\": \"../../extra_data/PhenotypeGaussianSmoothed.npy\"\n",
+ " },\n",
+ " \"3\": {\n",
+ " \"SAMPLED_DATASET\": \"../../extra_data/Figure3.SampledDataset.npy\",\n",
+ " \"PAIRWISE_DISTANCES\": \"../../extra_data/Figure3.PairwiseDistances.npy\",\n",
+ " \"PAIRWISE_DOT_PRODUCTS\": \"../../extra_data/Figure3.PairwiseDotProducts.npy\",\n",
+ " \"TRAJECTORIES\": \"../../extra_data/Figure3.Trajectories.npy\"\n",
+ " }\n",
+ " },\n",
+ " \"PHENOTYPE_GRID\": {\n",
+ " \"IN\": \"../../extra_data/PhenotypeGrid.npy\",\n",
+ " \"OUT\": \"../../extra_data/PhenotypeGrid_out.npy\"\n",
+ " },\n",
+ " \"PHENOTYPE_RGB\": \"../../extra_data/PhenotypeColors.npy\",\n",
+ " \"SVM\": {\n",
+ " \"MODEL\": \"../../other/svm/SVC_rbf_010820_16942_new.pkl\",\n",
+ " \"SCALER\": \"../../other/svm/SVC_rbf_scaler_010820_16942_new.pkl\"\n",
+ " },\n",
+ " \"NONPHYSICAL_MASK\": \"../../extra_data/NonPhysicalMask.npy\"\n",
+ "}\n"
+ ]
+ }
+ ],
+ "source": [
+ "from json import dumps\n",
+ "print(dumps(FILES,indent=4))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31cf538e",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "svm",
+ "language": "python",
+ "name": "svm"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}