{"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":"markdown","source":"### Imports","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport os\nfrom PIL import Image\nimport numpy as np\nimport plotly.figure_factory as ff\nimport plotly.graph_objects as go\nimport plotly.subplots as sp\nimport matplotlib.pyplot as plt\nimport math\nfrom matplotlib import animation, rc\nimport cv2","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:30.131503Z","iopub.execute_input":"2025-03-16T16:24:30.131989Z","iopub.status.idle":"2025-03-16T16:24:35.742243Z","shell.execute_reply.started":"2025-03-16T16:24:30.131952Z","shell.execute_reply":"2025-03-16T16:24:35.740818Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Simple operations","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train_labels.csv')\nprint('Number of tomograms in train set = ', len(set(df['tomo_id'])))\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:35.744188Z","iopub.execute_input":"2025-03-16T16:24:35.744842Z","iopub.status.idle":"2025-03-16T16:24:35.916559Z","shell.execute_reply.started":"2025-03-16T16:24:35.744794Z","shell.execute_reply":"2025-03-16T16:24:35.915342Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:35.919147Z","iopub.execute_input":"2025-03-16T16:24:35.919556Z","iopub.status.idle":"2025-03-16T16:24:35.961581Z","shell.execute_reply.started":"2025-03-16T16:24:35.919525Z","shell.execute_reply":"2025-03-16T16:24:35.960300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Unique shapes of tomograms available in the train set\ndf[['Array shape (axis 0)',\t'Array shape (axis 1)',\t'Array shape (axis 2)']].drop_duplicates().reset_index(drop=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:35.963489Z","iopub.execute_input":"2025-03-16T16:24:35.963931Z","iopub.status.idle":"2025-03-16T16:24:35.983043Z","shell.execute_reply.started":"2025-03-16T16:24:35.963888Z","shell.execute_reply":"2025-03-16T16:24:35.981769Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Plotly histograms","metadata":{}},{"cell_type":"code","source":"def plot_numeric_histograms(df):\n    \n    numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()\n    num_plots = len(numeric_cols)\n    rows = math.ceil(num_plots / 2)\n    \n    fig = sp.make_subplots(rows=rows, cols=2, subplot_titles=numeric_cols)\n    \n    for i, col in enumerate(numeric_cols):\n        row = (i // 2) + 1\n        col_pos = (i % 2) + 1\n        fig.add_trace(go.Histogram(x=df[col], name=col, nbinsx=30), row=row, col=col_pos)\n    \n    fig.update_layout(title_text=\"Histograms of Numeric Columns\", height=rows * 300, showlegend=False)\n    fig.show(renderer='iframe')\n\nplot_numeric_histograms(df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:35.984297Z","iopub.execute_input":"2025-03-16T16:24:35.984737Z","iopub.status.idle":"2025-03-16T16:24:36.833769Z","shell.execute_reply.started":"2025-03-16T16:24:35.984699Z","shell.execute_reply":"2025-03-16T16:24:36.832644Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### All motors visualization","metadata":{}},{"cell_type":"code","source":"print('Total number of motors in train set = ',len(df[df['Motor axis 0']!=-1]))\nprint('Total number of tomograms which have motors = ', len(set(df[df['Motor axis 0']!=-1]['tomo_id'])))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:36.834786Z","iopub.execute_input":"2025-03-16T16:24:36.835172Z","iopub.status.idle":"2025-03-16T16:24:36.845471Z","shell.execute_reply.started":"2025-03-16T16:24:36.835137Z","shell.execute_reply":"2025-03-16T16:24:36.844367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_tomogram(directory_path, experiment_name, scaling='None'):\n    \n    path = os.path.join(directory_path, experiment_name)\n    file_list = os.listdir(path)\n    file_list = sorted(file_list, key=lambda x: x)\n    arrays = []\n    \n    for file in file_list:\n        arr = cv2.imread(os.path.join(path, file), cv2.IMREAD_GRAYSCALE)\n        arrays.append(arr)\n\n    tomogram = np.stack(arrays, axis=0)\n    scaling = str.lower(scaling)\n\n    if scaling == 'z':\n        tomogram = (tomogram-np.mean(tomogram))/(np.maximum(np.std(tomogram),1e-6))\n\n    elif scaling == 'max':\n        tomogram = ((tomogram-tomogram.min())/(tomogram.max()-tomogram.min()))\n\n    return tomogram\n    \ndef view_slice(tomogram, z):\n    \n    image = tomogram[z]\n    plt.imshow(image, cmap=\"gray\")\n    plt.show()\n\ndef view_slice_circle(tomogram, z, y, x, voxel_spacing, thickness=2, ax=None):\n    \n    x, y, z = int(x), int(y), int(z)\n    center = (x, y)\n    radius = int(1000 / voxel_spacing)\n\n    if all(v >= 0 for v in [x, y, z]):\n        image = tomogram[z].copy()\n        color = int(np.max(image))\n        cv2.rectangle(image, (x-radius,y-radius), (x+radius,y+radius), color, thickness)  \n        cv2.putText(image, f'z={z} y={y} x={x}', (15,50), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0), thickness, cv2.LINE_AA)\n        \n        if ax is None:\n            plt.figure(figsize=(5, 5))\n            plt.imshow(image, cmap=\"gray\")\n            plt.show()\n        else:\n            ax.imshow(image, cmap=\"gray\")\n    else:\n        print('There is no flagellum in this tomogram. Use \"view_slice\" if you want to see a specific slice of this tomogram.')\n\ndef plot_all_flagellum(tomogram, experiment, data):\n    \n    exp_data = data[data['tomo_id'] == experiment].copy()\n    num_images = len(exp_data)\n    cols = 3\n    rows = (num_images + cols - 1) // cols \n    fig, axes = plt.subplots(rows, cols, figsize=(cols * 5, rows * 5))\n    axes = np.array(axes).reshape(rows, cols) \n    \n    for idx, (i, row) in enumerate(exp_data.iterrows()):\n        z, y, x, spacing = row['Motor axis 0'], row['Motor axis 1'], row['Motor axis 2'], row['Voxel spacing']\n        ax = axes[idx // cols, idx % cols]\n        view_slice_circle(tomogram, z, y, x, spacing, thickness=2, ax=ax)\n        ax.set_title(f\"Flagellum {idx}\")\n\n    for idx in range(num_images, rows * cols):\n        fig.delaxes(axes[idx // cols, idx % cols])\n\n    plt.tight_layout()\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:36.846877Z","iopub.execute_input":"2025-03-16T16:24:36.847483Z","iopub.status.idle":"2025-03-16T16:24:36.876810Z","shell.execute_reply.started":"2025-03-16T16:24:36.847430Z","shell.execute_reply":"2025-03-16T16:24:36.875354Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"directory = '/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train'\n\nfor exp in sorted(set(df[df['Motor axis 0']!=-1]['tomo_id'])):\n    \n    tom = get_tomogram(directory, exp, scaling='None')\n    print('*'*80)\n    print(exp, tom.shape)\n    plot_all_flagellum(tom, exp, df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T16:24:52.596250Z","iopub.execute_input":"2025-03-16T16:24:52.596594Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}