{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91249,"databundleVersionId":11294684,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nbs_path = \"/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/\"\n\ndf_labels_train = pd.read_csv(bs_path + \"train_labels.csv\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:20:26.357887Z","iopub.execute_input":"2025-04-07T22:20:26.358340Z","iopub.status.idle":"2025-04-07T22:20:26.368034Z","shell.execute_reply.started":"2025-04-07T22:20:26.358308Z","shell.execute_reply":"2025-04-07T22:20:26.366787Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_labels_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:20:26.723385Z","iopub.execute_input":"2025-04-07T22:20:26.723742Z","iopub.status.idle":"2025-04-07T22:20:26.741948Z","shell.execute_reply.started":"2025-04-07T22:20:26.723713Z","shell.execute_reply":"2025-04-07T22:20:26.740430Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Binary Labels - Is there a flagellar motor in this tomography?\n\n- Considering motor presence\n\nsimply look for column 'Number of motors' or any of the labels in 'Motor axis 0~2'\n\nif number of motors is 0, motor axis 0~2 are always -1,-1,-1 respectively\n\ntherefore we can **extract** a binary label for motor presence","metadata":{}},{"cell_type":"code","source":"df_labels_train['y'] = df_labels_train['Motor axis 0'].apply(lambda x: 0 if x == -1 else 1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:20:27.813471Z","iopub.execute_input":"2025-04-07T22:20:27.813840Z","iopub.status.idle":"2025-04-07T22:20:27.819910Z","shell.execute_reply.started":"2025-04-07T22:20:27.813809Z","shell.execute_reply":"2025-04-07T22:20:27.818775Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"count_label_type = df_labels_train[['tomo_id','y']].rename(columns={'tomo_id':'count'}) \\\n        .groupby(['count','y']).count().reset_index().groupby('y').count().T","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:22:48.660817Z","iopub.execute_input":"2025-04-07T22:22:48.661320Z","iopub.status.idle":"2025-04-07T22:22:48.675412Z","shell.execute_reply.started":"2025-04-07T22:22:48.661275Z","shell.execute_reply":"2025-04-07T22:22:48.674166Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"display(count_label_type.head()) # sum of 0 and 1 counts is n of tomographies\n\nprint(\"size of tomography samples: \"+ str(len(df_labels_train.groupby('tomo_id').count())))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:24:18.118417Z","iopub.execute_input":"2025-04-07T22:24:18.118792Z","iopub.status.idle":"2025-04-07T22:24:18.132574Z","shell.execute_reply.started":"2025-04-07T22:24:18.118761Z","shell.execute_reply":"2025-04-07T22:24:18.131137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\nplt.style.use('_mpl-gallery-nogrid')\n\n\n# make data\nwedge_sizes = count_label_type.loc['count'].to_list()\nlbs = count_label_type.loc['count'].index.to_list()\n\n\ncolors = plt.get_cmap('Blues')(np.linspace(0.2, 0.7, len(wedge_sizes)))\n\n# plot\nfig, ax = plt.subplots()\nax.pie(wedge_sizes, colors=colors, radius=3, center=(4, 4),\n       labels= lbs,\n       wedgeprops={\"linewidth\": 1, \"edgecolor\": \"white\"}, frame=True)\n\nax.set(xlim=(0, 8), xticks=np.arange(1, 8),\n       ylim=(0, 8), yticks=np.arange(1, 8))\n\nplt.title(\"sample per motor presence\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:22:52.424813Z","iopub.execute_input":"2025-04-07T22:22:52.425260Z","iopub.status.idle":"2025-04-07T22:22:52.605631Z","shell.execute_reply.started":"2025-04-07T22:22:52.425226Z","shell.execute_reply":"2025-04-07T22:22:52.604317Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Multiclass Labels\n\n- considering Nº of motors\n\nsimple group by on column Number of motors","metadata":{}},{"cell_type":"code","source":"import numpy as np\n\ncol = \"Number of motors\"\n\ncount_label_type = (\n    df_labels_train[['tomo_id', col]]\n    .rename(columns={'tomo_id': 'count'})\n    .groupby(['count', col]).count()\n    .reset_index()\n    .groupby(col).count()\n    .T\n)\n\n# Apply log to the existing 'count' row\ncount_label_type.loc['log_count'] = np.log(count_label_type.loc['count'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:28:21.840840Z","iopub.execute_input":"2025-04-07T22:28:21.841284Z","iopub.status.idle":"2025-04-07T22:28:21.857072Z","shell.execute_reply.started":"2025-04-07T22:28:21.841255Z","shell.execute_reply":"2025-04-07T22:28:21.856053Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"count_label_type","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:28:22.580427Z","iopub.execute_input":"2025-04-07T22:28:22.580803Z","iopub.status.idle":"2025-04-07T22:28:22.594503Z","shell.execute_reply.started":"2025-04-07T22:28:22.580771Z","shell.execute_reply":"2025-04-07T22:28:22.593074Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\nplt.style.use('_mpl-gallery-nogrid')\n\n\n# make data\nwedge_sizes = count_label_type.loc['count'].to_list()\nlbs = count_label_type.loc['count'].index.to_list()\n\n\ncolors = plt.get_cmap('Reds')(np.linspace(0.2, 0.7, len(wedge_sizes)))\n\n# plot\nfig, ax = plt.subplots()\nax.pie(wedge_sizes, colors=colors, radius=3, center=(4, 4),\n       labels= lbs,\n       wedgeprops={\"linewidth\": 1, \"edgecolor\": \"white\"}, frame=True)\n\nax.set(xlim=(0, 8), xticks=np.arange(1, 8),\n       ylim=(0, 8), yticks=np.arange(1, 8))\n\nplt.title(\"samples per number of motors\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:25:24.124400Z","iopub.execute_input":"2025-04-07T22:25:24.124763Z","iopub.status.idle":"2025-04-07T22:25:24.349772Z","shell.execute_reply.started":"2025-04-07T22:25:24.124728Z","shell.execute_reply":"2025-04-07T22:25:24.348635Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\nplt.style.use('_mpl-gallery-nogrid')\n\n\n# make data\nlog_wedge_sizes = count_label_type.loc['log_count'].to_list()\nlbs = count_label_type.loc['count'].index.to_list()\n\n\ncolors = plt.get_cmap('Reds')(np.linspace(0.2, 0.7, len(log_wedge_sizes)))\n\n# plot\nfig, ax = plt.subplots()\nax.pie(log_wedge_sizes, colors=colors, radius=3, center=(4, 4),\n       labels= lbs,\n       wedgeprops={\"linewidth\": 1, \"edgecolor\": \"white\"}, frame=True)\n\nax.set(xlim=(0, 8), xticks=np.arange(1, 8),\n       ylim=(0, 8), yticks=np.arange(1, 8))\n\nplt.title(\"samples per number of motors log\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:29:08.565593Z","iopub.execute_input":"2025-04-07T22:29:08.566032Z","iopub.status.idle":"2025-04-07T22:29:08.769229Z","shell.execute_reply.started":"2025-04-07T22:29:08.565997Z","shell.execute_reply":"2025-04-07T22:29:08.768069Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Multiclass x Multidimensional\n\n- Array shape defines size of multidimensional cube\n\nA tomography is defined by a group of images that compose a three-dimensional view of our real counterpart object.\n\nAn image is composed of pixels, in X and Y (width and height)\n\nWhen we add this new dimension of images to the group, we can call this dimension Z (depth).\n\nMultiplying X and Y, we get total area of an image, in pixels² (squared)\n\nMultiplying X, Y and Z, we get total volume of the tomography, in pixels³ (cube)","metadata":{}},{"cell_type":"code","source":"df_labels_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:07:34.617286Z","iopub.execute_input":"2025-04-07T22:07:34.617745Z","iopub.status.idle":"2025-04-07T22:07:34.633142Z","shell.execute_reply.started":"2025-04-07T22:07:34.617696Z","shell.execute_reply":"2025-04-07T22:07:34.631945Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_tomo = (\n    df_labels_train[['tomo_id', 'Number of motors', 'Array shape (axis 0)',\n                     'Array shape (axis 1)', 'Array shape (axis 2)','Voxel spacing']]\n    .rename(columns={\n        \"Array shape (axis 0)\": \"z_max\",\n        \"Array shape (axis 1)\": \"y_max\",\n        \"Array shape (axis 2)\": \"x_max\",\n        \"Voxel spacing\":\"voxel_spacing\"\n    })\n    .groupby(['tomo_id', 'z_max', 'y_max', 'x_max', 'voxel_spacing'])\n    .count()\n    .reset_index()\n    .set_index('tomo_id')\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:07:34.634471Z","iopub.execute_input":"2025-04-07T22:07:34.634861Z","iopub.status.idle":"2025-04-07T22:07:34.660366Z","shell.execute_reply.started":"2025-04-07T22:07:34.634832Z","shell.execute_reply":"2025-04-07T22:07:34.659054Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_tomo.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:07:34.662354Z","iopub.execute_input":"2025-04-07T22:07:34.662713Z","iopub.status.idle":"2025-04-07T22:07:34.684054Z","shell.execute_reply.started":"2025-04-07T22:07:34.662664Z","shell.execute_reply":"2025-04-07T22:07:34.682855Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_tomo['cube_size'] = df_tomo.apply(lambda x: x['z_max'] * x['y_max'] * x['x_max'], axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:07:34.685258Z","iopub.execute_input":"2025-04-07T22:07:34.685558Z","iopub.status.idle":"2025-04-07T22:07:34.709941Z","shell.execute_reply.started":"2025-04-07T22:07:34.685523Z","shell.execute_reply":"2025-04-07T22:07:34.708847Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_tomo.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:07:34.710979Z","iopub.execute_input":"2025-04-07T22:07:34.711304Z","iopub.status.idle":"2025-04-07T22:07:34.737381Z","shell.execute_reply.started":"2025-04-07T22:07:34.711274Z","shell.execute_reply":"2025-04-07T22:07:34.736234Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Bacterial Flagellar Motor Size\n\nAbout 45 nm\n\nThe bacterial flagellar motor is a reversible rotary nano-machine that is powered by the flux of H+ or Na+ ions across the cytoplasmic membrane [1](https://www.sciencedirect.com/science/article/abs/pii/S0966842X14002686) [3](https://pubmed.ncbi.nlm.nih.gov/18812014/). It is about 45 nm in diameter and is embedded in the bacterial cell envelope [3](https://pubmed.ncbi.nlm.nih.gov/18812014/). The motor is responsible for bacterial motility and can rotate at high speeds [1](https://www.sciencedirect.com/science/article/abs/pii/S0966842X14002686) [4](https://pmc.ncbi.nlm.nih.gov/articles/PMC5115386/).\n\nconsidering nanometer == voxel space, then we can estimate the total size of our motors in the three dimensional tomography cube. However, that may not be precise, and that's why I'm struggling to accurately represent the size of labels in this step","metadata":{}},{"cell_type":"code","source":"def sum_flagellar_motor_size(number_of_motors):\n    mean_flagellar_motor_size = 45 # 45 nm == 45 voxel spaces\n    # 45 nanometers in diameter\n    # in 3 dimensions: 45 * 45 * 45\n    dim_ = mean_flagellar_motor_size ** 3\n    return dim_ * number_of_motors\n\ndf_tomo['cube_voxels'] = df_tomo.apply \\\n            (lambda x: (x['voxel_spacing']** 3) * x['cube_size'], axis=1)\n\ndf_tomo['flagellar_motors_sum_size'] = \\\n    df_tomo.apply(lambda x: sum_flagellar_motor_size(x['Number of motors']), axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:07:51.304051Z","iopub.execute_input":"2025-04-07T22:07:51.304393Z","iopub.status.idle":"2025-04-07T22:07:51.324095Z","shell.execute_reply.started":"2025-04-07T22:07:51.304364Z","shell.execute_reply":"2025-04-07T22:07:51.322777Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_tomo.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:07:52.621485Z","iopub.execute_input":"2025-04-07T22:07:52.621905Z","iopub.status.idle":"2025-04-07T22:07:52.637606Z","shell.execute_reply.started":"2025-04-07T22:07:52.621864Z","shell.execute_reply":"2025-04-07T22:07:52.636164Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Total cube size X flagellar motor sizes","metadata":{}},{"cell_type":"code","source":"df = df_tomo[['cube_voxels','flagellar_motors_sum_size']] \\\n    .rename(columns={'flagellar_motors_sum_size':'motors³'}) \\\n    .sum()\n\nx = df.to_list()\ny = df.index.to_list()\n\npe_ = x[1] * 100 / x[0]\n\ny2 = []\n\nfor l in y:\n    if l == 'motors³':\n        l = 'motors³_'+str(float(np.round(pe_,6)))\n    y2.append(l)\nprint(x,y2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:08:36.989888Z","iopub.execute_input":"2025-04-07T22:08:36.990305Z","iopub.status.idle":"2025-04-07T22:08:37.000798Z","shell.execute_reply.started":"2025-04-07T22:08:36.990272Z","shell.execute_reply":"2025-04-07T22:08:36.999281Z"},"_kg_hide-input":true,"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\nplt.style.use('_mpl-gallery-nogrid')\n\n\n# make data\nwedge_sizes = x\nlbs = y2\n\ncolors = plt.get_cmap('Greys')(np.linspace(0.2, 0.7, len(wedge_sizes)))\n\n# plot\nfig, ax = plt.subplots()\nax.pie(wedge_sizes, colors=colors, radius=3, center=(4, 4),\n       labels= lbs,\n       wedgeprops={\"linewidth\": 1, \"edgecolor\": \"white\"}, frame=True)\n\nax.set(xlim=(0, 8), xticks=np.arange(1, 8),\n       ylim=(0, 8), yticks=np.arange(1, 8))\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T22:08:39.321507Z","iopub.execute_input":"2025-04-07T22:08:39.321873Z","iopub.status.idle":"2025-04-07T22:08:39.487007Z","shell.execute_reply.started":"2025-04-07T22:08:39.321841Z","shell.execute_reply":"2025-04-07T22:08:39.485762Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# motors are 0.00000008 of our total cube volume³, in **VOXELS**","metadata":{}},{"cell_type":"markdown","source":"## ","metadata":{}}]}