|
79 | 79 | "from loguru import logger\n", |
80 | 80 | "from numpy.typing import NDArray\n", |
81 | 81 | "\n", |
82 | | - "from bioimageio.spec.utils import download\n", |
| 82 | + "from bioimageio.spec.utils import get_reader\n", |
83 | 83 | "\n", |
84 | 84 | "# redirect stderr to stdout for better output comparison across runs with 'pytest --nbval'\n", |
85 | 85 | "sys.stderr = sys.stdout\n", |
|
388 | 388 | ], |
389 | 389 | "source": [ |
390 | 390 | "for i, cover in enumerate(model.covers):\n", |
391 | | - " downloaded_cover = download(cover)\n", |
392 | | - " cover_data: NDArray[Any] = imread(downloaded_cover.read()) # type: ignore\n", |
| 391 | + " cover_reader = get_reader(cover)\n", |
| 392 | + " cover_data: NDArray[Any] = imread(cover_reader.read())\n", |
393 | 393 | " _ = plt.figure(figsize=(10, 10))\n", |
394 | 394 | " plt.imshow(cover_data) # type: ignore\n", |
395 | 395 | " plt.xticks([]) # type: ignore\n", |
396 | 396 | " plt.yticks([]) # type: ignore\n", |
397 | | - " plt.title(f\"cover image {downloaded_cover.original_file_name}\") # type: ignore\n", |
| 397 | + " plt.title(f\"cover image {cover_reader.original_file_name}\") # type: ignore\n", |
398 | 398 | " plt.show()" |
399 | 399 | ] |
400 | 400 | }, |
|
713 | 713 | " assert_never(arch)" |
714 | 714 | ] |
715 | 715 | }, |
| 716 | + { |
| 717 | + "cell_type": "markdown", |
| 718 | + "metadata": {}, |
| 719 | + "source": [ |
| 720 | + "### Invalid Resource Descriptions\n", |
| 721 | + "\n", |
| 722 | + "To inspect invalid (or other non-model) resource description, use `load_description`, which always returns a description object (unlike `load_model_description`, which will throw an exception if the loaded resource is not a valid model).\n", |
| 723 | + "\n", |
| 724 | + "`load_description` may return:\n", |
| 725 | + "- A valid description of a known resource type (`ModelDescr`, `DatasetDescr`, `NotebeookDescr`, or `ApplicationDescr`).\n", |
| 726 | + "- A valid description of a generic resource: `GenericDescr` with a `type` other than `'model'`, `'dataset'`, `'notebook'`, or `'application'`.\n", |
| 727 | + "- An invalid description if there were any validation errors (`InvalidDescr`).\\\n", |
| 728 | + " This can also occur with valid models when using an older version of the bioimageio.spec library. \\\n", |
| 729 | + " In these cases the validation summary includes a warning like `\"future format_version '0.5.3' treated as '0.4.10'\"`, see example below" |
| 730 | + ] |
| 731 | + }, |
| 732 | + { |
| 733 | + "cell_type": "code", |
| 734 | + "execution_count": 11, |
| 735 | + "metadata": {}, |
| 736 | + "outputs": [ |
| 737 | + { |
| 738 | + "name": "stdout", |
| 739 | + "output_type": "stream", |
| 740 | + "text": [ |
| 741 | + "Description class name: InvalidDescr\n", |
| 742 | + "Type and format version attributes are always accessible (may return 'unknown'): model 0.4.10\n", |
| 743 | + "Validation status: failed\n", |
| 744 | + "Validation errors: ['Input should be a valid dictionary or instance of AttachmentsDescr', '...']\n", |
| 745 | + "Validation warnings: [\"future format_version '0.5.3' treated as '0.4.10'\"]\n" |
| 746 | + ] |
| 747 | + } |
| 748 | + ], |
| 749 | + "source": [ |
| 750 | + "from bioimageio.spec import load_description\n", |
| 751 | + "\n", |
| 752 | + "# load the model with an older format version to force an error\n", |
| 753 | + "# (backward conversion is not supported)\n", |
| 754 | + "descr = load_description(model_source, format_version=\"0.4\")\n", |
| 755 | + "\n", |
| 756 | + "# Print a few attributes instead of rendering the full validation summary with lots of errors...\n", |
| 757 | + "# descr.validation_summary.display()\n", |
| 758 | + "print(f\"Description class name: {descr.__class__.__name__}\")\n", |
| 759 | + "print(f\"Type and format version attributes are always accessible (may return 'unknown'): {descr.type} {descr.format_version}\")\n", |
| 760 | + "print(f\"Validation status: {descr.validation_summary.status}\")\n", |
| 761 | + "print(f\"Validation errors: {[descr.validation_summary.errors[0].msg, '...']}\")\n", |
| 762 | + "print(f\"Validation warnings: {[w.msg for w in descr.validation_summary.warnings]}\")" |
| 763 | + ] |
| 764 | + }, |
716 | 765 | { |
717 | 766 | "cell_type": "markdown", |
718 | 767 | "metadata": {}, |
|
727 | 776 | }, |
728 | 777 | { |
729 | 778 | "cell_type": "code", |
730 | | - "execution_count": 11, |
| 779 | + "execution_count": 12, |
731 | 780 | "metadata": { |
732 | 781 | "execution": { |
733 | 782 | "iopub.execute_input": "2025-09-25T15:14:17.617583Z", |
|
759 | 808 | "traceback": [ |
760 | 809 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", |
761 | 810 | "\u001b[1;31mValidationError\u001b[0m Traceback (most recent call last)", |
762 | | - "Cell \u001b[1;32mIn[11], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m ModelDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mModelDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
| 811 | + "Cell \u001b[1;32mIn[12], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m ModelDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mModelDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
763 | 812 | "\u001b[1;31mValidationError\u001b[0m: 4 validation errors for ModelDescr:\nname\n Field required [input={'format_version': '0.5.5', 'type': 'model'}]\ninputs\n Field required [input={'format_version': '0.5.5', 'type': 'model'}]\noutputs\n Field required [input={'format_version': '0.5.5', 'type': 'model'}]\nweights\n Field required [input={'format_version': '0.5.5', 'type': 'model'}]" |
764 | 813 | ] |
765 | 814 | } |
|
788 | 837 | }, |
789 | 838 | { |
790 | 839 | "cell_type": "code", |
791 | | - "execution_count": 12, |
| 840 | + "execution_count": 13, |
792 | 841 | "metadata": { |
793 | 842 | "execution": { |
794 | 843 | "iopub.execute_input": "2025-09-25T15:14:17.688095Z", |
|
816 | 865 | "traceback": [ |
817 | 866 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", |
818 | 867 | "\u001b[1;31mValidationError\u001b[0m Traceback (most recent call last)", |
819 | | - "Cell \u001b[1;32mIn[12], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m InputTensorDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mInputTensorDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
| 868 | + "Cell \u001b[1;32mIn[13], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m InputTensorDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mInputTensorDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
820 | 869 | "\u001b[1;31mValidationError\u001b[0m: 1 validation errors for InputTensorDescr:\naxes\n Field required [input={}]" |
821 | 870 | ] |
822 | 871 | } |
|
829 | 878 | }, |
830 | 879 | { |
831 | 880 | "cell_type": "code", |
832 | | - "execution_count": 13, |
| 881 | + "execution_count": 14, |
833 | 882 | "metadata": { |
834 | 883 | "execution": { |
835 | 884 | "iopub.execute_input": "2025-09-25T15:14:17.770073Z", |
|
883 | 932 | }, |
884 | 933 | { |
885 | 934 | "cell_type": "code", |
886 | | - "execution_count": 14, |
| 935 | + "execution_count": 15, |
887 | 936 | "metadata": { |
888 | 937 | "execution": { |
889 | 938 | "iopub.execute_input": "2025-09-25T15:14:19.851930Z", |
|
911 | 960 | "traceback": [ |
912 | 961 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", |
913 | 962 | "\u001b[1;31mValidationError\u001b[0m Traceback (most recent call last)", |
914 | | - "Cell \u001b[1;32mIn[14], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m OutputTensorDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mOutputTensorDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
| 963 | + "Cell \u001b[1;32mIn[15], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m OutputTensorDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mOutputTensorDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
915 | 964 | "\u001b[1;31mValidationError\u001b[0m: 1 validation errors for OutputTensorDescr:\naxes\n Field required [input={}]" |
916 | 965 | ] |
917 | 966 | } |
|
924 | 973 | }, |
925 | 974 | { |
926 | 975 | "cell_type": "code", |
927 | | - "execution_count": 15, |
| 976 | + "execution_count": 16, |
928 | 977 | "metadata": { |
929 | 978 | "execution": { |
930 | 979 | "iopub.execute_input": "2025-09-25T15:14:19.917767Z", |
|
985 | 1034 | }, |
986 | 1035 | { |
987 | 1036 | "cell_type": "code", |
988 | | - "execution_count": 16, |
| 1037 | + "execution_count": 17, |
989 | 1038 | "metadata": { |
990 | 1039 | "execution": { |
991 | 1040 | "iopub.execute_input": "2025-09-25T15:14:22.239956Z", |
|
1005 | 1054 | "traceback": [ |
1006 | 1055 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", |
1007 | 1056 | "\u001b[1;31mValidationError\u001b[0m Traceback (most recent call last)", |
1008 | | - "Cell \u001b[1;32mIn[16], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m PytorchStateDictWeightsDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mPytorchStateDictWeightsDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
| 1057 | + "Cell \u001b[1;32mIn[17], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mbioimageio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspec\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mv0_5\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m PytorchStateDictWeightsDescr\n\u001b[1;32m----> 3\u001b[0m _ \u001b[38;5;241m=\u001b[39m \u001b[43mPytorchStateDictWeightsDescr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# pyright: ignore[reportCallIssue]\u001b[39;00m\n", |
1009 | 1058 | "\u001b[1;31mValidationError\u001b[0m: 3 validation errors for PytorchStateDictWeightsDescr:\nsource\n Field required [input={}]\narchitecture\n Field required [input={}]\npytorch_version\n Field required [input={}]" |
1010 | 1059 | ] |
1011 | 1060 | } |
|
1032 | 1081 | }, |
1033 | 1082 | { |
1034 | 1083 | "cell_type": "code", |
1035 | | - "execution_count": 17, |
| 1084 | + "execution_count": 18, |
1036 | 1085 | "metadata": { |
1037 | 1086 | "execution": { |
1038 | 1087 | "iopub.execute_input": "2025-09-25T15:14:22.306568Z", |
|
1077 | 1126 | }, |
1078 | 1127 | { |
1079 | 1128 | "cell_type": "code", |
1080 | | - "execution_count": 18, |
| 1129 | + "execution_count": 19, |
1081 | 1130 | "metadata": { |
1082 | 1131 | "execution": { |
1083 | 1132 | "iopub.execute_input": "2025-09-25T15:14:27.148305Z", |
|
1107 | 1156 | }, |
1108 | 1157 | { |
1109 | 1158 | "cell_type": "code", |
1110 | | - "execution_count": 19, |
| 1159 | + "execution_count": 20, |
1111 | 1160 | "metadata": { |
1112 | 1161 | "execution": { |
1113 | 1162 | "iopub.execute_input": "2025-09-25T15:14:28.098738Z", |
|
1137 | 1186 | }, |
1138 | 1187 | { |
1139 | 1188 | "cell_type": "code", |
1140 | | - "execution_count": 20, |
| 1189 | + "execution_count": 21, |
1141 | 1190 | "metadata": { |
1142 | 1191 | "execution": { |
1143 | 1192 | "iopub.execute_input": "2025-09-25T15:14:28.858588Z", |
|
1182 | 1231 | }, |
1183 | 1232 | { |
1184 | 1233 | "cell_type": "code", |
1185 | | - "execution_count": 21, |
| 1234 | + "execution_count": 22, |
1186 | 1235 | "metadata": { |
1187 | 1236 | "execution": { |
1188 | 1237 | "iopub.execute_input": "2025-09-25T15:14:29.687571Z", |
|
1261 | 1310 | }, |
1262 | 1311 | { |
1263 | 1312 | "cell_type": "code", |
1264 | | - "execution_count": 22, |
| 1313 | + "execution_count": 23, |
1265 | 1314 | "metadata": { |
1266 | 1315 | "execution": { |
1267 | 1316 | "iopub.execute_input": "2025-09-25T15:14:32.351633Z", |
|
1329 | 1378 | }, |
1330 | 1379 | { |
1331 | 1380 | "cell_type": "code", |
1332 | | - "execution_count": 23, |
| 1381 | + "execution_count": 24, |
1333 | 1382 | "metadata": { |
1334 | 1383 | "execution": { |
1335 | 1384 | "iopub.execute_input": "2025-09-25T15:14:32.521339Z", |
|
1564 | 1613 | }, |
1565 | 1614 | { |
1566 | 1615 | "cell_type": "code", |
1567 | | - "execution_count": 24, |
| 1616 | + "execution_count": 25, |
1568 | 1617 | "metadata": { |
1569 | 1618 | "execution": { |
1570 | 1619 | "iopub.execute_input": "2025-09-25T15:15:03.940263Z", |
|
0 commit comments