From d6e252ec10f5fc6e1eae43c61e660ade0d47d3e9 Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 08:38:53 +0100 Subject: [PATCH 1/9] fix: update runner.sh and endoscopic notebook for MONAI 1.6 compatibility Add msd_crossval_datalist_generator.ipynb and hovernet_infer_compare.ipynb to doesnt_contain_max_epochs (inference/datalist notebooks with no training loop). Skip image_restoration.ipynb until monai.networks.nets.Restormer is merged into the dev branch. Fix endoscopic_inbody_classification notebook: pass return_state_dict=False to monai.bundle.load so it returns an nn.Module rather than a raw OrderedDict, which caused AttributeError on .train() with MONAI 1.6 API. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: R. Garcia-Dias --- .../endoscopic_inbody_classification.ipynb | 102 +----------------- runner.sh | 3 + 2 files changed, 7 insertions(+), 98 deletions(-) diff --git a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb index fb97c7f47..fc0a0e930 100644 --- a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb +++ b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb @@ -343,105 +343,11 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "4784fe9e", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "name endoscopic_inbody_classification\n", - "version None\n", - "bundle_dir .\n", - "source github\n", - "repo None\n", - "url None\n", - "remove_prefix monai_\n", - "progress True\n", - "2023-09-07 12:17:23,537 - INFO - --- input summary of monai.bundle.scripts.download ---\n", - "2023-09-07 12:17:23,539 - INFO - > name: 'endoscopic_inbody_classification'\n", - "2023-09-07 12:17:23,540 - INFO - > bundle_dir: PosixPath('.')\n", - "2023-09-07 12:17:23,540 - INFO - > source: 'github'\n", - "2023-09-07 12:17:23,541 - INFO - > remove_prefix: 'monai_'\n", - "2023-09-07 12:17:23,542 - INFO - > progress: True\n", - "2023-09-07 12:17:23,542 - INFO - ---\n", - "\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "endoscopic_inbody_classification_v0.4.4.zip: 185MB [00:09, 21.4MB/s] \n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-09-07 12:17:33,469 - INFO - Downloaded: endoscopic_inbody_classification_v0.4.4.zip\n", - "2023-09-07 12:17:33,469 - INFO - Expected md5 is None, skip md5 check for file endoscopic_inbody_classification_v0.4.4.zip.\n", - "2023-09-07 12:17:33,470 - INFO - Writing into directory: ..\n", - "workflow_name None\n", - "config_file endoscopic_inbody_classification/configs/train.json\n", - "workflow_type train\n", - "2023-09-07 12:17:34,468 - INFO - --- input summary of monai.bundle.scripts.run ---\n", - "2023-09-07 12:17:34,468 - INFO - > config_file: 'endoscopic_inbody_classification/configs/train.json'\n", - "2023-09-07 12:17:34,469 - INFO - > workflow_type: 'train'\n", - "2023-09-07 12:17:34,469 - INFO - ---\n", - "\n", - "\n", - "2023-09-07 12:17:34,470 - INFO - Setting logging properties based on config: endoscopic_inbody_classification/configs/logging.conf.\n", - "2023-09-07 12:17:34,701 - INFO - 'dst' model updated: 384 of 384 variables.\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 5/5 [00:02<00:00, 2.25it/s]\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgQAAAINCAYAAABBDWdeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAABiuklEQVR4nO3deXxU9bk/8M+ZPetkIyuBJOxr2EMSWawoIqXSarXqFcQVihbk19srt1W07ZX2Xqt2QUEUl1rFpUqtC0ipCELYAmERRMgOZCHbTNaZZOb8/kjOkGACmWRmzjkzn/frNa+XDGcyz2EMefh+n+/zCKIoiiAiIqKAppE7ACIiIpIfEwIiIiJiQkBERERMCIiIiAhMCIiIiAhMCIiIiAhMCIiIiAhMCIiIiAiATu4AesPpdOLChQsICwuDIAhyh0NERKQaoiiivr4eiYmJ0Gh6XgdQRUJw4cIFJCcnyx0GERGRapWWlmLgwIE9/r4qEoKwsDAA7TcTHh4uczRERETqYbVakZyc7PpZ2hNVJATSNkF4eDgTAiIioj642pY7iwqJiIiICQERERExISAiIiKopIaAiIgCjyiKaGtrg8PhkDsURdNqtdDpdP0+ls+EgIiIFMdut6OsrAxNTU1yh6IKwcHBSEhIgMFg6PPXYEJARESK4nQ6UVhYCK1Wi8TERBgMBjal64EoirDb7bh48SIKCwsxbNiwKzYfuhImBEREpCh2ux1OpxPJyckIDg6WOxzFCwoKgl6vR3FxMex2O0wmU5++DosKiYhIkfr6L91A5Ik/K/5pExERERMCIiIiYkJARETkMbNnz8bKlSvlDqNPmBAQEREREwIiIiJiQkBERCogiiKa7G0+f4ii2OeYa2trsWjRIkRGRiI4OBjz5s3DmTNnXL9fXFyMBQsWIDIyEiEhIRgzZgw+/fRT12vvuusuDBgwAEFBQRg2bBheffXVfv85Xgn7EBARkeI1tzow+oltPn/fk7+ei2BD335U3nPPPThz5gw++ugjhIeH47/+679w00034eTJk9Dr9Vi+fDnsdjt27dqFkJAQnDx5EqGhoQCAxx9/HCdPnsRnn32GmJgYnD17Fs3NzZ68te9gQkBERORhUiKwZ88eZGVlAQD+9re/ITk5GVu2bMGPf/xjlJSU4JZbbsG4ceMAAGlpaa7Xl5SUYOLEiZgyZQoAICUlxesxMyEgIgoARVWNCDZoERvety52cgvSa3Hy13Nled++OHXqFHQ6HTIyMlzPRUdHY8SIETh16hQA4Gc/+xmWLVuGzz//HHPmzMEtt9yC8ePHAwCWLVuGW265BYcPH8YNN9yAhQsXuhILb2ENARGRn6uwtmDeH3fjxxty4HT2fU9cToIgINig8/nDmzMU7r//fhQUFODuu+/G8ePHMWXKFPz5z38GAMybNw/FxcV49NFHceHCBVx33XX4+c9/7rVYACYERER+76szVWhudaC4ugnflNfLHU5AGDVqFNra2rB//37Xc9XV1Th9+jRGjx7tei45ORlLly7FBx98gP/3//4fNm7c6Pq9AQMGYPHixXjzzTfx/PPP46WXXvJqzNwyICLyczkF1a7/3ptfhdGJ4TJGExiGDRuGm2++GQ888AA2bNiAsLAwPPbYY0hKSsLNN98MAFi5ciXmzZuH4cOHo7a2Fl988QVGjRoFAHjiiScwefJkjBkzBjabDR9//LHr97yFKwRERH5uX6eEYM/ZKhkjCSyvvvoqJk+ejO9///vIzMyEKIr49NNPodfrAQAOhwPLly/HqFGjcOONN2L48OF44YUXAAAGgwGrV6/G+PHjMXPmTGi1WmzevNmr8Qpifw5Z+ojVaoXZbIbFYkF4ODNbIqLeKq1pwoz//cL16xCDFnlrboBeq9x/D7a0tKCwsBCpqal9HuUbaK70Z9bbn6HK/T+CiIj6TVodSE+OQFSIAY12B46W1skbFCkSEwIiIj+2r6AGAJA1JBqZadEAgD1nq6/0EgpQTAiIiPyUKIquFYLMtGhkDe1ICPJZR0DfxVMGRER+6lxtM87XNUOnETB5cCQGRQUDAI6U1KLJ3tbnlrzkn7hCQETkp3I61Q+EGHUYHB2MpIggtDpEHCyqlTm6q1NBzbtieOLPigkBEZGf2pffnhBMT4sC0N7tL2tI+7bBXgUfP5SO5TU1NckciXpIf1bSn11fuL1etGvXLvzf//0fcnNzUVZWhg8//BALFy7s1Wv37NmDWbNmYezYscjLy3P3rYmIqJe61g/EuJ7PHhqD93LPKbqOQKvVIiIiApWVlQCA4OBgr7YQVjNRFNHU1ITKykpERERAq+3b7AWgDwlBY2Mj0tPTce+99+JHP/pRr19XV1eHRYsW4brrrkNFRYW7b0tERG4oqWnCBUsL9FoBkwZHuJ6XVgi+vmBFXZMdEcEGmSK8svj4eABwJQV0ZREREa4/s75yOyGYN28e5s2b5/YbLV26FHfeeSe0Wi22bNni9uuJiKj3XP0HBkZ0KR6MDTdhWGwozlQ2ICe/GvPGJcgV4hUJgoCEhATExsaitbVV7nAUTa/X92tlQOKTEtNXX30VBQUFePPNN/Hb3/72qtfbbDbYbDbXr61WqzfDIyLyOzkd9QOZHSsCnWUPjcGZygbsya9SbEIg0Wq1HvlhR1fn9aLCM2fO4LHHHsObb74Jna53+cfatWthNptdj+TkZC9HSUTkP9rrB9obEk1P+25CcKmwkA2K6BKvJgQOhwN33nknnnrqKQwfPrzXr1u9ejUsFovrUVpa6sUoiYj8S3F1E8qtLTBoNZg0KPI7v5+RFg2NABRUNaLM0ixDhKREXt0yqK+vx6FDh3DkyBE8/PDDAACn0wlRFKHT6fD555/je9/73ndeZzQaYTQavRkaEZHfkvoPTEiOQJDhu8vt5iA9xg2MwNHSOuw5W41bJw/0dYikQF5NCMLDw3H8+PEuz73wwgv497//jffffx+pqanefHsiooAkFRRK/Qe6kz0kGkdL67D3bBUTAgLQh4SgoaEBZ8+edf26sLAQeXl5iIqKwqBBg7B69WqcP38eb7zxBjQaDcaOHdvl9bGxsTCZTN95noiI+k8URVdB4fRuCgol2UNj8MLOfOzJr4IoijznT+7XEBw6dAgTJ07ExIkTAQCrVq3CxIkT8cQTTwAAysrKUFJS4tkoiYioVwqrGlFZb+uxfkAyeXAkDDoNKqw25F9s9GGEpFRurxDMnj37ij2TX3vttSu+/sknn8STTz7p7tsSEVEvSKcLJg6KgEnf83E9k16LKYMjsTe/GnvzqzA0NtRXIZJCcZYBEZEfyXHVD/S8XSDJHtre0niPgucakO8wISAi8hNd5hdcoX5AIvUjyMmvhsPJyYKBjgkBEZGfyL/YiIv1Nhh0GkxIjrjq9eOSzAgz6mBtacPXFyzeD5AUjQkBEZGfkFYHJl2lfkCi02qQ0bG1sIddCwMeEwIiIj+R082446vJHtrRxljB45DJN5gQEBH5AVEUsb8XDYkuJxUWHiyqga3N4ZXYSB2YEBAR+YH8iw2oarDDqNNgwqCIXr9uWGwoBoQZ0dLqxOHiOq/FR8rHhICIyA9I3QknD46EUdf7ccGCIFyafshtg4DGhICIyA9cadzx1WQPYT8CYkJARKR67vYfuFxWR2Hh0XMW1Le0ejQ2Ug8mBEREKnemsgHVjXaY9BqMH2h2+/UDI4MxODoYDqeIA4U1XoiQ1IAJARGRykmrA1MGR7lVP9BZlmvbgP0IAhUTAiIilXONO3bjuOHl2I+AmBAQEamY0ylif8cyf1/qBySZHcWI35TXo6rB5pHYSF2YEBARqdi3lfWoabQjSK/FuKSIPn+d6FAjRiWEAwD25nPbIBAxISAiUrF9HT+8p6REwqDr31/p2VI/Ah4/DEhMCIiIVCzH1a6479sFEqmN8R7WEQQkJgRERCrVuX7AEwnBtNQo6DQCSmuaUVrT1O+vR+rChICISKVOV9SjrqkVwQZtn/oPXC7EqMOE5AgA7FoYiJgQEBGpVI6rfiAKeq1n/jrPcm0bsLAw0DAhICJSKVe7Yg9sF0ikwsKc/CqIouixr0vKx4SAiEiFutYP9L0h0eUmDopEkF6LqgY7TlfUe+zrkvIxISAiUqFT5VZYmlsRYtBibFL/6wckBp0GU1PbEwy2MQ4sTAiIiFRIGnc8NdVz9QMS9iMITEwIiIhU6NL8As/VD0ikfgT7C2vQ5nB6/OuTMjEhICJSmfYxxZ4vKJSMTghHRLAeDbY2HD1n8fjXJ2ViQkBEpDKnyqywtrQh1KjDmMRwj399jUZwJRrcNggcTAiIiFRGOm44NSUSOg/XD0iy2MY44DAhICJSGal+oD/jjq9GKiw8XFyHZrvDa+9DysGEgIhIRdrrBzw3v6AnqTEhSDCbYHc4cai4xmvvQ8rBhICISEVOXrCi3taGMKMOYxI913/gcoIgIGtIx7YB+xEEBCYEREQqklPQvqc/LTUKWo3g1ffKHtpRWMg6goDAhICISEWkhkTerB+QSP0Ijp+3wNLU6vX3I3kxISAiUok2h9Mn9QOSuHAThgwIgSgCOQXcNvB3TAiIiFTi6wtWNNjaEG7SYVSC5/sPdEdaJeC2gf9jQkBEpBJS/4FpqdFerx+QXCosZELg75gQEBGphLRs78lxx1eTmRYNjQDkX2xEuaXFZ+9LvseEgIhIBdocThws9F1BocQcrHeNV+a2gX9jQkBEpALHz1vQaHfAHKTHqHjf1A9I2I8gMDAhICJSAem44bTUKGh8VD8g6dyPQBRFn743+Q4TAiIiFZDqB7wx7vhqpgyOgkGrQZmlBYVVjT5/f/INJgRERArX6nDiUJHv+g9cLsigxaTBEQCAPfncNvBXTAiIiBTu+HkLmuwORATrMTI+TJYYsjvqCPby+KHfYkJARKRw0rjjDBnqByRZHQ2Kcgqq4XSyjsAfMSEgIlK4fTLWD0jSB5oRatShrqkVJ8usssVB3sOEgIhIwextThwqqgUATPdh/4HL6bQaZKS2N0Ri10L/xISAiEjBjp+vQ3OrA5HBegyPlad+QCJtG7Cw0D+5nRDs2rULCxYsQGJiIgRBwJYtW654/QcffIDrr78eAwYMQHh4ODIzM7Ft27a+xktEFFCk/gPT06Jlqx+QSP0IDhbWwN7mlDUW8jy3E4LGxkakp6dj3bp1vbp+165duP766/Hpp58iNzcX1157LRYsWIAjR464HSwRUaCRCgrlOG54uRFxYYgJNaC51YEjJbVyh0MepnP3BfPmzcO8efN6ff3zzz/f5ddPP/00/vGPf+Cf//wnJk6c6O7bExEFDHubE4eKfT+/oCeCICBzSAz+efQC9uRXI0MBSQp5js9rCJxOJ+rr6xEV5btpXUREanT0XB1aWp2ICjFgWGyo3OEAALI7EhP2I/A/bq8Q9NczzzyDhoYG3HbbbT1eY7PZYLPZXL+2WnnEhYgCz778S+OOBUHe+gFJdkdhYV5pHRptbQgx+vzHCHmJT1cI3nrrLTz11FN49913ERsb2+N1a9euhdlsdj2Sk5N9GCURkTLIOb+gJ8lRwUiOCkKbU8SBjnHM5B98lhBs3rwZ999/P959913MmTPniteuXr0aFovF9SgtLfVRlEREymBrcyC3uKP/gIISAuBSG2P2I/AvPkkI3n77bSxZsgRvv/025s+ff9XrjUYjwsPDuzyIiALJ0VILbG1OxIQaMFQh9QMS9iPwT25v/jQ0NODs2bOuXxcWFiIvLw9RUVEYNGgQVq9ejfPnz+ONN94A0L5NsHjxYvzxj39ERkYGysvLAQBBQUEwm80eug0iIv/iml+QFq2Y+gFJVkdh4akyK6obbIgONcocEXmC2ysEhw4dwsSJE11HBletWoWJEyfiiSeeAACUlZWhpKTEdf1LL72EtrY2LF++HAkJCa7HihUrPHQLRET+RwnzC3oSE2p0TV2U6hxI/dxeIZg9ezZEsedJV6+99lqXX+/cudPdtyAiCmgtrQ7kliizfkCSNSQG35TXY8/Zanx/fKLc4ZAHcJYBEZHC5JXWwd7mxIAwI4YMCJE7nG5JbYz35rOw0F8wISAiUhhpu2C6AusHJNNSo6DVCCiubsK52ia5wyEPYEJARKQwOZ0aEilVmEmP9IHtheF7z7KOwB8wISAiUpCWVgeOlNYBUGZBYWfZruOH3DbwB0wIiIgU5HBJLextTsSGGZEao8z6AUlWR4OivfnVVyw2J3VgQkBEpCD7CtrbASu5fkAyaXAETHoNLtbbcKayQe5wqJ+YEBARKYg00EgJ446vxqjTYmpKe50D2xirHxMCIiKFaLY7kNdRP6DU/gOXy3LNNWBhodoxISAiUogjJbWwO5yIDzchJTpY7nB6RepHsL+gGm0Op8zRUH8wISAiUoicgkvHDZVePyAZk2hGuEmHelsbjp+3yB0O9QMTAiIihXDNL1BB/YBEqxFc8e7l9ENVY0JARKQAaqwfkLj6EbCwUNWYEBARKUBucS1aHSISzCYMilJH/YBEKiw8VFyLllaHzNFQXzEhICJSgM7jjtVSPyAZMiAEceFG2NucyC2ulTsc6iMmBERECpDTaaCR2giCgOwh3DZQOyYEREQya7K34ag0v0BFBYWdZbnmGrCwUK2YEBARyexQUS3anCKSIoIwMDJI7nD6ROpHcPxcHSzNrTJHQ33BhICISGb7Om0XqK1+QJJgDkJaTAicYnuTIlIfJgRERDLr3JBIzbKGsh+BmjEhICKSUaOtDcfOtXf4U2NBYWcsLFQ3JgRERDI6VFwLh1PEwMggJKus/8DlModEQxCAM5UNqLS2yB0OuYkJARGRjHLy1Xvc8HIRwQaMSQwHwG0DNWJCQEQko84NifwBtw3UiwkBEZFMGjpNCMxQeUGhROpHsDe/GqIoyhwNuYMJARGRTA4W1cDhFJEcFYSBkequH5BMTYmEXivgfF0ziqub5A6H3MCEgIhIJv62XQAAwQYdJg6KBADsyee2gZowISAiksk+Pyoo7EyqI9h7loWFasKEgIhIBvUtra76Ab9LCFwNiqrgdLKOQC2YEBARyeBgUQ2cIjA4OhiJEeqcX9CT9OQIhBi0qG1qxalyq9zhUC8xISAiksG+ghoA/lU/INFrNZiW2n5qgtsG6sGEgIhIBv7UkKg72a5xyCwsVAsmBEREPmZpbsXXF/yzfkCS1VFYeKCwBvY2p8zRUG8wISAi8rFDHfUDqTEhiDeb5A7HK0bGhyEqxIAmuwNHz9XJHQ71AhMCIiIfu7Rd4B/dCbuj0QjIHNK++sE2xurAhICIyMf2Ffp3/YCE/QjUhQkBEZEPWZpa8fWF9qN4fp8QdPQjOFJaiyZ7m8zR0NUwISAi8qEDRTUQRSAtJgRx4f5ZPyAZFBWMpIggtDpEHCiskTscugomBEREPiTNL5g+xL9XBwBAEIROXQu5baB0AZsQOJ0iLE2tcodBRAHG3/sPXM7Vj4CFhYoXkAlBbnEtbvzjLjz6bp7coRBRAKlrsrta+frzCYPOpJMGJ8usqG20yxwNXUlAJgRRIQacqWzAv7+pxOnyernDIaIAsb+wvX5gyIAQxIb5d/2AJDbMhOFxoRBFIKeA2wZKFpAJQWpMCOaNjQcAbPgyX+ZoiChQSPUDmQFQP9CZ1LWQ2wbKFpAJAQAsnTUEAPDR0Qs4X9csczREFAgCrX5AItURsLBQ2QI2IRg/MAJZQ6LR5hTx8u4CucMhIj9X22jHNx1blBmpgZUQZKRFQSMAhVWNuMB/gClWwCYEwKVVgs0HSlnsQkRetb/jHP6w2FAMCDPKHI1vhZv0GD8wAgC3DZQsoBOCGcNiMCYxHM2tDvx1X7Hc4RCRH3P1Hwiw7QIJ+xEoX0AnBIIg4KGOVYLX9hah2e6QOSIi8leBWlAoye5UWCiKoszRUHcCOiEAgJvGxiM5Kgg1jXa8l1sqdzhE5IeqG2yu+oFpqYHRf+BykwZHwqjToLLehvyLDXKHQ91wOyHYtWsXFixYgMTERAiCgC1btlz1NTt37sSkSZNgNBoxdOhQvPbaa30I1Tt0Wg0enJEGAHhpVwHaHE6ZIyIifyP18R8eF4qY0MCqH5CY9FpMSYkEAOzh9ENFcjshaGxsRHp6OtatW9er6wsLCzF//nxce+21yMvLw8qVK3H//fdj27ZtbgfrLT+ekozoEAPO1Tbjk+NlcodDRH7GtV0QoPUDEvYjUDa3E4J58+bht7/9LX74wx/26vr169cjNTUVf/jDHzBq1Cg8/PDDuPXWW/Hcc8+5Hay3mPRaLM5KAQCs/7KA+1tE5FE5AV5QKJH6EewrqIbDyb9nlcbrNQQ5OTmYM2dOl+fmzp2LnJycHl9js9lgtVq7PLxtUeZgBBu0OFVmxa4zzF6JyDOqGmz4tqJ9zzwjwBOCcUlmhJl0sLa04cR5i9zh0GW8nhCUl5cjLi6uy3NxcXGwWq1obu6+QcXatWthNptdj+TkZG+HiYhgA34ydRAAYP1OtjMmIs/YX9BePzAyPgxRIQaZo5GXViO4Vkn25PMfXkqjyFMGq1evhsVicT1KS31T/X//jFToNAJyCqpxtLTOJ+9JRP4t0PsPXC6749jlXhYWKo7XE4L4+HhUVFR0ea6iogLh4eEICgrq9jVGoxHh4eFdHr6QGBGEH0xIBACs59AjIvIA1g90JdURHCyqQUsre78oidcTgszMTOzYsaPLc9u3b0dmZqa337pPpHbGW78uRwHPyhJRP1yst+FsZQMEAcgI0P4DlxsaG4rYMCNsbU4cLqmVOxzqxO2EoKGhAXl5ecjLywPQfqwwLy8PJSUlANqX+xctWuS6funSpSgoKMAvfvELfPPNN3jhhRfw7rvv4tFHH/XMHXjY8LgwXDcyFqIIbOTQIyLqh/2F7asDI+PDERng9QMSQRCQxW0DRXI7ITh06BAmTpyIiRMnAgBWrVqFiRMn4oknngAAlJWVuZIDAEhNTcUnn3yC7du3Iz09HX/4wx/w8ssvY+7cuR66Bc9bOrt9leDvuedRWd8iczREpFaXxh1zdaCzrI5tAxYWKovO3RfMnj37iuf0u+tCOHv2bBw5csTdt5LN1JQoTB4cidziWry6pwj/deNIuUMiIhViQ6LuSXUEx85ZUN/SijCTXuaICFDoKQMlkGoJ3txXjPqWVpmjISK1qbS2IP9iIwQhcOcX9CQpIggp0cFwOEXXsUySHxOCHlw3MhbDYkNR39KGt/aXXP0FRESd7OuYXzAqPhwRwawfuBy3DZSHCUEPNBoBD85sH3r0yleFsLXxeAwR9V6gjzu+GmkcMgsLlYMJwRXcPCEJ8eEmVNbbsOXIebnDISIV2ZfP/gNXIiVKpyvqcbHeJnM0BDAhuCKDToP7rkkFAGzYVQAnh3EQUS9UWFtQUMX6gSuJCjFgdEJ707m93DZQBCYEV3FHxiCEm3QouNiIz09WXP0FRBTwpO2CMYnhMAexgr4n2UPZj0BJmBBcRahRh7szBwNob2fM0chEdDU8btg7LCxUFiYEvXBPVioMOg3ySuuwv5BHZIjoynJYP9Ar01KioNMIOFfbjJLqJrnDCXhMCHphQJgRP548EACHHhHRlZVZmlFU3QSNAExl/cAVhRh1mDgoAgBXCZSACUEvPTgzDRoB2Hn6Ik6VWeUOh4gUSmq0MzbJjHB24LuqrI7jh3vOMiGQGxOCXhocHYJ54xIAABu4SkBEPeB2gXukNsY5+dU8ySUzJgRuWNbRzvifx8pwrpb7XUT0XfsKWVDojgnJEQjSa1HdaMfpinq5wwloTAjcMDbJjGuGxsDhFPHy7kK5wyEihblQ14zi6iZoNQKmpETKHY4qGHQaV68GbhvIiwmBm6ShR+8cLEVto13maIhISaTjhmOTzJzg5wZXP4J89iOQExMCN2UPjcbYpHA0tzrwek6R3OEQkYJICcH0NJ4ucIdUWLi/oBqtDqfM0QQuJgRuEgTBtUrw+t4iNNnbZI6IiJQip4AFhX0xOiEckcF6NNodOHauTu5wAhYTgj64cUw8BkUFo7apFe8eLJU7HCJSgHO1TSitaYZWI2BqClcI3KHRCK5hR3vYxlg2TAj6QKfV4IGO0cgbdxdyiYuIsK+j/8C4JDNCjTqZo1Ef9iOQHxOCPvrx5IGICTXgfF0zPjlWJnc4RCQz1/yCIdwu6AupH8GRkjo02x0yRxOYmBD0kUmvxT1ZKQA49IiI2JCov1Kig5FoNsHucOJgEWfGyIEJQT/cPT0FIQYtvimvx85vL8odDhHJpLSmCefrmqHTCJgymP0H+kIQBE4/lBkTgn4wB+txx7RBAID1O9nOmChQSdsF4weaEcL6gT5z9SNgYaEsmBD0030zUqHXCthfWIMjJbVyh0NEMuBxQ8+QCgtPXLCgromN33yNCUE/JZiDcPOEJAAcjUwUiERRdE04ZEFh/8SFmzA0NhSieGnVhXyHCYEHLJ3VfgTx85MVyL/YIHM0RORLpTXNOF/XDL1WwGTWD/RbNvsRyIYJgQcMjQ3DnFFxEEVg464CucMhIh+S/iWbPjACwQbWD/QXCwvlw4TAQ5bNbl8l+ODweVRaW2SOhoh8ZR/rBzxqelo0NAJQcLER5Rb+XepLTAg8ZPLgKExNiYTd4cQrezgamSgQiKLIgkIPMwfpMS7JDIBdC32NCYEHPTSzfejRW/tKYG1plTkaIvK2kpomlFlaWD/gYdw2kAcTAg/63shYDIsNRb2tDX/bVyJ3OETkZVJ3wgnJEQgyaGWOxn9kdxw/3Hu2ml1gfYgJgQdpNAIe6hiNvGlPIVpa2Y+byJ+55hdwu8CjpqREwqDToNzagoKqRrnDCRhMCDzsB+mJSDCbcLHehg+PnJc7HCLyElEUXRMOWT/gWSa9FpMHtW/B7GUdgc8wIfAwg06D+65JBQC8tKsADieXu4j8UVF1E8qtLTBoNZjE+gGPk9oYsx+B7zAh8II7pg2COUiPwqpGfP51udzhEJEXSNsFEwZFwKRn/YCnSYWFOQXV/IeVjzAh8IIQow6LMgcD4GhkIn/FccfeNT7JjDCjDpbmVpy8YJU7nIDAhMBLFmelwKjT4Og5i+ucMhH5h/b6ARYUepNOq0FGWhQAHj/0FSYEXhITasRtU5IBAOu/ZDtjIn9SUNWIynobDDoNJg6KkDscvyVNP2SDIt9gQuBFD8xIg0YAdn17EV9fsMgdDhF5iLQ6MIn1A16V3VFHcLCoBrY2HuP2NiYEXjQoOhjzxycCaD9xQET+gccNfWN4XChiQo1oaXXiSEmd3OH4PSYEXvbQzPahRx8fK0NpTZPM0RBRf4miyIJCHxEEAVkd45DZj8D7mBB42dgkM2YMi4HDKeLl3VwlIFK7/IuNqGqwwajTYEJyhNzh+D1XP4J8Fmd7GxMCH1ja0c74nUOlqG6wyRwNEfVHjqt+IJL1Az4gFRYeLa1Dg61N5mj8GxMCH8gaEo1xSWa0tDrxek6x3OEQUT+4jhsO4XaBLyRHBWNQVDDanCIOFHKVwJuYEPiAIAiuVYI3corQZGeWS6RGoihifwHrB3yNbYx9gwmBj9w4Nh4p0cGoa2rF5gOlcodDRH1wtrIBVQ12GHUapCeb5Q4nYLAfgW8wIfARrUbAAx0nDl75qhCtDqfMERGRu6TtgikpkTDqWD/gK9JJg2/K61HFOiyvYULgQ7dMGoiYUCPO1zXjn0cvyB0OEblJKiicnsrtAl+KDjViZHwYgEszJMjz+pQQrFu3DikpKTCZTMjIyMCBAweueP3zzz+PESNGICgoCMnJyXj00UfR0tLSp4DVzKTXYkl2CgBgw5cFHHpEpCLt8wvaGxKxoND3pK6FeznXwGvcTgjeeecdrFq1CmvWrMHhw4eRnp6OuXPnorKystvr33rrLTz22GNYs2YNTp06hVdeeQXvvPMO/vu//7vfwavRf0wfjFCjDqcr6vHF6e7/zIhIeb6taEBNox1Bei3GD4yQO5yAw8JC73M7IXj22WfxwAMPYMmSJRg9ejTWr1+P4OBgbNq0qdvr9+7di+zsbNx5551ISUnBDTfcgDvuuOOqqwr+yhykx50ZgwAA63eyURGRWnSuHzDouNvqa9NSo6HTCCipaWLXVy9x6/9qu92O3NxczJkz59IX0GgwZ84c5OTkdPuarKws5ObmuhKAgoICfPrpp7jpppt6fB+bzQar1drl4U/uzU6FXivgQFENcotr5Q6HiHphH48byirUqEN6R2dIbht4h1sJQVVVFRwOB+Li4ro8HxcXh/Ly8m5fc+edd+LXv/41rrnmGuj1egwZMgSzZ8++4pbB2rVrYTabXY/k5GR3wlS8eLMJP5yYBADY8GW+zNEQ0dU4nWKnhCBK5mgCV/YQbht4k9fXvXbu3Imnn34aL7zwAg4fPowPPvgAn3zyCX7zm9/0+JrVq1fDYrG4HqWl/ndu/8GZ7Y2Ktp+qwNnKBpmjIaIr+bayHrVNrawfkFmWq7CwmkXZXuBWQhATEwOtVouKioouz1dUVCA+Pr7b1zz++OO4++67cf/992PcuHH44Q9/iKeffhpr166F09n9WXyj0Yjw8PAuD38zNDYU14+OgygCL+3iKgGRkklH3aakREKvZf2AXCYOioBJr0FVgw3fVvAfUp7m1v/ZBoMBkydPxo4dO1zPOZ1O7NixA5mZmd2+pqmpCRpN17fRatsbegR6hie1M/7wyHmUWwLvGCaRWnB+gTIYdVpMTWnfsmHXQs9zO9VdtWoVNm7ciNdffx2nTp3CsmXL0NjYiCVLlgAAFi1ahNWrV7uuX7BgAV588UVs3rwZhYWF2L59Ox5//HEsWLDAlRgEqsmDIzEtJQqtDhGb9hTKHQ4RdcPpFLG/sL3/AAsK5cd+BN6jc/cFt99+Oy5evIgnnngC5eXlmDBhArZu3eoqNCwpKemyIvCrX/0KgiDgV7/6Fc6fP48BAwZgwYIF+J//+R/P3YWKLZ2dhgOv1eCt/SVYfu1QmIP0codERJ18U16PuqZWBBu0GJfE+QVyy+6Ya7C/oAZtDid03MLxGEFUwbq91WqF2WyGxWLxu3oCURRx4/O7cbqiHv85dwSWXztU7pCIqJNNXxXi1x+fxKzhA/D6vdPkDifgOZwiJv1mOyzNrfjgp1mYNChS7pAUr7c/Q5layUwQBDw0q33o0at7itDS6pA5IiLqLIf9BxRFqxGQ2fFZ7GUdgUcxIVCABemJSIoIQlWDDX8/fE7ucIiog9Mp4kAh5xcoDdsYewcTAgXQazW475pUAMDGXQVwOBW/i0MUEE6WWWFpbkWoUYexif61XalmUj+C3JJarqp6EBMChfjJtGREBOtRVN2ErSe67/pIRL4lHTecmhLJ4jUFSYsJQXy4CfY2Jw4Vsf27p/D/cIUINuiwKDMFALD+y/yA79FApATSuGPWDyiLIAjIkrYNePzQY5gQKMg9WSkw6TU4ft6CvfncGyOSk8MpYn8hCwqVSjp+yMJCz2FCoCBRIQbcPqV9kNN6Dj0iktWpMivqW9oQZtRhDOsHFEdqUHT8vAWW5laZo/EPTAgU5v4ZadBqBOw+U4UT5y1yh0MUsKT5BVNTo1g/oEDxZhPSBoTAKV6q9aD+4f/lCpMcFYz54xIAABt2FcgcDVHgcs0v4HaBYnHbwLOYECiQ1Kjok2MXUFLdJHM0RIHH0an/AOsHlMvVj4A1Vx7BhECBxiSaMXP4ADhFYONurhIQ+drXFyyot7UhzKTDaNYPKNb0tGgIAnC2sgEVVk6M7S8mBAq1tGOV4N1DpahqsMkcDVFgkbYLMlKjoNUIMkdDPYkINmBsYvvAKU4/7D8mBAqVmRaN9IFm2NqceH1vkdzhEAUUqaCQ2wXKl8U2xh7DhEChBEHA0llDAABv5BSj0dYmc0REgaHN4cTBju53TAiUr3NhIRu69Q8TAgW7YUw8UmNCYGluxdsHSuQOhyggnLhgRYOtDeEmHUYlsH5A6aamRMGg1eCCpQVFLMLuFyYECqbVCHhwZnstwStfFcLe5pQ5IiL/56ofSItm/YAKBBm0mDgoAgCwh8cP+4UJgcL9cGISBoQZUWZpwUdHL8gdDpHfkxICbheoh9S1kIWF/cOEQOFMei3uzW4fjbzhy3w4ORqZyGtaHU4cdPUfiJI5GuotqR9BTn41/47sByYEKnDX9EEIM+pwprIB//6mUu5wiPzWifMWNNodMAfpMSqe9QNqMX5gBEIMWtQ2teJkmVXucFSLCYEKhJv0uHP6IADAhl0cekTkLTmd+g9oWD+gGnqtBhkdWzzcNug7JgQqcW92KgxaDQ4W1SK3uEbucIj80r6C9u+tzCGsH1CbrCHsR9BfTAhUIi7chB9OTAIAvLiT7YyJPK3V4cShIs4vUCupsPBAYQ1PZPUREwIVeXBWGgQB+NepCpypqJc7HCK/cuycBU12ByKD9RgRFyZ3OOSmEXFhiA4xoLnVgaPn6uQOR5WYEKjIkAGhuGF0HACORibytEvzC6JZP6BCGo3g2uphP4K+YUKgMlI743/knUeZpVnmaIj8x6X+AzxuqFaufgSsI+gTJgQqM3FQJDJSo9DqEPHK7kK5wyHyC/Y2Jw51zC/I7OiNT+ojzTU4UlqLJjvnv7iLCYEKLZ3dvkrw9oESWJpaZY6GSP2OnatDc6sDUSEGDIsNlTsc6qNB0cEYGBmEVoeIA4U8jeUuJgQqNHv4AIyMD0Oj3YG/7iuSOxwi1eu8XcD6AXVzTT/M57aBu5gQqFDn0civ7ilCS6tD5oiI1E3qP8DjhuqXNZSFhX3FhEClvj8+AUkRQahutOO93HNyh0OkWrY2Bw4VMyHwF1kdKwQny6yobbTLHI26MCFQKZ1WgwdmtA892rirAG0ONuIg6otj5yxoaXUimvUDfmFAmBEj4sIgipdaUVPvMCFQsdumJiMyWI+SmiZ8dqJc7nCIVCkn/9K4Y0Fg/YA/4LZB3zAhULFggw6LMlMAtA89EkWO/SRyl6ugkPML/AYLC/uGCYHKLc5KgUmvwYnzVg71IHKTrc2B3OKO/gNsSOQ3MtKioNUIKKxqxIU6NnDrLSYEKhcVYsBPpraPRl7/JUcjE7kjr6QOtjYnYkKNGDKA9QP+Isykx/iBZgDcNnAHEwI/cN81qdBqBHx1tgrHz1nkDodINS4dN4xi/YCf4baB+5gQ+IHkqGAsGJ8AAFi/i6sERL2VU9D+r0ceN/Q/nQsLWV/VO0wI/MRDHY2KPjtehuLqRpmjIVK+llYHDpfUAYBrSh75j0mDImHUaVBZb0P+xQa5w1EFJgR+YlRCOGaPGACnCLzE0chEV3WkpA72NicGhBmRFhMidzjkYSa9FlNT2gtFWXDdO0wI/IjUzvi93HO4WG+TORoiZZOOG2ay/4DfYj8C9zAh8CMZqVGYkBwBe5sTr+3laGSiK7k00IjbBf5KKizcV1ANh5N1BFfDhMCPdB569NecYjTYOA+cqDstrQ4c6agfmM7+A35rbJIZ4SYdrC1tOHGeJ7CuhgmBn7lhdBzSBoTA2tKGt/eXyB0OkSIdLqmF3eFEXLgRqawf8FtajeBaAdqTz22Dq2FC4Gc0GgEPzUwDALzyVSHsbRx6RHS5fZxfEDCyh3b0I2Bh4VUxIfBDCycmITbMiHJrC7bknZc7HCLFkRoSZbJ+wO9ldxQWHiyqQUurQ+ZolI0JgR8y6rS495r20cgbvsyHk8U0RC7NdgfySusAsKAwEAwZEIrYMCNsbU4cLqmVOxxFY0Lgp+7MGIQwow75Fxux45tKucMhUgypfiDBbMLg6GC5wyEvEwSB2wa9xITAT4Wb9Lhr+mAAHHpE1Fnn44asHwgMWUNYWNgbfUoI1q1bh5SUFJhMJmRkZODAgQNXvL6urg7Lly9HQkICjEYjhg8fjk8//bRPAVPv3ZudAoNWg9ziWhwsqpE7HCJFyHEVFPK4YaCQVgiOnbOgvqVV5miUy+2E4J133sGqVauwZs0aHD58GOnp6Zg7dy4qK7tflrbb7bj++utRVFSE999/H6dPn8bGjRuRlJTU7+DpymLDTbhlcvuf8/qdXCUgarK34ei5OgBAZlqMvMGQzyRGBCE1JgQOp4j9BfzHUU/cTgieffZZPPDAA1iyZAlGjx6N9evXIzg4GJs2ber2+k2bNqGmpgZbtmxBdnY2UlJSMGvWLKSnp/c7eLq6B2akQRCAHd9U4nR5vdzhEMkqt7gWrQ4RiWYTkqOC5A6HfIjbBlfnVkJgt9uRm5uLOXPmXPoCGg3mzJmDnJycbl/z0UcfITMzE8uXL0dcXBzGjh2Lp59+Gg5Hz8c/bDYbrFZrlwf1TdqAUNw4Jh4AsIGjkSnAueoHhrB+INCwsPDq3EoIqqqq4HA4EBcX1+X5uLg4lJeXd/uagoICvP/++3A4HPj000/x+OOP4w9/+AN++9vf9vg+a9euhdlsdj2Sk5PdCZMuI7Uz/ijvAs7XNcscDZF8pP4DPG4YeNqHWAGnK+o5/K0HXj9l4HQ6ERsbi5deegmTJ0/G7bffjl/+8pdYv359j69ZvXo1LBaL61FaWurtMP1aenIEMtOi0eYU8cpuDj2iwNRoa8PRjv4DbEgUeCJDDBidEA4A2Mttg265lRDExMRAq9WioqKiy/MVFRWIj4/v9jUJCQkYPnw4tFqt67lRo0ahvLwcdru929cYjUaEh4d3eVD/LJ3dvkqw+WAJ6pq6/3Mn8me5xbVoc4pIighCchT7DwQibhtcmVsJgcFgwOTJk7Fjxw7Xc06nEzt27EBmZma3r8nOzsbZs2fhdF7qqf/tt98iISEBBoOhj2GTu2YOi8HohHA02R14I6dY7nCIfC6H444DHgsLr8ztLYNVq1Zh48aNeP3113Hq1CksW7YMjY2NWLJkCQBg0aJFWL16tev6ZcuWoaamBitWrMC3336LTz75BE8//TSWL1/uubugqxIEAQ/Nah969NreIjTb2dObAotUUJg5hAlBoJqWGgW9VsC52maUVDfJHY7iuJ0Q3H777XjmmWfwxBNPYMKECcjLy8PWrVtdhYYlJSUoKytzXZ+cnIxt27bh4MGDGD9+PH72s59hxYoVeOyxxzx3F9Qr88clYGBkEGoa7Xgvl3UZFDgabW04ds4CgA2JAlmwQYeJyZEAuErQHUEURcVPvrFarTCbzbBYLKwn6KfX9xZhzUdfY2BkEHb+fDZ0WnavJv+383Ql7nn1IJKjgrD7F9+TOxyS0fP/+hbP/+sMvj8+AX+5c5Lc4fhEb3+G8qdBgLltSjKiQgw4V9uMT090f1SUyN+4jhumcrsg0EmFhTn51ZwEexkmBAEmyKDF4swUAO3tjFWwQETUbywoJEn6wAgEG7SobrTjdAW7t3bGhCAALcocjCC9FifLrNh9hvto5N/qW1px4nxH/QALCgOeQafBtNT2OpI9Z/n3X2dMCAJQZIgBP5nW3v2Ro5HJ3x0qqoXDKWJQVDCSIji/gIDsIR39CPLZj6AzJgQB6v4ZadBpBOzNr8axjulvRP7IddyQ2wXUIWto+/8L+wuq0epwXuXqwMGEIEAlRQThB+mJALhKQP7t0kAjHjekdqPiwxEVYkCj3cF/EHXChCCAPdQx9OizE+UorGqUORoiz7O2tOK4VD/AFQLqoNEIrhWjPWxj7MKEIICNiA/D90bGQhSBl3YVyB0OkccdKqqBUwRSooORYGb9AF0ibRuwsPASJgQBThqN/PfD51BZ3yJzNESelZPP44bUPamw8EhJHVu5d2BCEOCmpkRi0qAI2NuceHVPkdzhEHmU1JCI8wvocoOj20+d2B1OHCyqkTscRWBCEODahx61rxK8ua8Y9S2tMkdE5BmW5lZ8fYH1A9Q9QRA4/fAyTAgI14+Kw5ABIahvacNb+0vkDofIIw4WttcPpMWEIC7cJHc4pEBSG+O9LCwEwISA0F5x+9DM9lWCV74qhK2N+2mkftJxwwyuDlAPpBWCExcsqGuyyxyN/JgQEADg5omJiAs3orLehn8cuSB3OET9dml+AfsPUPdiw00YFhsKUbyUQAYyJgQEADDqtLjvmlQAwPpd+ZwCRqpmaWrFyTIrAHYopCuTtg3Yj4AJAXVyx7RBCDPpUHCxEdtPVcgdDlGf7S+shigCaQNCEMv6AboCFhZewoSAXMJMetw9fTCA9nbGHI1MauU6bsjVAbqKjLRoaASg4GIjyi2B3YuFCQF1sSQ7FQadBkdK6nCgkGdzSZ1c8wuYENBVmIP0GDcwAgC7FjIhoC4GhBlx6+SBADj0iNSprsmOU+Xt9QNMCKg3srltAIAJAXXjwRlp0AjAF6cv4puOv1iJ1GJ/YQ1EERgaG4oBYUa5wyEV6NyPIJC3SpkQ0HekxIRg3tgEAMCGLzn0iNTl0vwCHjek3pk8OBIGnQbl1hYUBPDkVyYE1K2HZqUBAD46egHnaptkjoao96T6gcy0GJkjIbUw6bWYMjgSALA3gOsImBBQt8YPjEDWkGg4nCJe3l0odzhEvVLbaMc35fUAgAyuEJAb2I+ACQFdgTQa+Z2DpahtZFtPUr79he1/mQ+PC0VMKOsHqPekfgQ5BdVwBGhjNiYE1KMZw2IwJjEcza0OvJ5TJHc4RFcl9R/g6QJy17gkM8KMOliaW3HyQmAWUzMhoB51Ho38+t4iNNnbZI6I6MouFRQyISD36LQa1yCsQD1+yISAruimsfFIjgpCbVMr3jt0Tu5wiHpU3WDD6YqO+oFU1g+Q+7KHdiQEAVpYyISArkin1eDBGe0nDjbuLkCbwylzRETd29/RWXNEXBiiWT9AfSAVFh4sqgnIMfBMCOiqfjwlGdEhBpyrbcYnx8vkDoeoW67jhkO4XUB9M6yjmVVLqxNHSurkDsfnmBDQVZn0WtyTlQIAWP9lQUB38iLlujS/gNsF1DeCILhOGwRiPwImBNQrd2cORrBBi1NlVnz57UW5wyHqoqrBhm8rGgAAGalcIaC+yx7S0Y8gP/D6ETAhoF6JCDbgjmmDAHDoESnP/o7jhiPjwxAZYpA5GlKzrI7CwqOldWiwBdbJKiYE1Gv3XZMKnUbAvoIa5JXWyR0OkUtOQfvyLo8bUn8NjAzG4OhgtDlFHCgMrFUCJgTUa4kRQbh5QhIAYP1OrhKQckgNiVhQSJ6QNSQw2xgzISC3SEOPtp0sR/7FBpmjIQIu1ttwtrIBgsD+A+QZgdqPgAkBuWV4XBiuGxkLUQQ27uJoZJKfdLpgVHw4IoJZP0D9l9mx9fRNeT2qGmwyR+M7TAjIbUtnt7cz/uDweVRaW2SOhgLdpeOG3C4gz4gONWJUQjiAS+2wAwETAnLb1JQoTB4cCbvDiVf2cDQyySuH/QfIC7KlfgQBNNeACQH1iTQa+a19JbC2tMocDQWqSmsLCi42dtQPcIWAPEdqYxxIhYVMCKhPrhsZi2Gxoai3teGt/SVyh0MBSlodGJ0QDnOwXuZoyJ9MS42CTiOgpKYJpTVNcofjE0wIqE80GgEPzmw/cbDpq8KAHARC8nMdN2T9AHlYiFGHCckRAAJn24AJAfXZzROSkGA2obLehg8Pn5c7HApA+1lQSF6UFWDbBkwIqM8MOg3uuyYVAPDSrgI4nBx6RL5TYW1BQVUjNAIwlf0HyAsuFRZWB8RQNyYE1C8/mTYI4SYdCqoasf1kudzhUACRjhuOSTTDHMT6AfK8iYMiEaTXdhme5c+YEFC/hBp1WJSZAgB4kaORyYek8+E8bkjeYtBpXKtPgdC1kAkB9ds92Skw6jQ4WlrnKvIi8jZphYDzC8ibAqkfARMC6reYUCN+PGUgAI5GJt8oszSjqLoJGgGYksIVAvIeqR/B/oIatDmcMkfjXX1KCNatW4eUlBSYTCZkZGTgwIEDvXrd5s2bIQgCFi5c2Je3JQV7YEYaNALw5bcXcfKCVe5wyM9JqwPjkswIN7F+gLxndEI4IoL1qLe14dh5i9zheJXbCcE777yDVatWYc2aNTh8+DDS09Mxd+5cVFZWXvF1RUVF+PnPf44ZM2b0OVhSrsHRIZg3LgEAsGEXVwnIu/blt29N8bgheZtGI7j6XOz18zoCtxOCZ599Fg888ACWLFmC0aNHY/369QgODsamTZt6fI3D4cBdd92Fp556Cmlpaf0KmJRrWUc744+PlQVMZy+SRw77D5APBUo/ArcSArvdjtzcXMyZM+fSF9BoMGfOHOTk5PT4ul//+teIjY3Ffffd16v3sdlssFqtXR6kfGOTzLhmaAwcThEv7+ZoZPKO83XNKKlpglYjYEpKpNzhUACQCgtzS2rR0uq/XVndSgiqqqrgcDgQFxfX5fm4uDiUl3d/Bv2rr77CK6+8go0bN/b6fdauXQuz2ex6JCcnuxMmyUgaevTOoVJUB9AccfKdfR3HDccmmRHG+gHygdSYECSYTbC3OXGoqFbucLzGq6cM6uvrcffdd2Pjxo2IiYnp9etWr14Ni8XiepSWlnoxSvKk7KHRGJsUjpZWJ97IKZY7HPJDruOG3C4gHxEEAVlDOrYN/Pj4oVsJQUxMDLRaLSoqKro8X1FRgfj4+O9cn5+fj6KiIixYsAA6nQ46nQ5vvPEGPvroI+h0OuTnd198ZjQaER4e3uVB6iAIgmuV4PWcIjTZ22SOiPzNvkI2JCLfyx7q/4WFbiUEBoMBkydPxo4dO1zPOZ1O7NixA5mZmd+5fuTIkTh+/Djy8vJcjx/84Ae49tprkZeXx60APzVvbAIGRwejrqkV7xzk6g55zrnaJpTWNEOrETCV/QfIh6R+BMfPW2BpbpU5Gu9we8tg1apV2LhxI15//XWcOnUKy5YtQ2NjI5YsWQIAWLRoEVavXg0AMJlMGDt2bJdHREQEwsLCMHbsWBgMBs/eDSmCViPggRntp0le3l2IVj9v5kG+I3XCHD/QjBCjTuZoKJDEhZswZEAInOKlbSt/43ZCcPvtt+OZZ57BE088gQkTJiAvLw9bt251FRqWlJSgrKzM44GSutw6eSBiQg04X9eMj49dkDsc8hOX5hewfoB8T1ol8NdtA0FUwTQaq9UKs9kMi8XCegIVWffFWfzfttMYGR+Gz1bMgCAIcodEKpf9u3/jfF0z3rh3GmYOHyB3OBRgtp4ox9I3czE0NhT/WjVL7nB6rbc/QznLgLzmPzIGI8SgxTfl9dh5+qLc4ZDKldY04XxdM3QaAZMHs/8A+V5mWjQ0AnC2sgEV1ha5w/E4JgTkNeZgPe6YNggA8CKHHlE/Sd0J05MjWD9AsjAH6zE2yQzAP6cfMiEgr7pvRir0WgEHCmtwuMR/G3qQ9+0r4HFDkp+rH4EftjFmQkBelWAOws0TkgAA63dylYD6RhRFV4fCzLTeNzkj8rTO/QhUUILnFiYE5HVLZ7UfQdx+qgJnKxtkjobUqLSmGRcsLdBrBUwaHCF3OBTApgyOgkGrwQVLC4qq/WuIGxMC8rqhsWGYMyoOogi8xNHI1Ac5Be37tekDIxBsYP0AySfIoHUlpXv87PghEwLyiWWz21cJPjxyHuUW/6vOJe+SGhJlDmH/AZJfdkcdgb8VFjIhIJ+YPDgKU1Mi0eoQsWlPodzhkIqIotipoJAJAckvq6NBUU5+NZxO/6kjYEJAPiMNPXprf4nf9gInzyuubkKZpQUGrQaTBrH/AMkvfaAZoUYdaptacbLMKnc4HsOEgHzm2hGxGB4XigZbG/62n6ORqXek1YEJyREIMmhljoYI0Gk1yEhtP/7qT9sGTAjIZzQaAQ/NbF8l2PRVEVpaHTJHRGqQw/4DpEDStoE/9SNgQkA+9YMJiUg0m1DVYMMHh8/LHQ4pXJf6ARYUkoJI/QgOFNbA3uYfE12ZEJBP6bUa3NcxGvmlXflw+FFBDnleUXUTKqw21g+Q4oyIC0NMqAHNrQ7kldbJHY5HMCEgn/vJ1GSYg/Qoqm7Ctq/L5Q6HFEwadzxxUARMetYPkHIIgoBMVxtj/6gjYEJAPhdi1GFR5mAAwPov8/2u/Sd5Do8bkpJld2xj+UthIRMCksXirBQYdRocO2dx/SuQqDNRFF0FhWxIREqU3VFYeKSkDo22Npmj6T8mBCSLmFAjbpuSDICjkal7BVWNuFhvg0GnwYTkCLnDIfqO5KhgJEcFoc0p4kBRjdzh9BsTApLNAzPSoBGA3WeqcOK8Re5wSGGklaNJrB8gBXO1MfaDOgImBCSbQdHBmD8+EQCwYVeBzNGQ0kj1Axx3TErmT/0ImBCQrB6a2X4E8ZNjF1DiZ6NEqe/a+w+0L8GyIREpWVZHfcvJMitqGu0yR9M/TAhIVmOTzJgxLAZOEdi4m6sE1C7/YgOqGmww6jSYMChC7nCIehQTasTI+DAAUH2BNBMCkt2yjqFH7x4qRXWDTeZoSAlyOlYHJg+OhFHH+gFStiypH4HKjx8yISDZZQ6JxviBZtjanHh9b5Hc4ZAC7Mtn/wFSD6mNsdoLC5kQkOwEQXCNRn49p9gvzvNS33WeX8D+A6QG01KjoNUIKKpuwvm6ZrnD6TMmBKQIc8fEIzUmBJbmVmw+WCp3OCSjs5UNqG60w6TXYPxAs9zhEF1VmEmP9I7/V9XcxpgJASmCViPggY6hR6/sLkCrwz+mh5H7pO6EUwZHsX6AVEPqWqjmbQMmBKQYP5qUhJhQIy5YWvBR3gW5wyGZXJpfwOOGpB6XCgurVTufhQkBKYZJr8WS7BQAwIZd+XByNHLAcTov9R9g/QCpyaTBETDpNbhYb8PZyga5w+kTJgSkKP8xfTBCjTp8W9GAL05Xyh0O+diZygbUNNoRpNdiXFKE3OEQ9ZpRp8XUlPZVLbXWETAhIEUxB+lxZ8YgAO2jkSmw5HSc456SEgmDjn89kbp03jZQI37HkeLcm50KvVbAwaJa5Barf4IY9d6ldsXcLiD1kfoR7CuoRpsKC6OZEJDixJtN+OHEJADAizvZzjhQOJ0i9heyIRGp15hEM8JNOtS3tOHEBavc4biNCQEp0oMzh0AQgH+dqsCZinq5wyEfOF1Rj9qmVgQbtOw/QKqk1QiuYlg11hEwISBFGhobiutHxQEA7n7lAL46o75vLnKPdNxwSkoU9Fr+1UTq5OpHoMK5BvyuI8X65fxRSI0JQbm1Bf/xyn48+dHXaLY75A6LvCQnn/0HSP2kwsJDRbVoaVXX31dMCEixBkeH4JOfXYO7pw8GALy2twjz/7wbR0vr5A2MPK69fqCj/wDrB0jFhgwIQVy4EbY2Jw4X18odjluYEJCiBRt0+M3CsXj93mmIDTOi4GIjfvTiXjz/r2/Z3tiPfFNeD0tzK0IMWoxNYv0AqZcgCMhW6ThkJgSkCrOGD8Dnj87E98cnwOEU8fy/zuDWF/ci/6I6O4JRV9L8gqmprB8g9cvqqCPYc1Zd/Qj4nUeqERFswF/unIQ//mQCwk06HD1nwfw/7cbre4vY5ljlLs0v4HYBqZ/Uj+DYuTpYW1pljqb3mBCQ6tw8IQnbHp2JGcNi0NLqxJqPvsbiVw+g3NIid2jUBw6niP0dCQHrB8gfJJiDkBYTAqcI7C9QT3M1JgSkSgnmILy+ZBqe+sEYmPQa7D5ThRue+xL/yDsvd2jkplNlVlhb2hBq1GFMYrjc4RB5RNZQ9fUjYEJAqqXRCFiclYJPfjYD6QPNsLa0YcXmPDz81mHUNdnlDo96SdoumJoSCR3rB8hPSIWFaupHwO8+Ur0hA0Lx/rIsrJwzDFqNgI+PlWHu87vw5bcX5Q6NekFKCDjumPxJ5pBoCALwbUUDKuvVsZ3JhID8gl6rwco5w/HBsiykDQhBhdWGxZsO4PEtJ9Bkb5M7POqBo1P/ARYUkj+JCDa4tsByVDL9kAkB+ZX05Ah88sgM3JOVAgD4675izP/TVzhSoq4GIYHi5AUr6lvaEGbUYUwi+w+Qf3H1I1BJHQETAvI7QQYtnvzBGPz1vmmIDzehsKoRt67PwbOfn2YzI4WRtgumpUZBqxFkjobIszr3IxBF5R+NZkJAfmvGsAHYtnImbp6QCIdTxJ/+fRY/emEvzlZyeqJS5LD/APmxqSmR0GsFnK9rRklNk9zhXBUTAvJr5mA9/viTifjLnRNhDtLj+HkL5v/pK2z6qpDNjGTW5nDioDS/gAWF5IeCDTpMHBQJQB1dC/uUEKxbtw4pKSkwmUzIyMjAgQMHerx248aNmDFjBiIjIxEZGYk5c+Zc8Xoib/j++ER8/uhMzBw+ALY2J3798UncvWk/LtQ1yx1awDpZZkW9rQ3hJh1GJbD/APknNc01cDsheOedd7Bq1SqsWbMGhw8fRnp6OubOnYvKyspur9+5cyfuuOMOfPHFF8jJyUFycjJuuOEGnD/PBjLkW3HhJry+ZCp+s3AsgvRa7DlbjbnP78KHR86pYn/P30iV19NSo1k/QH5LamOck1+t+FVJtxOCZ599Fg888ACWLFmC0aNHY/369QgODsamTZu6vf5vf/sbfvrTn2LChAkYOXIkXn75ZTidTuzYsaPfwRO5SxAE3D19MD5dMQMTkiNQ39KGR985iuVvHUZtI5sZ+dKl+QVRMkdC5D3pyREIMWhR02jHN+XKrl9yKyGw2+3Izc3FnDlzLn0BjQZz5sxBTk5Or75GU1MTWltbERXV818CNpsNVqu1y4PIk1JjQvD+0kz8v+uHQ6cR8Onxctzw/C58cbr7lS7yrDaHEweL2o+Csn6A/Jleq8G01Pafd0rvWuhWQlBVVQWHw4G4uLguz8fFxaG8vLxXX+O//uu/kJiY2CWpuNzatWthNptdj+TkZHfCJOoVnVaDR64bhg9/mo2hsaG4WG/DklcP4r8/PI5GG5sZedOJC1Y02NpgDtJjVDzrB8i/ZQ9VRz8Cn54y+N3vfofNmzfjww8/hMlk6vG61atXw2KxuB6lpaU+jJICzbiBZnz8yDW4NzsVAPDW/hLc9KfdyC1mMyNvuVQ/EAUN6wfIz2V1FBYeKKxRdC8UtxKCmJgYaLVaVFRUdHm+oqIC8fHxV3ztM888g9/97nf4/PPPMX78+CteazQaER4e3uVB5E0mvRZPLBiNt+7PQKLZhOLqJvx4/V7837ZvYG9T7jewWu3juGMKICPjwxAVYkCj3YGjpXVyh9MjtxICg8GAyZMndykIlAoEMzMze3zd//7v/+I3v/kNtm7diilTpvQ9WiIvyxoag89WzsSPJibBKQLrvsjHD1/Yg28rlF0MpCatDicOFXF+AQUOjUZw1coouR+B21sGq1atwsaNG/H666/j1KlTWLZsGRobG7FkyRIAwKJFi7B69WrX9b///e/x+OOPY9OmTUhJSUF5eTnKy8vR0NDgubsg8iBzkB7P3j4BL941CZHBenx9wYrv//krvLy7QPHHhtTg+HkLGu0ORATrMTI+TO5wiHxCDf0I3E4Ibr/9djzzzDN44oknMGHCBOTl5WHr1q2uQsOSkhKUlZW5rn/xxRdht9tx6623IiEhwfV45plnPHcXRF4wb1wCtq2ciWtHDIC9zYnffnIKd768D+dqld+CVMmk7YIM1g9QAJH6ERwpqVXsBFZBVEFHFqvVCrPZDIvFwnoC8jlRFPH2gVL89pOTaLI7EGbUYc0PxuCWSUkQBP5Ac9fdr+zH7jNVeHLBaNzTUchJ5O9EUcQ1v/8C5+ua8fq90zBr+ACfvXdvf4ZylgHRVQiCgDszBuGzFTMweXAk6m1t+Pl7R7H0zVxUN9jkDk9V2usH2k9vTGf/AQoggiC4Vgn2KvT4IRMCol4aHB2Cdx/KxH/OHQG9VsC2rysw9/nd2HGq4uovJgDAsXMWNLc6EBmsx/BY1g9QYHH1I1BoHQETAiI3aDUCll87FFuWZ2N4XCiqGmy47/VDeOzvx9DAZkZXta/TuGPWD1CgkU4afH3Birom5bVKZ0JA1AdjEs346OFr8MCMVAgCsPlgKeb9cRcOdhyno+51TgiIAk1smAnD40IhipeacykJEwKiPjLptfjl/NF4+4HpSIoIQmlNM27bkIPfffYNbG0OucNTHHvbpfoBzi+gQJWl4OOHTAiI+ml6WjS2rpyBWycPhCgC67/Mx81/2YNvyjmUq7Nj5+rQ3OpAVIgBw2JD5Q6HSBZSHcFeBTYoYkJA5AFhJj2e+XE61v/HZESFGPBNeT1+8Oc92PBlPhxsZgTg0hLp9LQoHtekgJWRFgWNABRUNaLM0ix3OF0wISDyoBvHxmPbypmYMyoWdocTaz/7Bne8tA+lNWxmtK+Q8wuIwk16jB8YAUB5bYyZEBB52IAwIzYumoLf3zIOIQYtDhTV4Mbnd+Hdg6VQQR8wr7C1OVzTI1lQSIFOqf0ImBAQeYEgCLh96iB8tmImpqZEotHuwC/+fgwP/jUXVQHYzOhoqQUtrU7EhBowlPUDFOA6zzVQ0j8SmBAQedGg6GBsfjATj80bCb1WwPaTFZj73C58/nW53KH5lGt+QVo06wco4E0aHAmjToMKqw35FxvlDseFCQGRl2k1ApbOGoKPHr4GI+PDUN1ox4N/zcV/vncU9S2tcofnE1JBIesHiNqPLE9JiQQA7FXQ8UMmBEQ+MiohHP94OBsPzUqDIADv5Z7DvD/uxv4CZRUWeVpLqwOHS1g/QNSZqx+BguoImBAQ+ZBRp8XqeaPwzoOZGBgZhHO1zfjJxn14+tNTftvM6GhpHWxtTgwIM2LIgBC5wyFSBKkfQU5+tWKOJjMhIJLBtNQobF05E7dPSYYoAi/tKsAP/rwHJy/4XzOjnE7tilk/QNRuXJIZYSYdrC1t+PqCRe5wADAhIJJNqFGH3986HhsXTUFMqAGnK+px87qv8MLOs4r5F4MnXJpfECVzJETKodUIri00pfQjYEJAJLPrR8dh28qZuGF0HFodIv5362ncviEHJdXqb2bUXj9QB4AFhUSXy+6Y6aGUwkImBEQKEB1qxIa7J+P/bh2PUKMOh4prceMfd+HtAyWKOqfsriMldbC3OREbZkRqDOsHiDqT6ggOFtUoooaICQGRQgiCgB9PScZnK2ZgWmoUmuwOrP7gOO5//RAq61vkDq9PWD9A1LOhsaGIDTOipdWJw8V1cofDhIBIaZKjgrH5gen45U2jYNBqsOObSsx9bhe2niiTOzS3SfUDHHdM9F2CICBLQdsGTAiIFEijEfDAzDT885FrMCohHLVNrVj65mGsejcPVpU0M2ppdSCvo36A/QeIupc1VDn9CJgQECnYiPgw/GN5Nn46ewg0AvDB4fOY9/xuV+c/JTtcXAu7w4n4cBNSooPlDodIkaQ6gqPnLLJ3LmVCQKRwBp0Gv7hxJN59KBODooJxvq4Zd2zch99+fBItrfIXIvWk83FD1g8QdS8pIggp0cFwOEUcKKyRNRYmBEQqMSUlCp+tmIE7pg0CALz8VSEW/PkrnDivjKYml8th/QBRr1zaNpB35Y8JAZGKhBh1WPujcdh0zxTEhBpxprIBC9ftwV/+fQZtDqfc4bk02x3IK60DwPoBoquRxiHLXVjIhIBIhb43Mg6fPzoT88bGo80p4pnPv8VtG3JQVKWMUaqHS2rR6hCRYDZhUBTrB4iuRFpF+6a8HlUNNtniYEJApFJRIQa8cNckPHtbOsKMOhwuqcO8P+7G3/YXy97MqPO4Y9YPEF1ZVIgBoxPCAQB7ZSwYZkJApGKCIOBHkwZi66MzkZkWjeZWB3754Qksee0gKq3yNTPa16khERFdXfbQjn4EMh4/ZEJA5AeSIoLwt/sz8Pj3R8Og02Dn6Yu44fld+OSY75sZNdnbcPRcHQAWFBL1lquwUMY6AiYERH5CoxFw3zWp+OSRazA2KRx1Ta1Y/tZhrNx8BJZm351vzi1urx9IigjCwMggn70vkZpNS4mCTiOgtKYZpTXyDDZjQkDkZ4bFheGDZdl45HtDoRGALXkXcOPzu3zWCU2qH8hg/wGiXgsx6jBxUAQA+boWMiEg8kMGnQb/74YReH9ZFlKig1FmacFdL+/HU//82uvNjFzzC1g/QOSWrCHStoE8hYVMCIj82KRBkfh0xQz8x/T2Zkav7inC/D/txrGOPX5Pa7S14di59kZJLCgkcs/3RsbiR5OSMH9cvCzvz4SAyM8FG3T47cJxeG3JVMSGGZF/sRE/emEv/rTD882MDhXXos0pYmBkEJLZf4DILenJEXj2tgm4cWyCLO/PhIAoQMweEYttK2di/rgEtDlFPLv9W9y6PgcFFxs89h48bkikXkwIiAJIZIgBf7lzIp6/fQLCTDrkldbhpj/txl9zijzSzKhzQyIiUhcmBEQBRhAELJyYhG0rZyJ7aDRaWp14/B9fY9GmAyi39L2ZUYOtDcc7Bi1lpEV5Klwi8hEmBEQBKjEiCH+9NwNPLhgNo06D3WeqMPf5Xfjn0Qt9+nqHimrgcIpIjgrCwEjWDxCpDRMCogCm0Qi4JzsVn/xsBsYlmWFpbsUjbx/Bz94+AkuTe82McnjckEjVmBAQEYbGhuKDn2bhZ9cNg1Yj4KOjFzD3+V3YfeZir7/GvoIaACwoJFIrJgREBADQazVYdf1w/H1ZFtJiQlBubcHdrxzAE/84gWb7lZsZ1be04sR59h8gUjMmBETUxYTkCHzysxlYnDkYAPBGTjHm/2k3jpbW9fiaQ0W1cDhFDI4ORmIE5xcQqRETAiL6jiCDFk/dPBZv3DsNceFGFFQ14kcv7sVz279FazfNjNiumEj9mBAQUY9mDh+AbStnYkF6IhxOEX/ccQa3vLgXZyu7NjPKYUMiItVjQkBEVxQRbMCf75iIP90xEeYgPY6ds2D+n3bj1T2FcDpFWFk/QOQXdHIHQETq8IP0RExLicJ/vn8Uu89U4al/nsSOU5W4cWw8nCKQGhOCeLNJ7jCJqI+4QkBEvRZvNuGNe6fhNzePgUmvwVdnq/CrLScAANPZnZBI1fqUEKxbtw4pKSkwmUzIyMjAgQMHrnj9e++9h5EjR8JkMmHcuHH49NNP+xQsEclPEATcnZmCT342A+nJEa7nuV1ApG5uJwTvvPMOVq1ahTVr1uDw4cNIT0/H3LlzUVlZ2e31e/fuxR133IH77rsPR44cwcKFC7Fw4UKcOHGi38ETkXyGDAjF35dm4r9uHImbJyTihtHyzHAnIs8QRDdHnGVkZGDq1Kn4y1/+AgBwOp1ITk7GI488gscee+w7199+++1obGzExx9/7Hpu+vTpmDBhAtavX9+r97RarTCbzbBYLAgPD3cnXCIiooDW25+hbq0Q2O125ObmYs6cOZe+gEaDOXPmICcnp9vX5OTkdLkeAObOndvj9QBgs9lgtVq7PIiIiMh73EoIqqqq4HA4EBcX1+X5uLg4lJeXd/ua8vJyt64HgLVr18JsNrseycnJ7oRJREREblLkKYPVq1fDYrG4HqWlpXKHRERE5Nfc6kMQExMDrVaLioqKLs9XVFQgPr77gqL4+Hi3rgcAo9EIo9HoTmhERETUD26tEBgMBkyePBk7duxwPed0OrFjxw5kZmZ2+5rMzMwu1wPA9u3be7yeiIiIfM/tToWrVq3C4sWLMWXKFEybNg3PP/88GhsbsWTJEgDAokWLkJSUhLVr1wIAVqxYgVmzZuEPf/gD5s+fj82bN+PQoUN46aWXPHsnRERE1GduJwS33347Ll68iCeeeALl5eWYMGECtm7d6iocLCkpgUZzaeEhKysLb731Fn71q1/hv//7vzFs2DBs2bIFY8eO9dxdEBERUb+43YdADuxDQERE1Dde6UNARERE/okJARERETEhICIiIiYEREREBCYEREREBCYEREREBCYEREREBCYEREREBCYEREREBCYEREREhD7MMpCD1F3ZarXKHAkREZG6SD87rzapQBUJQX19PQAgOTlZ5kiIiIjUqb6+HmazucffV8VwI6fTiQsXLiAsLAyCIHjka1qtViQnJ6O0tNRvBibxnpTP3+4H4D2pBe9JHbxxT6Ioor6+HomJiV2mEV9OFSsEGo0GAwcO9MrXDg8P95v/kSS8J+Xzt/sBeE9qwXtSB0/f05VWBiQsKiQiIiImBERERBTACYHRaMSaNWtgNBrlDsVjeE/K52/3A/Ce1IL3pA5y3pMqigqJiIjIuwJ2hYCIiIguYUJARERETAiIiIiICQERERHBzxOCdevWISUlBSaTCRkZGThw4MAVr3/vvfcwcuRImEwmjBs3Dp9++qmPIu09d+7ptddegyAIXR4mk8mH0V7Zrl27sGDBAiQmJkIQBGzZsuWqr9m5cycmTZoEo9GIoUOH4rXXXvN6nO5w95527tz5nc9IEASUl5f7JuCrWLt2LaZOnYqwsDDExsZi4cKFOH369FVfp+Tvpb7ck9K/l1588UWMHz/e1cwmMzMTn3322RVfo+TPCHD/npT+GV3ud7/7HQRBwMqVK694nS8/J79NCN555x2sWrUKa9asweHDh5Geno65c+eisrKy2+v37t2LO+64A/fddx+OHDmChQsXYuHChThx4oSPI++Zu/cEtHe7Kisrcz2Ki4t9GPGVNTY2Ij09HevWrevV9YWFhZg/fz6uvfZa5OXlYeXKlbj//vuxbds2L0fae+7ek+T06dNdPqfY2FgvReieL7/8EsuXL8e+ffuwfft2tLa24oYbbkBjY2OPr1H691Jf7glQ9vfSwIED8bvf/Q65ubk4dOgQvve97+Hmm2/G119/3e31Sv+MAPfvCVD2Z9TZwYMHsWHDBowfP/6K1/n8cxL91LRp08Tly5e7fu1wOMTExERx7dq13V5/2223ifPnz+/yXEZGhvjQQw95NU53uHtPr776qmg2m30UXf8AED/88MMrXvOLX/xCHDNmTJfnbr/9dnHu3LlejKzvenNPX3zxhQhArK2t9UlM/VVZWSkCEL/88sser1HD91JnvbknNX0vSSIjI8WXX365299T22ckudI9qeUzqq+vF4cNGyZu375dnDVrlrhixYoer/X15+SXKwR2ux25ubmYM2eO6zmNRoM5c+YgJyen29fk5OR0uR4A5s6d2+P1vtaXewKAhoYGDB48GMnJyVfNrpVO6Z9Rf0yYMAEJCQm4/vrrsWfPHrnD6ZHFYgEAREVF9XiN2j6n3twToJ7vJYfDgc2bN6OxsRGZmZndXqO2z6g39wSo4zNavnw55s+f/50//+74+nPyy4SgqqoKDocDcXFxXZ6Pi4vrcW+2vLzcret9rS/3NGLECGzatAn/+Mc/8Oabb8LpdCIrKwvnzp3zRcge19NnZLVa0dzcLFNU/ZOQkID169fj73//O/7+978jOTkZs2fPxuHDh+UO7TucTidWrlyJ7OxsjB07tsfrlP691Flv70kN30vHjx9HaGgojEYjli5dig8//BCjR4/u9lq1fEbu3JMaPqPNmzfj8OHDWLt2ba+u9/XnpIpph9Q3mZmZXbLprKwsjBo1Chs2bMBvfvMbGSMjyYgRIzBixAjXr7OyspCfn4/nnnsOf/3rX2WM7LuWL1+OEydO4KuvvpI7FI/p7T2p4XtpxIgRyMvLg8Viwfvvv4/Fixfjyy+/7PEHqBq4c09K/4xKS0uxYsUKbN++XbHFjn6ZEMTExECr1aKioqLL8xUVFYiPj+/2NfHx8W5d72t9uafL6fV6TJw4EWfPnvVGiF7X02cUHh6OoKAgmaLyvGnTpinuh+7DDz+Mjz/+GLt27brqKHKlfy9J3Lmnyynxe8lgMGDo0KEAgMmTJ+PgwYP44x//iA0bNnznWrV8Ru7c0+WU9hnl5uaisrISkyZNcj3ncDiwa9cu/OUvf4HNZoNWq+3yGl9/Tn65ZWAwGDB58mTs2LHD9ZzT6cSOHTt63H/KzMzscj0AbN++/Yr7Vb7Ul3u6nMPhwPHjx5GQkOCtML1K6Z+Rp+Tl5SnmMxJFEQ8//DA+/PBD/Pvf/0ZqaupVX6P0z6kv93Q5NXwvOZ1O2Gy2bn9P6Z9RT650T5dT2md03XXX4fjx48jLy3M9pkyZgrvuugt5eXnfSQYAGT4nr5QqKsDmzZtFo9Eovvbaa+LJkyfFBx98UIyIiBDLy8tFURTFu+++W3zsscdc1+/Zs0fU6XTiM888I546dUpcs2aNqNfrxePHj8t1C9/h7j099dRT4rZt28T8/HwxNzdX/MlPfiKaTCbx66+/lusWuqivrxePHDkiHjlyRAQgPvvss+KRI0fE4uJiURRF8bHHHhPvvvtu1/UFBQVicHCw+J//+Z/iqVOnxHXr1olarVbcunWrXLfwHe7e03PPPSdu2bJFPHPmjHj8+HFxxYoVokajEf/1r3/JdQtdLFu2TDSbzeLOnTvFsrIy16Opqcl1jdq+l/pyT0r/XnrsscfEL7/8UiwsLBSPHTsmPvbYY6IgCOLnn38uiqL6PiNRdP+elP4ZdefyUwZyf05+mxCIoij++c9/FgcNGiQaDAZx2rRp4r59+1y/N2vWLHHx4sVdrn/33XfF4cOHiwaDQRwzZoz4ySef+Djiq3PnnlauXOm6Ni4uTrzpppvEw4cPyxB196Qjd5c/pHtYvHixOGvWrO+8ZsKECaLBYBDT0tLEV1991edxX4m79/T73/9eHDJkiGgymcSoqChx9uzZ4r///W95gu9Gd/cCoMufu9q+l/pyT0r/Xrr33nvFwYMHiwaDQRwwYIB43XXXuX5wiqL6PiNRdP+elP4ZdefyhEDuz4njj4mIiMg/awiIiIjIPUwIiIiIiAkBERERMSEgIiIiMCEgIiIiMCEgIiIiMCEgIiIiMCEgIpkIgoAtW7bIHQYRdWBCQBSA7rnnHgiC8J3HjTfeKHdoRCQTv5x2SERXd+ONN+LVV1/t8pzRaJQpGiKSG1cIiAKU0WhEfHx8l0dkZCSA9uX8F198EfPmzUNQUBDS0tLw/vvvd3n98ePH8b3vfQ9BQUGIjo7Ggw8+iIaGhi7XbNq0CWPGjIHRaERCQgIefvjhLr9fVVWFH/7whwgODsawYcPw0UcfefemiahHTAiIqFuPP/44brnlFhw9ehR33XUXfvKTn+DUqVMAgMbGRsydOxeRkZE4ePAg3nvvPfzrX//q8gP/xRdfxPLly/Hggw/i+PHj+Oijj1yz7SVPPfUUbrvtNhw7dgw33XQT7rrrLtTU1Pj0Pomog9fGJhGRYi1evFjUarViSEhIl8f//M//iKLYPhFw6dKlXV6TkZEhLlu2TBRFUXzppZfEyMhIsaGhwfX7n3zyiajRaFzjuBMTE8Vf/vKXPcYAQPzVr37l+nVDQ4MIQPzss888dp9E1HusISAKUNdeey1efPHFLs9FRUW5/jszM7PL72VmZiIvLw8AcOrUKaSnpyMkJMT1+9nZ2XA6nTh9+jQEQcCFCxdw3XXXXTGG8ePHu/47JCQE4eHhqKys7OstEVE/MCEgClAhISHfWcL3lKCgoF5dp9fru/xaEAQ4nU5vhEREV8EaAiLq1r59+77z61GjRgEARo0ahaNHj6KxsdH1+3v27IFGo8GIESMQFhaGlJQU7Nixw6cxE1HfcYWAKEDZbDaUl5d3eU6n0yEmJgYA8N5772HKlCm45ppr8Le//Q0HDhzAK6+8AgC46667sGbNGixevBhPPvkkLl68iEceeQR333034uLiAABPPvkkli5ditjYWMybNw/19fXYs2cPHnnkEd/eKBH1ChMCogC1detWJCQkdHluxIgR+OabbwC0nwDYvHkzfvrTnyIhIQFvv/02Ro8eDQAIDg7Gtm3bsGLFCkydOhXBwcG45ZZb8Oyzz7q+1uLFi9HS0oLnnnsOP//5zxETE4Nbb73VdzdIRG4RRFEU5Q6CiJRFEAR8+OGHWLhwodyhEJGPsIaAiIiImBAQERERawiIqBvcSSQKPFwhICIiIiYERERExISAiIiIwISAiIiIwISAiIiIwISAiIiIwISAiIiIwISAiIiIwISAiIiIAPx/2DnqyEPS/yAAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "max_epochs = 5\n", - "\n", - "pretrained_model = monai.bundle.load(name=\"endoscopic_inbody_classification\", bundle_dir=\"./\")\n", - "\n", - "pretrained_model.train()\n", - "losses = []\n", - "\n", - "for _ in trange(max_epochs):\n", - " epoch_loss = 0\n", - " for data in train_dataloader:\n", - " inputs, labels = data[\"image\"].to(device), data[\"label\"].to(device)\n", - " optimizer.zero_grad()\n", - " predictions = pretrained_model(inputs)\n", - " loss_iter = loss(predictions, labels)\n", - " loss_iter.backward()\n", - " optimizer.step()\n", - " epoch_loss += loss_iter.item()\n", - " losses.append(epoch_loss / len(train_dataloader))\n", - "\n", - "fig, ax = plt.subplots(1, 1, figsize=(6, 6), facecolor=\"white\")\n", - "ax.set_xlabel(\"Epoch\")\n", - "epochs = list(range(len(losses)))\n", - "ax.plot(epochs, losses, label=\"loss\")\n", - "plt.legend()\n", - "plt.show()" - ] + "outputs": [], + "source": "max_epochs = 5\n\n# return_state_dict=False returns the nn.Module rather than a raw OrderedDict (MONAI 1.6 API)\npretrained_model = monai.bundle.load(name=\"endoscopic_inbody_classification\", bundle_dir=\"./\", return_state_dict=False)\n\npretrained_model.train()\nlosses = []\n\nfor _ in trange(max_epochs):\n epoch_loss = 0\n for data in train_dataloader:\n inputs, labels = data[\"image\"].to(device), data[\"label\"].to(device)\n optimizer.zero_grad()\n predictions = pretrained_model(inputs)\n loss_iter = loss(predictions, labels)\n loss_iter.backward()\n optimizer.step()\n epoch_loss += loss_iter.item()\n losses.append(epoch_loss / len(train_dataloader))\n\nfig, ax = plt.subplots(1, 1, figsize=(6, 6), facecolor=\"white\")\nax.set_xlabel(\"Epoch\")\nepochs = list(range(len(losses)))\nax.plot(epochs, losses, label=\"loss\")\nplt.legend()\nplt.show()" }, { "cell_type": "markdown", @@ -501,4 +407,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/runner.sh b/runner.sh index 3296299fd..0474f124a 100755 --- a/runner.sh +++ b/runner.sh @@ -84,6 +84,8 @@ doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" maisi_inference_tut doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" realism_diversity_metrics.ipynb) doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" omniverse_integration.ipynb) doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" hugging_face_pipeline_for_monai.ipynb) +doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" msd_crossval_datalist_generator.ipynb) # inference/datalist-only notebook, no training loop +doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" hovernet_infer_compare.ipynb) # inference-only notebook # Execution of the notebook in these folders / with the filename cannot be automated skip_run_papermill=() @@ -135,6 +137,7 @@ skip_run_papermill=("${skip_run_papermill[@]}" .*learn2reg_oasis_unpaired_brain_ skip_run_papermill=("${skip_run_papermill[@]}" .*finetune_vista3d_for_hugging_face_pipeline.ipynb*) skip_run_papermill=("${skip_run_papermill[@]}" .*TCIA_PROSTATEx_Prostate_MRI_Anatomy_Model.ipynb*) # https://github.com/Project-MONAI/tutorials/issues/2029 skip_run_papermill=("${skip_run_papermill[@]}" .*maisi_inference_tutorial.ipynb*) +skip_run_papermill=("${skip_run_papermill[@]}" .*image_restoration.ipynb*) # monai.networks.nets.restormer not yet in dev branch # output formatting separator="" From 7877af80ac0042ca05645c88dc62a1b0b63a503c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 07:40:40 +0000 Subject: [PATCH 2/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Signed-off-by: R. Garcia-Dias --- .../endoscopic_inbody_classification.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb index fc0a0e930..95d96f691 100644 --- a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb +++ b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb @@ -407,4 +407,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} From a862ed1ac2cffdd99f24b45e2c12906ccd1a1a8a Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 09:12:54 +0100 Subject: [PATCH 3/9] fix: apply PEP8 autofix to 3 notebooks (E225/E231 whitespace violations) - competitions/MICCAI/surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb: E225 - deep_atlas/deep_atlas_tutorial.ipynb: E225 - modules/interpretability/class_lung_lesion.ipynb: E231 in f-string indexing Signed-off-by: R. Garcia-Dias --- .../preprocess_detect_scene_and_split_fold.ipynb | 2 +- deep_atlas/deep_atlas_tutorial.ipynb | 6 +++--- modules/interpretability/class_lung_lesion.ipynb | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/competitions/MICCAI/surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb b/competitions/MICCAI/surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb index f83c5881b..16a55bcc3 100644 --- a/competitions/MICCAI/surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb +++ b/competitions/MICCAI/surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb @@ -398,7 +398,7 @@ ], "source": [ "for lb in labels:\n", - " print(f\"{lb:30} {df_scene[df_scene[lb]>0].scene.nunique()}\")" + " print(f\"{lb:30} {df_scene[df_scene[lb] > 0].scene.nunique()}\")" ] }, { diff --git a/deep_atlas/deep_atlas_tutorial.ipynb b/deep_atlas/deep_atlas_tutorial.ipynb index 580e2c345..799a85fd3 100644 --- a/deep_atlas/deep_atlas_tutorial.ipynb +++ b/deep_atlas/deep_atlas_tutorial.ipynb @@ -1255,7 +1255,7 @@ "val_interval = 5\n", "\n", "for epoch_number in range(max_epochs):\n", - " print(f\"Epoch {epoch_number+1}/{max_epochs}:\")\n", + " print(f\"Epoch {epoch_number + 1}/{max_epochs}:\")\n", "\n", " seg_net.train()\n", " losses = []\n", @@ -1797,7 +1797,7 @@ "best_reg_validation_loss = float(\"inf\")\n", "\n", "for epoch_number in range(max_epochs):\n", - " print(f\"Epoch {epoch_number+1}/{max_epochs}:\")\n", + " print(f\"Epoch {epoch_number + 1}/{max_epochs}:\")\n", "\n", " # ------------------------------------------------\n", " # reg_net training, with seg_net frozen\n", @@ -2320,7 +2320,7 @@ "preview_image(det, normalize_by=\"slice\", threshold=0)\n", "loss = lncc_loss(example_warped_image, img12[:, [0], :, :, :]).item()\n", "print(f\"Similarity loss: {loss}\")\n", - "print(f\"number of folds: {(det<=0).sum()}\")\n", + "print(f\"number of folds: {(det <= 0).sum()}\")\n", "\n", "del reg_net_example_output, img12, example_warped_image\n", "torch.cuda.empty_cache()" diff --git a/modules/interpretability/class_lung_lesion.ipynb b/modules/interpretability/class_lung_lesion.ipynb index f6afb0c8b..246ee4257 100644 --- a/modules/interpretability/class_lung_lesion.ipynb +++ b/modules/interpretability/class_lung_lesion.ipynb @@ -680,8 +680,8 @@ " name += \"lesion\" if label == 1 else \"non-lesion\"\n", " name += \"\\npred: \"\n", " name += \"lesion\" if pred_label == 1 else \"non-lesion\"\n", - " name += f\"\\nlesion: {y_pred[0,1]:.3}\"\n", - " name += f\"\\nnon-lesion: {y_pred[0,0]:.3}\"\n", + " name += f\"\\nlesion: {y_pred[0, 1]:.3}\"\n", + " name += f\"\\nnon-lesion: {y_pred[0, 0]:.3}\"\n", "\n", " # run CAM\n", " cam_result = cam(x=image, class_idx=None)\n", From 252b9d697bfa3b8db81be60bd3cb96b942973605 Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 10:26:37 +0100 Subject: [PATCH 4/9] Fix bundle/05_spleen_segmentation_lightning: upgrade pytorch-lightning pin pytorch-lightning~=2.0.0 (2.0.9) imports mlflow at module level via pytorch_lightning.loggers.mlflow; mlflow 3.13.0 fails to initialize under Python 3.12, making `import pytorch_lightning` fail in the training subprocess. pytorch-lightning>=2.1 uses lazy mlflow imports; confirmed working with 2.6.5: training and evaluation run to completion. Also documents the root cause in diagnose_1_6_release.md: two-part R7 issue (fd-limit download truncation + mlflow/pl import chain). Signed-off-by: R. Garcia-Dias --- bundle/05_spleen_segmentation_lightning.ipynb | 4 +- diagnose_1_6_release.md | 450 ++++++++++++++++++ 2 files changed, 452 insertions(+), 2 deletions(-) create mode 100644 diagnose_1_6_release.md diff --git a/bundle/05_spleen_segmentation_lightning.ipynb b/bundle/05_spleen_segmentation_lightning.ipynb index 68af68eca..43cc966f8 100644 --- a/bundle/05_spleen_segmentation_lightning.ipynb +++ b/bundle/05_spleen_segmentation_lightning.ipynb @@ -38,7 +38,7 @@ "outputs": [], "source": [ "!python -c \"import monai\" || pip install -q \"monai-weekly[ignite,pyyaml]\"\n", - "!pip install -q pytorch-lightning~=2.0.0" + "!pip install -q pytorch-lightning>=2.1" ] }, { @@ -855,7 +855,7 @@ "execution_count": 11, "id": "c5ba337d-a5b0-47de-9ae2-1554a2cb4f86", "metadata": {}, - "outputs": [ + "outputs": [ { "name": "stdout", "output_type": "stream", diff --git a/diagnose_1_6_release.md b/diagnose_1_6_release.md new file mode 100644 index 000000000..261a37d5b --- /dev/null +++ b/diagnose_1_6_release.md @@ -0,0 +1,450 @@ +# MONAI 1.6 Release — Tutorial Test Diagnostics + +**Date:** 2026-06-10 +**Image:** `monai_1_6:latest` (`nvcr.io/nvidia/pytorch:25.03-py3` base) +**GPU:** NVIDIA RTX 5090 (Blackwell, SM_120, CUDA 12.8) +**Python:** 3.12 · PyTorch 2.7.0a0 (nv25.03) · NumPy 1.26.4 +**Runner:** `bash runner.sh` (all tutorials) +**Log:** `runner_output.logs` + +--- + +## Summary + +| Category | Count | Notebooks | +|---|---|---| +| **Passed** | ~150 | — | +| **Failed — ExecutionError** | 91 | Papermill failed; specific errors not in log (stderr not captured) | +| **Failed — PEP8** | 3 | Style violations caught by flake8 | +| **Failed — MissingKeyword** | 1 | `max_epochs` not found and not exempted | +| **Total failures** | **94 events / 93 notebooks** | `class_lung_lesion.ipynb` has both PEP8 + ExecutionError | + +> **Important — missing error details:** The runner was invoked without `2>&1`. Papermill writes +> progress and tracebacks to **stderr**, which was not redirected to `runner_output.logs`. All +> 91 ExecutionError notebooks show `papermill … -k python3` then immediately `Check failed!` in +> the log with no further detail. To see actual errors, re-run with: +> ```bash +> bash runner.sh 2>&1 | tee runner_output.logs +> ``` +> Or for a single notebook: +> ```bash +> docker --context default run --gpus all --rm \ +> --entrypoint bash -e NVIDIA_DISABLE_REQUIRE=true \ +> --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 \ +> -v /data/rgd/tutorials:/opt/tutorials \ +> monai_1_6:latest \ +> -c "cd /opt/tutorials && bash runner.sh --verbose -t 2>&1" +> ``` + +--- + +## Category 1 — PEP8 Violations (3 notebooks) + +The flake8 check (run via `jupytext`) fails before papermill is even invoked. +Fix with `bash runner.sh --autofix -t ` or apply manually. + +| Notebook | Error | Location | +|---|---|---| +| `competitions/MICCAI/surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb` | E225 missing whitespace around operator | `stdin:160:44` | +| `deep_atlas/deep_atlas_tutorial.ipynb` | E225 missing whitespace around operator | `stdin:1353:31` | +| `modules/interpretability/class_lung_lesion.ipynb` | E231 missing whitespace after `,` (two occurrences in f-strings `y_pred[0,1]` / `y_pred[0,0]`) | `stdin:358:34`, `stdin:359:38` | + +--- + +## Category 2 — MissingKeyword (1 notebook) + +The runner requires all training notebooks to declare `max_epochs` (so it can reduce it to 1 +for fast CI). Notebooks that don't have it must be added to the `doesnt_contain_max_epochs` +exemption list in `runner.sh`. + +| Notebook | Detail | +|---|---| +| `auto3dseg/notebooks/msd_crossval_datalist_generator.ipynb` | `max_epochs` keyword absent; not in `doesnt_contain_max_epochs` list | + +**Fix options:** +- Add the notebook filename to `doesnt_contain_max_epochs` in `runner.sh` (line ~32), or +- Add a `max_epochs = 1` cell/variable to the notebook. + +--- + +## Category 3 — ExecutionError (91 notebooks) + +Papermill returned a non-zero exit code. Specific errors are in stderr (not captured in +`runner_output.logs`). Sub-grouped by likely root cause. + +### 3a — Generative model training (30 notebooks) + +These notebooks train diffusion/VAE/GAN models. Even with `max_epochs = 1`, they likely fail +because they need either: +- Pre-trained checkpoint files not present in the container, or +- Custom dataset paths (e.g. BraTS, TCIA) not mounted. + +| Notebook | +|---| +| `generation/2d_autoencoderkl/2d_autoencoderkl_tutorial.ipynb` | +| `generation/2d_ddpm/2d_ddpm_compare_schedulers.ipynb` | +| `generation/2d_ddpm/2d_ddpm_inpainting.ipynb` | +| `generation/2d_ddpm/2d_ddpm_tutorial.ipynb` | +| `generation/2d_ddpm/2d_ddpm_tutorial_ignite.ipynb` | +| `generation/2d_ddpm/2d_ddpm_tutorial_v_prediction.ipynb` | +| `generation/2d_diffusion_autoencoder/2d_diffusion_autoencoder_tutorial.ipynb` | +| `generation/2d_ldm/2d_ldm_tutorial.ipynb` | +| `generation/2d_super_resolution/2d_sd_super_resolution.ipynb` | +| `generation/2d_super_resolution/2d_sd_super_resolution_lightning.ipynb` | +| `generation/2d_vqgan/2d_vqgan_tutorial.ipynb` | +| `generation/2d_vqvae/2d_vqvae_tutorial.ipynb` | +| `generation/2d_vqvae_transformer/2d_vqvae_transformer_tutorial.ipynb` | +| `generation/3d_autoencoderkl/3d_autoencoderkl_tutorial.ipynb` | +| `generation/3d_ddpm/3d_ddpm_tutorial.ipynb` | +| `generation/3d_ldm/3d_ldm_tutorial.ipynb` | +| `generation/3d_vqvae/3d_vqvae_tutorial.ipynb` | +| `generation/anomaly_detection/2d_classifierfree_guidance_anomalydetection_tutorial.ipynb` | +| `generation/anomaly_detection/anomaly_detection_with_transformers.ipynb` | +| `generation/anomaly_detection/anomalydetection_tutorial_classifier_guidance.ipynb` | +| `generation/classifier_free_guidance/2d_ddpm_classifier_free_guidance_tutorial.ipynb` | +| `generation/controlnet/2d_controlnet.ipynb` | +| `generation/image_to_image_translation/tutorial_segmentation_with_ddpm.ipynb` | +| `generation/maisi/data/mask_augmentation_example.ipynb` | +| `generation/maisi/maisi_train_controlnet_tutorial.ipynb` | +| `generation/maisi/maisi_train_diff_unet_tutorial.ipynb` | +| `generation/maisi/maisi_train_vae_tutorial.ipynb` | +| `generation/realism_diversity_metrics/realism_diversity_metrics.ipynb` | +| `generation/spade_gan/spade_gan.ipynb` | +| `generation/spade_ldm/spade_ldm_brats.ipynb` | + +### 3b — 3D segmentation / AutoSeg training (6 notebooks) + +These notebooks train segmentation models (Spleen, BraTS, VISTA-3D). They need the +corresponding datasets to be available at the paths assumed by the notebook. + +| Notebook | +|---| +| `3d_segmentation/spleen_segmentation_3d_lightning.ipynb` | +| `3d_segmentation/unet_segmentation_3d_ignite.ipynb` | +| `auto3dseg/notebooks/auto3dseg_autorunner_ref_api.ipynb` | +| `auto3dseg/notebooks/auto3dseg_hello_world.ipynb` | +| `auto3dseg/notebooks/ensemble_byoc.ipynb` | +| `vista_3d/vista3d_spleen_finetune.ipynb` | + +### 3c — External service / tool dependency (7 notebooks) + +These notebooks require external services (tracking servers, serving frameworks, or desktop +applications) that are not available inside the Docker container. + +| Notebook | Service needed | +|---|---| +| `experiment_management/bundle_integrate_mlflow.ipynb` | MLflow tracking server | +| `experiment_management/spleen_segmentation_mlflow.ipynb` | MLflow tracking server | +| `experiment_management/spleen_segmentation_aim.ipynb` | AIM tracking server | +| `deployment/bentoml/mednist_classifier_bentoml.ipynb` | BentoML serving framework | +| `monailabel/monailabel_vista2d_cell_segmentation_CellProfiler.ipynb` | MONAILabel server + CellProfiler | +| `modules/omniverse/omniverse_integration.ipynb` | NVIDIA Omniverse (desktop app) | +| `hugging_face/hugging_face_pipeline_for_monai.ipynb` | HuggingFace model hub / `transformers` pipeline | + +### 3d — MONAI core modules / data loading (48 notebooks) + +These are general-purpose tutorials covering transforms, networks, datasets, and workflows. +Likely failures are data download errors (missing network access or cached data), or import +errors from packages that changed API between versions. Requires `2>&1` re-run to diagnose. + +| Notebook | +|---| +| `2d_regression/image_restoration.ipynb` | +| `bundle/05_spleen_segmentation_lightning.ipynb` | +| `computer_assisted_intervention/endoscopic_inbody_classification.ipynb` | +| `microscopy/multichannel_microscopy_classification.ipynb` | +| `modules/2d_inference_3d_volume.ipynb` | +| `modules/2d_slices_from_3d_sampling.ipynb` | +| `modules/2d_slices_from_3d_training.ipynb` | +| `modules/3d_image_transforms.ipynb` | +| `modules/UNet_input_size_constraints.ipynb` | +| `modules/autoencoder_mednist.ipynb` | +| `modules/batch_output_transform.ipynb` | +| `modules/bending_energy_diffusion_loss_notes.ipynb` | +| `modules/cross_validation_models_ensemble.ipynb` | +| `modules/csv_datasets.ipynb` | +| `modules/decollate_batch.ipynb` | +| `modules/developer_guide.ipynb` | +| `modules/dice_loss_metric_notes.ipynb` | +| `modules/image_dataset.ipynb` | +| `modules/integrate_3rd_party_transforms.ipynb` | +| `modules/interpretability/cats_and_dogs.ipynb` | +| `modules/interpretability/class_lung_lesion.ipynb` *(also PEP8)* | +| `modules/interpretability/covid_classification.ipynb` | +| `modules/inverse_transforms_and_test_time_augmentations.ipynb` | +| `modules/jupyter_utils.ipynb` | +| `modules/layer_wise_learning_rate.ipynb` | +| `modules/lazy_resampling_benchmark.ipynb` | +| `modules/lazy_resampling_compose.ipynb` | +| `modules/lazy_resampling_functional.ipynb` | +| `modules/learning_rate.ipynb` | +| `modules/load_medical_images.ipynb` | +| `modules/mednist_GAN_tutorial.ipynb` | +| `modules/mednist_GAN_workflow_array.ipynb` | +| `modules/mednist_GAN_workflow_dict.ipynb` | +| `modules/network_api.ipynb` | +| `modules/network_contraints/unet_plusplus.ipynb` | +| `modules/nifti_read_example.ipynb` | +| `modules/postprocessing_transforms.ipynb` | +| `modules/public_datasets.ipynb` | +| `modules/resample_benchmark.ipynb` | +| `modules/tcia_csv_processing.ipynb` | +| `modules/torch_compile.ipynb` | +| `modules/transforms_demo_2d.ipynb` | +| `modules/transforms_metatensor.ipynb` | +| `modules/varautoencoder_mednist.ipynb` | +| `modules/workflow_profiling.ipynb` | +| `patch_inferer/modular_patch_inferer.ipynb` | +| `pathology/tumor_detection/ignite/profiling_camelyon_pipeline.ipynb` | + +--- + +## Environment Notes + +Key changes made to the Docker image to reach this test run (from baseline `nvcr.io/nvidia/pytorch:25.03-py3`): + +| Issue | Fix applied | +|---|---| +| `No module named pkg_resources` during build (MetricsReloaded, segment-anything) | `PIP_CONSTRAINT` with `setuptools<71` propagates to pip's isolated build envs | +| RTX 5090 SM_120 not supported | Rebased from `nvcr.io/nvidia/pytorch:24.10-py3` → `25.03-py3` | +| `torch.patch` for ONNX bug (24.10 only) | Removed | +| Python 3.12 markers excluded `cucim`, `transformers`, `onnxruntime` | Removed `python_version <= '3.10'` caps in `requirements-dev.txt` | +| Container's `jupytext==1.16.7` blocked tutorial runner | Rebuilt `/etc/pip/constraint.txt`, kept only `numpy==1.26.4` + `setuptools<71` | +| Container's `isort==6.0.1` conflicted with MONAI's `isort<6.0` | Same constraint file rebuild | +| NumPy 2.x broke PyTorch's C-extension bridge in DataLoader workers | `numpy==1.26.4` pin retained (nv25.03 PyTorch compiled against NumPy 1.x) | +| GPU allowlist check (`NVIDIA_DISABLE_REQUIRE`) | Launch with `-e NVIDIA_DISABLE_REQUIRE=true --entrypoint bash` | + +### Working docker run command + +```bash +docker --context default run --gpus all --rm \ + --entrypoint bash \ + -e NVIDIA_DISABLE_REQUIRE=true \ + --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 --ulimit nofile=65536:65536 \ + -v /data/rgd/tutorials:/opt/tutorials \ + -v /data/rgd/MONAI:/opt/monai \ + monai_1_6:latest \ + -c "cd /opt/tutorials && bash runner.sh -t 2>&1" +``` + +> `--ulimit nofile=65536:65536` is required for `modules/public_datasets.ipynb` (DataLoader +> workers pass file descriptors via Unix sockets; the default container limit of 1024 is too low). +> `2>&1` captures papermill tracebacks that would otherwise be invisible. + +--- + +## Rerun Results (stderr captured) — 2026-06-11 + +A targeted rerun of the 80 "our-only" failing notebooks was performed with +`2>&1 | tee` to capture papermill tracebacks. +Script: `run_our_only.sh` | Log: `runner_output_our_only.logs` + +### Outcome + +| Result | Count | +|---|---| +| Passed | **65** | +| Failed | **15** | +| Total targeted | 80 | + +**All 30 generation notebooks passed** (they download their own small synthetic datasets, +writing ~3.7 GB to `tutorials/generation/`). The unknown "ExecutionError" group is now +fully explained. + +### The 15 remaining failures + +#### Group R1 — mlflow 3.13.0 broken on Python 3.12 (4 notebooks) + +`mlflow 3.13.0` (installed in the image) fails on Python 3.12 with: +``` +ImportError: attempted relative import beyond top-level package +``` +The error originates inside `mlflow.utils.uv_utils` which performs a relative +`from .. import zipp` that is invalid at top-level scope in Python 3.12. + +| Notebook | Where mlflow is used | +|---|---| +| `3d_segmentation/unet_segmentation_3d_ignite.ipynb` | `MLFlowHandler` optional import | +| `auto3dseg/notebooks/auto3dseg_hello_world.ipynb` | bundled `train.py` imports mlflow | +| `auto3dseg/notebooks/ensemble_byoc.ipynb` | bundled `train.py` imports mlflow | +| `experiment_management/spleen_segmentation_mlflow.ipynb` | direct `import mlflow` | + +**Fix:** pin `mlflow<3.0` in the Dockerfile (or constraint file): +```dockerfile +RUN pip install "mlflow<3.0" +``` +Eric passes these notebooks — his environment likely has an older mlflow. + +#### Group R2 — Disk full `OSError: [Errno 28] No space left on device` (4 notebooks) + +During the first rerun the generation notebooks wrote ~3.7 GB to `tutorials/generation/`, +consuming enough space to cause `Errno 28` for subsequent data-downloading notebooks. + +| Notebook | What it tried to write | +|---|---| +| `deep_atlas/deep_atlas_tutorial.ipynb` | OASIS dataset (~2 GB) | +| `deployment/bentoml/mednist_classifier_bentoml.ipynb` | MedNIST dataset | +| `experiment_management/bundle_integrate_mlflow.ipynb` | Spleen bundle run artefacts (ran 221 min before failing) | +| `microscopy/multichannel_microscopy_classification.ipynb` | Pre-trained DenseNet169 weights | + +**This is a run-order artifact, not a persistent issue on this host.** The root +filesystem has 39 GB free and the 3.7 GB generation datasets are now cached. On +subsequent runs with the generation data already present these notebooks complete +normally — confirmed by rerun on 2026-06-11 (`runner_output_rerun_r2r7r8.logs`). +Note: `bundle_integrate_mlflow` also requires the mlflow fix (Group R1) to be in +the rebuilt image before it can complete. + +#### Group R3 — transformers 5.10.2 + PyTorch nv25.03 incompatibility (1 notebook) + +`transformers 5.10.2` references `torch.float8_e8m0fnu` which does not exist in +PyTorch 2.7.0a0+nv25.03, causing import of `PreTrainedModel` to fail. + +| Notebook | Error | +|---|---| +| `hugging_face/hugging_face_pipeline_for_monai.ipynb` | `ModuleNotFoundError: Could not import module 'PreTrainedModel'` (caused by `AttributeError: module 'torch' has no attribute 'float8_e8m0fnu'`) | + +**Fix:** Pin `transformers<5.0` in constraint file, or wait for nv25 PyTorch update. +Eric's PyTorch 2.12+cu130 supports `float8_e8m0fnu`; ours does not. + +#### Group R4 — Missing MONAI module (1 notebook) + +| Notebook | Error | +|---|---| +| `2d_regression/image_restoration.ipynb` | `ModuleNotFoundError: No module named 'monai.networks.nets.restormer'` | + +`Restormer` is not yet present in our MONAI dev branch (19cab577). Eric is on +eccefc57 (+143 commits) which may already include it, or the notebook needs updating. + +**Fix:** Cherry-pick the Restormer commit into the dev branch, or add the +notebook to `skip_run_papermill` until the class is merged. + +#### Group R5 — MONAI `bundle.load` API change (1 notebook) + +| Notebook | Error | +|---|---| +| `computer_assisted_intervention/endoscopic_inbody_classification.ipynb` | `AttributeError: 'collections.OrderedDict' object has no attribute 'train'` | + +`monai.bundle.load(name="endoscopic_inbody_classification")` returns an +`OrderedDict` (the raw state dict) in our branch but the notebook calls +`.train()` on it expecting a full `nn.Module`. + +**Fix (notebook):** Replace +```python +pretrained_model = monai.bundle.load(name="endoscopic_inbody_classification", bundle_dir="./") +pretrained_model.train() +``` +with +```python +bundle = monai.bundle.load(name="endoscopic_inbody_classification", bundle_dir="./", + return_state_dict=False) # or use BundleWorkflow +``` +**Fix (MONAI):** Verify whether `bundle.load` is supposed to return a model or a +state dict and align the API with the notebook expectation. + +#### Group R6 — Missing `aim` package (1 notebook) + +| Notebook | Error | +|---|---| +| `experiment_management/spleen_segmentation_aim.ipynb` | `ModuleNotFoundError: No module named 'aim'` | + +**Fix:** Add `aim` to `requirements-dev.txt` and reinstall in the image. + +#### Group R7 — pytorch-lightning → mlflow import chain failure (1 notebook) + +| Notebook | Error | +|---|---| +| `bundle/05_spleen_segmentation_lightning.ipynb` | First run: `ContentTooShortError` (89 min download truncated). Rerun with `--ulimit nofile=65536:65536`: download succeeds in 6 min but training cell fails with `OptionalImportError: from scripts.main import train (No module named 'pytorch_lightning')`. | + +**Root cause chain:** +1. Notebook installs `pytorch-lightning~=2.0.0` → installs 2.0.9 +2. `pytorch_lightning` 2.0.x eagerly imports `mlflow` at module level (via `pytorch_lightning.loggers.mlflow`) +3. mlflow 3.13.0 fails to initialize under Python 3.12 (same R1 root cause) +4. Result: `import pytorch_lightning` fails in the `%%bash` training subprocess + +**Fix:** Change `!pip install -q pytorch-lightning~=2.0.0` → `!pip install -q "pytorch-lightning>=2.1"`. +pytorch-lightning ≥ 2.1 uses lazy mlflow imports; tested with 2.6.5, training and evaluation pass. +The original download truncation (ContentTooShortError) was due to fd limits (R8) and is also resolved with `--ulimit nofile=65536:65536`. + +#### Group R8 — Socket resource exhaustion (1 notebook) + +| Notebook | Error | +|---|---| +| `modules/public_datasets.ipynb` | `RuntimeError: received 0 items of ancdata` | + +PyTorch DataLoader failed to pass file descriptors through Unix sockets between +the main process and worker processes (ancillary data = file-descriptor passing). +This happens when the per-process open-file-descriptor limit is too low +(Docker default: 1024; DataLoader workers need ~65 k). + +**Fix:** Add `--ulimit nofile=65536:65536` to the docker run command (already +reflected in the working command above). Confirmed fixed in rerun +`runner_output_rerun_r2r7r8.logs`. + +#### Group R9 — MissingKeyword (1 notebook) + +| Notebook | Error | +|---|---| +| `auto3dseg/notebooks/msd_crossval_datalist_generator.ipynb` | `max_epochs` not found; not in exemption list | + +Known issue (documented in Category 2 above). Add to `doesnt_contain_max_epochs`. + +--- + +## Recommended Next Steps + +1. **Pin `mlflow<3.0`** in the Dockerfile — fixes 4 notebooks (Group R1). ✓ DONE (PR #8912) +2. **R2 is a run-order artifact** — not applicable on this host (39 GB free, data cached). +3. **`--ulimit nofile=65536:65536`** added to working docker run command — fixes R8. ✓ DONE +4. **PEP8 autofix** — all three notebooks autofixed with `runner.sh --autofix`. ✓ DONE +5. **Fix MissingKeyword** — `msd_crossval_datalist_generator.ipynb` added to exemption list. ✓ DONE (PR #2065) +6. **Pin `transformers<5.0`** — fixes R3. ✓ DONE (PR #8912) +7. **Add `aim`** to `requirements-dev.txt` — fixes R6. ✓ DONE (PR #8912) +8. **Fix `bundle.load` API** (R5) — `return_state_dict=False` added to notebook. ✓ DONE (PR #2065) +9. **Skip `image_restoration.ipynb`** until Restormer is merged (R4). ✓ DONE (PR #2065) +10. **Fix R7** — `pytorch-lightning>=2.1` pin in `bundle/05_spleen_segmentation_lightning.ipynb`. ✓ DONE (PR #2065) + +### Priority order + +| Priority | Action | Impact | Status | +|---|---|---|---| +| High | Pin `mlflow<3.0` (Dockerfile rebuild) | +4 passes | ✓ Done (PR #8912) | +| High | R2 disk-full | +4 passes | ✓ Not an issue (run-order artifact) | +| Medium | `--ulimit nofile=65536:65536` in docker run | +1 pass | ✓ Done | +| Medium | Add `msd_crossval_datalist_generator` to exemption | +1 pass | ✓ Done (PR #2065) | +| Medium | Pin `transformers<5.0` | +1 pass | ✓ Done (PR #8912) | +| Low | Add `aim` to requirements | +1 pass | ✓ Done (PR #8912) | +| Low | Fix `bundle.load` in endoscopic notebook | +1 pass | ✓ Done (PR #2065) | +| Low | PEP8 autofix (3 notebooks) | 0 fails eliminated | ✓ Done | +| Low | Skip `image_restoration.ipynb` (Restormer missing) | +1 pass | ✓ Done (PR #2065) | +| Low | Fix Spleen Lightning notebook (`pytorch-lightning>=2.1`) | +1 pass | ✓ Done (PR #2065) | + +--- + +## Fixes Applied (2026-06-11) + +Changes committed to bring Docker run to parity with Eric's run: + +### MONAI repo (`/data/rgd/MONAI`) + +| File | Change | +|---|---| +| `Dockerfile` | Base image: `24.10-py3` → `25.03-py3`; rebuild pip constraint file (keep `numpy==1.26.4`, add `setuptools<71`); install `papermill jupytext autopep8 autoflake ipywidgets`; pin `mlflow<3.0`, `transformers<5.0`; add `aim`, `lightning>=2.0` | +| `requirements-dev.txt` | Pin `transformers<5.0`; pin `mlflow<3.0`; add `aim`; add `lightning>=2.0`; remove `python_version<=3.10` caps from `cucim`, `onnxruntime`, `transformers` | + +### Tutorials repo (`/data/rgd/tutorials`) + +| File | Change | +|---|---| +| `runner.sh` | Add `msd_crossval_datalist_generator.ipynb` and `hovernet_infer_compare.ipynb` to `doesnt_contain_max_epochs`; add `image_restoration.ipynb` to `skip_run_papermill` | +| `computer_assisted_intervention/endoscopic_inbody_classification.ipynb` | Pass `return_state_dict=False` to `monai.bundle.load` so it returns `nn.Module` instead of `OrderedDict` | +| `bundle/05_spleen_segmentation_lightning.ipynb` | Change `pytorch-lightning~=2.0.0` → `pytorch-lightning>=2.1` to avoid mlflow eager-import failure (R7) | + +### Still pending (require environment changes or separate PRs) + +| Issue | Action needed | +|---|---| +| Disk space (R2) | Free `/data` disk or bind-mount scratch volume; `deep_atlas` (~2 GB), `deployment/bentoml`, `experiment_management/bundle_integrate_mlflow`, `microscopy` notebooks | +| Socket FD limit (R8) | Add `--ulimit nofile=65536:65536` to docker run invocation | +| pytorch-lightning/mlflow import chain (R7) | ✓ Fixed: `pytorch-lightning>=2.1` in notebook (PR #2065) | +| PEP8 in 3 notebooks | Run `bash runner.sh --autofix` for `surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb`, `deep_atlas/deep_atlas_tutorial.ipynb`, `modules/interpretability/class_lung_lesion.ipynb` | +| Restormer in MONAI dev | Cherry-pick Restormer network class commit; remove from skip list once merged | From f3f49ff0a2a7514e5e523ee4c97663561d06fc82 Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 13:36:46 +0100 Subject: [PATCH 5/9] fix: revert return_state_dict change; update R5/R8 diagnostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Revert return_state_dict=False from endoscopic_inbody_classification.ipynb: the upstream MONAI dev (≥1.5) removed the deprecated param entirely and load() now returns nn.Module by default. The extra kwarg caused a TypeError in CI. The original notebook is correct for MONAI ≥1.5. - Update diagnose_1_6_release.md: - R5: clarify it is a local-only issue (our MONAI @ 19cab577 still has the deprecated return_state_dict=True default; upstream dev does not) - R8: mark confirmed fixed — isolated run with --ulimit nofile=65536:65536 completed all 39 cells in 3m1s with no ancdata error (2026-06-11) Signed-off-by: R. Garcia-Dias --- .../endoscopic_inbody_classification.ipynb | 4 +- diagnose_1_6_release.md | 53 ++++++++++--------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb index 95d96f691..6a5999046 100644 --- a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb +++ b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb @@ -347,7 +347,7 @@ "id": "4784fe9e", "metadata": {}, "outputs": [], - "source": "max_epochs = 5\n\n# return_state_dict=False returns the nn.Module rather than a raw OrderedDict (MONAI 1.6 API)\npretrained_model = monai.bundle.load(name=\"endoscopic_inbody_classification\", bundle_dir=\"./\", return_state_dict=False)\n\npretrained_model.train()\nlosses = []\n\nfor _ in trange(max_epochs):\n epoch_loss = 0\n for data in train_dataloader:\n inputs, labels = data[\"image\"].to(device), data[\"label\"].to(device)\n optimizer.zero_grad()\n predictions = pretrained_model(inputs)\n loss_iter = loss(predictions, labels)\n loss_iter.backward()\n optimizer.step()\n epoch_loss += loss_iter.item()\n losses.append(epoch_loss / len(train_dataloader))\n\nfig, ax = plt.subplots(1, 1, figsize=(6, 6), facecolor=\"white\")\nax.set_xlabel(\"Epoch\")\nepochs = list(range(len(losses)))\nax.plot(epochs, losses, label=\"loss\")\nplt.legend()\nplt.show()" + "source": "max_epochs = 5\n\npretrained_model = monai.bundle.load(name=\"endoscopic_inbody_classification\", bundle_dir=\"./\")\n\npretrained_model.train()\nlosses = []\n\nfor _ in trange(max_epochs):\n epoch_loss = 0\n for data in train_dataloader:\n inputs, labels = data[\"image\"].to(device), data[\"label\"].to(device)\n optimizer.zero_grad()\n predictions = pretrained_model(inputs)\n loss_iter = loss(predictions, labels)\n loss_iter.backward()\n optimizer.step()\n epoch_loss += loss_iter.item()\n losses.append(epoch_loss / len(train_dataloader))\n\nfig, ax = plt.subplots(1, 1, figsize=(6, 6), facecolor=\"white\")\nax.set_xlabel(\"Epoch\")\nepochs = list(range(len(losses)))\nax.plot(epochs, losses, label=\"loss\")\nplt.legend()\nplt.show()" }, { "cell_type": "markdown", @@ -407,4 +407,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/diagnose_1_6_release.md b/diagnose_1_6_release.md index 261a37d5b..576d60ebf 100644 --- a/diagnose_1_6_release.md +++ b/diagnose_1_6_release.md @@ -318,28 +318,25 @@ eccefc57 (+143 commits) which may already include it, or the notebook needs upda **Fix:** Cherry-pick the Restormer commit into the dev branch, or add the notebook to `skip_run_papermill` until the class is merged. -#### Group R5 — MONAI `bundle.load` API change (1 notebook) +#### Group R5 — MONAI `bundle.load` API — local-only issue (1 notebook) -| Notebook | Error | +| Notebook | Error (local MONAI dev @ 19cab577 only) | |---|---| | `computer_assisted_intervention/endoscopic_inbody_classification.ipynb` | `AttributeError: 'collections.OrderedDict' object has no attribute 'train'` | -`monai.bundle.load(name="endoscopic_inbody_classification")` returns an -`OrderedDict` (the raw state dict) in our branch but the notebook calls -`.train()` on it expecting a full `nn.Module`. +`monai.bundle.load()` in our local MONAI dev branch (19cab577) has +`@deprecated_arg("return_state_dict", since="1.2", removed="1.5")` with +`return_state_dict=True` still active as the default, so it returns an +`OrderedDict` instead of an `nn.Module`. -**Fix (notebook):** Replace -```python -pretrained_model = monai.bundle.load(name="endoscopic_inbody_classification", bundle_dir="./") -pretrained_model.train() -``` -with -```python -bundle = monai.bundle.load(name="endoscopic_inbody_classification", bundle_dir="./", - return_state_dict=False) # or use BundleWorkflow -``` -**Fix (MONAI):** Verify whether `bundle.load` is supposed to return a model or a -state dict and align the API with the notebook expectation. +**This is a local-environment-only issue.** The upstream MONAI dev branch +(eccefc57, used by CI and the upstream Docker image) removed the +`return_state_dict` parameter in MONAI 1.5, and `load()` now returns `nn.Module` +by default. The notebook is correct as-is for any MONAI ≥ 1.5. + +**No notebook fix needed.** The `return_state_dict=False` workaround that was +previously applied broke CI because the upstream MONAI does not accept that +parameter at all (`TypeError: unexpected keyword argument`). It has been reverted. #### Group R6 — Missing `aim` package (1 notebook) @@ -377,8 +374,14 @@ This happens when the per-process open-file-descriptor limit is too low (Docker default: 1024; DataLoader workers need ~65 k). **Fix:** Add `--ulimit nofile=65536:65536` to the docker run command (already -reflected in the working command above). Confirmed fixed in rerun -`runner_output_rerun_r2r7r8.logs`. +reflected in the working command above). + +**Rerun note:** The targeted rerun (`runner_output_rerun_r2r7r8.logs`) ran `public_datasets` in +the same container as `deep_atlas`. That notebook pip-installs packages which upgraded `urllib3` +to 2.x; `papermill` then failed to import immediately (`ModuleNotFoundError: No module named +'urllib3.packages.six.moves'`) — a run-order contamination, **not** the ancdata fix being tested. +**Confirmed fixed** in isolated run (container with `--ulimit nofile=65536:65536`, no shared +container): all 39 cells passed, `real 3m1s`. No `ancdata` error observed. #### Group R9 — MissingKeyword (1 notebook) @@ -394,12 +397,12 @@ Known issue (documented in Category 2 above). Add to `doesnt_contain_max_epochs` 1. **Pin `mlflow<3.0`** in the Dockerfile — fixes 4 notebooks (Group R1). ✓ DONE (PR #8912) 2. **R2 is a run-order artifact** — not applicable on this host (39 GB free, data cached). -3. **`--ulimit nofile=65536:65536`** added to working docker run command — fixes R8. ✓ DONE +3. **`--ulimit nofile=65536:65536`** added to working docker run command — fixes R8. ✓ DONE (confirmed clean run 3m1s) 4. **PEP8 autofix** — all three notebooks autofixed with `runner.sh --autofix`. ✓ DONE 5. **Fix MissingKeyword** — `msd_crossval_datalist_generator.ipynb` added to exemption list. ✓ DONE (PR #2065) 6. **Pin `transformers<5.0`** — fixes R3. ✓ DONE (PR #8912) 7. **Add `aim`** to `requirements-dev.txt` — fixes R6. ✓ DONE (PR #8912) -8. **Fix `bundle.load` API** (R5) — `return_state_dict=False` added to notebook. ✓ DONE (PR #2065) +8. **R5 is local-only** — no notebook fix needed; upstream MONAI ≥ 1.5 removed the deprecated param and `load()` returns `nn.Module` directly. ✓ CONFIRMED (reverted wrong fix) 9. **Skip `image_restoration.ipynb`** until Restormer is merged (R4). ✓ DONE (PR #2065) 10. **Fix R7** — `pytorch-lightning>=2.1` pin in `bundle/05_spleen_segmentation_lightning.ipynb`. ✓ DONE (PR #2065) @@ -409,11 +412,11 @@ Known issue (documented in Category 2 above). Add to `doesnt_contain_max_epochs` |---|---|---|---| | High | Pin `mlflow<3.0` (Dockerfile rebuild) | +4 passes | ✓ Done (PR #8912) | | High | R2 disk-full | +4 passes | ✓ Not an issue (run-order artifact) | -| Medium | `--ulimit nofile=65536:65536` in docker run | +1 pass | ✓ Done | +| Medium | `--ulimit nofile=65536:65536` in docker run | +1 pass | ✓ Done (confirmed, 3m1s clean run) | | Medium | Add `msd_crossval_datalist_generator` to exemption | +1 pass | ✓ Done (PR #2065) | | Medium | Pin `transformers<5.0` | +1 pass | ✓ Done (PR #8912) | | Low | Add `aim` to requirements | +1 pass | ✓ Done (PR #8912) | -| Low | Fix `bundle.load` in endoscopic notebook | +1 pass | ✓ Done (PR #2065) | +| Low | R5 `bundle.load` API — local-only, no fix needed | +1 pass (upstream) | ✓ Confirmed (reverted bad fix) | | Low | PEP8 autofix (3 notebooks) | 0 fails eliminated | ✓ Done | | Low | Skip `image_restoration.ipynb` (Restormer missing) | +1 pass | ✓ Done (PR #2065) | | Low | Fix Spleen Lightning notebook (`pytorch-lightning>=2.1`) | +1 pass | ✓ Done (PR #2065) | @@ -436,7 +439,7 @@ Changes committed to bring Docker run to parity with Eric's run: | File | Change | |---|---| | `runner.sh` | Add `msd_crossval_datalist_generator.ipynb` and `hovernet_infer_compare.ipynb` to `doesnt_contain_max_epochs`; add `image_restoration.ipynb` to `skip_run_papermill` | -| `computer_assisted_intervention/endoscopic_inbody_classification.ipynb` | Pass `return_state_dict=False` to `monai.bundle.load` so it returns `nn.Module` instead of `OrderedDict` | +| `computer_assisted_intervention/endoscopic_inbody_classification.ipynb` | Reverted `return_state_dict=False` — upstream MONAI ≥1.5 already returns `nn.Module` by default; the extra kwarg caused `TypeError` in CI | | `bundle/05_spleen_segmentation_lightning.ipynb` | Change `pytorch-lightning~=2.0.0` → `pytorch-lightning>=2.1` to avoid mlflow eager-import failure (R7) | ### Still pending (require environment changes or separate PRs) @@ -444,7 +447,7 @@ Changes committed to bring Docker run to parity with Eric's run: | Issue | Action needed | |---|---| | Disk space (R2) | Free `/data` disk or bind-mount scratch volume; `deep_atlas` (~2 GB), `deployment/bentoml`, `experiment_management/bundle_integrate_mlflow`, `microscopy` notebooks | -| Socket FD limit (R8) | Add `--ulimit nofile=65536:65536` to docker run invocation | +| Socket FD limit (R8) | ✓ Confirmed fixed — `--ulimit nofile=65536:65536` resolves ancdata error; isolated run completed in 3m1s (2026-06-11) | | pytorch-lightning/mlflow import chain (R7) | ✓ Fixed: `pytorch-lightning>=2.1` in notebook (PR #2065) | | PEP8 in 3 notebooks | Run `bash runner.sh --autofix` for `surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb`, `deep_atlas/deep_atlas_tutorial.ipynb`, `modules/interpretability/class_lung_lesion.ipynb` | | Restormer in MONAI dev | Cherry-pick Restormer network class commit; remove from skip list once merged | From a581217a8aa01701f42cd6ac03868b893b1a469b Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 14:10:35 +0100 Subject: [PATCH 6/9] style: add trailing newline to endoscopic_inbody_classification.ipynb Signed-off-by: R. Garcia-Dias --- .../endoscopic_inbody_classification.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb index 6a5999046..1b9f071e7 100644 --- a/computer_assisted_intervention/endoscopic_inbody_classification.ipynb +++ b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb @@ -407,4 +407,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} From c62cc063f9a681537377b5f5b1602bca7c54d824 Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 14:47:31 +0100 Subject: [PATCH 7/9] fix: skip 05_spleen_segmentation_lightning in CPU CI The notebook calls .to(device) where device is CUDA unconditionally; no CPU fallback exists. Fails with AssertionError: Torch not compiled with CUDA enabled on the CPU-only GitHub Actions runner. Signed-off-by: R. Garcia-Dias --- runner.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/runner.sh b/runner.sh index 0474f124a..92104ef4d 100755 --- a/runner.sh +++ b/runner.sh @@ -138,6 +138,7 @@ skip_run_papermill=("${skip_run_papermill[@]}" .*finetune_vista3d_for_hugging_fa skip_run_papermill=("${skip_run_papermill[@]}" .*TCIA_PROSTATEx_Prostate_MRI_Anatomy_Model.ipynb*) # https://github.com/Project-MONAI/tutorials/issues/2029 skip_run_papermill=("${skip_run_papermill[@]}" .*maisi_inference_tutorial.ipynb*) skip_run_papermill=("${skip_run_papermill[@]}" .*image_restoration.ipynb*) # monai.networks.nets.restormer not yet in dev branch +skip_run_papermill=("${skip_run_papermill[@]}" .*05_spleen_segmentation_lightning*) # requires GPU; hardcoded .to("cuda") with no CPU fallback # output formatting separator="" From 3d198d814d3857620a13dcd95069411bd05a125a Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 15:05:58 +0100 Subject: [PATCH 8/9] fix: skip deep_atlas_tutorial in CPU CI deep_atlas_tutorial.ipynb hardcodes device = torch.device("cuda:0") with no CPU fallback; fails with AssertionError: Torch not compiled with CUDA enabled on the CPU-only GitHub Actions runner. Signed-off-by: R. Garcia-Dias --- runner.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/runner.sh b/runner.sh index 92104ef4d..ae4f6d85b 100755 --- a/runner.sh +++ b/runner.sh @@ -139,6 +139,7 @@ skip_run_papermill=("${skip_run_papermill[@]}" .*TCIA_PROSTATEx_Prostate_MRI_Ana skip_run_papermill=("${skip_run_papermill[@]}" .*maisi_inference_tutorial.ipynb*) skip_run_papermill=("${skip_run_papermill[@]}" .*image_restoration.ipynb*) # monai.networks.nets.restormer not yet in dev branch skip_run_papermill=("${skip_run_papermill[@]}" .*05_spleen_segmentation_lightning*) # requires GPU; hardcoded .to("cuda") with no CPU fallback +skip_run_papermill=("${skip_run_papermill[@]}" .*deep_atlas_tutorial*) # requires GPU; device hardcoded to "cuda:0" # output formatting separator="" From d38d10149e5e7f1c81164d5556e9f8b20cd1e6be Mon Sep 17 00:00:00 2001 From: "R. Garcia-Dias" Date: Thu, 11 Jun 2026 15:35:15 +0100 Subject: [PATCH 9/9] fix: remove non-existent hovernet_infer_compare from doesnt_contain_max_epochs; fix stale pending table - runner.sh: hovernet_infer_compare.ipynb does not exist in the repo; the exemption was a dead entry that could never match. Removed. - diagnose_1_6_release.md: PEP8 row removed from the 'Still pending' table (autofix was already applied and marked done at line 401). Also updated runner.sh change summary to reflect the actual skip list entries (deep_atlas_tutorial, 05_spleen_segmentation_lightning). Signed-off-by: R. Garcia-Dias --- diagnose_1_6_release.md | 3 +-- runner.sh | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/diagnose_1_6_release.md b/diagnose_1_6_release.md index 576d60ebf..79d0e0c4c 100644 --- a/diagnose_1_6_release.md +++ b/diagnose_1_6_release.md @@ -438,7 +438,7 @@ Changes committed to bring Docker run to parity with Eric's run: | File | Change | |---|---| -| `runner.sh` | Add `msd_crossval_datalist_generator.ipynb` and `hovernet_infer_compare.ipynb` to `doesnt_contain_max_epochs`; add `image_restoration.ipynb` to `skip_run_papermill` | +| `runner.sh` | Add `msd_crossval_datalist_generator.ipynb` to `doesnt_contain_max_epochs`; add `image_restoration.ipynb`, `05_spleen_segmentation_lightning.ipynb`, `deep_atlas_tutorial.ipynb` to `skip_run_papermill` | | `computer_assisted_intervention/endoscopic_inbody_classification.ipynb` | Reverted `return_state_dict=False` — upstream MONAI ≥1.5 already returns `nn.Module` by default; the extra kwarg caused `TypeError` in CI | | `bundle/05_spleen_segmentation_lightning.ipynb` | Change `pytorch-lightning~=2.0.0` → `pytorch-lightning>=2.1` to avoid mlflow eager-import failure (R7) | @@ -449,5 +449,4 @@ Changes committed to bring Docker run to parity with Eric's run: | Disk space (R2) | Free `/data` disk or bind-mount scratch volume; `deep_atlas` (~2 GB), `deployment/bentoml`, `experiment_management/bundle_integrate_mlflow`, `microscopy` notebooks | | Socket FD limit (R8) | ✓ Confirmed fixed — `--ulimit nofile=65536:65536` resolves ancdata error; isolated run completed in 3m1s (2026-06-11) | | pytorch-lightning/mlflow import chain (R7) | ✓ Fixed: `pytorch-lightning>=2.1` in notebook (PR #2065) | -| PEP8 in 3 notebooks | Run `bash runner.sh --autofix` for `surgtoolloc/preprocess_detect_scene_and_split_fold.ipynb`, `deep_atlas/deep_atlas_tutorial.ipynb`, `modules/interpretability/class_lung_lesion.ipynb` | | Restormer in MONAI dev | Cherry-pick Restormer network class commit; remove from skip list once merged | diff --git a/runner.sh b/runner.sh index ae4f6d85b..431cc9ecc 100755 --- a/runner.sh +++ b/runner.sh @@ -85,7 +85,6 @@ doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" realism_diversity_m doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" omniverse_integration.ipynb) doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" hugging_face_pipeline_for_monai.ipynb) doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" msd_crossval_datalist_generator.ipynb) # inference/datalist-only notebook, no training loop -doesnt_contain_max_epochs=("${doesnt_contain_max_epochs[@]}" hovernet_infer_compare.ipynb) # inference-only notebook # Execution of the notebook in these folders / with the filename cannot be automated skip_run_papermill=()