From 65c87060a75e5d2e3bf10621cb315e2ab1fcd0f8 Mon Sep 17 00:00:00 2001 From: Raphael-Gazzotti <125291580+Raphael-Gazzotti@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:30:18 +0100 Subject: [PATCH] Pipeline: Namespace management update. (#29) * Version update for v4.0 * Pipeline update for namespace management, version files will need to be corrected with core and computation commit. update_commits.py is updated but not tested. * Pipeline update for namespace management, version files will need to be corrected with core, computation, controlledTerms last PRs. update_commits.py is updated but not tested. * Code simplification, variables renaming, version.json/dev file modifications. * Code simplification, lowercase of "acronym"-alike modules, versions.json update. * Typo in the pipeline name. * Signatures cleanup. * Addition of the attribute "_module". * Missing line break. --------- Co-authored-by: raphaelgazzotti --- .github/workflows/build.yml | 3 +- build.py | 7 +- openMINDS_pipeline/constants.py | 3 +- openMINDS_pipeline/models.py | 5 +- openMINDS_pipeline/resolver.py | 40 ++++- openMINDS_pipeline/utils.py | 42 +++-- openMINDS_pipeline/vocab.py | 103 +++++++++--- update_commits.py | 10 +- versions-dev.json | 74 +++++++++ versions.json | 273 ++++++++++++++++++++------------ 10 files changed, 399 insertions(+), 161 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 85879b7..96fd675 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,5 +1,5 @@ # MIT licensed -name: openMINDS_build_pipline +name: openMINDS_build_pipeline on: push: @@ -55,4 +55,3 @@ jobs: else echo "Nothing to commit" fi - diff --git a/build.py b/build.py index 2ca417f..843cc2f 100644 --- a/build.py +++ b/build.py @@ -1,5 +1,4 @@ import argparse - import sys from openMINDS_pipeline.models import DirectoryStructure, Trigger @@ -22,10 +21,9 @@ clone_central(True) # Step 1 - find the versions to be (re-)built -relevant_versions = evaluate_versions_to_be_built(args["config"], trigger) +relevant_versions, namespaces = evaluate_versions_to_be_built(args["config"], trigger) for version, modules in relevant_versions.items(): - DirectoryStructure.clear_directory(directory_structure.expanded_directory) DirectoryStructure.clear_directory(directory_structure.source_directory) @@ -33,7 +31,7 @@ clone_sources(modules, version) # Step 3 - Find all involved schemas - all_schemas = find_schemas(directory_structure, modules) + all_schemas = find_schemas(directory_structure, modules, namespaces[version]) # Step 4 - Resolve all "_extends" directives and save to target directory resolve_extends(all_schemas, directory_structure) @@ -56,7 +54,6 @@ # Step 10 - Copy results to the target directory copy_to_target_directory(directory_structure, version) - if not trigger: # We've built everything - this is the only chance to do a proper cleanup at the end because we know all versions have been processed. Types(directory_structure).clean_types() diff --git a/openMINDS_pipeline/constants.py b/openMINDS_pipeline/constants.py index 646c4d8..f37d287 100644 --- a/openMINDS_pipeline/constants.py +++ b/openMINDS_pipeline/constants.py @@ -1,3 +1,2 @@ -OPENMINDS_VOCAB="https://openminds.ebrains.eu/vocab/" SCHEMA_FILE_ENDING = ".schema.tpl.json" -INSTANCE_FILE_ENDING = ".jsonld" \ No newline at end of file +INSTANCE_FILE_ENDING = ".jsonld" diff --git a/openMINDS_pipeline/models.py b/openMINDS_pipeline/models.py index 8221b17..47ef918 100644 --- a/openMINDS_pipeline/models.py +++ b/openMINDS_pipeline/models.py @@ -21,11 +21,12 @@ class Trigger: class SchemaStructure: - def __init__(self, type, schema_group, version, file): + def __init__(self, type, schema_group, version, file, namespaces): self.type = type self.schema_group = schema_group self.file = file self.version = version + self.namespaces = namespaces self.categories = None self.absolute_path = None @@ -75,7 +76,7 @@ def find_resource_directories(self, file_ending) -> List[str]: resource_directories = set() for source in glob.glob(os.path.join(self.source_directory, f'**/*{file_ending}'), recursive=True): resource_dir = os.path.dirname(source)[len(self.source_directory) + 1:] - if ("target" not in resource_dir and "expanded" not in resource_dir): + if "target" not in resource_dir and "expanded" not in resource_dir: path_split = resource_dir.split("/") if len(path_split) == 1: resource_directories.add(path_split[0]) diff --git a/openMINDS_pipeline/resolver.py b/openMINDS_pipeline/resolver.py index 65d846d..b48a862 100644 --- a/openMINDS_pipeline/resolver.py +++ b/openMINDS_pipeline/resolver.py @@ -14,6 +14,7 @@ TEMPLATE_PROPERTY_CATEGORIES = "_categories" TEMPLATE_PROPERTY_LINKED_CATEGORIES = "_linkedCategories" TEMPLATE_PROPERTY_EMBEDDED_CATEGORIES = "_embeddedCategories" +TEMPLATE_PROPERTY_MODULE = "_module" def resolve_extends(schemas: List[SchemaStructure], directory_structure: DirectoryStructure): @@ -41,7 +42,7 @@ def resolve_categories(version:str, directory_structure: DirectoryStructure, sch schemas_by_category = _schemas_by_category(schemas) for schema in schemas: print(f"resolving categories for {schema.type}") - _do_resolve_categories(schema, schemas_by_category) + _do_resolve_categories(version, schema, schemas_by_category) categories[version] = schemas_by_category _save_categories(directory_structure, categories) @@ -71,12 +72,23 @@ def _schemas_by_category(schemas: List[SchemaStructure]) -> Dict[str, List[str]] for c in s.categories: if c not in result: result[c] = [] - result[c].append(s.type) + # lowercase "acronym"-alike modules + schema_group_normalized = s.schema_group.lower() if s.schema_group.isupper() else s.schema_group + result[c].append(schema_group_normalized + ':' + s.type) result[c].sort() return result def _do_resolve_extends(source_schema, schema, schema_group, directory_structure: DirectoryStructure): + # Autocomplete with the correct namespace, just rebuild it for older versions (replace part) + if TEMPLATE_PROPERTY_TYPE in schema: + schema_group_normalized = source_schema.schema_group.lower() if source_schema.schema_group.isupper() else source_schema.schema_group + schema[TEMPLATE_PROPERTY_TYPE] = source_schema.namespaces['types'].replace('{MODULE}', + schema_group_normalized) + \ + schema[TEMPLATE_PROPERTY_TYPE].split(":")[-1].split("/")[-1] + # Add schema module + schema[TEMPLATE_PROPERTY_MODULE] = source_schema.schema_group + if TEMPLATE_PROPERTY_EXTENDS in schema: if schema[TEMPLATE_PROPERTY_EXTENDS].startswith("/"): extends_split = schema[TEMPLATE_PROPERTY_EXTENDS].split("/") @@ -129,7 +141,20 @@ def _apply_extension(source, extension): source["properties"][k] = extension["properties"][k] -def _do_resolve_categories(schema: SchemaStructure, schemas_by_category): +def _do_resolve_categories(version:str, schema: SchemaStructure, schemas_by_category): + + def _namespace_completion_categories(schema_payload, schema, p, template_property): + def _build_namespace_type(_type): + # if _type is an URI rebuild it + # else _type consists of prefix:name_type + module = _type.split("/")[-2] if '/' in _type else _type.split(":")[0] + name_type = _type.split("/")[-1] if '/' in _type else _type.split(":")[-1] + return schema.namespaces['types'].replace('{MODULE}', module) + name_type + + schema_payload["properties"][p][template_property] = [ + _build_namespace_type(_type) for _type in schema_payload["properties"][p][template_property]] + return schema_payload + with open(schema.absolute_path, "r") as schema_file: schema_payload = json.load(schema_file) if "properties" in schema_payload: @@ -150,6 +175,13 @@ def _do_resolve_categories(schema: SchemaStructure, schemas_by_category): embedded_types.extend(schemas_by_category[embedded_category]) schema_payload["properties"][p][TEMPLATE_PROPERTY_EMBEDDED_TYPES] = sorted(embedded_types) del schema_payload["properties"][p][TEMPLATE_PROPERTY_EMBEDDED_CATEGORIES] + + # Write namespace for '_linkedTypes' and '_embeddedTypes' + if TEMPLATE_PROPERTY_LINKED_TYPES in schema_payload["properties"][p]: + _namespace_completion_categories(schema_payload, schema, p, TEMPLATE_PROPERTY_LINKED_TYPES) + + if TEMPLATE_PROPERTY_EMBEDDED_TYPES in schema_payload["properties"][p]: + _namespace_completion_categories(schema_payload, schema, p, TEMPLATE_PROPERTY_EMBEDDED_TYPES) + with open(schema.absolute_path, "w") as target_file: target_file.write(json.dumps(schema_payload, indent=2)) - diff --git a/openMINDS_pipeline/utils.py b/openMINDS_pipeline/utils.py index 7127203..98cfdbc 100644 --- a/openMINDS_pipeline/utils.py +++ b/openMINDS_pipeline/utils.py @@ -10,7 +10,7 @@ from packaging.utils import canonicalize_version from packaging.version import Version -from openMINDS_pipeline.constants import SCHEMA_FILE_ENDING, OPENMINDS_VOCAB +from openMINDS_pipeline.constants import SCHEMA_FILE_ENDING from openMINDS_pipeline.models import Trigger, OpenMINDSModule, DirectoryStructure, SchemaStructure from openMINDS_pipeline.resolver import TEMPLATE_PROPERTY_TYPE @@ -47,7 +47,7 @@ def get_basic_type(property_definition:dict) -> Optional[str]: return basic_type -def evaluate_versions_to_be_built(version_config: str, trigger:Optional[Trigger]) -> Dict[str, Dict[str, OpenMINDSModule]]: +def evaluate_versions_to_be_built(version_config: str, trigger:Optional[Trigger]) -> (Dict[str, Dict[str, OpenMINDSModule]], Dict[str, str]): """ :return: the dictionary describing all versions supposed to be built either because of a change or because of a build of everything. """ @@ -65,22 +65,29 @@ def evaluate_versions_to_be_built(version_config: str, trigger:Optional[Trigger] if os.path.exists("pipeline"): shutil.rmtree("pipeline") relevant_versions = {} - for version, modules in versions.items(): + namespaces = {} + + for version, bundle in versions.items(): triggering_module = None is_dynamic = False new_modules = {} - for module, module_spec in modules.items(): - m = OpenMINDSModule(**module_spec) - if not m.commit: - is_dynamic = True - _evaluate_branch_and_commit_for_dynamic_instances(m) - if trigger and m.repository and m.repository.endswith(f"{trigger.repository}.git"): - triggering_module = m - new_modules[module] = m + + for entry, entry_spec in bundle.items(): + if entry == "namespaces": + namespaces[version] = bundle.get("namespaces", {}) + if entry == "modules": + for module_name, module_spec in bundle[entry].items(): + m = OpenMINDSModule(**module_spec) + if not m.commit: + is_dynamic = True + _evaluate_branch_and_commit_for_dynamic_instances(m) + if trigger and m.repository and m.repository.endswith(f"{trigger.repository}.git"): + triggering_module = m + new_modules[module_name] = m # The version is only relevant if the process was not launched by a submodule change (so everything is built) or if the triggering module is specified with the given branch if not trigger or (is_dynamic and triggering_module and triggering_module.branch and triggering_module.branch == trigger.branch): relevant_versions[version] = new_modules - return relevant_versions + return relevant_versions, namespaces def _evaluate_branch_and_commit_for_dynamic_instances(module_spec:OpenMINDSModule): @@ -102,7 +109,7 @@ def _evaluate_branch_and_commit_for_dynamic_instances(module_spec:OpenMINDSModul module_spec.commit = branch_to_commit[module_spec.branch] -def find_schemas(directory_structure: DirectoryStructure, modules: Dict[str, OpenMINDSModule]) -> List[SchemaStructure]: +def find_schemas(directory_structure: DirectoryStructure, modules: Dict[str, OpenMINDSModule], namespaces: Dict[str, str]) -> List[SchemaStructure]: schema_information = [] for schema_group in directory_structure.find_resource_directories(file_ending=SCHEMA_FILE_ENDING): schema_group = schema_group.split("/")[0] @@ -116,7 +123,9 @@ def find_schemas(directory_structure: DirectoryStructure, modules: Dict[str, Ope with open(schema_path, "r") as schema_file: schema = json.load(schema_file) if TEMPLATE_PROPERTY_TYPE in schema: - schema_information.append(SchemaStructure(schema[TEMPLATE_PROPERTY_TYPE], schema_group, version, relative_schema_path)) + # remove namespace, will be rebuilt in resolve_extends and resolve_categories + schema[TEMPLATE_PROPERTY_TYPE] = schema[TEMPLATE_PROPERTY_TYPE].split(":")[-1].split("/")[-1] + schema_information.append(SchemaStructure(schema[TEMPLATE_PROPERTY_TYPE], schema_group, version, relative_schema_path, namespaces)) else: print(f"Skipping schema {relative_schema_path} because it doesn't contain a valid type") except JSONDecodeError: @@ -133,12 +142,11 @@ def qualify_property_names(schemas:List[SchemaStructure]): if "properties" in schema_payload: new_properties = {} for p, v in schema_payload["properties"].items(): - new_properties[f"{OPENMINDS_VOCAB}{p}"] = v + new_properties[f"{schema.namespaces['props']}{p}"] = v schema_payload["properties"] = new_properties if "required" in schema_payload: - schema_payload["required"] = [f"{OPENMINDS_VOCAB}{p}" for p in schema_payload["required"]] + schema_payload["required"] = [f"{schema.namespaces['props']}{p}" for p in schema_payload["required"]] schema_payload["required"].sort() - with open(schema.absolute_path, "w") as target_file: target_file.write(json.dumps(schema_payload, indent=2, sort_keys=True)) diff --git a/openMINDS_pipeline/vocab.py b/openMINDS_pipeline/vocab.py index a335ddf..607c107 100644 --- a/openMINDS_pipeline/vocab.py +++ b/openMINDS_pipeline/vocab.py @@ -1,7 +1,7 @@ import json import os import re -from typing import List +from typing import List, Dict from openMINDS_pipeline.models import DirectoryStructure, SchemaStructure from openMINDS_pipeline.resolver import TEMPLATE_PROPERTY_TYPE @@ -12,48 +12,50 @@ def _camel_case_to_human_readable(value: str): return re.sub("([a-z])([A-Z])", "\g<1> \g<2>", value).capitalize() -def enrich_with_types_and_properties(version: str, types, properties, schemas: List[SchemaStructure]): - for schema_info in schemas: +def enrich_with_types_and_properties(version, types, properties, schemas: List[SchemaStructure]): + for schema_info in schemas: print(f"Enriching schema {schema_info.file}") with open(schema_info.absolute_path, "r") as schema_file: schema = json.load(schema_file) - type = schema[TEMPLATE_PROPERTY_TYPE] + type = schema[TEMPLATE_PROPERTY_TYPE].split(":")[-1].split("/")[-1] if type in types: _enrich_with_type_information(schema, type, types) + if "properties" in schema: for p in schema["properties"]: - _enrich_with_property_information(version, p, properties, schema) + property_with_namespace = p + p = p.split('/')[-1] + _enrich_with_property_information(schema_info.version, p, properties, schema, property_with_namespace) with open(schema_info.absolute_path, "w") as schema_file: schema_file.write(json.dumps(schema, indent=2, sort_keys=True)) -def _enrich_with_property_information(version: str, p, properties, schema): +def _enrich_with_property_information(version: str, p, properties, schema, property_with_namespace): if p in properties: prop = properties[p] if "description" in prop and prop["description"]: - schema["properties"][p]["description"] = prop["description"] + schema["properties"][property_with_namespace]["description"] = prop["description"] if "label" in prop and prop["label"]: - schema["properties"][p]["label"] = prop["label"] + schema["properties"][property_with_namespace]["label"] = prop["label"] if "labelPlural" in prop and prop["labelPlural"]: - schema["properties"][p]["labelPlural"] = prop["labelPlural"] + schema["properties"][property_with_namespace]["labelPlural"] = prop["labelPlural"] if "name" in prop and prop["name"]: - schema["properties"][p]["name"] = prop["name"] + schema["properties"][property_with_namespace]["name"] = prop["name"] if "namePlural" in prop and prop["namePlural"]: - schema["properties"][p]["namePlural"] = prop["namePlural"] + schema["properties"][property_with_namespace]["namePlural"] = prop["namePlural"] if "semanticEquivalent" in prop and prop["semanticEquivalent"]: - schema["properties"][p]["semanticEquivalent"] = prop["semanticEquivalent"] + schema["properties"][property_with_namespace]["semanticEquivalent"] = prop["semanticEquivalent"] - embedded_types, linked_types, edge = is_edge(schema["properties"][p]) + embedded_types, linked_types, edge = is_edge(schema["properties"][property_with_namespace]) if edge and "asEdge" in prop: for k, v in prop["asEdge"].items(): if k != "canPointTo": - schema["properties"][p][k] = v - basic_type = get_basic_type(schema["properties"][p]) + schema["properties"][property_with_namespace][k] = v + basic_type = get_basic_type(schema["properties"][property_with_namespace]) if basic_type == "string" and "asString" in prop: for k, v in prop["asString"].items(): if k != "inVersions": - schema["properties"][p][k] = v - + schema["properties"][property_with_namespace][k] = v def _enrich_with_type_information(schema, type, types): t = types[type] @@ -78,7 +80,12 @@ def __init__(self, directory_structure: DirectoryStructure): def _load_types(self): if os.path.exists(self._types_file): with open(self._types_file, "r") as types_f: - return json.load(types_f) + _types = json.load(types_f) + _type_names = {} + for source_type in _types: + # remove namespace + _type_names[source_type.split(":")[-1].split("/")[-1]] = _types[source_type] + return _type_names else: return {} @@ -103,6 +110,7 @@ class TypeExtractor(Types): def __init__(self, directory_structure: DirectoryStructure, version: str): super().__init__(directory_structure) self._version = version + self._namespaces = None def extract_types(self, schemas) -> dict: new_types = [] @@ -125,12 +133,17 @@ def extract_types(self, schemas) -> dict: return self._types def _extract_type(self, schema: SchemaStructure) -> str: + self._namespaces = schema.namespaces + with open(schema.absolute_path, "r") as schema_file: schema_payload = json.load(schema_file) - t = schema_payload[TEMPLATE_PROPERTY_TYPE] + # Remove the namespace of the type + t = schema_payload[TEMPLATE_PROPERTY_TYPE].split(":")[-1].split("/")[-1] + if t in self._types: for k in list(self._types[t].keys()): - if k not in ["label", "labelPlural", "name", "namePlural", "description", "semanticEquivalent", "isPartOfVersion", "color"]: + if k not in ["label", "labelPlural", "name", "namePlural", "description", "semanticEquivalent", + "isPartOfVersion", "color", "hasNamespace"]: del self._types[t][k] simple_name = os.path.basename(t) if t not in self._types: @@ -153,6 +166,25 @@ def _extract_type(self, schema: SchemaStructure) -> str: if self._version not in self._types[t]["isPartOfVersion"]: self._types[t]["isPartOfVersion"].append(self._version) self._types[t]["isPartOfVersion"].sort() + + # replace by the module name in the versions prior to v4.0 + schema_group_normalized = schema.schema_group.lower() if schema.schema_group.isupper() else schema.schema_group + type_namespace= self._namespaces['types'].replace('{MODULE}', schema_group_normalized) + if "hasNamespace" not in self._types[t]: + self._types[t]["hasNamespace"] = [] + self._types[t]["hasNamespace"].append({'namespace': type_namespace, + 'inVersions': [self._version]}) + + tmp_namespaces = [] + for x in self._types[t]["hasNamespace"]: + tmp_namespaces.append(x["namespace"]) + if self._namespaces['types'].replace('{MODULE}', schema_group_normalized) == x["namespace"] and self._version not in x["inVersions"]: + x["inVersions"].append(self._version) + if type_namespace not in tmp_namespaces: + self._types[t]["hasNamespace"].append({'namespace': type_namespace, + 'inVersions': [self._version]}) + # Sort the 'hasNamespace' list based on 'inVersions' + self._types[t]["hasNamespace"].sort(key=lambda x: sorted(x["inVersions"])) return t @@ -165,7 +197,13 @@ def __init__(self, directory_structure: DirectoryStructure): def _load_properties(self): if os.path.exists(self._properties_file): with open(self._properties_file, "r") as properties_f: - return json.load(properties_f) + _properties = json.load(properties_f) + _properties_names = {} + for source_property in _properties: + # remove namespace, not necessary to check for ':' here (only done for types). + cleaned_property = source_property.split('/')[-1] + _properties_names[cleaned_property] = _properties[source_property] + return _properties_names else: return {} @@ -190,23 +228,26 @@ class PropertyExtractor(Property): def __init__(self, directory_structure: DirectoryStructure, version: str): super().__init__(directory_structure) self._version = version + self._namespaces = None def _extract_properties_for_schema(self, schema: SchemaStructure): + self._namespaces = schema.namespaces with open(schema.absolute_path, "r") as schema_file: schema_payload = json.load(schema_file) t = schema_payload[TEMPLATE_PROPERTY_TYPE] if "properties" in schema_payload: for p, v in schema_payload["properties"].items(): + # remove namespace, not necessary to check for ':' here (only done for types). + p = p.split('/')[-1] self._extract_property(t, p, v) def _extract_property(self, type: str, property: str, definition: dict): if property not in self._properties: self._properties[property] = {} prop = self._properties[property] - # Clear all unexpected fields for k in list(prop.keys()): - if k not in ["label", "labelPlural", "name", "namePlural", "description", "semanticEquivalent", "asEdge", "asString", "usedIn"]: + if k not in ["label", "labelPlural", "name", "namePlural", "description", "semanticEquivalent", "asEdge", "asString", "usedIn", "hasNamespace"]: del prop[k] # Set default values for manually managed properties @@ -263,6 +304,22 @@ def _extract_property(self, type: str, property: str, definition: dict): if "multiline" not in prop["asString"]: prop["asString"]["multiline"] = False + if "hasNamespace" not in prop: + prop["hasNamespace"] = [] + prop["hasNamespace"].append({'namespace': self._namespaces['props'], + 'inVersions': [self._version]}) + + tmp_namespaces = [] + for x in prop["hasNamespace"]: + tmp_namespaces.append(x["namespace"]) + if self._namespaces['props'] == x["namespace"] and self._version not in x["inVersions"]: + x["inVersions"].append(self._version) + if self._namespaces['props'] not in tmp_namespaces: + prop["hasNamespace"].append({'namespace': self._namespaces['props'], + 'inVersions': [self._version]}) + # Sort the 'hasNamespace' list based on 'inVersions' + prop["hasNamespace"].sort(key=lambda x: sorted(x["inVersions"])) + def extract_properties(self, schemas) -> dict: self._load_properties() self._clear_current_version() diff --git a/update_commits.py b/update_commits.py index 9b1b97c..7362427 100644 --- a/update_commits.py +++ b/update_commits.py @@ -11,19 +11,13 @@ versions = json.load(v) current_version = versions[args["version"]] updated = current_version.copy() - for k, v in current_version.items(): + for k, v in current_version['modules'].items(): if "commit" in v: raise ValueError(f"The version \"{args['version']}\" already contains at least one commit information.") command = ["git", "ls-remote", v["repository"], f"refs/heads/{v['branch']}"] output = subprocess.check_output(command).decode('utf-8').strip() latest_commit_hash = output.split()[0] - updated[k]["commit"] = latest_commit_hash + updated['modules'][k]["commit"] = latest_commit_hash versions[args["version"]] = updated with open("versions.json", "w") as result: result.write(json.dumps(versions, indent=2, sort_keys=True)) - - - - - - diff --git a/versions-dev.json b/versions-dev.json index 915e97a..58fc262 100644 --- a/versions-dev.json +++ b/versions-dev.json @@ -1,5 +1,9 @@ { "latest": { + "namespaces": { + "props": "https://openminds.om-i.org/props/", + "types": "https://openminds.om-i.org/types/" + }, "SANDS": { "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" }, @@ -33,6 +37,10 @@ } }, "v1.0": { + "namespaces": { + "props": "https://openminds.ebrains.eu/vocab/", + "types": "https://openminds.ebrains.eu/{MODULE}/" + }, "SANDS": { "branch": "v1", "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" @@ -47,6 +55,10 @@ } }, "v2.0": { + "namespaces": { + "props": "https://openminds.ebrains.eu/vocab/", + "types": "https://openminds.ebrains.eu/{MODULE}/" + }, "SANDS": { "branch": "v2", "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" @@ -61,6 +73,10 @@ } }, "v3.0": { + "namespaces": { + "props": "https://openminds.ebrains.eu/vocab/", + "types": "https://openminds.ebrains.eu/{MODULE}/" + }, "SANDS": { "branch": "v3", "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" @@ -97,5 +113,63 @@ "branch": "v1", "repository": "https://github.com/openMetadataInitiative/openMINDS_stimulation.git" } + }, + "v4.0": { + "namespaces": { + "props": "https://openminds.om-i.org/props/", + "types": "https://openminds.om-i.org/types/" + }, + "modules": { + "SANDS": { + "branch": "v4", + "commit": "9d3ed733c65ed0959364ee0255877224f5167414", + "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" + }, + "chemicals": { + "branch": "v2", + "commit": "fab4986659c4abd6e9a41356b9cd7c6f0cf88cc5", + "repository": "https://github.com/openMetadataInitiative/openMINDS_chemicals.git" + }, + "computation": { + "branch": "v2", + "commit": "ada215e3ae768948918d651aa4ff99e3372f04fd", + "repository": "https://github.com/openMetadataInitiative/openMINDS_computation.git" + }, + "controlledTerms": { + "branch": "v2", + "commit": "2fd8b53fe1fdda8e8e7be79cce6426ce2d5360b3", + "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" + }, + "core": { + "branch": "v5", + "commit": "5a64aa9dd0db8ac07b9010c7d51963d06f19a58f", + "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + }, + "ephys": { + "branch": "v2", + "commit": "3a043926e04184a5c4dbb92992301303d5d79f31", + "repository": "https://github.com/openMetadataInitiative/openMINDS_ephys.git" + }, + "publications": { + "branch": "v2", + "commit": "104783cc7330ef4e4a9118b4de612c0eec46cc85", + "repository": "https://github.com/openMetadataInitiative/openMINDS_publications.git" + }, + "specimenPrep": { + "branch": "v2", + "commit": "10ee61dd93e614385772d5fc5fbe59f8016c8136", + "repository": "https://github.com/openMetadataInitiative/openMINDS_specimenPrep.git" + }, + "stimulation": { + "branch": "v2", + "commit": "da22d249e824dc02c1ad0e358f82430a2afa2a87", + "repository": "https://github.com/openMetadataInitiative/openMINDS_stimulation.git" + }, + "neuroimaging": { + "branch": "dev", + "commit": "e94c255620c8bb9cc1f42b8d3847a38f9b4ca710", + "repository": "https://github.com/openMetadataInitiative/openMINDS_neuroimaging.git" + } + } } } diff --git a/versions.json b/versions.json index 5d07f06..1e1cf10 100644 --- a/versions.json +++ b/versions.json @@ -1,112 +1,189 @@ { "latest": { - "SANDS": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" - }, - "chemicals": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_chemicals.git" - }, - "computation": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_computation.git" - }, - "controlledTerms": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" - }, - "core": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" - }, - "ephys": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_ephys.git" - }, - "publications": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_publications.git" - }, - "specimenPrep": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_specimenPrep.git" - }, - "stimulation": { - "repository": "https://github.com/openMetadataInitiative/openMINDS_stimulation.git" + "namespaces": { + "props": "https://openminds.om-i.org/props/", + "types": "https://openminds.om-i.org/types/" + }, + "modules": { + "SANDS": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" + }, + "chemicals": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_chemicals.git" + }, + "computation": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_computation.git" + }, + "controlledTerms": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" + }, + "core": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + }, + "ephys": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_ephys.git" + }, + "publications": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_publications.git" + }, + "specimenPrep": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_specimenPrep.git" + }, + "stimulation": { + "repository": "https://github.com/openMetadataInitiative/openMINDS_stimulation.git" + } } }, "v1.0": { - "SANDS": { - "branch": "v1", - "commit": "e174e567600aa13fa81bc9c8f6bc1d7f9e7624c5", - "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" - }, - "controlledTerms": { - "branch": "v1", - "commit": "2400e43e873fbfadd9f776fa69bc541a86144c8a", - "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" - }, - "core": { - "branch": "v3", - "commit": "d328b5709bda8a61a3f1cb151780dfb5ef870b1a", - "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + "namespaces": { + "props": "https://openminds.ebrains.eu/vocab/", + "types": "https://openminds.ebrains.eu/{MODULE}/" + }, + "modules": { + "SANDS": { + "branch": "v1", + "commit": "e174e567600aa13fa81bc9c8f6bc1d7f9e7624c5", + "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" + }, + "controlledTerms": { + "branch": "v1", + "commit": "2400e43e873fbfadd9f776fa69bc541a86144c8a", + "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" + }, + "core": { + "branch": "v3", + "commit": "d328b5709bda8a61a3f1cb151780dfb5ef870b1a", + "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + } } }, "v2.0": { - "SANDS": { - "branch": "v2", - "commit": "be95b2bee743f1443167dc59ec3ffcc00a51b7db", - "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" - }, - "controlledTerms": { - "branch": "v1", - "commit": "1fb6b233720c6ff36829a17c8025424a7db7f8f0", - "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" - }, - "core": { - "branch": "v3", - "commit": "8c61d390419d35ff53ef85a13a8c4a9587af682f", - "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + "namespaces": { + "props": "https://openminds.ebrains.eu/vocab/", + "types": "https://openminds.ebrains.eu/{MODULE}/" + }, + "modules": { + "SANDS": { + "branch": "v2", + "commit": "be95b2bee743f1443167dc59ec3ffcc00a51b7db", + "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" + }, + "controlledTerms": { + "branch": "v1", + "commit": "1fb6b233720c6ff36829a17c8025424a7db7f8f0", + "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" + }, + "core": { + "branch": "v3", + "commit": "8c61d390419d35ff53ef85a13a8c4a9587af682f", + "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + } } }, "v3.0": { - "SANDS": { - "branch": "v3", - "commit": "ac2e238661c96bdfa98127b90dad35af6c132d50", - "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" - }, - "chemicals": { - "branch": "v1", - "commit": "57b5ce3c6d569f0bb8ce761adb48746fd1d970b2", - "repository": "https://github.com/openMetadataInitiative/openMINDS_chemicals.git" - }, - "computation": { - "branch": "v1", - "commit": "57e160465c285be1780f74cffa80d16209e2a706", - "repository": "https://github.com/openMetadataInitiative/openMINDS_computation.git" - }, - "controlledTerms": { - "branch": "v1", - "commit": "ec74648f99e9b02d4afde37c6aa7ae80919f460f", - "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" - }, - "core": { - "branch": "v4", - "commit": "8b2bc673cbd57a8620a306a7a84253bd6ecd30eb", - "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" - }, - "ephys": { - "branch": "v1", - "commit": "2accac60e9dc50116c5eee8893cffcd5b1bf24c8", - "repository": "https://github.com/openMetadataInitiative/openMINDS_ephys.git" - }, - "publications": { - "branch": "v1", - "commit": "d5446304a052a238d431a06bd66d0e444372f159", - "repository": "https://github.com/openMetadataInitiative/openMINDS_publications.git" - }, - "specimenPrep": { - "branch": "v1", - "commit": "0669813dae142946a19f00645b0d8c2d66d01975", - "repository": "https://github.com/openMetadataInitiative/openMINDS_specimenPrep.git" - }, - "stimulation": { - "branch": "v1", - "commit": "3916f02c139fe50c73aa0ad5ed35bae55d85e76c", - "repository": "https://github.com/openMetadataInitiative/openMINDS_stimulation.git" + "namespaces": { + "props": "https://openminds.ebrains.eu/vocab/", + "types": "https://openminds.ebrains.eu/{MODULE}/" + }, + "modules": { + "SANDS": { + "branch": "v3", + "commit": "ac2e238661c96bdfa98127b90dad35af6c132d50", + "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" + }, + "chemicals": { + "branch": "v1", + "commit": "57b5ce3c6d569f0bb8ce761adb48746fd1d970b2", + "repository": "https://github.com/openMetadataInitiative/openMINDS_chemicals.git" + }, + "computation": { + "branch": "v1", + "commit": "57e160465c285be1780f74cffa80d16209e2a706", + "repository": "https://github.com/openMetadataInitiative/openMINDS_computation.git" + }, + "controlledTerms": { + "branch": "v1", + "commit": "ec74648f99e9b02d4afde37c6aa7ae80919f460f", + "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" + }, + "core": { + "branch": "v4", + "commit": "8b2bc673cbd57a8620a306a7a84253bd6ecd30eb", + "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + }, + "ephys": { + "branch": "v1", + "commit": "2accac60e9dc50116c5eee8893cffcd5b1bf24c8", + "repository": "https://github.com/openMetadataInitiative/openMINDS_ephys.git" + }, + "publications": { + "branch": "v1", + "commit": "d5446304a052a238d431a06bd66d0e444372f159", + "repository": "https://github.com/openMetadataInitiative/openMINDS_publications.git" + }, + "specimenPrep": { + "branch": "v1", + "commit": "0669813dae142946a19f00645b0d8c2d66d01975", + "repository": "https://github.com/openMetadataInitiative/openMINDS_specimenPrep.git" + }, + "stimulation": { + "branch": "v1", + "commit": "4dfdbadde9223ea9b6b48f377a424d23b1c8cf04", + "repository": "https://github.com/openMetadataInitiative/openMINDS_stimulation.git" + } + } + }, + "v4.0": { + "namespaces": { + "props": "https://openminds.om-i.org/props/", + "types": "https://openminds.om-i.org/types/" + }, + "modules": { + "SANDS": { + "branch": "v4", + "commit": "9d3ed733c65ed0959364ee0255877224f5167414", + "repository": "https://github.com/openMetadataInitiative/openMINDS_SANDS.git" + }, + "chemicals": { + "branch": "v2", + "commit": "fab4986659c4abd6e9a41356b9cd7c6f0cf88cc5", + "repository": "https://github.com/openMetadataInitiative/openMINDS_chemicals.git" + }, + "computation": { + "branch": "v2", + "commit": "ada215e3ae768948918d651aa4ff99e3372f04fd", + "repository": "https://github.com/openMetadataInitiative/openMINDS_computation.git" + }, + "controlledTerms": { + "branch": "v2", + "commit": "2fd8b53fe1fdda8e8e7be79cce6426ce2d5360b3", + "repository": "https://github.com/openMetadataInitiative/openMINDS_controlledTerms.git" + }, + "core": { + "branch": "v5", + "commit": "5a64aa9dd0db8ac07b9010c7d51963d06f19a58f", + "repository": "https://github.com/openMetadataInitiative/openMINDS_core.git" + }, + "ephys": { + "branch": "v2", + "commit": "3a043926e04184a5c4dbb92992301303d5d79f31", + "repository": "https://github.com/openMetadataInitiative/openMINDS_ephys.git" + }, + "publications": { + "branch": "v2", + "commit": "104783cc7330ef4e4a9118b4de612c0eec46cc85", + "repository": "https://github.com/openMetadataInitiative/openMINDS_publications.git" + }, + "specimenPrep": { + "branch": "v2", + "commit": "10ee61dd93e614385772d5fc5fbe59f8016c8136", + "repository": "https://github.com/openMetadataInitiative/openMINDS_specimenPrep.git" + }, + "stimulation": { + "branch": "v2", + "commit": "da22d249e824dc02c1ad0e358f82430a2afa2a87", + "repository": "https://github.com/openMetadataInitiative/openMINDS_stimulation.git" + } } } }