Skip to content

Commit c8ef1bd

Browse files
committed
update notebooks
1 parent 8f06714 commit c8ef1bd

7 files changed

Lines changed: 21 additions & 205 deletions

File tree

notebooks/01_getting_started/01_upload_data.ipynb

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -326,43 +326,7 @@
326326
"execution_count": null,
327327
"metadata": {},
328328
"outputs": [],
329-
"source": [
330-
"# Get some resources to add to a project\n",
331-
"tutorial_resources = list(api.resources.get_list(\n",
332-
" tags=['tutorial'],\n",
333-
" status='inbox'\n",
334-
"))\n",
335-
"\n",
336-
"if tutorial_resources:\n",
337-
" resource_ids_for_project = [r.id for r in tutorial_resources[:3]] # Take first 3 resources\n",
338-
"\n",
339-
" # Create a new project\n",
340-
" try:\n",
341-
" project_id = api.projects.create(\n",
342-
" name=\"Tutorial Project\",\n",
343-
" description=\"A project created for demonstration purposes\",\n",
344-
" resources_ids=resource_ids_for_project\n",
345-
" )\n",
346-
" project = api.projects.get_by_id(project_id)\n",
347-
"\n",
348-
" print(f\"Created project: {project.name} (ID: {project.id})\")\n",
349-
"\n",
350-
" # List all projects\n",
351-
" all_projects = api.projects.get_list()\n",
352-
" print(f\"\\nAll projects ({len(all_projects)}):\")\n",
353-
" for proj in all_projects:\n",
354-
" print(f\" - {proj.name} (ID: {proj.id})\")\n",
355-
"\n",
356-
" except Exception as e:\n",
357-
" print(f\"Error creating project (may already exist): {e}\")\n",
358-
"\n",
359-
" # Try to find existing project\n",
360-
" existing_project = api.projects.get_by_name(\"Tutorial Project\")\n",
361-
" if existing_project:\n",
362-
" print(f\"Found existing project: {existing_project.name}\")\n",
363-
"else:\n",
364-
" print(\"No tutorial resources found to add to project\")"
365-
]
329+
"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\")"
366330
},
367331
{
368332
"cell_type": "markdown",
@@ -437,4 +401,4 @@
437401
},
438402
"nbformat": 4,
439403
"nbformat_minor": 2
440-
}
404+
}

notebooks/01_getting_started/02_explore_data.ipynb

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -445,34 +445,7 @@
445445
"id": "175ee2f9",
446446
"metadata": {},
447447
"outputs": [],
448-
"source": [
449-
"from datetime import date, timedelta\n",
450-
"\n",
451-
"# Filter by annotation type\n",
452-
"category_annotations = api.annotations.get_list(\n",
453-
" resource=selected_resource,\n",
454-
" annotation_type='category'\n",
455-
")\n",
456-
"print(f\"Category annotations: {len(category_annotations)}\")\n",
457-
"\n",
458-
"# Filter by date range\n",
459-
"date_to = date.today()\n",
460-
"date_from = date_to - timedelta(days=30) # Last 30 days\n",
461-
"\n",
462-
"recent_annotations = api.annotations.get_list(\n",
463-
" resource=selected_resource,\n",
464-
" date_from=date_from,\n",
465-
" date_to=date_to\n",
466-
")\n",
467-
"print(f\"Annotations from last 30 days: {len(recent_annotations)}\")\n",
468-
"\n",
469-
"# Filter by status\n",
470-
"published_annotations = api.annotations.get_list(\n",
471-
" resource=selected_resource,\n",
472-
" status='published'\n",
473-
")\n",
474-
"print(f\"Published annotations: {len(published_annotations)}\")"
475-
]
448+
"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)}\")"
476449
},
477450
{
478451
"cell_type": "markdown",
@@ -516,4 +489,4 @@
516489
},
517490
"nbformat": 4,
518491
"nbformat_minor": 5
519-
}
492+
}

notebooks/02_annotations/01_upload_annotations.ipynb

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -36,37 +36,21 @@
3636
"id": "3f470fe9",
3737
"metadata": {},
3838
"outputs": [],
39-
"source": [
40-
"from datetime import date\n",
41-
"from tqdm.auto import tqdm\n",
42-
"from datamint import APIHandler\n",
43-
"\n",
44-
"api = APIHandler()\n",
45-
"# resources = list(api.get_resources(project_name=\"Example Project\"))\n",
46-
"# resource_id = resources[0][\"id\"]"
47-
]
39+
"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]"
4840
},
4941
{
5042
"cell_type": "code",
5143
"execution_count": null,
5244
"id": "cf9bf31f",
5345
"metadata": {},
5446
"outputs": [],
55-
"source": [
56-
"# Adds an annotation to a single resource, associated with a project.\n",
57-
"api.add_annotations(resource_id=resource_id,\n",
58-
" identifier='img-lb1',\n",
59-
" project='Example Project' # You can pass None to use not associated with a project\n",
60-
" )"
61-
]
47+
"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)"
6248
},
6349
{
6450
"cell_type": "markdown",
6551
"id": "0db3307f",
6652
"metadata": {},
67-
"source": [
68-
"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)."
69-
]
53+
"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)."
7054
},
7155
{
7256
"cell_type": "markdown",
@@ -82,22 +66,13 @@
8266
"id": "b2dc2320",
8367
"metadata": {},
8468
"outputs": [],
85-
"source": [
86-
"# Adds an annotation to a single resource, associated with a project.\n",
87-
"api.add_image_category_annotation(resource_id,\n",
88-
" identifier='img-cls',\n",
89-
" value='cls1',\n",
90-
" project='Example Project' # You can pass None to use not associated with a project\n",
91-
" )"
92-
]
69+
"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)"
9370
},
9471
{
9572
"cell_type": "markdown",
9673
"id": "b1746dae",
9774
"metadata": {},
98-
"source": [
99-
"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)."
100-
]
75+
"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)."
10176
}
10277
],
10378
"metadata": {
@@ -113,4 +88,4 @@
11388
},
11489
"nbformat": 4,
11590
"nbformat_minor": 5
116-
}
91+
}

notebooks/02_annotations/02_geometry_annotations.ipynb

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,7 @@
111111
"cell_type": "markdown",
112112
"id": "1ab6ebdc",
113113
"metadata": {},
114-
"source": [
115-
"# Creating a Line annotation\n",
116-
"\n",
117-
"Reference: [APIHandler.add_line_annotation](https://sonanceai.github.io/datamint-python-api/datamint.apihandler.html#datamint.apihandler.api_handler.APIHandler.add_line_annotation)"
118-
]
114+
"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)"
119115
},
120116
{
121117
"cell_type": "code",
@@ -165,13 +161,7 @@
165161
"cell_type": "markdown",
166162
"id": "f8ba9aaf",
167163
"metadata": {},
168-
"source": [
169-
"# Creating a Box annotation\n",
170-
"\n",
171-
"Reference: [APIHandler.add_box_annotation](https://sonanceai.github.io/datamint-python-api/datamint.apihandler.html#datamint.apihandler.api_handler.APIHandler.add_box_annotation)\n",
172-
"\n",
173-
"First, add a new box/rectangle shape named 'BoundingBox1' in your project settings (similar to the line shape setup above)."
174-
]
164+
"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)."
175165
},
176166
{
177167
"cell_type": "code",
@@ -192,26 +182,7 @@
192182
"cell_type": "markdown",
193183
"id": "b0b73c10",
194184
"metadata": {},
195-
"source": [
196-
"Both line and box annotations support:\n",
197-
"- **DICOM coordinate conversion**: Automatically convert pixel coordinates to patient coordinates\n",
198-
"- **Patient coordinates**: Direct specification of 3D patient coordinates\n",
199-
"- **Model annotations**: Associate annotations with specific AI models\n",
200-
"\n",
201-
"### Example with DICOM metadata:\n",
202-
"\n",
203-
"```python\n",
204-
"# Assuming you have DICOM metadata\n",
205-
"dicom_path = \"/path/to/your/dicom/file.dcm\"\n",
206-
"api.add_box_annotation((10, 10), (50, 50),\n",
207-
" resource_id=res_id,\n",
208-
" identifier='DicomBox',\n",
209-
" frame_index=0,\n",
210-
" dicom_metadata=dicom_path, # Automatically converts to patient coordinates\n",
211-
" coords_system='pixel',\n",
212-
" project=PROJECT_NAME)\n",
213-
"```"
214-
]
185+
"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```"
215186
}
216187
],
217188
"metadata": {
@@ -235,4 +206,4 @@
235206
},
236207
"nbformat": 4,
237208
"nbformat_minor": 5
238-
}
209+
}

notebooks/04_experiment_tracking/02_model_registry.ipynb

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,7 @@
225225
"cell_type": "markdown",
226226
"id": "5edb693f",
227227
"metadata": {},
228-
"source": [
229-
"## Next Steps",
230-
"",
231-
"Once you have a model version you're happy with, alias it and deploy it, see",
232-
"`05_deployment/01_deploy_registered_model.ipynb`. Registered models are also created",
233-
"automatically when you pass `--ai-model <name>` to `datamint-upload` with a name that doesn't",
234-
"exist yet."
235-
]
228+
"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 <name>` to `datamint upload` with a name that doesn't\nexist yet."
236229
}
237230
],
238231
"metadata": {
@@ -256,4 +249,4 @@
256249
},
257250
"nbformat": 4,
258251
"nbformat_minor": 5
259-
}
252+
}

notebooks/05_deployment/03_validate_model.ipynb

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,11 @@
6565
},
6666
{
6767
"cell_type": "code",
68-
"execution_count": 13,
68+
"execution_count": null,
6969
"id": "e5f6a7b8",
7070
"metadata": {},
71-
"outputs": [
72-
{
73-
"name": "stdout",
74-
"output_type": "stream",
75-
"text": [
76-
"Resources : 364\n",
77-
"Box labels: ['Platelets', 'RBC', 'WBC']\n"
78-
]
79-
}
80-
],
81-
"source": [
82-
"dataset = build_dataset(project_name=PROJECT_NAME, allow_external_annotations=True)\n",
83-
"\n",
84-
"print(f\"Resources : {len(dataset.resources)}\")\n",
85-
"print(f\"Box labels: {dataset.box_labels_set}\")"
86-
]
71+
"outputs": [],
72+
"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}\")"
8773
},
8874
{
8975
"cell_type": "markdown",

notebooks/06_end_to_end/full_3d/02_synapse_nnunet.ipynb

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -901,53 +901,7 @@
901901
"id": "315e1ad6",
902902
"metadata": {},
903903
"outputs": [],
904-
"source": [
905-
"%matplotlib inline\n",
906-
"import numpy as np\n",
907-
"import matplotlib.pyplot as plt\n",
908-
"\n",
909-
"# Fetch CT volume\n",
910-
"ct_nifti = r.fetch_file_data(use_cache=True, auto_convert=True)\n",
911-
"ct_vol = ct_nifti.get_fdata()\n",
912-
"\n",
913-
"# Fetch the predicted segmentation (most recent annotation on this resource)\n",
914-
"annotations = list(r.get_annotations())\n",
915-
"pred_ann = annotations[-1]\n",
916-
"pred_vol = pred_ann.fetch_file_data(auto_convert=True, use_cache=True)\n",
917-
"\n",
918-
"SYNAPSE_CLASSES = {\n",
919-
" 1: 'aorta', 2: 'gallbladder', 3: 'spleen',\n",
920-
" 4: 'left_kidney', 5: 'right_kidney', 6: 'liver',\n",
921-
" 7: 'stomach', 8: 'pancreas',\n",
922-
"}\n",
923-
"num_classes = len(SYNAPSE_CLASSES)\n",
924-
"CMAP = plt.get_cmap('tab10', num_classes + 1)\n",
925-
"\n",
926-
"# nnU-Net volumes are (H, W, D) — pick 3 axial slices\n",
927-
"D = ct_vol.shape[2]\n",
928-
"slice_indices = [D // 4, D // 2, 3 * D // 4]\n",
929-
"\n",
930-
"fig, axes = plt.subplots(len(slice_indices), 2, figsize=(10, 4 * len(slice_indices)))\n",
931-
"fig.suptitle(f'nnU-Net inference result — {r.filename}', fontsize=13)\n",
932-
"\n",
933-
"for row, s in enumerate(slice_indices):\n",
934-
" ct_slice = ct_vol[:, :, s]\n",
935-
" pred_slice = pred_vol[:, :, s]\n",
936-
"\n",
937-
" axes[row, 0].imshow(ct_slice, cmap='gray')\n",
938-
" axes[row, 0].set_title(f'CT — axial slice {s}')\n",
939-
" axes[row, 0].axis('off')\n",
940-
"\n",
941-
" axes[row, 1].imshow(ct_slice, cmap='gray')\n",
942-
" axes[row, 1].imshow(pred_slice, cmap=CMAP, alpha=0.5, vmin=0, vmax=num_classes)\n",
943-
" axes[row, 1].set_title('nnU-Net Prediction')\n",
944-
" axes[row, 1].axis('off')\n",
945-
"\n",
946-
"handles = [plt.Rectangle((0, 0), 1, 1, color=CMAP(i + 1)) for i in range(num_classes)]\n",
947-
"fig.legend(handles, list(SYNAPSE_CLASSES.values()), loc='lower center', ncol=4, fontsize=9, title='Organ classes')\n",
948-
"plt.tight_layout()\n",
949-
"plt.show()"
950-
]
904+
"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()"
951905
}
952906
],
953907
"metadata": {
@@ -971,4 +925,4 @@
971925
},
972926
"nbformat": 4,
973927
"nbformat_minor": 5
974-
}
928+
}

0 commit comments

Comments
 (0)