bioimageio.spec.generic.v0_2
1import string 2from typing import ( 3 TYPE_CHECKING, 4 Any, 5 ClassVar, 6 Dict, 7 List, 8 Literal, 9 Mapping, 10 Optional, 11 Sequence, 12 Type, 13 TypeVar, 14 Union, 15) 16 17import annotated_types 18from annotated_types import Len, LowerCase, MaxLen 19from pydantic import ( 20 EmailStr, 21 Field, 22 RootModel, 23 ValidationInfo, 24 field_validator, 25 model_validator, 26) 27from typing_extensions import Annotated, Self, assert_never 28 29from .._internal.common_nodes import Node, ResourceDescrBase 30from .._internal.constants import TAG_CATEGORIES 31from .._internal.field_warning import as_warning, issue_warning, warn 32from .._internal.io import ( 33 BioimageioYamlContent, 34 InPackageIfLocalFileSource, 35 WithSuffix, 36 YamlValue, 37 include_in_package_serializer, 38) 39from .._internal.io_basics import AbsoluteFilePath as AbsoluteFilePath 40from .._internal.type_guards import is_sequence 41from .._internal.types import ( 42 DeprecatedLicenseId, 43 FileSource, 44 ImportantFileSource, 45 LicenseId, 46 NotEmpty, 47) 48from .._internal.types import Doi as Doi 49from .._internal.types import OrcidId as OrcidId 50from .._internal.types import RelativeFilePath as RelativeFilePath 51from .._internal.url import HttpUrl as HttpUrl 52from .._internal.validated_string import ValidatedString 53from .._internal.validator_annotations import AfterValidator, RestrictCharacters 54from .._internal.version_type import Version as Version 55from ._v0_2_converter import convert_from_older_format as _convert_from_older_format 56 57 58class ResourceId(ValidatedString): 59 root_model: ClassVar[Type[RootModel[Any]]] = RootModel[ 60 Annotated[ 61 NotEmpty[str], 62 AfterValidator(str.lower), # convert upper case on the fly 63 RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."), 64 annotated_types.Predicate( 65 lambda s: not (s.startswith("/") or s.endswith("/")) 66 ), 67 ] 68 ] 69 70 71KNOWN_SPECIFIC_RESOURCE_TYPES = ( 72 "application", 73 "collection", 74 "dataset", 75 "model", 76 "notebook", 77) 78 79VALID_COVER_IMAGE_EXTENSIONS = ( 80 ".gif", 81 ".jpeg", 82 ".jpg", 83 ".png", 84 ".svg", 85 ".tif", 86 ".tiff", 87) 88 89_WithImageSuffix = WithSuffix(VALID_COVER_IMAGE_EXTENSIONS, case_sensitive=False) 90CoverImageSource = Annotated[ 91 Union[AbsoluteFilePath, RelativeFilePath, HttpUrl], 92 Field(union_mode="left_to_right"), 93 _WithImageSuffix, 94 include_in_package_serializer, 95] 96 97 98class AttachmentsDescr(Node): 99 model_config = {**Node.model_config, "extra": "allow"} 100 """update pydantic model config to allow additional unknown keys""" 101 files: List[ImportantFileSource] = Field(default_factory=list) 102 """∈📦 File attachments""" 103 104 105def _remove_slashes(s: str): 106 return s.replace("/", "").replace("\\", "") 107 108 109class Uploader(Node): 110 email: EmailStr 111 """Email""" 112 name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None 113 """name""" 114 115 116class _Person(Node): 117 affiliation: Optional[str] = None 118 """Affiliation""" 119 120 email: Optional[EmailStr] = None 121 """Email""" 122 123 orcid: Annotated[Optional[OrcidId], Field(examples=["0000-0001-2345-6789"])] = None 124 """An [ORCID iD](https://support.orcid.org/hc/en-us/sections/360001495313-What-is-ORCID 125 ) in hyphenated groups of 4 digits, (and [valid]( 126 https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier 127 ) as per ISO 7064 11,2.) 128 """ 129 130 131class Author(_Person): 132 name: Annotated[str, AfterValidator(_remove_slashes)] 133 github_user: Optional[str] = None # TODO: validate github_user 134 135 136class Maintainer(_Person): 137 name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None 138 github_user: str 139 140 141class BadgeDescr(Node): 142 """A custom badge""" 143 144 label: Annotated[str, Field(examples=["Open in Colab"])] 145 """badge label to display on hover""" 146 147 icon: Annotated[ 148 Optional[InPackageIfLocalFileSource], 149 Field(examples=["https://colab.research.google.com/assets/colab-badge.svg"]), 150 ] = None 151 """badge icon""" 152 153 url: Annotated[ 154 HttpUrl, 155 Field( 156 examples=[ 157 "https://colab.research.google.com/github/HenriquesLab/ZeroCostDL4Mic/blob/master/Colab_notebooks/U-net_2D_ZeroCostDL4Mic.ipynb" 158 ] 159 ), 160 ] 161 """target URL""" 162 163 164class CiteEntry(Node): 165 text: str 166 """free text description""" 167 168 doi: Optional[Doi] = None 169 """A digital object identifier (DOI) is the prefered citation reference. 170 See https://www.doi.org/ for details. (alternatively specify `url`)""" 171 172 @field_validator("doi", mode="before") 173 @classmethod 174 def accept_prefixed_doi(cls, doi: Any) -> Any: 175 if isinstance(doi, str): 176 for doi_prefix in ("https://doi.org/", "http://dx.doi.org/"): 177 if doi.startswith(doi_prefix): 178 doi = doi[len(doi_prefix) :] 179 break 180 181 return doi 182 183 url: Optional[str] = None 184 """URL to cite (preferably specify a `doi` instead)""" 185 186 @model_validator(mode="after") 187 def _check_doi_or_url(self) -> Self: 188 if not self.doi and not self.url: 189 raise ValueError("Either 'doi' or 'url' is required") 190 191 return self 192 193 194class LinkedResource(Node): 195 """Reference to a bioimage.io resource""" 196 197 id: ResourceId 198 """A valid resource `id` from the bioimage.io collection.""" 199 200 version_number: Optional[int] = None 201 """version number (n-th published version, not the semantic version) of linked resource""" 202 203 204class GenericModelDescrBase(ResourceDescrBase): 205 """Base for all resource descriptions including of model descriptions""" 206 207 name: Annotated[NotEmpty[str], warn(MaxLen(128), "Longer than 128 characters.")] 208 """A human-friendly name of the resource description""" 209 210 description: str 211 212 covers: Annotated[ 213 List[CoverImageSource], 214 Field( 215 examples=["cover.png"], 216 description=( 217 "Cover images. Please use an image smaller than 500KB and an aspect" 218 " ratio width to height of 2:1.\nThe supported image formats are:" 219 f" {VALID_COVER_IMAGE_EXTENSIONS}" 220 ), 221 ), 222 ] = Field( 223 default_factory=list, 224 ) 225 """∈📦 Cover images. Please use an image smaller than 500KB and an aspect ratio width to height of 2:1.""" 226 227 id_emoji: Optional[ 228 Annotated[str, Len(min_length=1, max_length=1), Field(examples=["🦈", "🦥"])] 229 ] = None 230 """UTF-8 emoji for display alongside the `id`.""" 231 232 authors: List[Author] = Field(default_factory=list) 233 """The authors are the creators of the RDF and the primary points of contact.""" 234 235 @field_validator("authors", mode="before") 236 @classmethod 237 def accept_author_strings(cls, authors: Union[Any, Sequence[Any]]) -> Any: 238 """we unofficially accept strings as author entries""" 239 if is_sequence(authors): 240 authors = [{"name": a} if isinstance(a, str) else a for a in authors] 241 242 if not authors: 243 issue_warning("missing", value=authors, field="authors") 244 245 return authors 246 247 attachments: Optional[AttachmentsDescr] = None 248 """file and other attachments""" 249 250 cite: List[CiteEntry] = Field(default_factory=list) 251 """citations""" 252 253 @field_validator("cite", mode="after") 254 @classmethod 255 def _warn_empty_cite(cls, value: Any): 256 if not value: 257 issue_warning("missing", value=value, field="cite") 258 259 return value 260 261 config: Annotated[ 262 Dict[str, YamlValue], 263 Field( 264 examples=[ 265 dict( 266 bioimageio={ 267 "my_custom_key": 3837283, 268 "another_key": {"nested": "value"}, 269 }, 270 imagej={"macro_dir": "path/to/macro/file"}, 271 ) 272 ], 273 ), 274 ] = Field(default_factory=dict) 275 """A field for custom configuration that can contain any keys not present in the RDF spec. 276 This means you should not store, for example, a github repo URL in `config` since we already have the 277 `git_repo` field defined in the spec. 278 Keys in `config` may be very specific to a tool or consumer software. To avoid conflicting definitions, 279 it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name, 280 for example: 281 ```yaml 282 config: 283 bioimageio: # here is the domain name 284 my_custom_key: 3837283 285 another_key: 286 nested: value 287 imagej: # config specific to ImageJ 288 macro_dir: path/to/macro/file 289 ``` 290 If possible, please use [`snake_case`](https://en.wikipedia.org/wiki/Snake_case) for keys in `config`. 291 You may want to list linked files additionally under `attachments` to include them when packaging a resource 292 (packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains 293 an altered rdf.yaml file with local references to the downloaded files)""" 294 295 download_url: Optional[HttpUrl] = None 296 """URL to download the resource from (deprecated)""" 297 298 git_repo: Annotated[ 299 Optional[str], 300 Field( 301 examples=[ 302 "https://github.com/bioimage-io/spec-bioimage-io/tree/main/example_descriptions/models/unet2d_nuclei_broad" 303 ], 304 ), 305 ] = None 306 """A URL to the Git repository where the resource is being developed.""" 307 308 icon: Union[ 309 Annotated[str, Len(min_length=1, max_length=2)], ImportantFileSource, None 310 ] = None 311 """An icon for illustration""" 312 313 links: Annotated[ 314 List[str], 315 Field( 316 examples=[ 317 ( 318 "ilastik/ilastik", 319 "deepimagej/deepimagej", 320 "zero/notebook_u-net_3d_zerocostdl4mic", 321 ) 322 ], 323 ), 324 ] = Field(default_factory=list) 325 """IDs of other bioimage.io resources""" 326 327 uploader: Optional[Uploader] = None 328 """The person who uploaded the model (e.g. to bioimage.io)""" 329 330 maintainers: List[Maintainer] = Field(default_factory=list) 331 """Maintainers of this resource. 332 If not specified `authors` are maintainers and at least some of them should specify their `github_user` name""" 333 334 rdf_source: Optional[FileSource] = None 335 """Resource description file (RDF) source; used to keep track of where an rdf.yaml was loaded from. 336 Do not set this field in a YAML file.""" 337 338 tags: Annotated[ 339 List[str], 340 Field(examples=[("unet2d", "pytorch", "nucleus", "segmentation", "dsb2018")]), 341 ] = Field(default_factory=list) 342 """Associated tags""" 343 344 @as_warning 345 @field_validator("tags") 346 @classmethod 347 def warn_about_tag_categories( 348 cls, value: List[str], info: ValidationInfo 349 ) -> List[str]: 350 categories = TAG_CATEGORIES.get(info.data["type"], {}) 351 missing_categories: List[Mapping[str, Sequence[str]]] = [] 352 for cat, entries in categories.items(): 353 if not any(e in value for e in entries): 354 missing_categories.append({cat: entries}) 355 356 if missing_categories: 357 raise ValueError( 358 "Missing tags from bioimage.io categories: {missing_categories}" 359 ) 360 361 return value 362 363 version: Optional[Version] = None 364 """The version of the resource following SemVer 2.0.""" 365 366 version_number: Optional[int] = None 367 """version number (n-th published version, not the semantic version)""" 368 369 370class GenericDescrBase(GenericModelDescrBase): 371 """Base for all resource descriptions except for the model descriptions""" 372 373 implemented_format_version: ClassVar[Literal["0.2.4"]] = "0.2.4" 374 if TYPE_CHECKING: 375 format_version: Literal["0.2.4"] = "0.2.4" 376 else: 377 format_version: Literal["0.2.4"] 378 """The format version of this resource specification 379 (not the `version` of the resource description) 380 When creating a new resource always use the latest micro/patch version described here. 381 The `format_version` is important for any consumer software to understand how to parse the fields. 382 """ 383 384 @model_validator(mode="before") 385 @classmethod 386 def _convert_from_older_format( 387 cls, data: BioimageioYamlContent, / 388 ) -> BioimageioYamlContent: 389 _convert_from_older_format(data) 390 return data 391 392 badges: List[BadgeDescr] = Field(default_factory=list) 393 """badges associated with this resource""" 394 395 documentation: Annotated[ 396 Optional[ImportantFileSource], 397 Field( 398 examples=[ 399 "https://raw.githubusercontent.com/bioimage-io/spec-bioimage-io/main/example_descriptions/models/unet2d_nuclei_broad/README.md", 400 "README.md", 401 ], 402 ), 403 ] = None 404 """∈📦 URL or relative path to a markdown file with additional documentation. 405 The recommended documentation file name is `README.md`. An `.md` suffix is mandatory.""" 406 407 license: Annotated[ 408 Union[LicenseId, DeprecatedLicenseId, str, None], 409 Field(union_mode="left_to_right", examples=["CC0-1.0", "MIT", "BSD-2-Clause"]), 410 ] = None 411 """A [SPDX license identifier](https://spdx.org/licenses/). 412 We do not support custom license beyond the SPDX license list, if you need that please 413 [open a GitHub issue](https://github.com/bioimage-io/spec-bioimage-io/issues/new/choose 414 ) to discuss your intentions with the community.""" 415 416 @field_validator("license", mode="after") 417 @classmethod 418 def deprecated_spdx_license( 419 cls, value: Optional[Union[LicenseId, DeprecatedLicenseId, str]] 420 ): 421 if isinstance(value, LicenseId): 422 pass 423 elif value is None: 424 issue_warning("missing", value=value, field="license") 425 elif isinstance(value, DeprecatedLicenseId): 426 issue_warning( 427 "'{value}' is a deprecated license identifier.", 428 value=value, 429 field="license", 430 ) 431 elif isinstance(value, str): 432 issue_warning( 433 "'{value}' is an unknown license identifier.", 434 value=value, 435 field="license", 436 ) 437 else: 438 assert_never(value) 439 440 return value 441 442 443ResourceDescrType = TypeVar("ResourceDescrType", bound=GenericDescrBase) 444 445 446class GenericDescr(GenericDescrBase, extra="ignore"): 447 """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF). 448 449 An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook. 450 Note that those resources are described with a type-specific RDF. 451 Use this generic resource description, if none of the known specific types matches your resource. 452 """ 453 454 type: Annotated[str, LowerCase, Field(frozen=True)] = "generic" 455 """The resource type assigns a broad category to the resource.""" 456 457 id: Optional[ 458 Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])] 459 ] = None 460 """bioimage.io-wide unique resource identifier 461 assigned by bioimage.io; version **un**specific.""" 462 463 source: Optional[HttpUrl] = None 464 """The primary source of the resource""" 465 466 @field_validator("type", mode="after") 467 @classmethod 468 def check_specific_types(cls, value: str) -> str: 469 if value in KNOWN_SPECIFIC_RESOURCE_TYPES: 470 raise ValueError( 471 f"Use the {value} description instead of this generic description for" 472 + f" your '{value}' resource." 473 ) 474 475 return value
59class ResourceId(ValidatedString): 60 root_model: ClassVar[Type[RootModel[Any]]] = RootModel[ 61 Annotated[ 62 NotEmpty[str], 63 AfterValidator(str.lower), # convert upper case on the fly 64 RestrictCharacters(string.ascii_lowercase + string.digits + "_-/."), 65 annotated_types.Predicate( 66 lambda s: not (s.startswith("/") or s.endswith("/")) 67 ), 68 ] 69 ]
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
99class AttachmentsDescr(Node): 100 model_config = {**Node.model_config, "extra": "allow"} 101 """update pydantic model config to allow additional unknown keys""" 102 files: List[ImportantFileSource] = Field(default_factory=list) 103 """∈📦 File attachments"""
update pydantic model config to allow additional unknown keys
∈📦 File attachments
132class Author(_Person): 133 name: Annotated[str, AfterValidator(_remove_slashes)] 134 github_user: Optional[str] = None # TODO: validate github_user
Inherited Members
137class Maintainer(_Person): 138 name: Optional[Annotated[str, AfterValidator(_remove_slashes)]] = None 139 github_user: str
Inherited Members
142class BadgeDescr(Node): 143 """A custom badge""" 144 145 label: Annotated[str, Field(examples=["Open in Colab"])] 146 """badge label to display on hover""" 147 148 icon: Annotated[ 149 Optional[InPackageIfLocalFileSource], 150 Field(examples=["https://colab.research.google.com/assets/colab-badge.svg"]), 151 ] = None 152 """badge icon""" 153 154 url: Annotated[ 155 HttpUrl, 156 Field( 157 examples=[ 158 "https://colab.research.google.com/github/HenriquesLab/ZeroCostDL4Mic/blob/master/Colab_notebooks/U-net_2D_ZeroCostDL4Mic.ipynb" 159 ] 160 ), 161 ] 162 """target URL"""
A custom badge
badge label to display on hover
badge icon
165class CiteEntry(Node): 166 text: str 167 """free text description""" 168 169 doi: Optional[Doi] = None 170 """A digital object identifier (DOI) is the prefered citation reference. 171 See https://www.doi.org/ for details. (alternatively specify `url`)""" 172 173 @field_validator("doi", mode="before") 174 @classmethod 175 def accept_prefixed_doi(cls, doi: Any) -> Any: 176 if isinstance(doi, str): 177 for doi_prefix in ("https://doi.org/", "http://dx.doi.org/"): 178 if doi.startswith(doi_prefix): 179 doi = doi[len(doi_prefix) :] 180 break 181 182 return doi 183 184 url: Optional[str] = None 185 """URL to cite (preferably specify a `doi` instead)""" 186 187 @model_validator(mode="after") 188 def _check_doi_or_url(self) -> Self: 189 if not self.doi and not self.url: 190 raise ValueError("Either 'doi' or 'url' is required") 191 192 return self
A digital object identifier (DOI) is the prefered citation reference.
See https://www.doi.org/ for details. (alternatively specify url
)
173 @field_validator("doi", mode="before") 174 @classmethod 175 def accept_prefixed_doi(cls, doi: Any) -> Any: 176 if isinstance(doi, str): 177 for doi_prefix in ("https://doi.org/", "http://dx.doi.org/"): 178 if doi.startswith(doi_prefix): 179 doi = doi[len(doi_prefix) :] 180 break 181 182 return doi
195class LinkedResource(Node): 196 """Reference to a bioimage.io resource""" 197 198 id: ResourceId 199 """A valid resource `id` from the bioimage.io collection.""" 200 201 version_number: Optional[int] = None 202 """version number (n-th published version, not the semantic version) of linked resource"""
Reference to a bioimage.io resource
205class GenericModelDescrBase(ResourceDescrBase): 206 """Base for all resource descriptions including of model descriptions""" 207 208 name: Annotated[NotEmpty[str], warn(MaxLen(128), "Longer than 128 characters.")] 209 """A human-friendly name of the resource description""" 210 211 description: str 212 213 covers: Annotated[ 214 List[CoverImageSource], 215 Field( 216 examples=["cover.png"], 217 description=( 218 "Cover images. Please use an image smaller than 500KB and an aspect" 219 " ratio width to height of 2:1.\nThe supported image formats are:" 220 f" {VALID_COVER_IMAGE_EXTENSIONS}" 221 ), 222 ), 223 ] = Field( 224 default_factory=list, 225 ) 226 """∈📦 Cover images. Please use an image smaller than 500KB and an aspect ratio width to height of 2:1.""" 227 228 id_emoji: Optional[ 229 Annotated[str, Len(min_length=1, max_length=1), Field(examples=["🦈", "🦥"])] 230 ] = None 231 """UTF-8 emoji for display alongside the `id`.""" 232 233 authors: List[Author] = Field(default_factory=list) 234 """The authors are the creators of the RDF and the primary points of contact.""" 235 236 @field_validator("authors", mode="before") 237 @classmethod 238 def accept_author_strings(cls, authors: Union[Any, Sequence[Any]]) -> Any: 239 """we unofficially accept strings as author entries""" 240 if is_sequence(authors): 241 authors = [{"name": a} if isinstance(a, str) else a for a in authors] 242 243 if not authors: 244 issue_warning("missing", value=authors, field="authors") 245 246 return authors 247 248 attachments: Optional[AttachmentsDescr] = None 249 """file and other attachments""" 250 251 cite: List[CiteEntry] = Field(default_factory=list) 252 """citations""" 253 254 @field_validator("cite", mode="after") 255 @classmethod 256 def _warn_empty_cite(cls, value: Any): 257 if not value: 258 issue_warning("missing", value=value, field="cite") 259 260 return value 261 262 config: Annotated[ 263 Dict[str, YamlValue], 264 Field( 265 examples=[ 266 dict( 267 bioimageio={ 268 "my_custom_key": 3837283, 269 "another_key": {"nested": "value"}, 270 }, 271 imagej={"macro_dir": "path/to/macro/file"}, 272 ) 273 ], 274 ), 275 ] = Field(default_factory=dict) 276 """A field for custom configuration that can contain any keys not present in the RDF spec. 277 This means you should not store, for example, a github repo URL in `config` since we already have the 278 `git_repo` field defined in the spec. 279 Keys in `config` may be very specific to a tool or consumer software. To avoid conflicting definitions, 280 it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name, 281 for example: 282 ```yaml 283 config: 284 bioimageio: # here is the domain name 285 my_custom_key: 3837283 286 another_key: 287 nested: value 288 imagej: # config specific to ImageJ 289 macro_dir: path/to/macro/file 290 ``` 291 If possible, please use [`snake_case`](https://en.wikipedia.org/wiki/Snake_case) for keys in `config`. 292 You may want to list linked files additionally under `attachments` to include them when packaging a resource 293 (packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains 294 an altered rdf.yaml file with local references to the downloaded files)""" 295 296 download_url: Optional[HttpUrl] = None 297 """URL to download the resource from (deprecated)""" 298 299 git_repo: Annotated[ 300 Optional[str], 301 Field( 302 examples=[ 303 "https://github.com/bioimage-io/spec-bioimage-io/tree/main/example_descriptions/models/unet2d_nuclei_broad" 304 ], 305 ), 306 ] = None 307 """A URL to the Git repository where the resource is being developed.""" 308 309 icon: Union[ 310 Annotated[str, Len(min_length=1, max_length=2)], ImportantFileSource, None 311 ] = None 312 """An icon for illustration""" 313 314 links: Annotated[ 315 List[str], 316 Field( 317 examples=[ 318 ( 319 "ilastik/ilastik", 320 "deepimagej/deepimagej", 321 "zero/notebook_u-net_3d_zerocostdl4mic", 322 ) 323 ], 324 ), 325 ] = Field(default_factory=list) 326 """IDs of other bioimage.io resources""" 327 328 uploader: Optional[Uploader] = None 329 """The person who uploaded the model (e.g. to bioimage.io)""" 330 331 maintainers: List[Maintainer] = Field(default_factory=list) 332 """Maintainers of this resource. 333 If not specified `authors` are maintainers and at least some of them should specify their `github_user` name""" 334 335 rdf_source: Optional[FileSource] = None 336 """Resource description file (RDF) source; used to keep track of where an rdf.yaml was loaded from. 337 Do not set this field in a YAML file.""" 338 339 tags: Annotated[ 340 List[str], 341 Field(examples=[("unet2d", "pytorch", "nucleus", "segmentation", "dsb2018")]), 342 ] = Field(default_factory=list) 343 """Associated tags""" 344 345 @as_warning 346 @field_validator("tags") 347 @classmethod 348 def warn_about_tag_categories( 349 cls, value: List[str], info: ValidationInfo 350 ) -> List[str]: 351 categories = TAG_CATEGORIES.get(info.data["type"], {}) 352 missing_categories: List[Mapping[str, Sequence[str]]] = [] 353 for cat, entries in categories.items(): 354 if not any(e in value for e in entries): 355 missing_categories.append({cat: entries}) 356 357 if missing_categories: 358 raise ValueError( 359 "Missing tags from bioimage.io categories: {missing_categories}" 360 ) 361 362 return value 363 364 version: Optional[Version] = None 365 """The version of the resource following SemVer 2.0.""" 366 367 version_number: Optional[int] = None 368 """version number (n-th published version, not the semantic version)"""
Base for all resource descriptions including of model descriptions
A human-friendly name of the resource description
∈📦 Cover images. Please use an image smaller than 500KB and an aspect ratio width to height of 2:1.
UTF-8 emoji for display alongside the id
.
A field for custom configuration that can contain any keys not present in the RDF spec.
This means you should not store, for example, a github repo URL in config
since we already have the
git_repo
field defined in the spec.
Keys in config
may be very specific to a tool or consumer software. To avoid conflicting definitions,
it is recommended to wrap added configuration into a sub-field named with the specific domain or tool name,
for example:
config:
bioimageio: # here is the domain name
my_custom_key: 3837283
another_key:
nested: value
imagej: # config specific to ImageJ
macro_dir: path/to/macro/file
If possible, please use snake_case
for keys in config
.
You may want to list linked files additionally under attachments
to include them when packaging a resource
(packaging a resource means downloading/copying important linked files and creating a ZIP archive that contains
an altered rdf.yaml file with local references to the downloaded files)
URL to download the resource from (deprecated)
A URL to the Git repository where the resource is being developed.
An icon for illustration
IDs of other bioimage.io resources
Maintainers of this resource.
If not specified authors
are maintainers and at least some of them should specify their github_user
name
Resource description file (RDF) source; used to keep track of where an rdf.yaml was loaded from. Do not set this field in a YAML file.
The version of the resource following SemVer 2.0.
124 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 125 """We need to both initialize private attributes and call the user-defined model_post_init 126 method. 127 """ 128 init_private_attributes(self, context) 129 original_model_post_init(self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
371class GenericDescrBase(GenericModelDescrBase): 372 """Base for all resource descriptions except for the model descriptions""" 373 374 implemented_format_version: ClassVar[Literal["0.2.4"]] = "0.2.4" 375 if TYPE_CHECKING: 376 format_version: Literal["0.2.4"] = "0.2.4" 377 else: 378 format_version: Literal["0.2.4"] 379 """The format version of this resource specification 380 (not the `version` of the resource description) 381 When creating a new resource always use the latest micro/patch version described here. 382 The `format_version` is important for any consumer software to understand how to parse the fields. 383 """ 384 385 @model_validator(mode="before") 386 @classmethod 387 def _convert_from_older_format( 388 cls, data: BioimageioYamlContent, / 389 ) -> BioimageioYamlContent: 390 _convert_from_older_format(data) 391 return data 392 393 badges: List[BadgeDescr] = Field(default_factory=list) 394 """badges associated with this resource""" 395 396 documentation: Annotated[ 397 Optional[ImportantFileSource], 398 Field( 399 examples=[ 400 "https://raw.githubusercontent.com/bioimage-io/spec-bioimage-io/main/example_descriptions/models/unet2d_nuclei_broad/README.md", 401 "README.md", 402 ], 403 ), 404 ] = None 405 """∈📦 URL or relative path to a markdown file with additional documentation. 406 The recommended documentation file name is `README.md`. An `.md` suffix is mandatory.""" 407 408 license: Annotated[ 409 Union[LicenseId, DeprecatedLicenseId, str, None], 410 Field(union_mode="left_to_right", examples=["CC0-1.0", "MIT", "BSD-2-Clause"]), 411 ] = None 412 """A [SPDX license identifier](https://spdx.org/licenses/). 413 We do not support custom license beyond the SPDX license list, if you need that please 414 [open a GitHub issue](https://github.com/bioimage-io/spec-bioimage-io/issues/new/choose 415 ) to discuss your intentions with the community.""" 416 417 @field_validator("license", mode="after") 418 @classmethod 419 def deprecated_spdx_license( 420 cls, value: Optional[Union[LicenseId, DeprecatedLicenseId, str]] 421 ): 422 if isinstance(value, LicenseId): 423 pass 424 elif value is None: 425 issue_warning("missing", value=value, field="license") 426 elif isinstance(value, DeprecatedLicenseId): 427 issue_warning( 428 "'{value}' is a deprecated license identifier.", 429 value=value, 430 field="license", 431 ) 432 elif isinstance(value, str): 433 issue_warning( 434 "'{value}' is an unknown license identifier.", 435 value=value, 436 field="license", 437 ) 438 else: 439 assert_never(value) 440 441 return value
Base for all resource descriptions except for the model descriptions
∈📦 URL or relative path to a markdown file with additional documentation.
The recommended documentation file name is README.md
. An .md
suffix is mandatory.
A SPDX license identifier. We do not support custom license beyond the SPDX license list, if you need that please open a GitHub issue to discuss your intentions with the community.
417 @field_validator("license", mode="after") 418 @classmethod 419 def deprecated_spdx_license( 420 cls, value: Optional[Union[LicenseId, DeprecatedLicenseId, str]] 421 ): 422 if isinstance(value, LicenseId): 423 pass 424 elif value is None: 425 issue_warning("missing", value=value, field="license") 426 elif isinstance(value, DeprecatedLicenseId): 427 issue_warning( 428 "'{value}' is a deprecated license identifier.", 429 value=value, 430 field="license", 431 ) 432 elif isinstance(value, str): 433 issue_warning( 434 "'{value}' is an unknown license identifier.", 435 value=value, 436 field="license", 437 ) 438 else: 439 assert_never(value) 440 441 return value
124 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 125 """We need to both initialize private attributes and call the user-defined model_post_init 126 method. 127 """ 128 init_private_attributes(self, context) 129 original_model_post_init(self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
447class GenericDescr(GenericDescrBase, extra="ignore"): 448 """Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF). 449 450 An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook. 451 Note that those resources are described with a type-specific RDF. 452 Use this generic resource description, if none of the known specific types matches your resource. 453 """ 454 455 type: Annotated[str, LowerCase, Field(frozen=True)] = "generic" 456 """The resource type assigns a broad category to the resource.""" 457 458 id: Optional[ 459 Annotated[ResourceId, Field(examples=["affable-shark", "ambitious-sloth"])] 460 ] = None 461 """bioimage.io-wide unique resource identifier 462 assigned by bioimage.io; version **un**specific.""" 463 464 source: Optional[HttpUrl] = None 465 """The primary source of the resource""" 466 467 @field_validator("type", mode="after") 468 @classmethod 469 def check_specific_types(cls, value: str) -> str: 470 if value in KNOWN_SPECIFIC_RESOURCE_TYPES: 471 raise ValueError( 472 f"Use the {value} description instead of this generic description for" 473 + f" your '{value}' resource." 474 ) 475 476 return value
Specification of the fields used in a generic bioimage.io-compliant resource description file (RDF).
An RDF is a YAML file that describes a resource such as a model, a dataset, or a notebook. Note that those resources are described with a type-specific RDF. Use this generic resource description, if none of the known specific types matches your resource.
The resource type assigns a broad category to the resource.
bioimage.io-wide unique resource identifier assigned by bioimage.io; version unspecific.
467 @field_validator("type", mode="after") 468 @classmethod 469 def check_specific_types(cls, value: str) -> str: 470 if value in KNOWN_SPECIFIC_RESOURCE_TYPES: 471 raise ValueError( 472 f"Use the {value} description instead of this generic description for" 473 + f" your '{value}' resource." 474 ) 475 476 return value
124 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 125 """We need to both initialize private attributes and call the user-defined model_post_init 126 method. 127 """ 128 init_private_attributes(self, context) 129 original_model_post_init(self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.