{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.13"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":97984,"databundleVersionId":14096757,"sourceType":"competition"},{"sourceId":13746387,"sourceType":"datasetVersion","datasetId":8747012},{"sourceId":13816899,"sourceType":"datasetVersion","datasetId":8620533},{"sourceId":271051632,"sourceType":"kernelVersion"},{"sourceId":677607,"sourceType":"modelInstanceVersion","modelInstanceId":513841,"modelId":528480}],"dockerImageVersionId":31154,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":183.779437,"end_time":"2025-12-25T04:36:58.570038","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2025-12-25T04:33:54.790601","version":"2.6.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"0111f92d52bd48669aefae2314ec33bc":{"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_41713ebec723481ea394600ca82b7b07","placeholder":"​","style":"IPY_MODEL_3759ca8a80bf4b959dc7afe90f5cab26","tabbable":null,"tooltip":null,"value":"100%"}},"105e5226cae04a86b8dfb6abbf9c26f0":{"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":""}},"16888d7167ce4554800591b86c1f7fe6":{"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}},"1d0b3206815c4a1aa5667e98098e365b":{"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}},"2211083dd1a14fd987c4bd7c2708e63b":{"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_3788b7ac057d4f59915d6c7f37978931","placeholder":"​","style":"IPY_MODEL_5a8d62b514bc419dadad475290209cb6","tabbable":null,"tooltip":null,"value":" 9/9 [00:57&lt;00:00,  5.85s/it]"}},"2a7b5d50a4dc48e9b3dd7e20a6852730":{"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}},"2c53d02a1cc945a1a660305f6d5690b0":{"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}},"2da91137f128404b822f167749f10ca9":{"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}},"32c8450bf9b5435c852f1141a12c3f12":{"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}},"3384507c766f4e19bd9b5874106cd25b":{"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}},"3759ca8a80bf4b959dc7afe90f5cab26":{"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}},"3788b7ac057d4f59915d6c7f37978931":{"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}},"3a8868b20e734bddb765e55742f781a5":{"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}},"41713ebec723481ea394600ca82b7b07":{"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}},"49d100ba65e04df2ac8b6b9abdd8f48e":{"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}},"573abc154556462bb03f8d801f4c2aea":{"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_0111f92d52bd48669aefae2314ec33bc","IPY_MODEL_d75b772a6b4a468baebee4f0958553cd","IPY_MODEL_94c73921e6f7469ca145c723815e6690"],"layout":"IPY_MODEL_1d0b3206815c4a1aa5667e98098e365b","tabbable":null,"tooltip":null}},"583d7cab55124948bc2e17219f27cc11":{"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}},"588e385af542442a8d231b7f987c0c02":{"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}},"5a110c11912e4af8a88c6b02e0363e17":{"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_a6b624a147e148948b0a312fcff2fff8","max":9,"min":0,"orientation":"horizontal","style":"IPY_MODEL_6fc3d56308e24872850905634c92c812","tabbable":null,"tooltip":null,"value":9}},"5a8d62b514bc419dadad475290209cb6":{"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}},"5afa28457c6a4d87b15de302fd65beaa":{"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_d7de585e087741ada7b8c68a8e55237f","IPY_MODEL_5a110c11912e4af8a88c6b02e0363e17","IPY_MODEL_b74e70afdd8949028588b4154cd69ab9"],"layout":"IPY_MODEL_2da91137f128404b822f167749f10ca9","tabbable":null,"tooltip":null}},"6792871ad0394226ad246c1fbc37883b":{"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}},"6c1ed0121298422a8f2e626fa034e444":{"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_7f3a3e854463433dbd0528d58b27ed54","placeholder":"​","style":"IPY_MODEL_583d7cab55124948bc2e17219f27cc11","tabbable":null,"tooltip":null,"value":"100%"}},"6d9831d3256e4b38b1b610cf69d9c78b":{"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_915885071a4646cf9ef27846c3eb70f1","max":9,"min":0,"orientation":"horizontal","style":"IPY_MODEL_105e5226cae04a86b8dfb6abbf9c26f0","tabbable":null,"tooltip":null,"value":9}},"6fc3d56308e24872850905634c92c812":{"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":""}},"7f3a3e854463433dbd0528d58b27ed54":{"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}},"84a7c0d33f8e41db9f80b308f33e6e19":{"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_32c8450bf9b5435c852f1141a12c3f12","max":9,"min":0,"orientation":"horizontal","style":"IPY_MODEL_bc7066dd8a6b41e7ac8ba6112ed5c3e0","tabbable":null,"tooltip":null,"value":9}},"8f7e9ca8613c4131b15976e8193a5448":{"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}},"915885071a4646cf9ef27846c3eb70f1":{"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}},"94c73921e6f7469ca145c723815e6690":{"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_2a7b5d50a4dc48e9b3dd7e20a6852730","placeholder":"​","style":"IPY_MODEL_3a8868b20e734bddb765e55742f781a5","tabbable":null,"tooltip":null,"value":" 9/9 [00:01&lt;00:00,  5.48it/s]"}},"96e51f22495443d8b8304e4e2afbc68b":{"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_b96ea72cb88546ca90ca4cbda1cf9ba0","placeholder":"​","style":"IPY_MODEL_cbaad90b1c9a4852885ae8c84e5b44c1","tabbable":null,"tooltip":null,"value":"100%"}},"999fe022a50445018ac780af3a8bb27e":{"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}},"99a964921ba64fa9936033ddfda32dd3":{"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":""}},"9a5cf5e346bf4be69843f3755517703c":{"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_6c1ed0121298422a8f2e626fa034e444","IPY_MODEL_84a7c0d33f8e41db9f80b308f33e6e19","IPY_MODEL_dad44889a2b4429386e7b8b53445d037"],"layout":"IPY_MODEL_9b5ad2e24b9d48a89ddfc764078bf4e9","tabbable":null,"tooltip":null}},"9b5ad2e24b9d48a89ddfc764078bf4e9":{"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}},"a6b624a147e148948b0a312fcff2fff8":{"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}},"b74e70afdd8949028588b4154cd69ab9":{"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_8f7e9ca8613c4131b15976e8193a5448","placeholder":"​","style":"IPY_MODEL_3384507c766f4e19bd9b5874106cd25b","tabbable":null,"tooltip":null,"value":" 9/9 [00:22&lt;00:00,  2.49s/it]"}},"b96ea72cb88546ca90ca4cbda1cf9ba0":{"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}},"bc7066dd8a6b41e7ac8ba6112ed5c3e0":{"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":""}},"cbaad90b1c9a4852885ae8c84e5b44c1":{"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}},"d75b772a6b4a468baebee4f0958553cd":{"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_999fe022a50445018ac780af3a8bb27e","max":9,"min":0,"orientation":"horizontal","style":"IPY_MODEL_99a964921ba64fa9936033ddfda32dd3","tabbable":null,"tooltip":null,"value":9}},"d7de585e087741ada7b8c68a8e55237f":{"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_6792871ad0394226ad246c1fbc37883b","placeholder":"​","style":"IPY_MODEL_588e385af542442a8d231b7f987c0c02","tabbable":null,"tooltip":null,"value":"100%"}},"dad44889a2b4429386e7b8b53445d037":{"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_2c53d02a1cc945a1a660305f6d5690b0","placeholder":"​","style":"IPY_MODEL_49d100ba65e04df2ac8b6b9abdd8f48e","tabbable":null,"tooltip":null,"value":" 9/9 [00:17&lt;00:00,  1.92s/it]"}},"e3ad6e1d013b45eaaf540fe25f991f4a":{"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_96e51f22495443d8b8304e4e2afbc68b","IPY_MODEL_6d9831d3256e4b38b1b610cf69d9c78b","IPY_MODEL_2211083dd1a14fd987c4bd7c2708e63b"],"layout":"IPY_MODEL_16888d7167ce4554800591b86c1f7fe6","tabbable":null,"tooltip":null}}},"version_major":2,"version_minor":0}}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# ECG Image to Signal Conversion Pipeline\n \nThis notebook demonstrates a robust, multi-stage deep learning pipeline for digitizing ECG signals from images. It is designed for the PhysioNet ECG Image Digitization Challenge and is suitable for both competition and local testing environments.\n\n---\n\n## Overview\n\nThe pipeline consists of three main stages:\n\n- **Stage 0:** Image normalization and alignment (preprocessing, rotation, and homography correction)\n- **Stage 1:** Grid rectification and further normalization (removes grid artifacts, enhances signal visibility)\n- **Stage 2:** Signal extraction from rectified images (deep learning-based extraction of ECG traces)\n\nEach stage uses a custom-trained deep learning model. The notebook is modular, with clear error handling and fallback mechanisms to ensure robust processing.\n\n---\n\n## Key Features\n\n- Fully automated, end-to-end ECG image digitization\n- Custom deep learning models for each stage\n- Handles both competition and local test datasets\n- Robust error handling and fallback mechanisms\n- Produces a submission file in the required format for the challenge\n- Deterministic setup for reproducibility\n- Modular code for easy adaptation and extension\n\n**Note:** This notebook is intended for use in a Kaggle environment with the required datasets and model weights available in the specified input paths.","metadata":{"papermill":{"duration":0.007395,"end_time":"2025-12-25T04:34:00.304165","exception":false,"start_time":"2025-12-25T04:34:00.29677","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# --- Environment Setup ---\n# Uninstall TensorFlow (if present) and install required package for connected components 3D.\n# Note: The custom package is installed from a Kaggle dataset directory.\n# This ensures a clean environment and the correct dependencies for the pipeline.\n\n!pip uninstall -y tensorflow\n!uv pip install --no-deps --system --no-index --find-links='/kaggle/input/hengck23-submit-physionet/hengck23-submit-physionet/setup' 'connected-components-3d'\n\n# Optional: Check CUDA availability for PyTorch\nimport torch\nprint('CUDA available:', torch.cuda.is_available())","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2025-12-26T16:43:22.518974Z","iopub.execute_input":"2025-12-26T16:43:22.519635Z","iopub.status.idle":"2025-12-26T16:44:11.398643Z","shell.execute_reply.started":"2025-12-26T16:43:22.519608Z","shell.execute_reply":"2025-12-26T16:44:11.397672Z"},"papermill":{"duration":44.33977,"end_time":"2025-12-25T04:34:44.65064","exception":false,"start_time":"2025-12-25T04:34:00.31087","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- Imports and Data Preparation ---\n# Import all required libraries, set up deterministic behavior, and prepare paths for test data.\n# The code dynamically selects between competition and local test datasets.\n# Additional comments and structure for clarity and reproducibility.\n\nimport kagglehub\nfrom scipy.interpolate import CubicSpline\ndeterministic = kagglehub.package_import('wasupandceacar/deterministic').deterministic\ndeterministic.init_all(67, disable_list=['cuda_block'])\n\nimport sys\nsys.path.append('/kaggle/input/hengck23-submit-physionet/hengck23-submit-physionet')\n\nimport os\nimport gc\nimport cv2\nimport torch\nimport traceback\nimport numpy as np\nimport pandas as pd\nfrom pathlib import Path\nfrom tqdm.auto import tqdm\nfrom shutil import copyfile\nfrom scipy.signal import resample\n\n# Stage 0: Image Normalization and Alignment\nfrom stage0_model import Net as Stage0Net\nfrom stage0_common import *\n\nif_submit = os.getenv('KAGGLE_IS_COMPETITION_RERUN')\nif if_submit:\n    test_meta = Path(\"/kaggle/input/physionet-ecg-image-digitization/test.csv\")\n    test_dir = Path(\"/kaggle/input/physionet-ecg-image-digitization/test\")\nelse:\n    test_meta = Path(\"/kaggle/input/physio-test-fake-dataset/test_fake/test.csv\")\n    test_dir = Path(\"/kaggle/input/physio-test-fake-dataset/test_fake\")\n\nvalid_df = pd.read_csv(test_meta)\nvalid_df['id'] = valid_df['id'].astype(str) \nvalid_id = valid_df['id'].unique().tolist()\n\nglobal_dict = {\n    \"stage0_dir\": \"/kaggle/working/stage0\",\n    \"stage1_dir\": \"/kaggle/working/stage1\",\n    \"stage2_dir\": \"/kaggle/working/stage2\",\n}\n\n# --- Utility Function ---\n# Enhance image contrast and denoise for model input.\ndef change_color(image_rgb):\n    gray = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2GRAY)\n    denoised = cv2.fastNlMeansDenoising(gray, h=10)\n    clahe = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(8,8))\n    contrast_enhanced = clahe.apply(denoised)\n    return cv2.cvtColor(contrast_enhanced, cv2.COLOR_GRAY2RGB)\n\n# --- Stage 0: Image Normalization and Alignment ---\nstage0_dir = Path(global_dict[\"stage0_dir\"])\nstage0_dir.mkdir(exist_ok=True)\nstage0_net = Stage0Net(pretrained=False)\nstage0_net = load_net(stage0_net, '/kaggle/input/hengck23-submit-physionet/hengck23-submit-physionet/weight/stage0-last.checkpoint.pth')\nstage0_net.to(\"cuda:0\")\nstage0_net.eval()\n\nfor n, sample_id in enumerate(tqdm(valid_id)):\n    path = test_dir / f'{sample_id}.png'\n    output_path = stage0_dir / f'{sample_id}.png'\n    image_original = cv2.imread(str(path), cv2.IMREAD_COLOR)\n    image_original = cv2.cvtColor(image_original, cv2.COLOR_BGR2RGB)\n    image_for_model = change_color(image_original)\n    batch = image_to_batch(image_for_model)\n    try:\n        with torch.no_grad(), torch.amp.autocast('cuda', dtype=torch.float32):\n            output = stage0_net(batch)\n        rotated, keypoint = output_to_predict(image_original, batch, output)\n        normalised, _, _ = normalise_by_homography(rotated, keypoint)\n        cv2.imwrite(str(output_path), cv2.cvtColor(normalised, cv2.COLOR_RGB2BGR))\n    except Exception as e:\n        traceback.print_exc()\n        copyfile(path, output_path)\n\n# --- Stage 1: Grid Rectification ---\nfrom stage1_model import Net as Stage1Net\nfrom stage1_common import *\nstage0_dir = Path(global_dict[\"stage0_dir\"])\nstage1_dir = Path(global_dict[\"stage1_dir\"])\nstage1_dir.mkdir(exist_ok=True)\nstage1_net = Stage1Net(pretrained=False)\nstage1_net = load_net(stage1_net, '/kaggle/input/hengck23-submit-physionet/hengck23-submit-physionet/weight/stage1-last.checkpoint.pth')\nstage1_net.to(\"cuda:0\")\n\nfor n, sample_id in enumerate(tqdm(valid_id)):\n    path = stage0_dir / f'{sample_id}.png'\n    output_path = stage1_dir / f'{sample_id}.png'\n    image = cv2.imread(str(path), cv2.IMREAD_COLOR) # Corrected imread\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Explicit BGR to RGB conversion\n    batch = {'image': torch.from_numpy(np.ascontiguousarray(image.transpose(2, 0, 1))).unsqueeze(0)}\n    try:\n        with torch.no_grad(), torch.amp.autocast('cuda', dtype=torch.float32):\n            output = stage1_net(batch)\n        gridpoint_xy, _ = output_to_predict(image, batch, output)\n        rectified = rectify_image(image, gridpoint_xy)\n        cv2.imwrite(output_path, cv2.cvtColor(rectified, cv2.COLOR_RGB2BGR))\n    except:\n        traceback.print_exc()\n        copyfile(path, output_path)\n\n# --- Stage 2: Signal Extraction ---\nimport torchvision.transforms as T\nfrom stage2_model import *\nfrom stage2_common import *\nfrom scipy.signal import savgol_filter, medfilt\n\nclass Net3(torch.nn.Module):\n    \"\"\"Custom U-Net based model for signal extraction from rectified ECG images.\"\"\"\n    def __init__(self, pretrained=True):\n        super(Net3, self).__init__()\n        encoder_dim = [64, 128, 256, 512]\n        decoder_dim = [128, 64, 32, 16]\n        self.encoder = timm.create_model(\n            model_name='resnet34.a3_in1k', pretrained=pretrained, in_chans=3, num_classes=0, global_pool=''\n        )\n        self.decoder = MyCoordUnetDecoder(\n            in_channel=encoder_dim[-1],\n            skip_channel=encoder_dim[:-1][::-1] + [0],\n            out_channel=decoder_dim,\n            scale=[2, 2, 2, 2]\n        )\n        self.pixel = torch.nn.Conv2d(decoder_dim[-1], 4, 1)\n    def forward(self, image):\n        encode = encode_with_resnet(self.encoder, image)\n        last, _ = self.decoder(feature=encode[-1], skip=encode[:-1][::-1] + [None])\n        pixel = self.pixel(last)\n        return pixel\n\nstage1_dir = Path(global_dict[\"stage1_dir\"])\nstage2_dir = Path(global_dict[\"stage2_dir\"])\nstage2_dir.mkdir(exist_ok=True)\nstage2_net = Net3(pretrained=False).to(\"cuda:0\")\nmodel_path = \"/kaggle/input/physio-seg-public/pytorch/net3_009_4200/1/iter_0004200.pt\"\nstage2_net.load_state_dict(torch.load(model_path))\nstage2_net.eval()\n\nx0, x1 = 0, 2176\ny0, y1 = 0, 1696\nzero_mv = [703.5, 987.5, 1271.5, 1531.5]\nmv_to_pixel = 78.5\nt0, t1 = 235, 4161\nresize = T.Resize((1696, 4352), interpolation=T.InterpolationMode.BILINEAR)\n\nfor n, sample_id in enumerate(tqdm(valid_id)):\n    path = stage1_dir / f'{sample_id}.png'\n    output_path = stage2_dir / f'{sample_id}.npy'\n    image = cv2.imread(str(path), cv2.IMREAD_COLOR) # Corrected imread\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Explicit BGR to RGB conversion\n    length = valid_df[(valid_df['id']==sample_id) & (valid_df['lead']=='II')].iloc[0].number_of_rows\n    image = image[y0:y1, x0:x1] / 255\n    batch = resize(torch.from_numpy(np.ascontiguousarray(image.transpose(2, 0, 1))).unsqueeze(0)).float().to(\"cuda:0\")\n    try:\n        with torch.no_grad(), torch.amp.autocast('cuda', dtype=torch.float32):\n            output = stage2_net(batch)\n        pixel = torch.sigmoid(output).float().data.cpu().numpy()[0]\n        series_in_pixel = pixel_to_series(pixel[..., t0:t1], zero_mv, length)\n        series = (np.array(zero_mv).reshape(4, 1) - series_in_pixel) / mv_to_pixel\n        for i in range(series.shape[0]):\n            if i==3:\n                series[i] = savgol_filter(series[i], window_length=9, polyorder=2)\n            else:\n                series[i] = savgol_filter(series[i], window_length=5, polyorder=2)\n        np.save(output_path, series)\n    except:\n        traceback.print_exc()\n        series = np.zeros((4, length)) \n        np.save(output_path, series)\n\n# --- Helper: Series Dictionary ---\n# Converts extracted series into a dictionary by lead name.\ndef series_dict(series):\n    d = {}\n    for l in range(3):\n        lead_names = [\n            ['I',   'aVR', 'V1', 'V4'],\n            ['II',  'aVL', 'V2', 'V5'],\n            ['III', 'aVF', 'V3', 'V6'],\n        ][l]\n        split = np.array_split(series[l], 4)\n        for (k, s) in zip(lead_names, split):\n            d[k] = s\n    d['II'] = series[3]\n    return d\n\n# --- Submission File Creation ---\nstage2_dir = Path(global_dict[\"stage2_dir\"])\nres = []\ngb = valid_df.groupby('id')\nfor i, (sample_id, df) in enumerate(tqdm(gb)):\n    series = np.load(stage2_dir / f'{sample_id}.npy')\n    d_series = series_dict(series)\n    for _, d in df.iterrows():\n        s = d_series.get(d.lead, np.zeros(d.number_of_rows))\n        if len(s) != d.number_of_rows:\n            x_old = np.linspace(0, 1, len(s))\n            x_new = np.linspace(0, 1, d.number_of_rows)\n            # s = np.interp(x_new, x_old, s)\n            try:\n                cs = CubicSpline(x_old, s)\n                s = cs(x_new)\n            except:\n                s = np.interp(x_new, x_old, s)\n        row_id = [f'{sample_id}_{x}_{d.lead}' for x in range(d.number_of_rows)]\n        res.append(pd.DataFrame({'id': row_id, 'value': s}))\n    if i % 100 == 0:\n        gc.collect()\nsubmission = pd.concat(res, axis=0, ignore_index=True)\nsubmission.to_csv('submission.csv', index=False)\nsubmission.head(30)","metadata":{"execution":{"iopub.status.busy":"2025-12-26T16:44:11.400161Z","iopub.execute_input":"2025-12-26T16:44:11.400496Z","iopub.status.idle":"2025-12-26T16:46:02.911719Z","shell.execute_reply.started":"2025-12-26T16:44:11.400476Z","shell.execute_reply":"2025-12-26T16:46:02.910954Z"},"papermill":{"duration":130.998273,"end_time":"2025-12-25T04:36:55.658418","exception":false,"start_time":"2025-12-25T04:34:44.660145","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---\n\n## Additional Information\n\n- **Author:** Adapted for the PhysioNet ECG Image Digitization Challenge by the community.\n- **Requirements:** Kaggle environment, CUDA-enabled GPU, all referenced input datasets and model weights.\n- **References:**\n    - [PhysioNet Challenge 2024](https://physionetchallenges.org/2024/)\n    - [Kaggle competition page](https://www.kaggle.com/competitions/physionet-ecg-image-digitization)\n    - [Connected Components 3D](https://github.com/seung-lab/connected-components-3d)\n    - [PyTorch](https://pytorch.org/)\n    - [OpenCV](https://opencv.org/)\n    - [scipy.signal](https://docs.scipy.org/doc/scipy/reference/signal.html)\n\n- **Contact:** For questions or issues, please refer to the competition discussion forums or the official PhysioNet Challenge contact.\n\n---\n\n## How to Use This Notebook\n\n1. **Set up the Kaggle environment** with all required datasets and model weights in the specified input paths.\n2. **Run all cells in order**. The pipeline will process the test images and generate a submission file.\n3. **Check outputs and logs** for any errors or warnings. The notebook includes robust error handling and will fall back to default outputs if a stage fails.\n4. **Submit the generated CSV** to the competition platform.\n\n**Tip:** For best results, ensure all input paths and dependencies are available in your environment before running the notebook.\n\n---\n\n## Acknowledgements\n\nSpecial thanks to the PhysioNet Challenge organizers, the Kaggle community, and open-source contributors for providing resources and support.","metadata":{"papermill":{"duration":0.010315,"end_time":"2025-12-25T04:36:55.682761","exception":false,"start_time":"2025-12-25T04:36:55.672446","status":"completed"},"tags":[]}}]}