coco_pipe.descriptors.tables ============================ .. py:module:: coco_pipe.descriptors.tables .. autoapi-nested-parse:: Assemble descriptor extraction containers into epoch/subject feature tables. The descriptor lifecycle is **extract → reject → aggregate → merge**: * **extract** — :meth:`coco_pipe.descriptors.core.DescriptorPipeline.extract` returns a flat ``("obs", "feature")`` :class:`~coco_pipe.io.structures.DataContainer`. * **reject** — epoch MAD-outlier rejection is just :func:`coco_pipe.io.quality.drop_epoch_outliers` on that container; :func:`mad_failures_from_qc` turns the dropped epochs into failure records. * **aggregate** — :func:`build_descriptor_tables` builds the per-epoch table and the group-aggregated subject table (mean + extra grouped stats + optional band ratios) via :meth:`~coco_pipe.io.structures.DataContainer.aggregate` / :meth:`~coco_pipe.io.structures.DataContainer.aggregate_groups`. * **merge** — cross-shard concatenation lives in :func:`coco_pipe.descriptors.io.merge_descriptor_tables`. Project-specific concerns (BIDS grouping-key derivation, channel-group pooling, shard file layout, QC reports) stay with the caller. Author: Hamza Abdelhedi Functions --------- .. autoapisummary:: coco_pipe.descriptors.tables.mad_failures_from_qc coco_pipe.descriptors.tables.add_aggregated_band_ratios coco_pipe.descriptors.tables.build_descriptor_tables Module Contents --------------- .. py:function:: mad_failures_from_qc(qc_result) Turn epochs dropped by :func:`drop_epoch_outliers` into failure records. Mirrors the extractor failure schema (``obs_id``, ``obs_index``, ``channel_index``, ``channel_name``, ``family``, ``exception_type``, ``message``) so MAD drops flow into the same failure log as extraction failures. When rejection was made per descriptor group, one record is emitted per (group, epoch); otherwise one per dropped epoch. :param qc_result: The :class:`~coco_pipe.io.quality.QCResult` returned by :func:`coco_pipe.io.quality.drop_epoch_outliers` (``None`` yields ``[]``). .. py:function:: add_aggregated_band_ratios(base_features_df, ratio_pairs, floor = 0.0, prefixes = DEFAULT_RATIO_PREFIXES) Compute band-ratio columns from aggregated mean band-power features. For each ``(numerator, denominator)`` band pair and each ``(input_prefix, output_prefix)`` in *prefixes*, divide every matching ``{input_prefix}{numerator}_{suffix}`` column by its ``{input_prefix}{denominator}_{suffix}`` counterpart. Denominators at or below *floor* yield ``NaN`` instead of an unstable division. :returns: One column per emitted ratio (empty when nothing matched). Aligned to *base_features_df*'s row index. :rtype: pandas.DataFrame .. py:function:: build_descriptor_tables(container, metadata_df, group_by, id_col = 'obs_id', target_col = None, aggregation_groups = None, ratio_pairs = None, ratio_floor = 0.0, ratio_prefixes = DEFAULT_RATIO_PREFIXES, min_count = 1, on_insufficient = 'raise') Build epoch- and group-aggregated subject-level descriptor tables. :param container: Flat ``("obs", "feature")`` descriptor container from :meth:`~coco_pipe.descriptors.core.DescriptorPipeline.extract` (typically after epoch MAD rejection). :param metadata_df: One row per epoch, aligned with ``container.X``. Must contain *id_col*; every other column is carried as an observation coordinate and, when constant within a group, into the subject table. :param group_by: Metadata column defining the aggregation groups (e.g. a recording id). :param id_col: Observation-id column in *metadata_df* (default ``"obs_id"``). :param target_col: Optional target column carried onto the subject table. :param aggregation_groups: ``aggregate_groups`` specs producing the subject feature columns (each ``{"stats": ..., }``). Defaults to ``[{"stats": "mean"}]`` (mean of every feature). This is where median / IQR / etc. subject-level stats are requested. :param ratio_pairs: When *ratio_pairs* is given, band ratios from the aggregated mean features are appended via :func:`add_aggregated_band_ratios`. :param ratio_floor: When *ratio_pairs* is given, band ratios from the aggregated mean features are appended via :func:`add_aggregated_band_ratios`. :param ratio_prefixes: When *ratio_pairs* is given, band ratios from the aggregated mean features are appended via :func:`add_aggregated_band_ratios`. :param min_count: Forwarded to :meth:`~coco_pipe.io.structures.DataContainer.aggregate` and ``aggregate_groups``. With ``on_insufficient="warn"`` a group (or a single descriptor family within ``aggregate_groups``) whose surviving rows are all-NaN emits NaN features instead of raising, so the subject is retained with whatever else is computable. :param on_insufficient: Forwarded to :meth:`~coco_pipe.io.structures.DataContainer.aggregate` and ``aggregate_groups``. With ``on_insufficient="warn"`` a group (or a single descriptor family within ``aggregate_groups``) whose surviving rows are all-NaN emits NaN features instead of raising, so the subject is retained with whatever else is computable. :returns: ``epoch_df``, ``subject_df``, ``epoch_feature_columns``, and ``subject_feature_columns``. :rtype: dict :raises ValueError: If *id_col* or *group_by* is missing from *metadata_df*.