{"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":"gpu","dataSources":[{"sourceId":91249,"databundleVersionId":11294684,"sourceType":"competition"},{"sourceId":11463418,"sourceType":"datasetVersion","datasetId":7164893},{"sourceId":11532032,"sourceType":"datasetVersion","datasetId":7233026},{"sourceId":11589961,"sourceType":"datasetVersion","datasetId":7267493},{"sourceId":11632086,"sourceType":"datasetVersion","datasetId":7298194},{"sourceId":11822200,"sourceType":"datasetVersion","datasetId":7426148},{"sourceId":11872384,"sourceType":"datasetVersion","datasetId":7461117},{"sourceId":11924122,"sourceType":"datasetVersion","datasetId":7496839}],"dockerImageVersionId":31012,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!cp -r /kaggle/input/deimkit-offline-package/DEIM /kaggle/working","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:42:55.496774Z","iopub.execute_input":"2025-05-24T05:42:55.497118Z","iopub.status.idle":"2025-05-24T05:43:21.411724Z","shell.execute_reply.started":"2025-05-24T05:42:55.497082Z","shell.execute_reply":"2025-05-24T05:43:21.410447Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sys\n\nsys.path.append('/kaggle/working/DEIM')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:43:21.413286Z","iopub.execute_input":"2025-05-24T05:43:21.413594Z","iopub.status.idle":"2025-05-24T05:43:21.418761Z","shell.execute_reply.started":"2025-05-24T05:43:21.413561Z","shell.execute_reply":"2025-05-24T05:43:21.417775Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!cp /kaggle/input/deimkit-0-2-1-whl/deimkit-0.2.1-py3-none-any.whl /kaggle/working/DEIM/","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:43:21.420117Z","iopub.execute_input":"2025-05-24T05:43:21.420414Z","iopub.status.idle":"2025-05-24T05:43:21.559201Z","shell.execute_reply.started":"2025-05-24T05:43:21.420390Z","shell.execute_reply":"2025-05-24T05:43:21.558082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install --no-index --find-links='/kaggle/working/DEIM' deimkit ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:43:21.561315Z","iopub.execute_input":"2025-05-24T05:43:21.561595Z","iopub.status.idle":"2025-05-24T05:44:27.007230Z","shell.execute_reply.started":"2025-05-24T05:43:21.561569Z","shell.execute_reply":"2025-05-24T05:44:27.006095Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from deimkit import list_models\n\nlist_models()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:44:27.008440Z","iopub.execute_input":"2025-05-24T05:44:27.008791Z","iopub.status.idle":"2025-05-24T05:45:03.189752Z","shell.execute_reply.started":"2025-05-24T05:44:27.008752Z","shell.execute_reply":"2025-05-24T05:45:03.188892Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"'''\nfrom deimkit import Trainer, Config, configure_dataset\n\nconf = Config.from_model_name(\"deim_hgnetv2_l\")\n\nconf = configure_dataset(\n    config=conf,\n    image_size=[640, 640],\n    train_ann_file=\"/kaggle/input/byu-coco-format-dataset/dataset_json/train/annotations_train.json\",\n    train_img_folder=\"/kaggle/input/byu-coco-format-dataset/dataset_json/train\",\n    val_ann_file=\"/kaggle/input/byu-coco-format-dataset/dataset_json/val/annotations_valid.json\",\n    val_img_folder=\"/kaggle/input/byu-coco-format-dataset/dataset_json/val\",\n    train_batch_size=8,\n    val_batch_size=8,\n    num_classes=2,\n    output_dir=\"./outputs\",\n)\n'''","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:03.191256Z","iopub.execute_input":"2025-05-24T05:45:03.191596Z","iopub.status.idle":"2025-05-24T05:45:03.197554Z","shell.execute_reply.started":"2025-05-24T05:45:03.191571Z","shell.execute_reply":"2025-05-24T05:45:03.196604Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!cp '/kaggle/input/deimkit-img800-wts/best (8).pth' /kaggle/working/best.pth","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:03.198403Z","iopub.execute_input":"2025-05-24T05:45:03.198696Z","iopub.status.idle":"2025-05-24T05:45:03.214149Z","shell.execute_reply.started":"2025-05-24T05:45:03.198667Z","shell.execute_reply":"2025-05-24T05:45:03.213019Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!cp /kaggle/input/deimkit-img640-wts/best.pth  /kaggle/working/best.pth","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:03.215288Z","iopub.execute_input":"2025-05-24T05:45:03.215630Z","iopub.status.idle":"2025-05-24T05:45:03.232375Z","shell.execute_reply.started":"2025-05-24T05:45:03.215597Z","shell.execute_reply":"2025-05-24T05:45:03.231310Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!cp '/kaggle/input/original-image-coco-deimkit-wts/best (11).pth'  /kaggle/working/best.pth","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:03.233374Z","iopub.execute_input":"2025-05-24T05:45:03.233715Z","iopub.status.idle":"2025-05-24T05:45:03.253032Z","shell.execute_reply.started":"2025-05-24T05:45:03.233691Z","shell.execute_reply":"2025-05-24T05:45:03.251795Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!cp '/kaggle/input/deimkit-640-p94r98-e35-wts/checkpoint0035.pth'  /kaggle/working/best.pth","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:03.256109Z","iopub.execute_input":"2025-05-24T05:45:03.256515Z","iopub.status.idle":"2025-05-24T05:45:05.117155Z","shell.execute_reply.started":"2025-05-24T05:45:03.256491Z","shell.execute_reply":"2025-05-24T05:45:05.115918Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!cp '/kaggle/input/deimkit-640-p94r98-e35-wts/best (17).pth'  /kaggle/working/best.pth","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport sys\nimport tempfile\nimport torch\nimport torch.distributed as dist\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.multiprocessing as mp\n\nfrom torch.nn.parallel import DistributedDataParallel as DDP\n\n# On Windows platform, the torch.distributed package only\n# supports Gloo backend, FileStore and TcpStore.\n# For FileStore, set init_method parameter in init_process_group\n# to a local file. Example as follow:\n# init_method=\"file:///f:/libtmp/some_file\"\n# dist.init_process_group(\n#    \"gloo\",\n#    rank=rank,\n#    init_method=init_method,\n#    world_size=world_size)\n# For TcpStore, same way as on Linux.\n\ndef setup(rank, world_size):\n    os.environ['MASTER_ADDR'] = 'localhost'\n    os.environ['MASTER_PORT'] = '12355'\n\n    # initialize the process group\n    dist.init_process_group(\"gloo\", rank=rank, world_size=world_size)\n\ndef cleanup():\n    dist.destroy_process_group()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:05.118331Z","iopub.execute_input":"2025-05-24T05:45:05.118613Z","iopub.status.idle":"2025-05-24T05:45:05.125551Z","shell.execute_reply.started":"2025-05-24T05:45:05.118590Z","shell.execute_reply":"2025-05-24T05:45:05.124575Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"setup(0, 1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:05.126580Z","iopub.execute_input":"2025-05-24T05:45:05.126932Z","iopub.status.idle":"2025-05-24T05:45:13.162508Z","shell.execute_reply.started":"2025-05-24T05:45:05.126900Z","shell.execute_reply":"2025-05-24T05:45:13.161442Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":" #image_size=(640 , 640),","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from deimkit import load_model\n\ncoco_classes = [\"motor\"]\nmodel = load_model(\n    \"deim_hgnetv2_s\", \n    checkpoint=\"/kaggle/working/best.pth\",\n    class_names=[\"motor\"],\n    image_size=(960 , 960),\n   \n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:13.163935Z","iopub.execute_input":"2025-05-24T05:45:13.164595Z","iopub.status.idle":"2025-05-24T05:45:14.069437Z","shell.execute_reply.started":"2025-05-24T05:45:13.164566Z","shell.execute_reply":"2025-05-24T05:45:14.068437Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#result = model.predict(\"/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/test/tomo_01a877/slice_0026.jpg\", visualize=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:14.070655Z","iopub.execute_input":"2025-05-24T05:45:14.071024Z","iopub.status.idle":"2025-05-24T05:45:14.075977Z","shell.execute_reply.started":"2025-05-24T05:45:14.070993Z","shell.execute_reply":"2025-05-24T05:45:14.074989Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#result.visualization","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:14.077022Z","iopub.execute_input":"2025-05-24T05:45:14.077311Z","iopub.status.idle":"2025-05-24T05:45:14.345104Z","shell.execute_reply.started":"2025-05-24T05:45:14.077288Z","shell.execute_reply":"2025-05-24T05:45:14.344138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import glob\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom timeit import default_timer as timer\n\nimport matplotlib\nimport matplotlib.pyplot as plt\n\n#from ultralytics import YOLO, RTDETR\n\nimport os,sys\nsys.path.append('/kaggle/working/')\n\n\n#--- helper -------------------- \nclass dotdict(dict):\n    __setattr__ = dict.__setitem__\n    __delattr__ = dict.__delitem__\n\n    def __getattr__(self, name):\n        try:\n            return self[name]\n        except KeyError:\n            raise AttributeError(name)\n\ndef time_to_str(t, mode='min'):\n\tif mode=='min':\n\t\tt  = int(t)/60\n\t\thr = t//60\n\t\tmin = t%60\n\t\treturn '%2d hr %02d min'%(hr,min)\n\n\telif mode=='sec':\n\t\tt   = int(t)\n\t\tmin = t//60\n\t\tsec = t%60\n\t\treturn '%2d min %02d sec'%(min,sec)\n\telse:\n\t\traise NotImplementedError\n#--------------------------------\n\n\n\nprint('IMPORT OK!!!')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:14.346069Z","iopub.execute_input":"2025-05-24T05:45:14.346372Z","iopub.status.idle":"2025-05-24T05:45:14.359329Z","shell.execute_reply.started":"2025-05-24T05:45:14.346349Z","shell.execute_reply":"2025-05-24T05:45:14.358386Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"KAGGLE_DATA_DIR='/kaggle/input/byu-locating-bacterial-flagellar-motors-2025'\n\nMODE='submit'\n\n#MODE = 'local'\n\nif MODE == 'local':\n    valid_dir = f'{KAGGLE_DATA_DIR}/train'\n    valid_id = ['tomo_00e047', 'tomo_0c3a99', 'tomo_0fe63f', 'tomo_13484c', 'tomo_0363f2', 'tomo_1446aa', 'tomo_19a313', 'tomo_1cc887', 'tomo_221a47', 'tomo_2483bb', 'tomo_2a6ca2', 'tomo_2c9da1', 'tomo_30b580', 'tomo_331130', 'tomo_378f43', 'tomo_3e7783', 'tomo_412d88', 'tomo_455dcd', 'tomo_4b124b', 'tomo_4ee35e', 'tomo_517f70', 'tomo_53e048', 'tomo_57c814', 'tomo_5dd63d', 'tomo_60ddbd', 'tomo_640a74', 'tomo_672101', 'tomo_68e123', 'tomo_6cb0f0', 'tomo_6f2c1f', 'tomo_73173f', 'tomo_79756f', 'tomo_7f0184', 'tomo_82d780', 'tomo_881d84', 'tomo_8e4f7d', 'tomo_8f4d60', 'tomo_93c0b4', 'tomo_98686a', 'tomo_99a3ce', 'tomo_9f1828', 'tomo_a1a9a3', 'tomo_a537dd', 'tomo_a910fe', 'tomo_b03f81', 'tomo_b54396', 'tomo_ba9b3d', 'tomo_be4a3a', 'tomo_c36baf', 'tomo_c7b008', 'tomo_cc65a9', 'tomo_d0aa3b', 'tomo_d26fcb', 'tomo_d6c63f', 'tomo_d9a2af', 'tomo_decb81', 'tomo_e34af8', 'tomo_e63ab4', 'tomo_ec1314', 'tomo_f2fa4a', 'tomo_f871ad', 'tomo_fc5ae4', 'tomo_003acc', 'tomo_04d42b', 'tomo_087d64', 'tomo_0c2749', 'tomo_10a3bd', 'tomo_17143f', 'tomo_1c75ac', 'tomo_221c8e', 'tomo_24a095', 'tomo_288d4f', 'tomo_2c9f35', 'tomo_307f33', 'tomo_37c426', 'tomo_3a3519', 'tomo_3e6ead', 'tomo_466489', 'tomo_4baff0', 'tomo_4e3e37', 'tomo_512f98', 'tomo_569981', 'tomo_5d01e8', 'tomo_646049', 'tomo_6607ec', 'tomo_6a6a3b', 'tomo_6e196d', 'tomo_746d88', 'tomo_7dc063', 'tomo_80bf0f', 'tomo_85708b', 'tomo_8acc4b', 'tomo_8ee8fd', 'tomo_957567', 'tomo_97876d', 'tomo_9dbc12', 'tomo_a4f419', 'tomo_ab78d0', 'tomo_aeaf51', 'tomo_b24f1a', 'tomo_b7becf', 'tomo_b98cf6', 'tomo_bb5ac1', 'tomo_be9b98', 'tomo_c3619a', 'tomo_c596be', 'tomo_c925ee', 'tomo_cae587', 'tomo_d31c96', 'tomo_d8c917', 'tomo_dbc66d', 'tomo_dfdc32', 'tomo_e32b81', 'tomo_e72e60', 'tomo_e8db69', 'tomo_ecbc12', 'tomo_f672c0', 'tomo_f8b835', 'tomo_fc1665', 'tomo_ff7c20']\n    valid_id = valid_id[:20]\nif MODE == 'submit':\n    valid_dir = f'{KAGGLE_DATA_DIR}/test'\n    valid_id = glob.glob(f'{valid_dir}/*')\n    valid_id = [f.split('/')[-1] for f in valid_id]\n\nprint('valid_id:', len(valid_id))\nprint(valid_id[:5], '...')\n\ncfg = dotdict(\n    slice_step=1,\n    #batch_size=16,\n    #batch_size=1,\n    batch_size=32,\n    \n    #box_min_conf=0.40,\n    box_min_conf=0.3,\n    box_size=24,\n    #iou_threshold=0.5,\n\n    iou_threshold=0.5,\n\n    device='cuda',\n\n    #try cpu, gpu out of quota\n    #device='cpu',\n    checkpoint=\\\n    #'/kaggle/input/rtdetr-60e-wts/runs/detect/train/weights/best.pt'\n    #'/kaggle/input/rtdetr-100epoch-wts/last.pt'\n\n    '/kaggle/working/best.pth'\n    \n)\n\nprint('MODE:', MODE)\nprint('SETTING OK!!!')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:14.360225Z","iopub.execute_input":"2025-05-24T05:45:14.360678Z","iopub.status.idle":"2025-05-24T05:45:14.384730Z","shell.execute_reply.started":"2025-05-24T05:45:14.360634Z","shell.execute_reply":"2025-05-24T05:45:14.383783Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#double gpu \n\nmodels = []\nfor i in [0,1] :\n    #m = YOLO(cfg.checkpoint)\n    m = model\n   \n    models.append(m)\n\nprint('MODEL OK!!!')\n ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:14.385635Z","iopub.execute_input":"2025-05-24T05:45:14.386001Z","iopub.status.idle":"2025-05-24T05:45:14.403507Z","shell.execute_reply.started":"2025-05-24T05:45:14.385969Z","shell.execute_reply":"2025-05-24T05:45:14.402384Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BASE_IMAGE_DIR = \"/kaggle/input/byu-locating-bacterial-flagellar-motors-2025\"\nTEST_IMAGE_DIR = os.path.join(BASE_IMAGE_DIR, \"test\")\ntest_tomo_dir_list = glob.glob(f'{TEST_IMAGE_DIR}/*')\ntest_tomo_id_list = [d.split('/')[-1] for d in test_tomo_dir_list]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:14.404694Z","iopub.execute_input":"2025-05-24T05:45:14.405060Z","iopub.status.idle":"2025-05-24T05:45:14.422790Z","shell.execute_reply.started":"2025-05-24T05:45:14.405037Z","shell.execute_reply":"2025-05-24T05:45:14.421889Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#deimkit load image methods\nIMAGE_SIZE = (640, 640)\nfrom PIL import Image, ImageDraw\n\ndef load_images(tomo_id, train_or_test='test', resize_size=IMAGE_SIZE, loader='torchvision'):\n    assert loader in ['pil', 'torchvision']\n    image_dir = f'{BASE_IMAGE_DIR}/{train_or_test}/{tomo_id}'\n    image_files = sorted(glob.glob(f'{image_dir}/*.*'))\n    df_image_files = pd.DataFrame({'filepath': image_files})\n    df_image_files['no'] = df_image_files['filepath'].map(lambda x: int(x.split('_')[-1].split('.')[0]))\n    df_image_files = df_image_files.sort_values(by='no', ascending=True)\n  \n    num=len(image_files)\n    #print(image_files[:5])\n    # print(df_image_files['filepath'][:10])\n \n    # None : pil/torchvision resize results in slightly different values.\n    if loader == 'pil':\n        images = [Image.open(f).convert('L') for f in df_image_files['filepath']]\n        org_image_size = images[0].size  # (w, h)\n        if resize_size is not None:\n            images = [image.resize(resize_size) for image in images]\n        images = np.stack([np.asarray(image) for image in images])  # (n_frames, h, w)\n    elif loader == 'torchvision':\n        trainsforms = T.Resize(resize_size) if resize_size is not None else T.Compose([])\n        images = [torchvision.io.read_image(f) for f in df_image_files['filepath']]\n        org_image_size = (images[0].shape[2], images[0].shape[1])  # (w, h)\n        images = [trainsforms(image) for image in images]\n        images = torch.concatenate(images, dim=0)  # (n_frames, h, w)\n        images = images.numpy()\n    return images, df_image_files, org_image_size","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:45:14.423885Z","iopub.execute_input":"2025-05-24T05:45:14.424388Z","iopub.status.idle":"2025-05-24T05:45:14.443781Z","shell.execute_reply.started":"2025-05-24T05:45:14.424354Z","shell.execute_reply":"2025-05-24T05:45:14.442551Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# for evaluation\ndef make_truth_df(valid_id):\n    label_df = pd.read_csv(f'{KAGGLE_DATA_DIR}/train_labels.csv',\n       dtype={\n           'Number of motors': int,\n           'Array shape (axis 0)': int,\n           'Array shape (axis 1)': int,\n           'Array shape (axis 2)': int,\n           'Motor axis 0': int,\n           'Motor axis 1': int,\n           'Motor axis 2': int,\n           'Voxel spacing': float,\n       })\n\n    truth_df = []\n    for tomo_id in valid_id:\n        df = label_df[label_df['tomo_id'] == tomo_id]\n        zyx = df[['Motor axis 0','Motor axis 1','Motor axis 2']].values[0].tolist()\n        spacing = df['Voxel spacing'].values[0]\n        num_motor = df['Number of motors'].values[0]\n        truth_df.append({\n            'tomo_id': tomo_id,\n            'Voxel spacing': spacing,\n            'Motor axis 0': zyx[0],\n            'Motor axis 1': zyx[1],\n            'Motor axis 2': zyx[2],\n            'Has motor': int(num_motor>0)\n        })\n\n    truth_df = pd.DataFrame(truth_df)\n    return truth_df\n\n# inference helper\n\ndef distance_3d(d1, d2):\n    return np.sqrt((d1['z'] - d2['z']) ** 2 +\n                   (d1['y'] - d2['y']) ** 2 +\n                   (d1['x'] - d2['x']) ** 2)\n\ndef do_mns_3d(detection):\n    if not detection:\n        return []\n\n    distance_threshold = cfg.box_size * cfg.iou_threshold\n\n    # Sort by confidence (highest first)\n    detection = sorted(detection, key=lambda x: x['confidence'], reverse=True)\n\n    #detection = sorted(detection, key=lambda x: x['scores'], reverse=True)\n\n    nms = []\n    while detection:\n        # take the detection with highest confidence\n        best_detection = detection.pop(0)\n        nms.append(best_detection)\n        detection = [d for d in detection if distance_3d(d, best_detection) > distance_threshold]\n\n    return nms\n\n\n\ndef predict_one(model, tomo_id,imgsize=640):\n\n    #yolo load image\n  \n    image_file = glob.glob(f'{valid_dir}/{tomo_id}/*.jpg')\n    image_file = sorted(image_file)\n    m = cv2.imread(image_file[0], cv2.IMREAD_GRAYSCALE)\n    D = len(image_file)\n    H,W = m.shape\n    \n\n    # deimkit load image\n    # 1. Load images for target tomo_id\n    '''\n    image, image_file, org_image_size = load_images(tomo_id=tomo_id, loader='pil', resize_size=IMAGE_SIZE)\n    image = image.transpose(1, 2, 0)  # (n_frames, h, w) => (h, w, n_frames)\n    z_max = image.shape[-1] - 1\n    w_org, h_org = org_image_size\n    D = len(image_file)\n    '''    \n\n    slice_no = np.arange(D)[::cfg.slice_step]\n    image_file = image_file[::cfg.slice_step]\n    num_file = len(image_file)\n    #print('num_file:',num_file)\n\n    detection=[]\n    for i in range(0, num_file, cfg.batch_size):\n        batch_z = slice_no[i:i+cfg.batch_size]\n        #print(batch_z)\n\n        batch_file = image_file[i:i+cfg.batch_size]\n        #print(batch_file)\n        #result = model(batch_file, verbose=False)\n\n        #result = model.predict(batch_file, visualize=False)\n\n        result = model.predict_batch(batch_file,batch_size=cfg.batch_size, visualize=False)\n\n\n        #result=    boxes,labels,scores,class_names,visualization\n        \n\n        for j, r in enumerate(result):\n            if len(r.boxes) > 0:\n                boxes = r.boxes\n                #for k, confidence in enumerate(boxes.conf):\n                #    if confidence >= cfg.box_min_conf:\n                for k, confidence in enumerate(r.scores):\n                    if confidence >= cfg.box_min_conf:\n                        #x1, y1, x2, y2 = boxes.xyxy[k].cpu().numpy()\n                        #yolo detection format\n                        #x1, y1, x2, y2 = boxes[k]\n                        #x = (x1 + x2) / 2\n                        #y = (y1 + y2) / 2\n                        #z = batch_z[j]\n\n\n                        #deimkit format detection prediction, with normalized images 640  xywh??\n                        #box format is [y1, x1, y2, x2] (COCO format)??\n                        \n                        x1, y1, x2, y2 = boxes[k]\n                        x = (x1 + x2) / 2\n                        y = (y1 + y2) / 2\n                        #rescale back\n                        #x =W*x/imgsize \n                        #y =H*y/imgsize\n                        z = batch_z[j]\n                        # Store detection with 3D coordinates\n                        detection.append({\n                            'z': round(z),\n                            'y': round(y),\n                            'x': round(x),\n                            'confidence': float(confidence)\n                        })\n    # 3D Non-Maximum Suppression to merge nearby detections across slices\n    mns = do_mns_3d(detection)\n    mns.sort(key=lambda x: x['confidence'], reverse=True)\n\n\n    #try no mns_3d\n    #mns = detection\n    #mns.sort(key=lambda x: x['confidence'], reverse=True)    \n\n\n    # If there are no detections, return NA values\n    if not mns:\n        return {\n            'tomo_id': tomo_id,\n            'Motor axis 0': -1,\n            'Motor axis 1': -1,\n            'Motor axis 2': -1,\n            'confidence': cfg.box_min_conf,\n        }\n    else:\n        return {\n            'tomo_id': tomo_id,\n            'Motor axis 0': mns[0]['z'],\n            'Motor axis 1': mns[0]['y'],\n            'Motor axis 2': mns[0]['x'],\n            'confidence': mns[0]['confidence'],\n        }\n\n\n\n\ndef do_predict(model, valid_id, rank):\n\n    result = []\n    total_time_taken = 0\n    for i,tomo_id in enumerate(valid_id):\n        start_timer = timer()\n\n        r = predict_one(model, tomo_id)\n        print(r)\n        result.append(r)\n        time_taken = timer() - start_timer\n        total_time_taken += time_taken\n        print('\\r',f'rank{rank}', i, r,  time_to_str(total_time_taken, 'min'), end='')\n        if 0: #MODE=='local': #show some example\n            pass\n\n            if i ==0:\n                z = int(r['Motor axis 0'])\n                y = int(r['Motor axis 1'])\n                x = int(r['Motor axis 2'])\n                if z==-1:\n                    continue\n\n                image_file = f'{valid_dir}/{tomo_id}/slice_{z:04d}.jpg'\n                m = cv2.imread(image_file, cv2.IMREAD_GRAYSCALE)\n                \n                overlay = np.stack([m, m, m], -1)\n                cv2.circle(overlay, (x,y), 6, (0,255,255), 2)\n\n                #overlay = 255 - (255 - overlay) * (1 - p)\n                overlay = overlay.astype(np.uint8)\n                plt.imshow(overlay)\n                plt.show()\n    print('')\n    return result\n\n\n#########################################################################################################\nif 1:\n    from concurrent.futures import ThreadPoolExecutor\n    start_timer = timer()\n    N = len(valid_id)\n  \n    with ThreadPoolExecutor(max_workers=2) as executor:\n       \n        future0 = executor.submit(do_predict, model, valid_id[0::2], 0)\n        future1 = executor.submit(do_predict, model, valid_id[1::2], 1)\n        result0 = future0.result()\n        result1 = future1.result()\n    result = result0+result1\n    \n    '''\n    with ThreadPoolExecutor(max_workers=1) as executor:\n        future = executor.submit(do_predict, model,valid_id[0::2], 0)\n\n        result = future.result()\n   '''\n\n    total_time_taken = timer() - start_timer\n    print('** total_time_taken:',time_to_str(total_time_taken, 'min'))\n    print('time est for 900 tomograph:', time_to_str(total_time_taken/len(valid_id)*900, 'min'))\n    print('')\n\n    result_df = pd.DataFrame(result)\n    result_df.to_csv('result.csv',index=False)\n\n    submit_df = result_df[['tomo_id','Motor axis 0','Motor axis 1','Motor axis 2']]\n    submit_df.to_csv('submission.csv',index=False)\n    print(submit_df)\n    print('SUBMIT OK !!!!!!!!!!!!')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T05:53:49.632028Z","iopub.execute_input":"2025-05-24T05:53:49.633282Z","iopub.status.idle":"2025-05-24T06:08:12.751288Z","shell.execute_reply.started":"2025-05-24T05:53:49.633245Z","shell.execute_reply":"2025-05-24T06:08:12.750195Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}