{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","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":"nvidiaTeslaT4","dataSources":[{"sourceId":91249,"databundleVersionId":11294684,"sourceType":"competition"},{"sourceId":244158095,"sourceType":"kernelVersion"}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":65.173677,"end_time":"2025-05-11T16:15:04.398074","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2025-05-11T16:13:59.224397","version":"2.6.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"0674e5a4b4ed474baf3094606625483a":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"0cfbc4cda4b84729b2538b73c371bcdf":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"165bc23e5f5241b092a204f5ad7837d7":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"1be05446fb864002b6eff5c67ace2918":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"1e3ece48e30045dd9c1f8dac60d0d8ec":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"2f5136ac71394859ae8db4327df66434":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_1e3ece48e30045dd9c1f8dac60d0d8ec","placeholder":"​","style":"IPY_MODEL_78c346f0be804f9f903c0cb9cb9aafd1","tabbable":null,"tooltip":null,"value":"tomo_003acc: 100%"}},"31d2bce5c4c74e0b8ea3a6ba7f28ea3d":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"success","description":"","description_allow_html":false,"layout":"IPY_MODEL_a8570868873848aeb9c308a07703e29d","max":5,"min":0,"orientation":"horizontal","style":"IPY_MODEL_990ab58d3c524f628591bee4c9f1c3f6","tabbable":null,"tooltip":null,"value":5}},"3abd7f6dc6ea436187a876b2af3ed8f3":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"3e45514eda1d482b9c2637166c5ee868":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"492415b135d44a23a8fc4d2a9ab5734a":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_67a8001a8dfc4dad87a58f25841b8e99","placeholder":"​","style":"IPY_MODEL_de1f8d4c51f64b359bb7d9eab2ec8ca3","tabbable":null,"tooltip":null,"value":"tomo_01a877: 100%"}},"67a8001a8dfc4dad87a58f25841b8e99":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"6e5def6361d44c378471055834fe354f":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"729fa7dda6194e17af500b4541b40e99":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"success","description":"","description_allow_html":false,"layout":"IPY_MODEL_a3e1884f7dc84628a608910e346315cd","max":8,"min":0,"orientation":"horizontal","style":"IPY_MODEL_a15d81d863c14120915bd7427bfe7301","tabbable":null,"tooltip":null,"value":8}},"78c346f0be804f9f903c0cb9cb9aafd1":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"7fd65b9d83214caf9f614fb2361018bd":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"82050c93ab8d492297b147ce8b2b1e9a":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"88d93e66d4f74b7a8442556e1031c03d":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"92e9378eb53c48f3a5e06f6774efdbb9":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_2f5136ac71394859ae8db4327df66434","IPY_MODEL_729fa7dda6194e17af500b4541b40e99","IPY_MODEL_ba466a39e0414e6890102e84de041907"],"layout":"IPY_MODEL_1be05446fb864002b6eff5c67ace2918","tabbable":null,"tooltip":null}},"92f5074c5b824de8962d88909e7cca4f":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_492415b135d44a23a8fc4d2a9ab5734a","IPY_MODEL_e2401152c84549c9934c82ade16cd2cd","IPY_MODEL_cab1d11549f64bf6b3d1ef97ec929b59"],"layout":"IPY_MODEL_0674e5a4b4ed474baf3094606625483a","tabbable":null,"tooltip":null}},"990ab58d3c524f628591bee4c9f1c3f6":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"9a71b7ec425a4b11a962099562596df8":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_88d93e66d4f74b7a8442556e1031c03d","placeholder":"​","style":"IPY_MODEL_3abd7f6dc6ea436187a876b2af3ed8f3","tabbable":null,"tooltip":null,"value":" 5/5 [00:29&lt;00:00,  4.80s/it]"}},"a15d81d863c14120915bd7427bfe7301":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"a3e1884f7dc84628a608910e346315cd":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"a5771925c6014ac4a410b54c53bf807d":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"a8570868873848aeb9c308a07703e29d":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"b4902a7049fd48ff8e0884cbcc89e702":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"ba466a39e0414e6890102e84de041907":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_82050c93ab8d492297b147ce8b2b1e9a","placeholder":"​","style":"IPY_MODEL_3e45514eda1d482b9c2637166c5ee868","tabbable":null,"tooltip":null,"value":" 8/8 [00:41&lt;00:00,  5.06s/it]"}},"c3338529c28b4776a47e3609e7ac2a8b":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_d80851262e914ea78e2fe2008531e4c2","placeholder":"​","style":"IPY_MODEL_0cfbc4cda4b84729b2538b73c371bcdf","tabbable":null,"tooltip":null,"value":"tomo_00e047: 100%"}},"cab1d11549f64bf6b3d1ef97ec929b59":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_165bc23e5f5241b092a204f5ad7837d7","placeholder":"​","style":"IPY_MODEL_a5771925c6014ac4a410b54c53bf807d","tabbable":null,"tooltip":null,"value":" 5/5 [00:20&lt;00:00,  3.64s/it]"}},"d80851262e914ea78e2fe2008531e4c2":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"de1f8d4c51f64b359bb7d9eab2ec8ca3":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"e2401152c84549c9934c82ade16cd2cd":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"success","description":"","description_allow_html":false,"layout":"IPY_MODEL_7fd65b9d83214caf9f614fb2361018bd","max":5,"min":0,"orientation":"horizontal","style":"IPY_MODEL_6e5def6361d44c378471055834fe354f","tabbable":null,"tooltip":null,"value":5}},"ee61395efeeb4b989158e6ac897b6c0d":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_c3338529c28b4776a47e3609e7ac2a8b","IPY_MODEL_31d2bce5c4c74e0b8ea3a6ba7f28ea3d","IPY_MODEL_9a71b7ec425a4b11a962099562596df8"],"layout":"IPY_MODEL_b4902a7049fd48ff8e0884cbcc89e702","tabbable":null,"tooltip":null}}},"version_major":2,"version_minor":0}}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from concurrent.futures import ThreadPoolExecutor\nfrom torch.utils.data import Dataset, DataLoader\nfrom scipy.spatial import distance\nfrom tqdm.notebook import tqdm\nfrom PIL import Image\nimport matplotlib.patches as patches\nimport matplotlib.pyplot as plt\nimport networkx as nx\nimport pandas as pd\nimport numpy as np\nimport warnings\nimport random\nimport torch\nimport time\nimport cv2\nimport os\nimport gc\n\nwarnings.filterwarnings(\"ignore\")","metadata":{"_kg_hide-input":false,"papermill":{"duration":6.12597,"end_time":"2025-05-11T16:14:09.366541","exception":false,"start_time":"2025-05-11T16:14:03.240571","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_batch_size(device, min_batch_size=8, max_batch_size=64):\n    device_id = int(device.split(':')[1])\n    gpu_mem = torch.cuda.get_device_properties(device_id).total_memory / 1e9  \n    free_mem = gpu_mem - torch.cuda.memory_allocated(device_id) / 1e9\n    batch_size = max(min_batch_size, min(max_batch_size, int(free_mem * 4)))\n    torch.cuda.empty_cache()\n    return batch_size","metadata":{"papermill":{"duration":0.011612,"end_time":"2025-05-11T16:14:09.384337","exception":false,"start_time":"2025-05-11T16:14:09.372725","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CFG:\n    dataset_path = \"/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/\"\n    test_image_path = os.path.join(dataset_path, \"test\")\n    model_paths = [\n        \"/kaggle/input/flagellar-motor-detection-2-3-yolo-training/byu-locating-bacterial-flagellar-motors/yolo11s_fold_0/weights/best.torchscript\"\n    ]\n    \n    seed = 42    \n    devices = ['cuda:0', 'cuda:1']\n    image_size = 640\n    box_size = 64\n    confidence_threshold = 0.4\n    nms_iou_threshold = 0.2\n    concentration = 1\n    \n    batch_sizes = [get_batch_size(device_id) for device_id in devices]","metadata":{"papermill":{"duration":0.115206,"end_time":"2025-05-11T16:14:09.505133","exception":false,"start_time":"2025-05-11T16:14:09.389927","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"torch.backends.cudnn.benchmark = True\ntorch.backends.cudnn.deterministic = False\ntorch.backends.cuda.matmul.allow_tf32 = True\ntorch.backends.cudnn.allow_tf32 = True\n\ntorch.manual_seed(CFG.seed)\nrandom.seed(CFG.seed)\nnp.random.seed(CFG.seed)","metadata":{"papermill":{"duration":0.014041,"end_time":"2025-05-11T16:14:09.524964","exception":false,"start_time":"2025-05-11T16:14:09.510923","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class GPUProfiler:        \n    def __enter__(self):\n        torch.cuda.synchronize()\n        return self\n        \n    def __exit__(self, *args):\n        torch.cuda.synchronize()","metadata":{"papermill":{"duration":0.010144,"end_time":"2025-05-11T16:14:09.540594","exception":false,"start_time":"2025-05-11T16:14:09.530450","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class TomogramDataset(Dataset):\n    def __init__(self,tomo_dir, files, image_size=CFG.image_size):\n        self.tomo_dir = tomo_dir\n        self.files = files\n        self.image_size = image_size\n\n    def __getitem__(self, index):\n        image_path = os.path.join(self.tomo_dir, self.files[index])\n        image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)\n        \n        if image is None:\n            image = np.array(Image.open(image_path))\n            \n        processed_image = self.preprocess(image)\n        z_index = int(self.files[index].split('_')[1].split('.')[0])\n        \n        return *processed_image, z_index\n        \n    def __len__(self):\n        return len(self.files)\n    \n    def preprocess(self, image):\n        image, ratio, pad_w, pad_h = self.letterbox(image)\n        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)\n        image = image.transpose(2, 0, 1)\n        image = np.ascontiguousarray(image, dtype=np.float32) / 255.0\n        img_tensor = torch.from_numpy(image)\n        return img_tensor, ratio, pad_w, pad_h\n\n    def letterbox(self, image, color=(114, 114, 114), min_pad=0):\n        new_w, new_h = self.image_size, self.image_size\n        h, w = image.shape[:2]\n        ratio = min(new_w / w, new_h / h ) \n        \n        new_unpad_w,new_unpad_h  = (int(round(w * ratio) - 2 * min_pad), int(round(h * ratio)) - 2 * min_pad)\n        ratio = min(new_unpad_w / w, new_unpad_h / h)\n        dw, dh = new_w - new_unpad_w, new_h - new_unpad_h\n\n        dw /= 2  \n        dh /= 2\n\n        image_resized = cv2.resize(image, (new_unpad_w,new_unpad_h), interpolation=cv2.INTER_LINEAR)\n        image_resized = self.normalize(image_resized)\n        top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))\n        left, right = int(round(dw - 0.1)), int(round(dw + 0.1))\n        image_padded = cv2.copyMakeBorder(image_resized, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)\n\n        return image_padded, ratio, left, top\n    \n    def normalize(self, image):\n        p2, p98 = np.percentile(image, [2, 98])\n        clipped_data = np.clip(image, p2, p98)\n        normalized = 255 * (clipped_data - p2) / (p98 - p2)\n        return np.uint8(normalized)","metadata":{"papermill":{"duration":0.015925,"end_time":"2025-05-11T16:14:09.562069","exception":false,"start_time":"2025-05-11T16:14:09.546144","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def perform_3d_nms(detections, distance_threshold=CFG.nms_iou_threshold):\n    if not detections:\n        return []\n\n    detections = sorted(detections, key=lambda x: x['confidence'], reverse=True)\n    final_detections = []\n\n    def distance_3d(d1, d2):\n        return np.sqrt((d1['z'] - d2['z'])**2 + (d1['y'] - d2['y'])**2 + (d1['x'] - d2['x'])**2)\n\n    while detections:\n        best_detection = detections.pop(0)\n\n        final_detections.append(best_detection)\n\n        detections = [d for d in detections if distance_3d(d, best_detection) > distance_threshold]\n        \n    return final_detections","metadata":{"papermill":{"duration":0.011722,"end_time":"2025-05-11T16:14:09.579305","exception":false,"start_time":"2025-05-11T16:14:09.567583","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def infer_batch(model, device_idx, img_tensor, ratios, paddings, conf_thres=CFG.confidence_threshold):\n    img_tensor = img_tensor.to(device_idx)\n    \n    with torch.no_grad():\n        with torch.amp.autocast(device_type='cuda', enabled=True, dtype=torch.float16):\n            outputs = model(img_tensor) \n            \n    outputs = outputs.cpu()\n    if \"10m\" in CFG.model_paths[0]:\n        outputs = outputs.permute(0, 2, 1)\n        \n    batch_results = []\n    for i, output in enumerate(outputs):\n        if \"10m\" in CFG.model_paths[0]:\n            x_center, y_center, width, height, confidence, _ = output\n        else:\n            x_center, y_center, width, height, confidence = output\n            \n        mask = confidence > conf_thres\n\n        x, y, w, h, conf = x_center[mask], y_center[mask], width[mask], height[mask], confidence[mask]\n        ratio, pad_w, pad_h = ratios[i], paddings[0][i], paddings[1][i]\n        x1, y1, x2, y2 = (x - w / 2 - pad_w) / ratio, (y - h / 2 - pad_h) / ratio, (x + w / 2 - pad_w) / ratio, (y + h / 2 - pad_h) / ratio\n        batch_results.append((np.stack((x1, y1, x2, y2), axis=1), conf.numpy()))\n\n    return batch_results","metadata":{"papermill":{"duration":0.01285,"end_time":"2025-05-11T16:14:09.597693","exception":false,"start_time":"2025-05-11T16:14:09.584843","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_tomogram(tomo_id, models, device_idx):\n    tomo_dir = os.path.join(CFG.test_image_path, tomo_id)\n    slice_files = sorted([f for f in os.listdir(tomo_dir) if f.endswith('.jpg')])\n    selected_indices = np.linspace(0, len(slice_files)-1, int(len(slice_files) * CFG.concentration))\n    selected_indices = np.round(selected_indices).astype(int)\n    slice_files = [slice_files[i] for i in selected_indices]\n\n    batch_size = CFG.batch_sizes[device_idx]\n    streams = [torch.cuda.Stream(device=device_idx) for _ in range(min(4, batch_size))]\n    dataloader = DataLoader(\n        TomogramDataset(tomo_dir, slice_files), \n        batch_size=batch_size, \n        num_workers=1\n    )\n\n    all_detections = []\n    for batch in tqdm(dataloader, desc=tomo_id):\n        images, ratios, paddings_w, paddings_h, indexes = batch\n\n        sub_batches = (\n            torch.tensor_split(images, len(streams)),\n            torch.tensor_split(ratios, len(streams)),\n            torch.tensor_split(paddings_w, len(streams)),\n            torch.tensor_split(paddings_h, len(streams)),\n            torch.tensor_split(indexes, len(streams))\n        )\n\n        for i, (sub_images, sub_ratios, sub_paddings_w, sub_paddings_h, sub_indexes) in enumerate(zip(*sub_batches)):\n            if len(sub_images) == 0:\n                continue\n            \n            for fold_idx, model in enumerate(models):\n                \n                stream = streams[i % len(streams)]\n                with torch.cuda.stream(stream):\n                    with GPUProfiler():\n                        sub_results = infer_batch(model, device_idx, sub_images, sub_ratios, (sub_paddings_w, sub_paddings_h))\n\n                    for k, (boxes, confs) in enumerate(sub_results):\n                        for box, conf in zip(boxes, confs):\n                            x1, y1, x2, y2 = box\n                            x_center = (x1 + x2) / 2\n                            y_center = (y1 + y2) / 2\n                            all_detections.append({\n                                'z': sub_indexes[k].item(),\n                                'y': round(y_center),\n                                'x': round(x_center),\n                                'confidence': float(conf),\n                                'fold': fold_idx,\n                                'tomo_id': tomo_id\n                            })\n\n        torch.cuda.synchronize()\n        torch.cuda.empty_cache()\n        \n    if len(all_detections) == 0:\n        return [{\n            'z': -1,\n            'y': -1,\n            'x': -1,\n            'confidence': 0,\n            'fold': -1,\n            'tomo_id': tomo_id\n        }]\n\n    return all_detections","metadata":{"papermill":{"duration":0.01586,"end_time":"2025-05-11T16:14:09.619093","exception":false,"start_time":"2025-05-11T16:14:09.603233","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"models = {}\n\nfor device in CFG.devices:\n    models[device] = []\n    for path in CFG.model_paths:\n        models[device].append(torch.jit.load(path, map_location=device).eval())","metadata":{"papermill":{"duration":1.274046,"end_time":"2025-05-11T16:14:10.898785","exception":false,"start_time":"2025-05-11T16:14:09.624739","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# %%time\n\nall_detections = []\nfuture_to_tomo = {}\ntest_tomos = sorted([d for d in os.listdir(CFG.test_image_path) if os.path.isdir(os.path.join(CFG.test_image_path, d))])\n\nwith ThreadPoolExecutor(max_workers=len(CFG.devices)) as executor:\n    for i, tomo_id in enumerate(test_tomos):\n        device_idx = i % len(CFG.devices)\n        future = executor.submit(process_tomogram, tomo_id, models[CFG.devices[device_idx]], device_idx)\n        future_to_tomo[future] = tomo_id\n        \nfor future, tomo_id in future_to_tomo.items():\n    try:\n        result = future.result()\n        all_detections.extend(result)\n        \n    except Exception as e:\n        all_detections.extend([{\n            'z': -1,\n            'y': -1,\n            'x': -1,\n            'confidence': 0,\n            'fold': -1,\n            'tomo_id': tomo_id\n        }])\n        print(e)\n    \n    finally:\n        torch.cuda.empty_cache()\n        gc.collect()","metadata":{"papermill":{"duration":49.617853,"end_time":"2025-05-11T16:15:00.526412","exception":false,"start_time":"2025-05-11T16:14:10.908559","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"all_detections = pd.DataFrame(all_detections)\nif all_detections.tomo_id.nunique() == 3:\n    all_detections.to_csv(\"all_detections.csv\", index=False)","metadata":{"papermill":{"duration":0.034232,"end_time":"2025-05-11T16:15:00.567097","exception":false,"start_time":"2025-05-11T16:15:00.532865","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def postprocess(df, confidence_threshold, group_distance_threshold, min_detection_per_group):\n    df = df[df['confidence'] >= confidence_threshold]\n    \n    df_agg_det_tomo_list = []\n    for tomo_id, df_det_tomo in df.groupby('tomo_id'):\n        dist_mat = distance.cdist(df_det_tomo[['x', 'y', 'z']], df_det_tomo[['x', 'y', 'z']], metric='euclidean')\n        adj_mat = (dist_mat <= group_distance_threshold).astype(int)\n        np.fill_diagonal(adj_mat, 0)\n        G = nx.from_numpy_array(adj_mat)\n        connected_components = list(nx.connected_components(G))\n        agg_det_dict_list = []\n        for group_idx_set in connected_components:\n            df_det_grp = df_det_tomo.iloc[list(group_idx_set)] \n\n            z = (df_det_grp['z'] * df_det_grp['confidence']).sum() / df_det_grp['confidence'].sum()\n            y = (df_det_grp['y'] * df_det_grp['confidence']).sum() / df_det_grp['confidence'].sum()\n            x = (df_det_grp['x'] * df_det_grp['confidence']).sum() / df_det_grp['confidence'].sum()\n            score_mean = df_det_grp['confidence'].mean()\n\n            agg_det = {\n                'tomo_id': tomo_id,\n                'x': x,\n                'y': y,\n                'z': z,\n                'confidence': score_mean,\n                'group_det_count': len(group_idx_set),\n            }\n            agg_det_dict_list.append(agg_det)\n            \n        df_agg_det_tomo = pd.DataFrame(agg_det_dict_list)\n        df_agg_det_tomo = df_agg_det_tomo[df_agg_det_tomo['group_det_count'] >= min_detection_per_group]\n        df_agg_det_tomo = df_agg_det_tomo.sort_values(by=['group_det_count', 'confidence'], ascending=False).iloc[:1]\n        df_agg_det_tomo_list.append(df_agg_det_tomo)\n        \n    return pd.concat(df_agg_det_tomo_list)","metadata":{"papermill":{"duration":0.024258,"end_time":"2025-05-11T16:15:00.597570","exception":false,"start_time":"2025-05-11T16:15:00.573312","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def add_no_motor_tomos(predictions, test_tomos):\n    no_motors_ids = list(set(test_tomos) - set(predictions['tomo_id']))\n    \n    no_motors_sf = pd.DataFrame({\n        'tomo_id': no_motors_ids,\n        'x': [-1] * len(no_motors_ids),\n        'y': [-1] * len(no_motors_ids),\n        'z': [-1] * len(no_motors_ids),\n        'confidence': [0] * len(no_motors_ids),\n        'fold': [-1] * len(no_motors_ids)\n    })\n    \n    return pd.concat([predictions, no_motors_sf])\n\ndef fix_dtypes(predictions):\n    predictions[\"x\"] = predictions[\"x\"].astype(int)\n    predictions[\"y\"] = predictions[\"y\"].astype(int)\n    predictions[\"z\"] = predictions[\"z\"].astype(int)\n    return predictions","metadata":{"papermill":{"duration":0.012324,"end_time":"2025-05-11T16:15:00.615795","exception":false,"start_time":"2025-05-11T16:15:00.603471","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"final_predictions = postprocess(all_detections, confidence_threshold=0.02, group_distance_threshold=74, min_detection_per_group=2)\nfinal_predictions = add_no_motor_tomos(final_predictions, test_tomos)\nfinal_predictions = fix_dtypes(final_predictions)\nfinal_predictions","metadata":{"papermill":{"duration":0.266046,"end_time":"2025-05-11T16:15:00.887810","exception":false,"start_time":"2025-05-11T16:15:00.621764","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if len(final_predictions) == 3:\n    points = []\n    image_paths = []\n    \n    for i, r in final_predictions.iterrows():\n        if (\n            r['z'] != -1 and \n            r['y'] != -1 and \n            r['x'] != -1\n        ):\n            slice_num = int(r['z'])\n            slice_str = f\"{slice_num:04d}\"\n            image_path = f\"/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/test/{r['tomo_id']}/slice_{slice_str}.jpg\"\n            image_paths.append(image_path)\n            points.append((r['x'], r['y'], r['confidence']))\n\n    fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n    box_size = 64\n    half_box = box_size // 2\n\n    for i, path in enumerate(image_paths):\n        img = cv2.imread(path)\n        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        axes[i].imshow(img_rgb)\n        x, y, confidence = points[i]\n        \n        axes[i].scatter(x, y, color=\"red\")\n        \n        rect = patches.Rectangle((x - half_box, y - half_box), box_size, box_size, linewidth=2, edgecolor='lime', facecolor='none')\n        axes[i].add_patch(rect)\n        \n        axes[i].text(x - half_box, y - half_box - 10, f\"Confidence: {confidence:.4f}\", color='lime', fontsize=10, weight='bold', ha='center')\n        axes[i].set_title(path.split(\"/\")[-2] + \"/\" + path.split(\"/\")[-1])\n        axes[i].axis('off')\n\n    plt.tight_layout()\n    plt.show()","metadata":{"papermill":{"duration":1.197427,"end_time":"2025-05-11T16:15:02.092170","exception":false,"start_time":"2025-05-11T16:15:00.894743","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = final_predictions.copy()\nsubmission = submission.rename(columns={\"x\": \"Motor axis 2\", \"y\": \"Motor axis 1\", \"z\": \"Motor axis 0\"})\nsubmission = submission[['tomo_id', 'Motor axis 0', 'Motor axis 1', 'Motor axis 2']]\nsubmission.to_csv(\"submission.csv\", index=False)\nsubmission.head()","metadata":{"papermill":{"duration":0.036272,"end_time":"2025-05-11T16:15:02.153081","exception":false,"start_time":"2025-05-11T16:15:02.116809","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null}]}