Skip to content

API Reference

This section provides comprehensive documentation for all HED Python tools modules and classes.

Core Modules

Models

Core data models for working with HED data:

  • HedString: Represents and validates HED annotation strings
  • HedTag: Individual HED tag manipulation
  • HedGroup: Grouped HED annotations
  • Sidecar: BIDS sidecar file handling
  • TabularInput: Spreadsheet and tabular data processing

Schema

HED schema management and validation:

  • HedSchema: Main schema class for loading and querying schemas
  • HedSchemaIO: Schema input/output operations
  • SchemaComparer: Compare different schema versions

Validator

Validation tools and error handling:

  • HedValidator: Main validation engine
  • ErrorReporter: Error collection and reporting
  • ValidationContext: Validation state management

Tools

Utility tools and scripts:

  • BidsTabularSummary: BIDS dataset analysis
  • ReorderColumns: Spreadsheet manipulation
  • TagCompareUtil: Tag comparison utilities

Errors

Error handling and exception classes:

  • HedFileError: File-related errors
  • HedExceptions: General HED exceptions
  • ErrorMessages: Error message definitions

Quick Reference

Loading and Using Schemas

load_schema

load_schema(
    hed_path, schema_namespace=None, schema=None, name=None
) -> "HedSchema"

Load a schema from the given file or URL path.

Parameters:

Name Type Description Default
hed_path str

A filepath or url to open a schema from. If loading a TSV file, this should be a single filename where: Template: basename.tsv, where files are named basename_Struct.tsv, basename_Tag.tsv, etc. Alternatively, you can point to a directory containing the .tsv files.

required
schema_namespace str or None

The name_prefix all tags in this schema will accept.

None
schema HedSchema or None

A HED schema to merge this new file into It must be a with-standard schema with the same value.

None
name str or None

User supplied identifier for this schema

None

Returns:

Name Type Description
HedSchema 'HedSchema'

The loaded schema.

:raises HedFileError: - Empty path passed - Unknown extension - Any fatal issues when loading the schema.

Source code in hed/schema/hed_schema_io.py
def load_schema(hed_path, schema_namespace=None, schema=None, name=None) -> 'HedSchema':
    """ Load a schema from the given file or URL path.

    Parameters:
        hed_path (str): A filepath or url to open a schema from.
            If loading a TSV file, this should be a single filename where:
            Template: basename.tsv, where files are named basename_Struct.tsv, basename_Tag.tsv, etc.
            Alternatively, you can point to a directory containing the .tsv files.
        schema_namespace (str or None): The name_prefix all tags in this schema will accept.
        schema (HedSchema or None): A HED schema to merge this new file into
                                   It must be a with-standard schema with the same value.
        name (str or None): User supplied identifier for this schema

    Returns:
        HedSchema: The loaded schema.

    :raises HedFileError:
        - Empty path passed
        - Unknown extension
        - Any fatal issues when loading the schema.

    """
    if not hed_path:
        raise HedFileError(HedExceptions.FILE_NOT_FOUND, "Empty file path passed to HedSchema.load_file",
                           filename=hed_path)

    is_url = hed_cache._check_if_url(hed_path)
    if is_url:
        try:
            file_as_string = schema_util.url_to_string(hed_path)
        except URLError as e:
            raise HedFileError(HedExceptions.URL_ERROR, str(e), hed_path) from e
        hed_schema = from_string(file_as_string, schema_format=os.path.splitext(hed_path.lower())[1], name=name)
    elif hed_path.lower().endswith(".xml"):
        hed_schema = SchemaLoaderXML.load(hed_path, schema=schema, name=name)
    elif hed_path.lower().endswith(".mediawiki"):
        hed_schema = SchemaLoaderWiki.load(hed_path, schema=schema, name=name)
    elif hed_path.lower().endswith(".tsv") or os.path.isdir(hed_path):
        if schema is not None:
            raise HedFileError(HedExceptions.INVALID_HED_FORMAT,
                               "Cannot pass a schema to merge into spreadsheet loading currently.", filename=name)
        hed_schema = SchemaLoaderDF.load_spreadsheet(filenames=hed_path, name=name)
    else:
        raise HedFileError(HedExceptions.INVALID_EXTENSION, "Unknown schema extension", filename=hed_path)

    if schema_namespace:
        hed_schema.set_schema_prefix(schema_namespace=schema_namespace)

    return hed_schema

Basic Validation

HedString

Bases: HedGroup

A HED string with its schema and definitions.

Source code in hed/models/hed_string.py
class HedString(HedGroup):
    """ A HED string with its schema and definitions. """

    OPENING_GROUP_CHARACTER = '('
    CLOSING_GROUP_CHARACTER = ')'

    def __init__(self, hed_string, hed_schema, def_dict=None, _contents=None):
        """ Constructor for the HedString class.

        Parameters:
            hed_string (str): A HED string consisting of tags and tag groups.
            hed_schema (HedSchema): The schema to use to identify tags.
            def_dict (DefinitionDict or None): The def dict to use to identify def/def expand tags.
            _contents ([HedGroup and/or HedTag] or None): Create a HedString from this exact list of children.
                                                          Does not make a copy.
        Notes:
            - The HedString object parses its component tags and groups into a tree-like structure.

        """

        if _contents is not None:
            contents = _contents
        else:
            try:
                contents = self.split_into_groups(hed_string, hed_schema, def_dict)
            except ValueError:
                contents = []
        super().__init__(hed_string, contents=contents, startpos=0, endpos=len(hed_string))
        self._schema = hed_schema
        self._from_strings = None
        self._def_dict = def_dict

    @classmethod
    def from_hed_strings(cls, hed_strings):
        """ Factory for creating HedStrings via combination.

        Parameters:
            hed_strings (list or None): A list of HedString objects to combine.
                                        This takes ownership of their children.

        Returns:
            new_string(HedString): The newly combined HedString.
        """
        if not hed_strings:
            raise TypeError("Passed an empty list to from_hed_strings")
        new_string = HedString.__new__(HedString)
        hed_string = ",".join([group._hed_string for group in hed_strings])
        contents = [child for sub_string in hed_strings for child in sub_string.children]
        first_schema = hed_strings[0]._schema
        first_dict = hed_strings[0]._def_dict
        new_string.__init__(hed_string=hed_string, _contents=contents, hed_schema=first_schema, def_dict=first_dict)
        new_string._from_strings = hed_strings
        return new_string

    @property
    def is_group(self):
        """ Always False since the underlying string is not a group with parentheses. """
        return False

    def _calculate_to_canonical_forms(self, hed_schema):
        """ Identify all tags using the given schema.

        Parameters:
            hed_schema (HedSchema, HedSchemaGroup): The schema to use to validate/convert tags.

        Returns:
            list: A list of issues found while converting the string. Each issue is a dictionary.

        """
        validation_issues = []
        for tag in self.get_all_tags():
            validation_issues += tag._calculate_to_canonical_forms(hed_schema)

        return validation_issues

    def __deepcopy__(self, memo):
        # check if the object has already been copied
        if id(self) in memo:
            return memo[id(self)]

        # create a new instance of HedString class, and direct copy all parameters
        new_string = self.__class__.__new__(self.__class__)
        new_string.__dict__.update(self.__dict__)

        # add the new object to the memo dictionary
        memo[id(self)] = new_string

        # Deep copy the attributes that need it(most notably, we don't copy schema/schema entry)
        new_string._original_children = copy.deepcopy(self._original_children, memo)
        new_string._from_strings = copy.deepcopy(self._from_strings, memo)
        new_string.children = copy.deepcopy(self.children, memo)

        return new_string

    def copy(self) -> 'HedString':
        """ Return a deep copy of this string.

        Returns:
            HedString: The copied group.

        """
        return_copy = copy.deepcopy(self)
        return return_copy

    def remove_definitions(self):
        """ Remove definition tags and groups from this string.

            This does not validate definitions and will blindly removing invalid ones as well.
        """
        definition_groups = self.find_top_level_tags({DefTagNames.DEFINITION_KEY}, include_groups=1)
        if definition_groups:
            self.remove(definition_groups)

    def shrink_defs(self) -> 'HedString':
        """ Replace def-expand tags with def tags.

            This does not validate them and will blindly shrink invalid ones as well.

        Returns:
            self
        """
        for def_expand_tag, def_expand_group in self.find_tags({DefTagNames.DEF_EXPAND_KEY}, recursive=True):
            expanded_parent = def_expand_group._parent
            if expanded_parent:
                def_expand_tag.short_base_tag = DefTagNames.DEF_KEY
                def_expand_tag._parent = expanded_parent
                expanded_parent.replace(def_expand_group, def_expand_tag)

        return self

    def expand_defs(self) -> "HedString":
        """ Replace def tags with def-expand tags.

            This does very minimal validation.

        Returns:
            HedString: self
        """
        def_tags = self.find_def_tags(recursive=True, include_groups=0)

        replacements = []
        for tag in def_tags:
            if tag.expandable and not tag.expanded:
                replacements.append((tag, tag.expandable))

        for tag, group in replacements:
            tag_parent = tag._parent
            tag_parent.replace(tag, group)
            tag._parent = group
            tag.short_base_tag = DefTagNames.DEF_EXPAND_KEY

        return self

    def get_as_original(self) -> str:
        """ Return the original form of this string.

        Returns:
            str: The string with all the tags in their original form.

        Notes:
            Potentially with some extraneous spaces removed on returned string.
        """
        return self.get_as_form("org_tag")

    @staticmethod
    def split_into_groups(hed_string, hed_schema, def_dict=None):
        """ Split the HED string into a parse tree.

        Parameters:
            hed_string (str): A HED string consisting of tags and tag groups to be processed.
            hed_schema (HedSchema): HED schema to use to identify tags.
            def_dict (DefinitionDict): The definitions to identify.
        Returns:
            list:  A list of HedTag and/or HedGroup.

        :raises ValueError:
            - The string is significantly malformed, such as mismatched parentheses.

        Notes:
            - The parse tree consists of tag groups, tags, and delimiters.
        """
        current_tag_group = [[]]

        input_tags = HedString.split_hed_string(hed_string)
        for is_hed_tag, (startpos, endpos) in input_tags:
            if is_hed_tag:
                new_tag = HedTag(hed_string, hed_schema, (startpos, endpos), def_dict)
                current_tag_group[-1].append(new_tag)
            else:
                string_portion = hed_string[startpos:endpos]
                delimiter_index = 0
                for i, char in enumerate(string_portion):
                    if not char.isspace():
                        delimiter_index = i
                        break

                delimiter_char = string_portion[delimiter_index]

                if delimiter_char is HedString.OPENING_GROUP_CHARACTER:
                    current_tag_group.append(HedGroup(hed_string, startpos + delimiter_index))

                if delimiter_char is HedString.CLOSING_GROUP_CHARACTER:
                    # Terminate existing group, and save it off.
                    paren_end = startpos + delimiter_index + 1

                    if len(current_tag_group) > 1:
                        new_group = current_tag_group.pop()
                        new_group._endpos = paren_end

                        current_tag_group[-1].append(new_group)
                    else:
                        raise ValueError(f"Closing parentheses in HED string {hed_string}")

        # Comma delimiter issues are ignored and assumed already validated currently.
        if len(current_tag_group) != 1:
            raise ValueError(f"Unmatched opening parentheses in HED string {hed_string}")

        return current_tag_group[0]

    def _get_org_span(self, tag_or_group):
        """ If this tag or group was in the original HED string, find its original span.

        Parameters:
            tag_or_group (HedTag or HedGroup): The HED tag to locate in this string.

        Returns:
            int or None:   Starting position of the given item in the original string.
            int or None:   Ending position of the given item in the original string.

        Notes:
            - If the HED tag or group was not in the original string, returns (None, None).

        """
        if self._from_strings:
            return self._get_org_span_from_strings(tag_or_group)

        if self.check_if_in_original(tag_or_group):
            return tag_or_group.span

        return None, None

    def _get_org_span_from_strings(self, tag_or_group):
        """ A different case of the above, to handle if this was created from HED string objects."""
        found_string = None
        string_start_index = 0
        for string in self._from_strings:
            if string.check_if_in_original(tag_or_group):
                found_string = string
                break
            # Add 1 for comma
            string_start_index += string.span[1] + 1

        if not found_string:
            return None, None

        return tag_or_group.span[0] + string_start_index, tag_or_group.span[1] + string_start_index

    @staticmethod
    def split_hed_string(hed_string) -> list[tuple[bool, tuple[int, int]]]:
        """ Split a HED string into delimiters and tags.

        Parameters:
            hed_string (str): The HED string to split.

        Returns:
            list[tuple[bool, tuple[int, int]]]:  A list of tuples where each tuple is (is_hed_tag, (start_pos, end_pos)).

        Notes:
            - The tuple format is as follows
                - is_hed_tag (bool): A (possible) HED tag if True, delimiter if not.
                - start_pos (int):   Index of start of string in hed_string.
                - end_pos (int):     Index of end of string in hed_string.

            - This function does not validate tags or delimiters in any form.

        """
        tag_delimiters = ",()"
        current_spacing = 0
        found_symbol = True
        result_positions = []
        tag_start_pos = None
        last_end_pos = 0
        for i, char in enumerate(hed_string):
            if char == " ":
                current_spacing += 1
                continue

            if char in tag_delimiters:
                if found_symbol:
                    if last_end_pos != i:
                        result_positions.append((False, (last_end_pos, i)))
                    last_end_pos = i
                elif not found_symbol:
                    found_symbol = True
                    last_end_pos = i - current_spacing
                    result_positions.append((True, (tag_start_pos, last_end_pos)))
                    current_spacing = 0
                    tag_start_pos = None
                continue

            # If we have a current delimiter, end it here.
            if found_symbol and last_end_pos is not None:
                if last_end_pos != i:
                    result_positions.append((False, (last_end_pos, i)))
                last_end_pos = None

            found_symbol = False
            current_spacing = 0
            if tag_start_pos is None:
                tag_start_pos = i

        if last_end_pos is not None and len(hed_string) != last_end_pos:
            result_positions.append((False, (last_end_pos, len(hed_string))))
        if tag_start_pos is not None:
            result_positions.append((True, (tag_start_pos, len(hed_string) - current_spacing)))
            if current_spacing:
                result_positions.append((False, (len(hed_string) - current_spacing, len(hed_string))))

        return result_positions

    def validate(self, allow_placeholders=True, error_handler=None) -> list[dict]:
        """ Validate the string using the schema.

        Parameters:
            allow_placeholders (bool): Allow placeholders in the string.
            error_handler (ErrorHandler or None): The error handler to use, creates a default one if none passed.
        Returns:
            list[dict]: A list of issues for HED string.
        """
        from hed.validator import HedValidator

        validator = HedValidator(self._schema, def_dicts=self._def_dict)
        return validator.validate(self, allow_placeholders=allow_placeholders, error_handler=error_handler)

    def find_top_level_tags(self, anchor_tags, include_groups=2):
        """ Find top level groups with an anchor tag.

            A max of 1 tag located per top level group.

        Parameters:
            anchor_tags (container):  A list/set/etc. of short_base_tags to find groups by.
            include_groups (0, 1 or 2):  Parameter indicating what return values to include.
                If 0: return only tags.
                If 1: return only groups.
                If 2 or any other value: return both.
        Returns:
            list: The returned result depends on include_groups.
        """
        anchor_tags = {tag.casefold() for tag in anchor_tags}
        top_level_tags = []
        for group in self.groups():
            for tag in group.tags():
                if tag.short_base_tag.casefold() in anchor_tags:
                    top_level_tags.append((tag, group))
                    # Only capture a max of 1 per group.  These are implicitly unique.
                    break

        if include_groups == 0 or include_groups == 1:
            return [tag[include_groups] for tag in top_level_tags]
        return top_level_tags

    def remove_refs(self):
        """ Remove any refs(tags contained entirely inside curly braces) from the string.

            This does NOT validate the contents of the curly braces.  This is only relevant when directly
            editing sidecar strings.  Tools will naturally ignore these.
        """
        ref_tags = [tag for tag in self.get_all_tags() if tag.is_column_ref()]
        if ref_tags:
            self.remove(ref_tags)

__init__

__init__(
    hed_string, hed_schema, def_dict=None, _contents=None
)

Constructor for the HedString class.

Parameters:

Name Type Description Default
hed_string str

A HED string consisting of tags and tag groups.

required
hed_schema HedSchema

The schema to use to identify tags.

required
def_dict DefinitionDict or None

The def dict to use to identify def/def expand tags.

None
_contents [HedGroup and/or HedTag] or None

Create a HedString from this exact list of children. Does not make a copy.

None

Notes: - The HedString object parses its component tags and groups into a tree-like structure.

Source code in hed/models/hed_string.py
def __init__(self, hed_string, hed_schema, def_dict=None, _contents=None):
    """ Constructor for the HedString class.

    Parameters:
        hed_string (str): A HED string consisting of tags and tag groups.
        hed_schema (HedSchema): The schema to use to identify tags.
        def_dict (DefinitionDict or None): The def dict to use to identify def/def expand tags.
        _contents ([HedGroup and/or HedTag] or None): Create a HedString from this exact list of children.
                                                      Does not make a copy.
    Notes:
        - The HedString object parses its component tags and groups into a tree-like structure.

    """

    if _contents is not None:
        contents = _contents
    else:
        try:
            contents = self.split_into_groups(hed_string, hed_schema, def_dict)
        except ValueError:
            contents = []
    super().__init__(hed_string, contents=contents, startpos=0, endpos=len(hed_string))
    self._schema = hed_schema
    self._from_strings = None
    self._def_dict = def_dict

validate

validate(
    allow_placeholders=True, error_handler=None
) -> list[dict]

Validate the string using the schema.

Parameters:

Name Type Description Default
allow_placeholders bool

Allow placeholders in the string.

True
error_handler ErrorHandler or None

The error handler to use, creates a default one if none passed.

None

Returns: list[dict]: A list of issues for HED string.

Source code in hed/models/hed_string.py
def validate(self, allow_placeholders=True, error_handler=None) -> list[dict]:
    """ Validate the string using the schema.

    Parameters:
        allow_placeholders (bool): Allow placeholders in the string.
        error_handler (ErrorHandler or None): The error handler to use, creates a default one if none passed.
    Returns:
        list[dict]: A list of issues for HED string.
    """
    from hed.validator import HedValidator

    validator = HedValidator(self._schema, def_dicts=self._def_dict)
    return validator.validate(self, allow_placeholders=allow_placeholders, error_handler=error_handler)

remove_definitions

remove_definitions()

Remove definition tags and groups from this string.

This does not validate definitions and will blindly removing invalid ones as well.

Source code in hed/models/hed_string.py
def remove_definitions(self):
    """ Remove definition tags and groups from this string.

        This does not validate definitions and will blindly removing invalid ones as well.
    """
    definition_groups = self.find_top_level_tags({DefTagNames.DEFINITION_KEY}, include_groups=1)
    if definition_groups:
        self.remove(definition_groups)

Working with BIDS Data

Sidecar

Contents of a JSON file or JSON files.

Source code in hed/models/sidecar.py
class Sidecar:
    """ Contents of a JSON file or JSON files.

    """

    def __init__(self, files, name=None):
        """ Construct a Sidecar object representing a JSON file.

        Parameters:
            files (str or FileLike or list): A string or file-like object representing a JSON file, or a list of such.
            name (str or None): Optional name identifying this sidecar, generally a filename.
        """
        self.name = name
        self.loaded_dict = self.load_sidecar_files(files)
        self._def_dict = None
        self._extract_definition_issues = []

    def __iter__(self):
        """ An iterator to go over the individual column metadata.

        Returns:
            iterator: An iterator over the column metadata values.

        """
        return iter(self.column_data.values())

    def __getitem__(self, column_name):
        if column_name not in self.loaded_dict:
            return None
        return ColumnMetadata(name=column_name)

    @property
    def all_hed_columns(self):
        """ Return all columns that are HED compatible.

            Returns:
                column_refs(list): A list of all valid HED columns by name.
        """
        possible_column_references = [column.column_name for column in self if column.column_type != ColumnType.Ignore]

        return possible_column_references

    @property
    def def_dict(self) -> 'DefinitionDict':
        """ Definitions from this sidecar.

            Generally you should instead call get_def_dict to get the relevant definitions.

        Returns:
            DefinitionDict: The definitions for this sidecar.
        """
        return self._def_dict

    @property
    def column_data(self):
        """ Generate the ColumnMetadata for this sidecar.

        Returns:
            dict({str:ColumnMetadata}): The column metadata defined by this sidecar.
        """
        return {col_name: ColumnMetadata(name=col_name, source=self.loaded_dict) for col_name in self.loaded_dict}

    def get_def_dict(self, hed_schema, extra_def_dicts=None) -> 'DefinitionDict':
        """ Return the definition dict for this sidecar.

        Parameters:
            hed_schema (HedSchema): Identifies tags to find definitions.
            extra_def_dicts (list, DefinitionDict, or None): Extra dicts to add to the list.

        Returns:
            DefinitionDict:  A single definition dict representing all the data(and extra def dicts).
        """
        if self._def_dict is None and hed_schema:
            self._def_dict = self.extract_definitions(hed_schema)
        def_dicts = []
        if self.def_dict:
            def_dicts.append(self.def_dict)
        if extra_def_dicts:
            if not isinstance(extra_def_dicts, list):
                extra_def_dicts = [extra_def_dicts]
            def_dicts += extra_def_dicts
        return DefinitionDict(def_dicts)

    def save_as_json(self, save_filename):
        """ Save column metadata to a JSON file.

        Parameters:
            save_filename (str): Path to save file.

        """
        with open(save_filename, "w") as fp:
            json.dump(self.loaded_dict, fp, indent=4)

    def get_as_json_string(self) -> str:
        """ Return this sidecar's column metadata as a string.

        Returns:
            str: The json string representing this sidecar.

        """
        return json.dumps(self.loaded_dict, indent=4)

    def load_sidecar_file(self, file):
        """ Load column metadata from a given json file.

        Parameters:
            file (str or FileLike): If a string, this is a filename. Otherwise, it will be parsed as a file-like.

        :raises HedFileError:
            - If the file was not found or could not be parsed into JSON.
        """
        if not file:
            return {}
        elif isinstance(file, str):
            if not self.name:
                self.name = file
            try:
                with open(file, "r") as fp:
                    return self._load_json_file(fp)
            except OSError as e:
                raise HedFileError(HedExceptions.FILE_NOT_FOUND, e.strerror, file) from e
        else:
            return self._load_json_file(file)

    def load_sidecar_files(self, files):
        """ Load json from a given file or list.

        Parameters:
            files (str or FileLike or list): A string or file-like object representing a JSON file, or a list of such.

        :raises HedFileError:
            - If the file was not found or could not be parsed into JSON.

        """
        if not files:
            return {}
        if not isinstance(files, list):
            files = [files]

        merged_dict = {}
        for file in files:
            loaded_json = self.load_sidecar_file(file)
            merged_dict.update(loaded_json)
        return merged_dict

    def validate(self, hed_schema, extra_def_dicts=None, name=None, error_handler=None) -> list[dict]:
        """Create a SidecarValidator and validate this sidecar with the schema.

        Parameters:
            hed_schema (HedSchema): Input data to be validated.
            extra_def_dicts (list or DefinitionDict): Extra def dicts in addition to sidecar.
            name (str): The name to report this sidecar as.
            error_handler (ErrorHandler): Error context to use.  Creates a new one if None.

        Returns:
            list[dict]: A list of issues associated with each level in the HED string.
        """
        from hed.validator.sidecar_validator import SidecarValidator

        if error_handler is None:
            error_handler = ErrorHandler()

        validator = SidecarValidator(hed_schema)
        issues = validator.validate(self, extra_def_dicts, name, error_handler=error_handler)
        return issues

    def _load_json_file(self, fp):
        """ Load the raw json of a given file.

        Parameters:
            fp (File-like): The JSON source stream.

        :raises HedFileError:
            - If the file cannot be parsed.
        """
        try:
            return json.load(fp)
        except (json.decoder.JSONDecodeError, AttributeError) as e:
            raise HedFileError(HedExceptions.CANNOT_PARSE_JSON, str(e), self.name) from e

    def extract_definitions(self, hed_schema, error_handler=None) -> 'DefinitionDict':
        """ Gather and validate definitions in metadata.

        Parameters:
            hed_schema (HedSchema): The schema to used to identify tags.
            error_handler (ErrorHandler or None): The error handler to use for context, uses a default one if None.

        Returns:
            DefinitionDict: Contains all the definitions located in the sidecar.

        """
        if error_handler is None:
            error_handler = ErrorHandler()
        def_dict = DefinitionDict()

        self._extract_definition_issues = []
        if hed_schema:
            for column_data in self:
                error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, column_data.column_name)
                hed_strings = column_data.get_hed_strings()
                for key_name, hed_string in hed_strings.items():
                    hed_string_obj = HedString(hed_string, hed_schema)
                    if len(hed_strings) > 1:
                        error_handler.push_error_context(ErrorContext.SIDECAR_KEY_NAME, key_name)
                    error_handler.push_error_context(ErrorContext.HED_STRING, hed_string_obj)
                    self._extract_definition_issues += def_dict.check_for_definitions(hed_string_obj, error_handler)
                    error_handler.pop_error_context()
                    if len(hed_strings) > 1:
                        error_handler.pop_error_context()

                error_handler.pop_error_context()

        return def_dict

    def get_column_refs(self):
        """ Returns a list of column refs found in this sidecar.

            This does not validate

        Returns:
            column_refs(list): A list of unique column refs found.
        """
        found_vals = set()
        for column_data in self:
            if column_data.column_type == ColumnType.Ignore:
                continue
            hed_strings = column_data.get_hed_strings()
            matches = hed_strings.str.findall(r"\{([a-z_\-0-9]+)\}", re.IGNORECASE)
            u_vals = [match for sublist in matches for match in sublist]

            found_vals.update(u_vals)

        return list(found_vals)

__init__

__init__(files, name=None)

Construct a Sidecar object representing a JSON file.

Parameters:

Name Type Description Default
files str or FileLike or list

A string or file-like object representing a JSON file, or a list of such.

required
name str or None

Optional name identifying this sidecar, generally a filename.

None
Source code in hed/models/sidecar.py
def __init__(self, files, name=None):
    """ Construct a Sidecar object representing a JSON file.

    Parameters:
        files (str or FileLike or list): A string or file-like object representing a JSON file, or a list of such.
        name (str or None): Optional name identifying this sidecar, generally a filename.
    """
    self.name = name
    self.loaded_dict = self.load_sidecar_files(files)
    self._def_dict = None
    self._extract_definition_issues = []

validate

validate(
    hed_schema,
    extra_def_dicts=None,
    name=None,
    error_handler=None,
) -> list[dict]

Create a SidecarValidator and validate this sidecar with the schema.

Parameters:

Name Type Description Default
hed_schema HedSchema

Input data to be validated.

required
extra_def_dicts list or DefinitionDict

Extra def dicts in addition to sidecar.

None
name str

The name to report this sidecar as.

None
error_handler ErrorHandler

Error context to use. Creates a new one if None.

None

Returns:

Type Description
list[dict]

list[dict]: A list of issues associated with each level in the HED string.

Source code in hed/models/sidecar.py
def validate(self, hed_schema, extra_def_dicts=None, name=None, error_handler=None) -> list[dict]:
    """Create a SidecarValidator and validate this sidecar with the schema.

    Parameters:
        hed_schema (HedSchema): Input data to be validated.
        extra_def_dicts (list or DefinitionDict): Extra def dicts in addition to sidecar.
        name (str): The name to report this sidecar as.
        error_handler (ErrorHandler): Error context to use.  Creates a new one if None.

    Returns:
        list[dict]: A list of issues associated with each level in the HED string.
    """
    from hed.validator.sidecar_validator import SidecarValidator

    if error_handler is None:
        error_handler = ErrorHandler()

    validator = SidecarValidator(hed_schema)
    issues = validator.validate(self, extra_def_dicts, name, error_handler=error_handler)
    return issues

extract_definitions

extract_definitions(
    hed_schema, error_handler=None
) -> DefinitionDict

Gather and validate definitions in metadata.

Parameters:

Name Type Description Default
hed_schema HedSchema

The schema to used to identify tags.

required
error_handler ErrorHandler or None

The error handler to use for context, uses a default one if None.

None

Returns:

Name Type Description
DefinitionDict DefinitionDict

Contains all the definitions located in the sidecar.

Source code in hed/models/sidecar.py
def extract_definitions(self, hed_schema, error_handler=None) -> 'DefinitionDict':
    """ Gather and validate definitions in metadata.

    Parameters:
        hed_schema (HedSchema): The schema to used to identify tags.
        error_handler (ErrorHandler or None): The error handler to use for context, uses a default one if None.

    Returns:
        DefinitionDict: Contains all the definitions located in the sidecar.

    """
    if error_handler is None:
        error_handler = ErrorHandler()
    def_dict = DefinitionDict()

    self._extract_definition_issues = []
    if hed_schema:
        for column_data in self:
            error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, column_data.column_name)
            hed_strings = column_data.get_hed_strings()
            for key_name, hed_string in hed_strings.items():
                hed_string_obj = HedString(hed_string, hed_schema)
                if len(hed_strings) > 1:
                    error_handler.push_error_context(ErrorContext.SIDECAR_KEY_NAME, key_name)
                error_handler.push_error_context(ErrorContext.HED_STRING, hed_string_obj)
                self._extract_definition_issues += def_dict.check_for_definitions(hed_string_obj, error_handler)
                error_handler.pop_error_context()
                if len(hed_strings) > 1:
                    error_handler.pop_error_context()

            error_handler.pop_error_context()

    return def_dict