Source code for remodeler.operations.factor_hed_tags_op

"""Append columns of factors based on column values to a columnar file."""

import pandas as pd
from remodeler.operations.base_op import BaseOp
from hed.models.tabular_input import TabularInput
from hed.models.sidecar import Sidecar
from hed.models import query_service
from hed.tools.analysis.event_manager import EventManager
from hed.tools.analysis.hed_tag_manager import HedTagManager
from hed.tools.util.data_util import replace_na


[docs] class FactorHedTagsOp(BaseOp): """Append columns of factors based on column values to a columnar file. Required remodeling parameters: - **queries** (*list*): Queries to be applied successively as filters. Optional remodeling parameters: - **expand_context** (*bool*): Expand the context if True. - **query_names** (*list*): Column names for the query factors. - **remove_types** (*list*): Structural HED tags to be removed (such as Condition-variable or Task). - **expand_context** (*bool*): If true, expand the context based on Onset, Offset, and Duration. Notes: - If query names are not provided, *query1*, *query2*, ... are used. - If query names are provided, the list must have same list as the number of queries. - When the context is expanded, the effect of events for temporal extent is accounted for. """ NAME = "factor_hed_tags" PARAMS = { "type": "object", "properties": { "queries": { "type": "array", "description": "List of HED tag queries to compute one-hot factors for.", "items": {"type": "string"}, "minItems": 1, "uniqueItems": True, }, "query_names": { "type": "array", "description": "Optional column names for the queries.", "items": {"type": "string"}, "minItems": 1, "uniqueItems": True, }, "remove_types": { "type": "array", "descriptions": "List of type tags to remove from before querying (e.g., Condition-variable, Task).", "items": {"type": "string"}, "minItems": 1, "uniqueItems": True, }, "expand_context": { "type": "boolean", "description": "If true, the assembled HED tags include the effects of temporal extent (e.g., Onset).", }, "replace_defs": { "type": "boolean", "description": "If true, Def tags are replaced with definition contents.", }, }, "required": ["queries"], "additionalProperties": False, } def __init__(self, parameters): """Constructor for the factor HED tags operation. Parameters: parameters (dict): Actual values of the parameters for the operation. """ super().__init__(parameters) self.queries = parameters["queries"] self.remove_types = parameters.get("remove_types", []) self.expand_context = parameters.get("expand_context", True) self.replace_defs = parameters.get("replace_defs", True) self.query_handlers, self.query_names, issues = query_service.get_query_handlers( self.queries, parameters.get("query_names", None) ) if issues: raise ValueError("FactorHedTagInvalidQueries", "\n".join(issues))
[docs] def do_op(self, dispatcher, df, name, sidecar=None) -> pd.DataFrame: """Create factor columns based on HED tag queries. Parameters: dispatcher (Dispatcher): Manages the operation I/O. df (DataFrame): The DataFrame to be remodeled. name (str): Unique identifier for the dataframe -- often the original file path. sidecar (Sidecar or file-like): Only needed for HED operations. Returns: DataFrame: A new dataframe after processing. Raises: ValueError: If a name for a new query factor column is already a column. """ if sidecar and not isinstance(sidecar, Sidecar): sidecar = Sidecar(sidecar) input_data = TabularInput(df.copy().fillna("n/a"), sidecar=sidecar, name=name) column_names = list(df.columns) for query_name in self.query_names: if query_name in column_names: raise ValueError( "QueryNameAlreadyColumn", f"Query [{query_name}]: is already a column name of the data frame" ) df_list = [input_data.dataframe] tag_man = HedTagManager(EventManager(input_data, dispatcher.hed_schema), remove_types=self.remove_types) hed_objs = tag_man.get_hed_objs(include_context=self.expand_context, replace_defs=self.replace_defs) df_factors = query_service.search_hed_objs(hed_objs, self.query_handlers, query_names=self.query_names) if len(df_factors.columns) > 0: df_list.append(df_factors) df_new = pd.concat(df_list, axis=1) replace_na(df_new) return df_new
[docs] @staticmethod def validate_input_data(parameters) -> list: """Parse and valid the queries and return issues in parsing queries, if any. Parameters: parameters (dict): Dictionary representing the actual operation values. Returns: list: List of issues in parsing queries. """ queries, names, issues = query_service.get_query_handlers( parameters.get("queries", []), parameters.get("query_names", None) ) return issues