Skip to content

Commit

Permalink
[ENH] Generate glossary page from schema (#923)
Browse files Browse the repository at this point in the history
* Use two underscores for multi-sense metadata entries.

* Fill in missing object descriptions.

* Draft glossary page.

* Use better key.

* Place marker.
  • Loading branch information
tsalo authored Dec 15, 2021
1 parent 05f7ce1 commit 7489ff5
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 6 deletions.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}
) }}

Expand Down Expand Up @@ -1072,7 +1072,7 @@ Required fields:

{{ MACROS___make_metadata_table(
{
"EchoTime_fmap": "REQUIRED",
"EchoTime__fmap": "REQUIRED",
}
) }}

Expand Down
9 changes: 9 additions & 0 deletions src/99-appendices/14-glossary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Appendix XIV: Glossary of schema objects

This section compiles the object definitions in the schema.

<!--
This section is autogenerated based on the src/schema. DO NOT EDIT DIRECTLY.
Follow https://github.com/bids-standard/bids-specification/blob/master/CONTRIBUTING.md#updating-the-schema
-->
{{ MACROS___make_glossary() }}
3 changes: 2 additions & 1 deletion src/schema/objects/associated_data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ code:
source data.
derivatives:
name: Derivative data
description:
description: |
Derivative data
sourcedata:
name: Source data
description: |
Expand Down
3 changes: 2 additions & 1 deletion src/schema/objects/datatypes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 4 additions & 2 deletions src/schema/objects/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
15 changes: 15 additions & 0 deletions tools/mkdocs_macros_bids/macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions tools/mkdocs_macros_bids/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
78 changes: 78 additions & 0 deletions tools/schemacode/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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", "<br>")
# Otherwise a newline corresponds to a space
obj_desc = obj_desc.replace("\n", " ")

text += f'\n<a name="{obj_marker}"></a>'
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":
Expand Down

0 comments on commit 7489ff5

Please sign in to comment.