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/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/computer_assisted_intervention/endoscopic_inbody_classification.ipynb b/computer_assisted_intervention/endoscopic_inbody_classification.ipynb index fb97c7f47..1b9f071e7 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\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", 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/diagnose_1_6_release.md b/diagnose_1_6_release.md new file mode 100644 index 000000000..79d0e0c4c --- /dev/null +++ b/diagnose_1_6_release.md @@ -0,0 +1,452 @@ +# 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 — local-only issue (1 notebook) + +| 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()` 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`. + +**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) + +| 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). + +**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) + +| 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 (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. **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) + +### 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 (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 | 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) | + +--- + +## 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` 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) | + +### 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) | ✓ 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) | +| Restormer in MONAI dev | Cherry-pick Restormer network class commit; remove from skip list once merged | 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", diff --git a/runner.sh b/runner.sh index 3296299fd..431cc9ecc 100755 --- a/runner.sh +++ b/runner.sh @@ -84,6 +84,7 @@ 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 # Execution of the notebook in these folders / with the filename cannot be automated skip_run_papermill=() @@ -135,6 +136,9 @@ 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 +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=""