Repository: hed-standard/hed-python (language: python)

Issue:
display_name -> name.  Update base input so you can swap out the colu…
…mn mapper later.  Redo how defs are gathered to match new system


Discussion / hints:

Fix patch:
diff --git a/hedtools/examples/data/hed_tag_def_example.tsv b/hedtools/examples/data/hed_tag_def_example.tsv
new file mode 100644
index 000000000..18918567e
--- /dev/null
+++ b/hedtools/examples/data/hed_tag_def_example.tsv
@@ -0,0 +1,5 @@
+Event code	Short label	Description in text	HED tags
+251	PerturbLeft	Vehicle undergoes a perturbation to left.	Event/Sensory event, (Participant/Cognitive state/Awake ~ Participant/Trait/Age/15 ~ Item/Sound/Siren, Item/Object/Manmade/Vehicle, Attribute/Sensory/Visual/Color/RGB color/RGB Red/100), (Definition/ExampleFileDef, (Item/ExampleFileTag))
+252	PerturbRight	Vehicle undergoes a perturbation to right.	Sensory event, (Awake ~ Age/15 ~ Siren, Vehicle, RGB Red/100)
+253	ResponseOnset	Subject starts to respond to perturbation by steering vehicle back to center of the lane.	Event/Sensory event, (Participant/Cognitive state/Awake ~ Participant/Trait/Age/15 ~ Item/Sound/Siren, Item/Object/Manmade/Vehicle, Attribute/Sensory/Visual/Color/RGB color/RGB Red/100), def/ExampleFileDef
+254	ResponseOffset	Subject completes response to perturbation having steered the vehicle back to the center of the lane.	Event/Sensory event, (Participant/Cognitive state/Awake ~ Participant/Trait/Age/15 ~ Item/Sound/Siren, Item/Object/Manmade/Vehicle, Attribute/Sensory/Visual/Color/RGB color/RGB Red/100), def/ExampleDef
diff --git a/hedtools/examples/data/hed_tag_def_example.xlsx b/hedtools/examples/data/hed_tag_def_example.xlsx
deleted file mode 100644
index 9172de7bf..000000000
Binary files a/hedtools/examples/data/hed_tag_def_example.xlsx and /dev/null differ
diff --git a/hedtools/examples/run_hed_def_mapper_example.py b/hedtools/examples/run_hed_def_mapper_example.py
index fa0ed6e8d..4b933428c 100644
--- a/hedtools/examples/run_hed_def_mapper_example.py
+++ b/hedtools/examples/run_hed_def_mapper_example.py
@@ -20,21 +20,16 @@
 if __name__ == '__main__':
     local_hed_file = 'data/HED8.0.0-alpha.1.xml'
     example_data_path = 'data'  # path to example data
-    hed3_tags_single_sheet = os.path.join(example_data_path, 'hed_tag_def_example.xlsx')
-
+    hed3_tags_single_sheet = os.path.join(example_data_path, 'hed_tag_def_example.tsv')
     hed_schema = load_schema(local_hed_file)
     prefixed_needed_tag_columns = {2: 'Event/Label/', 3: 'Event/Description/'}
     json_file = "data/both_types_events_def_example.json"
     column_group = ColumnDefGroup(json_file)
-    def_dict = column_group.extract_defs()
-    def_issues = def_dict.get_def_issues(hed_schema=hed_schema)
+    def_issues = column_group.validate_entries(hed_schema=hed_schema)
     if def_issues:
         print(hed.get_printable_issue_string(def_issues,
                                              title="There should be no errors in the definitions from the sidecars:"))
-    input_file = EventsInput(hed3_tags_single_sheet, json_def_files=column_group,
-                             tag_columns=[4], column_prefix_dictionary=prefixed_needed_tag_columns,
-                             worksheet_name='LKT Events',
-                             def_dicts=def_dict)
+    input_file = EventsInput(hed3_tags_single_sheet, json_def_files=column_group)
 
     validation_issues = input_file.validate_file_sidecars(hed_schema=hed_schema)
     if validation_issues:
diff --git a/hedtools/hed/errors/exceptions.py b/hedtools/hed/errors/exceptions.py
index bff4b8643..e4a09748c 100644
--- a/hedtools/hed/errors/exceptions.py
+++ b/hedtools/hed/errors/exceptions.py
@@ -25,7 +25,7 @@ def __init__(self, error_type, message, filename):
         self.filename = filename
 
     def format_error_message(self, include_tabbing=True, return_string_only=False,
-                             display_filename=None):
+                             name=None):
         """This takes a HedFileError exception and translates it to human readable
 
         Parameters
@@ -34,7 +34,7 @@ def format_error_message(self, include_tabbing=True, return_string_only=False,
             Prefixes string with a tab if True
         return_string_only : bool
             If True, returns a string rather than an "error object"
-        display_filename : str or None
+        name : str or None
             Overrides the filename from the error if present.
             This is useful on the web code and similar that deals with temporary filenames.
         Returns
@@ -47,8 +47,8 @@ def format_error_message(self, include_tabbing=True, return_string_only=False,
             error_prefix = "\t" + error_prefix
 
         error_type, message, filename = self.error_type, self.message, self.filename
-        if display_filename:
-            filename = display_filename
+        if name:
+            filename = name
         error_types = {
             HedExceptions.FILE_NOT_FOUND: f"{error_prefix}{message}.  '{filename}'",
             HedExceptions.INVALID_EXTENSION: f"{error_prefix}Invalid extension.  '{filename}'",
diff --git a/hedtools/hed/models/base_input.py b/hedtools/hed/models/base_input.py
index 78883b1d3..1c345cb27 100644
--- a/hedtools/hed/models/base_input.py
+++ b/hedtools/hed/models/base_input.py
@@ -2,9 +2,7 @@
 import openpyxl
 import pandas
 import copy
-import io
 
-from itertools import islice
 from hed.models.def_dict import DefDict
 from hed.models.column_mapper import ColumnMapper
 from hed.errors.exceptions import HedFileError, HedExceptions
@@ -23,8 +21,7 @@ class BaseInput:
     TAB_DELIMITER = '\t'
     COMMA_DELIMITER = ','
 
-    def __init__(self, filename, file_type=None, worksheet_name=None, has_column_names=True,
-                 mapper=None, display_name=None):
+    def __init__(self, filename, file_type=None, worksheet_name=None, has_column_names=True, mapper=None, name=None):
         """Constructor for the BaseInput class.
 
          Parameters
@@ -33,7 +30,7 @@ def __init__(self, filename, file_type=None, worksheet_name=None, has_column_nam
              An xlsx/tsv file to open.
          file_type: str
             ".xlsx" for excel, ".tsv" or ".txt" for tsv. data.  Derived from filename if filename is a str.
-         worksheet_name: str
+         worksheet_name: str or None
              The name of the Excel workbook worksheet that contains the HED tags.  Not applicable to tsv files.
          has_column_names: bool
              True if file has column names. The validation will skip over the first line of the file. False, if
@@ -41,14 +38,14 @@ def __init__(self, filename, file_type=None, worksheet_name=None, has_column_nam
          mapper: ColumnMapper
              Pass in a built column mapper(see HedInput or EventsInput for examples), or None to just
              retrieve all columns as hed tags.
-         display_name: str or None
+         name: str or None
             Optional field for how this file will report errors.
          """
         if mapper is None:
             mapper = ColumnMapper()
         self._mapper = mapper
         self._has_column_names = has_column_names
-        self._display_name = display_name
+        self._name = name
         # This is the loaded workbook if we loaded originally from an excel file.
         self._loaded_workbook = None
         self._worksheet_name = worksheet_name
@@ -74,23 +71,35 @@ def __init__(self, filename, file_type=None, worksheet_name=None, has_column_nam
         else:
             raise HedFileError(HedExceptions.INVALID_EXTENSION, "", filename)
 
-        # Finalize mapping information if we have columns
+        self.reset_mapper(mapper)
+
+    def reset_mapper(self, new_mapper):
+        """
+            Set the column mapper to the passed in one, allowing you to view the file differently.
+
+        Parameters
+        ----------
+        new_mapper : ColumnMapper
+        """
+        self._mapper = new_mapper
+        if not self._mapper:
+            self._mapper = ColumnMapper()
+
         if self._dataframe is not None and self._has_column_names:
             columns = self._dataframe.columns
             self._mapper.set_column_map(columns)
 
-        # Now that the file is fully initialized, gather the definitions from it.
         self.file_def_dict = self.extract_definitions()
-        # finally add the new file dict to the mapper.
-        mapper.update_definition_mapper_with_file(self.file_def_dict)
+
+        self._mapper.update_definition_mapper_with_file(self.file_def_dict)
 
     @property
     def dataframe(self):
         return self._dataframe
 
     @property
-    def display_name(self):
-        return self._display_name
+    def name(self):
+        return self._name
 
     @property
     def has_column_names(self):
@@ -280,7 +289,7 @@ def iter_raw(self):
         column_to_hed_tags_dictionary: dict
             A dict with keys column_number, value the cell at that position.
         """
-        default_mapper = ColumnMapper()
+        default_mapper = ColumnMapper(enable_def_mapping=False)
         return self.iter_dataframe(default_mapper)
 
     def iter_dataframe(self, mapper=None, return_row_dict=False, expand_defs=True):
@@ -436,4 +445,4 @@ def _get_dataframe_from_worksheet(worksheet, has_headers):
             data = list(data)
             return pandas.DataFrame(data, columns=cols)
         else:
-            return pandas.DataFrame(worksheet.values)
\ No newline at end of file
+            return pandas.DataFrame(worksheet.values)
diff --git a/hedtools/hed/models/column_def_group.py b/hedtools/hed/models/column_def_group.py
index 1d8ce59c1..35d212d1d 100644
--- a/hedtools/hed/models/column_def_group.py
+++ b/hedtools/hed/models/column_def_group.py
@@ -3,29 +3,26 @@
 from hed.errors.error_types import ErrorContext
 from hed.errors import error_reporter
 from hed.errors.exceptions import HedFileError, HedExceptions
-from hed.models.def_dict import DefDict
 from hed.models.hed_string import HedString
 
 
 class ColumnDefGroup:
     """This stores column definitions for parsing hed spreadsheets, generally loaded from a single json file."""
-    def __init__(self, json_filename=None, json_string=None, display_name=None):
+    def __init__(self, file, name=None):
         """
 
         Parameters
         ----------
-        json_filename: str or None, optional
-            The actual filename to be loaded.
-        json_string: str or None, optional
-            Alternate to passing a filename, you can pass in a json string to be parsed
+        file: str or FileLike
+            If a string, this is a filename.
+            Otherwise it will be parsed as a file-like.
+        name: str or None
+            Optional name to identify this group.  Generally a filename.
         """
-        self._json_filename = None
         self._column_settings = {}
-        self.display_name = display_name
-        if json_string:
-            self.add_json_string(json_string)
-        if json_filename:
-            self.add_json_file_defs(json_filename)
+        self.name = name
+        if file:
+            self.add_json_file_defs(file)
 
     def __iter__(self):
         """
@@ -36,30 +33,6 @@ def __iter__(self):
         """
         return iter(self._column_settings.values())
 
-    def extract_defs(self, error_handler=None):
-        """
-            Finds all definitions in the hed strings of this column def group.
-
-        Parameters
-        ----------
-        error_handler : ErrorHandler or None
-            Used to report errors.  Uses a default one if none passed in.
-        Returns
-        -------
-        def_dicts: DefDict
-            A DefDict containing all the definitions found.
-        """
-        if error_handler is None:
-            error_handler = error_reporter.ErrorHandler()
-        new_def_dict = DefDict()
-        for hed_string in self.hed_string_iter():
-            hed_string_obj = HedString(hed_string)
-            error_handler.push_error_context(ErrorContext.HED_STRING, hed_string_obj, False)
-            new_def_dict.check_for_definitions(hed_string_obj, error_handler=error_handler)
-            error_handler.pop_error_context()
-
-        return new_def_dict
-
     def save_as_json(self, save_filename):
         """
             Saves out a column definition group to a json file
@@ -87,44 +60,49 @@ def get_as_json_string(self):
             output_dict[entry.column_name] = entry.hed_dict
         return json.dumps(output_dict, indent=4)
 
-    def add_json_string(self, json_string):
+    def add_json_file_defs(self, file):
         """
-            Loads column definitions from a given json string
+            Loads column definitions from a given json file.
+            You can load multiple files into one ColumnDefGroup, but it is discouraged.
 
         Parameters
         ----------
-        json_string : str
-            path to file to load
-        """
-        try:
-            loaded_defs = json.loads(json_string)
-            for col_def, col_dict in loaded_defs.items():
-                self._add_single_col_type(col_def, col_dict)
-        except json.decoder.JSONDecodeError as e:
-            raise HedFileError(HedExceptions.CANNOT_PARSE_JSON, str(e), json_string[:100])
+        file: str or FileLike
+            If a string, this is a filename.
+            Otherwise it will be parsed as a file-like.
+        """
+        if isinstance(file, str):
+            try:
+                with open(file, "r") as fp:
+                    if not self.name:
+                        self.name = file
+                    self._add_json_file_defs(fp)
+            except FileNotFoundError as e:
+                raise HedFileError(HedExceptions.FILE_NOT_FOUND, e.strerror, file)
+            except TypeError as e:
+                raise HedFileError(HedExceptions.FILE_NOT_FOUND, str(e), file)
+        else:
+            self._add_json_file_defs(file)
 
-    def add_json_file_defs(self, json_filename):
+    def _add_json_file_defs(self, fp):
         """
-            Loads column definitions from a given json file.
-            You can load multiple files into one ColumnDefGroup, but it is discouraged.
+            Takes a file like and parses it as json.
 
         Parameters
         ----------
-        json_filename : str
-            path to file to load
+        fp : file like
+            The source for the json.
+
+        Returns
+        -------
+
         """
         try:
-            with open(json_filename, "r") as fp:
-                loaded_defs = json.load(fp)
-                self._json_filename = json_filename
-                for col_def, col_dict in loaded_defs.items():
-                    self._add_single_col_type(col_def, col_dict)
+            loaded_defs = json.load(fp)
+            for col_def, col_dict in loaded_defs.items():
+                self._add_single_col_type(col_def, col_dict)
         except json.decoder.JSONDecodeError as e:
-            raise HedFileError(HedExceptions.CANNOT_PARSE_JSON, str(e), json_filename)
-        except FileNotFoundError as e:
-            raise HedFileError(HedExceptions.FILE_NOT_FOUND, e.strerror, json_filename)
-        except TypeError as e:
-            raise HedFileError(HedExceptions.FILE_NOT_FOUND, str(e), json_filename)
+            raise HedFileError(HedExceptions.CANNOT_PARSE_JSON, str(e), self.name)
 
     @staticmethod
     def load_multiple_json_files(json_file_input_list):
@@ -153,25 +131,6 @@ def load_multiple_json_files(json_file_input_list):
             loaded_files.append(json_file)
         return loaded_files
 
-    @staticmethod
-    def extract_defs_from_list(column_group_defs):
-        """
-            Take a list of column def groups, and return a list of def dicts extracted from them.
-            This is primarily for quick development tests.  It is not suggested you use this, as
-            validation issues will not be returned.
-
-        Parameters
-        ----------
-        column_group_defs : [ColumnDefGroup]
-        Returns
-        -------
-        def_dicts: [DefDict]
-        """
-        if column_group_defs:
-            return [column_group_def.extract_defs()[0] for column_group_def in column_group_defs]
-        else:
-            return []
-
     def hed_string_iter(self, include_position=False):
         """
         Return iterator to loop over all hed strings in all column definitions
@@ -212,36 +171,6 @@ def set_hed_string(self, new_hed_string, position):
         entry = self._column_settings[column_name]
         entry.set_hed_string(new_hed_string, position)
 
-    # Figure out later if we want support like this...
-    # def add_value_column(self, column_name, hed):
-    #     new_entry = {
-    #         "HED": hed
-    #     }
-    #     new_entry = ColumnDef(new_entry, column_name, ColumnType.Value)
-    #     self._column_settings[column_name] = column_entry
-    #
-    # def add_categorical_column(self, column_name, hed_category_dict):
-    #     new_entry = {
-    #         "HED": hed_category_dict
-    #     }
-    #     new_entry = ColumnDef(new_entry, column_name, ColumnType.Categorical)
-    #     self._column_settings[column_name] = column_entry
-    #
-    # def add_attribute_columns(self, column_names):
-    #     self._add_multiple_columns(column_names, ColumnType.Attribute)
-
-    # def add_hedtag_columns(self, column_names):
-    #     self._add_multiple_columns(column_names, ColumnType.HEDTags)
-    #
-    # def add_ignore_columns(self, column_names):
-    #     self._add_multiple_columns(column_names, ColumnType.Ignore)
-
-    # def _add_multiple_columns(self, column_names, column_type):
-    #     if isinstance(column_names, str):
-    #         column_names = [column_names]
-    #     for column_name in column_names:
-    #         self._add_single_col_type(column_name, None, column_type)
-
     def _add_single_col_type(self, column_name, dict_for_entry, column_type=None):
         """
         Creates a single column definition with the given parameters.
@@ -258,14 +187,14 @@ def _add_single_col_type(self, column_name, dict_for_entry, column_type=None):
         column_entry = ColumnDef(column_type, column_name, dict_for_entry)
         self._column_settings[column_name] = column_entry
 
-    def validate_entries(self, hed_schema=None, display_filename=None, error_handler=None):
+    def validate_entries(self, hed_schema=None, name=None, error_handler=None):
         """Validate the column entries, and also hed strings in the column entries if a hed_schema is passed.
 
         Parameters
         ----------
         hed_schema : HedSchema, optional
             The dictionary to use to validate individual hed strings.
-        display_filename: str
+        name: str
             If present, will use this as the filename for context, rather than using the actual filename
             Useful for temp filenames.
         error_handler : ErrorHandler or None
@@ -278,18 +207,15 @@ def validate_entries(self, hed_schema=None, display_filename=None, error_handler
         """
         if error_handler is None:
             error_handler = error_reporter.ErrorHandler()
-        if not display_filename:
-            display_filename = self._json_filename
-        if display_filename:
-            error_handler.push_error_context(ErrorContext.FILE_NAME, display_filename, False)
+        if not name:
+            name = self.name
+        if name:
+            error_handler.push_error_context(ErrorContext.FILE_NAME, name, False)
 
         all_validation_issues = []
         for column_entry in self:
-            error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, column_entry.column_name)
             all_validation_issues += column_entry.validate_column_entry(hed_schema, error_handler=error_handler)
-            error_handler.pop_error_context()
 
-        if display_filename:
+        if name:
             error_handler.pop_error_context()
         return all_validation_issues
-
diff --git a/hedtools/hed/models/column_definition.py b/hedtools/hed/models/column_definition.py
index 78db8da25..f45b976a0 100644
--- a/hedtools/hed/models/column_definition.py
+++ b/hedtools/hed/models/column_definition.py
@@ -1,5 +1,6 @@
 from enum import Enum
 from hed.models.hed_string import HedString
+from hed.models.def_dict import DefDict
 from hed.errors.error_types import SidecarErrors, ErrorContext, ValidationErrors
 from hed.errors import error_reporter
 
@@ -25,7 +26,8 @@ class ColumnType(Enum):
 
 class ColumnDef:
     """A single column in either the ColumnMapper or ColumnDefGroup"""
-    def __init__(self, column_type=None, name=None, hed_dict=None, column_prefix=None):
+    def __init__(self, column_type=None, name=None, hed_dict=None, column_prefix=None,
+                 error_handler=None):
         """
         A single column entry in the column mapper.  Each column you want to retrieve data from will have one.
 
@@ -41,6 +43,8 @@ def __init__(self, column_type=None, name=None, hed_dict=None, column_prefix=Non
             At a minimum, this needs "HED" in the dict for several ColumnType
         column_prefix : str
             If present, prepend the given prefix to all hed tags in the columns.  Only works on ColumnType HedTags
+        error_handler : ErrorHandler or None
+            Used to report errors.  Uses a default one if none passed in.
         """
         if column_type is None or column_type == ColumnType.Unknown:
             column_type = ColumnDef._detect_column_def_type(hed_dict)
@@ -52,6 +56,11 @@ def __init__(self, column_type=None, name=None, hed_dict=None, column_prefix=Non
         self.column_name = name
         self.column_prefix = column_prefix
         self._hed_dict = hed_dict
+        self._def_dict = self.extract_defs(error_handler=error_handler)
+
+    @property
+    def def_dict(self):
+        return self._def_dict
 
     @property
     def hed_dict(self):
@@ -65,7 +74,7 @@ def hed_dict(self):
         """
         return self._hed_dict
 
-    def hed_string_iter(self, include_position=False):
+    def hed_string_iter(self, include_position=False, also_return_bad_types=False):
         """
         Return iterator to loop over all hed strings in this column definition
 
@@ -73,7 +82,8 @@ def hed_string_iter(self, include_position=False):
         ----------
         include_position : bool
             If true, this returns a tuple including a position element you can pass back in to set_hed_string
-
+        also_return_bad_types: bool
+            If true, will return invalid entries, such as lists, rather than silently skipping them.
         Yields
         -------
         hed_string : str
@@ -86,6 +96,8 @@ def hed_string_iter(self, include_position=False):
         hed_strings = self._hed_dict.get("HED", None)
         if isinstance(hed_strings, dict):
             for key, value in hed_strings.items():
+                if not also_return_bad_types and not isinstance(value, str):
+                    continue
                 if include_position:
                     yield value, key
                 else:
@@ -278,7 +290,16 @@ def _detect_column_def_type(dict_for_entry):
 
         return ColumnType.Value
 
-    def validate_column_entry(self, hed_schema=None, error_handler=None):
+    def get_def_issues(self):
+        """
+        Returns the issues found extracting definitions from this column.
+        Returns
+        -------
+
+        """
+        return self._def_dict.get_def_issues()
+
+    def validate_column_entry(self, hed_schema=None, def_mapper=None, error_handler=None):
         """
         Finds all validation issues in this column.
 
@@ -286,6 +307,8 @@ def validate_column_entry(self, hed_schema=None, error_handler=None):
         ----------
         hed_schema : HedSchema, optional
             The dictionary to use to validate hed_strings.  If absent, will only validate column syntax.
+        def_mapper: DefMapper
+            The definition mapper to validate def tags with.
         error_handler : ErrorHandler or None
             Used to report errors.  Uses a default one if none passed in.
         Returns
@@ -295,6 +318,7 @@ def validate_column_entry(self, hed_schema=None, error_handler=None):
         if error_handler is None:
             error_handler = error_reporter.ErrorHandler()
 
+        error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, self.column_name)
         col_validation_issues = []
         if self.hed_string_iter():
             event_validator = None
@@ -304,9 +328,8 @@ def validate_column_entry(self, hed_schema=None, error_handler=None):
                 event_validator = EventValidator(check_for_warnings=True, run_semantic_validation=True,
                                                  hed_schema=hed_schema, error_handler=error_handler,
                                                  allow_numbers_to_be_pound_sign=True)
-            for hed_string, position in self.hed_string_iter(include_position=True):
+            for hed_string, position in self.hed_string_iter(include_position=True, also_return_bad_types=True):
                 error_handler.push_error_context(ErrorContext.SIDECAR_KEY_NAME, position)
-                error_handler.push_error_context(ErrorContext.HED_STRING, hed_string, increment_depth_after=False)
                 if not hed_string:
                     col_validation_issues += error_handler.format_error(SidecarErrors.BLANK_HED_STRING)
                 if not isinstance(hed_string, str):
@@ -314,10 +337,15 @@ def validate_column_entry(self, hed_schema=None, error_handler=None):
                                                                         given_type=type(hed_string),
                                                                         expected_type="str")
                 else:
+                    hed_string_obj = HedString(hed_string)
+                    error_handler.push_error_context(ErrorContext.HED_STRING, hed_string_obj,
+                                                     increment_depth_after=False)
+                    if def_mapper:
+                        col_validation_issues += def_mapper.replace_and_remove_tags(hed_string_obj, expand_defs=False)
                     if event_validator:
-                        col_validation_issues += event_validator.validate_input(hed_string)
-                    col_validation_issues += self._validate_pound_sign_count(hed_string, error_handler)
-                error_handler.pop_error_context()
+                        col_validation_issues += event_validator.validate_input(hed_string_obj)
+                    col_validation_issues += self._validate_pound_sign_count(hed_string_obj, error_handler)
+                    error_handler.pop_error_context()
                 error_handler.pop_error_context()
 
         if self.column_type is None:
@@ -328,6 +356,8 @@ def validate_column_entry(self, hed_schema=None, error_handler=None):
             if not raw_hed_dict:
                 col_validation_issues += error_handler.format_error(SidecarErrors.BLANK_HED_STRING)
 
+        col_validation_issues += self.get_def_issues()
+        error_handler.pop_error_context()
         return col_validation_issues
 
     def _validate_pound_sign_count(self, hed_string, error_handler):
@@ -337,7 +367,7 @@ def _validate_pound_sign_count(self, hed_string, error_handler):
 
         Parameters
         ----------
-        hed_string : str
+        hed_string : str or HedString
         error_handler : ErrorHandler
 
         Returns
@@ -362,3 +392,31 @@ def _validate_pound_sign_count(self, hed_string, error_handler):
             return error_handler.format_error(error_type, pound_sign_count=str(hed_string).count("#"))
 
         return []
+
+    def extract_defs(self, error_handler=None):
+        """
+            Finds all definitions in the hed strings of this column def group.
+
+        Parameters
+        ----------
+        error_handler : ErrorHandler or None
+            Used to report errors.  Uses a default one if none passed in.
+        Returns
+        -------
+        def_dicts: DefDict
+            A DefDict containing all the definitions found.
+        """
+        if error_handler is None:
+            error_handler = error_reporter.ErrorHandler()
+        def_dict = DefDict()
+        for hed_string, key_name in self.hed_string_iter(include_position=True):
+            hed_string_obj = HedString(hed_string)
+            error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, self.column_name)
+            error_handler.push_error_context(ErrorContext.SIDECAR_KEY_NAME, key_name)
+            error_handler.push_error_context(ErrorContext.HED_STRING, hed_string_obj, False)
+            def_dict.check_for_definitions(hed_string_obj, error_handler=error_handler)
+            error_handler.pop_error_context()
+            error_handler.pop_error_context()
+            error_handler.pop_error_context()
+
+        return def_dict
\ No newline at end of file
diff --git a/hedtools/hed/models/column_mapper.py b/hedtools/hed/models/column_mapper.py
index a7845eea1..1c7fae9c6 100644
--- a/hedtools/hed/models/column_mapper.py
+++ b/hedtools/hed/models/column_mapper.py
@@ -2,6 +2,9 @@
 from hed.models.column_def_group import ColumnDefGroup
 from hed.models.hed_string import HedString
 from hed.models import model_constants
+from hed.models.def_mapper import DefinitionMapper
+from hed.errors import error_reporter
+
 import copy
 
 
@@ -11,7 +14,9 @@ class ColumnMapper:
         Private Functions and variables column and row indexing starts at 0.
         Public functions and variables indexing starts at 1(or 2 if has column names)"""
     def __init__(self, json_def_files=None, tag_columns=None, column_prefix_dictionary=None,
-                 attribute_columns=None, definition_mapper=None):
+                 attribute_columns=None, extra_def_dicts=None,
+                 also_gather_defs_from_column_groups=True, strict_named_columns=True,
+                 enable_def_mapping=True):
         """Constructor for ColumnMapper
 
         Parameters
@@ -29,8 +34,17 @@ def __init__(self, json_def_files=None, tag_columns=None, column_prefix_dictiona
             and the fifth column contains tags that needs Event/Category/ prepended to them.
         attribute_columns: str or int or [str] or [int]
              A list of column names or numbers to treat as attributes.
-        definition_mapper: DefinitionMapper
-            The mapper to use to remove definitions and replace dlabels from the given input
+        extra_def_dicts: [DefDict]
+            DefDict's containing all the definitions this file should use - other than the ones coming from the file
+            itself, and from the column def groups.  These are added as as the last entries, so names will override
+            earlier ones.
+        also_gather_defs_from_column_groups: bool
+            Default to true.  If False, do NOT extract any definitions from column groups, assume they are already
+            in the def_dict list.
+        strict_named_columns: bool
+            If True, any missing named tag column will be an error when assigning headers.
+        enable_def_mapping: bool
+            Default True.  If True, this will remove definitions while parsing.
         """
         # This points to column_type entries based on column names or indexes if columns have no column_name.
         self.column_defs = {}
@@ -40,10 +54,14 @@ def __init__(self, json_def_files=None, tag_columns=None, column_prefix_dictiona
         self._column_map = None
         self._tag_columns = []
         self._column_prefix_dictionary = {}
-        self._def_mapper = definition_mapper
+        self._extra_def_dicts = extra_def_dicts
+        self._enable_def_mapping = enable_def_mapping
+        self._def_mapper = None
+        self._strict_named_columns = strict_named_columns
+        self._also_gather_defs_from_column_groups = also_gather_defs_from_column_groups
 
         self._na_patterns = ["n/a", "nan"]
-
+        self._mapper_issues = []
         if json_def_files:
             self.add_json_file_defs(json_def_files)
         self.add_columns(attribute_columns)
@@ -51,8 +69,9 @@ def __init__(self, json_def_files=None, tag_columns=None, column_prefix_dictiona
         self.set_tag_columns(tag_columns, False)
         self.set_column_prefix_dict(column_prefix_dictionary, False)
 
-        # finalize the column map based on initial settings.
+        # finalize the column map based on initial settings with no header
         self._finalize_mapping()
+        self._finalize_def_dicts()
 
     def add_json_file_defs(self, json_file_input_list):
         """
@@ -97,7 +116,8 @@ def set_column_prefix_dict(self, column_prefix_dictionary, finalize_mapping=True
         if column_prefix_dictionary:
             self._column_prefix_dictionary = self._subtract_1_from_dictionary_keys(column_prefix_dictionary)
         if finalize_mapping:
-            self._finalize_mapping()
+            return self._finalize_mapping()
+        return []
 
     def set_tag_columns(self, tag_columns, finalize_mapping=True):
         """Adds the given columns as hed tag columns if they don't exist.  If they do exist,
@@ -113,7 +133,10 @@ def set_tag_columns(self, tag_columns, finalize_mapping=True):
         if tag_columns:
             self._tag_columns = self._subtract_1_from_list_elements(tag_columns)
         if finalize_mapping:
-            self._finalize_mapping()
+            issues = self._finalize_mapping()
+            self._finalize_def_dicts()
+            return issues
+        return []
 
     def set_column_map(self, new_column_map=None):
         """Pass in the column number to column_name mapping to finalize
@@ -130,7 +153,7 @@ def set_column_map(self, new_column_map=None):
         else:
             column_map = {column_number: column_name for column_number, column_name in enumerate(new_column_map)}
         self._column_map = column_map
-        self._finalize_mapping()
+        return self._finalize_mapping()
 
     def add_columns(self, column_names_or_numbers, column_type=ColumnType.Attribute):
         """
@@ -143,9 +166,9 @@ def add_columns(self, column_names_or_numbers, column_type=ColumnType.Attribute)
         column_type : ColumnType, default Attribute
             The type of this column.  Generally will be Attribute
         """
-        if not isinstance(column_names_or_numbers, list):
-            column_names_or_numbers = [column_names_or_numbers]
         if column_names_or_numbers:
+            if not isinstance(column_names_or_numbers, list):
+                column_names_or_numbers = [column_names_or_numbers]
             for column_name in column_names_or_numbers:
                 new_def = ColumnDef(column_type, column_name)
                 self._add_column_def(new_def)
@@ -304,12 +327,16 @@ def _finalize_mapping(self):
         This needs to be called after all definitions and columns are added.
         """
         self._final_column_map = {}
+        found_named_tag_columns = {}
+        self._mapper_issues = []
         if self._column_map is not None:
             for column_number, column_name in self._column_map.items():
                 if column_name in self.column_defs:
                     column_entry = self.column_defs[column_name]
                     column_entry.column_name = column_name
                     self._final_column_map[column_number] = column_entry
+                elif column_name in self._tag_columns:
+                    found_named_tag_columns[column_name] = column_number
 
         # Add any numbered columns
         for column_name, column_entry in self.column_defs.items():
@@ -318,15 +345,61 @@ def _finalize_mapping(self):
                 column_number = column_name - 1
                 self._final_column_map[column_number] = column_entry
 
-        # Add column numbers.
+        # Add any tag columns
         for column_number in self._tag_columns:
-            if column_number not in self._final_column_map:
+            if isinstance(column_number, int):
+                if column_number not in self._final_column_map:
+                    self._final_column_map[column_number] = ColumnDef(ColumnType.HEDTags, column_number)
+            elif column_number in found_named_tag_columns:
+                column_name = column_number
+                column_number = found_named_tag_columns[column_name]
                 self._final_column_map[column_number] = ColumnDef(ColumnType.HEDTags, column_number)
+            elif self._strict_named_columns:
+                # todo: update this with an actual error
+                self._mapper_issues += [{'message': f"Column '{column_number}' missing."}]
 
         # Add prefixes
         for column_number, prefix in self._column_prefix_dictionary.items():
             self._set_column_prefix(column_number, prefix)
 
+        return self._mapper_issues
+
+    def _finalize_def_dicts(self):
+        def_dicts = []
+        if self._also_gather_defs_from_column_groups or not self._extra_def_dicts:
+            def_dicts = [entry.def_dict for entry in self.column_defs.values()]
+        if self._extra_def_dicts:
+            def_dicts += self._extra_def_dicts
+
+        self._def_mapper = None
+        if self._enable_def_mapping:
+            self._def_mapper = DefinitionMapper(def_dicts)
+
+    def validate_column_defs(self, hed_schema=None, error_handler=None):
+        """
+        Validates all column definitions that are being used and column definition hed strings
+
+        Parameters
+        ----------
+        hed_schema : HedSchema, optional
+            Also semantically validates hed strings if present.
+        error_handler : ErrorHandler or None
+            Used to report errors.  Uses a default one if none passed in.
+        Returns
+        -------
+        validation_issues : [{}]
+            A list of syntax and semantic issues found in the definitions.
+        """
+        if error_handler is None:
+            error_handler = error_reporter.ErrorHandler()
+        all_validation_issues = []
+        for column_def_group in self.column_defs.values():
+            all_validation_issues += column_def_group.validate_column_entry(hed_schema=hed_schema,
+                                                                            error_handler=error_handler,
+                                                                            def_mapper=self._def_mapper)
+
+        return all_validation_issues
+
     @staticmethod
     def _subtract_1_from_dictionary_keys(int_key_dictionary):
         """Subtracts 1 from each dictionary key.
@@ -357,4 +430,4 @@ def _subtract_1_from_list_elements(int_list):
             A list of containing each element subtracted by 1.
 
         """
-        return [x - 1 for x in int_list]
+        return [x if isinstance(x, str) else x - 1 for x in int_list]
diff --git a/hedtools/hed/models/def_dict.py b/hedtools/hed/models/def_dict.py
index 964ca2b91..1ea8cf48c 100644
--- a/hedtools/hed/models/def_dict.py
+++ b/hedtools/hed/models/def_dict.py
@@ -69,29 +69,17 @@ def __init__(self):
         # Definition related issues
         self._extract_def_issues = []
 
-    def get_def_issues(self, hed_schema=None):
+    def get_def_issues(self):
         """
-            Returns definition errors found during extraction, additionally will check if definition terms already
-            exist in the schema if a hed_schema is passed in.
+            Returns definition errors found during extraction
 
         Parameters
         ----------
-        hed_schema : HedSchema
-            Optional parameter to check if the definition terms were already in the schema
-
         Returns
         -------
         issues_list: [{}]
             List of DefinitionErrors found.
         """
-        if hed_schema:
-            new_issues = []
-            for def_entry in self._defs.values():
-                if def_entry.name.lower() in hed_schema.short_tag_mapping:
-                    new_issues += error_reporter.ErrorHandler.format_error_from_context(
-                        DefinitionErrors.TAG_IN_SCHEMA, def_entry.source_context, def_entry.name)
-            return self._extract_def_issues + new_issues
-
         return self._extract_def_issues
 
     def __iter__(self):
diff --git a/hedtools/hed/models/def_mapper.py b/hedtools/hed/models/def_mapper.py
index 604db2e52..89f6f8176 100644
--- a/hedtools/hed/models/def_mapper.py
+++ b/hedtools/hed/models/def_mapper.py
@@ -119,7 +119,7 @@ def replace_and_remove_tags(self, hed_string_obj, expand_defs=True):
                                             "tag": tag}]
                         continue
                     if not expand_defs:
-                       continue
+                        continue
 
                     tag.tag = def_tag_name
 
@@ -127,6 +127,7 @@ def replace_and_remove_tags(self, hed_string_obj, expand_defs=True):
                     continue
 
         if remove_groups:
-            hed_string_obj.remove_groups(remove_groups)
+            if expand_defs:
+                hed_string_obj.remove_groups(remove_groups)
 
         return def_issues
diff --git a/hedtools/hed/models/events_input.py b/hedtools/hed/models/events_input.py
index e31b85347..422522321 100644
--- a/hedtools/hed/models/events_input.py
+++ b/hedtools/hed/models/events_input.py
@@ -1,89 +1,90 @@
 from hed.models.column_mapper import ColumnMapper
 from hed.models.base_input import BaseInput
 from hed.models.column_def_group import ColumnDefGroup
-from hed.models.def_mapper import DefinitionMapper
-from hed.errors import error_reporter
 
 
 class EventsInput(BaseInput):
     """A class to parse bids style spreadsheets into a more general format."""
 
-    def __init__(self, filename=None, file_type=None, worksheet_name=None, tag_columns=None,
-                 has_column_names=True, column_prefix_dictionary=None,
-                 json_def_files=None, attribute_columns=None,
-                 def_dicts=None, display_name=None):
+    HED_COLUMN_NAME = "HED"
+
+    def __init__(self, filename=None, json_def_files=None, attribute_columns=None, extra_def_dicts=None,
+                 also_gather_defs_from_column_groups=True, name=None):
         """Constructor for the EventsInput class.
 
         Parameters
         ----------
          filename: str or file like
              An xlsx/tsv file to open.
-        file_type: str
-            ".xlsx" for excel, ".tsv" or ".txt" for tsv. data.  Derived from filename if filename is a str.
-        worksheet_name: str
-            The name of the Excel workbook worksheet that contains the HED tags.  Not applicable to tsv files.
-        tag_columns: []
-            A list of ints containing the columns that contain the HED tags. The default value is the 2nd column.
-        has_column_names: bool
-            True if file has column names. The validation will skip over the first line of the file. False, if
-            otherwise.
-        column_prefix_dictionary: {}
-            A dictionary with keys pertaining to the required HED tag columns that correspond to tags that need to be
-            prefixed with a parent tag path. For example, prefixed_needed_tag_columns = {3: 'Event/Description',
-            4: 'Event/Label/', 5: 'Event/Category/'} The third column contains tags that need Event/Description/
-            prepended to them, the fourth column contains tags that need Event/Label/ prepended to them,
-            and the fifth column contains tags that needs Event/Category/ prepended to them.
         json_def_files : str or [str] or ColumnDefGroup or [ColumnDefGroup]
             A list of json filenames to pull events from
         attribute_columns: str or int or [str] or [int]
             A list of column names or numbers to treat as attributes.
             Default: ["duration", "onset"]
-        def_dicts: [DefDict]
+        extra_def_dicts: [DefDict]
             DefDict's containing all the definitions this file should use - other than the ones coming from the file
-            itself.
-            If this is NOT passed, the class will instead gather definitions from any passed in ColumnDefGroups
+            itself, and from the column def groups.  These are added as as the last entries, so names will override
+            earlier ones.
+        also_gather_defs_from_column_groups: bool
+            Default to true.  If False, do NOT extract any definitions from column groups, assume they are already
+            in the def_dict list.
+        name: str
+            The name to display for this file for error purposes.
         """
-        if tag_columns is None:
-            tag_columns = []
-        if column_prefix_dictionary is None:
-            column_prefix_dictionary = {}
         if attribute_columns is None:
             attribute_columns = ["duration", "onset"]
 
-        # This stuff is mostly here to make this easier to use for development
-        # you should generally create the DefDict and ColumnDefGroup before reaching this point.
+        column_group_defs = None
         if json_def_files:
-            self.column_group_defs = ColumnDefGroup.load_multiple_json_files(json_def_files)
-        else:
-            self.column_group_defs = None
-        # if def_dicts is None:
-        #     self.def_dicts = ColumnDefGroup.extract_defs_from_list(self.column_group_defs)
-        # else:
-        #     if not isinstance(def_dicts, list):
-        #         self.def_dicts = [def_dicts]
-        #     else:
-        #         self.def_dicts = def_dicts
-        if def_dicts and not isinstance(def_dicts, list):
-            self._def_dicts = [def_dicts]
+            column_group_defs = ColumnDefGroup.load_multiple_json_files(json_def_files)
+        if extra_def_dicts and not isinstance(extra_def_dicts, list):
+            extra_def_dicts = [column_group_defs]
         else:
-            self._def_dicts = def_dicts
+            extra_def_dicts = column_group_defs
 
-        def_mapper = DefinitionMapper(self._def_dicts)
-        new_mapper = ColumnMapper(json_def_files=self.column_group_defs, tag_columns=tag_columns,
-                                  column_prefix_dictionary=column_prefix_dictionary,
+        new_mapper = ColumnMapper(json_def_files=column_group_defs, tag_columns=[self.HED_COLUMN_NAME],
                                   attribute_columns=attribute_columns,
-                                  definition_mapper=def_mapper)
+                                  extra_def_dicts=extra_def_dicts,
+                                  also_gather_defs_from_column_groups=also_gather_defs_from_column_groups,
+                                  strict_named_columns=False)
 
-        super().__init__(filename, file_type, worksheet_name, has_column_names, new_mapper,
-                         display_name=display_name)
+        super().__init__(filename, file_type=".tsv", worksheet_name=None, has_column_names=True, mapper=new_mapper,
+                         name=name)
 
         if not self._has_column_names:
             raise ValueError("You are attempting to open a bids style file with no column headers provided.\n"
                              "This is probably not intended.")
 
-    @property
-    def def_dicts(self):
-        return self._def_dicts
+    def reset_column_defs(self, json_def_files=None, attribute_columns=None, extra_def_dicts=None,
+                          also_gather_defs_from_column_groups=True):
+        """
+            Change the sidecars in use for parsing this file.
+
+        Parameters
+        ----------
+        json_def_files : str or [str] or ColumnDefGroup or [ColumnDefGroup]
+            A list of json filenames to pull events from
+        attribute_columns: str or int or [str] or [int]
+            A list of column names or numbers to treat as attributes.
+            Default: ["duration", "onset"]
+        extra_def_dicts: [DefDict]
+            DefDict's containing all the definitions this file should use - other than the ones coming from the file
+            itself, and from the column def groups.  These are added as as the last entries, so names will override
+            earlier ones.
+        also_gather_defs_from_column_groups: bool
+            Default to true.  If False, do NOT extract any definitions from column groups, assume they are already
+            in the def_dict list.
+        Returns
+        -------
+
+        """
+        new_mapper = ColumnMapper(json_def_files=json_def_files, tag_columns=[self.HED_COLUMN_NAME],
+                                  attribute_columns=attribute_columns,
+                                  extra_def_dicts=extra_def_dicts,
+                                  also_gather_defs_from_column_groups=also_gather_defs_from_column_groups,
+                                  strict_named_columns=False)
+
+        self.reset_mapper(new_mapper)
 
     def validate_file_sidecars(self, hed_schema=None, error_handler=None):
         """
@@ -102,11 +103,4 @@ def validate_file_sidecars(self, hed_schema=None, error_handler=None):
         validation_issues : [{}]
             A list of syntax and semantic issues found in the definitions.
         """
-        if error_handler is None:
-            error_handler = error_reporter.ErrorHandler()
-        all_validation_issues = []
-        for column_def_group in self.column_group_defs:
-            all_validation_issues += column_def_group.validate_entries(hed_schema=hed_schema,
-                                                                       error_handler=error_handler)
-
-        return all_validation_issues
+        return self._mapper.validate_column_defs(hed_schema, error_handler)
diff --git a/hedtools/hed/models/hed_input.py b/hedtools/hed/models/hed_input.py
index d04fcb70d..ce6208c0b 100644
--- a/hedtools/hed/models/hed_input.py
+++ b/hedtools/hed/models/hed_input.py
@@ -6,7 +6,7 @@ class HedInput(BaseInput):
     """A class to parse basic hed style spreadsheets into a more general format."""
     def __init__(self, filename=None, file_type=None, worksheet_name=None, tag_columns=None,
                  has_column_names=True, column_prefix_dictionary=None,
-                 definition_mapper=None, csv_string=None, display_name=None):
+                 def_dicts=None, name=None):
         """Constructor for the HedInput class.
 
         Parameters
@@ -28,10 +28,8 @@ def __init__(self, filename=None, file_type=None, worksheet_name=None, tag_colum
             4: 'Event/Label/', 5: 'Event/Category/'} The third column contains tags that need Event/Description/
             prepended to them, the fourth column contains tags that need Event/Label/ prepended to them,
             and the fifth column contains tags that needs Event/Category/ prepended to them.
-        definition_mapper: DefinitionMapper
-            The definition mapper to use to remove and replace definition labels in HED data.
-        csv_string: str or None
-            The data to treat as this file.  eg web services passing a string.
+        def_dicts: [DefDict] or DefDict
+            The gathered definitions to use for this file, other than the ones that come from itself.
         """
         if tag_columns is None:
             tag_columns = [2]
@@ -39,6 +37,6 @@ def __init__(self, filename=None, file_type=None, worksheet_name=None, tag_colum
             column_prefix_dictionary = {}
 
         new_mapper = ColumnMapper(tag_columns=tag_columns, column_prefix_dictionary=column_prefix_dictionary,
-                                  definition_mapper=definition_mapper)
+                                  extra_def_dicts=def_dicts)
         super().__init__(filename, file_type, worksheet_name, has_column_names, new_mapper,
-                         display_name=display_name)
+                         name=name)
diff --git a/hedtools/hed/schema/hed_schema.py b/hedtools/hed/schema/hed_schema.py
index 5010160fb..7ad9f370d 100644
--- a/hedtools/hed/schema/hed_schema.py
+++ b/hedtools/hed/schema/hed_schema.py
@@ -108,7 +108,7 @@ def version(self):
     def library(self):
         return self.header_attributes.get('library')
 
-    def check_compliance(self, also_check_for_warnings=True, display_filename=None,
+    def check_compliance(self, also_check_for_warnings=True, name=None,
                          error_handler=None):
         """
             Checks for hed3 compliance of this schema.
@@ -117,7 +117,7 @@ def check_compliance(self, also_check_for_warnings=True, display_filename=None,
         ----------
         also_check_for_warnings : bool, default True
             If True, also checks for formatting issues like invalid characters, capitalization, etc.
-        display_filename: str
+        name: str
             If present, will use this as the filename for context, rather than using the actual filename
             Useful for temp filenames.
         error_handler : ErrorHandler or None
@@ -127,7 +127,7 @@ def check_compliance(self, also_check_for_warnings=True, display_filename=None,
         issue_list : [{}]
             A list of all warnings and errors found in the file.
         """
-        return schema_compliance.check_compliance(self, also_check_for_warnings, display_filename, error_handler)
+        return schema_compliance.check_compliance(self, also_check_for_warnings, name, error_handler)
 
     def find_duplicate_tags(self):
         """Finds all tags that are not unique.
diff --git a/hedtools/hed/schema/hed_schema_file.py b/hedtools/hed/schema/hed_schema_file.py
index a697919ca..44a2c8fc3 100644
--- a/hedtools/hed/schema/hed_schema_file.py
+++ b/hedtools/hed/schema/hed_schema_file.py
@@ -92,7 +92,7 @@ def load_schema_version(xml_folder=None, xml_version_number=None):
 
 
 def convert_schema_to_format(hed_schema, check_for_issues=True,
-                             display_filename=None, save_as_mediawiki=False, save_as_legacy_xml=False):
+                             name=None, save_as_mediawiki=False, save_as_legacy_xml=False):
     """
     Loads a local schema file or from a URL, then outputs a temporary file with the requested format.
     Parameters
@@ -101,7 +101,7 @@ def convert_schema_to_format(hed_schema, check_for_issues=True,
         The schema to convert
     check_for_issues : bool
         After conversion checks for warnings like capitalization or invalid characters.
-    display_filename: str
+    name: str
         If present, will use this as the filename for context, rather than using the actual filename
         Useful for temp filenames.
     save_as_mediawiki: bool
@@ -117,7 +117,7 @@ def convert_schema_to_format(hed_schema, check_for_issues=True,
     """
     issue_list = []
     if check_for_issues:
-        warnings = hed_schema.check_compliance(display_filename=display_filename)
+        warnings = hed_schema.check_compliance(name=name)
         issue_list += warnings
 
     if save_as_mediawiki:
diff --git a/hedtools/hed/schema/schema_compliance.py b/hedtools/hed/schema/schema_compliance.py
index ab93cc15d..9de32a73a 100644
--- a/hedtools/hed/schema/schema_compliance.py
+++ b/hedtools/hed/schema/schema_compliance.py
@@ -5,7 +5,7 @@
 ALLOWED_DESC_CHARS = "-_:;,./()+ ^"
 
 
-def check_compliance(hed_schema, also_check_for_warnings=True, display_filename=None,
+def check_compliance(hed_schema, also_check_for_warnings=True, name=None,
                      error_handler=None):
     """
         Checks for hed3 compliance of a schema object.
@@ -16,7 +16,7 @@ def check_compliance(hed_schema, also_check_for_warnings=True, display_filename=
         HedSchema object to check for hed3 compliance
     also_check_for_warnings : bool, default True
         If True, also checks for formatting issues like invalid characters, capitalization, etc.
-    display_filename: str
+    name: str
         If present, will use this as the filename for context, rather than using the actual filename
         Useful for temp filenames.
     error_handler : ErrorHandler or None
@@ -30,9 +30,9 @@ def check_compliance(hed_schema, also_check_for_warnings=True, display_filename=
         error_handler = error_reporter.ErrorHandler()
     issues_list = []
 
-    if not display_filename:
-        display_filename = hed_schema.filename
-    error_handler.push_error_context(ErrorContext.FILE_NAME, display_filename)
+    if not name:
+        name = hed_schema.filename
+    error_handler.push_error_context(ErrorContext.FILE_NAME, name)
 
     if hed_schema.has_duplicate_tags():
         duplicate_dict = hed_schema.find_duplicate_tags()
diff --git a/hedtools/hed/validator/event_validator.py b/hedtools/hed/validator/event_validator.py
index 4e69c9e17..b41cdd470 100644
--- a/hedtools/hed/validator/event_validator.py
+++ b/hedtools/hed/validator/event_validator.py
@@ -57,7 +57,7 @@ def __init__(self, check_for_warnings=False, run_semantic_validation=True,
 
         self._run_semantic_validation = run_semantic_validation
 
-    def validate_input(self, hed_input, display_filename=None):
+    def validate_input(self, hed_input, name=None):
         """
             Validates any given hed_input string, file, or list and returns a list of issues.
 
@@ -66,7 +66,7 @@ def validate_input(self, hed_input, display_filename=None):
         hed_input: str or list or HedInput object
             A list of HED strings, a single HED string, or a HedInput object.
             If it is a single string or a list, validate them as hed strings.
-        display_filename: str
+        name: str
             If present, will use this as the filename for context, rather than using the actual filename
             Useful for temp filenames.
         Returns
@@ -74,13 +74,13 @@ def validate_input(self, hed_input, display_filename=None):
         validation_issues : [{}]
         """
         is_file = isinstance(hed_input, BaseInput)
-        if not display_filename and is_file:
-            display_filename = hed_input.display_name
+        if not name and is_file:
+            name = hed_input.name
 
         if isinstance(hed_input, list):
             validation_issues = self._validate_hed_strings(hed_input)
         elif is_file:
-            self._error_handler.push_error_context(ErrorContext.FILE_NAME, display_filename)
+            self._error_handler.push_error_context(ErrorContext.FILE_NAME, name)
             validation_issues = self._validate_hed_tags_in_file(hed_input)
         else:
             validation_issues = self._validate_hed_strings([hed_input])[0]
@@ -106,7 +106,10 @@ def _validate_hed_strings(self, hed_strings):
         eeg_issues = []
         for i in range(0, len(hed_strings)):
             hed_string = hed_strings[i]
-            hed_string_obj = HedString(hed_string)
+            if isinstance(hed_string, HedString):
+                hed_string_obj = hed_string
+            else:
+                hed_string_obj = HedString(hed_string)
             self._error_handler.push_error_context(ErrorContext.HED_STRING, hed_string_obj, increment_depth_after=False)
             validation_issues = self._tag_validator.run_hed_string_validators(hed_string_obj)
             if not validation_issues:
@@ -131,7 +134,7 @@ def _validate_hed_tags_in_file(self, hed_input):
         validation_issues : [{}]
         """
         validation_issues = []
-        validation_issues += hed_input.file_def_dict.get_def_issues(hed_schema=self._hed_schema)
+        validation_issues += hed_input.file_def_dict.get_def_issues()
         for row_number, row_dict in hed_input.iter_dataframe(return_row_dict=True):
             validation_issues = self._append_validation_issues_if_found(validation_issues, row_number, row_dict)
         return validation_issues


Test patch:
diff --git a/hedtools/tests/data/ExcelMultipleSheets_fileio.xlsx b/hedtools/tests/data/ExcelMultipleSheets_fileio.xlsx
deleted file mode 100644
index a8a007c58..000000000
Binary files a/hedtools/tests/data/ExcelMultipleSheets_fileio.xlsx and /dev/null differ
diff --git a/hedtools/tests/data/ExcelMultipleSheets_resave.csv b/hedtools/tests/data/ExcelMultipleSheets_resave.csv
deleted file mode 100644
index 05579552f..000000000
--- a/hedtools/tests/data/ExcelMultipleSheets_resave.csv
+++ /dev/null
@@ -1,5 +0,0 @@
-Event code	Short label	Description in text	HED tags
-251	PerturbLeft	Vehicle undergoes a perturbation to left.	Event/Category/Participant response, (Item/Object/Vehicle/Car, Attribute/Object control/Perturb), Attribute/Direction/Right, Attribute/Onset
-252	PerturbRight	Vehicle undergoes a perturbation to right.	Event/Category/Participant response, (Item/Object/Vehicle/Car, Attribute/Object control/Perturb), Attribute/Direction/Right, Attribute/Onset
-253	ResponseOnset	Subject starts to respond to perturbation by steering vehicle back to center of the lane.	Event/Category/Participant response, (Participant ~ Action/Control Vehicle/Drive/Correct ~ Item/Object/Vehicle/Car), Attribute/Onset
-254	ResponseOffset	Subject completes response to perturbation having steered the vehicle back to the center of the lane.	Event/Category/Participant response, (Participant ~ Action/Control Vehicle/Drive/Correct ~ Item/Object/Vehicle/Car), Attribute/Offset
diff --git a/hedtools/tests/data/ExcelMultipleSheets_resave.xlsx b/hedtools/tests/data/ExcelMultipleSheets_resave.xlsx
deleted file mode 100644
index a8a007c58..000000000
Binary files a/hedtools/tests/data/ExcelMultipleSheets_resave.xlsx and /dev/null differ
diff --git a/hedtools/tests/data/ExcelMultipleSheets_resave_formatting.xlsx b/hedtools/tests/data/ExcelMultipleSheets_resave_formatting.xlsx
deleted file mode 100644
index a8a007c58..000000000
Binary files a/hedtools/tests/data/ExcelMultipleSheets_resave_formatting.xlsx and /dev/null differ
diff --git a/hedtools/tests/data/ExcelMultipleSheets_test_save.xlsx b/hedtools/tests/data/ExcelMultipleSheets_test_save.xlsx
deleted file mode 100644
index 1cb00894f..000000000
Binary files a/hedtools/tests/data/ExcelMultipleSheets_test_save.xlsx and /dev/null differ
diff --git a/hedtools/tests/schema/test_hed_schema.py b/hedtools/tests/schema/test_hed_schema.py
index cd05c49b1..c4f67b782 100644
--- a/hedtools/tests/schema/test_hed_schema.py
+++ b/hedtools/tests/schema/test_hed_schema.py
@@ -46,16 +46,16 @@ def test_invalid_schema(self):
             pass
         self.assertFalse(hed_schema)
 
-    def test_display_filename(self):
+    def test_name(self):
         invalid_xml_file = "invalidxmlfile.xml"
-        display_filename = "PrettyDisplayName.xml"
+        name = "PrettyDisplayName.xml"
         try:
             schema.load_schema(invalid_xml_file)
             # We should have an error before we reach here.
             self.assertTrue(False)
         except HedFileError as e:
-            self.assertTrue(display_filename in e.format_error_message(return_string_only=True,
-                                                                       display_filename=display_filename))
+            self.assertTrue(name in e.format_error_message(return_string_only=True,
+                                                                       name=name))
 
     def test_attribute_keys(self):
         tag_dictionary_keys = ['defaultUnits', 'extensionAllowed', 'isNumeric', 'position', 'predicateType',
diff --git a/hedtools/tests/util/test_col_def_group.py b/hedtools/tests/util/test_col_def_group.py
index 7e3f031a5..985ddc070 100644
--- a/hedtools/tests/util/test_col_def_group.py
+++ b/hedtools/tests/util/test_col_def_group.py
@@ -5,6 +5,7 @@
 from hed.models.column_definition import ColumnDef
 from hed.errors.exceptions import HedFileError
 from hed import schema
+import io
 
 
 class Test(unittest.TestCase):
@@ -39,20 +40,20 @@ def test_invalid_filenames(self):
             pass
         self.assertTrue(len(json_dict._column_settings) == 0)
 
-    def test_display_filename(self):
+    def test_name(self):
         invalid_json = "invalidxmlfile.json"
-        display_filename = "PrettyDisplayName.json"
+        name = "PrettyDisplayName.json"
         try:
             json_dict = ColumnDefGroup(invalid_json)
             self.assertTrue(False)
         except HedFileError as e:
-            self.assertTrue(display_filename in e.format_error_message(return_string_only=True,
-                                                                       display_filename=display_filename))
+            self.assertTrue(name in e.format_error_message(return_string_only=True,
+                                                                       name=name))
 
     def test_add_json_string(self):
-        with open(self.json_filename, "r") as fp:
-            input_string = fp.read()
-            json_file = ColumnDefGroup(json_string=input_string)
+        with open(self.json_filename) as file:
+            file_as_string = io.StringIO(file.read())
+            json_file = ColumnDefGroup(file_as_string)
             self.assertTrue(json_file)
 
     def test__iter__(self):
@@ -81,7 +82,7 @@ def test__iter__(self):
     #
     # def get_validation_issues(self):
     #
-    # def validate_entries(self, hed_schema=None, display_filename=None):
+    # def validate_entries(self, hed_schema=None, name=None):
     #
 
     def test_validate_column_group(self):
diff --git a/hedtools/tests/util/test_def_dict.py b/hedtools/tests/util/test_def_dict.py
index d03d319f9..6d6e46b4d 100644
--- a/hedtools/tests/util/test_def_dict.py
+++ b/hedtools/tests/util/test_def_dict.py
@@ -21,7 +21,8 @@ def check_def_base(self, test_strings, expected_issues):
             def_dict = DefDict()
             def_dict.check_for_definitions(HedString(test_strings[test_key]))
             expected_issue = expected_issues[test_key]
-            self.assertCountEqual(def_dict.get_def_issues(hed_schema=self.hed_schema), expected_issue, HedString(test_strings[test_key]))
+            test_issues = def_dict.get_def_issues()
+            self.assertCountEqual(test_issues, expected_issue, HedString(test_strings[test_key]))
 
 
 class TestDefDict(TestDefBase):
@@ -76,7 +77,8 @@ def test_definitions(self):
             'twoGroupTags': self.error_handler.format_error(DefinitionErrors.WRONG_NUMBER_GROUP_TAGS, "InvalidDef1", [self.def_contents_string, self.def_contents_string2]),
             'duplicateDef': self.error_handler.format_error(DefinitionErrors.DUPLICATE_DEFINITION, "Def1"),
             'duplicateDef2': self.error_handler.format_error(DefinitionErrors.DUPLICATE_DEFINITION, "Def1"),
-            'defAlreadyTagInSchema': self.error_handler.format_error(DefinitionErrors.TAG_IN_SCHEMA, "Item"),
+            # This is not an error since re-used terms are checked elsewhere.
+            'defAlreadyTagInSchema': [],
             'defTooManyPlaceholders': self.error_handler.format_error(DefinitionErrors.WRONG_NUMBER_PLACEHOLDER_TAGS, "TestDefPlaceholder",
                                                                                  expected_count=1, tag_list=["Item/TestDef1/#", "Item/TestDef2/#"]),
             'invalidPlaceholderExtension': self.error_handler.format_error(DefinitionErrors.INVALID_DEFINITION_EXTENSION, "InvalidDef1/thispartisnotallowed"),
diff --git a/hedtools/tests/util/test_def_mapper.py b/hedtools/tests/util/test_def_mapper.py
index 4efaf623b..fd47e23f1 100644
--- a/hedtools/tests/util/test_def_mapper.py
+++ b/hedtools/tests/util/test_def_mapper.py
@@ -75,7 +75,7 @@ def test_replace_and_remove_tags_no_expand(self):
 
         test_string = HedString(self.basic_def_string)
         def_issues = def_mapper.replace_and_remove_tags(test_string, expand_defs=False)
-        self.assertEqual(str(test_string), "")
+        self.assertEqual(str(test_string), self.basic_def_string)
 
         test_string = HedString(self.basic_def_string_no_paren)
         def_issues = def_mapper.replace_and_remove_tags(test_string, expand_defs=False)
@@ -83,23 +83,23 @@ def test_replace_and_remove_tags_no_expand(self):
 
         test_string = HedString(self.basic_hed_string + "," + self.basic_def_string)
         def_issues = def_mapper.replace_and_remove_tags(test_string, expand_defs=False)
-        self.assertEqual(str(test_string), self.basic_hed_string)
+        self.assertEqual(str(test_string), self.basic_hed_string + "," + self.basic_def_string)
 
         test_string = HedString(self.basic_def_string + "," + self.basic_hed_string)
         def_issues = def_mapper.replace_and_remove_tags(test_string, expand_defs=False)
-        self.assertEqual(str(test_string), self.basic_hed_string)
+        self.assertEqual(str(test_string), self.basic_def_string + "," + self.basic_hed_string)
 
         test_string = HedString(self.basic_hed_string_with_def)
         def_issues = def_mapper.replace_and_remove_tags(test_string, expand_defs=False)
-        self.assertEqual(str(test_string), self.basic_hed_string + "," + self.label_def_string)
+        self.assertEqual(str(test_string), self.basic_hed_string_with_def)
 
         test_string = HedString(self.basic_hed_string_with_def_first)
         def_issues = def_mapper.replace_and_remove_tags(test_string, expand_defs=False)
-        self.assertEqual(str(test_string), self.label_def_string + "," + self.basic_hed_string)
+        self.assertEqual(str(test_string), self.basic_hed_string_with_def_first)
 
         test_string = HedString(self.basic_hed_string_with_def_first_paren)
         def_issues = def_mapper.replace_and_remove_tags(test_string, expand_defs=False)
-        self.assertEqual(str(test_string), "(" + self.label_def_string + "," + self.basic_hed_string + ")")
+        self.assertEqual(str(test_string), self.basic_hed_string_with_def_first_paren)
 
 
     def test_replace_and_remove_tags_placeholder(self):
diff --git a/hedtools/tests/util/test_error_reporter.py b/hedtools/tests/util/test_error_reporter.py
index 610e5d8ca..9e3be12b1 100644
--- a/hedtools/tests/util/test_error_reporter.py
+++ b/hedtools/tests/util/test_error_reporter.py
@@ -12,20 +12,20 @@ def setUpClass(cls):
     def test_push_error_context(self):
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
         self.assertTrue(len(error_list) == 1)
-        display_filename = "DummyFileName.txt"
-        self.error_handler.push_error_context(ErrorContext.FILE_NAME, display_filename)
+        name = "DummyFileName.txt"
+        self.error_handler.push_error_context(ErrorContext.FILE_NAME, name)
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
-        self.assertTrue(display_filename in error_list[0][ErrorContext.FILE_NAME])
+        self.assertTrue(name in error_list[0][ErrorContext.FILE_NAME])
         column_name = "DummyColumnName"
         self.error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, column_name)
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
         self.assertTrue(column_name in error_list[0][ErrorContext.SIDECAR_COLUMN_NAME])
         self.error_handler.reset_error_context()
-        self.error_handler.push_error_context(ErrorContext.FILE_NAME, display_filename)
+        self.error_handler.push_error_context(ErrorContext.FILE_NAME, name)
         self.error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, column_name)
         self.error_handler.push_error_context(ErrorContext.COLUMN, 1)
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
-        self.assertTrue(display_filename in error_list[0][ErrorContext.FILE_NAME])
+        self.assertTrue(name in error_list[0][ErrorContext.FILE_NAME])
         self.assertTrue(column_name in error_list[0][ErrorContext.SIDECAR_COLUMN_NAME])
         self.assertTrue(1 in error_list[0][ErrorContext.COLUMN])
         self.assertTrue(len(error_list) == 1)
@@ -34,11 +34,11 @@ def test_push_error_context(self):
     def test_pop_error_context(self):
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
         self.assertTrue(len(error_list) == 1)
-        display_filename = "DummyFileName.txt"
-        self.error_handler.push_error_context(ErrorContext.FILE_NAME, display_filename)
+        name = "DummyFileName.txt"
+        self.error_handler.push_error_context(ErrorContext.FILE_NAME, name)
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
         self.assertTrue(len(error_list) == 1)
-        self.assertTrue(display_filename in error_list[0][ErrorContext.FILE_NAME])
+        self.assertTrue(name in error_list[0][ErrorContext.FILE_NAME])
         self.error_handler.pop_error_context()
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
         self.assertTrue(len(error_list) == 1)
@@ -46,12 +46,12 @@ def test_pop_error_context(self):
         self.error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, column_name)
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
         self.assertTrue(len(error_list) == 1)
-        self.error_handler.push_error_context(ErrorContext.FILE_NAME, display_filename)
+        self.error_handler.push_error_context(ErrorContext.FILE_NAME, name)
         self.error_handler.push_error_context(ErrorContext.SIDECAR_COLUMN_NAME, column_name)
         self.error_handler.push_error_context(ErrorContext.COLUMN, 1)
         error_list = self.error_handler.format_error(ValidationErrors.HED_TAG_NOT_UNIQUE, "")
         self.assertTrue(len(error_list) == 1)
-        self.assertTrue(display_filename in error_list[0][ErrorContext.FILE_NAME])
+        self.assertTrue(name in error_list[0][ErrorContext.FILE_NAME])
         self.assertTrue(column_name in error_list[0][ErrorContext.SIDECAR_COLUMN_NAME])
         self.assertTrue(1 in error_list[0][ErrorContext.COLUMN])
         self.error_handler.pop_error_context()
diff --git a/hedtools/tests/util/test_hed_file_input.py b/hedtools/tests/util/test_hed_file_input.py
index 4bd078fb3..b12b37169 100644
--- a/hedtools/tests/util/test_hed_file_input.py
+++ b/hedtools/tests/util/test_hed_file_input.py
@@ -42,7 +42,6 @@ def test_all(self):
         # Just make sure this didn't crash for now
         self.assertTrue(True)
 
-
     def test_get_row_hed_tags(self):
         row_dict = self.generic_file_input._mapper.expand_row_tags(self.row_with_hed_tags)
         hed_string, column_to_hed_tags_dictionary = self.generic_file_input._get_row_hed_tags_from_dict(row_dict)
@@ -56,16 +55,12 @@ def test_file_as_string(self):
 
         json_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../data/bids_events.json")
         column_group = ColumnDefGroup(json_path)
-        def_dict = column_group.extract_defs()
-        self.assertEqual(len(def_dict.get_def_issues()), 0)
-        input_file = EventsInput(events_path, json_def_files=column_group,
-                                 def_dicts=def_dict)
+        self.assertEqual(len(column_group.validate_entries()), 0)
+        input_file = EventsInput(events_path, json_def_files=column_group)
 
         with open(events_path) as file:
             events_file_as_string = io.StringIO(file.read())
-        input_file_from_string = EventsInput(filename=events_file_as_string,
-                                             file_type='.tsv', json_def_files=column_group,
-                                             def_dicts=def_dict)
+        input_file_from_string = EventsInput(filename=events_file_as_string, json_def_files=column_group)
 
         for (row_number, column_dict), (row_number2, column_dict) in zip(input_file, input_file_from_string):
             self.assertEqual(row_number, row_number2)
@@ -120,6 +115,21 @@ def test_loading_and_reloading(self):
 
         self.assertTrue(test_input_file._dataframe.equals(reloaded_input._dataframe))
 
+    def test_loading_and_reset_mapper(self):
+        events_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../data/bids_events.tsv')
+        json_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../data/bids_events.json")
+        column_group = ColumnDefGroup(json_path)
+        self.assertEqual(len(column_group.validate_entries()), 0)
+        input_file_1 = EventsInput(events_path, json_def_files=column_group)
+        input_file_2 = EventsInput(events_path, json_def_files=column_group)
+
+        input_file_2.reset_column_defs()
+
+        for (row_number, column_dict), (row_number2, column_dict2) in zip(input_file_1.iter_dataframe(expand_defs=True), input_file_2.iter_dataframe(expand_defs=True)):
+            self.assertEqual(row_number, row_number2)
+            self.assertTrue(len(column_dict) == 4)
+            self.assertTrue(len(column_dict2) == 11)
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/hedtools/tests/validator/test_event_validator.py b/hedtools/tests/validator/test_event_validator.py
index 17e7c29e3..2aed4982c 100644
--- a/hedtools/tests/validator/test_event_validator.py
+++ b/hedtools/tests/validator/test_event_validator.py
@@ -56,25 +56,25 @@ def test__validate_input(self):
         validation_issues = self.generic_hed_input_reader.validate_input(self.base_hed_input)
         self.assertIsInstance(validation_issues, list)
 
-        display_filename = "DummyDisplayFilename.txt"
+        name = "DummyDisplayFilename.txt"
         validation_issues = self.generic_hed_input_reader.validate_input(self.hed_file_with_errors,
-                                                                         display_filename=display_filename)
+                                                                         name=name)
         self.assertIsInstance(validation_issues, list)
-        self.assertTrue(display_filename in validation_issues[0][ErrorContext.FILE_NAME])
+        self.assertTrue(name in validation_issues[0][ErrorContext.FILE_NAME])
 
     def test__validate_input_major_errors(self):
-        display_filename = "DummyDisplayFilename.txt"
+        name = "DummyDisplayFilename.txt"
         validation_issues = self.generic_hed_input_reader.validate_input(self.hed_file_with_major_errors,
-                                                                         display_filename=display_filename)
+                                                                         name=name)
         self.assertIsInstance(validation_issues, list)
-        self.assertTrue(display_filename in validation_issues[0][ErrorContext.FILE_NAME])
+        self.assertTrue(name in validation_issues[0][ErrorContext.FILE_NAME])
 
     def test__validate_input_major_errors_columns(self):
-        display_filename = "DummyDisplayFilename.txt"
+        name = "DummyDisplayFilename.txt"
         validation_issues = self.generic_hed_input_reader2.validate_input(self.hed_file_with_major_errors_multi_column,
-                                                                         display_filename=display_filename)
+                                                                         name=name)
         self.assertIsInstance(validation_issues, list)
-        self.assertTrue(display_filename in validation_issues[0][ErrorContext.FILE_NAME])
+        self.assertTrue(name in validation_issues[0][ErrorContext.FILE_NAME])
 
     def test__validate_individual_tags_in_hed_string(self):
         validation_issues = self.generic_hed_input_reader._validate_individual_tags_in_hed_string(self.hed_string_with_invalid_tags)
@@ -124,10 +124,8 @@ def test_complex_file_validation(self):
         hed_schema = schema.load_schema(schema_path)
         json_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../data/bids_events.json")
         column_group = ColumnDefGroup(json_path)
-        def_dict = column_group.extract_defs()
-        self.assertEqual(len(def_dict.get_def_issues(hed_schema=hed_schema)), 0)
-        input_file = EventsInput(events_path, json_def_files=column_group,
-                                 def_dicts=def_dict)
+        self.assertEqual(len(column_group.validate_entries(hed_schema=hed_schema)), 0)
+        input_file = EventsInput(events_path, json_def_files=column_group)
 
         validation_issues = input_file.validate_file_sidecars(hed_schema=hed_schema)
         self.assertEqual(len(validation_issues), 0)
@@ -143,13 +141,11 @@ def test_complex_file_validation_invalid(self):
         hed_schema = schema.load_schema(schema_path)
         json_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../data/bids_events_bad_defs.json")
         column_group = ColumnDefGroup(json_path)
-        def_dict = column_group.extract_defs()
-        self.assertEqual(len(def_dict.get_def_issues(hed_schema=hed_schema)), 0)
-        input_file = EventsInput(events_path, json_def_files=column_group,
-                                 def_dicts=def_dict)
+        self.assertEqual(len(column_group.validate_entries()), 0)
+        input_file = EventsInput(events_path, json_def_files=column_group)
 
         validation_issues = input_file.validate_file_sidecars(hed_schema=hed_schema)
-        self.assertEqual(len(validation_issues), 1)
+        self.assertEqual(len(validation_issues), 3)
 
         validator = EventValidator(hed_schema=hed_schema)
         validation_issues = validator.validate_input(input_file)
@@ -176,7 +172,7 @@ def test_error_spans_from_file(self):
 
         hed_schema = schema.load_schema(schema_path)
 
-        input_file = EventsInput(events_path, tag_columns=[2, 3])
+        input_file = HedInput(events_path, tag_columns=[2, 3, "error"])
         validator = EventValidator(hed_schema=hed_schema)
         validation_issues = validator.validate_input(input_file)
         self.assertEqual(validation_issues[0]['char_index'], 6)