diff --git a/mkdocs.yml b/mkdocs.yml index 8cfc8853d9..96b856c6db 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -59,6 +59,7 @@ nav: - Quantitative MRI: 99-appendices/11-qmri.md - Arterial Spin Labeling: 99-appendices/12-arterial-spin-labeling.md - Cross modality correspondence: 99-appendices/13-cross-modality-correspondence.md + - Glossary: 99-appendices/14-glossary.md - Changelog: CHANGES.md - The BIDS Starter Kit: - GitHub repository: https://github.com/bids-standard/bids-starter-kit diff --git a/src/04-modality-specific-files/01-magnetic-resonance-imaging-data.md b/src/04-modality-specific-files/01-magnetic-resonance-imaging-data.md index aa5c2c7f12..a6c911a2c4 100644 --- a/src/04-modality-specific-files/01-magnetic-resonance-imaging-data.md +++ b/src/04-modality-specific-files/01-magnetic-resonance-imaging-data.md @@ -150,7 +150,7 @@ Useful for multimodal co-registration with MEG, (S)EEG, TMS, and so on. {{ MACROS___make_metadata_table( { - "AnatomicalLandmarkCoordinates_mri": "RECOMMENDED", + "AnatomicalLandmarkCoordinates__mri": "RECOMMENDED", } ) }} @@ -1072,7 +1072,7 @@ Required fields: {{ MACROS___make_metadata_table( { - "EchoTime_fmap": "REQUIRED", + "EchoTime__fmap": "REQUIRED", } ) }} diff --git a/src/99-appendices/14-glossary.md b/src/99-appendices/14-glossary.md new file mode 100644 index 0000000000..8f9affb6f1 --- /dev/null +++ b/src/99-appendices/14-glossary.md @@ -0,0 +1,9 @@ +# Appendix XIV: Glossary of schema objects + +This section compiles the object definitions in the schema. + + +{{ MACROS___make_glossary() }} diff --git a/src/schema/objects/associated_data.yaml b/src/schema/objects/associated_data.yaml index 50fa80247c..901e17bdac 100644 --- a/src/schema/objects/associated_data.yaml +++ b/src/schema/objects/associated_data.yaml @@ -10,7 +10,8 @@ code: source data. derivatives: name: Derivative data - description: + description: | + Derivative data sourcedata: name: Source data description: | diff --git a/src/schema/objects/datatypes.yaml b/src/schema/objects/datatypes.yaml index f17e8feb9f..1366f66da9 100644 --- a/src/schema/objects/datatypes.yaml +++ b/src/schema/objects/datatypes.yaml @@ -37,4 +37,5 @@ perf: Blood perfusion imaging data, including arterial spin labeling (ASL) pet: name: Positron Emission Tomography - description: + description: | + Positron emission tomography data diff --git a/src/schema/objects/metadata.yaml b/src/schema/objects/metadata.yaml index 873f69a357..f8118c6351 100644 --- a/src/schema/objects/metadata.yaml +++ b/src/schema/objects/metadata.yaml @@ -104,7 +104,8 @@ AnatomicalLandmarkCoordinates: type: number minItems: 3 maxItems: 3 -AnatomicalLandmarkCoordinates_mri: +# Redefinition of AnatomicalLandmarkCoordinates for MRI data +AnatomicalLandmarkCoordinates__mri: name: AnatomicalLandmarkCoordinates description: | Key:value pairs of any number of additional anatomical landmarks and their @@ -682,7 +683,8 @@ EchoTime2: type: number unit: s exclusiveMinimum: 0 -EchoTime_fmap: +# Redefinition of EchoTime for fieldmap data +EchoTime__fmap: name: EchoTime description: | The time (in seconds) when the echo corresponding to this map was acquired. diff --git a/tools/mkdocs_macros_bids/macros.py b/tools/mkdocs_macros_bids/macros.py index 2cfa5e4b78..0531203e24 100644 --- a/tools/mkdocs_macros_bids/macros.py +++ b/tools/mkdocs_macros_bids/macros.py @@ -70,6 +70,21 @@ def make_entity_definitions(): return text +def make_glossary(): + """Generate glossary. + + Returns + ------- + text : str + A multiline string containing descriptions and some formatting + information about the entities in the schema. + """ + schemapath = utils.get_schema_path() + schema_obj = schema.load_schema(schemapath) + text = schema.make_glossary(schema_obj) + return text + + def make_suffix_table(suffixes): """Generate a markdown table of suffix information. diff --git a/tools/mkdocs_macros_bids/main.py b/tools/mkdocs_macros_bids/main.py index 8db94a0411..56c1d725ed 100644 --- a/tools/mkdocs_macros_bids/main.py +++ b/tools/mkdocs_macros_bids/main.py @@ -35,6 +35,7 @@ def define_env(env): macros.make_entity_definitions, "MACROS___make_entity_definitions", ) + env.macro(macros.make_glossary, "MACROS___make_glossary") env.macro(macros.make_suffix_table, "MACROS___make_suffix_table") env.macro(macros.make_metadata_table, "MACROS___make_metadata_table") env.macro(macros.make_columns_table, "MACROS___make_columns_table") diff --git a/tools/schemacode/schema.py b/tools/schemacode/schema.py index f4ec722d69..77529e45d5 100644 --- a/tools/schemacode/schema.py +++ b/tools/schemacode/schema.py @@ -13,6 +13,9 @@ from . import utils +# import utils + + lgr = utils.get_logger() # Basic settings for output, for now just basic utils.set_logger_level( @@ -208,6 +211,81 @@ def make_entity_definitions(schema): return text +def make_glossary(schema): + """Generate glossary. + + Parameters + ---------- + schema : dict + The schema object, which is a dictionary with nested dictionaries and + lists stored within it. + + Returns + ------- + text : str + A string containing descriptions and some formatting + information about the entities in the schema. + """ + all_objects = {} + + for group, group_objects in schema["objects"].items(): + group_obj_keys = list(group_objects.keys()) + # Remove private objects + group_obj_keys = [k for k in group_obj_keys if not k.startswith("_")] + + multi_sense_objects = [] + # Identify multi-sense objects (multiple entries, some with __ in them) + for key in group_obj_keys: + if "__" in key: + temp_key = key.split("__")[0] + multi_sense_objects.append(temp_key) + + multi_sense_objects = sorted(list(set(multi_sense_objects))) + sense_keys = {mso: [] for mso in multi_sense_objects} + + for key in group_obj_keys: + for sense_key in sense_keys.keys(): + if (key == sense_key) or (key.startswith(sense_key + "__")): + sense_keys[sense_key].append(key) + + sense_names = {} + for sense_key, key_list in sense_keys.items(): + for i_key, key in enumerate(key_list): + new_key_name = f"{sense_key} _sense {i_key + 1}_" + sense_names[key] = new_key_name + + for key in group_obj_keys: + new_name = sense_names.get(key, key) + new_name = f"{new_name} ({group})" + all_objects[new_name] = {} + all_objects[new_name]["key"] = f"objects.{group}.{key}" + all_objects[new_name]["definition"] = group_objects[key] + + text = "" + for obj_key in sorted(all_objects.keys()): + obj = all_objects[obj_key] + obj_marker = obj["key"] + obj_def = obj["definition"] + obj_name = obj_def["name"] + obj_desc = obj_def["description"] + # A backslash before a newline means continue a string + obj_desc = obj_desc.replace("\\\n", "") + # Two newlines should be respected + obj_desc = obj_desc.replace("\n\n", "
") + # Otherwise a newline corresponds to a space + obj_desc = obj_desc.replace("\n", " ") + + text += f'\n' + text += f"\n## {obj_key}\n\n" + text += f"name: {obj_name}\n\n" + text += f"description:\n>{obj_desc}\n\n" + + temp_obj_def = {k: v for k, v in obj_def.items() if k not in ("description", "name")} + text += f"schema information:\n```yaml\n{temp_obj_def}\n```" + + return text + + def _add_entity(filename_template, entity_pattern, requirement_level): """Add entity pattern to filename template based on requirement level.""" if requirement_level == "required":