From c8ef1bd8be8ba81440ea058baaffe0432c8d1251 Mon Sep 17 00:00:00 2001 From: luandalmazo Date: Mon, 3 Aug 2026 13:53:04 -0300 Subject: [PATCH] update notebooks --- .../01_getting_started/01_upload_data.ipynb | 40 +-------------- .../01_getting_started/02_explore_data.ipynb | 31 +----------- .../01_upload_annotations.ipynb | 37 +++----------- .../02_geometry_annotations.ipynb | 37 ++------------ .../02_model_registry.ipynb | 11 +--- .../05_deployment/03_validate_model.ipynb | 20 ++------ .../full_3d/02_synapse_nnunet.ipynb | 50 +------------------ 7 files changed, 21 insertions(+), 205 deletions(-) diff --git a/notebooks/01_getting_started/01_upload_data.ipynb b/notebooks/01_getting_started/01_upload_data.ipynb index ceecea8e..deb58ac7 100644 --- a/notebooks/01_getting_started/01_upload_data.ipynb +++ b/notebooks/01_getting_started/01_upload_data.ipynb @@ -326,43 +326,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "# Get some resources to add to a project\n", - "tutorial_resources = list(api.resources.get_list(\n", - " tags=['tutorial'],\n", - " status='inbox'\n", - "))\n", - "\n", - "if tutorial_resources:\n", - " resource_ids_for_project = [r.id for r in tutorial_resources[:3]] # Take first 3 resources\n", - "\n", - " # Create a new project\n", - " try:\n", - " project_id = api.projects.create(\n", - " name=\"Tutorial Project\",\n", - " description=\"A project created for demonstration purposes\",\n", - " resources_ids=resource_ids_for_project\n", - " )\n", - " project = api.projects.get_by_id(project_id)\n", - "\n", - " print(f\"Created project: {project.name} (ID: {project.id})\")\n", - "\n", - " # List all projects\n", - " all_projects = api.projects.get_list()\n", - " print(f\"\\nAll projects ({len(all_projects)}):\")\n", - " for proj in all_projects:\n", - " print(f\" - {proj.name} (ID: {proj.id})\")\n", - "\n", - " except Exception as e:\n", - " print(f\"Error creating project (may already exist): {e}\")\n", - "\n", - " # Try to find existing project\n", - " existing_project = api.projects.get_by_name(\"Tutorial Project\")\n", - " if existing_project:\n", - " print(f\"Found existing project: {existing_project.name}\")\n", - "else:\n", - " print(\"No tutorial resources found to add to project\")" - ] + "source": "# Get some resources to add to a project\ntutorial_resources = list(api.resources.get_list(\n tags=['tutorial'],\n status='inbox'\n))\n\nif tutorial_resources:\n resource_ids_for_project = [r.id for r in tutorial_resources[:3]] # Take first 3 resources\n\n # Create a new project (exists_ok returns the existing project instead of raising)\n project = api.projects.create(\n name=\"Tutorial Project\",\n description=\"A project created for demonstration purposes\",\n resource_ids=resource_ids_for_project,\n exists_ok=True\n )\n\n print(f\"Created project: {project.name} (ID: {project.id})\")\n\n # List all projects\n all_projects = api.projects.get_list()\n print(f\"\\nAll projects ({len(all_projects)}):\")\n for proj in all_projects:\n print(f\" - {proj.name} (ID: {proj.id})\")\nelse:\n print(\"No tutorial resources found to add to project\")" }, { "cell_type": "markdown", @@ -437,4 +401,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/notebooks/01_getting_started/02_explore_data.ipynb b/notebooks/01_getting_started/02_explore_data.ipynb index 50e47a34..679c3204 100644 --- a/notebooks/01_getting_started/02_explore_data.ipynb +++ b/notebooks/01_getting_started/02_explore_data.ipynb @@ -445,34 +445,7 @@ "id": "175ee2f9", "metadata": {}, "outputs": [], - "source": [ - "from datetime import date, timedelta\n", - "\n", - "# Filter by annotation type\n", - "category_annotations = api.annotations.get_list(\n", - " resource=selected_resource,\n", - " annotation_type='category'\n", - ")\n", - "print(f\"Category annotations: {len(category_annotations)}\")\n", - "\n", - "# Filter by date range\n", - "date_to = date.today()\n", - "date_from = date_to - timedelta(days=30) # Last 30 days\n", - "\n", - "recent_annotations = api.annotations.get_list(\n", - " resource=selected_resource,\n", - " date_from=date_from,\n", - " date_to=date_to\n", - ")\n", - "print(f\"Annotations from last 30 days: {len(recent_annotations)}\")\n", - "\n", - "# Filter by status\n", - "published_annotations = api.annotations.get_list(\n", - " resource=selected_resource,\n", - " status='published'\n", - ")\n", - "print(f\"Published annotations: {len(published_annotations)}\")" - ] + "source": "from datetime import date, timedelta\n\n# Filter by annotation type\ncategory_annotations = api.annotations.get_list(\n resource=selected_resource,\n annotation_type='category'\n)\nprint(f\"Category annotations: {len(category_annotations)}\")\n\n# Filter by date range\ndate_to = date.today()\ndate_from = date_to - timedelta(days=30) # Last 30 days\n\nrecent_annotations = api.annotations.get_list(\n resource=selected_resource,\n from_date=date_from,\n to_date=date_to\n)\nprint(f\"Annotations from last 30 days: {len(recent_annotations)}\")\n\n# Filter by status\npublished_annotations = api.annotations.get_list(\n resource=selected_resource,\n status='published'\n)\nprint(f\"Published annotations: {len(published_annotations)}\")" }, { "cell_type": "markdown", @@ -516,4 +489,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/notebooks/02_annotations/01_upload_annotations.ipynb b/notebooks/02_annotations/01_upload_annotations.ipynb index 063f4466..12b93108 100644 --- a/notebooks/02_annotations/01_upload_annotations.ipynb +++ b/notebooks/02_annotations/01_upload_annotations.ipynb @@ -36,15 +36,7 @@ "id": "3f470fe9", "metadata": {}, "outputs": [], - "source": [ - "from datetime import date\n", - "from tqdm.auto import tqdm\n", - "from datamint import APIHandler\n", - "\n", - "api = APIHandler()\n", - "# resources = list(api.get_resources(project_name=\"Example Project\"))\n", - "# resource_id = resources[0][\"id\"]" - ] + "source": "from datamint import Api\n\napi = Api()\n\nPROJECT_NAME = \"Example Project\"\nresources = list(api.resources.get_list(project_name=PROJECT_NAME))\nresource = resources[0]" }, { "cell_type": "code", @@ -52,21 +44,13 @@ "id": "cf9bf31f", "metadata": {}, "outputs": [], - "source": [ - "# Adds an annotation to a single resource, associated with a project.\n", - "api.add_annotations(resource_id=resource_id,\n", - " identifier='img-lb1',\n", - " project='Example Project' # You can pass None to use not associated with a project\n", - " )" - ] + "source": "from datamint.api.dto import CreateAnnotationDto\nfrom datamint.entities.annotations import AnnotationType\n\n# Adds a label annotation to a single resource\nannotation = CreateAnnotationDto(type=AnnotationType.LABEL, identifier='img-lb1', scope='image')\napi.annotations.create(resource, annotation)\n\n# Associate the resource with a project. Resources aren't tied to a project\n# automatically anymore, so this is a separate, explicit step.\napi.projects.add_resources(resource, project=PROJECT_NAME)" }, { "cell_type": "markdown", "id": "0db3307f", "metadata": {}, - "source": [ - "See more details about the function parameter in the documentation [APIHandler.add_annotations](https://sonanceai.github.io/datamint-python-api/datamint.apihandler.html#datamint.apihandler.api_handler.APIHandler.add_annotations)." - ] + "source": "See more details about the function parameters in the documentation [AnnotationsApi.create](https://sonanceai.github.io/datamint-python-api/datamint.api.endpoints.html#datamint.api.endpoints.annotations_api.AnnotationsApi.create)." }, { "cell_type": "markdown", @@ -82,22 +66,13 @@ "id": "b2dc2320", "metadata": {}, "outputs": [], - "source": [ - "# Adds an annotation to a single resource, associated with a project.\n", - "api.add_image_category_annotation(resource_id,\n", - " identifier='img-cls',\n", - " value='cls1',\n", - " project='Example Project' # You can pass None to use not associated with a project\n", - " )" - ] + "source": "# Adds an image classification annotation to a single resource\napi.annotations.create_image_classification(resource, identifier='img-cls', value='cls1')\n\n# Associate the resource with a project. Resources aren't tied to a project\n# automatically anymore, so this is a separate, explicit step.\napi.projects.add_resources(resource, project=PROJECT_NAME)" }, { "cell_type": "markdown", "id": "b1746dae", "metadata": {}, - "source": [ - "See more details about the function parameter in the documentation [APIHandler.add_image_category_annotation](https://sonanceai.github.io/datamint-python-api/datamint.apihandler.html#datamint.apihandler.api_handler.APIHandler.add_image_category_annotation)." - ] + "source": "See more details about the function parameters in the documentation [AnnotationsApi.create_image_classification](https://sonanceai.github.io/datamint-python-api/datamint.api.endpoints.html#datamint.api.endpoints.annotations_api.AnnotationsApi.create_image_classification)." } ], "metadata": { @@ -113,4 +88,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/notebooks/02_annotations/02_geometry_annotations.ipynb b/notebooks/02_annotations/02_geometry_annotations.ipynb index fca17be1..ec6dc6e5 100644 --- a/notebooks/02_annotations/02_geometry_annotations.ipynb +++ b/notebooks/02_annotations/02_geometry_annotations.ipynb @@ -111,11 +111,7 @@ "cell_type": "markdown", "id": "1ab6ebdc", "metadata": {}, - "source": [ - "# Creating a Line annotation\n", - "\n", - "Reference: [APIHandler.add_line_annotation](https://sonanceai.github.io/datamint-python-api/datamint.apihandler.html#datamint.apihandler.api_handler.APIHandler.add_line_annotation)" - ] + "source": "# Creating a Line annotation\n\nReference: [AnnotationsApi.add_line_annotation](https://sonanceai.github.io/datamint-python-api/datamint.api.endpoints.html#datamint.api.endpoints.annotations_api.AnnotationsApi.add_line_annotation)" }, { "cell_type": "code", @@ -165,13 +161,7 @@ "cell_type": "markdown", "id": "f8ba9aaf", "metadata": {}, - "source": [ - "# Creating a Box annotation\n", - "\n", - "Reference: [APIHandler.add_box_annotation](https://sonanceai.github.io/datamint-python-api/datamint.apihandler.html#datamint.apihandler.api_handler.APIHandler.add_box_annotation)\n", - "\n", - "First, add a new box/rectangle shape named 'BoundingBox1' in your project settings (similar to the line shape setup above)." - ] + "source": "# Creating a Box annotation\n\nReference: [AnnotationsApi.add_box_annotation](https://sonanceai.github.io/datamint-python-api/datamint.api.endpoints.html#datamint.api.endpoints.annotations_api.AnnotationsApi.add_box_annotation)\n\nFirst, add a new box/rectangle shape named 'BoundingBox1' in your project settings (similar to the line shape setup above)." }, { "cell_type": "code", @@ -192,26 +182,7 @@ "cell_type": "markdown", "id": "b0b73c10", "metadata": {}, - "source": [ - "Both line and box annotations support:\n", - "- **DICOM coordinate conversion**: Automatically convert pixel coordinates to patient coordinates\n", - "- **Patient coordinates**: Direct specification of 3D patient coordinates\n", - "- **Model annotations**: Associate annotations with specific AI models\n", - "\n", - "### Example with DICOM metadata:\n", - "\n", - "```python\n", - "# Assuming you have DICOM metadata\n", - "dicom_path = \"/path/to/your/dicom/file.dcm\"\n", - "api.add_box_annotation((10, 10), (50, 50),\n", - " resource_id=res_id,\n", - " identifier='DicomBox',\n", - " frame_index=0,\n", - " dicom_metadata=dicom_path, # Automatically converts to patient coordinates\n", - " coords_system='pixel',\n", - " project=PROJECT_NAME)\n", - "```" - ] + "source": "Both line and box annotations support:\n- **DICOM coordinate conversion**: Automatically convert pixel coordinates to patient coordinates\n- **Patient coordinates**: Direct specification of 3D patient coordinates\n- **Model annotations**: Associate annotations with specific AI models\n\n### Example with DICOM metadata:\n\n```python\n# Assuming you have DICOM metadata\nimport pydicom\n\ndicom_metadata = pydicom.dcmread(\"/path/to/your/dicom/file.dcm\")\napi.annotations.add_box_annotation((10, 10), (50, 50),\n resource=res,\n identifier='DicomBox',\n frame_index=0,\n metadata=dicom_metadata, # Required when coords_system='patient'\n coords_system='patient', # Automatically converts to patient coordinates\n worklist_id=proj.fetch_worklists()[0].id)\n```" } ], "metadata": { @@ -235,4 +206,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/notebooks/04_experiment_tracking/02_model_registry.ipynb b/notebooks/04_experiment_tracking/02_model_registry.ipynb index 69304d80..bffc4085 100644 --- a/notebooks/04_experiment_tracking/02_model_registry.ipynb +++ b/notebooks/04_experiment_tracking/02_model_registry.ipynb @@ -225,14 +225,7 @@ "cell_type": "markdown", "id": "5edb693f", "metadata": {}, - "source": [ - "## Next Steps", - "", - "Once you have a model version you're happy with, alias it and deploy it, see", - "`05_deployment/01_deploy_registered_model.ipynb`. Registered models are also created", - "automatically when you pass `--ai-model ` to `datamint-upload` with a name that doesn't", - "exist yet." - ] + "source": "## Next Steps\n\nOnce you have a model version you're happy with, alias it and deploy it, see\n`05_deployment/01_deploy_registered_model.ipynb`. Registered models are also created\nautomatically when you pass `--ai-model ` to `datamint upload` with a name that doesn't\nexist yet." } ], "metadata": { @@ -256,4 +249,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/notebooks/05_deployment/03_validate_model.ipynb b/notebooks/05_deployment/03_validate_model.ipynb index c0e0ed95..2365e500 100644 --- a/notebooks/05_deployment/03_validate_model.ipynb +++ b/notebooks/05_deployment/03_validate_model.ipynb @@ -65,25 +65,11 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "e5f6a7b8", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Resources : 364\n", - "Box labels: ['Platelets', 'RBC', 'WBC']\n" - ] - } - ], - "source": [ - "dataset = build_dataset(project_name=PROJECT_NAME, allow_external_annotations=True)\n", - "\n", - "print(f\"Resources : {len(dataset.resources)}\")\n", - "print(f\"Box labels: {dataset.box_labels_set}\")" - ] + "outputs": [], + "source": "dataset = build_dataset(project=PROJECT_NAME, allow_external_annotations=True)\n\nprint(f\"Resources : {len(dataset.resources)}\")\nprint(f\"Box labels: {dataset.box_labels_set}\")" }, { "cell_type": "markdown", diff --git a/notebooks/06_end_to_end/full_3d/02_synapse_nnunet.ipynb b/notebooks/06_end_to_end/full_3d/02_synapse_nnunet.ipynb index 3d61cdfd..3e5b0ce4 100644 --- a/notebooks/06_end_to_end/full_3d/02_synapse_nnunet.ipynb +++ b/notebooks/06_end_to_end/full_3d/02_synapse_nnunet.ipynb @@ -901,53 +901,7 @@ "id": "315e1ad6", "metadata": {}, "outputs": [], - "source": [ - "%matplotlib inline\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "# Fetch CT volume\n", - "ct_nifti = r.fetch_file_data(use_cache=True, auto_convert=True)\n", - "ct_vol = ct_nifti.get_fdata()\n", - "\n", - "# Fetch the predicted segmentation (most recent annotation on this resource)\n", - "annotations = list(r.get_annotations())\n", - "pred_ann = annotations[-1]\n", - "pred_vol = pred_ann.fetch_file_data(auto_convert=True, use_cache=True)\n", - "\n", - "SYNAPSE_CLASSES = {\n", - " 1: 'aorta', 2: 'gallbladder', 3: 'spleen',\n", - " 4: 'left_kidney', 5: 'right_kidney', 6: 'liver',\n", - " 7: 'stomach', 8: 'pancreas',\n", - "}\n", - "num_classes = len(SYNAPSE_CLASSES)\n", - "CMAP = plt.get_cmap('tab10', num_classes + 1)\n", - "\n", - "# nnU-Net volumes are (H, W, D) — pick 3 axial slices\n", - "D = ct_vol.shape[2]\n", - "slice_indices = [D // 4, D // 2, 3 * D // 4]\n", - "\n", - "fig, axes = plt.subplots(len(slice_indices), 2, figsize=(10, 4 * len(slice_indices)))\n", - "fig.suptitle(f'nnU-Net inference result — {r.filename}', fontsize=13)\n", - "\n", - "for row, s in enumerate(slice_indices):\n", - " ct_slice = ct_vol[:, :, s]\n", - " pred_slice = pred_vol[:, :, s]\n", - "\n", - " axes[row, 0].imshow(ct_slice, cmap='gray')\n", - " axes[row, 0].set_title(f'CT — axial slice {s}')\n", - " axes[row, 0].axis('off')\n", - "\n", - " axes[row, 1].imshow(ct_slice, cmap='gray')\n", - " axes[row, 1].imshow(pred_slice, cmap=CMAP, alpha=0.5, vmin=0, vmax=num_classes)\n", - " axes[row, 1].set_title('nnU-Net Prediction')\n", - " axes[row, 1].axis('off')\n", - "\n", - "handles = [plt.Rectangle((0, 0), 1, 1, color=CMAP(i + 1)) for i in range(num_classes)]\n", - "fig.legend(handles, list(SYNAPSE_CLASSES.values()), loc='lower center', ncol=4, fontsize=9, title='Organ classes')\n", - "plt.tight_layout()\n", - "plt.show()" - ] + "source": "%matplotlib inline\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Fetch CT volume\nct_nifti = r.fetch_file_data(use_cache=True, auto_convert=True)\nct_vol = ct_nifti.get_fdata()\n\n# Fetch the predicted segmentation (most recent annotation on this resource)\nannotations = list(r.fetch_annotations())\npred_ann = annotations[-1]\npred_vol = pred_ann.fetch_file_data(auto_convert=True, use_cache=True)\n\nSYNAPSE_CLASSES = {\n 1: 'aorta', 2: 'gallbladder', 3: 'spleen',\n 4: 'left_kidney', 5: 'right_kidney', 6: 'liver',\n 7: 'stomach', 8: 'pancreas',\n}\nnum_classes = len(SYNAPSE_CLASSES)\nCMAP = plt.get_cmap('tab10', num_classes + 1)\n\n# nnU-Net volumes are (H, W, D) — pick 3 axial slices\nD = ct_vol.shape[2]\nslice_indices = [D // 4, D // 2, 3 * D // 4]\n\nfig, axes = plt.subplots(len(slice_indices), 2, figsize=(10, 4 * len(slice_indices)))\nfig.suptitle(f'nnU-Net inference result — {r.filename}', fontsize=13)\n\nfor row, s in enumerate(slice_indices):\n ct_slice = ct_vol[:, :, s]\n pred_slice = pred_vol[:, :, s]\n\n axes[row, 0].imshow(ct_slice, cmap='gray')\n axes[row, 0].set_title(f'CT — axial slice {s}')\n axes[row, 0].axis('off')\n\n axes[row, 1].imshow(ct_slice, cmap='gray')\n axes[row, 1].imshow(pred_slice, cmap=CMAP, alpha=0.5, vmin=0, vmax=num_classes)\n axes[row, 1].set_title('nnU-Net Prediction')\n axes[row, 1].axis('off')\n\nhandles = [plt.Rectangle((0, 0), 1, 1, color=CMAP(i + 1)) for i in range(num_classes)]\nfig.legend(handles, list(SYNAPSE_CLASSES.values()), loc='lower center', ncol=4, fontsize=9, title='Organ classes')\nplt.tight_layout()\nplt.show()" } ], "metadata": { @@ -971,4 +925,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file