Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Generate glossary page from schema #923

Merged
merged 7 commits into from
Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,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 @@ -148,7 +148,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 @@ -1050,7 +1050,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