{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\n\nSEED = 42\nnp.random.seed(SEED)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.060069Z","iopub.execute_input":"2025-06-09T15:27:49.060375Z","iopub.status.idle":"2025-06-09T15:27:49.071028Z","shell.execute_reply.started":"2025-06-09T15:27:49.060352Z","shell.execute_reply":"2025-06-09T15:27:49.069889Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"byu_train_path = '/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train'\n\nworking_yolo_path = '/kaggle/working/BYU_YOLO_dataset'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.072504Z","iopub.execute_input":"2025-06-09T15:27:49.072942Z","iopub.status.idle":"2025-06-09T15:27:49.094855Z","shell.execute_reply.started":"2025-06-09T15:27:49.072915Z","shell.execute_reply":"2025-06-09T15:27:49.093895Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nworking_images_train_path = os.path.join(working_yolo_path, 'images', 'train')\nworking_images_test_path = os.path.join(working_yolo_path, 'images', 'val')\nworking_labels_train_path = os.path.join(working_yolo_path, 'labels', 'train')\nworking_labels_test_path = os.path.join(working_yolo_path, 'labels', 'val')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.095740Z","iopub.execute_input":"2025-06-09T15:27:49.096015Z","iopub.status.idle":"2025-06-09T15:27:49.117075Z","shell.execute_reply.started":"2025-06-09T15:27:49.095993Z","shell.execute_reply":"2025-06-09T15:27:49.115957Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for path in [working_images_train_path, \n             working_images_test_path, \n             working_labels_train_path, \n             working_labels_test_path]:\n    \n    os.makedirs(path, exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.118942Z","iopub.execute_input":"2025-06-09T15:27:49.119221Z","iopub.status.idle":"2025-06-09T15:27:49.137537Z","shell.execute_reply.started":"2025-06-09T15:27:49.119198Z","shell.execute_reply":"2025-06-09T15:27:49.136397Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def normalize_slice(slice_data):\n    \n    percentile_2th = np.percentile(slice_data, 2)\n    percentile_98th = np.percentile(slice_data, 98)\n    \n    clipped_data = np.clip(slice_data, percentile_2th, percentile_98th)\n    \n    normalized = 255 * (clipped_data - percentile_2th) / (percentile_98th - percentile_2th)\n    \n    return np.uint8(normalized)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.138432Z","iopub.execute_input":"2025-06-09T15:27:49.138719Z","iopub.status.idle":"2025-06-09T15:27:49.158543Z","shell.execute_reply.started":"2025-06-09T15:27:49.138696Z","shell.execute_reply":"2025-06-09T15:27:49.157367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\ntrain_labels_df = pd.read_csv('/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train_labels.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.159732Z","iopub.execute_input":"2025-06-09T15:27:49.160009Z","iopub.status.idle":"2025-06-09T15:27:49.589119Z","shell.execute_reply.started":"2025-06-09T15:27:49.159987Z","shell.execute_reply":"2025-06-09T15:27:49.588073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.589964Z","iopub.execute_input":"2025-06-09T15:27:49.590203Z","iopub.status.idle":"2025-06-09T15:27:49.629339Z","shell.execute_reply.started":"2025-06-09T15:27:49.590184Z","shell.execute_reply":"2025-06-09T15:27:49.628293Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels_df['Number of motors'].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.630329Z","iopub.execute_input":"2025-06-09T15:27:49.630564Z","iopub.status.idle":"2025-06-09T15:27:49.644060Z","shell.execute_reply.started":"2025-06-09T15:27:49.630543Z","shell.execute_reply":"2025-06-09T15:27:49.643272Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(train_labels_df.tomo_id.unique())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.644819Z","iopub.execute_input":"2025-06-09T15:27:49.645050Z","iopub.status.idle":"2025-06-09T15:27:49.667084Z","shell.execute_reply.started":"2025-06-09T15:27:49.645033Z","shell.execute_reply":"2025-06-09T15:27:49.666210Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels_df.tomo_id.value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.669718Z","iopub.execute_input":"2025-06-09T15:27:49.670035Z","iopub.status.idle":"2025-06-09T15:27:49.688997Z","shell.execute_reply.started":"2025-06-09T15:27:49.669971Z","shell.execute_reply":"2025-06-09T15:27:49.687998Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels_df[train_labels_df['Number of motors'] > 0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.690082Z","iopub.execute_input":"2025-06-09T15:27:49.690407Z","iopub.status.idle":"2025-06-09T15:27:49.719203Z","shell.execute_reply.started":"2025-06-09T15:27:49.690379Z","shell.execute_reply":"2025-06-09T15:27:49.718330Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels_df[train_labels_df.tomo_id == 'tomo_00e047']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.720329Z","iopub.execute_input":"2025-06-09T15:27:49.720570Z","iopub.status.idle":"2025-06-09T15:27:49.748132Z","shell.execute_reply.started":"2025-06-09T15:27:49.720550Z","shell.execute_reply":"2025-06-09T15:27:49.747172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels_df[train_labels_df.tomo_id == 'tomo_00e463']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.748846Z","iopub.execute_input":"2025-06-09T15:27:49.749199Z","iopub.status.idle":"2025-06-09T15:27:49.777205Z","shell.execute_reply.started":"2025-06-09T15:27:49.749171Z","shell.execute_reply":"2025-06-09T15:27:49.776153Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for _, row in train_labels_df[train_labels_df.tomo_id == 'tomo_00e463'].iterrows():\n    print(row)\n    print(50 * '-')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.778104Z","iopub.execute_input":"2025-06-09T15:27:49.778345Z","iopub.status.idle":"2025-06-09T15:27:49.802547Z","shell.execute_reply.started":"2025-06-09T15:27:49.778325Z","shell.execute_reply":"2025-06-09T15:27:49.801630Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tomo_id_unique_motors_exist = train_labels_df[train_labels_df['Number of motors'] > 0].tomo_id.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.803682Z","iopub.execute_input":"2025-06-09T15:27:49.804180Z","iopub.status.idle":"2025-06-09T15:27:49.825351Z","shell.execute_reply.started":"2025-06-09T15:27:49.804150Z","shell.execute_reply":"2025-06-09T15:27:49.823946Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_split_len = len(tomo_id_unique_motors_exist) * 4 // 5\ntrain_split_len","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.826249Z","iopub.execute_input":"2025-06-09T15:27:49.826512Z","iopub.status.idle":"2025-06-09T15:27:49.847095Z","shell.execute_reply.started":"2025-06-09T15:27:49.826490Z","shell.execute_reply":"2025-06-09T15:27:49.846099Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np.random.shuffle(tomo_id_unique_motors_exist)\n\ntrain_tomo_ids = tomo_id_unique_motors_exist[:train_split_len]\ntest_tomo_ids = tomo_id_unique_motors_exist[train_split_len:]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.848278Z","iopub.execute_input":"2025-06-09T15:27:49.848547Z","iopub.status.idle":"2025-06-09T15:27:49.868470Z","shell.execute_reply.started":"2025-06-09T15:27:49.848525Z","shell.execute_reply":"2025-06-09T15:27:49.867518Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tqdm.notebook import tqdm\nfrom PIL import Image\n\nTRUST = 4\nBOX_SIZE = 24\n\ndef process_tomogram_set(train_test_tomo_ids, train_test_images_path, train_test_labels_path):\n    \n    motor_axis_data = []\n    \n    for train_test_tomo_id in train_test_tomo_ids:\n        train_test_tomo_id_df = train_labels_df[train_labels_df.tomo_id == train_test_tomo_id]\n        \n        for _, row in train_test_tomo_id_df.iterrows():\n            \n            if pd.isna(row['Motor axis 0']):\n                continue\n            motor_axis_data.append(\n                (train_test_tomo_id, \n                 int(row['Motor axis 0']), \n                 int(row['Motor axis 1']), \n                 int(row['Motor axis 2']),\n                 int(row['Array shape (axis 0)']))\n            )\n    \n    for tomo_id, motor_axis_0, motor_axis_1, motor_axis_2, array_shape_axis_0 in tqdm(motor_axis_data):\n        \n        motor_axis_0_min = max(0, motor_axis_0 - TRUST)\n        array_shape_axis_0 = min(array_shape_axis_0 - 1, motor_axis_0 + TRUST)\n        \n        for axis_0 in range(motor_axis_0_min, array_shape_axis_0 + 1):\n            \n            slice_filename = f'slice_{axis_0:04d}.jpg'\n            \n            current_path = os.path.join(byu_train_path, tomo_id, slice_filename)\n            \n            if not os.path.exists(current_path):\n                print(f\"Warning: {current_path} does not exist, skipping.\")\n                continue\n                \n            image = Image.open(current_path)\n            img_array = np.array(image)\n            \n            normalized_img = normalize_slice(img_array)\n            \n            dest_filename = f'{tomo_id}_z{axis_0:04d}_y{motor_axis_1:04d}_x{motor_axis_2:04d}.jpg'\n            dest_path = os.path.join(train_test_images_path, dest_filename)\n            \n            Image.fromarray(normalized_img).save(dest_path)\n            \n            img_width, img_height = image.size\n            \n            motor_axis_2_norm = motor_axis_2 / img_width\n            motor_axis_1_norm = motor_axis_1 / img_height\n            box_width_norm = BOX_SIZE / img_width\n            box_height_norm = BOX_SIZE / img_height\n\n            label_path = os.path.join(train_test_labels_path, dest_filename.replace('.jpg', '.txt'))\n            with open(label_path, 'w') as f:\n                f.write(f\"0 {motor_axis_2_norm} {motor_axis_1_norm} {box_width_norm} {box_height_norm}\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:49.869303Z","iopub.execute_input":"2025-06-09T15:27:49.869552Z","iopub.status.idle":"2025-06-09T15:27:50.073964Z","shell.execute_reply.started":"2025-06-09T15:27:49.869532Z","shell.execute_reply":"2025-06-09T15:27:50.072916Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"process_tomogram_set(train_tomo_ids, working_images_train_path, working_labels_train_path)\nprocess_tomogram_set(test_tomo_ids, working_images_test_path, working_labels_test_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:50.075102Z","iopub.execute_input":"2025-06-09T15:27:50.075390Z","iopub.status.idle":"2025-06-09T15:31:43.305032Z","shell.execute_reply.started":"2025-06-09T15:27:50.075367Z","shell.execute_reply":"2025-06-09T15:31:43.303862Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import yaml\n\nyaml_content = {\n    'path': working_yolo_path,\n    'train': 'images/train',\n    'val': 'images/val',\n    'names': {0: 'motor'}\n}\n\nwith open(os.path.join(working_yolo_path, 'dataset.yaml'), 'w') as f:\n    yaml.dump(yaml_content, f, default_flow_style=False)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:31:43.306158Z","iopub.execute_input":"2025-06-09T15:31:43.306529Z","iopub.status.idle":"2025-06-09T15:31:43.333716Z","shell.execute_reply.started":"2025-06-09T15:31:43.306499Z","shell.execute_reply":"2025-06-09T15:31:43.332555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}