diff --git a/tools/schemacode/bidsschematools/render.py b/tools/schemacode/bidsschematools/render.py
index 5971af423e..ee68e2bfa9 100644
--- a/tools/schemacode/bidsschematools/render.py
+++ b/tools/schemacode/bidsschematools/render.py
@@ -6,6 +6,7 @@
from collections.abc import Mapping
import pandas as pd
+import yaml
from tabulate import tabulate
from . import utils
@@ -16,6 +17,19 @@
utils.set_logger_level(lgr, os.environ.get("BIDS_SCHEMA_LOG_LEVEL", logging.INFO))
logging.basicConfig(format="%(asctime)-15s [%(levelname)8s] %(message)s")
+TYPE_CONVERTER = {
+ "associated_data": "associated data",
+ "columns": "column",
+ "common_principles": "common principle",
+ "datatypes": "datatype",
+ "entities": "entity",
+ "extensions": "extension",
+ "formats": "format",
+ "metadata": "metadata",
+ "top_level_files": "top level file",
+ "suffixes": "suffix",
+}
+
def get_relpath(src_path):
"""Retrieve relative path to the source root from the perspective of a Markdown file.
@@ -77,24 +91,29 @@ def make_entity_definitions(schema, src_path=None):
text = ""
for entity in entity_order:
entity_info = entity_definitions[entity]
- entity_shorthand = entity_info["name"]
- text += "\n"
- text += "## {}".format(entity_shorthand)
- text += "\n\n"
- text += "Full name: {}".format(entity_info["display_name"])
- text += "\n\n"
- text += "Format: `{}-<{}>`".format(
- entity_info["name"],
- entity_info.get("format", "label"),
- )
+ entity_text = _make_entity_definition(entity, entity_info, src_path)
+ text += "\n" + entity_text
+
+ return text
+
+
+def _make_entity_definition(entity, entity_info, src_path):
+ """Describe an entity."""
+ entity_shorthand = entity_info["name"]
+ text = ""
+ text += "## {}".format(entity_shorthand)
+ text += "\n\n"
+ text += f"**Full name**: {entity_info['display_name']}"
+ text += "\n\n"
+ text += f"**Format**: `{entity_info['name']}-<{entity_info.get('format', 'label')}>`"
+ text += "\n\n"
+ if "enum" in entity_info.keys():
+ text += f"**Allowed values**: `{'`, `'.join(entity_info['enum'])}`"
text += "\n\n"
- if "enum" in entity_info.keys():
- text += "Allowed values: `{}`".format("`, `".join(entity_info["enum"]))
- text += "\n\n"
- description = entity_info["description"]
- description = description.replace("SPEC_ROOT", get_relpath(src_path))
- text += "Definition: {}".format(description)
+ description = entity_info["description"]
+ description = description.replace("SPEC_ROOT", get_relpath(src_path))
+ text += f"**Definition**: {description}"
return text
@@ -117,14 +136,16 @@ def make_glossary(schema, src_path=None):
information about the entities in the schema.
"""
all_objects = {}
+ schema = schema.to_dict()
for group, group_objects in schema["objects"].items():
group_obj_keys = list(group_objects.keys())
- # Remove private objects
+
+ # Do not include private objects in the glossary
group_obj_keys = [k for k in group_obj_keys if not k.startswith("_")]
+ # Identify multi-sense objects (multiple entries, indicated by __ in key)
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]
@@ -149,6 +170,7 @@ def make_glossary(schema, src_path=None):
new_name = f"{new_name} ({group})"
all_objects[new_name] = {}
all_objects[new_name]["key"] = f"objects.{group}.{key}"
+ all_objects[new_name]["type"] = TYPE_CONVERTER.get(group, group)
all_objects[new_name]["definition"] = group_objects[key]
text = ""
@@ -156,7 +178,8 @@ def make_glossary(schema, src_path=None):
obj = all_objects[obj_key]
obj_marker = obj["key"]
obj_def = obj["definition"]
- obj_name = obj_def["display_name"]
+
+ # Clean up the text description
obj_desc = obj_def["description"]
# A backslash before a newline means continue a string
obj_desc = obj_desc.replace("\\\n", "")
@@ -169,11 +192,31 @@ def make_glossary(schema, src_path=None):
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```"
+ text += f"**Name**: {obj_def['display_name']}\n\n"
+ text += f"**Type**: {obj['type'].title()}\n\n"
+
+ if obj["type"] == "suffix":
+ text += f"**Format**: `_{obj_def['value']}.`\n\n"
+ elif obj["type"] == "extension":
+ text += f"**Format**: `_{obj_def['value']}`\n\n"
+ elif obj["type"] == "format":
+ text += f"**Regular expression**: `{obj_def['pattern']}`\n\n"
+
+ if "enum" in obj_def.keys():
+ allowed_vals = [f"`{enum}`" for enum in obj_def["enum"]]
+ text += f"**Allowed values**: {', '.join(allowed_vals)}\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", "display_name", "name", "value", "enum", "pattern")
+ }
+
+ if temp_obj_def:
+ temp_obj_def = yaml.dump(temp_obj_def)
+ text += f"**Schema information**:\n```yaml\n{temp_obj_def}\n```"
return text
diff --git a/tools/schemacode/bidsschematools/tests/test_render.py b/tools/schemacode/bidsschematools/tests/test_render.py
index c321850c94..02d09f4fd6 100644
--- a/tools/schemacode/bidsschematools/tests/test_render.py
+++ b/tools/schemacode/bidsschematools/tests/test_render.py
@@ -11,22 +11,22 @@ def test_make_entity_definitions(schema_obj):
"""
schema_text = render.make_entity_definitions(schema_obj)
expected_formats = [
- "Format: `sub-