From fee5b28ee4eccff1ebd4b6ebcc819cb00d34acef Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Thu, 14 Jul 2022 19:29:59 -0500 Subject: [PATCH 001/143] Started the remodelling tools documentation pages --- docs/source/DesignMatricesWithHed.md | 171 ++++++++++ docs/source/EventRestructuring.md | 125 +++++++ docs/source/HedRemodelingTools.md | 305 ++++++++++++++++++ docs/source/HedSearchingAndSummary.md | 171 ++++++++++ .../bids_validate_dataset.ipynb | 4 +- ...bids_validate_dataset_with_libraries.ipynb | 2 +- .../matlab_scripts/web_services/runAllTests.m | 1 + 7 files changed, 776 insertions(+), 3 deletions(-) create mode 100644 docs/source/DesignMatricesWithHed.md create mode 100644 docs/source/EventRestructuring.md create mode 100644 docs/source/HedRemodelingTools.md create mode 100644 docs/source/HedSearchingAndSummary.md diff --git a/docs/source/DesignMatricesWithHed.md b/docs/source/DesignMatricesWithHed.md new file mode 100644 index 0000000..99471e0 --- /dev/null +++ b/docs/source/DesignMatricesWithHed.md @@ -0,0 +1,171 @@ +# Event restructuring + + + +This tutorial takes you through the steps of annotating the events +using HED (Hierarchical Event Descriptors). +The tutorial focuses on how to make good choices of HED annotations +to make your data usable for downstream analysis. +The mechanics of putting your selected HED annotations into +[BIDS (Brain Imaging Data Structure)](https://bids.neuroimaging.io/) format +is covered in the [**BIDS annotation quickstart**](./BidsAnnotationQuickstart.md) guide. + +* [**What is HED annotation?**](what-is-hed-annotation-anchor) +* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) + +(what-is-hed-annotation-anchor)= +## What is HED annotation? + +A HED annotation consists of a comma separated list of tags selected from +a HED vocabulary or schema. +An important reason for using an agreed-upon vocabulary rather than +free-form tagging for annotation is to avoid confusion and ambiguity +and to promote data-sharing. + +The basic terms are organized into trees for easier access and search. +The [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) allows +you to explore these terms. + +(a-recipe-for-simple-annotation-anchor)= +## A recipe for simple annotation +In thinking about how to annotate an event, you should always start +by selecting a tag from the *Event* subtree to indicate the general event category. +Possible choices are: *Sensory-event*, *Agent-action*, *Data-feature*, *Experiment-control*, +*Experiment-procedure*, *Experiment-structure*, and *Measurement-event*. +See the [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) +to view the available tags. + +Most experiments will only have a few types of distinct events. +The simplest way to create a minimal HED annotation for your events is: + +1. Select one of the 7 tags from the *Event* subtree to designate the general category of the event. +2. Use the following table to select the appropriate supporting tags given that event type. + +(standard-hed-tag-selections-anchor)= +```{admonition} Standard HED tag selections for minimal annotation. +:class: tip + +| Event tag | Support tag type | Example tags | Reason | +| ------------- | -------------------- | ------------ | ------ | +| **Sensory-event** | *Sensory-presentation* | *Visual-presentation*
*Auditory-presentation*| Which sense? | +| | *Task-event-role* | *Experimental-stimulus*
*Instructional* | What task role? | +| | *Task-stimulus-role* | *Cue*
*Target* | Stimulus purpose? | +| | *Item* | *(Face, Image)*
*Siren* | What is presented? | +| | *Sensory-attribute* | *Red* | What modifiers are needed? | +| **Agent-action** | *Agent-task-role* | *Experiment-participant* | Who is agent? | +| | *Action* | *Move*
*Press* | What action is performed? | +| | *Task-action-type* | *Appropriate-action*
*Near-miss* | What task relationship? | +| | *Item* | *Arm*
*Mouse-button* | What is action target? | +| **Data-feature** | *Data-source-type* | *Expert-annotation*
*Computed-feature* | Where did the feature come from? | +| | *Label* | *Label/Blinker_BlinkMax* | Tool name?
Feature type? | +| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | Feature value or type? | +| **Experiment-control** | *Agent* | *Controller-Agent* | What is the controller? | +| | *Informational* | *Label/Stop-recording* | What did the controller do? | +| **Experiment-procedure** | *Task-event-role* | *Task-activity* | What procedure? | +| **Experiment-structure** | *Organizational-property* | *Time-block*
*Condition-variable* | What structural property? | +| **Measurement-event** | *Data-source-type* | *Instrument-measurement*
*Observation* | Source of the data. | +| | *Label* | *Label/Oximeter_O2Level* | Instrument name?
Measurement type? | +| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | What value or type? +``` + + +As in BIDS, we assume that the event metadata is given in tabular form. +Each table row represents the metadata associated with a single data event marker, +as shown in the following excerpt of the `events.tsv` file for a simple Go/No-go experiment. +The `onset` column gives the time in seconds of the marker relative +to the beginning of the associated data file. + +(example-go-no-go-event-table-anchor)= +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + +In the Go/No-go experiment, the experimental participant is presented +with a series of target and distractor animal images. +The participant is instructed to lift a finger off a button +when a target animal image appears. +Since in this experiment, the `value` column has distinct values +for all possible unique event types, the `event_type` column is redundant. +In this case, we can choose to assign all the annotations to +the `value` column as demonstrated in the following example. + +````{admonition} Version 1: Assigning all annotations to the value column. + +| value | Event category | Supporting tags | +| ------- | -------------- | --------------- | +| animal_target | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | +| animal_distractor | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Non-target*, *Distractor*, (*Animal*, *Image*) | +| correct_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Correct-action* | +| incorrect_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Incorrect-action* | + +```` + +The table above shows the event category and the supporting tags as suggested in the +[**Standard hed tags for minimal annotation**](standard-hed-tag-selections-anchor) table. + +A better format for your annotations is the +[**4-column spreadsheet format**](four-column-spreadsheet-format-anchor) described in +[**BIDS annotation quickstart**](BidsAnnotationQuickstart.md), since there are online +tools to convert this format into a JSON sidecar that can be deployed directly in +a BIDS dataset. + +````{admonition} 4-column spreadsheet format for the previous example. + +| column_name| column_value | description | HED | +| ------- | -------------- | ----------- | ------- | +| value | animal_target | An target animal image was
presented on a screen. |*Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | +| value | animal_distractor | A non-target animal distractor
image was presented
on a screen. | *Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*, *Non-target*,
*Distractor*, (*Animal*, *Image*)| +| value | correct_response | Participant correctly
lifted finger off button. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Correct-action* | +| value | incorrect_response | Participant lifted finger off
the button but should not have. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Incorrect-action* | + +```` + +HED tools assemble the annotations for each event into a single HED tag string. +An exactly equivalent version of the previous example splits the HED tag annotation between +the `event_type` and `value` columns as shown in the next example. + +````{admonition} Version 2: Assigning annotations to multiple event file columns. + +| column_name | column_value | description | HED | +| ------- | -------------- | --------------- | ------ | +| event_type | stimulus | An image of an animal
was presented on a
computer screen.| *Sensory-event*,
*Visual-presentation*,
*experimental-stimulus* | +| event_type | response | Participant lifted finger
off button.| *Agent-action*,
*Experiment-participant*,
(*Lift*, *Finger*) | +| value | animal_target | A target animal image. | *Target*, (*Animal*, *Image*) | +| value | animal_distractor | A non-target animal image
meant as a distractor. | *Non-target*, *Distractor*,
(*Animal*, *Image*) | +| value | correct_response | The previous stimulus
was a target animal. | *Correct-action* | +| value | incorrect_response | The previous stimulus
was not a target animal. | *Incorrect-action* | +| stim_file | n/a | Filename of stimulus image. | (*Image*, *Pathname/#*) | +```` +In version 2, the annotations that are common +to all stimuli and responses are assigned to `event_type`. +We have also included the annotation for the `stim_file` column in the last row +of this table. + +The assembled annotation for the first event (with onset 5.035) in the +[**event file excerpt from go/no-go**](example-go-no-go-event-table-anchor) above is: + +> *Sensory-event*, *Visual-presentation*, *Experimental-stimulus*, *Target*, (*Animal*, *Image*), (*Image*, *Pathname/105064.jpg*) + +Mapping annotations and column information across multiple column values often makes +the annotation process simpler, especially when annotations become more complex. +Multiple column representation also can make analysis easier, +particularly if the columns represent information such as design variables. + +See [**BIDS annotation quick start**](BidsAnnotationQuickstart.md#bids-annotation-quickstart) for how to +create templates to fill in with your annotations using online tools. +Once you have completed the annotation and converted it to a sidecar, +you simply need to place this sidecar in the root directory of your BIDS dataset. + +This quick start demonstrates the most basic HED annotations. +HED is capable of much more extensive and expressive annotations as +explained in a series of tutorials on this site. \ No newline at end of file diff --git a/docs/source/EventRestructuring.md b/docs/source/EventRestructuring.md new file mode 100644 index 0000000..42c7553 --- /dev/null +++ b/docs/source/EventRestructuring.md @@ -0,0 +1,125 @@ +# Event restructuring + +This tutorial works through the process of restructuring event files using the HED event remodeling tools. The tools are designed to be run on an entire BIDS dataset. + +* [**What is HED annotation?**](what-is-hed-annotation-anchor) +* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) + +(what-is-event-restructuring-anchor)= +## What is event restructuring? + + +(a-recipe-for-simple-annotation-anchor)= +## Installation and running of the restructuring + + +(standard-hed-tag-selections-anchor)= +```{admonition} Standard HED tag selections for minimal annotation. +:class: tip + +| Event tag | Support tag type | Example tags | Reason | +| ------------- | -------------------- | ------------ | ------ | +| **Sensory-event** | *Sensory-presentation* | *Visual-presentation*
*Auditory-presentation*| Which sense? | +``` + + +As in BIDS, we assume that the event metadata is given in tabular form. +Each table row represents the metadata associated with a single data event marker, +as shown in the following excerpt of the `events.tsv` file for a simple Go/No-go experiment. +The `onset` column gives the time in seconds of the marker relative +to the beginning of the associated data file. + +(example-go-no-go-event-table-anchor)= +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + +In the Go/No-go experiment, the experimental participant is presented +with a series of target and distractor animal images. +The participant is instructed to lift a finger off a button +when a target animal image appears. +Since in this experiment, the `value` column has distinct values +for all possible unique event types, the `event_type` column is redundant. +In this case, we can choose to assign all the annotations to +the `value` column as demonstrated in the following example. + +````{admonition} Version 1: Assigning all annotations to the value column. + +| value | Event category | Supporting tags | +| ------- | -------------- | --------------- | +| animal_target | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | +| animal_distractor | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Non-target*, *Distractor*, (*Animal*, *Image*) | +| correct_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Correct-action* | +| incorrect_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Incorrect-action* | + +```` + +The table above shows the event category and the supporting tags as suggested in the +[**Standard hed tags for minimal annotation**](standard-hed-tag-selections-anchor) table. + +A better format for your annotations is the +[**4-column spreadsheet format**](four-column-spreadsheet-format-anchor) described in +[**BIDS annotation quickstart**](BidsAnnotationQuickstart.md), since there are online +tools to convert this format into a JSON sidecar that can be deployed directly in +a BIDS dataset. + +````{admonition} 4-column spreadsheet format for the previous example. + +| column_name| column_value | description | HED | +| ------- | -------------- | ----------- | ------- | +| value | animal_target | An target animal image was
presented on a screen. |*Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | +| value | animal_distractor | A non-target animal distractor
image was presented
on a screen. | *Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*, *Non-target*,
*Distractor*, (*Animal*, *Image*)| +| value | correct_response | Participant correctly
lifted finger off button. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Correct-action* | +| value | incorrect_response | Participant lifted finger off
the button but should not have. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Incorrect-action* | + +```` + +HED tools assemble the annotations for each event into a single HED tag string. +An exactly equivalent version of the previous example splits the HED tag annotation between +the `event_type` and `value` columns as shown in the next example. + +````{admonition} Version 2: Assigning annotations to multiple event file columns. + +| column_name | column_value | description | HED | +| ------- | -------------- | --------------- | ------ | +| event_type | stimulus | An image of an animal
was presented on a
computer screen.| *Sensory-event*,
*Visual-presentation*,
*experimental-stimulus* | +| event_type | response | Participant lifted finger
off button.| *Agent-action*,
*Experiment-participant*,
(*Lift*, *Finger*) | +| value | animal_target | A target animal image. | *Target*, (*Animal*, *Image*) | +| value | animal_distractor | A non-target animal image
meant as a distractor. | *Non-target*, *Distractor*,
(*Animal*, *Image*) | +| value | correct_response | The previous stimulus
was a target animal. | *Correct-action* | +| value | incorrect_response | The previous stimulus
was not a target animal. | *Incorrect-action* | +| stim_file | n/a | Filename of stimulus image. | (*Image*, *Pathname/#*) | +```` +In version 2, the annotations that are common +to all stimuli and responses are assigned to `event_type`. +We have also included the annotation for the `stim_file` column in the last row +of this table. + +The assembled annotation for the first event (with onset 5.035) in the +[**event file excerpt from go/no-go**](example-go-no-go-event-table-anchor) above is: + +> *Sensory-event*, *Visual-presentation*, *Experimental-stimulus*, *Target*, (*Animal*, *Image*), (*Image*, *Pathname/105064.jpg*) + +Mapping annotations and column information across multiple column values often makes +the annotation process simpler, especially when annotations become more complex. +Multiple column representation also can make analysis easier, +particularly if the columns represent information such as design variables. + +See [**BIDS annotation quick start**](BidsAnnotationQuickstart.md#bids-annotation-quickstart) for how to +create templates to fill in with your annotations using online tools. +Once you have completed the annotation and converted it to a sidecar, +you simply need to place this sidecar in the root directory of your BIDS dataset. + +This quick start demonstrates the most basic HED annotations. +HED is capable of much more extensive and expressive annotations as +explained in a series of tutorials on this site. \ No newline at end of file diff --git a/docs/source/HedRemodelingTools.md b/docs/source/HedRemodelingTools.md new file mode 100644 index 0000000..9969e29 --- /dev/null +++ b/docs/source/HedRemodelingTools.md @@ -0,0 +1,305 @@ +# HED remodeling tools + +This tutorial works through the process of restructuring event files using the HED event remodeling tools. The tools are designed to be run on an entire BIDS dataset. + +* [**What is HED annotation?**](what-is-hed-annotation-anchor) +* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) + +(what-is-event-restructuring-anchor)= +## What is event restructuring? + + +(a-recipe-for-simple-annotation-anchor)= +## Installation and running of the restructuring + +(remodeling-operations)= +## Remodeling operations + + +### Add structure + +Use: Add trial or block markers --- used for epoching around the start of a trial. The duration is the duration of the trial or block respectively. + + + +### Add trial numbers +Add a column with the trial numbers. + + + +### Derive column + +Create a new column or overwrite values in an existing column using a mapping from existing columns. Can also be used to overwrite values on existing columns, only values with the predefined combinations will be overwritten. + + +(parameters-for-derive-column-anchor)= +```{admonition} Standard HED tag selections for minimal annotation. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list of str | A list of columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` +The following example .... + +```json +{ + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } +} +``` +Results in the following: + +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + + +### Factor column + +Factor each of the specified values in the indicated column into a column containing 1’s and 0’s indicating presence and absence. If no values are specified, all unique values in that column are factored. + +### Factor HED + +Produce a list of factor columns based on the specified HED condition-variable values. + +### Merge events +One long event is represented by multiple repeat events. Merges these same events occurring consecutively into one event with duration of the new event updated as the sum of all merged events. + +### Remove columns + +Remove the specified columns if present. + + +(parameters-for-remove-columns-anchor)= +```{admonition} Parameters for the remove_columns operation. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_names | list of str | A list of columns to remove.| +``` + +Example command: +```json +{ + "column_names": ["sample", "ethn_target", "ethn_distractor"] +} +``` + +```{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + +### Remove rows + +Remove rows where specified columns take particular values. + +(parameters-for-remove-rows-anchor)= +```{admonition} Standard HED tag selections for minimal annotation. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list of str | A list of columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` +The following example .... + +```json +{ + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } +} +``` +Results in the following: + +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + +### Rename columns + +Rename columns by providing old name and new name. + +(parameters-for-rename-columns-anchor)= +```{admonition} Parameters for rename_columns. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| mapping | dict | The keys are the old column names and the values are the new names.| +| ignore_missing | bool | If false, an error is thrown if any keys are missing. | + +``` +The following example .... + +```json +{ + "mapping": { + "face_type": "xxx", + "hand": "response_hand" + }, + "ignore_missing": true +} + +``` +Results in the following: + +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + +### Reorder columns + +Reorder the columns in the specified order. Columns not included are discarded or placed at the end. If a specified column is not in the data --- do what? + +(parameters-for-reorder-columns-anchor)= +```{admonition} Parameters for reorder_columns. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_names | list of str | A list of columns in the order they should appear in the data.| +| keep_missing | boolean | If true, existing columns that aren't in column_names are moved to the end and in the same relative order that they originally appeared in the data. | + +``` + + +```json +{ + "column_names": ["onset", "duration", "trial_type", "response_time"], + "keep_missing": false +} +``` + +Results in the following: + +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + +### Split event + +The split_event is the most complicated of the remodeling operations and generally +Multiple information and responses are encoded in a single event. Split this event into multiple lines in the event file and adjust the meanings of the columns — usually this means removing the original event and replacing it with new events at various offsets. +The final result has rows ordered by increasing offsets. + +Rename columns by providing old name and new name. + +(parameters-for-split-event-anchor)= +```{admonition} Parameters for split_event. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column that will be used for split-event codes.| +| split_dict | dict | Dictionary specifying how the split should occur. | +|remove_parent_event | bool | If true, remove parent event. | + +``` + +The `column_name` is the column that the split event codes are written. +If this column does not exist in the `events.tsv` file it is added prior to the split processing. + +(parameters-for-split-dict-anchor)= +```{admonition} values for split_dict. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| onset_source | list | A list of column names and numbers representing values added to the onset of the parent event.| +| split_dict | dict | Dictionary specifying how the split should occur. | +|remove_parent_event | bool | If true, remove parent event. | + +``` + +The +The following example .... + +```json +{ + "mapping": { + "face_type": "xxx", + "hand": "response_hand" + }, + "ignore_missing": true +} + +``` +Results in the following: + +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` diff --git a/docs/source/HedSearchingAndSummary.md b/docs/source/HedSearchingAndSummary.md new file mode 100644 index 0000000..99471e0 --- /dev/null +++ b/docs/source/HedSearchingAndSummary.md @@ -0,0 +1,171 @@ +# Event restructuring + + + +This tutorial takes you through the steps of annotating the events +using HED (Hierarchical Event Descriptors). +The tutorial focuses on how to make good choices of HED annotations +to make your data usable for downstream analysis. +The mechanics of putting your selected HED annotations into +[BIDS (Brain Imaging Data Structure)](https://bids.neuroimaging.io/) format +is covered in the [**BIDS annotation quickstart**](./BidsAnnotationQuickstart.md) guide. + +* [**What is HED annotation?**](what-is-hed-annotation-anchor) +* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) + +(what-is-hed-annotation-anchor)= +## What is HED annotation? + +A HED annotation consists of a comma separated list of tags selected from +a HED vocabulary or schema. +An important reason for using an agreed-upon vocabulary rather than +free-form tagging for annotation is to avoid confusion and ambiguity +and to promote data-sharing. + +The basic terms are organized into trees for easier access and search. +The [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) allows +you to explore these terms. + +(a-recipe-for-simple-annotation-anchor)= +## A recipe for simple annotation +In thinking about how to annotate an event, you should always start +by selecting a tag from the *Event* subtree to indicate the general event category. +Possible choices are: *Sensory-event*, *Agent-action*, *Data-feature*, *Experiment-control*, +*Experiment-procedure*, *Experiment-structure*, and *Measurement-event*. +See the [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) +to view the available tags. + +Most experiments will only have a few types of distinct events. +The simplest way to create a minimal HED annotation for your events is: + +1. Select one of the 7 tags from the *Event* subtree to designate the general category of the event. +2. Use the following table to select the appropriate supporting tags given that event type. + +(standard-hed-tag-selections-anchor)= +```{admonition} Standard HED tag selections for minimal annotation. +:class: tip + +| Event tag | Support tag type | Example tags | Reason | +| ------------- | -------------------- | ------------ | ------ | +| **Sensory-event** | *Sensory-presentation* | *Visual-presentation*
*Auditory-presentation*| Which sense? | +| | *Task-event-role* | *Experimental-stimulus*
*Instructional* | What task role? | +| | *Task-stimulus-role* | *Cue*
*Target* | Stimulus purpose? | +| | *Item* | *(Face, Image)*
*Siren* | What is presented? | +| | *Sensory-attribute* | *Red* | What modifiers are needed? | +| **Agent-action** | *Agent-task-role* | *Experiment-participant* | Who is agent? | +| | *Action* | *Move*
*Press* | What action is performed? | +| | *Task-action-type* | *Appropriate-action*
*Near-miss* | What task relationship? | +| | *Item* | *Arm*
*Mouse-button* | What is action target? | +| **Data-feature** | *Data-source-type* | *Expert-annotation*
*Computed-feature* | Where did the feature come from? | +| | *Label* | *Label/Blinker_BlinkMax* | Tool name?
Feature type? | +| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | Feature value or type? | +| **Experiment-control** | *Agent* | *Controller-Agent* | What is the controller? | +| | *Informational* | *Label/Stop-recording* | What did the controller do? | +| **Experiment-procedure** | *Task-event-role* | *Task-activity* | What procedure? | +| **Experiment-structure** | *Organizational-property* | *Time-block*
*Condition-variable* | What structural property? | +| **Measurement-event** | *Data-source-type* | *Instrument-measurement*
*Observation* | Source of the data. | +| | *Label* | *Label/Oximeter_O2Level* | Instrument name?
Measurement type? | +| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | What value or type? +``` + + +As in BIDS, we assume that the event metadata is given in tabular form. +Each table row represents the metadata associated with a single data event marker, +as shown in the following excerpt of the `events.tsv` file for a simple Go/No-go experiment. +The `onset` column gives the time in seconds of the marker relative +to the beginning of the associated data file. + +(example-go-no-go-event-table-anchor)= +````{admonition} Event file from a simple Go/No-go experiment. + +| onset | duration | event_type | value | stim_file | +| ----- | -------- | ---------- | ----- | --------- | +| 5.035 | n/a | stimulus | animal_target | 105064.jpg | +| 5.370 | n/a | response | correct_response | n/a | +| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | +| 8.651 | n/a | stimulus | animal_target | 136095.jpg | +| 8.940 | n/a | response | correct_response | n/a | +| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | +| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | +| 12.943 | n/a | response | incorrect_response | n/a | +```` + +In the Go/No-go experiment, the experimental participant is presented +with a series of target and distractor animal images. +The participant is instructed to lift a finger off a button +when a target animal image appears. +Since in this experiment, the `value` column has distinct values +for all possible unique event types, the `event_type` column is redundant. +In this case, we can choose to assign all the annotations to +the `value` column as demonstrated in the following example. + +````{admonition} Version 1: Assigning all annotations to the value column. + +| value | Event category | Supporting tags | +| ------- | -------------- | --------------- | +| animal_target | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | +| animal_distractor | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Non-target*, *Distractor*, (*Animal*, *Image*) | +| correct_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Correct-action* | +| incorrect_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Incorrect-action* | + +```` + +The table above shows the event category and the supporting tags as suggested in the +[**Standard hed tags for minimal annotation**](standard-hed-tag-selections-anchor) table. + +A better format for your annotations is the +[**4-column spreadsheet format**](four-column-spreadsheet-format-anchor) described in +[**BIDS annotation quickstart**](BidsAnnotationQuickstart.md), since there are online +tools to convert this format into a JSON sidecar that can be deployed directly in +a BIDS dataset. + +````{admonition} 4-column spreadsheet format for the previous example. + +| column_name| column_value | description | HED | +| ------- | -------------- | ----------- | ------- | +| value | animal_target | An target animal image was
presented on a screen. |*Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | +| value | animal_distractor | A non-target animal distractor
image was presented
on a screen. | *Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*, *Non-target*,
*Distractor*, (*Animal*, *Image*)| +| value | correct_response | Participant correctly
lifted finger off button. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Correct-action* | +| value | incorrect_response | Participant lifted finger off
the button but should not have. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Incorrect-action* | + +```` + +HED tools assemble the annotations for each event into a single HED tag string. +An exactly equivalent version of the previous example splits the HED tag annotation between +the `event_type` and `value` columns as shown in the next example. + +````{admonition} Version 2: Assigning annotations to multiple event file columns. + +| column_name | column_value | description | HED | +| ------- | -------------- | --------------- | ------ | +| event_type | stimulus | An image of an animal
was presented on a
computer screen.| *Sensory-event*,
*Visual-presentation*,
*experimental-stimulus* | +| event_type | response | Participant lifted finger
off button.| *Agent-action*,
*Experiment-participant*,
(*Lift*, *Finger*) | +| value | animal_target | A target animal image. | *Target*, (*Animal*, *Image*) | +| value | animal_distractor | A non-target animal image
meant as a distractor. | *Non-target*, *Distractor*,
(*Animal*, *Image*) | +| value | correct_response | The previous stimulus
was a target animal. | *Correct-action* | +| value | incorrect_response | The previous stimulus
was not a target animal. | *Incorrect-action* | +| stim_file | n/a | Filename of stimulus image. | (*Image*, *Pathname/#*) | +```` +In version 2, the annotations that are common +to all stimuli and responses are assigned to `event_type`. +We have also included the annotation for the `stim_file` column in the last row +of this table. + +The assembled annotation for the first event (with onset 5.035) in the +[**event file excerpt from go/no-go**](example-go-no-go-event-table-anchor) above is: + +> *Sensory-event*, *Visual-presentation*, *Experimental-stimulus*, *Target*, (*Animal*, *Image*), (*Image*, *Pathname/105064.jpg*) + +Mapping annotations and column information across multiple column values often makes +the annotation process simpler, especially when annotations become more complex. +Multiple column representation also can make analysis easier, +particularly if the columns represent information such as design variables. + +See [**BIDS annotation quick start**](BidsAnnotationQuickstart.md#bids-annotation-quickstart) for how to +create templates to fill in with your annotations using online tools. +Once you have completed the annotation and converted it to a sidecar, +you simply need to place this sidecar in the root directory of your BIDS dataset. + +This quick start demonstrates the most basic HED annotations. +HED is capable of much more extensive and expressive annotations as +explained in a series of tutorials on this site. \ No newline at end of file diff --git a/hedcode/jupyter_notebooks/bids_validate_dataset.ipynb b/hedcode/jupyter_notebooks/bids_validate_dataset.ipynb index 3dc2f79..08f359d 100644 --- a/hedcode/jupyter_notebooks/bids_validate_dataset.ipynb +++ b/hedcode/jupyter_notebooks/bids_validate_dataset.ipynb @@ -53,8 +53,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using HEDTOOLS version: {'date': '2022-06-20T14:40:24-0500', 'dirty': False, 'error': None, 'full-revisionid': 'c4ecd1834cd31a05ebad3e97dc57e537550da044', 'version': '0.1.0'}\n", - "HED Examples version: {'version': '0+untagged.233.ge70e761.dirty', 'full-revisionid': 'e70e761ea596de4fbebe926e1274ec64d85db4f1', 'dirty': True, 'error': None, 'date': '2022-06-20T11:11:00-0500'}\n", + "Using HEDTOOLS version: {'date': '2022-07-05T18:08:32-0500', 'dirty': True, 'error': None, 'full-revisionid': '63fc2f3a91c897d6c6d7ad163c33d80145b472cc', 'version': '0.1.0+38.g63fc2f3.dirty'}\n", + "HED Examples version: {'version': '0.1.0+0.gf9bf968.dirty', 'full-revisionid': 'f9bf968253e528ef49ad3b066d87f05bfefc8bc8', 'dirty': True, 'error': None, 'date': '2022-06-21T09:41:35-0500'}\n", "BIDS path is: ../../datasets/eeg_ds003654s_hed\n", "No HED validation errors\n", "BIDS path is: ../../datasets/eeg_ds003654s_hed_column\n", diff --git a/hedcode/jupyter_notebooks/bids_validate_dataset_with_libraries.ipynb b/hedcode/jupyter_notebooks/bids_validate_dataset_with_libraries.ipynb index 4d91a60..8546104 100644 --- a/hedcode/jupyter_notebooks/bids_validate_dataset_with_libraries.ipynb +++ b/hedcode/jupyter_notebooks/bids_validate_dataset_with_libraries.ipynb @@ -53,7 +53,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Handling a BIDS data set that uses library schema: ../../../datasets/eeg_ds003654s_hed_library\n", + "Handling a BIDS data set that uses library schema: ../../datasets/eeg_ds003654s_hed_library\n", "No HED validation errors\n", "\n", "Now validating with the prerelease schema.\n", diff --git a/hedcode/matlab_scripts/web_services/runAllTests.m b/hedcode/matlab_scripts/web_services/runAllTests.m index 1e5d415..a26c179 100644 --- a/hedcode/matlab_scripts/web_services/runAllTests.m +++ b/hedcode/matlab_scripts/web_services/runAllTests.m @@ -1,4 +1,5 @@ host = 'https://hedtools.ucsd.edu/hed'; +host = 'http://127.0.0.1:5000/'; errorMap = containers.Map('KeyType', 'char', 'ValueType', 'any'); errorMap('testGetServices') = testGetServices(host); errorMap('testEventServices') = testEventServices(host); From dc922c2bf0f9e640321fa73e2016dfd3a53cb615 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Thu, 21 Jul 2022 14:00:28 -0500 Subject: [PATCH 002/143] Started working on documentation for the HED remodeling tools --- docs/source/EventRestructuring.md | 125 ---- ...y.md => HedConditionsAndDesignMatrices.md} | 4 +- docs/source/HedRemodelingTools.md | 678 ++++++++++++++---- ...ricesWithHed.md => HedSearchAndSummary.md} | 4 +- docs/source/index.rst | 9 + 5 files changed, 536 insertions(+), 284 deletions(-) delete mode 100644 docs/source/EventRestructuring.md rename docs/source/{HedSearchingAndSummary.md => HedConditionsAndDesignMatrices.md} (97%) rename docs/source/{DesignMatricesWithHed.md => HedSearchAndSummary.md} (97%) diff --git a/docs/source/EventRestructuring.md b/docs/source/EventRestructuring.md deleted file mode 100644 index 42c7553..0000000 --- a/docs/source/EventRestructuring.md +++ /dev/null @@ -1,125 +0,0 @@ -# Event restructuring - -This tutorial works through the process of restructuring event files using the HED event remodeling tools. The tools are designed to be run on an entire BIDS dataset. - -* [**What is HED annotation?**](what-is-hed-annotation-anchor) -* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) - -(what-is-event-restructuring-anchor)= -## What is event restructuring? - - -(a-recipe-for-simple-annotation-anchor)= -## Installation and running of the restructuring - - -(standard-hed-tag-selections-anchor)= -```{admonition} Standard HED tag selections for minimal annotation. -:class: tip - -| Event tag | Support tag type | Example tags | Reason | -| ------------- | -------------------- | ------------ | ------ | -| **Sensory-event** | *Sensory-presentation* | *Visual-presentation*
*Auditory-presentation*| Which sense? | -``` - - -As in BIDS, we assume that the event metadata is given in tabular form. -Each table row represents the metadata associated with a single data event marker, -as shown in the following excerpt of the `events.tsv` file for a simple Go/No-go experiment. -The `onset` column gives the time in seconds of the marker relative -to the beginning of the associated data file. - -(example-go-no-go-event-table-anchor)= -````{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | -```` - -In the Go/No-go experiment, the experimental participant is presented -with a series of target and distractor animal images. -The participant is instructed to lift a finger off a button -when a target animal image appears. -Since in this experiment, the `value` column has distinct values -for all possible unique event types, the `event_type` column is redundant. -In this case, we can choose to assign all the annotations to -the `value` column as demonstrated in the following example. - -````{admonition} Version 1: Assigning all annotations to the value column. - -| value | Event category | Supporting tags | -| ------- | -------------- | --------------- | -| animal_target | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | -| animal_distractor | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Non-target*, *Distractor*, (*Animal*, *Image*) | -| correct_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Correct-action* | -| incorrect_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Incorrect-action* | - -```` - -The table above shows the event category and the supporting tags as suggested in the -[**Standard hed tags for minimal annotation**](standard-hed-tag-selections-anchor) table. - -A better format for your annotations is the -[**4-column spreadsheet format**](four-column-spreadsheet-format-anchor) described in -[**BIDS annotation quickstart**](BidsAnnotationQuickstart.md), since there are online -tools to convert this format into a JSON sidecar that can be deployed directly in -a BIDS dataset. - -````{admonition} 4-column spreadsheet format for the previous example. - -| column_name| column_value | description | HED | -| ------- | -------------- | ----------- | ------- | -| value | animal_target | An target animal image was
presented on a screen. |*Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | -| value | animal_distractor | A non-target animal distractor
image was presented
on a screen. | *Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*, *Non-target*,
*Distractor*, (*Animal*, *Image*)| -| value | correct_response | Participant correctly
lifted finger off button. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Correct-action* | -| value | incorrect_response | Participant lifted finger off
the button but should not have. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Incorrect-action* | - -```` - -HED tools assemble the annotations for each event into a single HED tag string. -An exactly equivalent version of the previous example splits the HED tag annotation between -the `event_type` and `value` columns as shown in the next example. - -````{admonition} Version 2: Assigning annotations to multiple event file columns. - -| column_name | column_value | description | HED | -| ------- | -------------- | --------------- | ------ | -| event_type | stimulus | An image of an animal
was presented on a
computer screen.| *Sensory-event*,
*Visual-presentation*,
*experimental-stimulus* | -| event_type | response | Participant lifted finger
off button.| *Agent-action*,
*Experiment-participant*,
(*Lift*, *Finger*) | -| value | animal_target | A target animal image. | *Target*, (*Animal*, *Image*) | -| value | animal_distractor | A non-target animal image
meant as a distractor. | *Non-target*, *Distractor*,
(*Animal*, *Image*) | -| value | correct_response | The previous stimulus
was a target animal. | *Correct-action* | -| value | incorrect_response | The previous stimulus
was not a target animal. | *Incorrect-action* | -| stim_file | n/a | Filename of stimulus image. | (*Image*, *Pathname/#*) | -```` -In version 2, the annotations that are common -to all stimuli and responses are assigned to `event_type`. -We have also included the annotation for the `stim_file` column in the last row -of this table. - -The assembled annotation for the first event (with onset 5.035) in the -[**event file excerpt from go/no-go**](example-go-no-go-event-table-anchor) above is: - -> *Sensory-event*, *Visual-presentation*, *Experimental-stimulus*, *Target*, (*Animal*, *Image*), (*Image*, *Pathname/105064.jpg*) - -Mapping annotations and column information across multiple column values often makes -the annotation process simpler, especially when annotations become more complex. -Multiple column representation also can make analysis easier, -particularly if the columns represent information such as design variables. - -See [**BIDS annotation quick start**](BidsAnnotationQuickstart.md#bids-annotation-quickstart) for how to -create templates to fill in with your annotations using online tools. -Once you have completed the annotation and converted it to a sidecar, -you simply need to place this sidecar in the root directory of your BIDS dataset. - -This quick start demonstrates the most basic HED annotations. -HED is capable of much more extensive and expressive annotations as -explained in a series of tutorials on this site. \ No newline at end of file diff --git a/docs/source/HedSearchingAndSummary.md b/docs/source/HedConditionsAndDesignMatrices.md similarity index 97% rename from docs/source/HedSearchingAndSummary.md rename to docs/source/HedConditionsAndDesignMatrices.md index 99471e0..61cec8f 100644 --- a/docs/source/HedSearchingAndSummary.md +++ b/docs/source/HedConditionsAndDesignMatrices.md @@ -1,6 +1,6 @@ -# Event restructuring - +# HED conditions and design matrices +**Under construction** This tutorial takes you through the steps of annotating the events using HED (Hierarchical Event Descriptors). diff --git a/docs/source/HedRemodelingTools.md b/docs/source/HedRemodelingTools.md index 9969e29..496c7f7 100644 --- a/docs/source/HedRemodelingTools.md +++ b/docs/source/HedRemodelingTools.md @@ -1,35 +1,167 @@ -# HED remodeling tools +# Event file restructuring + +**UNDER DEVELOPMENT** This tutorial works through the process of restructuring event files using the HED event remodeling tools. The tools are designed to be run on an entire BIDS dataset. -* [**What is HED annotation?**](what-is-hed-annotation-anchor) -* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) +* [**What is restructuring?**](what-is-event-file-restructuring-anchor) +* [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) +* [**Running remodeling tools**](running-remodeling-tools-anchor) +* [**Remodeling operations**](remodeling-operations-anchor) + * [**Add structure**](add-structure-anchor) Docs not written + * [**Add trial numbers**](add-trial-numbers-anchor) Docs not written + * [**Derive column**](derive-column-anchor) Docs not written + * [**Factor column**](factor-column-anchor) Docs not written + * [**Factor HED**](factor-column-anchor) Docs not written + * [**Merge events**](merge-events-anchor) Docs not written + * [**Remove columns**](remove-columns-anchor) + * [**Rename columns**](rename-columns-anchor) + * [**Reorder columns**](reorder-columns-anchor) + * [**Split event**](split-event-anchor) + + +(what-is-event-file-restructuring-anchor)= +## What is event file restructuring? + +**Need brief introduction to event remodeling here** -(what-is-event-restructuring-anchor)= -## What is event restructuring? +(installation-of-remodeling-tools-anchor)= +## Installation of remodeling tools +**Need information about installation.** -(a-recipe-for-simple-annotation-anchor)= -## Installation and running of the restructuring +(running-remodeling-tools-anchor)= +## Running remodeling tools -(remodeling-operations)= +**Need information about how to run** + +(remodeling-operations-anchor)= ## Remodeling operations +The examples in this chapter use the following excerpt from sub-0013 +stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneuro.org) as ds002790. + +(sample-remodeling-events-file-anchor)= +````{admonition} Excerpt from event file for a stop-go task. +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` +(add-structure-anchor)= ### Add structure +**NOT WRITTEN - PLACEHOLDER** + Use: Add trial or block markers --- used for epoching around the start of a trial. The duration is the duration of the trial or block respectively. +(parameters-for-add-structure-anchor)= +```{admonition} Parameters for the *add_structure* command. +:class: tip +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list | Names of the columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` +The following example .... + +````{admonition} Parameters for the *add_structure* command. +:class: tip + +```json +{ + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } +} +``` +```` + +The results of executing the *add_structure* command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Stop-go event file XXX. + +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(add-trial-numbers-anchor)= ### Add trial numbers + +**NOT WRITTEN - PLACEHOLDER** + Add a column with the trial numbers. +(parameters-for-add-trial-numbers-anchor)= +```{admonition} Parameters for the *add_trial_numbers* command. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list of str | A list of columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` +The following example .... + +````{admonition} An example . +:class: tip + +```json +{ + "command": "add_trial_numbers" + "description": "xxx" + "parameters": { + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } + } +} +``` +```` + +The results of executing this command on the [**sample events file**](sample-remodeling-events-file-anchor) are: + +````{admonition} Results of adding trial numbers to the file. +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` +(derive-column-anchor)= ### Derive column -Create a new column or overwrite values in an existing column using a mapping from existing columns. Can also be used to overwrite values on existing columns, only values with the predefined combinations will be overwritten. +**NOT WRITTEN - PLACEHOLDER** + +Create a new column or overwrite values in an existing column using a mapping from existing columns. +This command can be used to overwrite values particular values in existing columns +based on predefined combinations of values in other columns. (parameters-for-derive-column-anchor)= @@ -42,49 +174,206 @@ Create a new column or overwrite values in an existing column using a mapping fr | source_columns | list of str | A list of columns to be used for remapping. | | mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` -The following example .... +The following example creates a *match_side column* with values *left* and *right* +based on particular combinations of values in the *response_accuracy* and +*response_hand* columns. + +````{admonition} Create a *match_side* column with values *left* and *right*. +:class: tip ```json { - "column_name": "match_side", - "source_columns": ["response_accuracy", "response_hand"], - "mapping": { - "left": [["correct", "left"], ["incorrect", "right"]], - "right": [["correct", "right"], ["incorrect", "left"]] + "command": "add_trial_numbers" + "description": "xxx" + "parameters": { + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } } } ``` -Results in the following: - -````{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | ```` +The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Adding a *match_side* column using the *derive_column* command. + +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` +(factor-column-anchor)= ### Factor column +**NOT WRITTEN - PLACEHOLDER** + Factor each of the specified values in the indicated column into a column containing 1’s and 0’s indicating presence and absence. If no values are specified, all unique values in that column are factored. +(parameters-for-factor-column-anchor)= +```{admonition} Standard HED tag selections for minimal annotation. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list of str | A list of columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` +The following example .... + +````{admonition} Create XXXX. +:class: tip + +```json +{ + "command": "factor_column" + "description": "xxx" + "parameters": { + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } + } +} +``` +```` + +The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Results of factoring column XXX. + +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(factor-hed-anchor)= ### Factor HED +**NOT WRITTEN - PLACEHOLDER** + Produce a list of factor columns based on the specified HED condition-variable values. +(parameters-for-factor-hed-anchor)= +```{admonition} Parameters for factor_hed. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list of str | A list of columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` + +The following example .... + +````{admonition} Create XXXX. +:class: tip + +```json +{ + "command": "factor_hed" + "description": "xxx" + "parameters": { + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } + } +} +``` +```` + +The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Results of *factor_hed*. + +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(merge-events-anchor)= ### Merge events + +**NOT WRITTEN - PLACEHOLDER** + One long event is represented by multiple repeat events. Merges these same events occurring consecutively into one event with duration of the new event updated as the sum of all merged events. +(parameters-for-merge-events-anchor)= +```{admonition} Standard HED tag selections for minimal annotation. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list of str | A list of columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` +The following example .... + +````{admonition} Merge events. +:class: tip + +```json +{ + "command": "merge_events" + "description": "xxx" + "parameters": { + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } + } +} +``` +```` + +The results of executing the example *merge_events* command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} The results of the *merge_events* command. + +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(remove-columns-anchor)= ### Remove columns Remove the specified columns if present. +If one of the specified columns is not in the file and the *ignore_missing* +parameter is *false*, a `KeyError` is raised for missing column. (parameters-for-remove-columns-anchor)= @@ -93,75 +382,94 @@ Remove the specified columns if present. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_names | list of str | A list of columns to remove.| +| remove_names | list of str | A list of columns to remove.| +| ignore_missing | boolean | If true, missing columns are ignored, otherwise raise an error. | ``` -Example command: +The following example command removes the columns *stop_signal_delay*, +*response_accuracy*, and *face*. + +````{admonition} An example . +:class: tip + ```json -{ - "column_names": ["sample", "ethn_target", "ethn_distractor"] +{ + "command": "remove_columns", + "description": "Remove columns before the next step.", + "parameters": { + "remove_names": ["stop_signal_delay", "response_accuracy", "face"], + "ignore_missing": true + } } ``` +```` -```{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | +The results of executing this command on the +[sample events file](sample-remodeling-events-file-anchor) are shown below. +Although *face* is not the name of a column in the dataframe, +it is ignored because *ignore_missing* is true. +If *ignore_missing* had been false, a `KeyError` would have been generated. + +```{admonition} Results of *remove_column*. +| onset | duration | trial_type | response_time | response_hand | sex | +| ----- | -------- | ---------- | ------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | 0.565 | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.49 | right | female | +| 9.5856 | 0.5084 | go | 0.45 | right | female | +| 13.5939 | 0.5083 | succesful_stop | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.633 | left | male | +| 21.6103 | 0.5083 | go | 0.443 | left | male | ```` +(remove-rows-anchor)= ### Remove rows -Remove rows where specified columns take particular values. +Remove rows in which the named column has one of the specified values. (parameters-for-remove-rows-anchor)= -```{admonition} Standard HED tag selections for minimal annotation. +```{admonition} Parameters for remove_rows. :class: tip | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list of str | A list of columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| column_name | str | The name of the column to be tested.| +| remove_values | list | A list of values to be tested for removal. | ``` -The following example .... + +The following example command removes the rows whose *trial_type* column has either +*succesful_stop* or *unsuccesful_stop*. + +````{admonition} Example remove_rows command. +:class: tip ```json -{ - "column_name": "match_side", - "source_columns": ["response_accuracy", "response_hand"], - "mapping": { - "left": [["correct", "left"], ["incorrect", "right"]], - "right": [["correct", "right"], ["incorrect", "left"]] +{ + "command": "remove_rows", + "description": "Remove rows where trial_type is either succesful_stop or unsuccesful_stop.", + "parameters": { + "column_name": "trial_type", + "remove_values": ["succesful_stop", "unsuccesful_stop"] } } ``` -Results in the following: - -````{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | ```` +The results of executing this command on the +[sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} After removing rows with *trial_type* equal to *succesful_stop* or *unsuccesful_stop*. + +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(rename-columns-anchor)= ### Rename columns -Rename columns by providing old name and new name. +Rename columns by providing a dictionary of old names to new names. (parameters-for-rename-columns-anchor)= ```{admonition} Parameters for rename_columns. @@ -170,40 +478,56 @@ Rename columns by providing old name and new name. | Parameter | Type | Description | | ------------ | ---- | ----------- | | mapping | dict | The keys are the old column names and the values are the new names.| -| ignore_missing | bool | If false, an error is thrown if any keys are missing. | +| ignore_missing | bool | If false, a key error is raised if a dictionary key is not a column name . | ``` -The following example .... +The command in the following example specifies that *response_hand* column be renamed *hand_used* +and that the *sex* column be renamed *image_sex*. +The *face* entry in the mapping will be ignored because *ignore_missing* is true. +If *ignore_missing* is false, a `KeyError` exception is raised if a column specified in +the mapping does not correspond to a column name in the dataframe. + +````{admonition} Example rename_columns command. +:class: tip ```json -{ - "mapping": { - "face_type": "xxx", - "hand": "response_hand" - }, - "ignore_missing": true +{ + "command": "rename_columns", + "description": "Remove columns before splitting events.", + "parameters": { + "mapping": { + "face": "face_image", + "response_hand": "hand_used", + "sex": "image_sex" + }, + "ignore_missing": true + } } ``` -Results in the following: - -````{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | ```` +The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Renaming columns in staop +| onset | duration | trial_type | stop_signal_delay | hand_used | response_accuracy | response_hand | image_sex | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(reorder-columns-anchor)= ### Reorder columns -Reorder the columns in the specified order. Columns not included are discarded or placed at the end. If a specified column is not in the data --- do what? +Reorder the columns in the specified order. If *ignore_missing* is true, +the dataframe columns not included are discarded. +On the other hand, if *ignore_missing* is false, +column names that do not appear in the reorder list are moved to the end +of the dataframe in the same order that they appear. (parameters-for-reorder-columns-anchor)= ```{admonition} Parameters for reorder_columns. @@ -211,42 +535,71 @@ Reorder the columns in the specified order. Columns not included are discarded o | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_names | list of str | A list of columns in the order they should appear in the data.| -| keep_missing | boolean | If true, existing columns that aren't in column_names are moved to the end and in the same relative order that they originally appeared in the data. | +| column_order | list | A list of columns in the order they should appear in the data.| +| ignore_missing | boolean | If false, existing columns that aren't in column_names
are moved to the end and in the same relative
order that they originally appeared in the data. | ``` +The command in the following example specifies that the first four columns of the dataset +should be: *onset*, *duration*, *trial_type*, *response_hand*, and *response_time*. +Since *ignore_missing* is true, these will be the only columns retained. + +````{admonition} Example reorder_columns command. +:class: tip ```json -{ - "column_names": ["onset", "duration", "trial_type", "response_time"], - "keep_missing": false +{ + "command": "reorder_columns", + "description": "Reorder columns.", + "parameters": { + "column_order": ["onset", "duration", "trial_type", "response_hand", "response_time"], + "ignore_missing": true + } } ``` +```` + -Results in the following: +The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Event file from a simple Go/No-go experiment. +````{admonition} Results of reorder_columns. -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | +| onset | duration | trial_type | response_hand | response_time | +| ----- | -------- | ---------- | ------------- | ------------- | +| 0.0776 | 0.5083 | go | right | 0.565 | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.49 | +| 9.5856 | 0.5084 | go | right | 0.45 | +| 13.5939 | 0.5083 | succesful_stop | n/a | n/a | +| 17.1021 | 0.5083 | unsuccesful_stop | left | 0.633 | +| 21.6103 | 0.5083 | go | left | 0.443 | ```` +(split-event-anchor)= ### Split event -The split_event is the most complicated of the remodeling operations and generally -Multiple information and responses are encoded in a single event. Split this event into multiple lines in the event file and adjust the meanings of the columns — usually this means removing the original event and replacing it with new events at various offsets. -The final result has rows ordered by increasing offsets. +The *split_event* is the most complicated of the remodeling operations and is often used to +convert event files from using *trial-level* encoding to *event-level* encoding. +In *trial-level* encoding each row of the event file represents all the events in a single trial +(usually some variation of cue-stimulus-response-feedback-ready sequence). +In *event-level* encoding, each row represents the marker for a single event. +In this case a trial consists of a sequence of multiple events. + +The *split_event* command requires an *anchor_column*, which could be an existing +column or a column that must be added to the dataframe. +The purpose of the *anchor_column* is to hold the codes for the new events. + +The *new_events* dictionary has the new events to be created. +The keys are the new event codes to be inserted into the *anchor_column*. +The values in *new_events* are themselves dictionaries. +Each of these dictionaries has three keys: + +- *onset_source*, a list specifying the items to be added to the *onset* +of the event row being split. These items can be any combination of numerical values and column names. +- *duration* a list of any combinations of numerical values and column names whose values are to be added +to compute the duration. +- *copy_columns* a list of column names whose values should be copied into the new events. +Unlisted columns are filled with n/a. -Rename columns by providing old name and new name. (parameters-for-split-event-anchor)= ```{admonition} Parameters for split_event. @@ -254,52 +607,67 @@ Rename columns by providing old name and new name. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column that will be used for split-event codes.| -| split_dict | dict | Dictionary specifying how the split should occur. | -|remove_parent_event | bool | If true, remove parent event. | +| anchor_event | str | The name of the column that will be used for split-event codes.| +| event_selection | dict | Dictionary which events should be split (currently ignored and all events are split). | +| new_events | dict | Dictionary whose keys are the codes to be inserted as new events and whose values +are dictionaries with keys onset_source, duration, and copy_columns. | +| add_trial_numbers | boolean | If true, a column of trial numbers are added before the split. | +| remove_parent_event | boolean | If true, remove parent event. | ``` -The `column_name` is the column that the split event codes are written. -If this column does not exist in the `events.tsv` file it is added prior to the split processing. +The command in the following example specifies that *response_hand* column be renamed *hand_used* +and that the *sex* column be renamed *image_sex*. +The *face* entry in the mapping will be ignored because *ignore_missing* is true. +If *ignore_missing* is false, a `KeyError` exception is raised if a column specified in +the mapping does not correspond to a column name in the dataframe. -(parameters-for-split-dict-anchor)= -```{admonition} values for split_dict. +````{admonition} An example split_event command. :class: tip -| Parameter | Type | Description | -| ------------ | ---- | ----------- | -| onset_source | list | A list of column names and numbers representing values added to the onset of the parent event.| -| split_dict | dict | Dictionary specifying how the split should occur. | -|remove_parent_event | bool | If true, remove parent event. | - -``` - -The -The following example .... - ```json -{ - "mapping": { - "face_type": "xxx", - "hand": "response_hand" - }, - "ignore_missing": true +{ + "command": "split_event", + "description": "Takes trial-level encoding and turns it into event-level encoding.", + "parameters": { + "anchor_column": "trial_type", + "event_selection": {}, + "new_events": { + "response": { + "onset": ["response_time"], + "duration": [0], + "column_columns": ["response_accuracy", "response_hand", "sex"] + }, + "stop_signal": { + "onset": ["stop_signal_delay"], + "duration": [0.5], + "column_columns": ["response_accuracy", "response_hand", "sex"] + } + }, + "add_trial_numbers": true, + "remove_parent_event": false + } } - ``` -Results in the following: - -````{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | ```` + +The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Results of the split_events command. +| onset | duration | trial_type | response_accuracy | response_hand | sex | trial_number | +| ----- | -------- | ---------- | ----------------- | ------------- | --- | ------------ | +| 0.0776 | 0.5083 | go | correct | right | female | 1 | +| 0.6426 | 0.0 | response | correct | right | female | 1 | +| 5.5774 | 0.5083 | unsuccesful_stop | correct | right | female | 2 | +| 5.7774 | 0.5 | stop_signal | correct | right | female | 2 | +| 6.0674 | 0.0 | response | correct | right | female | 2 | +| 9.5856 | 0.5084 | go | correct | right | female | 3 | +| 10.0356 | 0.0 | response | correct | right | female | 3 | +| 13.5939 | 0.5083 | succesful_stop | n/a | right | female | 4 | +| 13.7939 | 0.5 | stop_signal | n/a | right | female | 4 | +| 17.1021 | 0.5083 | unsuccesful_stop | correct | left | male | 5 | +| 17.3521 | 0.5 | stop_signal | correct | left | male | 5 | +| 17.7351 | 0.0 | response | correct | left | male | 5 | +| 21.6103 | 0.5083 | go | correct | left | male | 6 | +| 22.0533 | 0.0 | response | correct | left | male | 6 | +```` \ No newline at end of file diff --git a/docs/source/DesignMatricesWithHed.md b/docs/source/HedSearchAndSummary.md similarity index 97% rename from docs/source/DesignMatricesWithHed.md rename to docs/source/HedSearchAndSummary.md index 99471e0..889dee1 100644 --- a/docs/source/DesignMatricesWithHed.md +++ b/docs/source/HedSearchAndSummary.md @@ -1,6 +1,6 @@ -# Event restructuring - +# HED search and summary +**Under construction** This tutorial takes you through the steps of annotating the events using HED (Hierarchical Event Descriptors). diff --git a/docs/source/index.rst b/docs/source/index.rst index 52f1f37..5f95903 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,6 +15,15 @@ HED examples and tutorials BidsAnnotationQuickstart.md HedAnnotationQuickstart.md HedValidation.md + HedSearchAndSummary.md + HedConditionsAndDesignMatrices.md + HedRemodelingTools.md + + +.. toctree:: + :maxdepth: 3 + :caption: HED Tools: + TaggingWithCTagger.md DataCuration101.md HedToolsOnline.md From dec9403290cc9dc6370023e634c3a7ecc1fbf5e3 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sat, 23 Jul 2022 05:34:07 -0500 Subject: [PATCH 003/143] Worked on the documentation for event restructuring --- docs/source/HedConditionsAndDesignMatrices.md | 168 ----------- docs/source/HedRemodelingTools.md | 261 +++++++++++------- docs/source/HedSearchAndSummary.md | 167 ----------- 3 files changed, 163 insertions(+), 433 deletions(-) diff --git a/docs/source/HedConditionsAndDesignMatrices.md b/docs/source/HedConditionsAndDesignMatrices.md index 61cec8f..a7566ac 100644 --- a/docs/source/HedConditionsAndDesignMatrices.md +++ b/docs/source/HedConditionsAndDesignMatrices.md @@ -1,171 +1,3 @@ # HED conditions and design matrices **Under construction** - -This tutorial takes you through the steps of annotating the events -using HED (Hierarchical Event Descriptors). -The tutorial focuses on how to make good choices of HED annotations -to make your data usable for downstream analysis. -The mechanics of putting your selected HED annotations into -[BIDS (Brain Imaging Data Structure)](https://bids.neuroimaging.io/) format -is covered in the [**BIDS annotation quickstart**](./BidsAnnotationQuickstart.md) guide. - -* [**What is HED annotation?**](what-is-hed-annotation-anchor) -* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) - -(what-is-hed-annotation-anchor)= -## What is HED annotation? - -A HED annotation consists of a comma separated list of tags selected from -a HED vocabulary or schema. -An important reason for using an agreed-upon vocabulary rather than -free-form tagging for annotation is to avoid confusion and ambiguity -and to promote data-sharing. - -The basic terms are organized into trees for easier access and search. -The [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) allows -you to explore these terms. - -(a-recipe-for-simple-annotation-anchor)= -## A recipe for simple annotation -In thinking about how to annotate an event, you should always start -by selecting a tag from the *Event* subtree to indicate the general event category. -Possible choices are: *Sensory-event*, *Agent-action*, *Data-feature*, *Experiment-control*, -*Experiment-procedure*, *Experiment-structure*, and *Measurement-event*. -See the [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) -to view the available tags. - -Most experiments will only have a few types of distinct events. -The simplest way to create a minimal HED annotation for your events is: - -1. Select one of the 7 tags from the *Event* subtree to designate the general category of the event. -2. Use the following table to select the appropriate supporting tags given that event type. - -(standard-hed-tag-selections-anchor)= -```{admonition} Standard HED tag selections for minimal annotation. -:class: tip - -| Event tag | Support tag type | Example tags | Reason | -| ------------- | -------------------- | ------------ | ------ | -| **Sensory-event** | *Sensory-presentation* | *Visual-presentation*
*Auditory-presentation*| Which sense? | -| | *Task-event-role* | *Experimental-stimulus*
*Instructional* | What task role? | -| | *Task-stimulus-role* | *Cue*
*Target* | Stimulus purpose? | -| | *Item* | *(Face, Image)*
*Siren* | What is presented? | -| | *Sensory-attribute* | *Red* | What modifiers are needed? | -| **Agent-action** | *Agent-task-role* | *Experiment-participant* | Who is agent? | -| | *Action* | *Move*
*Press* | What action is performed? | -| | *Task-action-type* | *Appropriate-action*
*Near-miss* | What task relationship? | -| | *Item* | *Arm*
*Mouse-button* | What is action target? | -| **Data-feature** | *Data-source-type* | *Expert-annotation*
*Computed-feature* | Where did the feature come from? | -| | *Label* | *Label/Blinker_BlinkMax* | Tool name?
Feature type? | -| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | Feature value or type? | -| **Experiment-control** | *Agent* | *Controller-Agent* | What is the controller? | -| | *Informational* | *Label/Stop-recording* | What did the controller do? | -| **Experiment-procedure** | *Task-event-role* | *Task-activity* | What procedure? | -| **Experiment-structure** | *Organizational-property* | *Time-block*
*Condition-variable* | What structural property? | -| **Measurement-event** | *Data-source-type* | *Instrument-measurement*
*Observation* | Source of the data. | -| | *Label* | *Label/Oximeter_O2Level* | Instrument name?
Measurement type? | -| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | What value or type? -``` - - -As in BIDS, we assume that the event metadata is given in tabular form. -Each table row represents the metadata associated with a single data event marker, -as shown in the following excerpt of the `events.tsv` file for a simple Go/No-go experiment. -The `onset` column gives the time in seconds of the marker relative -to the beginning of the associated data file. - -(example-go-no-go-event-table-anchor)= -````{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | -```` - -In the Go/No-go experiment, the experimental participant is presented -with a series of target and distractor animal images. -The participant is instructed to lift a finger off a button -when a target animal image appears. -Since in this experiment, the `value` column has distinct values -for all possible unique event types, the `event_type` column is redundant. -In this case, we can choose to assign all the annotations to -the `value` column as demonstrated in the following example. - -````{admonition} Version 1: Assigning all annotations to the value column. - -| value | Event category | Supporting tags | -| ------- | -------------- | --------------- | -| animal_target | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | -| animal_distractor | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Non-target*, *Distractor*, (*Animal*, *Image*) | -| correct_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Correct-action* | -| incorrect_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Incorrect-action* | - -```` - -The table above shows the event category and the supporting tags as suggested in the -[**Standard hed tags for minimal annotation**](standard-hed-tag-selections-anchor) table. - -A better format for your annotations is the -[**4-column spreadsheet format**](four-column-spreadsheet-format-anchor) described in -[**BIDS annotation quickstart**](BidsAnnotationQuickstart.md), since there are online -tools to convert this format into a JSON sidecar that can be deployed directly in -a BIDS dataset. - -````{admonition} 4-column spreadsheet format for the previous example. - -| column_name| column_value | description | HED | -| ------- | -------------- | ----------- | ------- | -| value | animal_target | An target animal image was
presented on a screen. |*Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | -| value | animal_distractor | A non-target animal distractor
image was presented
on a screen. | *Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*, *Non-target*,
*Distractor*, (*Animal*, *Image*)| -| value | correct_response | Participant correctly
lifted finger off button. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Correct-action* | -| value | incorrect_response | Participant lifted finger off
the button but should not have. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Incorrect-action* | - -```` - -HED tools assemble the annotations for each event into a single HED tag string. -An exactly equivalent version of the previous example splits the HED tag annotation between -the `event_type` and `value` columns as shown in the next example. - -````{admonition} Version 2: Assigning annotations to multiple event file columns. - -| column_name | column_value | description | HED | -| ------- | -------------- | --------------- | ------ | -| event_type | stimulus | An image of an animal
was presented on a
computer screen.| *Sensory-event*,
*Visual-presentation*,
*experimental-stimulus* | -| event_type | response | Participant lifted finger
off button.| *Agent-action*,
*Experiment-participant*,
(*Lift*, *Finger*) | -| value | animal_target | A target animal image. | *Target*, (*Animal*, *Image*) | -| value | animal_distractor | A non-target animal image
meant as a distractor. | *Non-target*, *Distractor*,
(*Animal*, *Image*) | -| value | correct_response | The previous stimulus
was a target animal. | *Correct-action* | -| value | incorrect_response | The previous stimulus
was not a target animal. | *Incorrect-action* | -| stim_file | n/a | Filename of stimulus image. | (*Image*, *Pathname/#*) | -```` -In version 2, the annotations that are common -to all stimuli and responses are assigned to `event_type`. -We have also included the annotation for the `stim_file` column in the last row -of this table. - -The assembled annotation for the first event (with onset 5.035) in the -[**event file excerpt from go/no-go**](example-go-no-go-event-table-anchor) above is: - -> *Sensory-event*, *Visual-presentation*, *Experimental-stimulus*, *Target*, (*Animal*, *Image*), (*Image*, *Pathname/105064.jpg*) - -Mapping annotations and column information across multiple column values often makes -the annotation process simpler, especially when annotations become more complex. -Multiple column representation also can make analysis easier, -particularly if the columns represent information such as design variables. - -See [**BIDS annotation quick start**](BidsAnnotationQuickstart.md#bids-annotation-quickstart) for how to -create templates to fill in with your annotations using online tools. -Once you have completed the annotation and converted it to a sidecar, -you simply need to place this sidecar in the root directory of your BIDS dataset. - -This quick start demonstrates the most basic HED annotations. -HED is capable of much more extensive and expressive annotations as -explained in a series of tutorials on this site. \ No newline at end of file diff --git a/docs/source/HedRemodelingTools.md b/docs/source/HedRemodelingTools.md index 496c7f7..975166e 100644 --- a/docs/source/HedRemodelingTools.md +++ b/docs/source/HedRemodelingTools.md @@ -7,9 +7,10 @@ This tutorial works through the process of restructuring event files using the H * [**What is restructuring?**](what-is-event-file-restructuring-anchor) * [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) * [**Running remodeling tools**](running-remodeling-tools-anchor) -* [**Remodeling operations**](remodeling-operations-anchor) - * [**Add structure**](add-structure-anchor) Docs not written - * [**Add trial numbers**](add-trial-numbers-anchor) Docs not written +* [**Remodeling operations**](remodeling-operations-anchor) + * [**Add structure column**](add-structure-column-anchor) Docs not written + * [**Add structure events**](add-structure-events-anchor) Docs not written + * [**Add structure numbers**](add-structure-numbers-anchor) Docs not written * [**Derive column**](derive-column-anchor) Docs not written * [**Factor column**](factor-column-anchor) Docs not written * [**Factor HED**](factor-column-anchor) Docs not written @@ -43,6 +44,57 @@ stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneu (sample-remodeling-events-file-anchor)= ````{admonition} Excerpt from event file for a stop-go task. +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(add-structure-column-anchor)= +### Add structure column + +**NOT WRITTEN - PLACEHOLDER** + +Add a column of numbers corresponding to a structure elements such as trials or blocks. + +(parameters-for-add-structure-column-anchor)= +```{admonition} Parameters for the *add_structure_column* command. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list | Names of the columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` + +The *add_structure_column* command in the following example specifies . . . + + +````{admonition} An example *add_structure_column* command. +:class: tip + +```json +{ + "column_name": "add_structure_column", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } +} +``` +```` + +The results of executing this *add_structure_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: + + +````{admonition} Results of the previous *add_structure_column* command. + | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | | 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | @@ -53,15 +105,15 @@ stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneu | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` -(add-structure-anchor)= -### Add structure +(add-structure-events-anchor)= +### Add structure events **NOT WRITTEN - PLACEHOLDER** -Use: Add trial or block markers --- used for epoching around the start of a trial. The duration is the duration of the trial or block respectively. +Add events representing the start of a structural element such as a trial or a block. -(parameters-for-add-structure-anchor)= -```{admonition} Parameters for the *add_structure* command. +(parameters-for-add-structure-event-anchor)= +```{admonition} Parameters for the *add_structure_events* command. :class: tip | Parameter | Type | Description | @@ -71,14 +123,14 @@ Use: Add trial or block markers --- used for epoching around the start of a tria | mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` -The following example .... +The *add_structure_events* command in the following example specifies . . . -````{admonition} Parameters for the *add_structure* command. +````{admonition} An example *add_structure_events* command. :class: tip ```json { - "column_name": "match_side", + "column_name": "add_structure_events", "source_columns": ["response_accuracy", "response_hand"], "mapping": { "left": [["correct", "left"], ["incorrect", "right"]], @@ -88,9 +140,10 @@ The following example .... ``` ```` -The results of executing the *add_structure* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *add_structure_events* command on the [sample events file](sample-remodeling-events-file-anchor) are: + -````{admonition} Stop-go event file XXX. +````{admonition} Results of the previous *add_structure_events* command. | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -102,15 +155,17 @@ The results of executing the *add_structure* command on the [sample events file] | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` -(add-trial-numbers-anchor)= -### Add trial numbers +(add-structure-numbers-anchor)= +### Add structure numbers **NOT WRITTEN - PLACEHOLDER** -Add a column with the trial numbers. +Add a column with numbers corresponding to a structural element. -(parameters-for-add-trial-numbers-anchor)= -```{admonition} Parameters for the *add_trial_numbers* command. +**TODO** clarify the difference between add_structure_numbers and add_structure_column. + +(parameters-for-add-structure-numbers-anchor)= +```{admonition} Parameters for the *add_structure_numbers* command. :class: tip | Parameter | Type | Description | @@ -119,14 +174,14 @@ Add a column with the trial numbers. | source_columns | list of str | A list of columns to be used for remapping. | | mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` -The following example .... +The *add_structure_numbers* command in the following example specifies . . . ````{admonition} An example . :class: tip ```json { - "command": "add_trial_numbers" + "command": "add_structure_numbers" "description": "xxx" "parameters": { "column_name": "match_side", @@ -140,9 +195,10 @@ The following example .... ``` ```` -The results of executing this command on the [**sample events file**](sample-remodeling-events-file-anchor) are: +The results of executing this *add_structure_numbers* command on the [sample events file](sample-remodeling-events-file-anchor) are: + -````{admonition} Results of adding trial numbers to the file. +````{admonition} Results of executing the previous *add_structure_numbers* command. | onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -165,7 +221,7 @@ based on predefined combinations of values in other columns. (parameters-for-derive-column-anchor)= -```{admonition} Standard HED tag selections for minimal annotation. +```{admonition} Parameters for the *derive_column* command. :class: tip | Parameter | Type | Description | @@ -174,16 +230,14 @@ based on predefined combinations of values in other columns. | source_columns | list of str | A list of columns to be used for remapping. | | mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` -The following example creates a *match_side column* with values *left* and *right* -based on particular combinations of values in the *response_accuracy* and -*response_hand* columns. +The *derive_column* command in the following example specifies . . . -````{admonition} Create a *match_side* column with values *left* and *right*. +````{admonition} An example *derive_column* command. :class: tip ```json { - "command": "add_trial_numbers" + "command": "derive_column" "description": "xxx" "parameters": { "column_name": "match_side", @@ -197,7 +251,7 @@ based on particular combinations of values in the *response_accuracy* and ``` ```` -The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *derive_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: ````{admonition} Adding a *match_side* column using the *derive_column* command. @@ -214,53 +268,60 @@ The results of executing this command on the [sample events file](sample-remodel (factor-column-anchor)= ### Factor column -**NOT WRITTEN - PLACEHOLDER** - -Factor each of the specified values in the indicated column into a column containing 1’s and 0’s indicating presence and absence. If no values are specified, all unique values in that column are factored. +For each of the specified values in the indicated column create a column containing 1’s and 0’s +indicating presence or absence of the value. +If no values are specified, all unique values in that column are factored. (parameters-for-factor-column-anchor)= -```{admonition} Standard HED tag selections for minimal annotation. +```{admonition} Parameters for the *factor_column* command. :class: tip | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list of str | A list of columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| column_name | str | The name of the column to be factored.| +| factor_values | list | A list of column values to be included as factors. | +| factor_names | list| A list of column names for created factors
of the same length as factor_values. | +| overwrite_existing| bool | If true an existing factor column is overwritten. | ``` -The following example .... +The *factor_column* command in the following example specifies that factor columns +should be created for *succesful_stop* and *unsuccesful_stop* of the *trial_type* column. +The resulting columns are called *stopped* and *stop_failed*, respectively. +If the *factor_values* is an empty list, +factors are created for all unique values in the *column_name* column. +The *factor_names* parameters must be the same length as *factor_values*. +If *factor_names* is empty, the newly created columns are of the +form *column_name.factor_value*. -````{admonition} Create XXXX. + +````{admonition} A sample *factor_column* command. :class: tip ```json { "command": "factor_column" - "description": "xxx" + "description": "Create factors for the succesful_stop and unsuccesful_stop values." "parameters": { - "column_name": "match_side", - "source_columns": ["response_accuracy", "response_hand"], - "mapping": { - "left": [["correct", "left"], ["incorrect", "right"]], - "right": [["correct", "right"], ["incorrect", "left"]] - } + "column_name": "trial_type", + "factor_values": ["succesful_stop", "unsuccesful_stop"], + "factor_names": ["stopped", "stop_failed"], + "overwrite_existing": true } } ``` ```` -The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *factor_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: ````{admonition} Results of factoring column XXX. -| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | -| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | -| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | -| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | -| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | stopped | stop_failed | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | ---------- | ---------- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | 0 | 0 | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | 0 | 1 | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | 0 | 0| +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | 1 | 0 | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | 0 | 1 | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | 0 | 0 | ```` (factor-hed-anchor)= @@ -271,7 +332,7 @@ The results of executing this command on the [sample events file](sample-remodel Produce a list of factor columns based on the specified HED condition-variable values. (parameters-for-factor-hed-anchor)= -```{admonition} Parameters for factor_hed. +```{admonition} Parameters for *factor_hed* command. :class: tip | Parameter | Type | Description | @@ -281,9 +342,9 @@ Produce a list of factor columns based on the specified HED condition-variable v | mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` -The following example .... +The *factor_hed* command in the following example specifies . . . -````{admonition} Create XXXX. +````{admonition} Example *factor_hed* command. :class: tip ```json @@ -302,7 +363,7 @@ The following example .... ``` ```` -The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *factor_hed* command on the [sample events file](sample-remodeling-events-file-anchor) are: ````{admonition} Results of *factor_hed*. @@ -324,7 +385,7 @@ The results of executing this command on the [sample events file](sample-remodel One long event is represented by multiple repeat events. Merges these same events occurring consecutively into one event with duration of the new event updated as the sum of all merged events. (parameters-for-merge-events-anchor)= -```{admonition} Standard HED tag selections for minimal annotation. +```{admonition} Parameters for the *merge_events* command. :class: tip | Parameter | Type | Description | @@ -333,9 +394,10 @@ One long event is represented by multiple repeat events. Merges these same event | source_columns | list of str | A list of columns to be used for remapping. | | mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` -The following example .... -````{admonition} Merge events. +The *merge_events* command in the following example specifies . . . + +````{admonition} A sample *merge_events* command. :class: tip ```json @@ -354,7 +416,7 @@ The following example .... ``` ```` -The results of executing the example *merge_events* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *merge_events* command on the [sample events file](sample-remodeling-events-file-anchor) are: ````{admonition} The results of the *merge_events* command. @@ -377,7 +439,7 @@ parameter is *false*, a `KeyError` is raised for missing column. (parameters-for-remove-columns-anchor)= -```{admonition} Parameters for the remove_columns operation. +```{admonition} Parameters for the *remove_columns* operation. :class: tip | Parameter | Type | Description | @@ -386,10 +448,10 @@ parameter is *false*, a `KeyError` is raised for missing column. | ignore_missing | boolean | If true, missing columns are ignored, otherwise raise an error. | ``` -The following example command removes the columns *stop_signal_delay*, -*response_accuracy*, and *face*. +The *remove_column* command in the following example removes the *stop_signal_delay*, +*response_accuracy*, and *face* columns. -````{admonition} An example . +````{admonition} An example *remove_column* command. :class: tip ```json @@ -410,7 +472,7 @@ Although *face* is not the name of a column in the dataframe, it is ignored because *ignore_missing* is true. If *ignore_missing* had been false, a `KeyError` would have been generated. -```{admonition} Results of *remove_column*. +```{admonition} Results of executing the *remove_column*. | onset | duration | trial_type | response_time | response_hand | sex | | ----- | -------- | ---------- | ------------- | ------------- | --- | | 0.0776 | 0.5083 | go | 0.565 | right | female | @@ -436,10 +498,10 @@ Remove rows in which the named column has one of the specified values. | remove_values | list | A list of values to be tested for removal. | ``` -The following example command removes the rows whose *trial_type* column has either -*succesful_stop* or *unsuccesful_stop*. +The following example *remove_rows* command removes the rows whose *trial_type* column +has either *succesful_stop* or *unsuccesful_stop*. -````{admonition} Example remove_rows command. +````{admonition} Sample remove_rows command. :class: tip ```json @@ -454,10 +516,10 @@ The following example command removes the rows whose *trial_type* column has eit ``` ```` -The results of executing this command on the +The results of executing the previous *remove_rows* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} After removing rows with *trial_type* equal to *succesful_stop* or *unsuccesful_stop*. +````{admonition} The results of executing the previous *remove_rows* command. | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -466,28 +528,31 @@ The results of executing this command on the | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` +After removing rows with *trial_type* equal to *succesful_stop* or *unsuccesful_stop* only the +three *go* trials remain. + (rename-columns-anchor)= ### Rename columns Rename columns by providing a dictionary of old names to new names. (parameters-for-rename-columns-anchor)= -```{admonition} Parameters for rename_columns. +```{admonition} Parameters for *rename_columns*. :class: tip | Parameter | Type | Description | | ------------ | ---- | ----------- | -| mapping | dict | The keys are the old column names and the values are the new names.| +| column_mapping | dict | The keys are the old column names and the values are the new names.| | ignore_missing | bool | If false, a key error is raised if a dictionary key is not a column name . | ``` -The command in the following example specifies that *response_hand* column be renamed *hand_used* -and that the *sex* column be renamed *image_sex*. +The *rename_columns* command in the following example specifies that *response_hand* column be +renamed *hand_used* and that the *sex* column be renamed *image_sex*. The *face* entry in the mapping will be ignored because *ignore_missing* is true. If *ignore_missing* is false, a `KeyError` exception is raised if a column specified in the mapping does not correspond to a column name in the dataframe. -````{admonition} Example rename_columns command. +````{admonition} Example *rename_columns* command. :class: tip ```json @@ -495,8 +560,9 @@ the mapping does not correspond to a column name in the dataframe. "command": "rename_columns", "description": "Remove columns before splitting events.", "parameters": { - "mapping": { - "face": "face_image", + "column_mapping": { + "random_column": "new_random_column", + "stop_signal_delay": "stop_delay", "response_hand": "hand_used", "sex": "image_sex" }, @@ -507,15 +573,15 @@ the mapping does not correspond to a column name in the dataframe. ``` ```` -The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *rename_columns* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Renaming columns in staop -| onset | duration | trial_type | stop_signal_delay | hand_used | response_accuracy | response_hand | image_sex | +````{admonition} After the *rename_columns* command is executed, the sample events file is: +| onset | duration | trial_type | stop_delay | response_time | response_accuracy | hand_used | image_sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | | 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | | 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | | 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | | 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` @@ -530,7 +596,7 @@ column names that do not appear in the reorder list are moved to the end of the dataframe in the same order that they appear. (parameters-for-reorder-columns-anchor)= -```{admonition} Parameters for reorder_columns. +```{admonition} Parameters for *reorder_columns*. :class: tip | Parameter | Type | Description | @@ -540,11 +606,11 @@ of the dataframe in the same order that they appear. ``` -The command in the following example specifies that the first four columns of the dataset -should be: *onset*, *duration*, *trial_type*, *response_hand*, and *response_time*. +The *reorder_columns* command in the following example specifies that the first four +columns of the dataset should be: *onset*, *duration*, *trial_type*, *response_hand*, and *response_time*. Since *ignore_missing* is true, these will be the only columns retained. -````{admonition} Example reorder_columns command. +````{admonition} Example *reorder_columns* command. :class: tip ```json @@ -560,9 +626,9 @@ Since *ignore_missing* is true, these will be the only columns retained. ```` -The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *reorder_columns* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of reorder_columns. +````{admonition} Results of *reorder_columns*. | onset | duration | trial_type | response_hand | response_time | | ----- | -------- | ---------- | ------------- | ------------- | @@ -609,15 +675,14 @@ Unlisted columns are filled with n/a. | ------------ | ---- | ----------- | | anchor_event | str | The name of the column that will be used for split-event codes.| | event_selection | dict | Dictionary which events should be split (currently ignored and all events are split). | -| new_events | dict | Dictionary whose keys are the codes to be inserted as new events and whose values -are dictionaries with keys onset_source, duration, and copy_columns. | -| add_trial_numbers | boolean | If true, a column of trial numbers are added before the split. | +| new_events | dict | Dictionary whose keys are the codes to be inserted as new events and whose values are dictionaries with keys *onset_source*, *duration*, and *copy_columns*. | +| add_event_numbers | boolean | If true, a column of event numbers are added before the split. | | remove_parent_event | boolean | If true, remove parent event. | ``` -The command in the following example specifies that *response_hand* column be renamed *hand_used* -and that the *sex* column be renamed *image_sex*. +The *split_event* command in the following example specifies that *response_hand* +column be renamed *hand_used* and that the *sex* column be renamed *image_sex*. The *face* entry in the mapping will be ignored because *ignore_missing* is true. If *ignore_missing* is false, a `KeyError` exception is raised if a column specified in the mapping does not correspond to a column name in the dataframe. @@ -644,16 +709,16 @@ the mapping does not correspond to a column name in the dataframe. "column_columns": ["response_accuracy", "response_hand", "sex"] } }, - "add_trial_numbers": true, + "add_event_numbers": true, "remove_parent_event": false } } ``` ```` -The results of executing this command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *split_event* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of the split_events command. +````{admonition} Results of the split_event command. | onset | duration | trial_type | response_accuracy | response_hand | sex | trial_number | | ----- | -------- | ---------- | ----------------- | ------------- | --- | ------------ | | 0.0776 | 0.5083 | go | correct | right | female | 1 | @@ -663,7 +728,7 @@ The results of executing this command on the [sample events file](sample-remodel | 6.0674 | 0.0 | response | correct | right | female | 2 | | 9.5856 | 0.5084 | go | correct | right | female | 3 | | 10.0356 | 0.0 | response | correct | right | female | 3 | -| 13.5939 | 0.5083 | succesful_stop | n/a | right | female | 4 | +| 13.5939 | 0.5083 | succesful_stop | n/a | n/a | female | 4 | | 13.7939 | 0.5 | stop_signal | n/a | right | female | 4 | | 17.1021 | 0.5083 | unsuccesful_stop | correct | left | male | 5 | | 17.3521 | 0.5 | stop_signal | correct | left | male | 5 | diff --git a/docs/source/HedSearchAndSummary.md b/docs/source/HedSearchAndSummary.md index 889dee1..543b429 100644 --- a/docs/source/HedSearchAndSummary.md +++ b/docs/source/HedSearchAndSummary.md @@ -2,170 +2,3 @@ **Under construction** -This tutorial takes you through the steps of annotating the events -using HED (Hierarchical Event Descriptors). -The tutorial focuses on how to make good choices of HED annotations -to make your data usable for downstream analysis. -The mechanics of putting your selected HED annotations into -[BIDS (Brain Imaging Data Structure)](https://bids.neuroimaging.io/) format -is covered in the [**BIDS annotation quickstart**](./BidsAnnotationQuickstart.md) guide. - -* [**What is HED annotation?**](what-is-hed-annotation-anchor) -* [**A recipe for simple annotation**](a-recipe-for-simple-annotation-anchor) - -(what-is-hed-annotation-anchor)= -## What is HED annotation? - -A HED annotation consists of a comma separated list of tags selected from -a HED vocabulary or schema. -An important reason for using an agreed-upon vocabulary rather than -free-form tagging for annotation is to avoid confusion and ambiguity -and to promote data-sharing. - -The basic terms are organized into trees for easier access and search. -The [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) allows -you to explore these terms. - -(a-recipe-for-simple-annotation-anchor)= -## A recipe for simple annotation -In thinking about how to annotate an event, you should always start -by selecting a tag from the *Event* subtree to indicate the general event category. -Possible choices are: *Sensory-event*, *Agent-action*, *Data-feature*, *Experiment-control*, -*Experiment-procedure*, *Experiment-structure*, and *Measurement-event*. -See the [**Expandable HED vocabulary viewer**](https://www.hedtags.org/display_hed.html) -to view the available tags. - -Most experiments will only have a few types of distinct events. -The simplest way to create a minimal HED annotation for your events is: - -1. Select one of the 7 tags from the *Event* subtree to designate the general category of the event. -2. Use the following table to select the appropriate supporting tags given that event type. - -(standard-hed-tag-selections-anchor)= -```{admonition} Standard HED tag selections for minimal annotation. -:class: tip - -| Event tag | Support tag type | Example tags | Reason | -| ------------- | -------------------- | ------------ | ------ | -| **Sensory-event** | *Sensory-presentation* | *Visual-presentation*
*Auditory-presentation*| Which sense? | -| | *Task-event-role* | *Experimental-stimulus*
*Instructional* | What task role? | -| | *Task-stimulus-role* | *Cue*
*Target* | Stimulus purpose? | -| | *Item* | *(Face, Image)*
*Siren* | What is presented? | -| | *Sensory-attribute* | *Red* | What modifiers are needed? | -| **Agent-action** | *Agent-task-role* | *Experiment-participant* | Who is agent? | -| | *Action* | *Move*
*Press* | What action is performed? | -| | *Task-action-type* | *Appropriate-action*
*Near-miss* | What task relationship? | -| | *Item* | *Arm*
*Mouse-button* | What is action target? | -| **Data-feature** | *Data-source-type* | *Expert-annotation*
*Computed-feature* | Where did the feature come from? | -| | *Label* | *Label/Blinker_BlinkMax* | Tool name?
Feature type? | -| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | Feature value or type? | -| **Experiment-control** | *Agent* | *Controller-Agent* | What is the controller? | -| | *Informational* | *Label/Stop-recording* | What did the controller do? | -| **Experiment-procedure** | *Task-event-role* | *Task-activity* | What procedure? | -| **Experiment-structure** | *Organizational-property* | *Time-block*
*Condition-variable* | What structural property? | -| **Measurement-event** | *Data-source-type* | *Instrument-measurement*
*Observation* | Source of the data. | -| | *Label* | *Label/Oximeter_O2Level* | Instrument name?
Measurement type? | -| | *Data-value* | *Percentage/32.5*
*Time-interval/1.5 s* | What value or type? -``` - - -As in BIDS, we assume that the event metadata is given in tabular form. -Each table row represents the metadata associated with a single data event marker, -as shown in the following excerpt of the `events.tsv` file for a simple Go/No-go experiment. -The `onset` column gives the time in seconds of the marker relative -to the beginning of the associated data file. - -(example-go-no-go-event-table-anchor)= -````{admonition} Event file from a simple Go/No-go experiment. - -| onset | duration | event_type | value | stim_file | -| ----- | -------- | ---------- | ----- | --------- | -| 5.035 | n/a | stimulus | animal_target | 105064.jpg | -| 5.370 | n/a | response | correct_response | n/a | -| 6.837 | n/a | stimulus | animal_distractor | 38068.jpg | -| 8.651 | n/a | stimulus | animal_target | 136095.jpg | -| 8.940 | n/a | response | correct_response | n/a | -| 10.801 | n/a | stimulus | animal_distractor | 38014.jpg | -| 12.684 | n/a | stimulus | animal_distractor | 82063.jpg | -| 12.943 | n/a | response | incorrect_response | n/a | -```` - -In the Go/No-go experiment, the experimental participant is presented -with a series of target and distractor animal images. -The participant is instructed to lift a finger off a button -when a target animal image appears. -Since in this experiment, the `value` column has distinct values -for all possible unique event types, the `event_type` column is redundant. -In this case, we can choose to assign all the annotations to -the `value` column as demonstrated in the following example. - -````{admonition} Version 1: Assigning all annotations to the value column. - -| value | Event category | Supporting tags | -| ------- | -------------- | --------------- | -| animal_target | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | -| animal_distractor | *Sensory-event* | *Visual-presentation*, *Experimental-stimulus*,
*Non-target*, *Distractor*, (*Animal*, *Image*) | -| correct_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Correct-action* | -| incorrect_response | *Agent-action* | *Experiment-participant*, (*Lift*, *Finger*), *Incorrect-action* | - -```` - -The table above shows the event category and the supporting tags as suggested in the -[**Standard hed tags for minimal annotation**](standard-hed-tag-selections-anchor) table. - -A better format for your annotations is the -[**4-column spreadsheet format**](four-column-spreadsheet-format-anchor) described in -[**BIDS annotation quickstart**](BidsAnnotationQuickstart.md), since there are online -tools to convert this format into a JSON sidecar that can be deployed directly in -a BIDS dataset. - -````{admonition} 4-column spreadsheet format for the previous example. - -| column_name| column_value | description | HED | -| ------- | -------------- | ----------- | ------- | -| value | animal_target | An target animal image was
presented on a screen. |*Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*,
*Target*, (*Animal*, *Image*) | -| value | animal_distractor | A non-target animal distractor
image was presented
on a screen. | *Sensory-event*, *Visual-presentation*,
*Experimental-stimulus*, *Non-target*,
*Distractor*, (*Animal*, *Image*)| -| value | correct_response | Participant correctly
lifted finger off button. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Correct-action* | -| value | incorrect_response | Participant lifted finger off
the button but should not have. | *Agent-action*, *Experiment-participant*,
(*Lift*, *Finger*), *Incorrect-action* | - -```` - -HED tools assemble the annotations for each event into a single HED tag string. -An exactly equivalent version of the previous example splits the HED tag annotation between -the `event_type` and `value` columns as shown in the next example. - -````{admonition} Version 2: Assigning annotations to multiple event file columns. - -| column_name | column_value | description | HED | -| ------- | -------------- | --------------- | ------ | -| event_type | stimulus | An image of an animal
was presented on a
computer screen.| *Sensory-event*,
*Visual-presentation*,
*experimental-stimulus* | -| event_type | response | Participant lifted finger
off button.| *Agent-action*,
*Experiment-participant*,
(*Lift*, *Finger*) | -| value | animal_target | A target animal image. | *Target*, (*Animal*, *Image*) | -| value | animal_distractor | A non-target animal image
meant as a distractor. | *Non-target*, *Distractor*,
(*Animal*, *Image*) | -| value | correct_response | The previous stimulus
was a target animal. | *Correct-action* | -| value | incorrect_response | The previous stimulus
was not a target animal. | *Incorrect-action* | -| stim_file | n/a | Filename of stimulus image. | (*Image*, *Pathname/#*) | -```` -In version 2, the annotations that are common -to all stimuli and responses are assigned to `event_type`. -We have also included the annotation for the `stim_file` column in the last row -of this table. - -The assembled annotation for the first event (with onset 5.035) in the -[**event file excerpt from go/no-go**](example-go-no-go-event-table-anchor) above is: - -> *Sensory-event*, *Visual-presentation*, *Experimental-stimulus*, *Target*, (*Animal*, *Image*), (*Image*, *Pathname/105064.jpg*) - -Mapping annotations and column information across multiple column values often makes -the annotation process simpler, especially when annotations become more complex. -Multiple column representation also can make analysis easier, -particularly if the columns represent information such as design variables. - -See [**BIDS annotation quick start**](BidsAnnotationQuickstart.md#bids-annotation-quickstart) for how to -create templates to fill in with your annotations using online tools. -Once you have completed the annotation and converted it to a sidecar, -you simply need to place this sidecar in the root directory of your BIDS dataset. - -This quick start demonstrates the most basic HED annotations. -HED is capable of much more extensive and expressive annotations as -explained in a series of tutorials on this site. \ No newline at end of file From d99a198b07144e2175fb5103146abbee7c890f3a Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Mon, 25 Jul 2022 09:52:11 -0500 Subject: [PATCH 004/143] Continuing to correct event restructuring examples --- docs/source/HedRemodelingTools.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/source/HedRemodelingTools.md b/docs/source/HedRemodelingTools.md index 975166e..ea3294b 100644 --- a/docs/source/HedRemodelingTools.md +++ b/docs/source/HedRemodelingTools.md @@ -281,6 +281,7 @@ If no values are specified, all unique values in that column are factored. | column_name | str | The name of the column to be factored.| | factor_values | list | A list of column values to be included as factors. | | factor_names | list| A list of column names for created factors
of the same length as factor_values. | +| ignore_missing| bool | If true, columns corresponding to factor values
that do not appear in column are included. | | overwrite_existing| bool | If true an existing factor column is overwritten. | ``` The *factor_column* command in the following example specifies that factor columns @@ -304,6 +305,7 @@ form *column_name.factor_value*. "column_name": "trial_type", "factor_values": ["succesful_stop", "unsuccesful_stop"], "factor_names": ["stopped", "stop_failed"], + "ignore_missing": false, "overwrite_existing": true } } @@ -314,12 +316,12 @@ The results of executing this *factor_column* command on the [sample events file ````{admonition} Results of factoring column XXX. -| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | stopped | stop_failed | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | ---------- | ---------- | -| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | 0 | 0 | -| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | 0 | 1 | -| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | 0 | 0| -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | 1 | 0 | +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | stopped | stop_failed | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | ---------- | ---------- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | 0 | 0 | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | 0 | 1 | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | 0 | 0 | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | 1 | 0 | | 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | 0 | 1 | | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | 0 | 0 | ```` @@ -448,10 +450,11 @@ parameter is *false*, a `KeyError` is raised for missing column. | ignore_missing | boolean | If true, missing columns are ignored, otherwise raise an error. | ``` -The *remove_column* command in the following example removes the *stop_signal_delay*, -*response_accuracy*, and *face* columns. +The *remove_column* command in the following example removes the *stop_signal_delay* and +*response_accuracy* columns. The *face* column is not in the dataframe, but it is ignored, +since *ignore_missing* is True. -````{admonition} An example *remove_column* command. +````{admonition} An example *remove_columns* command. :class: tip ```json @@ -478,7 +481,7 @@ If *ignore_missing* had been false, a `KeyError` would have been generated. | 0.0776 | 0.5083 | go | 0.565 | right | female | | 5.5774 | 0.5083 | unsuccesful_stop | 0.49 | right | female | | 9.5856 | 0.5084 | go | 0.45 | right | female | -| 13.5939 | 0.5083 | succesful_stop | n/a | right | female | +| 13.5939 | 0.5083 | succesful_stop | n/a | n/a | female | | 17.1021 | 0.5083 | unsuccesful_stop | 0.633 | left | male | | 21.6103 | 0.5083 | go | 0.443 | left | male | ```` From 77b60845a671ce0dcb8faa10a668a6a09130363e Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Tue, 26 Jul 2022 10:48:34 -0500 Subject: [PATCH 005/143] Updated the link to event restructuring --- ...lingTools.md => EventFileRestructuring.md} | 88 +++++++++++++++---- docs/source/index.rst | 2 +- 2 files changed, 72 insertions(+), 18 deletions(-) rename docs/source/{HedRemodelingTools.md => EventFileRestructuring.md} (88%) diff --git a/docs/source/HedRemodelingTools.md b/docs/source/EventFileRestructuring.md similarity index 88% rename from docs/source/HedRemodelingTools.md rename to docs/source/EventFileRestructuring.md index ea3294b..dd01e40 100644 --- a/docs/source/HedRemodelingTools.md +++ b/docs/source/EventFileRestructuring.md @@ -8,13 +8,14 @@ This tutorial works through the process of restructuring event files using the H * [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) * [**Running remodeling tools**](running-remodeling-tools-anchor) * [**Remodeling operations**](remodeling-operations-anchor) - * [**Add structure column**](add-structure-column-anchor) Docs not written - * [**Add structure events**](add-structure-events-anchor) Docs not written - * [**Add structure numbers**](add-structure-numbers-anchor) Docs not written - * [**Derive column**](derive-column-anchor) Docs not written - * [**Factor column**](factor-column-anchor) Docs not written - * [**Factor HED**](factor-column-anchor) Docs not written - * [**Merge events**](merge-events-anchor) Docs not written + * [**Add structure column**](add-structure-column-anchor) Docs in process + * [**Add structure events**](add-structure-events-anchor) Docs in process + * [**Add structure numbers**](add-structure-numbers-anchor) Docs in process + * [**Derive column**](derive-column-anchor) Docs in process + * [**Factor column**](factor-column-anchor) + * [**Factor HED tags**](factor-hed-tags-anchor) Docs in process + * [**Factor HED type**](factor-hed-type-anchor) Docs in process + * [**Merge events**](merge-events-anchor) Docs in process * [**Remove columns**](remove-columns-anchor) * [**Rename columns**](rename-columns-anchor) * [**Reorder columns**](reorder-columns-anchor) @@ -326,15 +327,15 @@ The results of executing this *factor_column* command on the [sample events file | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | 0 | 0 | ```` -(factor-hed-anchor)= -### Factor HED +(factor-hed-tags-anchor)= +### Factor HED tags **NOT WRITTEN - PLACEHOLDER** Produce a list of factor columns based on the specified HED condition-variable values. -(parameters-for-factor-hed-anchor)= -```{admonition} Parameters for *factor_hed* command. +(parameters-for-factor-hed-tags-anchor)= +```{admonition} Parameters for *factor_hed_tags* command. :class: tip | Parameter | Type | Description | @@ -344,14 +345,14 @@ Produce a list of factor columns based on the specified HED condition-variable v | mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` -The *factor_hed* command in the following example specifies . . . +The *factor_hed-tags* command in the following example specifies . . . -````{admonition} Example *factor_hed* command. +````{admonition} Example *factor_hed_tags* command. :class: tip ```json { - "command": "factor_hed" + "command": "factor_hed_tags" "description": "xxx" "parameters": { "column_name": "match_side", @@ -365,16 +366,69 @@ The *factor_hed* command in the following example specifies . . . ``` ```` -The results of executing this *factor_hed* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *factor_hed-tags* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of *factor_hed*. +````{admonition} Results of *factor_hed_tags*. | onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | | 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | | 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | | 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + +(factor-hed-type-anchor)= +### Factor HED type + +**NOT WRITTEN - PLACEHOLDER** + +Produce a list of factor columns based on the specified HED condition-variable values. + +(parameters-for-factor-hed-type-anchor)= +```{admonition} Parameters for *factor_hed_type* command. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| column_name | str | The name of the column to be created or modified.| +| source_columns | list of str | A list of columns to be used for remapping. | +| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` + +The *factor_hed-type* command in the following example specifies . . . + +````{admonition} Example *factor_hed-type* command. +:class: tip + +```json +{ + "command": "factor_hed_type" + "description": "xxx" + "parameters": { + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } + } +} +``` +```` + +The results of executing this *factor_hed-type* command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Results of *factor_hed_type*. + +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | | 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` diff --git a/docs/source/index.rst b/docs/source/index.rst index 5f95903..b97b4cb 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -17,7 +17,7 @@ HED examples and tutorials HedValidation.md HedSearchAndSummary.md HedConditionsAndDesignMatrices.md - HedRemodelingTools.md + EventFileRestructuring.md .. toctree:: From 3b62eeb59e5f172a570d033c540ff8648e26b6a6 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Wed, 27 Jul 2022 10:35:49 -0500 Subject: [PATCH 006/143] Added documentation for split_event --- docs/source/EventFileRestructuring.md | 151 ++++++++++++++------------ 1 file changed, 80 insertions(+), 71 deletions(-) diff --git a/docs/source/EventFileRestructuring.md b/docs/source/EventFileRestructuring.md index dd01e40..cc3eb36 100644 --- a/docs/source/EventFileRestructuring.md +++ b/docs/source/EventFileRestructuring.md @@ -4,10 +4,10 @@ This tutorial works through the process of restructuring event files using the HED event remodeling tools. The tools are designed to be run on an entire BIDS dataset. -* [**What is restructuring?**](what-is-event-file-restructuring-anchor) -* [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) -* [**Running remodeling tools**](running-remodeling-tools-anchor) -* [**Remodeling operations**](remodeling-operations-anchor) +* [**What is restructuring?**](what-is-event-file-restructuring-anchor) Docs in process +* [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) Docs in process +* [**Running remodeling tools**](running-remodeling-tools-anchor) Docs in process +* [**Remodeling operations**](remodeling-operations-anchor) Docs in process * [**Add structure column**](add-structure-column-anchor) Docs in process * [**Add structure events**](add-structure-events-anchor) Docs in process * [**Add structure numbers**](add-structure-numbers-anchor) Docs in process @@ -151,7 +151,7 @@ The results of executing this *add_structure_events* command on the [sample even | 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | | 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | | 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | | 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` @@ -647,10 +647,13 @@ The results of executing the previous *rename_columns* command on the [sample ev ### Reorder columns Reorder the columns in the specified order. If *ignore_missing* is true, -the dataframe columns not included are discarded. +and items in the reorder list do not exist in the file, these columns are ignored. On the other hand, if *ignore_missing* is false, -column names that do not appear in the reorder list are moved to the end -of the dataframe in the same order that they appear. +a column name not appearing in the reorder list causes a *ValueError* to be raised. + +The *keep_others* parameter controls whether or not columns in the dataframe that +do not appear in the reorder list are dropped (*keep_others* is false) or +put at the end of the dataframe in the order they appear (*keep_others* is true). (parameters-for-reorder-columns-anchor)= ```{admonition} Parameters for *reorder_columns*. @@ -659,7 +662,8 @@ of the dataframe in the same order that they appear. | Parameter | Type | Description | | ------------ | ---- | ----------- | | column_order | list | A list of columns in the order they should appear in the data.| -| ignore_missing | boolean | If false, existing columns that aren't in column_names
are moved to the end and in the same relative
order that they originally appeared in the data. | +| ignore_missing | bool | If true and a column in column_order does not appear in the dataframe
a ValueError is raised, otherwise these columns are ignored. | +| keep_others | bool | If true, existing columns that aren't in column_order
are moved to the end in the same relative
order that they originally appeared in the data,
otherwise these columns are dropped.| ``` @@ -675,8 +679,9 @@ Since *ignore_missing* is true, these will be the only columns retained. "command": "reorder_columns", "description": "Reorder columns.", "parameters": { - "column_order": ["onset", "duration", "trial_type", "response_hand", "response_time"], - "ignore_missing": true + "column_order": ["onset", "duration", "response_time", "trial_type"], + "ignore_missing": true, + "keep_others": false } } ``` @@ -687,23 +692,23 @@ The results of executing the previous *reorder_columns* command on the [sample e ````{admonition} Results of *reorder_columns*. -| onset | duration | trial_type | response_hand | response_time | -| ----- | -------- | ---------- | ------------- | ------------- | -| 0.0776 | 0.5083 | go | right | 0.565 | -| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.49 | -| 9.5856 | 0.5084 | go | right | 0.45 | -| 13.5939 | 0.5083 | succesful_stop | n/a | n/a | -| 17.1021 | 0.5083 | unsuccesful_stop | left | 0.633 | -| 21.6103 | 0.5083 | go | left | 0.443 | +| onset | duration | response_time | trial_type | +| ----- | -------- | ---------- | ------------- | +| 0.0776 | 0.5083 | 0.565 | go | +| 5.5774 | 0.5083 | 0.49 | unsuccesful_stop | +| 9.5856 | 0.5084 | 0.45 | go | +| 13.5939 | 0.5083 | n/a | succesful_stop | +| 17.1021 | 0.5083 | 0.633 | unsuccesful_stop | +| 21.6103 | 0.5083 | 0.443 | go | ```` (split-event-anchor)= ### Split event -The *split_event* is the most complicated of the remodeling operations and is often used to -convert event files from using *trial-level* encoding to *event-level* encoding. +The *split_event*, which is one of the more complicated remodeling operations, +is often used to convert event files from using *trial-level* encoding to *event-level* encoding. In *trial-level* encoding each row of the event file represents all the events in a single trial -(usually some variation of cue-stimulus-response-feedback-ready sequence). +(usually some variation of the cue-stimulus-response-feedback-ready sequence). In *event-level* encoding, each row represents the marker for a single event. In this case a trial consists of a sequence of multiple events. @@ -731,65 +736,69 @@ Unlisted columns are filled with n/a. | Parameter | Type | Description | | ------------ | ---- | ----------- | | anchor_event | str | The name of the column that will be used for split-event codes.| -| event_selection | dict | Dictionary which events should be split (currently ignored and all events are split). | -| new_events | dict | Dictionary whose keys are the codes to be inserted as new events and whose values are dictionaries with keys *onset_source*, *duration*, and *copy_columns*. | -| add_event_numbers | boolean | If true, a column of event numbers are added before the split. | -| remove_parent_event | boolean | If true, remove parent event. | +| new_events | dict | Dictionary whose keys are the codes to be inserted as new events
and whose values are dictionaries with
keys *onset_source*, *duration*, and *copy_columns*. | +| add_event_numbers | bool | If true, adds a column called *event_numbers*. | +| remove_parent_event | bool | If true, remove parent event. | ``` -The *split_event* command in the following example specifies that *response_hand* -column be renamed *hand_used* and that the *sex* column be renamed *image_sex*. -The *face* entry in the mapping will be ignored because *ignore_missing* is true. -If *ignore_missing* is false, a `KeyError` exception is raised if a column specified in -the mapping does not correspond to a column name in the dataframe. +The *split_event* command in the following example specifies that new rows should be added +to encode the response and stop signal. The anchor column is still trial_type. +In a full processing example, it might make sense to rename *trial_type* to be +*event_type* and to delete the *response_time* and the *stop_signal_delay* +since these items have been unfolded into separate events. -````{admonition} An example split_event command. +````{admonition} An example *split_event* command. :class: tip ```json -{ - "command": "split_event", - "description": "Takes trial-level encoding and turns it into event-level encoding.", - "parameters": { - "anchor_column": "trial_type", - "event_selection": {}, - "new_events": { - "response": { - "onset": ["response_time"], - "duration": [0], - "column_columns": ["response_accuracy", "response_hand", "sex"] - }, - "stop_signal": { - "onset": ["stop_signal_delay"], - "duration": [0.5], - "column_columns": ["response_accuracy", "response_hand", "sex"] - } - }, - "add_event_numbers": true, - "remove_parent_event": false +{ + "command": "split_events", + "description": "add response events to the trials.", + "parameters": { + "anchor_column": "trial_type", + "event_numbers_column": "trial_number", + "new_events": { + "response": { + "onset_source": ["response_time"], + "duration": [0], + "copy_columns": ["response_accuracy", "response_hand", "sex", "trial_number"] + }, + "stop_signal": { + "onset_source": ["stop_signal_delay"], + "duration": [0.5], + "copy_columns": ["trial_number"] + } + }, + "remove_parent_event": false + } } -} ``` ```` The results of executing this *split_event* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of the split_event command. -| onset | duration | trial_type | response_accuracy | response_hand | sex | trial_number | -| ----- | -------- | ---------- | ----------------- | ------------- | --- | ------------ | -| 0.0776 | 0.5083 | go | correct | right | female | 1 | -| 0.6426 | 0.0 | response | correct | right | female | 1 | -| 5.5774 | 0.5083 | unsuccesful_stop | correct | right | female | 2 | -| 5.7774 | 0.5 | stop_signal | correct | right | female | 2 | -| 6.0674 | 0.0 | response | correct | right | female | 2 | -| 9.5856 | 0.5084 | go | correct | right | female | 3 | -| 10.0356 | 0.0 | response | correct | right | female | 3 | -| 13.5939 | 0.5083 | succesful_stop | n/a | n/a | female | 4 | -| 13.7939 | 0.5 | stop_signal | n/a | right | female | 4 | -| 17.1021 | 0.5083 | unsuccesful_stop | correct | left | male | 5 | -| 17.3521 | 0.5 | stop_signal | correct | left | male | 5 | -| 17.7351 | 0.0 | response | correct | left | male | 5 | -| 21.6103 | 0.5083 | go | correct | left | male | 6 | -| 22.0533 | 0.0 | response | correct | left | male | 6 | -```` \ No newline at end of file +````{admonition} Results of the previous *split_event* command. + +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | trial_number | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -------- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | 1 | +| 0.6426 | 0 | response | n/a | n/a | correct | right | female | 1 | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | 2 | +| 5.7774 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | 2 | +| 6.0674 | 0 | response | n/a | n/a | correct | right | female | 2 | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | 3 | +| 10.0356 | 0 | response | n/a | n/a | correct | right | female | 3 | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | 4 | +| 13.7939 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | 4 | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | 5 | +| 17.3521 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | 5 | +| 17.7351 | 0 | response | n/a | n/a | correct | left | male | 5 | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | 6 | +| 22.0533 | 0 | response | n/a | n/a | correct | left | male | 6 | +```` + +Note that the event numbers are added before the splitting and then +copied as the new events are created. +This strategy results in a trial number column associated with the events, +an alternative to the more complicated process of adding a structure column after splitting. \ No newline at end of file From 37051700a1b7643d969036cca68e3f6f4ca8cefb Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Wed, 27 Jul 2022 16:30:38 -0500 Subject: [PATCH 007/143] Added italics for parameters --- docs/source/EventFileRestructuring.md | 142 +++++++++++------- ...b-0013_task-stopsignal_acq-seq_events.json | 63 ++++++++ 2 files changed, 154 insertions(+), 51 deletions(-) create mode 100644 docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json diff --git a/docs/source/EventFileRestructuring.md b/docs/source/EventFileRestructuring.md index cc3eb36..c041f84 100644 --- a/docs/source/EventFileRestructuring.md +++ b/docs/source/EventFileRestructuring.md @@ -101,7 +101,7 @@ The results of executing this *add_structure_column* command on the [sample even | 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | | 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | | 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | | 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` @@ -119,9 +119,9 @@ Add events representing the start of a structural element such as a trial or a b | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list | Names of the columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *column_name* | str | The name of the column to be created or modified.| +| *source_columns* | list | Names of the columns to be used for remapping. | +| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` The *add_structure_events* command in the following example specifies . . . @@ -171,9 +171,9 @@ Add a column with numbers corresponding to a structural element. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list of str | A list of columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *column_name* | str | The name of the column to be created or modified.| +| *source_columns* | list of str | A list of columns to be used for remapping. | +| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` The *add_structure_numbers* command in the following example specifies . . . @@ -227,9 +227,9 @@ based on predefined combinations of values in other columns. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list of str | A list of columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *column_name* | str | The name of the column to be created or modified.| +| *source_columns* | list of str | A list of columns to be used for remapping. | +| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` The *derive_column* command in the following example specifies . . . @@ -279,11 +279,11 @@ If no values are specified, all unique values in that column are factored. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be factored.| -| factor_values | list | A list of column values to be included as factors. | -| factor_names | list| A list of column names for created factors
of the same length as factor_values. | -| ignore_missing| bool | If true, columns corresponding to factor values
that do not appear in column are included. | -| overwrite_existing| bool | If true an existing factor column is overwritten. | +| *column_name* | str | The name of the column to be factored.| +| *factor_values* | list | A list of column values to be included as factors. | +| *factor_names* | list| A list of column names for created factors
of the same length as factor_values. | +| *ignore_missing* | bool | If true, columns corresponding to factor values
that do not appear in column are included. | +| *overwrite_existing* | bool | If true an existing factor column is overwritten. | ``` The *factor_column* command in the following example specifies that factor columns should be created for *succesful_stop* and *unsuccesful_stop* of the *trial_type* column. @@ -340,9 +340,9 @@ Produce a list of factor columns based on the specified HED condition-variable v | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list of str | A list of columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *column_name* | str | The name of the column to be created or modified.| +| *source_columns* | list of str | A list of columns to be used for remapping. | +| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` The *factor_hed-tags* command in the following example specifies . . . @@ -383,9 +383,19 @@ The results of executing this *factor_hed-tags* command on the [sample events fi (factor-hed-type-anchor)= ### Factor HED type -**NOT WRITTEN - PLACEHOLDER** +The factor HED type operation produces factor columns in an event file +based on values of the specified HED type tag. +The most common type is the HED *Condition-variable* tag, which corresponds to +factor vectors based in the experimental design. +Other commonly use type tags include *Task*, *Control-variable*, and *Time-block*. -Produce a list of factor columns based on the specified HED condition-variable values. +We assume that the dataset has been annotated using HED tags to properly document +the experiment conditions and focus on how such an annotated dataset can be +used with event remodeling to produce factor columns in the event file corresponding to these +condition variables. + +For additional information on how to encode experimental designs using HED please see +[HED conditions and design matrices](https://hed-examples.readthedocs.io/en/latest/HedConditionsAndDesignMatrices.html). (parameters-for-factor-hed-type-anchor)= ```{admonition} Parameters for *factor_hed_type* command. @@ -393,20 +403,20 @@ Produce a list of factor columns based on the specified HED condition-variable v | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list of str | A list of columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *type_tag* | str | A HED tag used to produce the factors (most commonly *Condition-variable*).| +| *type_values* | list | A list of values to factor for the *type_tag*.
If empty all values of that type_tag are used. | +| *overwrite_existing* | bool | If true an existing factor column is overwritten. | ``` -The *factor_hed-type* command in the following example specifies . . . +To simplifyThe *factor_hed_type* command in the following example specifies . . . -````{admonition} Example *factor_hed-type* command. +````{admonition} Example *factor_hed_type* command. :class: tip ```json { "command": "factor_hed_type" - "description": "xxx" + "description": "Factor based on the sex of the images being presented." "parameters": { "column_name": "match_side", "source_columns": ["response_accuracy", "response_hand"], @@ -419,18 +429,48 @@ The *factor_hed-type* command in the following example specifies . . . ``` ```` -The results of executing this *factor_hed-type* command on the [sample events file](sample-remodeling-events-file-anchor) are: +In order to use the JSON file. The full file is at: + + +````{admonition} Example *factor_hed_type* command. +:class: tip + +```json +{ + "trial_type": { + "HED": { + "succesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/succesful_stop", + "unsuccesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/unsuccesful_stop", + "go": "Sensory-presentation, Visual-presentation, Image, Label/go" + }, + "sex": { + "HED": { + "male": "Def/Male-image-cond", + "female": "Def/Female-image-cond" + } + }, + "hed_defs": { + "HED": { + "def_male": "(Definition/Male-image-cond, (Condition-variable/Image-sex, (Male, (Image, Face))))", + "def_female": "(Definition/Female-image-cond, (Condition-variable/Image-sex, (Female, (Image, Face))))" + } + } +} +``` +```` + +The results of executing this *factor_hed_type* command on the [sample events file](sample-remodeling-events-file-anchor) are: ````{admonition} Results of *factor_hed_type*. -| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | -| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | -| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | -| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | -| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | Image-sex.Female-image-cond | Image-sex.Male-image-cond | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | ------- | ---------- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | 1 | 0 | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | 1 | 0 | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | 1 | 0 | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | 1 | 0 | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | 0 | 1 | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | 0 | 1 | ```` (merge-events-anchor)= @@ -446,9 +486,9 @@ One long event is represented by multiple repeat events. Merges these same event | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be created or modified.| -| source_columns | list of str | A list of columns to be used for remapping. | -| mapping | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *column_name* | str | The name of the column to be created or modified.| +| *source_columns* | list of str | A list of columns to be used for remapping. | +| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | ``` The *merge_events* command in the following example specifies . . . @@ -500,8 +540,8 @@ parameter is *false*, a `KeyError` is raised for missing column. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| remove_names | list of str | A list of columns to remove.| -| ignore_missing | boolean | If true, missing columns are ignored, otherwise raise an error. | +| *remove_names* | list of str | A list of columns to remove.| +| *ignore_missing* | boolean | If true, missing columns are ignored, otherwise raise an error. | ``` The *remove_column* command in the following example removes the *stop_signal_delay* and @@ -551,8 +591,8 @@ Remove rows in which the named column has one of the specified values. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_name | str | The name of the column to be tested.| -| remove_values | list | A list of values to be tested for removal. | +| *column_name* | str | The name of the column to be tested.| +| *remove_values* | list | A list of values to be tested for removal. | ``` The following example *remove_rows* command removes the rows whose *trial_type* column @@ -599,8 +639,8 @@ Rename columns by providing a dictionary of old names to new names. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_mapping | dict | The keys are the old column names and the values are the new names.| -| ignore_missing | bool | If false, a key error is raised if a dictionary key is not a column name . | +| *column_mapping* | dict | The keys are the old column names and the values are the new names.| +| *ignore_missing* | bool | If false, a key error is raised if a dictionary key is not a column name. | ``` The *rename_columns* command in the following example specifies that *response_hand* column be @@ -661,9 +701,9 @@ put at the end of the dataframe in the order they appear (*keep_others* is true) | Parameter | Type | Description | | ------------ | ---- | ----------- | -| column_order | list | A list of columns in the order they should appear in the data.| -| ignore_missing | bool | If true and a column in column_order does not appear in the dataframe
a ValueError is raised, otherwise these columns are ignored. | -| keep_others | bool | If true, existing columns that aren't in column_order
are moved to the end in the same relative
order that they originally appeared in the data,
otherwise these columns are dropped.| +| *column_order* | list | A list of columns in the order they should appear in the data.| +| *ignore_missing* | bool | If true and a column in *column_order* does not appear in the dataframe
a *ValueError* is raised, otherwise these columns are ignored. | +| *keep_others* | bool | If true, existing columns that aren't in *column_order*
are moved to the end in the same relative
order that they originally appeared in the data,
otherwise these columns are dropped.| ``` @@ -735,10 +775,10 @@ Unlisted columns are filled with n/a. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| anchor_event | str | The name of the column that will be used for split-event codes.| -| new_events | dict | Dictionary whose keys are the codes to be inserted as new events
and whose values are dictionaries with
keys *onset_source*, *duration*, and *copy_columns*. | -| add_event_numbers | bool | If true, adds a column called *event_numbers*. | -| remove_parent_event | bool | If true, remove parent event. | +| *anchor_event* | str | The name of the column that will be used for split-event codes.| +| *new_events* | dict | Dictionary whose keys are the codes to be inserted as new events
and whose values are dictionaries with
keys *onset_source*, *duration*, and *copy_columns*. | +| *add_event_numbers* | bool | If true, adds a column called *event_numbers*. | +| *remove_parent_event* | bool | If true, remove parent event. | ``` diff --git a/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json b/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json new file mode 100644 index 0000000..205666d --- /dev/null +++ b/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json @@ -0,0 +1,63 @@ +{ + "trial_type": { + "Description": "Description for trial_type", + "HED": { + "succesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/succesful_stop", + "unsuccesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/unsuccesful_stop", + "go": "Sensory-presentation, Visual-presentation, Image, Label/go" + }, + "Levels": { + "succesful_stop": "Presentation of a face image in a trial with a stop signal in which participant inhibited response.", + "unsuccesful_stop": "Presentation of a face image in a trial with a stop signal in which participant did not inhibit response.", + "go": "Presentation of a face image in a trial with no stop signal" + } + }, + "stop_signal_delay": { + "Description": "Stop-signal cue delay from onset.", + "HED": "((Cue, Think/Inhibit), Delay/# s)" + }, + "response_time": { + "Description": "Response time delay from onset.", + "HED": "(Participant-response, Delay/# s)" + }, + "response_accuracy": { + "Description": "Indicates whether a response correctly indicated", + "HED": { + "incorrect": "(Incorrect-action, (Identify, (Image, Sex)))", + "correct": "(Correct-action, (Identify, (Image, Sex)))" + }, + "Levels": { + "incorrect": "Used the wrong hand to indicate the sex of the face image.", + "correct": "Used the correct hand to indicate the sex of the face image." + } + }, + "response_hand": { + "Description": "Description for response_hand", + "HED": { + "left": "(Hand, (Left-side-of, Body))", + "right": "(Hand, (Right-side-of, Body))" + }, + "Levels": { + "left": "A response using the left hand.", + "right": "A response using the right hand." + } + }, + "sex": { + "Description": "The sex of the image", + "HED": { + "male": "Def/Male-image-cond", + "female": "Def/Female-image-cond" + }, + "Levels": { + "male": "The image was the face of a male person.", + "female": "The image was the face of a female person." + } + }, + "hed_defs": { + "Description": "HED user-defined terms for the dataset.", + "HED": { + "def_male": "(Definition/Male-image-cond, (Condition-variable/Image-sex, (Male, (Image, Face))))", + "def_female": "(Definition/Female-image-cond, (Condition-variable/Image-sex, (Female, (Image, Face))))" + } + } +} \ No newline at end of file From d0c8cb990eac6e176584888231dd0e8a215abbf1 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sat, 30 Jul 2022 13:15:53 -0500 Subject: [PATCH 008/143] Worked on the ConditionsAndDesign tutorial --- docs/source/EventFileRestructuring.md | 26 +- docs/source/HedConditionsAndDesignMatrices.md | 278 +++++++++++++++++- docs/source/package.json | 14 + 3 files changed, 308 insertions(+), 10 deletions(-) create mode 100644 docs/source/package.json diff --git a/docs/source/EventFileRestructuring.md b/docs/source/EventFileRestructuring.md index c041f84..aff01f7 100644 --- a/docs/source/EventFileRestructuring.md +++ b/docs/source/EventFileRestructuring.md @@ -25,7 +25,14 @@ This tutorial works through the process of restructuring event files using the H (what-is-event-file-restructuring-anchor)= ## What is event file restructuring? -**Need brief introduction to event remodeling here** +Event file restructuring generally falls into four categories: cleanup, +row modifications, column modifications, and structure modifications. + +#### Cleanup operations + +Cleanup operations include: *rename_columns*, *reorder_columns*, and *remove_columns*. + +#### Row modifications (installation-of-remodeling-tools-anchor)= ## Installation of remodeling tools @@ -44,7 +51,7 @@ The examples in this chapter use the following excerpt from sub-0013 stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneuro.org) as ds002790. (sample-remodeling-events-file-anchor)= -````{admonition} Excerpt from event file for a stop-go task. +````{admonition} Excerpt from event file for a stop-go task of AOMIC-PIOP2 (ds002790). | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | | 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | @@ -405,7 +412,9 @@ For additional information on how to encode experimental designs using HED pleas | ------------ | ---- | ----------- | | *type_tag* | str | A HED tag used to produce the factors (most commonly *Condition-variable*).| | *type_values* | list | A list of values to factor for the *type_tag*.
If empty all values of that type_tag are used. | -| *overwrite_existing* | bool | If true an existing factor column is overwritten. | +| *overwrite_existing* | bool | If true, an existing factor columns is overwritten. | +| *include_hed_strings* | bool | If true, a column *hed_expand* with HED strings is included. | +| *one_hot_factors* | bool | If true, the factors use one-hot representation (zeros and ones). | ``` To simplifyThe *factor_hed_type* command in the following example specifies . . . @@ -418,12 +427,11 @@ To simplifyThe *factor_hed_type* command in the following example specifies . . "command": "factor_hed_type" "description": "Factor based on the sex of the images being presented." "parameters": { - "column_name": "match_side", - "source_columns": ["response_accuracy", "response_hand"], - "mapping": { - "left": [["correct", "left"], ["incorrect", "right"]], - "right": [["correct", "right"], ["incorrect", "left"]] - } + "type_tag": "Condition-variable", + "type_values": [], + "overwrite_existing": true, + "include_hed_strings": false, + "one_hot_factors": true } } ``` diff --git a/docs/source/HedConditionsAndDesignMatrices.md b/docs/source/HedConditionsAndDesignMatrices.md index a7566ac..254f6af 100644 --- a/docs/source/HedConditionsAndDesignMatrices.md +++ b/docs/source/HedConditionsAndDesignMatrices.md @@ -1,3 +1,279 @@ # HED conditions and design matrices -**Under construction** +This tutorial discusses how information from neuroimaging experiments should be +stored and annotated so that the underlying experimental design and experimental conditions +for a dataset can be automatically extracted, summarized, and used in analysis. +The mechanisms for doing this use HED (Hierarchical Event Descriptors) in conjunction +with a [BIDS](https://bids.neuroimaging.io/) +(Brain Imaging Data Structure) representation of the dataset. + +The tutorial assumes that you have a basic understanding of HED and +how HED annotations are used in BIDS. +Please review [**Annotating a BIDS dataset**](https://bids-standard.github.io/bids-starter-kit/tutorials/annotation.html), +the [**BIDS annotation quickstart**](https://hed-examples.readthedocs.io/en/latest/BidsAnnotationQuickstart.html), and the +[**HED annotation quickstart**](https://hed-examples.readthedocs.io/en/latest/HedAnnotationQuickstart.html) +tutorials as needed. + + + +* [**Neuroimaging experimental design**](neuroimaging-experimental-anchor) + * [**Design matrices and factor variables**](design-matrices-and-factor-variables-anchor) + * [**Types of condition encoding**](types-of-condition-encoding-anchor) +* [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) Docs in process +* [**Running remodeling tools**](running-remodeling-tools-anchor) Docs in process +* [**Remodeling operations**](remodeling-operations-anchor) Docs in process + * [**Add structure column**](add-structure-column-anchor) Docs in process + * [**Add structure events**](add-structure-events-anchor) Docs in process + +This tutorial introduces tools and strategies for including this information +as part of a dataset without excessive effort on the part of the researcher. +The discussion mainly focuses on categorical variables, but HED +also can encode numerical values as discussed later in the tutorial. + +(neuroimaging-experimental-anchor)= +## Neuroimaging experimental design +Traditional neuroimaging experiments are carefully designed to control and +document the external conditions under which the experiment is conducted. +Often a few items such as the task or the properties of a stimulus are +systematically varied as the stimulus is presented and participant responses +are recorded. + +For example, in an experiment to test for differences in +brain responses to pictures of houses versus pictures of faces, +the researcher would label time points in the recording corresponding +to presentations of the respective pictures so that differences in +brain responses between the two types of pictures could be observed. +An fMRI analysis might determine which brain regions +showed a significant response differential between the two types of responses. +An EEG/MEG analysis might also focus on the differences in time courses +between the responses to the two types of images. + +Thus, the starting point for many analyses is the association of +labels corresponding to different **experimental conditions** with +time points in the data recording. +In BIDS, this association is stored an `events.tsv` file paired +with the data recording, +but this information may also be stored as part of the recording +itself, depending on the technology and the format of the recording. + +(design-matrices-and-factor-variables-anchor)= +### Design matrices and factor variables + +The type of information included for the experimental conditions +and how this information is stored depends very much on the experiment. +Most analysis tools require a vector (sometimes called a **factor vector**) +of elements associated with the event markers for each type of experimental condition. + +For linear modeling and other types of regression, these factor vectors are assembled +into **design matrix** to use as input for the analysis. +Design matrices can also include other types of columns depending on the modeling strategy. + +(types-of-condition-encoding-anchor)= +### Types of condition encoding + +Consider the simple example introduced above of an experiment which +varies the stimuli between pictures of houses and faces to measure +differences in response. +The following example shows three possible types of encodings +(**categorical**, **ordinal**, and **one-hot**) that might be sued +for this association. The table shows an excerpt from a putative events file, +with the onset column (required by BIDS) containing the time of the event marker +relative to the start of the associated data recording. +The duration column (also required by BIDS) contains the duration of the +image presentation in seconds. + +(different-encodings-of-design-variables-anchor)= +````{admonition} Example 1: Different encodings of a column with categorical values. +| onset | duration | categorical | ordinal | one_hot.house | one_hot.face | +| ----- | -------- |----------- |-------- | ------------- | ------------ | +| 2.010 | 0.1 | house | 1 | 1 | 0 | +| 3.210 | 0.1 | house | 1 | 1 | 0 | +| 4.630 | 0.1 | face | 2 | 0 | 1 | +| 6.012 | 0.1 | house | 1 | 1 | 0 | +| 7.440 | 0.1 | face | 2 | 0 | 1 | +```` + +The **categorical** encoding assigns laboratory-specific names to the +different types of stimuli. +In theory, this categorical column consisting of the strings *house* and *face* +could be used as a factor vector or as part of a design matrix for regression. +However, many analysis tools require that these names be assigned numerical +values. + +The **ordinal** encoding assigns an arbitrary sequence of numbers corresponding +to the unique values. +If there are only 2 values, the values -1 and 1 are often used. +Ordinal encodings impose an order based on the values +chosen, which may have undesirable affects on the results of analyses such +as regression if the ordering/relative sizes do not reflect the +properties of the encoded experimental conditions. + +In the example above, the experimental conditions houses and faces do not +have an ordering/size relationship reflected by the encoding (house=1, face=2). +In addition, neither categorical nor ordinal encoding +can represent items falling into multiple categories of the same condition at the same time. +For these reasons, many statistical tools require one-hot encoding. + +In **one-hot** encoding, each possible value of the condition is represented +by its own column with 1's representing the presence of that condition value +and experimental conditions and 0's otherwise. One-hot encodes all values +without bias and allows for a given event to be a member of multiple categories. +This representation is required for many machine-learning models. +A disadvantage is that it can generate a large number of columns if there +are many unique categorical values. It can also cause a problem if not all +files contain the same values, as then different files may have different columns. + +(hed-annotation-for-conditions-anchor) +## HED annotation for conditions + +As mentioned above, HED (Hierarchical Event Descriptors) provide several mechanisms for easily +annotating the experimental conditions represented by a BIDS dataset so that +the information can be automatically extracted, summarized and used by tools. + +HED has three ways of annotating experimental conditions: condition variables without definitions, +condition variables with definitions but no levels, and condition variables with levels. +All three mechanisms use the *Condition-variable* tag as part of the annotation. +The three mechanisms can be used in any combination to document the experimental design +for a dataset. + +(condition-variables-without-definitions-anchor)= +### Condition variables without definitions + +The simplest way to encode experimental conditions is to use named *Condition-variable* +tags for each condition value. The following is a sample excerpt from +a possible event file for the experiment to distinguish brain responses +for houses and faces. We assume that the participant has been +instructed to push a button to indicate that he/she has identified +the image as a either a house or a face. + +(sample-house-face-example-anchor)= +````{admonition} Example 2. Excerpt from a sample event file from house-face experiment. +| onset | duration | event_type | response_time | stim_file | +| ----- | -------- |----------- |-------- | ---------- | +| 2.010 | 0.1 | house | 0.23 | ranch1.png | +| 3.210 | 0.1 | house | 0.12 | colonial68.png | +| 4.630 | 0.1 | face | 0.41 | female43.png | +| 6.012 | 0.1 | house | 0.35 | castle2.png | +| 7.440 | 0.1 | face | 0.32 | male81.png | +```` + +As explained in [**BIDS annotation quickstart**](https://hed-examples.readthedocs.io/en/latest/BidsAnnotationQuickstart.html), +the most commonly used strategy for annotating events in a BIDS dataset is +to create a single JSON file located in the dataset root containing the annotations +for the columns. The following shows a minimal example + +````{admonition} Example 3: Minimal JSON sidecar with HED annotations for Example 1. +:class: tip + +```json +{ + "event_type": { + "HED": { + "house": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Building/House), Condition-variable/House-cond", + "face": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Face), Condition-variable/Face-cond" + } + }, + "response_time": { + "HED": "(Participant-response, (Press, Push-button), Delay/#)" + }, + "stim_file": { + "HED": "(Image, Pathname/#)" + } +} +``` +```` + +Each row in an `events.tsv` file represents a time marker in the corresponding data recording. +At analysis time, HED tools look up each column value in the JSON file and concatenate the +corresponding HED annotation into a single string representing the annotation for that row. +Annotations without #'s are used directly, while annotations with # have the corresponding +column values substituted when the annotation is assembled. + +````{admonition} Example 3: HED annotation for first event in Example 1 using JSON sidecar of Example 2. +:class: tip +> "*Sensory-presentation*, *Visual-presentation*, *Experimental-stimulus*, +> (*Image*, *Building/House*), *Condition-variable/House-cond*, +> (*Participant-response*, (*Press*, *Push-button*), *Delay/0.23*), +> (*Image*, *Pathname/ranch1.png*)" +```` + +HED tools have the capability of automatically detecting *Condition-variable* +tags in annotated HED datasets and creating factor vectors and summaries automatically. +Example 4 shows the event file after HED tools have appended one-hot factor vectors. + + +````{admonition} Example 4. Example 2 after HED tools have extracted one-hot factor vectors. +| onset | duration | event_type | response_time | stim_file | House-cond | Face-cond | +| ----- | -------- |----------- |-------- | ---------- |----------- | ----------- | +| 2.010 | 0.1 | house | 0.23 | ranch1.png | 1 | 0 | +| 3.210 | 0.1 | house | 0.12 | colonial68.png | 1 | 0 | +| 4.630 | 0.1 | face | 0.41 | female43.png | 0 | 1 | +| 6.012 | 0.1 | house | 0.35 | castle2.png | 1 | 0 | +| 7.440 | 0.1 | face | 0.32 | male81.png | 0 | 1 | +```` + +Example 5 shows the JSON summary that HED tools can extract once a dataset has been +annotated using HED. This very simple example only had two condition variables +and only used direct references to condition variables. +The summary shows that of the total of 5 events in the file 3 events were under +the house condition and 2 events were under the face condition. + +````{admonition} Example 5: The HED tools summary of condition variables for Example 4. +:class: tip + +```json +{ + "house-cond": { + "name": "house-cond", + "variable_type": "condition-variable", + "levels": 0, + "direct_references": 3, + "total events": 5, + "number events": 3, + "number_multiple": 0, + "multiple maximum": 1, + "level counts": {} + }, + "face-cond": { + "name": "face-cond", + "variable_type": "condition-variable", + "levels": 0, + "direct_references": 2, + "total events": 5, + "number events": 2, + "number_multiple": 0, + "multiple maximum": 1, + "level counts": {} + } +} +```` +There were no events in multiple categories of the same condition variables +(which would not be possible since these condition variables were referenced +directly rather than assigned levels). +All names are translated to lower case as HED is case-insensitive with respect to analysis. + +These HED summaries can be created for other tags besides *Condition-variable*, +hence the variable_type is given in the summary of Example 5. +Other commonly created summaries are for *Task* and *Control-variable*. + + +## Definitions +(sample-design-matrix-events-file-anchor)= +````{admonition} Excerpt from event file for a stop-go task. + +| onset | duration | sample | event_type | face_type | rep_status | trial | rep_lag | value | stim_file | +| ----- | -------- | ------ | ---------- | --------- | ---------- | ----- | ------- | ----- | --------- | +| 0.004 | n/a | 1.0 | setup_right_sym | n/a | n/a | n/a | n/a | 3 | n/a | +| 24.2098181818 | n/a | 6052.4545 | show_face_initial | unfamiliar_face | first_show | 1 | n/a | 13 | u032.bmp | +| 25.0352727273 | n/a | 6258.8182 | show_circle | n/a | n/a | 1 | n/a | 0 | circle.bmp | +| 25.158 | n/a | 6289.5 | left_press | n/a | n/a | 1 | n/a | 256 | n/a | +| 26.7352727273 | n/a | 6683.8182 | show_cross | n/a | n/a | 2 | n/a | 1 | cross.bmp | +| 27.2498181818 | n/a | 6812.4545 | show_face | unfamiliar_face | immediate_repeat | 2 | 1 | 14 | u032.bmp | +| 27.8970909091 | n/a | 6974.2727 | left_press | n/a | n/a | 2 | n/a | 256 | n/a | +| 28.0998181818 | n/a | 7024.9545 | show_circle | n/a | n/a | 2 | n/a | 0 | circle.bmp | +| 29.7998181818 | n/a | 7449.9545 | show_cross | n/a | n/a | 3 | n/a | 1 | cross.bmp | +| 30.3570909091 | n/a | 7589.2727 | show_face | unfamiliar_face | first_show | 3 | n/a | 13 | u088.bmp | +```` + + + diff --git a/docs/source/package.json b/docs/source/package.json new file mode 100644 index 0000000..28539dd --- /dev/null +++ b/docs/source/package.json @@ -0,0 +1,14 @@ +{ + "event_type": { + "HED": { + "house": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Building/House), Condition-variable/House-cond", + "face": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Face), Condition-variable/Face-cond" + } + }, + "response_time": { + "HED": "Participant-response, Delay/#" + }, + "stim_file": { + "HED": "(Image, Pathname/#)" + } +} From 98f299645d1bb69b4553b22415c007ec8cd54116 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sat, 30 Jul 2022 18:37:51 -0500 Subject: [PATCH 009/143] Updated condition variables --- docs/source/HedConditionsAndDesignMatrices.md | 346 +++++++++++++----- 1 file changed, 262 insertions(+), 84 deletions(-) diff --git a/docs/source/HedConditionsAndDesignMatrices.md b/docs/source/HedConditionsAndDesignMatrices.md index 254f6af..3772a90 100644 --- a/docs/source/HedConditionsAndDesignMatrices.md +++ b/docs/source/HedConditionsAndDesignMatrices.md @@ -19,11 +19,10 @@ tutorials as needed. * [**Neuroimaging experimental design**](neuroimaging-experimental-anchor) * [**Design matrices and factor variables**](design-matrices-and-factor-variables-anchor) * [**Types of condition encoding**](types-of-condition-encoding-anchor) -* [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) Docs in process -* [**Running remodeling tools**](running-remodeling-tools-anchor) Docs in process -* [**Remodeling operations**](remodeling-operations-anchor) Docs in process - * [**Add structure column**](add-structure-column-anchor) Docs in process - * [**Add structure events**](add-structure-events-anchor) Docs in process +* [**HED annotations for conditions**](hed-annotations-for-conditions-anchor) + * [**Direct condition variables**](direct-condition-variables-anchor) + * [**Defined condition variables**](defined-condition-variables-anchor) + * [**Column vs row conditions**](column-vs-row-conditions-anchor) This tutorial introduces tools and strategies for including this information as part of a dataset without excessive effort on the part of the researcher. @@ -123,8 +122,8 @@ A disadvantage is that it can generate a large number of columns if there are many unique categorical values. It can also cause a problem if not all files contain the same values, as then different files may have different columns. -(hed-annotation-for-conditions-anchor) -## HED annotation for conditions +(hed-annotations-for-conditions-anchor)= +## HED annotations for conditions As mentioned above, HED (Hierarchical Event Descriptors) provide several mechanisms for easily annotating the experimental conditions represented by a BIDS dataset so that @@ -136,25 +135,23 @@ All three mechanisms use the *Condition-variable* tag as part of the annotation. The three mechanisms can be used in any combination to document the experimental design for a dataset. -(condition-variables-without-definitions-anchor)= -### Condition variables without definitions +(direct-condition-variables-anchor)= +### Direct condition variables The simplest way to encode experimental conditions is to use named *Condition-variable* tags for each condition value. The following is a sample excerpt from -a possible event file for the experiment to distinguish brain responses -for houses and faces. We assume that the participant has been -instructed to push a button to indicate that he/she has identified -the image as a either a house or a face. +a simplified event file for an experiment to distinguish brain responses +for houses and faces. (sample-house-face-example-anchor)= -````{admonition} Example 2. Excerpt from a sample event file from house-face experiment. -| onset | duration | event_type | response_time | stim_file | -| ----- | -------- |----------- |-------- | ---------- | -| 2.010 | 0.1 | house | 0.23 | ranch1.png | -| 3.210 | 0.1 | house | 0.12 | colonial68.png | -| 4.630 | 0.1 | face | 0.41 | female43.png | -| 6.012 | 0.1 | house | 0.35 | castle2.png | -| 7.440 | 0.1 | face | 0.32 | male81.png | +````{admonition} Example 2. Excerpt from a sample event file from a simplified house-face experiment. +| onset | duration | event_type | stim_file | +| ----- | -------- |----------- | ---------- | +| 2.010 | 0.1 | show_house | ranch1.png | +| 3.210 | 0.1 | show_house | colonial68.png | +| 4.630 | 0.1 | show_face | female43.png | +| 6.012 | 0.1 | show_house | castle2.png | +| 7.440 | 0.1 | show_face | male81.png | ```` As explained in [**BIDS annotation quickstart**](https://hed-examples.readthedocs.io/en/latest/BidsAnnotationQuickstart.html), @@ -167,18 +164,15 @@ for the columns. The following shows a minimal example ```json { - "event_type": { - "HED": { - "house": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Building/House), Condition-variable/House-cond", - "face": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Face), Condition-variable/Face-cond" - } - }, - "response_time": { - "HED": "(Participant-response, (Press, Push-button), Delay/#)" - }, - "stim_file": { - "HED": "(Image, Pathname/#)" - } + "event_type": { + "HED": { + "show_house": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Building/House), Condition-variable/House-cond", + "show_face": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Face), Condition-variable/Face-cond" + } + }, + "stim_file": { + "HED": "(Image, Pathname/#)" + } } ``` ```` @@ -191,89 +185,273 @@ column values substituted when the annotation is assembled. ````{admonition} Example 3: HED annotation for first event in Example 1 using JSON sidecar of Example 2. :class: tip -> "*Sensory-presentation*, *Visual-presentation*, *Experimental-stimulus*, -> (*Image*, *Building/House*), *Condition-variable/House-cond*, -> (*Participant-response*, (*Press*, *Push-button*), *Delay/0.23*), + +> "*Sensory-presentation*, *Visual-presentation*, *Experimental-stimulus*, +> (*Image*, *Building/House*), *Condition-variable/House-cond*, > (*Image*, *Pathname/ranch1.png*)" ```` +Notice that *Building/House* is a partial path rather than a single tag. +This is because *House* is currently not part of the base HED vocabulary. +However, users are allowed to extend tags at most nodes in the HED schema, +but they must use a path that includes a least one ancestor that is in the HED schema. + HED tools have the capability of automatically detecting *Condition-variable* tags in annotated HED datasets and creating factor vectors and summaries automatically. Example 4 shows the event file after HED tools have appended one-hot factor vectors. -````{admonition} Example 4. Example 2 after HED tools have extracted one-hot factor vectors. -| onset | duration | event_type | response_time | stim_file | House-cond | Face-cond | -| ----- | -------- |----------- |-------- | ---------- |----------- | ----------- | -| 2.010 | 0.1 | house | 0.23 | ranch1.png | 1 | 0 | -| 3.210 | 0.1 | house | 0.12 | colonial68.png | 1 | 0 | -| 4.630 | 0.1 | face | 0.41 | female43.png | 0 | 1 | -| 6.012 | 0.1 | house | 0.35 | castle2.png | 1 | 0 | -| 7.440 | 0.1 | face | 0.32 | male81.png | 0 | 1 | +````{admonition} Example 4. Event file from Example 2 after one-hot factor vector extraction. + +| onset | duration | event_type | stim_file | house-cond | face-cond | +| ----- | -------- |----------- |-------- | ---------- |----------- | +| 2.010 | 0.1 | show_house | ranch1.png | 1 | 0 | +| 3.210 | 0.1 | show_house | colonial68.png | 1 | 0 | +| 4.630 | 0.1 | show_face | female43.png | 0 | 1 | +| 6.012 | 0.1 | show_house | castle2.png | 1 | 0 | +| 7.440 | 0.1 | show_face | male81.png | 0 | 1 | ```` -Example 5 shows the JSON summary that HED tools can extract once a dataset has been -annotated using HED. This very simple example only had two condition variables -and only used direct references to condition variables. -The summary shows that of the total of 5 events in the file 3 events were under -the house condition and 2 events were under the face condition. +Example 5 shows a JSON summary that HED tools can extract from a single events file +once a dataset has been annotated using HED. +This very simple example only had two condition variables +and only used direct references to these condition variables. +Dataset-wide summaries can also be extracted. + ````{admonition} Example 5: The HED tools summary of condition variables for Example 4. :class: tip ```json { - "house-cond": { - "name": "house-cond", - "variable_type": "condition-variable", - "levels": 0, - "direct_references": 3, - "total events": 5, - "number events": 3, + "house-cond": { + "name": "house-cond", + "variable_type": "condition-variable", + "levels": 0, + "direct_references": 3, + "total events": 5, + "number events": 3, "number_multiple": 0, "multiple maximum": 1, "level counts": {} - }, - "face-cond": { - "name": "face-cond", - "variable_type": "condition-variable", - "levels": 0, - "direct_references": 2, - "total events": 5, - "number events": 2, + }, + "face-cond": { + "name": "face-cond", + "variable_type": "condition-variable", + "levels": 0, + "direct_references": 2, + "total events": 5, + "number events": 2, "number_multiple": 0, "multiple maximum": 1, "level counts": {} - } + } } ```` +The summary shows that of the total of 5 events in the file 3 events were under +the house condition and 2 events were under the face condition. There were no events in multiple categories of the same condition variables (which would not be possible since these condition variables were referenced -directly rather than assigned levels). -All names are translated to lower case as HED is case-insensitive with respect to analysis. +directly rather than using assigned levels). +All names are translated to lower case as HED is case-insensitive with respect to analysis, +and the summary and factorization tools convert to lower case before processing. These HED summaries can be created for other tags besides *Condition-variable*, -hence the variable_type is given in the summary of Example 5. +hence the *variable_type* is given in the summary of Example 5. Other commonly created summaries are for *Task* and *Control-variable*. +In this example, the two conditions: *house-cond* and *face-cond* are +treated is though they are unrelated. These direct condition variables +are very easy to annotate--- just make up a name and stick the tags anywhere +you want to create factor variables or summaries. +However, a more common situation is for a condition variable to have multiple levels, +which direct use condition variables do not support. -## Definitions -(sample-design-matrix-events-file-anchor)= -````{admonition} Excerpt from event file for a stop-go task. - -| onset | duration | sample | event_type | face_type | rep_status | trial | rep_lag | value | stim_file | -| ----- | -------- | ------ | ---------- | --------- | ---------- | ----- | ------- | ----- | --------- | -| 0.004 | n/a | 1.0 | setup_right_sym | n/a | n/a | n/a | n/a | 3 | n/a | -| 24.2098181818 | n/a | 6052.4545 | show_face_initial | unfamiliar_face | first_show | 1 | n/a | 13 | u032.bmp | -| 25.0352727273 | n/a | 6258.8182 | show_circle | n/a | n/a | 1 | n/a | 0 | circle.bmp | -| 25.158 | n/a | 6289.5 | left_press | n/a | n/a | 1 | n/a | 256 | n/a | -| 26.7352727273 | n/a | 6683.8182 | show_cross | n/a | n/a | 2 | n/a | 1 | cross.bmp | -| 27.2498181818 | n/a | 6812.4545 | show_face | unfamiliar_face | immediate_repeat | 2 | 1 | 14 | u032.bmp | -| 27.8970909091 | n/a | 6974.2727 | left_press | n/a | n/a | 2 | n/a | 256 | n/a | -| 28.0998181818 | n/a | 7024.9545 | show_circle | n/a | n/a | 2 | n/a | 0 | circle.bmp | -| 29.7998181818 | n/a | 7449.9545 | show_cross | n/a | n/a | 3 | n/a | 1 | cross.bmp | -| 30.3570909091 | n/a | 7589.2727 | show_face | unfamiliar_face | first_show | 3 | n/a | 13 | u088.bmp | +Another disadvantage of direct condition variables is that there is +no information about what the conditions represent beyond the arbitrarily chosen condition names. + +A third disadvantage is that direct condition variables can not be used to +anchor events with temporal extent. + +The next section introduces the use of defined condition variables, +which address both of these disadvantages. + +(defined-condition-variables-anchor)= +## Defined condition variables + + +````{admonition} Example 6: A revised JSON sidecar using defined conditions for Example 1. +:class: tip + +```json +{ + "event_type": { + "HED": { + "show_house": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Building/House), Def/House-cond", + "show_face": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Face), Def/Face-cond" + } + }, + "stim_file": { + "HED": "(Image, Pathname/#)" + }, + "my_definitions": { + "HED": { + "house_cond_def": (Definition/House-cond, (Condition-variable/Presentation-type, (Image, Building/House))), + "face_cond_def": (Definition/Face-cond, (Condition-variable/Presentation-type, (Image, Face)))" +} +``` ```` +Example 6 defines a condition variable called *Presentation-type* with two levels: +*House-cond* and *Face-cond*. +The definitions of *House-cond* and *Face-cond* both include the same *Presentation-type* +*Condition-variable* so tools can recognize these as levels of the same variable and +automatically extract 2-factor experimental design. + +Notice that the (*Image*, *Building/House*) tags are included both in the definition of +the *House-cond* level of the *Presentation-type* condition variable +and in the tags for the event_type *show_house*. +Similarly, the (*Image*, *Face*) tags appear in both the definition of the +*Face-cond* level of the *Presentation-type* condition variable +and in the tags for the event_type *show_face*. +We have included them in both places because generally the condition variable definitions +are removed prior to searching for HED tags because the tags in the definitions +define the meaning of the conditions. + +````{admonition} Example 7: The summary extracted when the JSON sidecar of Example 6 is used. +:class: tip +```json +{ + "presentation-type": { + "name": "presentation-type", + "variable_type": "condition-variable", + "levels": 2, + "direct_references": 0, + "total events": 5, + "number events": 5, + "number_multiple": 0, + "multiple maximum": 1, + "level counts": { + "house-cond": 3, + "face-cond": 2 + } + } +} +``` +```` + +(column-vs-row-conditions-anchor)= +## Column vs row conditions + +In this section, we look at a more complicated example based on the Wakeman-Henson face-processing dataset. +This dataset, which is available on [OpenNeuro](https://openneuro.org) under accession number +ds003654, was used in as a case study on HED annotation described in the +[Capturing the nature of events paper](https://www.sciencedirect.com/science/article/pii/S1053811921010387). + +The experiment is based on a 3 x 3 x 2 experimental design: face type x repetition status x key choice. +The experimental stimulus is each trial was the visual presentation of one of 3 possible types of images: +a well-known face, an unfamiliar face, and a scrambled face image. +The type of face was randomized across trials. + +The repetition status condition variable also had one of three possible values and indicated: +whether the stimulus image had not been seen before (first show), +was just seen in the previous trial (immediate repeat), +or had been seen in a several trials ago (delayed repeat). +The repetition status was randomized across trials. +The final condition variable in the experimental design was the key assignment. +In the right symmetry condition, participants pressed the right mouse button +to indicate that the presented face had above average symmetry, +while in the left symmetry condition, participants pressed the left mouse button +to indicate that the presented face had above average symmetry. +The key assignment was held constant for each recording, but the key choice was +counter-balanced across participants. + + +(sample-design-matrix-events-file-anchor)= +```{admonition} Example 8: An excerpt from the Wakeman-Henson face-processing dataset.. + +| onset | duration | event_type | face_type | rep_status | trial | rep_lag | value | stim_file | +| ----- | -------- | ---------- | --------- | ---------- | ----- | ------- | ----- | --------- | +| 0.004 | n/a | setup_right_sym | n/a | n/a | n/a | n/a | 3 | n/a | +| 24.2098 | n/a | show_face_initial | unfamiliar_face | first_show | 1 | n/a | 13 | u032.bmp | +| 25.0353 | n/a | show_circle | n/a | n/a | 1 | n/a | 0 | circle.bmp | +| 25.158 | n/a | left_press | n/a | n/a | 1 | n/a | 256 | n/a | +| 26.7353 | n/a | show_cross | n/a | n/a | 2 | n/a | 1 | cross.bmp | +| 27.2498 | n/a | show_face | unfamiliar_face | immediate_repeat | 2 | 1 | 14 | u032.bmp | +| 27.8971 | n/a | left_press | n/a | n/a | 2 | n/a | 256 | n/a | +| 28.0998 | n/a | show_circle | n/a | n/a | 2 | n/a | 0 | circle.bmp | +| 29.7998 | n/a | show_cross | n/a | n/a | 3 | n/a | 1 | cross.bmp | +| 30.3571 | n/a | show_face | unfamiliar_face | first_show | 3 | n/a | 13 | u088.bmp | +``` + +Example 8 illustrates two different ways of using defined conditions for encoding. +The key assignment is marked by inserting an event with temporal extent at the beginning +of the file. The *setup_right_sym* event is encoded in the JSON sidecar as: + +The condition variab + +```{admonition} Example 9: HED tools automatic extraction of the design matrix in categorical form for Example 8. + +| onset | key-assignment | face-type | repetition-type | +| ----- | -------------- | ---- ---- | --------------- | +| 0.004 | right-sym-com | n/a | n/a | +| 24.2098 | right-sym-com | unfamiliar-face-cond | first-show-cond | +| 25.0353 | right-sym-com | n/a | n/a | +| 25.158 | right-sym-com | n/a| n/a | +| 26.7353 | right-sym-com | n/a | n/a | +| 27.2498 | right-sym-com | unfamiliar-face-cond | immediate-repeat-cond | +| 27.8971 | right-sym-com | n/a | n/a | +| 28.0998 | right-sym-com | n/a | n/a | +| 29.7998 | right-sym-com | n/a | n/a | +| 30.3571 | right-sym-com | unfamiliar-face-cond | first-show-cond | +``` + + + +{ + "key-assignment": { + "name": "key-assignment", + "variable_type": "condition-variable", + "levels": 1, + "direct_references": 0, + "total events": 200, + "number events": 200, + "number_multiple": 0, + "multiple maximum": 1, + "level counts": { + "right-sym-cond": 200 + } + }, + "face-type": { + "name": "face-type", + "variable_type": "condition-variable", + "levels": 3, + "direct_references": 0, + "total events": 200, + "number events": 52, + "number_multiple": 0, + "multiple maximum": 1, + "level counts": { + "unfamiliar-face-cond": 20, + "famous-face-cond": 14, + "scrambled-face-cond": 18 + } + }, + "repetition-type": { + "name": "repetition-type", + "variable_type": "condition-variable", + "levels": 3, + "direct_references": 0, + "total events": 200, + "number events": 52, + "number_multiple": 0, + "multiple maximum": 1, + "level counts": { + "first-show-cond": 28, + "immediate-repeat-cond": 12, + "delayed-repeat-cond": 12 + } + } +} \ No newline at end of file From 65dbd2aa59026a1a5de8089ba4362d1295f02165 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Mon, 1 Aug 2022 09:32:02 -0500 Subject: [PATCH 010/143] Updated the restructuring documentation --- docs/source/EventFileRestructuring.md | 162 +++++----- docs/source/HedConditionsAndDesignMatrices.md | 283 +++++++++++++----- .../data/task-FacePerception_events.json | 138 +++++++++ docs/source/package.json | 22 +- 4 files changed, 441 insertions(+), 164 deletions(-) create mode 100644 docs/source/_static/data/task-FacePerception_events.json diff --git a/docs/source/EventFileRestructuring.md b/docs/source/EventFileRestructuring.md index aff01f7..559010b 100644 --- a/docs/source/EventFileRestructuring.md +++ b/docs/source/EventFileRestructuring.md @@ -11,11 +11,11 @@ This tutorial works through the process of restructuring event files using the H * [**Add structure column**](add-structure-column-anchor) Docs in process * [**Add structure events**](add-structure-events-anchor) Docs in process * [**Add structure numbers**](add-structure-numbers-anchor) Docs in process - * [**Derive column**](derive-column-anchor) Docs in process * [**Factor column**](factor-column-anchor) * [**Factor HED tags**](factor-hed-tags-anchor) Docs in process * [**Factor HED type**](factor-hed-type-anchor) Docs in process * [**Merge events**](merge-events-anchor) Docs in process + * [**Remap columns**](remap-columns-anchor) Docs in process * [**Remove columns**](remove-columns-anchor) * [**Rename columns**](rename-columns-anchor) * [**Reorder columns**](reorder-columns-anchor) @@ -32,7 +32,14 @@ row modifications, column modifications, and structure modifications. Cleanup operations include: *rename_columns*, *reorder_columns*, and *remove_columns*. -#### Row modifications +#### Row and columns + +*factor_column*, *factor_hed_tags*, and *factor_hed_type* + +#### Restructuring + +Restructuring operations include: *add_structure_column*, *add_structure_events*, +*add_structure_numbers*, *merge_events*, *remap_columns*, and *split_event* (installation-of-remodeling-tools-anchor)= ## Installation of remodeling tools @@ -218,61 +225,6 @@ The results of executing this *add_structure_numbers* command on the [sample eve | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` -(derive-column-anchor)= -### Derive column - -**NOT WRITTEN - PLACEHOLDER** - -Create a new column or overwrite values in an existing column using a mapping from existing columns. -This command can be used to overwrite values particular values in existing columns -based on predefined combinations of values in other columns. - - -(parameters-for-derive-column-anchor)= -```{admonition} Parameters for the *derive_column* command. -:class: tip - -| Parameter | Type | Description | -| ------------ | ---- | ----------- | -| *column_name* | str | The name of the column to be created or modified.| -| *source_columns* | list of str | A list of columns to be used for remapping. | -| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | -``` -The *derive_column* command in the following example specifies . . . - -````{admonition} An example *derive_column* command. -:class: tip - -```json -{ - "command": "derive_column" - "description": "xxx" - "parameters": { - "column_name": "match_side", - "source_columns": ["response_accuracy", "response_hand"], - "mapping": { - "left": [["correct", "left"], ["incorrect", "right"]], - "right": [["correct", "right"], ["incorrect", "left"]] - } - } -} -``` -```` - -The results of executing the previous *derive_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: - -````{admonition} Adding a *match_side* column using the *derive_column* command. - -| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | -| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | -| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | -| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | -| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | -```` - (factor-column-anchor)= ### Factor column @@ -287,14 +239,15 @@ If no values are specified, all unique values in that column are factored. | Parameter | Type | Description | | ------------ | ---- | ----------- | | *column_name* | str | The name of the column to be factored.| -| *factor_values* | list | A list of column values to be included as factors. | -| *factor_names* | list| A list of column names for created factors
of the same length as factor_values. | -| *ignore_missing* | bool | If true, columns corresponding to factor values
that do not appear in column are included. | -| *overwrite_existing* | bool | If true an existing factor column is overwritten. | +| *factor_values* | list | Column values to be included as factors. | +| *factor_names* | list| Column names for created factors. Must be the same length as *factor_values*. | +| *ignore_missing* | bool | If true, include columns for factor values not in events. | +| *overwrite_existing* | bool | If true, existing factor columns are overwritten. | ``` The *factor_column* command in the following example specifies that factor columns should be created for *succesful_stop* and *unsuccesful_stop* of the *trial_type* column. The resulting columns are called *stopped* and *stop_failed*, respectively. + If the *factor_values* is an empty list, factors are created for all unique values in the *column_name* column. The *factor_names* parameters must be the same length as *factor_values*. @@ -337,9 +290,12 @@ The results of executing this *factor_column* command on the [sample events file (factor-hed-tags-anchor)= ### Factor HED tags -**NOT WRITTEN - PLACEHOLDER** - -Produce a list of factor columns based on the specified HED condition-variable values. +Produce a one-hot factor based on a HED tag search. +The search is based on a list of query filters, which are applied in succession +to the assembled HED strings for the event file. +Only events that satisfy each query filter as applied in succession +will have 1 for the factors. +If an event fails one of the queries it does not get a factor (parameters-for-factor-hed-tags-anchor)= ```{admonition} Parameters for *factor_hed_tags* command. @@ -347,9 +303,11 @@ Produce a list of factor columns based on the specified HED condition-variable v | Parameter | Type | Description | | ------------ | ---- | ----------- | -| *column_name* | str | The name of the column to be created or modified.| -| *source_columns* | list of str | A list of columns to be used for remapping. | -| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *factor_name* | str | Name of the column to create for the factor. | +| *remove_types* | list | Structural HED tags to be removed (usually *Condition-variable* and *Task*). | +| *filter_queries* | list | Queries to be applied in succession to filter. | +| *overwrite_existing* | bool | Overwrite the contents of factor_name column. | + ``` The *factor_hed-tags* command in the following example specifies . . . @@ -410,11 +368,10 @@ For additional information on how to encode experimental designs using HED pleas | Parameter | Type | Description | | ------------ | ---- | ----------- | -| *type_tag* | str | A HED tag used to produce the factors (most commonly *Condition-variable*).| -| *type_values* | list | A list of values to factor for the *type_tag*.
If empty all values of that type_tag are used. | -| *overwrite_existing* | bool | If true, an existing factor columns is overwritten. | -| *include_hed_strings* | bool | If true, a column *hed_expand* with HED strings is included. | -| *one_hot_factors* | bool | If true, the factors use one-hot representation (zeros and ones). | +| *type_tag* | str | HED tag used to find the factors (most commonly *Condition-variable*).| +| *type_values* | list | Values to factor for the *type_tag*.
If empty all values of that type_tag are used. | +| *overwrite_existing* | bool | If true, existing factor columns are overwritten. | +| *factor_encoding* | str | Indicates type of encoding. Valid encodings are 'categorical' and 'one-hot'. | ``` To simplifyThe *factor_hed_type* command in the following example specifies . . . @@ -430,8 +387,7 @@ To simplifyThe *factor_hed_type* command in the following example specifies . . "type_tag": "Condition-variable", "type_values": [], "overwrite_existing": true, - "include_hed_strings": false, - "one_hot_factors": true + "factor_encoding": "one-hot" } } ``` @@ -534,6 +490,64 @@ The results of executing the previous *merge_events* command on the [sample even | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` + +(remap-columns-anchor)= +### Remap columns + +This command maps the values that appear in a specified m columns of an event file +into values in n columns using a defined mapping. +This is often used for recoding the event file. +The mapping must have targets for all combinations of values that appear in the m columns. +Create a new column or overwrite values in an existing column using a mapping from existing columns. +This command can be used to overwrite values particular values in existing columns +based on predefined combinations of values in other columns. + + +(parameters-for-remap-columns-anchor)= +```{admonition} Parameters for the *remap_columns* command. +:class: tip + +| Parameter | Type | Description | +| ------------ | ---- | ----------- | +| *column_name* | str | The name of the column to be created or modified.| +| *source_columns* | list of str | A list of columns to be used for remapping. | +| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | +``` +The *remap_columns* command in the following example specifies . . . + +````{admonition} An example *remap_columns* command. +:class: tip + +```json +{ + "command": "remap_columns" + "description": "xxx" + "parameters": { + "column_name": "match_side", + "source_columns": ["response_accuracy", "response_hand"], + "mapping": { + "left": [["correct", "left"], ["incorrect", "right"]], + "right": [["correct", "right"], ["incorrect", "left"]] + } + } +} +``` +```` + +The results of executing the previous *derive_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: + +````{admonition} Adding a *match_side* column using the *remap_columns* command. + +| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +```` + (remove-columns-anchor)= ### Remove columns diff --git a/docs/source/HedConditionsAndDesignMatrices.md b/docs/source/HedConditionsAndDesignMatrices.md index 3772a90..00072e2 100644 --- a/docs/source/HedConditionsAndDesignMatrices.md +++ b/docs/source/HedConditionsAndDesignMatrices.md @@ -229,22 +229,22 @@ Dataset-wide summaries can also be extracted. "variable_type": "condition-variable", "levels": 0, "direct_references": 3, - "total events": 5, - "number events": 3, - "number_multiple": 0, - "multiple maximum": 1, - "level counts": {} + "total_events": 5, + "number_type_events": 3, + "number_multiple_events": 0, + "multiple_event_maximum": 1, + "level_counts": {} }, "face-cond": { "name": "face-cond", "variable_type": "condition-variable", "levels": 0, "direct_references": 2, - "total events": 5, - "number events": 2, - "number_multiple": 0, - "multiple maximum": 1, - "level counts": {} + "total_events": 5, + "number_type_events": 2, + "number_multiple_events": 0, + "multiple_event_maximum": 1, + "level_counts": {} } } ```` @@ -296,8 +296,8 @@ which address both of these disadvantages. }, "my_definitions": { "HED": { - "house_cond_def": (Definition/House-cond, (Condition-variable/Presentation-type, (Image, Building/House))), - "face_cond_def": (Definition/Face-cond, (Condition-variable/Presentation-type, (Image, Face)))" + "house_cond_def": "(Definition/House-cond, (Condition-variable/Presentation-type, (Image, Building/House)))", + "face_cond_def": "(Definition/Face-cond, (Condition-variable/Presentation-type, (Image, Face)))" } ``` ```` @@ -328,11 +328,11 @@ define the meaning of the conditions. "variable_type": "condition-variable", "levels": 2, "direct_references": 0, - "total events": 5, - "number events": 5, - "number_multiple": 0, - "multiple maximum": 1, - "level counts": { + "total_events": 5, + "number_type_events": 5, + "number_multiple_events": 0, + "multiple_event_maximum": 1, + "level_counts": { "house-cond": 3, "face-cond": 2 } @@ -368,9 +368,13 @@ to indicate that the presented face had above average symmetry. The key assignment was held constant for each recording, but the key choice was counter-balanced across participants. +Example 8 shows an excerpt from the event file of sub-002 run-1. +(You may find it useful to look at the full event file [sub-002_task-FacePerception_run-1_events.tsv](./_static/data/sub-002_task-FacePerception_run-1_events.tsv) and the dataset's +JSON sidecar with full HED annotations: +[task-facePerception_events.json](./_static/data/task-FacePerception_events.json) (sample-design-matrix-events-file-anchor)= -```{admonition} Example 8: An excerpt from the Wakeman-Henson face-processing dataset.. +```{admonition} Example 8: An excerpt from the Wakeman-Henson face-processing dataset. | onset | duration | event_type | face_type | rep_status | trial | rep_lag | value | stim_file | | ----- | -------- | ---------- | --------- | ---------- | ----- | ------- | ----- | --------- | @@ -386,72 +390,195 @@ counter-balanced across participants. | 30.3571 | n/a | show_face | unfamiliar_face | first_show | 3 | n/a | 13 | u088.bmp | ``` -Example 8 illustrates two different ways of using defined conditions for encoding. -The key assignment is marked by inserting an event with temporal extent at the beginning -of the file. The *setup_right_sym* event is encoded in the JSON sidecar as: +Example 8 illustrates two different ways of using defined conditions for encoding: +**inserting an event with temporal extent** or using **column encoding**. -The condition variab +The key assignment condition is marked by inserting an event with *event_type* equal to +*setup_right_sym* at the beginning of the file. +As we shall see below, this event is annotated with having temporal extent, +as defined by HED *Onset* and *Offset* tags, +so the condition is in effect until the event's extent ends. -```{admonition} Example 9: HED tools automatic extraction of the design matrix in categorical form for Example 8. +In the column strategy, an event file column represents the condition variable, +and the values in that column represent the levels. +With this encoding, the condition variable is only applicable at a particular +level when that level name appears in the column. +An n/a value in that column indicates the condition does not apply to that event. -| onset | key-assignment | face-type | repetition-type | -| ----- | -------------- | ---- ---- | --------------- | -| 0.004 | right-sym-com | n/a | n/a | -| 24.2098 | right-sym-com | unfamiliar-face-cond | first-show-cond | -| 25.0353 | right-sym-com | n/a | n/a | -| 25.158 | right-sym-com | n/a| n/a | -| 26.7353 | right-sym-com | n/a | n/a | -| 27.2498 | right-sym-com | unfamiliar-face-cond | immediate-repeat-cond | -| 27.8971 | right-sym-com | n/a | n/a | -| 28.0998 | right-sym-com | n/a | n/a | -| 29.7998 | right-sym-com | n/a | n/a | -| 30.3571 | right-sym-com | unfamiliar-face-cond | first-show-cond | +Example 9 shows the portion of the +[**task-facePerception_events.json**](./_static/data/task-FacePerception_events.json) +that encodes information about the *setup_right_sym* event found as the first event +in the event file excerpt of Example 8. +This file contains definitions for all the condition variables used in the dataset. + + +````{admonition} Example 9: Excerpt of the JSON sidecar relevant to the *setup_right_sym* event. +:class: tip + +```json +{ + "event_type": { + "HED": { + "setup_right_sym": "Experiment-structure, (Def/Right-sym-cond, Onset), (Def/Initialize-recording, Onset)" + } + }, + "hed_def_conds": { + "HED": { + "right_sym_cond_def": "(Definition/Right-sym-cond, (Condition-variable/Key-assignment, ((Index-finger, (Right-side-of, Experiment-participant)), (Behavioral-evidence, Symmetrical)), ((Index-finger, (Left-side-of, Experiment-participant)), (Behavioral-evidence, Asymmetrical)), Description/Right index finger key press indicates a face with above average symmetry.))" + } + } +} ``` +```` + +Only the *event_type* column is relevant for assembling the annotations for the first row +of Example 8, since the other annotated columns have n/a values. +The assembled HED annotation for the first row of Example 8 is shown in Example 10. + +````{admonition} Example 10: The HED annotation of the first row of Example 8. +:class: tip +> "*Experiment-structure*, +> (*Def/Right-sym-cond*, *Onset*), +> (*Def/Initialize-recording*, *Onset*)" + +```` +HED represents events of temporal extent using HED definitions with the *Onset* +and *Offset* tags grouped with a user-defined term. +The (*Def/Right-sym-cond*, *Onset*) specifies that an event defined by +*Right-sym-cond* begins at the time-marker represented by this row in the event file. +This event continues until the end of the file or until an event marker with +(*Def/Right-sym-cond*, *Offset*) occurs. +In this case, no *Offset* marker for *Right-sym-cond* appears in the file, +so the event represented by *Right-sym-cond* occurs over the entire recording. +The user-defined term is prefixed with *Def/* and indicates what the event +of temporal extent represents. +If the definition includes a *Condition-variable*, +then the event represents the occurrence of that experimental condition. +The user-defined terms are usually defined in the `events.json` file +located at the top-level of the BIDS dataset. + +Example 11 shows a more readable form for the definition of *Right-sym-cond*. + +````{admonition} Example 11: The contents of the definition for *Right-sym-cond*. +:class: tip + +```text +( + Definition/Right-sym-cond, ( + Condition-variable/Key-assignment, + ((Index-finger, (Right-side-of, Experiment-participant)), (Behavioral-evidence, Symmetrical)), + ((Index-finger, (Left-side-of, Experiment-participant)), (Behavioral-evidence, Asymmetrical)), + Description/Right index finger key press indicates a face with above average symmetry. + ) +) +``` +```` +The primary use of the definitions for condition variables is to encode +the experimental design in an actionable format. +Thus, as a general practice, *Defs* representing condition variables are +removed prior to searching for other tags to avoid repeats. +Notice that both *Right-side-of* and *Left-side-of* appear in the definition. +Thus, if these *Defs* were included, every event would have both left and right tags. + +Once a dataset includes the appropriate annotations, +HED tools can automatically extract the experimental design. +Example 12 shows the result of extraction of categorical factor vectors for +the event file of Example 8. + +```{admonition} Example 12: HED tools categorical form extraction of the design matrix for Example 8. + +| onset | key-assignment | face-type | repetition-type | +| ----- | -------------- | --------- | --------------- | +| 0.004 | right-sym-cond | n/a | n/a | +| 24.2098 | right-sym-cond | unfamiliar-face-cond | first-show-cond | +| 25.0353 | right-sym-cond | n/a | n/a | +| 25.158 | right-sym-cond | n/a | n/a | +| 26.7353 | right-sym-cond | n/a | n/a | +| 27.2498 | right-sym-cond | unfamiliar-face-cond | immediate-repeat-cond | +| 27.8971 | right-sym-cond | n/a | n/a | +| 28.0998 | right-sym-cond | n/a | n/a | +| 29.7998 | right-sym-cond | n/a | n/a | +| 30.3571 | right-sym-cond | unfamiliar-face-cond | first-show-cond | + +```` + +In the categorical representation, +HED uses the condition variable name as the column name. +The level values appear in the columns for event markers at which +the condition variable at that level applies. +Notice that *right-sym-cond* appears in every row because it was used in an event +that extended to the end of the file. +On the other hand, the other condition variables were encoded using +columns and only appear when present in the column. + +Note that if an event has multiple levels of the same condition, +categorical and ordinal encoding cannot be used. +Only one-hot encoding supports multiple levels in the same event. + +Example 13 below shows the condition variable summary that HED produces for the +full [sub-002_task-FacePerception_run-1_events.tsv](./_static/data/sub-002_task-FacePerception_run-1_events.tsv) +and JSON sidecar +[task-facePerception_events.json](./_static/data/task-FacePerception_events.json). + +````{admonition} Example 13: The condition variable summary extracted from the full event file. +:class: tip + +```json { - "key-assignment": { - "name": "key-assignment", - "variable_type": "condition-variable", - "levels": 1, - "direct_references": 0, - "total events": 200, - "number events": 200, - "number_multiple": 0, - "multiple maximum": 1, - "level counts": { - "right-sym-cond": 200 - } - }, - "face-type": { - "name": "face-type", - "variable_type": "condition-variable", - "levels": 3, - "direct_references": 0, - "total events": 200, - "number events": 52, - "number_multiple": 0, - "multiple maximum": 1, - "level counts": { - "unfamiliar-face-cond": 20, - "famous-face-cond": 14, - "scrambled-face-cond": 18 - } - }, - "repetition-type": { - "name": "repetition-type", - "variable_type": "condition-variable", - "levels": 3, - "direct_references": 0, - "total events": 200, - "number events": 52, - "number_multiple": 0, - "multiple maximum": 1, - "level counts": { - "first-show-cond": 28, - "immediate-repeat-cond": 12, - "delayed-repeat-cond": 12 - } + "key-assignment": { + "name": "key-assignment", + "variable_type": "condition-variable", + "levels": 1, + "direct_references": 0, + "total_events": 552, + "number_type_events": 552, + "number_multiple_events": 0, + "multiple_event_maximum": 1, + "level_counts": { + "right-sym-cond": 552 + } + }, + "face-type": { + "name": "face-type", + "variable_type": "condition-variable", + "levels": 3, + "direct_references": 0, + "total_events": 552, + "number_type_events": 146, + "number_multiple_events": 0, + "multiple_event_maximum": 1, + "level_counts": { + "unfamiliar-face-cond": 47, + "famous-face-cond": 49, + "scrambled-face-cond": 50 + } + }, + "repetition-type": { + "name": "repetition-type", + "variable_type": "condition-variable", + "levels": 3, + "direct_references": 0, + "total_events": 552, + "number_type_events": 146, + "number_multiple_events": 0, + "multiple_event_maximum": 1, + "level_counts": { + "first-show-cond": 75, + "immediate-repeat-cond": 36, + "delayed-repeat-cond": 35 + } } -} \ No newline at end of file +} +``` +```` + +The file has 552 events. +Since the *key-assignment* condition variable with level *right-sym-cond* +applies to every event in this file, the *number_type_events* is also 552. +On the other hand, the *face-type* condition variable is only applicable in 146 events. + +All the condition variables have *number_multiple_events* equal to 0, +so any of the three possible encodings: categorical, ordinal, or one-hot can be used. \ No newline at end of file diff --git a/docs/source/_static/data/task-FacePerception_events.json b/docs/source/_static/data/task-FacePerception_events.json new file mode 100644 index 0000000..fa018c4 --- /dev/null +++ b/docs/source/_static/data/task-FacePerception_events.json @@ -0,0 +1,138 @@ +{ + "onset": { + "Description": "Position of event marker in seconds relative to the start.", + "Units": "s" + }, + "duration": { + "Description": "Duration of the event in seconds.", + "Units": "s" + }, + "event_type": { + "LongName": "Event category", + "Description": "The main category of the event.", + "Levels": { + "show_face": "Display a face to mark end of pre-stimulus and start of blink-inhibition.", + "show_face_initial": "Display a face at the beginning of the recording.", + "show_circle": "Display a white circle to mark end of the stimulus and blink inhibition.", + "show_cross": "Display only a white cross to mark start of trial and fixation.", + "left_press": "Experiment participant presses a key with left index finger.", + "right_press": "Experiment participant presses a key with right index finger.", + "setup_left_sym": "Setup for experiment with pressing key with left index finger means a face with above average symmetry.", + "setup_right_sym": "Setup for experiment with pressing key with right index finger means a face with above average symmetry.", + "double_press": "Experiment participant presses both keys ." + }, + "HED": { + "show_face": "Sensory-event, Experimental-stimulus, (Def/Face-image, Onset), (Def/Blink-inhibition-task,Onset),(Def/Cross-only, Offset)", + "show_face_initial": "Sensory-event, Experimental-stimulus, (Def/Face-image, Onset), (Def/Blink-inhibition-task,Onset), (Def/Fixation-task, Onset)", + "show_circle": "Sensory-event, (Intended-effect, Cue), (Def/Circle-only, Onset), (Def/Face-image, Offset), (Def/Blink-inhibition-task, Offset), (Def/Fixation-task, Offset)", + "show_cross": "Sensory-event, (Intended-effect, Cue), (Def/Cross-only, Onset), (Def/Fixation-task, Onset), (Def/Circle-only, Offset)", + "left_press": "Agent-action, Participant-response, Def/Press-left-finger", + "right_press": "Agent-action, Participant-response, Def/Press-right-finger", + "setup_left_sym": "Experiment-structure, (Def/Left-sym-cond, Onset), (Def/Initialize-recording, Onset)", + "setup_right_sym": "Experiment-structure, (Def/Right-sym-cond, Onset), (Def/Initialize-recording, Onset)", + "double_press": "Agent-action, Indeterminate-action, (Press, Keyboard-key)" + } + }, + "face_type": { + "Description": "Factor indicating type of face image being displayed.", + "Levels": { + "famous_face": "A face that should be recognized by the participants.", + "unfamiliar_face": "A face that should not be recognized by the participants.", + "scrambled_face": "A scrambled face image generated by taking face 2D FFT." + }, + "HED": { + "famous_face": "Def/Famous-face-cond", + "unfamiliar_face": "Def/Unfamiliar-face-cond", + "scrambled_face": "Def/Scrambled-face-cond" + } + }, + "rep_status": { + "Description": "Factor indicating whether this image has been already seen.", + "Levels": { + "first_show": "Factor level indicating the first display of this face.", + "immediate_repeat": "Factor level indicating this face was the same as previous one.", + "delayed_repeat": "Factor level indicating face was seen 5 to 15 trials ago." + }, + "HED": { + "first_show": "Def/First-show-cond", + "immediate_repeat": "Def/Immediate-repeat-cond", + "delayed_repeat": "Def/Delayed-repeat-cond" + } + }, + "trial": { + "Description": "Indicates which trial this event belongs to.", + "HED": "Experimental-trial/#" + }, + "rep_lag": { + "Description": "How face images before this one was the image was previously presented.", + "HED": "(Face, Item-interval/#)" + }, + "stim_file": { + "Description": "Path of the stimulus file in the stimuli directory.", + "HED": "(Image, Pathname/#)" + }, + "hed_def_sensory": { + "Description": "Metadata dictionary for gathering sensory definitions", + "HED": { + "cross_only_def": "(Definition/Cross-only, (Visual-presentation, (Foreground-view, (White, Cross), (Center-of, Computer-screen)), (Background-view, Black), Description/A white fixation cross on a black background in the center of the screen.))", + "face_image_def": "(Definition/Face-image, (Visual-presentation, (Foreground-view, ((Image, Face, Hair), Color/Grayscale), ((White, Cross), (Center-of, Computer-screen))), (Background-view, Black), Description/A happy or neutral face in frontal or three-quarters frontal pose with long hair cropped presented as an achromatic foreground image on a black background with a white fixation cross superposed.))", + "circle_only_def": "(Definition/Circle-only, (Visual-presentation, (Foreground-view, ((White, Circle), (Center-of, Computer-screen))), (Background-view, Black), Description/A white circle on a black background in the center of the screen.))" + } + }, + "hed_def_actions": { + "Description": "Metadata dictionary for gathering participant action definitions", + "HED": { + "press_left_finger_def": "(Definition/Press-left-finger, ((Index-finger, (Left-side-of, Experiment-participant)), (Press, Keyboard-key), Description/The participant presses a key with the left index finger to indicate a face symmetry judgment.))", + "press_right_finger_def": "(Definition/Press-right-finger, ((Index-finger, (Right-side-of, Experiment-participant)), (Press, Keyboard-key), Description/The participant presses a key with the right index finger to indicate a face symmetry evaluation.))" + } + }, + "hed_def_conds": { + "Description": "Metadata dictionary for gathering experimental condition definitions", + "HED": { + "famous_face_cond_def": "(Definition/Famous-face-cond, (Condition-variable/Face-type, (Image, (Face, Famous)), Description/A face that should be recognized by the participants))", + "unfamiliar_face_cond_def": "(Definition/Unfamiliar-face-cond, (Condition-variable/Face-type, (Image, (Face, Unfamiliar)), Description/A face that should not be recognized by the participants.))", + "scrambled_face_cond_def": "(Definition/Scrambled-face-cond, (Condition-variable/Face-type, (Image, (Face, Disordered)), Description/A scrambled face image generated by taking face 2D FFT.))", + "first_show_cond_def": "(Definition/First-show-cond, ((Condition-variable/Repetition-type, (Item-count/1, Face), Item-interval/0), Description/Factor level indicating the first display of this face.))", + "immediate_repeat_cond_def": "(Definition/Immediate-repeat-cond, ((Condition-variable/Repetition-type, (Item-count/2, Face), Item-interval/1), Description/Factor level indicating this face was the same as previous one.))", + "delayed_repeat_cond_def": "(Definition/Delayed-repeat-cond, (Condition-variable/Repetition-type, (Item-count/2, Face), (Item-interval, (Greater-than-or-equal-to, Item-interval/5)), Description/Factor level indicating face was seen 5 to 15 trials ago.))", + "left_sym_cond_def": "(Definition/Left-sym-cond, (Condition-variable/Key-assignment, ((Index-finger, (Left-side-of, Experiment-participant)), (Behavioral-evidence, Symmetrical)), ((Index-finger, (Right-side-of, Experiment-participant)), (Behavioral-evidence, Asymmetrical)), Description/Left index finger key press indicates a face with above average symmetry.))", + "right_sym_cond_def": "(Definition/Right-sym-cond, (Condition-variable/Key-assignment, ((Index-finger, (Right-side-of, Experiment-participant)), (Behavioral-evidence, Symmetrical)), ((Index-finger, (Left-side-of, Experiment-participant)), (Behavioral-evidence, Asymmetrical)), Description/Right index finger key press indicates a face with above average symmetry.))" + } + }, + "hed_def_tasks": { + "Description": "Metadata dictionary for gathering task definitions", + "HED": { + "face_symmetry_evaluation_task_def": "(Definition/Face-symmetry-evaluation-task, (Task, Experiment-participant, (See, Face), (Discriminate, (Face, Symmetrical)), (Press, Keyboard-key), Description/Evaluate degree of image symmetry and respond with key press evaluation.))", + "blink_inhibition_task_def": "(Definition/Blink-inhibition-task, (Task, Experiment-participant, Inhibit-blinks, Description/Do not blink while the face image is displayed.))", + "fixation_task_def": "(Definition/Fixation-task, (Task, Experiment-participant, (Fixate, Cross), Description/Fixate on the cross at the screen center.))" + } + }, + "hed_def_setup": { + "Description": "Metadata dictionary for gathering setup definitions", + "HED": { + "setup_def": "(Definition/Initialize-recording, (Recording))" + } + + }, + "value": { + "Description": "Numerical event marker", + "Levels": { + "x0": "Disappearance of face image and display of the inter-stimulus circle simultaneously", + "x1": "Disappearance of face image and display of the inter-stimulus circle simultaneously", + "x2": "Initial setup with left finger key press indicating above average symmetry", + "x3": "Initial setup with right finger key press indicating above average symmetry", + "x5": "Initial presentation of famous face", + "x6": "Immediate repeated presentation of famous face", + "x7": "Delayed repeated presentation of famous face", + "x13": "Initial presentation of unfamiliar face", + "x14": "Immediate repeated presentation of unfamiliar face", + "x15": "Delayed repeated presentation of unfamiliar face", + "x17": "Initial presentation of scrambled face", + "x18": "Immediate repeated presentation of scrambled face", + "x19": "Delayed repeated presentation of scrambled face", + "x256": "Left finger key press", + "x4096": "Right finger key press", + "x4352": "Left and right finger key presses" + } + } +} diff --git a/docs/source/package.json b/docs/source/package.json index 28539dd..3cd6b26 100644 --- a/docs/source/package.json +++ b/docs/source/package.json @@ -1,14 +1,12 @@ { - "event_type": { - "HED": { - "house": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Building/House), Condition-variable/House-cond", - "face": "Sensory-presentation, Visual-presentation, Experimental-stimulus, (Image, Face), Condition-variable/Face-cond" - } - }, - "response_time": { - "HED": "Participant-response, Delay/#" - }, - "stim_file": { - "HED": "(Image, Pathname/#)" - } + "event_type": { + "HED": { + "setup_right_sym": "Experiment-structure, (Def/Right-sym-cond, Onset), (Def/Initialize-recording, Onset)" + } + }, + "hed_def_conds": { + "HED": { + "right_sym_cond_def": "(Definition/Right-sym-cond, (Condition-variable/Key-assignment, ((Index-finger, (Right-side-of, Experiment-participant)), (Behavioral-evidence, Symmetrical)), ((Index-finger, (Left-side-of, Experiment-participant)), (Behavioral-evidence, Asymmetrical)), Description/Right index finger key press indicates a face with above average symmetry.))" + } + } } From c72873fc22c8466b2a56258907e02a048234e124 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Tue, 2 Aug 2022 17:44:26 -0500 Subject: [PATCH 011/143] Added implementation of remap_columns --- docs/source/EventFileRestructuring.md | 68 +++--- docs/source/HedConditionsAndDesignMatrices.md | 201 +++++++++--------- 2 files changed, 142 insertions(+), 127 deletions(-) diff --git a/docs/source/EventFileRestructuring.md b/docs/source/EventFileRestructuring.md index 559010b..747346d 100644 --- a/docs/source/EventFileRestructuring.md +++ b/docs/source/EventFileRestructuring.md @@ -61,7 +61,7 @@ stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneu ````{admonition} Excerpt from event file for a stop-go task of AOMIC-PIOP2 (ds002790). | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | +| 0.0776 | 0.5083 | go | n/a | 0.565 | |correct | right | female | 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | | 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | | 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | @@ -494,13 +494,11 @@ The results of executing the previous *merge_events* command on the [sample even (remap-columns-anchor)= ### Remap columns -This command maps the values that appear in a specified m columns of an event file -into values in n columns using a defined mapping. -This is often used for recoding the event file. -The mapping must have targets for all combinations of values that appear in the m columns. -Create a new column or overwrite values in an existing column using a mapping from existing columns. -This command can be used to overwrite values particular values in existing columns -based on predefined combinations of values in other columns. +This command maps the values that appear in a specified *m* columns of an event file +into values in *n* columns using a defined mapping. +This command is often used for recoding the event file. +The mapping should have targets for all combinations of values that appear in the *m* columns. + (parameters-for-remap-columns-anchor)= @@ -509,45 +507,57 @@ based on predefined combinations of values in other columns. | Parameter | Type | Description | | ------------ | ---- | ----------- | -| *column_name* | str | The name of the column to be created or modified.| -| *source_columns* | list of str | A list of columns to be used for remapping. | -| *mapping* | dict | The keys are the values to be placed in the derived columns and the values are each an array | +| *source_columns* | list | Columns with combinations of values to be mapped.| +| *destination_columns* | list | Columns to be mapped into. | +| *map_list* | list | A list. Each element consists n + m elements
corresponding to the lengths of the source and destination lists respectively. | +| *ignore_missing* | bool | If false, a combination of ``` -The *remap_columns* command in the following example specifies . . . +The *map_list* parameter specifies how each unique combination of values from the source +columns will be mapped into the destination columns. +If there are *m* source columns and *n* destination columns, +then each entry in *map_list must be a list with *n* + *m* elements. + +The *remap_columns* command in the following example creates a new column called *response_type* +based on the unique values in the combination of columns *response_accuracy* and *response_hand*. ````{admonition} An example *remap_columns* command. :class: tip ```json { - "command": "remap_columns" - "description": "xxx" + "command": "remap_columns", + "description": "Map response_accuracy and response hand into a single column.", "parameters": { - "column_name": "match_side", "source_columns": ["response_accuracy", "response_hand"], - "mapping": { - "left": [["correct", "left"], ["incorrect", "right"]], - "right": [["correct", "right"], ["incorrect", "left"]] - } + "destination_columns": ["response_type"], + "map_list": [["correct", "left", "correct_left"], + ["correct", "right", "correct_right"], + ["incorrect", "left", "incorrect_left"], + ["incorrect", "right", "incorrect_left"], + ["n/a", "n/a", "n/a"]], + "ignore_missing": true } } ``` ```` -The results of executing the previous *derive_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *remap_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Adding a *match_side* column using the *remap_columns* command. +````{admonition} Mapping columns *response_accuracy* and *response_hand* into a *response_type* column. -| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | -| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | -| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | right | female | -| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | -| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | response_type | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | --- | ------------------- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | correct_right | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | correct_right | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | correct_right | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | n/a | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | correct_left | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | correct_left | ```` +Typically, the *remap_columns* command is used often used to map single codes in the experimental log +into multiple columns in the final events file. + (remove-columns-anchor)= ### Remove columns diff --git a/docs/source/HedConditionsAndDesignMatrices.md b/docs/source/HedConditionsAndDesignMatrices.md index 00072e2..2e9bedd 100644 --- a/docs/source/HedConditionsAndDesignMatrices.md +++ b/docs/source/HedConditionsAndDesignMatrices.md @@ -14,114 +14,23 @@ the [**BIDS annotation quickstart**](https://hed-examples.readthedocs.io/en/late [**HED annotation quickstart**](https://hed-examples.readthedocs.io/en/latest/HedAnnotationQuickstart.html) tutorials as needed. +The [**Neuorimaging experimental design**](neuroimaging-experimental-anchor) +section at the end of this tutorial provides a basic introduction to the ideas +of factor vectors and experimental design if you are unfamiliar with these topics. - -* [**Neuroimaging experimental design**](neuroimaging-experimental-anchor) - * [**Design matrices and factor variables**](design-matrices-and-factor-variables-anchor) - * [**Types of condition encoding**](types-of-condition-encoding-anchor) * [**HED annotations for conditions**](hed-annotations-for-conditions-anchor) * [**Direct condition variables**](direct-condition-variables-anchor) * [**Defined condition variables**](defined-condition-variables-anchor) * [**Column vs row conditions**](column-vs-row-conditions-anchor) +* [**Review of experimental design concepts**](review-of-experimental-design-concepts-anchor) + * [**Design matrices and factor variables**](design-matrices-and-factor-variables-anchor) + * [**Types of condition encoding**](types-of-condition-encoding-anchor) This tutorial introduces tools and strategies for including this information as part of a dataset without excessive effort on the part of the researcher. The discussion mainly focuses on categorical variables, but HED also can encode numerical values as discussed later in the tutorial. -(neuroimaging-experimental-anchor)= -## Neuroimaging experimental design -Traditional neuroimaging experiments are carefully designed to control and -document the external conditions under which the experiment is conducted. -Often a few items such as the task or the properties of a stimulus are -systematically varied as the stimulus is presented and participant responses -are recorded. - -For example, in an experiment to test for differences in -brain responses to pictures of houses versus pictures of faces, -the researcher would label time points in the recording corresponding -to presentations of the respective pictures so that differences in -brain responses between the two types of pictures could be observed. -An fMRI analysis might determine which brain regions -showed a significant response differential between the two types of responses. -An EEG/MEG analysis might also focus on the differences in time courses -between the responses to the two types of images. - -Thus, the starting point for many analyses is the association of -labels corresponding to different **experimental conditions** with -time points in the data recording. -In BIDS, this association is stored an `events.tsv` file paired -with the data recording, -but this information may also be stored as part of the recording -itself, depending on the technology and the format of the recording. - -(design-matrices-and-factor-variables-anchor)= -### Design matrices and factor variables - -The type of information included for the experimental conditions -and how this information is stored depends very much on the experiment. -Most analysis tools require a vector (sometimes called a **factor vector**) -of elements associated with the event markers for each type of experimental condition. - -For linear modeling and other types of regression, these factor vectors are assembled -into **design matrix** to use as input for the analysis. -Design matrices can also include other types of columns depending on the modeling strategy. - -(types-of-condition-encoding-anchor)= -### Types of condition encoding - -Consider the simple example introduced above of an experiment which -varies the stimuli between pictures of houses and faces to measure -differences in response. -The following example shows three possible types of encodings -(**categorical**, **ordinal**, and **one-hot**) that might be sued -for this association. The table shows an excerpt from a putative events file, -with the onset column (required by BIDS) containing the time of the event marker -relative to the start of the associated data recording. -The duration column (also required by BIDS) contains the duration of the -image presentation in seconds. - -(different-encodings-of-design-variables-anchor)= -````{admonition} Example 1: Different encodings of a column with categorical values. -| onset | duration | categorical | ordinal | one_hot.house | one_hot.face | -| ----- | -------- |----------- |-------- | ------------- | ------------ | -| 2.010 | 0.1 | house | 1 | 1 | 0 | -| 3.210 | 0.1 | house | 1 | 1 | 0 | -| 4.630 | 0.1 | face | 2 | 0 | 1 | -| 6.012 | 0.1 | house | 1 | 1 | 0 | -| 7.440 | 0.1 | face | 2 | 0 | 1 | -```` - -The **categorical** encoding assigns laboratory-specific names to the -different types of stimuli. -In theory, this categorical column consisting of the strings *house* and *face* -could be used as a factor vector or as part of a design matrix for regression. -However, many analysis tools require that these names be assigned numerical -values. - -The **ordinal** encoding assigns an arbitrary sequence of numbers corresponding -to the unique values. -If there are only 2 values, the values -1 and 1 are often used. -Ordinal encodings impose an order based on the values -chosen, which may have undesirable affects on the results of analyses such -as regression if the ordering/relative sizes do not reflect the -properties of the encoded experimental conditions. - -In the example above, the experimental conditions houses and faces do not -have an ordering/size relationship reflected by the encoding (house=1, face=2). -In addition, neither categorical nor ordinal encoding -can represent items falling into multiple categories of the same condition at the same time. -For these reasons, many statistical tools require one-hot encoding. - -In **one-hot** encoding, each possible value of the condition is represented -by its own column with 1's representing the presence of that condition value -and experimental conditions and 0's otherwise. One-hot encodes all values -without bias and allows for a given event to be a member of multiple categories. -This representation is required for many machine-learning models. -A disadvantage is that it can generate a large number of columns if there -are many unique categorical values. It can also cause a problem if not all -files contain the same values, as then different files may have different columns. - (hed-annotations-for-conditions-anchor)= ## HED annotations for conditions @@ -581,4 +490,100 @@ applies to every event in this file, the *number_type_events* is also 552. On the other hand, the *face-type* condition variable is only applicable in 146 events. All the condition variables have *number_multiple_events* equal to 0, -so any of the three possible encodings: categorical, ordinal, or one-hot can be used. \ No newline at end of file +so any of the three possible encodings: categorical, ordinal, or one-hot can be used. + + + +(review-of-experimental-design-concepts-anchor)= +## Review of experimental design concepts + +Traditional neuroimaging experiments are carefully designed to control and +document the external conditions under which the experiment is conducted. +Often a few items such as the task or the properties of a stimulus are +systematically varied as the stimulus is presented and participant responses +are recorded. + +For example, in an experiment to test for differences in +brain responses to pictures of houses versus pictures of faces, +the researcher would label time points in the recording corresponding +to presentations of the respective pictures so that differences in +brain responses between the two types of pictures could be observed. +An fMRI analysis might determine which brain regions +showed a significant response differential between the two types of responses. +An EEG/MEG analysis might also focus on the differences in time courses +between the responses to the two types of images. + +Thus, the starting point for many analyses is the association of +labels corresponding to different **experimental conditions** with +time points in the data recording. +In BIDS, this association is stored an `events.tsv` file paired +with the data recording, +but this information may also be stored as part of the recording +itself, depending on the technology and the format of the recording. + +(design-matrices-and-factor-variables-anchor)= +### Design matrices and factor variables + +The type of information included for the experimental conditions +and how this information is stored depends very much on the experiment. +Most analysis tools require a vector (sometimes called a **factor vector**) +of elements associated with the event markers for each type of experimental condition. + +For linear modeling and other types of regression, these factor vectors are assembled +into **design matrix** to use as input for the analysis. +Design matrices can also include other types of columns depending on the modeling strategy. + +(types-of-condition-encoding-anchor)= +### Types of condition encoding + +Consider the simple example introduced above of an experiment which +varies the stimuli between pictures of houses and faces to measure +differences in response. +The following example shows three possible types of encodings +(**categorical**, **ordinal**, and **one-hot**) that might be sued +for this association. The table shows an excerpt from a putative events file, +with the onset column (required by BIDS) containing the time of the event marker +relative to the start of the associated data recording. +The duration column (also required by BIDS) contains the duration of the +image presentation in seconds. + +(different-encodings-of-design-variables-anchor)= +````{admonition} Example 1: Different encodings of a column with categorical values. +| onset | duration | categorical | ordinal | one_hot.house | one_hot.face | +| ----- | -------- |----------- |-------- | ------------- | ------------ | +| 2.010 | 0.1 | house | 1 | 1 | 0 | +| 3.210 | 0.1 | house | 1 | 1 | 0 | +| 4.630 | 0.1 | face | 2 | 0 | 1 | +| 6.012 | 0.1 | house | 1 | 1 | 0 | +| 7.440 | 0.1 | face | 2 | 0 | 1 | +```` + +The **categorical** encoding assigns laboratory-specific names to the +different types of stimuli. +In theory, this categorical column consisting of the strings *house* and *face* +could be used as a factor vector or as part of a design matrix for regression. +However, many analysis tools require that these names be assigned numerical +values. + +The **ordinal** encoding assigns an arbitrary sequence of numbers corresponding +to the unique values. +If there are only 2 values, the values -1 and 1 are often used. +Ordinal encodings impose an order based on the values +chosen, which may have undesirable affects on the results of analyses such +as regression if the ordering/relative sizes do not reflect the +properties of the encoded experimental conditions. + +In the example above, the experimental conditions houses and faces do not +have an ordering/size relationship reflected by the encoding (house=1, face=2). +In addition, neither categorical nor ordinal encoding +can represent items falling into multiple categories of the same condition at the same time. +For these reasons, many statistical tools require one-hot encoding. + +In **one-hot** encoding, each possible value of the condition is represented +by its own column with 1's representing the presence of that condition value +and experimental conditions and 0's otherwise. One-hot encodes all values +without bias and allows for a given event to be a member of multiple categories. +This representation is required for many machine-learning models. +A disadvantage is that it can generate a large number of columns if there +are many unique categorical values. It can also cause a problem if not all +files contain the same values, as then different files may have different columns. From 4611d531a17850d07c2655a0280208ab6d913096 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Thu, 4 Aug 2022 08:50:21 -0500 Subject: [PATCH 012/143] Removed the add trial numbers from split_events --- docs/source/EventFileRestructuring.md | 34 +++++----- docs/source/HedConditionsAndDesignMatrices.md | 64 ++++++++++--------- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/docs/source/EventFileRestructuring.md b/docs/source/EventFileRestructuring.md index 747346d..d66706c 100644 --- a/docs/source/EventFileRestructuring.md +++ b/docs/source/EventFileRestructuring.md @@ -809,7 +809,6 @@ Unlisted columns are filled with n/a. | ------------ | ---- | ----------- | | *anchor_event* | str | The name of the column that will be used for split-event codes.| | *new_events* | dict | Dictionary whose keys are the codes to be inserted as new events
and whose values are dictionaries with
keys *onset_source*, *duration*, and *copy_columns*. | -| *add_event_numbers* | bool | If true, adds a column called *event_numbers*. | | *remove_parent_event* | bool | If true, remove parent event. | ``` @@ -829,7 +828,6 @@ since these items have been unfolded into separate events. "description": "add response events to the trials.", "parameters": { "anchor_column": "trial_type", - "event_numbers_column": "trial_number", "new_events": { "response": { "onset_source": ["response_time"], @@ -852,22 +850,22 @@ The results of executing this *split_event* command on the [sample events file]( ````{admonition} Results of the previous *split_event* command. -| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | trial_number | -| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -------- | -| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | 1 | -| 0.6426 | 0 | response | n/a | n/a | correct | right | female | 1 | -| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | 2 | -| 5.7774 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | 2 | -| 6.0674 | 0 | response | n/a | n/a | correct | right | female | 2 | -| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | 3 | -| 10.0356 | 0 | response | n/a | n/a | correct | right | female | 3 | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | 4 | -| 13.7939 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | 4 | -| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | 5 | -| 17.3521 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | 5 | -| 17.7351 | 0 | response | n/a | n/a | correct | left | male | 5 | -| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | 6 | -| 22.0533 | 0 | response | n/a | n/a | correct | left | male | 6 | +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | +| 0.6426 | 0 | response | n/a | n/a | correct | right | female | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | +| 5.7774 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | +| 6.0674 | 0 | response | n/a | n/a | correct | right | female | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | +| 10.0356 | 0 | response | n/a | n/a | correct | right | female | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | +| 13.7939 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | +| 17.3521 | 0.5 | stop_signal | n/a | n/a | n/a | n/a | n/a | +| 17.7351 | 0 | response | n/a | n/a | correct | left | male | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | +| 22.0533 | 0 | response | n/a | n/a | correct | left | male | ```` Note that the event numbers are added before the splitting and then diff --git a/docs/source/HedConditionsAndDesignMatrices.md b/docs/source/HedConditionsAndDesignMatrices.md index 2e9bedd..d9fd124 100644 --- a/docs/source/HedConditionsAndDesignMatrices.md +++ b/docs/source/HedConditionsAndDesignMatrices.md @@ -14,7 +14,7 @@ the [**BIDS annotation quickstart**](https://hed-examples.readthedocs.io/en/late [**HED annotation quickstart**](https://hed-examples.readthedocs.io/en/latest/HedAnnotationQuickstart.html) tutorials as needed. -The [**Neuorimaging experimental design**](neuroimaging-experimental-anchor) +The [**Neuorimaging experimental design**](review-of-experimental-design-concepts-anchor) section at the end of this tutorial provides a basic introduction to the ideas of factor vectors and experimental design if you are unfamiliar with these topics. @@ -26,17 +26,17 @@ of factor vectors and experimental design if you are unfamiliar with these topic * [**Design matrices and factor variables**](design-matrices-and-factor-variables-anchor) * [**Types of condition encoding**](types-of-condition-encoding-anchor) -This tutorial introduces tools and strategies for including this information -as part of a dataset without excessive effort on the part of the researcher. -The discussion mainly focuses on categorical variables, but HED -also can encode numerical values as discussed later in the tutorial. +This tutorial introduces tools and strategies for encoding information +about the experimental design as part of a dataset metadata +without excessive effort on the part of the researcher. +The discussion mainly focuses on categorical variables. (hed-annotations-for-conditions-anchor)= ## HED annotations for conditions As mentioned above, HED (Hierarchical Event Descriptors) provide several mechanisms for easily annotating the experimental conditions represented by a BIDS dataset so that -the information can be automatically extracted, summarized and used by tools. +the information can be automatically extracted, summarized, and used by tools. HED has three ways of annotating experimental conditions: condition variables without definitions, condition variables with definitions but no levels, and condition variables with levels. @@ -53,7 +53,7 @@ a simplified event file for an experiment to distinguish brain responses for houses and faces. (sample-house-face-example-anchor)= -````{admonition} Example 2. Excerpt from a sample event file from a simplified house-face experiment. +````{admonition} Example 1. Excerpt from a sample event file from a simplified house-face experiment. | onset | duration | event_type | stim_file | | ----- | -------- |----------- | ---------- | | 2.010 | 0.1 | show_house | ranch1.png | @@ -66,9 +66,9 @@ for houses and faces. As explained in [**BIDS annotation quickstart**](https://hed-examples.readthedocs.io/en/latest/BidsAnnotationQuickstart.html), the most commonly used strategy for annotating events in a BIDS dataset is to create a single JSON file located in the dataset root containing the annotations -for the columns. The following shows a minimal example +for the columns. The following shows a minimal example: -````{admonition} Example 3: Minimal JSON sidecar with HED annotations for Example 1. +````{admonition} Example 2: Minimal JSON sidecar with HED annotations for Example 1. :class: tip ```json @@ -87,11 +87,13 @@ for the columns. The following shows a minimal example ```` Each row in an `events.tsv` file represents a time marker in the corresponding data recording. -At analysis time, HED tools look up each column value in the JSON file and concatenate the +At analysis time, HED tools look up each `events.tsv` column value in the JSON file and concatenate the corresponding HED annotation into a single string representing the annotation for that row. Annotations without #'s are used directly, while annotations with # have the corresponding column values substituted when the annotation is assembled. +Example 3 shows the Hed annotation for the first row in the `events.tsv` file of Example 1. + ````{admonition} Example 3: HED annotation for first event in Example 1 using JSON sidecar of Example 2. :class: tip @@ -103,11 +105,15 @@ column values substituted when the annotation is assembled. Notice that *Building/House* is a partial path rather than a single tag. This is because *House* is currently not part of the base HED vocabulary. However, users are allowed to extend tags at most nodes in the HED schema, -but they must use a path that includes a least one ancestor that is in the HED schema. +but they must use a path that includes a least one ancestor in the HED schema. HED tools have the capability of automatically detecting *Condition-variable* -tags in annotated HED datasets and creating factor vectors and summaries automatically. -Example 4 shows the event file after HED tools have appended one-hot factor vectors. +tags in annotated HED datasets to create factor vectors and summaries automatically. +Example 4 shows the event file after HED tools have appended one-hot factor vectors +for the two condition variables *Condition-variable/House-cond* and +*Condition-variable/Face-cond*. +The 1's and 0's *house_cond* and *face-cond* columns indicate presence or absence +of the corresponding condition variables. ````{admonition} Example 4. Event file from Example 2 after one-hot factor vector extraction. @@ -157,7 +163,7 @@ Dataset-wide summaries can also be extracted. } } ```` -The summary shows that of the total of 5 events in the file 3 events were under +The summary shows that of the total of 5 events in the file: 3 events were under the house condition and 2 events were under the face condition. There were no events in multiple categories of the same condition variables (which would not be possible since these condition variables were referenced @@ -174,7 +180,7 @@ treated is though they are unrelated. These direct condition variables are very easy to annotate--- just make up a name and stick the tags anywhere you want to create factor variables or summaries. However, a more common situation is for a condition variable to have multiple levels, -which direct use condition variables do not support. +which direct use condition variables does not support. Another disadvantage of direct condition variables is that there is no information about what the conditions represent beyond the arbitrarily chosen condition names. @@ -182,7 +188,7 @@ no information about what the conditions represent beyond the arbitrarily chosen A third disadvantage is that direct condition variables can not be used to anchor events with temporal extent. -The next section introduces the use of defined condition variables, +The next section introduces defined condition variables, which address both of these disadvantages. (defined-condition-variables-anchor)= @@ -214,17 +220,17 @@ which address both of these disadvantages. Example 6 defines a condition variable called *Presentation-type* with two levels: *House-cond* and *Face-cond*. The definitions of *House-cond* and *Face-cond* both include the same *Presentation-type* -*Condition-variable* so tools can recognize these as levels of the same variable and -automatically extract 2-factor experimental design. +*Condition-variable* so tools recognize these as levels of the same variable and +automatically extract the 2-factor experimental design. Notice that the (*Image*, *Building/House*) tags are included both in the definition of the *House-cond* level of the *Presentation-type* condition variable -and in the tags for the event_type *show_house*. +and in the tags for the *event_type* column value *show_house*. Similarly, the (*Image*, *Face*) tags appear in both the definition of the *Face-cond* level of the *Presentation-type* condition variable -and in the tags for the event_type *show_face*. -We have included them in both places because generally the condition variable definitions -are removed prior to searching for HED tags because the tags in the definitions +and in the tags for the *event_type* column value *show_face*. +We have included these tags in both places because generally the condition variable definitions +are removed prior to searching for HED tags. The tags in the definitions define the meaning of the conditions. ````{admonition} Example 7: The summary extracted when the JSON sidecar of Example 6 is used. @@ -257,16 +263,16 @@ In this section, we look at a more complicated example based on the Wakeman-Hens This dataset, which is available on [OpenNeuro](https://openneuro.org) under accession number ds003654, was used in as a case study on HED annotation described in the [Capturing the nature of events paper](https://www.sciencedirect.com/science/article/pii/S1053811921010387). - The experiment is based on a 3 x 3 x 2 experimental design: face type x repetition status x key choice. -The experimental stimulus is each trial was the visual presentation of one of 3 possible types of images: + +The experimental stimulus in each trial was the visual presentation of one of 3 possible types of images: a well-known face, an unfamiliar face, and a scrambled face image. The type of face was randomized across trials. -The repetition status condition variable also had one of three possible values and indicated: +The repetition status condition variable also had one of three possible values and indicated whether the stimulus image had not been seen before (first show), was just seen in the previous trial (immediate repeat), -or had been seen in a several trials ago (delayed repeat). +or had been last seen several trials ago (delayed repeat). The repetition status was randomized across trials. The final condition variable in the experimental design was the key assignment. @@ -318,7 +324,7 @@ Example 9 shows the portion of the [**task-facePerception_events.json**](./_static/data/task-FacePerception_events.json) that encodes information about the *setup_right_sym* event found as the first event in the event file excerpt of Example 8. -This file contains definitions for all the condition variables used in the dataset. +This excerpt only contains the relevent definition and the relevant annotation. ````{admonition} Example 9: Excerpt of the JSON sidecar relevant to the *setup_right_sym* event. @@ -548,7 +554,7 @@ The duration column (also required by BIDS) contains the duration of the image presentation in seconds. (different-encodings-of-design-variables-anchor)= -````{admonition} Example 1: Different encodings of a column with categorical values. +````{admonition} Example 14: Illustration of categorical and one-hot encoding of categorical variables. | onset | duration | categorical | ordinal | one_hot.house | one_hot.face | | ----- | -------- |----------- |-------- | ------------- | ------------ | | 2.010 | 0.1 | house | 1 | 1 | 0 | @@ -573,7 +579,7 @@ chosen, which may have undesirable affects on the results of analyses such as regression if the ordering/relative sizes do not reflect the properties of the encoded experimental conditions. -In the example above, the experimental conditions houses and faces do not +In Example 14, the experimental conditions houses and faces do not have an ordering/size relationship reflected by the encoding (house=1, face=2). In addition, neither categorical nor ordinal encoding can represent items falling into multiple categories of the same condition at the same time. From b05c08f946b1f39dd76de6b99b9594bb18a9dbb9 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sat, 6 Aug 2022 17:14:35 -0500 Subject: [PATCH 013/143] Updated the introduction for event restructuring --- docs/source/EventFileRestructuring.md | 435 +++++++++++++----- ...dInJavascript.md => HedJavascriptTools.md} | 2 +- .../{HedInMatlab.md => HedMatlabTools.md} | 2 +- .../{HedToolsOnline.md => HedOnlineTools.md} | 0 .../{HedInPython.md => HedPythonTools.md} | 2 +- ...b-0013_task-stopsignal_acq-seq_events.json | 63 --- ...ub-0013_task-stopsignal_acq-seq_events.tsv | 101 ++++ .../data/task-stopsignal_acq-seq_events.json | 24 + .../_static/images/EventRemappingProcess.png | Bin 0 -> 75048 bytes docs/source/_static/images/RestructureWeb.png | Bin 0 -> 11675 bytes docs/source/index.rst | 8 +- 11 files changed, 451 insertions(+), 186 deletions(-) rename docs/source/{HedInJavascript.md => HedJavascriptTools.md} (96%) rename docs/source/{HedInMatlab.md => HedMatlabTools.md} (97%) rename docs/source/{HedToolsOnline.md => HedOnlineTools.md} (100%) rename docs/source/{HedInPython.md => HedPythonTools.md} (97%) delete mode 100644 docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json create mode 100644 docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.tsv create mode 100644 docs/source/_static/data/task-stopsignal_acq-seq_events.json create mode 100644 docs/source/_static/images/EventRemappingProcess.png create mode 100644 docs/source/_static/images/RestructureWeb.png diff --git a/docs/source/EventFileRestructuring.md b/docs/source/EventFileRestructuring.md index d66706c..43c9d0c 100644 --- a/docs/source/EventFileRestructuring.md +++ b/docs/source/EventFileRestructuring.md @@ -1,21 +1,23 @@ # Event file restructuring -**UNDER DEVELOPMENT** - -This tutorial works through the process of restructuring event files using the HED event remodeling tools. The tools are designed to be run on an entire BIDS dataset. - -* [**What is restructuring?**](what-is-event-file-restructuring-anchor) Docs in process -* [**Installation of remodeling tools**](installation-of-remodeling-tools-anchor) Docs in process -* [**Running remodeling tools**](running-remodeling-tools-anchor) Docs in process -* [**Remodeling operations**](remodeling-operations-anchor) Docs in process +This tutorial works through the process of restructuring event files using the HED event remodeling tools. +The tools, which are written in Python, are designed to be run on an entire BIDS dataset. +The tools can be called in Jupyter notebook or run via command-line scripts. + +* [**What is restructuring?**](what-is-event-file-restructuring-anchor) +* [**Installing remodeling tools**](installing-remodeling-tools-anchor) +* [**Running remodeling scripts**](running-remodeling-scripts-anchor) + * [**Backing up the events**](backing-up-the-events-anchor) + * [**Remodeling the events**](remodeling-the-events-anchor) +* [**Remodeling operations**](remodeling-operations-anchor) * [**Add structure column**](add-structure-column-anchor) Docs in process * [**Add structure events**](add-structure-events-anchor) Docs in process * [**Add structure numbers**](add-structure-numbers-anchor) Docs in process * [**Factor column**](factor-column-anchor) - * [**Factor HED tags**](factor-hed-tags-anchor) Docs in process - * [**Factor HED type**](factor-hed-type-anchor) Docs in process - * [**Merge events**](merge-events-anchor) Docs in process - * [**Remap columns**](remap-columns-anchor) Docs in process + * [**Factor HED tags**](factor-hed-tags-anchor) + * [**Factor HED type**](factor-hed-type-anchor) + * [**Merge events**](merge-events-anchor) + * [**Remap columns**](remap-columns-anchor) * [**Remove columns**](remove-columns-anchor) * [**Rename columns**](rename-columns-anchor) * [**Reorder columns**](reorder-columns-anchor) @@ -25,40 +27,209 @@ This tutorial works through the process of restructuring event files using the H (what-is-event-file-restructuring-anchor)= ## What is event file restructuring? -Event file restructuring generally falls into four categories: cleanup, -row modifications, column modifications, and structure modifications. +The event files in an experiment provide a crucial link between what happens in +the experiment and the experimental data by providing identified time markers +linked to the timeline of the experiment. + +Event files are often initially created using information in the logs files +generated by the experiment's presentation software or other control software. +These event files are then used to identify portions of the data +corresponding to particular points or blocks of data to be analyzed or compared. + +Event file restructuring refers to creating, modifying, and +reorganizing the event markers in tabular files in order to +disambiguate or clarify the information for distribution and analysis. +Restructuring can occur at several stages during the acquisition and processing +of experimental data as shown in this schematic diagram: +![schematic diagram](./_static/images/RestructureWeb.png). + +In addition to restructuring during initial creation of the tabular event files, +restructuring may be required when the event files do not conform to the requirements +of a particular analysis. +Thus, restructuring is an iterative process, +which is supported by the HED remodeling tools for datasets with tabular event files. + +Table 1 gives a summary of the tools available in the HED remodeling toolbox. + +(summary-of-hed-remodeling-tools-anchor)= +````{table} **Table 1:** Summary of the HED remodeling tools for tabular files. +| Category | Command | Example use case | +| -------- | ------- | -----| +| **clean-up** | | | +| | *remove_columns* | Remove temporary columns created during restructuring. | +| | *remove_rows* | Remove rows with n/a values in a specified column. | +| | *rename_columns* | Make columns names consistent across a dataset. | +| | *reorder_columns* | Make column order consistent across a dataset. | +| **factor** | | | +| | *factor_column* | Extract factor vectors from a column of condition variables. | +| | *factor_hed_tags* | Extract factor vectors from search queries of HED annotations. | +| | *factor_hed_types* | Extract design matrices and/or condition variables. | +| **restructure** | | | +| | *remap_columns* | Create m columns from values in n columns (for recoding). | +| | *split_event* | Split trial-encoded rows into multiple events. | +| | *merge_consecutive* | Replace multiple consecutive events of the same type
with one event of longer duration. | +| | *add_structure_column* | Add a column with condition names. | +| | *add_structure_rows* | Add a row representing the start of a block or trial. | +| | *add_structure_numbers* | Add a column with trial or block numbers. | +```` + +The **clean-up** commands are used at various phases of restructuring to assure consistency +across event files in the dataset. + +The **factor** commands produce column vectors of the same length as the events file +that encode condition variables, design matrices, or satisfaction of other search criteria. +See the +[**HED conditions and design matrices**](https://hed-examples.readthedocs.io/en/latest/HedConditionsAndDesignMatrices.html) +for more information on factoring and analysis. + +The **restructure** commands modify the way that events are encoded. + +(installing-remodeling-tools-anchor)= +## Installing remodeling tools + +Currently, the remodeling tools are available in the GitHub +[**hed-curation repository**](https://github.com/hed-standard/hed-curation) +along with other tools for data cleaning and curation. +These tools rely on the *hedtools* library which is available on PyPI +and can be installed via PIP. + +Once the HED remodeling tools are available in final form, +the tools will be moved to the GitHub +[hed-python repository](https://github.com/hed-standard/hed-python) +and be available for installation via PyPI. +At that time, versions for single event files will become available +as a web-service and through a web-interface +on the [HED online tools](https://hedtools.ucsd.edu/hed). +A docker version is also under development. + +In the meantime, if you want to run the latest version of the tools, +you will need to install the development branch of both +*hed-python* and *hed-curation* using: + +```text +pip install git+https://github.com/hed-standard/hed-python/@develop +pip install git+https://github.com/hed-standard/hed-curation/@develop +``` + +(running-remodeling-scripts-anchor)= +## Running remodeling scripts -#### Cleanup operations +Remodeling consists of applying a list of commands to an events file +to restructure or modify it in some way. -Cleanup operations include: *rename_columns*, *reorder_columns*, and *remove_columns*. +The following diagram shows a schematic of the remodeling process. -#### Row and columns +![Event remodeling process](./_static/images/EventRemappingProcess.png) -*factor_column*, *factor_hed_tags*, and *factor_hed_type* +Initially, the user creates a backup of the event files. +Restructuring applies a sequence of remodeling commands given in a JSON transformation file +to produce a final result. +The transformation file provides a record of the operations performed on the file. +If the user detects a mistake in the transformation, +he/she can correct the transformation file and restore the backup to rerun. -#### Restructuring +The remodeling toolbox provides several scripts to apply the transformations +to the files in a [BIDS-formatted dataset](https://bids.neuroimaging.io/). +The basic scripts are summarized in Table 2. -Restructuring operations include: *add_structure_column*, *add_structure_events*, -*add_structure_numbers*, *merge_events*, *remap_columns*, and *split_event* +(summary-of-remodeling-scripts-anchor)= +````{table} **Table 2:** Summary of the remodeling scripts. +| Script name | Arguments | Purpose | +| ----------- | -------- | ------- | +|*run_backup* | *bids_dir*
*-t task_name*
*-b backup-type*
*-e exclude_dirs* | Backup the event files. | +|*run_remodel* | *bids_dir*
*-t task_name*
*-m model-path*
*-e exclude_dirs* | Remodel the event files. | +|*run_restore* | *bids_dir*
*-t task_name*
*-b backup-type*
*-e exclude_dirs* | Restore the event files. | +|*run_remove* | *bids_dir*
*-t task_name*
*-b backup-type*
*-e exclude_dirs* | Remove the backup event files. | +```` + +All the scripts have a required parameter which is the full path of the BIDS dataset root. +The *-t task_name* option specifies which task in the dataset the remodeling should apply to. +Often, when a dataset includes multiple tasks, +the event files are structured differently for each task and thus require different transformation files. + +The other *-e exclude_dirs* gives a list of directories to ignore in searching for event file. +In BIDS, typical directories to exclude are `derivatives`, `code`, and `stimulus_files`. + +(backing-up-the-events-anchor)= +### Backing up the events +Before any remodeling is performed, you should always back up the event files. +Usually this is just done once, before any remodeling is done. +There are two strategies for doing the backup: *in-place* and *full-tree*. + +The *in-place* strategy makes a copy of each event file in the same directory +as the event file using the suffix `_eventsorig.tsv` to distinguish +these backup files from the active event files (which end in `_events.tsv`). +The *in-place* strategy is simple, but the extra files prevent the dataset from +validating with the BIDS validator. + +The *full-tree* strategy creates a complete tree backup in the +`code/event_backup` directory of the BIDS dataset. +This strategy is more expensive, but does not prevent validation +or interfere with other processing. + +(remodel-backup-anchor)= +````{admonition} Example command to backup the events. +:class: tip -(installation-of-remodeling-tools-anchor)= -## Installation of remodeling tools +```bash +python run_backup.py t:\ds002790-data -b full-tree -e derivatives code simulus_files -**Need information about installation.** +``` +```` -(running-remodeling-tools-anchor)= -## Running remodeling tools +(remodeling-the-events-anchor)= +### Remodeling the events -**Need information about how to run** +The event remodeling process is given by the following example: +(remodel-run-anchor)= +````{admonition} Example command to remodel the events. +:class: tip + +```bash +python run_remodel.py t:\ds002790-data -m derivatives/models/simple_rmdl.json -e derivatives code simulus_files + +``` +```` + +(remodel-backup-example-anchor)= +````{admonition} Example remodeling file with commands to remove columns and reorder the rest. +:class: tip + +```json +[ + { + "command": "remove_columns", + "description": "Get rid of the sample and the value columns.", + "parameters": { + "remove_names": ["sample", "value"], + "ignore_missing": true + } + }, + { + "command": "reorder_columns", + "description": "Want event_type and task_role columns after onset and duration.", + "parameters": { + "column_order": ["onset", "duration", "event_type", "task_role"], + "ignore_missing": false, + "keep_others": true + } + } +] +``` +```` + (remodeling-operations-anchor)= ## Remodeling operations -The examples in this chapter use the following excerpt from sub-0013 -stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneuro.org) as ds002790. +The examples in this tutorial use the following excerpt of the stop-go task from sub-0013 +of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneuro.org) as ds002790. +The full events file is +[sub-0013_task-stopsignal_acq-seq_events.tsv](./_static/data/sub-0013_task-stopsignal_acq-seq_events.tsv). + (sample-remodeling-events-file-anchor)= -````{admonition} Excerpt from event file for a stop-go task of AOMIC-PIOP2 (ds002790). +````{admonition} Table 3: Excerpt from an event file from the stop-go task of AOMIC-PIOP2 (ds002790). | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | | 0.0776 | 0.5083 | go | n/a | 0.565 | |correct | right | female @@ -69,6 +240,48 @@ stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneu | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` +The *factor_hed_types* and *factor_hed_tags* also require HED annotations of +the events and require a JSON sidecar that includes HED annotations. +The tutorial uses the following JSON excerpt to illustrate these operations. +The full JSON file can be found at: +[task-stopsiqnal_acq-seq_events.json](./_static/data/task-stopsignal_acq-seq_events.json). +These HED commands also require the HED schema. +The tutorials use the latest version that is downloaded from the web. + + +(sample-remodeling-sidecar-file-anchor)= +````{admonition} Excerpt of JSON sidecar with HED annotations for the stop-go task of AOMIC-PIOP2. +:class: tip + +```json +{ + "trial_type": { + "HED": { + "succesful_stop": "Sensory-presentation, Visual-presentation, Correct-action, Image, Label/succesful_stop", + "unsuccesful_stop": "Sensory-presentation, Visual-presentation, Incorrect-action, Image, Label/unsuccesful_stop", + "go": "Sensory-presentation, Visual-presentation, Image, Label/go" + } + }, + "stop_signal_delay": { + "HED": "(Auditory-presentation, Delay/# s)" + }, + "sex": { + "HED": { + "male": "Def/Male-image-cond", + "female": "Def/Female-image-cond" + } + }, + "hed_defs": { + "HED": { + "def_male": "(Definition/Male-image-cond, (Condition-variable/Image-sex, (Male, (Image, Face))))", + "def_female": "(Definition/Female-image-cond, (Condition-variable/Image-sex, (Female, (Image, Face))))" + } + } +} +``` +```` + + (add-structure-column-anchor)= ### Add structure column @@ -77,7 +290,7 @@ stop-go task of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneu Add a column of numbers corresponding to a structure elements such as trials or blocks. (parameters-for-add-structure-column-anchor)= -```{admonition} Parameters for the *add_structure_column* command. +```{admonition} Table 4: Parameters for the *add_structure_column* command. :class: tip | Parameter | Type | Description | @@ -105,10 +318,11 @@ The *add_structure_column* command in the following example specifies . . . ``` ```` -The results of executing this *add_structure_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *add_structure_column* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of the previous *add_structure_column* command. +````{admonition} Table 5: Results of the previous *add_structure_column* command. | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -128,7 +342,7 @@ The results of executing this *add_structure_column* command on the [sample even Add events representing the start of a structural element such as a trial or a block. (parameters-for-add-structure-event-anchor)= -```{admonition} Parameters for the *add_structure_events* command. +```{admonition} Table 6: Parameters for the *add_structure_events* command. :class: tip | Parameter | Type | Description | @@ -155,10 +369,11 @@ The *add_structure_events* command in the following example specifies . . . ``` ```` -The results of executing this *add_structure_events* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *add_structure_events* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of the previous *add_structure_events* command. +````{admonition} Table 7: Results of the previous *add_structure_events* command. | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -180,7 +395,7 @@ Add a column with numbers corresponding to a structural element. **TODO** clarify the difference between add_structure_numbers and add_structure_column. (parameters-for-add-structure-numbers-anchor)= -```{admonition} Parameters for the *add_structure_numbers* command. +```{admonition} Table 8: Parameters for the *add_structure_numbers* command. :class: tip | Parameter | Type | Description | @@ -191,7 +406,7 @@ Add a column with numbers corresponding to a structural element. ``` The *add_structure_numbers* command in the following example specifies . . . -````{admonition} An example . +````{admonition} An example *add_structure_numbers* command. :class: tip ```json @@ -210,10 +425,11 @@ The *add_structure_numbers* command in the following example specifies . . . ``` ```` -The results of executing this *add_structure_numbers* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *add_structure_numbers* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of executing the previous *add_structure_numbers* command. +````{admonition} Table 9: Results of executing the previous *add_structure_numbers* command. | onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -233,7 +449,7 @@ indicating presence or absence of the value. If no values are specified, all unique values in that column are factored. (parameters-for-factor-column-anchor)= -```{admonition} Parameters for the *factor_column* command. +```{admonition} Table 10: Parameters for the *factor_column* command. :class: tip | Parameter | Type | Description | @@ -273,9 +489,10 @@ form *column_name.factor_value*. ``` ```` -The results of executing this *factor_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *factor_column* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of factoring column XXX. +````{admonition} Table 11: Results of factoring column XXX. | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | stopped | stop_failed | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | ---------- | ---------- | @@ -298,7 +515,7 @@ will have 1 for the factors. If an event fails one of the queries it does not get a factor (parameters-for-factor-hed-tags-anchor)= -```{admonition} Parameters for *factor_hed_tags* command. +```{admonition} Table 12: Parameters for *factor_hed_tags* command. :class: tip | Parameter | Type | Description | @@ -331,13 +548,16 @@ The *factor_hed-tags* command in the following example specifies . . . ``` ```` -The results of executing this *factor_hed-tags* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *factor_hed-tags* command on the +[sample events file](sample-remodeling-events-file-anchor) using the +[sample sidecar file](sample-remodeling-sidecar-file-anchor) for HED annotations is: -````{admonition} Results of *factor_hed_tags*. -| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | -| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | +````{admonition} Table 13: Results of *factor_hed_tags*. + +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | +| ----- | -------- |---------- | ----------------- | ------------- | ----------------- | ------------- | --- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | | 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | | 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | | 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | @@ -363,7 +583,7 @@ For additional information on how to encode experimental designs using HED pleas [HED conditions and design matrices](https://hed-examples.readthedocs.io/en/latest/HedConditionsAndDesignMatrices.html). (parameters-for-factor-hed-type-anchor)= -```{admonition} Parameters for *factor_hed_type* command. +```{admonition} Table 14: Parameters for *factor_hed_type* command. :class: tip | Parameter | Type | Description | @@ -395,42 +615,17 @@ To simplifyThe *factor_hed_type* command in the following example specifies . . In order to use the JSON file. The full file is at: +The results of executing this *factor_hed-tags* command on the +[sample events file](sample-remodeling-events-file-anchor) using the +[sample sidecar file](sample-remodeling-sidecar-file-anchor) for HED annotations are: -````{admonition} Example *factor_hed_type* command. -:class: tip - -```json -{ - "trial_type": { - "HED": { - "succesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/succesful_stop", - "unsuccesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/unsuccesful_stop", - "go": "Sensory-presentation, Visual-presentation, Image, Label/go" - }, - "sex": { - "HED": { - "male": "Def/Male-image-cond", - "female": "Def/Female-image-cond" - } - }, - "hed_defs": { - "HED": { - "def_male": "(Definition/Male-image-cond, (Condition-variable/Image-sex, (Male, (Image, Face))))", - "def_female": "(Definition/Female-image-cond, (Condition-variable/Image-sex, (Female, (Image, Face))))" - } - } -} -``` -```` - -The results of executing this *factor_hed_type* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of *factor_hed_type*. +````{admonition} Table 15: Results of *factor_hed_type*. -| onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | Image-sex.Female-image-cond | Image-sex.Male-image-cond | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | ------- | ---------- | -| 0.0776 | 0.5083 | go |right | n/a | 0.565 | correct | right | female | 1 | 0 | -| 5.5774 | 0.5083 | unsuccesful_stop | right | 0.2 | 0.49 | correct | right | female | 1 | 0 | +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | Image-sex.Female-image-cond | Image-sex.Male-image-cond | +| ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | ------- | ---------- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | 1 | 0 | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | 1 | 0 | | 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | 1 | 0 | | 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | 1 | 0 | | 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | 0 | 1 | @@ -442,10 +637,12 @@ The results of executing this *factor_hed_type* command on the [sample events fi **NOT WRITTEN - PLACEHOLDER** -One long event is represented by multiple repeat events. Merges these same events occurring consecutively into one event with duration of the new event updated as the sum of all merged events. +One long event is represented by multiple repeat events. +Merges these same events occurring consecutively into one event with duration +of the new event updated as the sum of all merged events. (parameters-for-merge-events-anchor)= -```{admonition} Parameters for the *merge_events* command. +```{admonition} Table 16: Parameters for the *merge_events* command. :class: tip | Parameter | Type | Description | @@ -476,9 +673,10 @@ The *merge_events* command in the following example specifies . . . ``` ```` -The results of executing the previous *merge_events* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *merge_events* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} The results of the *merge_events* command. +````{admonition} Table 17: The results of the *merge_events* command. | onset | duration | trial_type | match_side | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -502,7 +700,7 @@ The mapping should have targets for all combinations of values that appear in th (parameters-for-remap-columns-anchor)= -```{admonition} Parameters for the *remap_columns* command. +```{admonition} Table 18: Parameters for the *remap_columns* command. :class: tip | Parameter | Type | Description | @@ -541,18 +739,19 @@ based on the unique values in the combination of columns *response_accuracy* and ``` ```` -The results of executing the previous *remap_column* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *remap_column* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Mapping columns *response_accuracy* and *response_hand* into a *response_type* column. +````{admonition} Table 19: Mapping columns *response_accuracy* and *response_hand* into a *response_type* column. -| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | response_type | -| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | --- | ------------------- | -| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | correct_right | -| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | correct_right | -| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | correct_right | -| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | n/a | -| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | correct_left | -| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | correct_left | +| onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | response_type | +| ----- | -------- | ---------- | ---------- | ----------------- | ------------- | ----------------- | --- | ------------------- | +| 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | correct_right | +| 5.5774 | 0.5083 | unsuccesful_stop | 0.2 | 0.49 | correct | right | female | correct_right | +| 9.5856 | 0.5084 | go | n/a | 0.45 | correct | right | female | correct_right | +| 13.5939 | 0.5083 | succesful_stop | 0.2 | n/a | n/a | n/a | female | n/a | +| 17.1021 | 0.5083 | unsuccesful_stop | 0.25 | 0.633 | correct | left | male | correct_left | +| 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | correct_left | ```` Typically, the *remap_columns* command is used often used to map single codes in the experimental log @@ -567,7 +766,7 @@ parameter is *false*, a `KeyError` is raised for missing column. (parameters-for-remove-columns-anchor)= -```{admonition} Parameters for the *remove_columns* operation. +```{admonition} Table 20: Parameters for the *remove_columns* operation. :class: tip | Parameter | Type | Description | @@ -595,13 +794,14 @@ since *ignore_missing* is True. ``` ```` -The results of executing this command on the -[sample events file](sample-remodeling-events-file-anchor) are shown below. +The results of executing this command on the +[sample events file](sample-remodeling-events-file-anchor) +are shown below. Although *face* is not the name of a column in the dataframe, it is ignored because *ignore_missing* is true. If *ignore_missing* had been false, a `KeyError` would have been generated. -```{admonition} Results of executing the *remove_column*. +```{admonition} Table 21: Results of executing the *remove_column*. | onset | duration | trial_type | response_time | response_hand | sex | | ----- | -------- | ---------- | ------------- | ------------- | --- | | 0.0776 | 0.5083 | go | 0.565 | right | female | @@ -618,7 +818,7 @@ If *ignore_missing* had been false, a `KeyError` would have been generated. Remove rows in which the named column has one of the specified values. (parameters-for-remove-rows-anchor)= -```{admonition} Parameters for remove_rows. +```{admonition} Table 22: Parameters for remove_rows. :class: tip | Parameter | Type | Description | @@ -648,7 +848,7 @@ has either *succesful_stop* or *unsuccesful_stop*. The results of executing the previous *remove_rows* command on the [sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} The results of executing the previous *remove_rows* command. +````{admonition} Table 23: The results of executing the previous *remove_rows* command. | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | @@ -666,7 +866,7 @@ three *go* trials remain. Rename columns by providing a dictionary of old names to new names. (parameters-for-rename-columns-anchor)= -```{admonition} Parameters for *rename_columns*. +```{admonition} Table 24: Parameters for *rename_columns*. :class: tip | Parameter | Type | Description | @@ -702,9 +902,10 @@ the mapping does not correspond to a column name in the dataframe. ``` ```` -The results of executing the previous *rename_columns* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *rename_columns* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} After the *rename_columns* command is executed, the sample events file is: +````{admonition} Table 25: After the *rename_columns* command is executed, the sample events file is: | onset | duration | trial_type | stop_delay | response_time | response_accuracy | hand_used | image_sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | | 0.0776 | 0.5083 | go | n/a | 0.565 | correct | right | female | @@ -728,13 +929,13 @@ do not appear in the reorder list are dropped (*keep_others* is false) or put at the end of the dataframe in the order they appear (*keep_others* is true). (parameters-for-reorder-columns-anchor)= -```{admonition} Parameters for *reorder_columns*. +```{admonition} Table 26: Parameters for *reorder_columns*. :class: tip | Parameter | Type | Description | | ------------ | ---- | ----------- | | *column_order* | list | A list of columns in the order they should appear in the data.| -| *ignore_missing* | bool | If true and a column in *column_order* does not appear in the dataframe
a *ValueError* is raised, otherwise these columns are ignored. | +| *ignore_missing* | bool | If true and a column in *column_order* does not appear in the dataframe
a *ValueError* is raised, otherwise these columns are ignored. | | *keep_others* | bool | If true, existing columns that aren't in *column_order*
are moved to the end in the same relative
order that they originally appeared in the data,
otherwise these columns are dropped.| ``` @@ -760,9 +961,10 @@ Since *ignore_missing* is true, these will be the only columns retained. ```` -The results of executing the previous *reorder_columns* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing the previous *reorder_columns* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of *reorder_columns*. +````{admonition} Table 27: Results of *reorder_columns*. | onset | duration | response_time | trial_type | | ----- | -------- | ---------- | ------------- | @@ -802,14 +1004,14 @@ Unlisted columns are filled with n/a. (parameters-for-split-event-anchor)= -```{admonition} Parameters for split_event. +```{admonition} Table 28: Parameters for *split_event*. :class: tip | Parameter | Type | Description | | ------------ | ---- | ----------- | -| *anchor_event* | str | The name of the column that will be used for split-event codes.| +| *anchor_event* | str | The name of the column that will be used for split-event codes.| | *new_events* | dict | Dictionary whose keys are the codes to be inserted as new events
and whose values are dictionaries with
keys *onset_source*, *duration*, and *copy_columns*. | -| *remove_parent_event* | bool | If true, remove parent event. | +| *remove_parent_event* | bool | If true, remove parent event. | ``` @@ -846,9 +1048,10 @@ since these items have been unfolded into separate events. ``` ```` -The results of executing this *split_event* command on the [sample events file](sample-remodeling-events-file-anchor) are: +The results of executing this *split_event* command on the +[sample events file](sample-remodeling-events-file-anchor) are: -````{admonition} Results of the previous *split_event* command. +````{admonition} Table 29: Results of the previous *split_event* command. | onset | duration | trial_type | stop_signal_delay | response_time | response_accuracy | response_hand | sex | | ----- | -------- | ---------- | ----------------- | ------------- | ----------------- | ------------- | --- | diff --git a/docs/source/HedInJavascript.md b/docs/source/HedJavascriptTools.md similarity index 96% rename from docs/source/HedInJavascript.md rename to docs/source/HedJavascriptTools.md index c67aa84..5881b1c 100644 --- a/docs/source/HedInJavascript.md +++ b/docs/source/HedJavascriptTools.md @@ -1,4 +1,4 @@ -# HED in JavaScript +# HED JavaScript tools The JavaScript code for HED validation is in the validation directory of the `hed-javascript` repository located at [https://github.com/hed-standard/hed-javascript](https://github.com/hed-standard/hed-javascript). diff --git a/docs/source/HedInMatlab.md b/docs/source/HedMatlabTools.md similarity index 97% rename from docs/source/HedInMatlab.md rename to docs/source/HedMatlabTools.md index 42a9a2a..fed9c47 100644 --- a/docs/source/HedInMatlab.md +++ b/docs/source/HedMatlabTools.md @@ -1,4 +1,4 @@ -# HED in MATLAB +# HED MATLAB tools There are currently three types of support available for HED (Hierarchical Event Descriptors) supports in MATLAB: diff --git a/docs/source/HedToolsOnline.md b/docs/source/HedOnlineTools.md similarity index 100% rename from docs/source/HedToolsOnline.md rename to docs/source/HedOnlineTools.md diff --git a/docs/source/HedInPython.md b/docs/source/HedPythonTools.md similarity index 97% rename from docs/source/HedInPython.md rename to docs/source/HedPythonTools.md index f798ad4..6fe9f62 100644 --- a/docs/source/HedInPython.md +++ b/docs/source/HedPythonTools.md @@ -1,4 +1,4 @@ -# HED in Python +# HED Python tools The HED (Hierarchical Event Descriptor) scripts and notebooks assume that the Python HedTools have been installed. diff --git a/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json b/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json deleted file mode 100644 index 205666d..0000000 --- a/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "trial_type": { - "Description": "Description for trial_type", - "HED": { - "succesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/succesful_stop", - "unsuccesful_stop": "Sensory-presentation, Visual-presentation, Image, Label/unsuccesful_stop", - "go": "Sensory-presentation, Visual-presentation, Image, Label/go" - }, - "Levels": { - "succesful_stop": "Presentation of a face image in a trial with a stop signal in which participant inhibited response.", - "unsuccesful_stop": "Presentation of a face image in a trial with a stop signal in which participant did not inhibit response.", - "go": "Presentation of a face image in a trial with no stop signal" - } - }, - "stop_signal_delay": { - "Description": "Stop-signal cue delay from onset.", - "HED": "((Cue, Think/Inhibit), Delay/# s)" - }, - "response_time": { - "Description": "Response time delay from onset.", - "HED": "(Participant-response, Delay/# s)" - }, - "response_accuracy": { - "Description": "Indicates whether a response correctly indicated", - "HED": { - "incorrect": "(Incorrect-action, (Identify, (Image, Sex)))", - "correct": "(Correct-action, (Identify, (Image, Sex)))" - }, - "Levels": { - "incorrect": "Used the wrong hand to indicate the sex of the face image.", - "correct": "Used the correct hand to indicate the sex of the face image." - } - }, - "response_hand": { - "Description": "Description for response_hand", - "HED": { - "left": "(Hand, (Left-side-of, Body))", - "right": "(Hand, (Right-side-of, Body))" - }, - "Levels": { - "left": "A response using the left hand.", - "right": "A response using the right hand." - } - }, - "sex": { - "Description": "The sex of the image", - "HED": { - "male": "Def/Male-image-cond", - "female": "Def/Female-image-cond" - }, - "Levels": { - "male": "The image was the face of a male person.", - "female": "The image was the face of a female person." - } - }, - "hed_defs": { - "Description": "HED user-defined terms for the dataset.", - "HED": { - "def_male": "(Definition/Male-image-cond, (Condition-variable/Image-sex, (Male, (Image, Face))))", - "def_female": "(Definition/Female-image-cond, (Condition-variable/Image-sex, (Female, (Image, Face))))" - } - } -} \ No newline at end of file diff --git a/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.tsv b/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.tsv new file mode 100644 index 0000000..05bffac --- /dev/null +++ b/docs/source/_static/data/sub-0013_task-stopsignal_acq-seq_events.tsv @@ -0,0 +1,101 @@ +onset duration trial_type stop_signal_delay response_time response_accuracy response_hand sex +0.0776 0.5083 go n/a 0.565 correct right female +5.5774 0.5083 unsuccesful_stop 0.2 0.49 correct right female +9.5856 0.5084 go n/a 0.45 correct right female +13.5939 0.5083 succesful_stop 0.2 n/a n/a right female +17.1021 0.5083 unsuccesful_stop 0.25 0.633 correct left male +21.6103 0.5083 go n/a 0.443 correct left male +24.6186 0.5083 go n/a 0.439 correct left male +28.6268 0.5083 go n/a 0.667 correct left male +32.1434 0.5083 go n/a 0.55 correct right female +36.1516 0.5083 succesful_stop 0.25 n/a n/a right female +41.6514 0.5084 go n/a 0.59 correct right female +44.6597 0.5083 unsuccesful_stop 0.3 0.511 correct right female +49.6679 0.5083 go n/a 0.604 correct right female +52.1845 0.5083 go n/a 0.743 correct left male +56.1927 0.5084 succesful_stop 0.3 n/a n/a right female +60.6926 0.5083 unsuccesful_stop 0.35 0.555 correct left male +65.7008 0.5083 go n/a 0.584 correct right female +73.7173 0.5083 succesful_stop 0.35 n/a n/a right female +76.7255 0.5083 succesful_stop 0.4 n/a n/a right male +81.2337 0.5084 go n/a 0.615 correct left male +84.742 0.5083 go n/a 0.754 correct left male +89.2502 0.5083 go n/a 0.777 correct right female +92.2668 0.5083 go n/a 0.644 correct right female +97.2666 0.5084 unsuccesful_stop 0.45 0.629 correct right female +100.2832 0.5083 go n/a 0.714 correct right female +104.7831 0.5083 go n/a 0.627 correct left male +108.2997 0.5083 go n/a 0.668 correct left male +113.2995 0.5084 go n/a 0.558 correct left male +117.3078 0.5083 go n/a 1.038 incorrect left female +120.816 0.5083 go n/a 0.764 correct left male +125.8242 0.5083 go n/a 0.782 correct right female +129.3325 0.5083 unsuccesful_stop 0.5 0.722 correct left male +132.8407 0.5083 go n/a 0.716 correct right female +137.8489 0.5083 go n/a 0.741 correct right female +141.3571 0.5084 succesful_stop 0.5 n/a n/a right male +145.8653 0.5084 go n/a 1.027 correct right female +149.3736 0.5083 go n/a 0.881 correct left male +153.3818 0.5083 go n/a 0.801 correct right female +157.89 0.5084 go n/a 0.803 correct left male +160.8983 0.5083 go n/a 0.771 correct right female +164.4149 0.5083 succesful_stop 0.55 n/a n/a right female +169.4147 0.5083 go n/a 0.899 correct left male +172.923 0.5083 unsuccesful_stop 0.6 0.754 correct left male +176.9312 0.5083 go n/a 1.11 correct left male +180.4478 0.5083 succesful_stop 0.65 n/a n/a right male +188.9559 0.5083 unsuccesful_stop 0.7 0.867 correct right female +193.4641 0.5083 unsuccesful_stop 0.75 0.814 correct left male +197.4723 0.5083 go n/a 1.21 correct right female +201.4805 0.5084 go n/a 0.859 correct left male +204.9888 0.5083 unsuccesful_stop 0.75 0.973 correct right female +212.5136 0.5083 go n/a 1.02 correct left male +221.5217 0.5083 go n/a 0.817 correct left male +225.5299 0.5083 go n/a 1.038 correct right female +228.5465 0.5083 go n/a 1.049 correct right female +234.0463 0.5084 go n/a 0.92 correct left male +237.0546 0.5083 succesful_stop 0.7 n/a n/a right female +241.0628 0.5083 go n/a 1.266 correct right female +245.071 0.5084 unsuccesful_stop 0.7 0.854 correct right female +248.5876 0.5083 go n/a 0.985 correct left male +254.0875 0.5083 go n/a 0.789 correct right female +260.6123 0.5083 go n/a 0.928 correct right female +266.1122 0.5083 go n/a 0.807 correct left male +269.6204 0.5083 go n/a 0.735 correct left male +273.6286 0.5083 succesful_stop 0.65 n/a n/a right male +277.6368 0.5084 go n/a 0.896 correct right female +281.6451 0.5083 succesful_stop 0.65 n/a n/a right female +289.6615 0.5083 unsuccesful_stop 0.7 0.831 correct right female +293.1698 0.5083 go n/a 0.876 correct left male +296.6863 0.5084 go n/a 1.021 correct right female +302.1862 0.5083 unsuccesful_stop 0.7 1.085 correct left male +306.1944 0.5083 succesful_stop 0.65 n/a n/a right female +309.2027 0.5083 go n/a 0.814 correct right female +313.2109 0.5083 go n/a 1.053 correct left male +318.2191 0.5083 go n/a 1.002 correct left male +322.2273 0.5083 go n/a 1.057 correct right female +326.2355 0.5084 succesful_stop 0.65 n/a n/a right male +330.2438 0.5083 succesful_stop 0.7 n/a n/a right male +334.252 0.5083 go n/a 0.962 correct left male +341.2685 0.5083 go n/a 0.817 correct right female +346.2767 0.5083 unsuccesful_stop 0.75 0.822 correct left male +350.2849 0.5083 go n/a 0.889 correct left male +353.2932 0.5083 go n/a 0.946 correct right female +358.3014 0.5083 go n/a 0.911 correct right female +360.818 0.5083 unsuccesful_stop 0.8 1.054 correct left male +364.8262 0.5083 go n/a 0.966 correct right female +368.8344 0.5083 unsuccesful_stop 0.8 0.99 correct right female +373.8343 0.5083 go n/a 1.004 correct right female +377.8425 0.5083 unsuccesful_stop 0.75 0.909 correct left male +381.8507 0.5084 go n/a 0.859 correct left male +385.859 0.5083 go n/a 1.186 correct right female +389.3672 0.5083 go n/a 1.288 correct right female +393.3754 0.5083 go n/a 0.979 correct left male +398.3836 0.5084 go n/a 1.067 correct left male +400.9002 0.5083 succesful_stop 0.7 n/a n/a right male +409.4083 0.5084 go n/a 0.901 correct left male +414.4165 0.5084 unsuccesful_stop 0.65 0.879 correct left male +418.4248 0.5083 go n/a 1.003 correct left male +422.433 0.5083 succesful_stop 0.6 n/a n/a right female +429.9495 0.5083 succesful_stop 0.55 n/a n/a right female +437.9659 0.5083 go n/a 0.866 correct left male diff --git a/docs/source/_static/data/task-stopsignal_acq-seq_events.json b/docs/source/_static/data/task-stopsignal_acq-seq_events.json new file mode 100644 index 0000000..d9d1a79 --- /dev/null +++ b/docs/source/_static/data/task-stopsignal_acq-seq_events.json @@ -0,0 +1,24 @@ +{ + "trial_type": { + "HED": { + "succesful_stop": "Sensory-presentation, Visual-presentation, Correct-action, Image, Label/succesful_stop", + "unsuccesful_stop": "Sensory-presentation, Visual-presentation, Incorrect-action, Image, Label/unsuccesful_stop", + "go": "Sensory-presentation, Visual-presentation, Image, Label/go" + } + }, + "stop_signal_delay": { + "HED": "(Auditory-presentation, Delay/# s)" + }, + "sex": { + "HED": { + "male": "Def/Male-image-cond", + "female": "Def/Female-image-cond" + } + }, + "hed_defs": { + "HED": { + "def_male": "(Definition/Male-image-cond, (Condition-variable/Image-sex, (Male, (Image, Face))))", + "def_female": "(Definition/Female-image-cond, (Condition-variable/Image-sex, (Female, (Image, Face))))" + } + } +} \ No newline at end of file diff --git a/docs/source/_static/images/EventRemappingProcess.png b/docs/source/_static/images/EventRemappingProcess.png new file mode 100644 index 0000000000000000000000000000000000000000..ad233c03cabd62844cb34289f3093158119bdc6b GIT binary patch literal 75048 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/source/_static/images/RestructureWeb.png b/docs/source/_static/images/RestructureWeb.png new file mode 100644 index 0000000000000000000000000000000000000000..306d3e6561ca22770d7ea8128942ae747d648108 GIT binary patch literal 11675 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 Date: Sat, 6 Aug 2022 17:26:54 -0500 Subject: [PATCH 014/143] Updated the configuration to change the title on sidebar --- docs/source/_templates/layout.html | 2 +- docs/source/conf.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html index ea12149..694e8c6 100644 --- a/docs/source/_templates/layout.html +++ b/docs/source/_templates/layout.html @@ -3,7 +3,7 @@ {% block menu %} {{ super() }}

- HED resources: + Other HED resources:

{% endblock %} From a4da1e88090b4bb78b5e007c1e21c7b84b2a6c59 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Mon, 5 Dec 2022 10:48:00 -0600 Subject: [PATCH 085/143] Updated the index structure --- ...tionSummary.md => DocumentationSummary.md} | 2 +- ...tart.md => FileRestructuringQuickstart.md} | 8 ++- docs/source/HedSchemaViewers.md | 22 +++++++ docs/source/HedValidation.md | 39 ------------- docs/source/HedValidationGuide.md | 57 +++++++++++++++++++ docs/source/_templates/layout.html | 8 +-- docs/source/index.rst | 5 +- 7 files changed, 89 insertions(+), 52 deletions(-) rename docs/source/{HedDocumentationSummary.md => DocumentationSummary.md} (97%) rename docs/source/{EventFileRestructuringQuickstart.md => FileRestructuringQuickstart.md} (96%) create mode 100644 docs/source/HedSchemaViewers.md delete mode 100644 docs/source/HedValidation.md create mode 100644 docs/source/HedValidationGuide.md diff --git a/docs/source/HedDocumentationSummary.md b/docs/source/DocumentationSummary.md similarity index 97% rename from docs/source/HedDocumentationSummary.md rename to docs/source/DocumentationSummary.md index e34a6ef..83f03b7 100644 --- a/docs/source/HedDocumentationSummary.md +++ b/docs/source/DocumentationSummary.md @@ -17,7 +17,7 @@ Detailed case study in using HED-3G for tagging: > NeuroImage Special Issue Practice in MEEG. NeuroImage 245 (2021) 118766. > [https://www.sciencedirect.com/science/article/pii/S1053811921010387](https://www.sciencedirect.com/science/article/pii/S1053811921010387). -## HED schema viewers +## HED viewers The HED schema is usually developed in `.mediawiki` format and converted to XML for use by tools. However, researchers wishing to tag datasets will find both of these views hard to read. diff --git a/docs/source/EventFileRestructuringQuickstart.md b/docs/source/FileRestructuringQuickstart.md similarity index 96% rename from docs/source/EventFileRestructuringQuickstart.md rename to docs/source/FileRestructuringQuickstart.md index c7f3dee..0a49dd2 100644 --- a/docs/source/EventFileRestructuringQuickstart.md +++ b/docs/source/FileRestructuringQuickstart.md @@ -1,13 +1,15 @@ -# Event file restructuring quickstart +# File restructuring quickstart + +This tutorial works through the process of restructuring tabular (`.tsv) files using the HED file remodeling tools. +These tools particularly useful for creating and restructuring event files from +information in experimental logs and for restructuring events to enable a particular analysis. -This tutorial works through the process of restructuring event files using the HED event file remodeling tools. The tools, which are written in Python, are designed to be run on an entire dataset. This dataset can either be in BIDS ([**Brain Imaging Data Structure**](https://bids.neuroimaging.io/)) format, or can consist of files in a directory tree. The later format is useful for restructuring that occurs early in the experimental process, for example, during the conversion from the experimental control software formats. -In both cases, the event files are assumed to be in a tabular, tab-separated value format. The tools can be run using a command-line script, called from a Jupyter notebook, or run using online tools. This quickstart covers the basic concepts of remodeling and diff --git a/docs/source/HedSchemaViewers.md b/docs/source/HedSchemaViewers.md new file mode 100644 index 0000000..edfb2e9 --- /dev/null +++ b/docs/source/HedSchemaViewers.md @@ -0,0 +1,22 @@ +# HED schema viewers + +## Viewing the standard schema + +The HED standard schema contains the basic vocabulary for annotating experiments. +Special purpose HED terms, such as *Definition* and *Def* are only interpreted by HED tools +if they come from the standard schema. + +| Viewer | Link | Use | +| ------ | ---- | --- | +|Expandable
HTML | [**Latest**](http://www.hedtags.org/display_hed.html) or
[**Prerelease**](https://www.hedtags.org/display_hed_prelease.html) | Look up or search for tags.
View during vocabulary development. | +| XML | [**Raw**](https://raw.githubusercontent.com/hed-standard/hed-schemas/main/standard_schema/hedxml/HED8.1.0.xml) or
[**Formatted**](https://github.com/hed-standard/hed-schemas/blob/main/standard_schema/hedxml/HED8.1.0.xml) | Accessed by tools for validation and analysis. | +| Mediawiki | [**Raw**](https://raw.githubusercontent.com/hed-standard/hed-schemas/main/standard_schema/hedwiki/HED8.1.0.mediawiki) or
[**Formatted**](https://github.com/hed-standard/hed-schemas/blob/main/standard_schema/hedwiki/HED8.1.0.mediawiki) | Edit to create a new schema. | + + +## Viewing the SCORE library + +| Viewer | Link | Use | +| ------ | ---- | --- | +|Expandable
HTML | [**Latest**](https://www.hedtags.org/display_hed_score.html) or
[**Prerelease**](https://www.hedtags.org/display_hed_score_prerelease.html) | Look up or search for tags.
View during vocabulary development. | +| XML | [**Raw**](https://raw.githubusercontent.com/hed-standard/hed-schemas/main/library_schemas/score/hedxml/HED_score_0.0.1.xml) or
[**Formatted**](https://github.com/hed-standard/hed-schemas/blob/main/library_schemas/score/hedxml/HED_score_0.0.1.xml) | Accessed by tools for validation and analysis. | +| Mediawiki | [**Raw**](https://raw.githubusercontent.com/hed-standard/hed-schemas/main/library_schemas/score/hedwiki/HED_score_0.0.1.mediawiki) or
[**Formatted**](https://github.com/hed-standard/hed-schemas/blob/main/library_schemas/score/hedwiki/HED_score_0.0.1.mediawiki) | Edit to create a new schema. | diff --git a/docs/source/HedValidation.md b/docs/source/HedValidation.md deleted file mode 100644 index 850cbe9..0000000 --- a/docs/source/HedValidation.md +++ /dev/null @@ -1,39 +0,0 @@ -# HED validation - -## What is HED validation? - -HED validation is the process of checking the consistency and usage of HED annotations. -This tutorial takes demonstrates tools for online validation of -HED (Hierarchical Event Descriptor) annotations. -HED analysis tools assume that your dataset and its accompanying annotations have -already been validated and are free from errors. -You should be sure to validate your dataset - -### Types of errors - -HED annotations consist of comma-separated lists of HED tags selected from -valid HED vocabularies, referred to as **HED schema**. -HED annotations may include arbitrary levels of parentheses to clarify -associations among HED tags. - -In some cases, mainly in BIDS sidecars, HED annotations may contain `#` placeholders, -which are replaced by values from the appropriate columns of an event file when HED -annotations are assembled for analysis. - -#### Syntax errors - -Syntax errors refer to annotation format errors that aren't related to any particular HED schema, -for example, missing commas or mismatched parentheses. - -#### Semantic errors - -Semantic errors refer to annotations that don't comply with the rules of the -particular HED vocabularies - -https://hed-specification.readthedocs.io/en/latest/Appendix_B.html#b-1-hed-validation-errors - -https://hed-specification.readthedocs.io/en/latest/Appendix_B.html#b-1-hed-validation-errors - -## What types of validation are available? -This tutorial also discusses types of validation errors and how -to fix them. diff --git a/docs/source/HedValidationGuide.md b/docs/source/HedValidationGuide.md new file mode 100644 index 0000000..e30f305 --- /dev/null +++ b/docs/source/HedValidationGuide.md @@ -0,0 +1,57 @@ +# HED validation guide + +## What is HED validation? + +HED validation is the process of checking the consistency and usage of HED annotations. +This tutorial takes demonstrates tools for online validation of +HED (Hierarchical Event Descriptor) annotations. +HED analysis tools assume that your dataset and its accompanying annotations have +already been validated and are free from errors. +You should be sure to validate your dataset + +### Types of errors + +HED annotations consist of comma-separated lists of HED tags selected from +valid HED vocabularies, referred to as **HED schema**. +HED annotations may include arbitrary levels of parentheses to clarify +associations among HED tags. + +In some cases, mainly in BIDS sidecars, HED annotations may contain `#` placeholders, +which are replaced by values from the appropriate columns of an event file when HED +annotations are assembled for analysis. + +Two types of errors can occur: syntactic and semantic. + +**Syntactic** errors refer to annotation format errors that aren't related to any particular HED schema, +for example, missing commas or mismatched parentheses. + +**Semantic** errors refer to annotations that don't comply with the rules of the +particular HED vocabularies used in the annotation. + +Current versions of the validators do not separate these phases and require that the appropriate +HED schemas are input at the time of validation. + +See [HED validation errors](https://hed-specification.readthedocs.io/en/latest/Appendix_B.html#b-1-hed-validation-errors) for a list of the validation errors that should be +supported by validation tools. + +Most HED analysis tools, such as those used for searching, summarizing, or creating design matrices, +assume that the dataset and its respective event files have already been validated +and do not re-validate during analysis. + + +## Validation strategies + +### Validation in BIDS + +### Validate using online tools + +### Validate using remodeling tools + +### Validate using a Jupyter notebook + +### Validate in Python + +### Validate in MATLAB + + +## \ No newline at end of file diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html index 722e067..50352ec 100644 --- a/docs/source/_templates/layout.html +++ b/docs/source/_templates/layout.html @@ -9,13 +9,7 @@
  • Project homepage
  • - HED documentation summary
  • -
  • HED schema viewers: - -
  • + Documentation summary
  • Specification
  • Online tools
  • diff --git a/docs/source/index.rst b/docs/source/index.rst index a89870f..049706a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -14,16 +14,17 @@ HED resources HedIntroduction.md BidsAnnotationQuickstart.md HedAnnotationQuickstart.md - HedValidation.md + HedValidationGuide.md HedSearchAndSummary.md HedConditionsAndDesignMatrices.md - EventFileRestructuringQuickstart.md + FileRestructuringQuickstart.md .. toctree:: :maxdepth: 3 :caption: Tools: + HedSchemaViewers.md CTaggerGuiTaggingTool.md FileRemodelingTools.md HedOnlineTools.md From 5d63e330491886bc36abceea8e550a5ba5e197bd Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sat, 10 Dec 2022 14:26:48 -0600 Subject: [PATCH 086/143] First draft of validation guide --- docs/source/BidsAnnotationQuickstart.md | 2 +- docs/source/CTaggerGuiTaggingTool.md | 6 +- docs/source/FileRemodelingTools.md | 35 ++- docs/source/HedValidationGuide.md | 237 ++++++++++++++++-- .../_static/images/BidsOnlineValidator.png | Bin 0 -> 58613 bytes .../EventValidateOnlineToolsScreenshot.png | Bin 0 -> 320552 bytes docs/source/index.rst | 4 +- 7 files changed, 242 insertions(+), 42 deletions(-) create mode 100644 docs/source/_static/images/BidsOnlineValidator.png create mode 100644 docs/source/_static/images/EventValidateOnlineToolsScreenshot.png diff --git a/docs/source/BidsAnnotationQuickstart.md b/docs/source/BidsAnnotationQuickstart.md index aeee3e6..4720124 100644 --- a/docs/source/BidsAnnotationQuickstart.md +++ b/docs/source/BidsAnnotationQuickstart.md @@ -406,7 +406,7 @@ to select HED tags. Once you have finished, you should validate your JSON file to make sure that your annotations are correct. -See [**HED validation**](./HedValidation.md) for detailed guidance. +See the [**HED validation guide**](./HedValidationGuide.md) for detailed guidance. When you are satisfied with your valid JSON sidecar, simply upload it to the root directory of your BIDS dataset, and you are done. diff --git a/docs/source/CTaggerGuiTaggingTool.md b/docs/source/CTaggerGuiTaggingTool.md index d7555d9..621c13d 100644 --- a/docs/source/CTaggerGuiTaggingTool.md +++ b/docs/source/CTaggerGuiTaggingTool.md @@ -6,9 +6,9 @@ This tutorial takes you through the process of using CTagger, a user interface w CTagger can be used as a standalone application or as part of the EEGLAB BIDS data pipeline, making it easy to integrate the annotation pipeline mentioned in the Quick guide. -## Installation +## CTAGGER installation -### Standalone application installation +### CTAGGER standalone installation #### Step 1:Check to see that you have Java installed. Linux usually comes with OpenJDK (open source version of JDK) already installed. @@ -31,7 +31,7 @@ On Linux, you might need to make the jar executable first by executing `chmod +x while in the directory containing the downloaded CTagger. -### Installation in the EEGLAB environment +### CTAGGER in EEGLAB Install HEDTools plugin. Installation is done through the **Manage EEGLAB extensions** options on the EEGLAB GUI File menu. The HEDTools options then appear under the EEGLAB Edit diff --git a/docs/source/FileRemodelingTools.md b/docs/source/FileRemodelingTools.md index b5c62f4..2fc1417 100644 --- a/docs/source/FileRemodelingTools.md +++ b/docs/source/FileRemodelingTools.md @@ -25,9 +25,11 @@ This user's guide contains the following topics: * [**Remodel command-line interface**](remodel-command-line-interface-anchor) * [**Remodel scripts**](remodel-scripts-anchor) * [**Remodel with HED**](remodel-with-hed-anchor) -* [**Remodel file format**](remodel-file-format-anchor) -* [**Remodel operations**](remodel-operations-anchor) - * [**Create event**](create-event-anchor) +* [**Remodel data formats**](remodel-file-format-anchor) + * [**Example remodel file**](example-remodel-file-anchor) + * [**Example event file**](example-event-file-anchor) + * [**Example json sidecar**](example-json-sidecar-anchor) +* [**Remodel file operations**](remodel-file-operations-anchor) * [**Factor column**](factor-column-anchor) * [**Factor HED tags**](factor-hed-tags-anchor) * [**Factor HED type**](factor-hed-type-anchor) @@ -39,6 +41,7 @@ This user's guide contains the following topics: * [**Rename columns**](rename-columns-anchor) * [**Reorder columns**](reorder-columns-anchor) * [**Split event**](split-event-anchor) +* [**Remodel summary operations**](remodel-summary-operations-anchor) * [**Summarize column names**](summarize-column-names-anchor) * [**Summarize column values**](summarize-column-values-anchor) * [**Summarize events to sidecar**](summarize-events-to-sidecar-anchor) @@ -107,7 +110,6 @@ and links to further documentation. Operations not listed in the summarization s | | [*factor_hed_tags*](factor-hed-tags-anchor) | Extract factor vectors from search queries of HED annotations. | | | [*factor_hed_type*](factor-hed-type-anchor) | Extract design matrices and/or condition variables. | | **restructure** | | | -| | [*create_event*](create-event-anchor) | | | | | [*merge_consecutive*](merge-consecutive-anchor) | Replace multiple consecutive events of the same type
    with one event of longer duration. | | | [*number_groups*](number-groups-anchor) | | | | [*number_rows*](number-rows-anchor) | | @@ -365,7 +367,7 @@ The backups provide useful state and provenance information about the data. (restructuring-event-files-anchor)= ### Restructuring event files -Restructuring consists of applying a sequence of transformations from the +Restructuring consists of applying a sequence of operations from the [**Remodel operation summary table**](remodel-operation-summary-anchor) to the backup files corresponding to the event files in the dataset. The transformations are specified as a list of dictionaries in a JSON file in the @@ -538,6 +540,8 @@ which contains a single operation with instructions to remove the `value` and `s from an event file if the columns exist. (example-remodel-file-anchor)= +### Example remodel file + ````{admonition} JSON remodeling file with an operation to remove the value and sample columns if they exist. :class: tip @@ -564,7 +568,7 @@ Finally, the "parameters" value is a dictionary mapping parameter name to parameter value. The parameters for each operation are listed in the -[**Remodel operations**](remodel-operations-anchor) section. +[**Remodel file operations**](remodel-file-operations-anchor) section. An operation may have both required and optional parameters. Optional parameters may be omitted if unneeded, but all parameters are specified in the "parameters" section of the dictionary. @@ -574,8 +578,8 @@ Although these files can be stored anywhere, their preferred location is in the `deriviatves/remodel/transformations` subdirectory under the dataset root so that they can provide provenance for the dataset. -(remodel-operations-anchor)= -## Remodel operations +(example-event-file-anchor)= +### Example event file The examples in this tutorial use the following excerpt of the stop-go task from sub-0013 of the AOMIC-PIOP2 dataset available on [OpenNeuro](https://openneuro.org) as ds002790. @@ -594,6 +598,10 @@ The full events file is | 21.6103 | 0.5083 | go | n/a | 0.443 | correct | left | male | ```` +(example-json-sidecar-anchor)= +### Example JSON sidecar + + The *factor_hed_type* and *factor_hed_tags* also require HED annotations of the events and require a JSON sidecar that includes HED annotations. The tutorial uses the following JSON excerpt to illustrate these operations. @@ -635,10 +643,8 @@ The tutorials use the latest version that is downloaded from the web. ``` ```` -(create-event-anchor)= -### Create event - -... coming soon ... +(remodel-file-operations-anchor)= +## Remodel file operations (factor-column-anchor)= ### Factor column @@ -1096,7 +1102,7 @@ If *ignore_missing* had been false, a `KeyError` would have been generated. Remove rows eliminates rows in which the named column has one of the specified values. (remove-rows-parameters-anchor)= -####Remove rows parameters +#### Remove rows parameters ```{admonition} Parameters for *remove_rows*. :class: tip @@ -1385,6 +1391,9 @@ copied as the new events are created. This strategy results in a trial number column associated with the events, an alternative to the more complicated process of adding a structure column after splitting. +(remodel-summary-operations-anchor)= +## Remodel summary operations + (summarize-column-names-anchor)= ### Summarize column names diff --git a/docs/source/HedValidationGuide.md b/docs/source/HedValidationGuide.md index e30f305..0c043be 100644 --- a/docs/source/HedValidationGuide.md +++ b/docs/source/HedValidationGuide.md @@ -3,13 +3,19 @@ ## What is HED validation? HED validation is the process of checking the consistency and usage of HED annotations. -This tutorial takes demonstrates tools for online validation of -HED (Hierarchical Event Descriptor) annotations. + HED analysis tools assume that your dataset and its accompanying annotations have already been validated and are free from errors. -You should be sure to validate your dataset +Most HED analysis tools, such as those used for searching, summarizing, or creating design matrices, +assume that the dataset and its respective event files have already been validated +and do not re-validate during analysis. -### Types of errors +You should be sure to validate your data before applying analysis tools. + +This guide explains the types of errors that can occur and various ways that +users can validate their HED (Hierarchical Event Descriptor) annotations. + +## Types of errors HED annotations consist of comma-separated lists of HED tags selected from valid HED vocabularies, referred to as **HED schema**. @@ -17,41 +23,226 @@ HED annotations may include arbitrary levels of parentheses to clarify associations among HED tags. In some cases, mainly in BIDS sidecars, HED annotations may contain `#` placeholders, -which are replaced by values from the appropriate columns of an event file when HED -annotations are assembled for analysis. +which are replaced by values from the appropriate columns of an associated event file +when HED annotations are assembled for analysis. -Two types of errors can occur: syntactic and semantic. +Two types of errors can occur: **syntactic** and **semantic**. -**Syntactic** errors refer to annotation format errors that aren't related to any particular HED schema, -for example, missing commas or mismatched parentheses. +>**Syntactic** errors refer to format errors that aren't related to any particular HED schema, +>for example, missing commas or mismatched parentheses. -**Semantic** errors refer to annotations that don't comply with the rules of the -particular HED vocabularies used in the annotation. +>**Semantic** errors refer to annotations that don't comply with the rules of the +>particular HED vocabularies used in the annotation, for example, invalid HED tags +>or values that have the wrong units or type. +>Semantic errors also include higher-level requirements such as missing definitions +>or mismatched *Offset* tags when designating the +>[temporal scope](https://hed-specification.readthedocs.io/en/latest/05_Advanced_annotation.html#temporal-scope) of events. Current versions of the validators do not separate these phases and require that the appropriate -HED schemas are input at the time of validation. +HED schemas are available at the time of validation. -See [HED validation errors](https://hed-specification.readthedocs.io/en/latest/Appendix_B.html#b-1-hed-validation-errors) for a list of the validation errors that should be -supported by validation tools. +See [**HED validation errors**](https://hed-specification.readthedocs.io/en/latest/Appendix_B.html#b-1-hed-validation-errors) +for a list of the validation errors that are detected by validation tools. -Most HED analysis tools, such as those used for searching, summarizing, or creating design matrices, -assume that the dataset and its respective event files have already been validated -and do not re-validate during analysis. + +## Available validators + +HED currently supports native validators for Python and JavaScript. +Both validators support [**HED-specification v3.0.0**](https://github.com/hed-standard/hed-specification/blob/master/hedspec/HEDSpecification_3_0_0.pdf). + +### Python validator +The Python validator included in +[**HEDTools**](https://pypi.org/project/hedtools/) on PyPI is +used as the basis for most HED analysis tools. +Generally, new HED features are first implemented and tested in this validator +before propagating to other tools in the HED ecosystem. +The source code for HEDTools is available in the +[**hed-python**](https://github.com/hed-standard/hed-python) GitHub repository. + +### JavaScript validator +The JavaScript [**hed-validator**](https://www.npmjs.com/package/hed-validator/v/3.7.0) on npm +is the package used for validation in [**BIDS**](https://bids.neuroimaging.io/). +Although the main interface is designed for BIDS integration, +the underlying validation functions can be called directly. +The source code is available in the +[**hed-javascript**](https://github.com/hed-standard/hed-javascript) GitHub repository. + + +### MATLAB support +Validation in MATLAB is currently not directly supported, +although some discussion about future native support is ongoing. +MATLAB users should use the [**HED online validation tools**](https://hedtools.ucsd.edu/hed) +or the [**HED RESTful services interface**](./HedOnlineTools.md#hed-restful-services) +as discussed [**below**](validation-for-matlab-users-anchor). ## Validation strategies +In most experiments, the event files and metadata sidecars share a common structure. +A practical HED approach is to annotate and validate a single file and sidecar using the online tools +before trying to validate entire dataset. +If most of the annotations are in a BIDS JSON sidecar, +this may be all you need to complete annotation. + +``````{admonition} How to approach HED annotation. + +1. Use the online tools to validate a single event file and sidecar if available. +2. Correct errors. (This will get most of the HED errors out.) +3. Use Jupyter notebooks or the remodeling tools to fully validate the dataset. +4. Use the BIDS validators to validate the entire dataset, if the dataset is in BIDS. +`````` + ### Validation in BIDS -### Validate using online tools +BIDS validates many aspects of a dataset beyond HED, +including the format and metadata for all the files in the dataset. + +#### Specifying the HED version +BIDS datasets that have HED annotations, should have the +`HEDVersion` field specified in `dataset_description.json` as +illustrated in the following example: + +````{admonition} Sample dataset_description.json for a BIDS dataset. +:class: tip + +```json +{ + "Name": "Face processing MEEG dataset with HED annotation", + "BIDSVersion": "1.8.4", + "HEDVersion": "8.0.0", + "License": "CC0" +} +``` +```` + +#### BIDS online validator +The simplest way to validate a BIDS dataset is to use the BIDS +online validator: + +![BIDSOnlineValidatorScreenshot](./_static/images/BIDSOnlineValidator.png) + +The BIDS online validator is available at +[**https://bids-standard.github.io/bids-validator/**](https://bids-standard.github.io/bids-validator/). +The BIDS validators use the [**hed-validator**](https://www.npmjs.com/package/hed-validator) +JavaScript package available at [**npm**](https://docs.npmjs.com/) to do the validation. + +See the [**bids-validator**](https://github.com/bids-standard/bids-validator) for additional details. + +(hed-online-validation-anchor)= +### HED online validation + +The HED online validation tools are available at +[**https://hedtools.ucsd.edu/hed**](https://hedtools.ucsd.edu/hed). +The HED web-based tools are designed to act on a single file (e.g. events, sidecar, spreadsheet, schema), but may require supporting files. + +For example, the following screenshot shows the menu for the online event validation tools. +The buttons in the banner allow you to select the time of file to operate on. +The default action is validation. + +![ValidateEvent](./_static/images/EventValidateOnlineToolsScreenshot.png) +*Menu for validating an events file using the HED online tools.* + +Upload the events file and the supporting JSON sidecar using the *Browser* buttons. +If you aren't using the latest HED vocabulary, you can use the *HED schema version* +pull-down to select the desired schema. + +When you press the *Process* button, the files (event file and sidecar) are validated. +If the files have errors, a downloadable text file containing the error messages is returned. +Otherwise, a message indicating successful validation appears at the bottom of the screen. + +The online tools support many other operations and most of them automatically +validate the files before applying the requested operation. +For example, one of the available actions shown on the menu above is + +New features of the tools take a while to propagate to the released version of the online tools. +Use the [**HED online development server**](https://hedtools.ucsd.edu/hed_dev) to access the latest versions. + + +(validation-for-matlab-users-anchor)= +### Validation for MATLAB users + +HED validation in MATLAB is currently done by accessing the HED online tools as web services. + +#### Direct access to services +Users can access these services directly by calling using the HED MATLAB web services +functions as explained in [**HED services in MATLAB**](https://hed-examples.readthedocs.io/en/latest/HedMatlabTools.html#hed-services-in-matlab). +Download the [**web_services**](https://github.com/hed-standard/hed-examples/tree/main/hedcode/matlab_scripts/web_services) +directory from GitHub and include this directory in your MATLAB path. +The [**runAllTests.m**](https://raw.githubusercontent.com/hed-standard/hed-examples/main/hedcode/matlab_scripts/web_services/runAllTests.m) +script calls all the services on test data and illustrates how to call. + +#### Access through EEGLAB +[**EEGLAB**](https://sccn.ucsd.edu/eeglab/index.php) +users can access HED validation through the +[**EEGLAB HEDTools plugin**](./HedMatlabTools.md#eeglab-plug-in-integration). + +[**CTAGGER**](./CTaggerGuiTaggingTool.md) is an application + +#### Access through Fieldtrip + +An interface for accessing HED in [**Fieldtrip**](https://www.fieldtriptoolbox.org/) has recently been added, +but is not yet fully documented. + +### Validation for Python users + +The [HEDTools](https://pypi.org/project/hedtools/) for Python are available on PyPI +and can be installed using the usual Python package installation mechanisms with PIP. +However, new features are not immediately available in the released version. +If you need the latest version you should install the `develop` branch +of the GitHub [**hed-python**](https://github.com/hed-standard/hed-python) repository +directly using PIP. + +````{annotation} +:class: tip + +```python + pip install git+https://github.com/hed-standard/hed-python/@master + ``` + ```` + +#### Jupyter notebooks for validation + +Several [**Jupyter notebooks**](https://github.com/hed-standard/hed-examples/tree/main/hedcode/jupyter_notebooks) are available +as wrappers for calling various Python HED tools. + +For example, the [**bids_validate_datasets.ipynb](https://github.com/hed-standard/hed-examples/blob/main/hedcode/jupyter_notebooks/bids/bids_validate_datasets.ipynb) notebook shown in the following: + +`````{admonition} Python code to validate HED in a BIDS dataset. + +:class: tip + +```python +import os +from hed.errors import get_printable_issue_string +from hed.tools import BidsDataset +from hed import _version as vr +from hedcode._version import get_versions + +print(f"Using HEDTOOLS version: {str(vr.get_versions())}") +print(f"HED Examples version: {str(get_versions())}") -### Validate using remodeling tools +## Set the dataset location and the check_for_warnings flag +check_for_warnings = False +bids_root_path = 'Q:/PerceptionalON' -### Validate using a Jupyter notebook +## Validate the dataset +bids = BidsDataset(bids_root_path) +issue_list = bids.validate(check_for_warnings=check_for_warnings) +if issue_list: + issue_str = get_printable_issue_string(issue_list, "HED validation errors: ", skip_filename=False) +else: + issue_str = "No HED validation errors" +print(issue_str) -### Validate in Python +``` +````` -### Validate in MATLAB +This program can be run directly or as a Jupyter notebook. +The program assumes that dataset is organized as a BIDS dataset. +Users just need to set the path to the root directory of the dataset. +Errors, if any are printed to the command line. +(remodeling-summaries-for-validation-anchor)= +#### Remodeling validation summaries -## \ No newline at end of file +Validation is also available through a remodeling script for command line. \ No newline at end of file diff --git a/docs/source/_static/images/BidsOnlineValidator.png b/docs/source/_static/images/BidsOnlineValidator.png new file mode 100644 index 0000000000000000000000000000000000000000..c1ea7f54704a767329ac94f1e23f9814dcf81785 GIT binary patch literal 58613 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 literal 0 HcmV?d00001 diff --git a/docs/source/_static/images/EventValidateOnlineToolsScreenshot.png b/docs/source/_static/images/EventValidateOnlineToolsScreenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..f9aa6bac2386d501534c49a1fb87d85b46d27269 GIT binary patch literal 320552 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 z