# Form and Annotation Exporter <!-- omit in toc -->
- [Overview](#overview)
- [Summary](#summary)
- [License](#license)
- [Classification](#classification)
- [Usage](#usage)
- [Inputs](#inputs)
- [Config](#config)
- [Outputs](#outputs)
- [Example Conversion to Wide Format](#example-conversion-to-wide-format)
- [Example of Merging Form Responses and Annotations](#example-of-merging-form-responses-and-annotations)
- [**form-responses-\<datestamp\>.csv**](#form-responses-datestampcsv)
- [**annotations-\<datestamp\>.csv**](#annotations-datestampcsv)
- [Example of Retrieving Form-Responses from Session Variables](#example-of-retrieving-form-responses-from-session-variables)
- [Cite](#cite)
- [Contributing](#contributing)
## Overview
### Summary
Export Form Responses and/or Annotations to CSV file(s).
### License
*License:* MIT
### Classification
*Category:* Analysis
*Gear Level:*
- [X] Project
- [X] Subject
- [X] Session
- [X] Acquisition
- [ ] Analysis
## Usage
The Form and Annotation Exporter gear is executed by ensuring the following
configuration parameters are provided and are in a valid combination. This gear has no
file inputs. This gear requires that the Reader Task Workflow be enabled on the instance
it is run on.
If an `ohif_config.json` is being used to configure the OHIF Viewer, and you are
using it to capture form responses outside of the Reader Task workflow, you cannot use
this gear to retrieve the form responses from the sessions. See the [Example of
Retrieving Form-Responses from Session Variables](#example-of-retrieving-form-responses-from-session-variables)
section for anexample of how to do this.
If the gear is run within a project for a protocol where the *protocol_name* is
not defined, the gear will fail.
For the *annotations-scope* configuration parameter, the following combinations are valid:
- `task` and `both` settings require a valid *protocol_name* for a protocol defined
within the project.
- `non-task` and `none` settings do not require a valid *protocol_name*. This allows for
the export of annotations and form responses that are not associated with a task.
- if both *-scope* settings are set to `none`, the gear will fail as there will be no
output.
For the *form-responses-scope* configuration parameter, the following combinations are valid:
- `task` and `none` are the only valid combinations
Running this gear under a specific subject, session, or acquisition will constrain the
output to only those tasks, form-responses, and annotations that are associated with
the container and its children.
This gear will output select annotation properties for the following annotation types:
- Ellipse
- Circle
- Rectangle
- Freehand/Contour (closed)
- Length
- Annotate (Arrow)
- Bidirectional
- Angle
The gear will output the following annotation properties if available in the tool type:
- Area
- Length
- Angle
- Units (of measurement)
- min/max X/Y coordinates of a bounding box of the annotation
- perpendicular min/max X/Y of a Bidirectional annotation
- ShortestDiameter/LongestDiameter of a Bidirectional annotation
### Inputs
This gear has no file input. The exported form responses and annotations will depend
on the level at which the gear is launched (e.g. project, subject, session, acquisition)
and the confiugration options selected.
### Config
- *debug*
- **Type**: *boolean*
- **Description**: *Log debug messages*
- **Default**: *False*
- *protocol_name*
- **Type**: *string*
- **Description**: *The name of the protocol to export data from.*
- **Optional**: *True*
- *annotations-scope*
- **Type**: *string*
- **Description**: *The scope of the exported annotations.*
- **Default**: *task*
- *form-responses-scope*
- **Type**: *string*
- **Description**: *The scope of the form responses.*
- **Default**: *task*
- *read_timeout*
- **Type**: *integer*
- **Description**: *The maximum time in seconds to wait for a response from the server.*
- **Default**: *60*
### Outputs
The Form and Annotations Exporter gear has the following outputs:
- form-responses-\<datestamp\>.csv
- annotations-\<datestamp\>.csv
For form responses and annotations that are coordinated with a task, the above outputs
will correspond to the same Task ID and the `Location` column of the annotations CSV
will correspond to the matching `Question` with a `Answer` of `yes`. The question will
take the form of `<question #>: <Location>` (e.g. `2: LV`).
Both output CSV files are in a "narrow" format where each row represents a single form
response Question/Answer or annotation Property/Value pair. Each of these CSV files can
be converted to a "wide" format using the `pandas` Python library with the [`pivot`
command](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pivot.html). A
[data dictionary](./data_dictionary.csv) is provided for the CSV files.
#### Example Conversion to Wide Format
```python
import pandas as pd
from pathlib import Path
root_dir = Path('~')
# Read in the CSV file
form_responses_path = root_dir / 'form-responses-2023-05-13_08-47-26.csv'
df = pd.read_csv(form_responses_path)
index_cols = [col for col in list(df.columns) if col not in ['Question', 'Answer']]
df_wide = df.pivot(index=index_cols, columns='Question', values='Answer').reset_index()
df_wide.to_csv(root / (form_responses_path.stem + '_wide.csv'))
# Read in the CSV file
annotations_path = root_dir / 'annotations-2023-05-13_08-47-26.csv'
df = pd.read_csv(annotations_path)
index_cols = [col for col in list(df.columns) if col not in ['Property', 'Value']]
df_wide = df.pivot(index=index_cols, columns='Property', values='Value').reset_index()
df_wide.to_csv(annotations_path.stem + '_wide.csv')
```
#### Example of Merging Form Responses and Annotations
```python
import pandas as pd
annotations_wide_df = pd.read_csv('annotations-2023-05-13_08-47-26_wide.csv')
form_responses_wide_df = pd.read_csv('form-responses-2023-05-13_08-47-26_wide.csv')
# Ensure that the common columns have the same datatypes
form_responses_wide_df=form_responses_wide_df.astype(object)
annotations_wide_df=annotations_wide_df.astype(object)
# Get the common columns between the two dataframes
common_columns = set(annotations_wide_df.columns)
common_columns = list(common_columns.intersection(set(form_responses_wide_df.columns)))
common_columns = [
col for col in common_columns if col not in ['Created', 'Modified','Revision']
]
# Acquisition and File Name may not be common columns
common_columns = [
col
for col in common_columns
if col not in ["Acquisition Label", "acquisition.id", "File Name", "file.id"]
]
# Merge the two dataframes on the common columns
merged_df = pd.merge(
annotations_wide_df,
form_responses_wide_df,
on=list(common_columns),
how="outer"
)
# More than one annotation per task.id will produce multiple rows for the same task.id
merged_df.to_csv('merged_annotations_and_form_responses.csv')
```
The columns of each CSV output are described below.
#### **form-responses-\<datestamp\>.csv**
On form-response-scope being `task`, `non-task`, or `both` and a non-empty response,
the gear will output a CSV file containing the form responses for the specified
protocol.
The file name will be prefixed with `form-responses-` and suffixed with the datestamp
of the export (e.g. `form-responses-2023-05-13_08-47-26.csv`). The CSV will contain the
following columns:
- **Task ID**: The ID of the task the form response is associated with (e.g. R-2-1)
- **Task Type**: The type of the task the form response is associated with (e.g. Read)
- **Protocol Label**: The label of the protocol the form response is associated with.
- **Group**: The group the form response is associated with.
- **Project Label**: The project label the form response is associated with.
- **Subject Label**: The subject label the form response is associated with.
- **Session Label**: The session label the form response is associated with.
- **Session Timestamp**: The timestamp of the session.
- **Acquisition Label**: The acquisition label the form response is associated with.
Can be blank.
- **File Name**: The name of the file the form response is associated with.
Can be blank.
- **Task Assignee**: The user who was assigned the task. Blank if non-task.
- **Task Creator**: The user who created the task. Blank if non-task.
- **Task Due Date**: The due date of the task. Blank if non-task.
- **Task Status**: The status of the task (e.g. Complete, Todo, In_Progress).
Blank if non-task.
- **Question**: The text of a question (e.g. "What is the patient's age?")
- **Answer**: The answer to the question (e.g. "42")
- **Created**: The date the form response was created.
- **Modified**: The date the form response was last modified.
- **Revision**: The revision number of the form response.
- **Url**: The URL of the session the form response is associated with.
- **group**: The group.id.
- **project.id**: The ID of the project the form response is associated with.
- **subject.id**: The ID of the subject the form response is associated with.
- **session.id**: The ID of the session the form response is associated with.
- **acquisition.id**: The ID of the acquisition the form response is associated with.
- **file.file_id**: The ID of the file the form response is associated with.
- **formresponse.id**: The ID of the form response.
- **form.id**: The ID of the form the form response is associated with.
- **task.id**: The ID of the task the form response is associated with.
#### **annotations-\<datestamp\>.csv**
On annotations-scope being `task`, `non-task`, or `both` and a non-empty response, the
gear willoutput a CSV file containing the annotations for the specified protocol.
The file name will be prefixed with `annotations-` and suffixed with the datestamp
of the export (e.g. `annotations-2023-05-13_08-47-26.csv`). The CSV will contain the
following columns:
- **Task ID**: The ID of the task the annotation is associated with (e.g. R-2-1)
- **Task Type**: The type of the task the annotation is associated with (e.g. Read)
- **Group**: The group the annotation is associated with.
- **Project Label**: The project label the annotation is associated with.
- **Subject Label**: The subject label the annotation is associated with.
- **Session Label**: The session label the annotation is associated with.
- **Session Timestamp**: The timestamp of the session the annotation is associated with.
- **Acquisition Label**: The acquisition label the annotation is associated with.
- **File Name**: The name of the file the annotation is associated with.
- **Task Assignee**: The user who was assigned the task. Blank if non-task annotation.
- **Task Creator**: The user who created the task. Blank if non-task annotation.
- **Task Due Date**: The due date of the task. Blank if non-task annotation.
- **Task Status**: The status of the task (e.g. Complete, Todo, In_Progress).
Blank if non-task annotation.
- **SliceNumber**: The slice number of the image the annotation is drawn upon.
- **Location**: The label of the annotation. Corresponds to the label in the
form-responses.
- **Annotation ID**: The ID of the annotation.
- **Property**: The name of the property being reported on (e.g "toolType", "Area")
- **Value**: The value of the property being reported on (e.g. "Length", "859.075")
- **Created**: The date the annotation was created.
- **Modified**: The date the annotation was last modified.
- **Revision**: The revision number of the annotation.
- **frameIndex**: The frame index of the annotation. This will be `0` for non-DICOM
images and the slice number for DICOM images.
- **imagePath**: This will be a `$$$`-separated string representing different attributes
for DICOM and non-DICOM images.
- For DICOM images, the format is
`StudyInstanceUID$$$instancSeriesInstanceUIDeUID$$$SOPInstanceUID$$$frameIndex`.
- For NIfTI images, the format is
`fileName$$$Orientation$$$api-address#<slice_features>`.
- For other image types please see the
[Flywheel Annotation Data Format](https://gitlab.com/flywheel-io/public/ohif-viewer/-/wikis/Annotation-Data-Format) wiki.
- **group**: The group the annotation is associated with.
- **project.id**: The ID of the project the annotation is associated with.
- **subject.id**: The ID of the subject the annotation is associated with.
- **session.id**: The ID of the session the annotation is associated with.
- **acquisition.id**: The ID of the acquisition the annotation is associated with.
- **file.file_id**: The ID of the file the annotation is associated with.
- **File ID**: The ID of the file the annotation is associated with.
- **File Version**: The version of the file the annotation is associated with.
- **task.id**: The ID of the task the annotation is associated with.
Blank if non-task annotation.
#### Example of Retrieving Form-Responses from Session Variables
When session forms have been filled outside of the Reader Task Workflow (i.e.
using a `ohif_config.json` stored that the project leve), the form
responses are stored in the session custom info variable (`session.info`).
You can export the responses in 2 ways:
1. Using a [DataView](https://docs.flywheel.io/hc/en-us/articles/4536056285075)
to export as columns the responses you need.
2. Using the SDK. For instance, the script below can be used to retrieve the form responses from the
session info and convert them to a CSV file.
```python
import flywheel
import os
import json
import pandas as pd
api_key = os.environ['FW_LATEST_KEY']
client = flywheel.Client(api_key)
group="your_group"
project_label="form_and_annotation_export_project"
project = client.lookup(f"{group}/{project_label}")
read_df = pd.DataFrame()
df_indx = 0
for session in project.sessions.iter():
info = session.reload().info
reads = info.get("ohifViewer", {}).get("read", {})
reader_keys = info.get("ohifViewer", {}).get("read", {}).keys()
for reader in reader_keys:
read_df.at[df_indx, "session_id"] = session.id
read_df.at[df_indx, "session_label"] = session.label
read_df.at[df_indx, "reader"] = reader
read_df.at[df_indx, "date"] = reads.get(reader, {}).get("date", {})
read_df.at[df_indx, "readTime"] = reads.get(reader, {}).get("readTime", {})
read_df.at[df_indx, "readStatus"] = reads.get(reader, {}).get("readStatus", {})
for k,v in reads.get(reader, {}).get("notes", {}).items():
read_df.at[df_indx, k] = v
df_indx += 1
read_df.to_csv("read_df.csv", index=False)
```
## Cite
*License:* *MIT*
## Contributing
For more information about how to get started contributing to that gear,
checkout [CONTRIBUTING.md](CONTRIBUTING.md).
Raw data
{
"_id": null,
"home_page": "https://gitlab.com/flywheel-io/scientific-solutions/gears/fw-gear-form-and-annotations-exporter",
"name": "fw-gear-form-and-annotations-exporter",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "Flywheel, Gears",
"author": "Flywheel",
"author_email": "support@flywheel.io",
"download_url": null,
"platform": null,
"description": "# Form and Annotation Exporter <!-- omit in toc -->\n\n- [Overview](#overview)\n - [Summary](#summary)\n - [License](#license)\n - [Classification](#classification)\n- [Usage](#usage)\n - [Inputs](#inputs)\n - [Config](#config)\n - [Outputs](#outputs)\n - [Example Conversion to Wide Format](#example-conversion-to-wide-format)\n - [Example of Merging Form Responses and Annotations](#example-of-merging-form-responses-and-annotations)\n - [**form-responses-\\<datestamp\\>.csv**](#form-responses-datestampcsv)\n - [**annotations-\\<datestamp\\>.csv**](#annotations-datestampcsv)\n - [Example of Retrieving Form-Responses from Session Variables](#example-of-retrieving-form-responses-from-session-variables)\n- [Cite](#cite)\n- [Contributing](#contributing)\n\n## Overview\n\n### Summary\n\nExport Form Responses and/or Annotations to CSV file(s).\n\n### License\n\n*License:* MIT\n\n### Classification\n\n*Category:* Analysis\n\n*Gear Level:*\n\n- [X] Project\n- [X] Subject\n- [X] Session\n- [X] Acquisition\n- [ ] Analysis\n\n## Usage\n\nThe Form and Annotation Exporter gear is executed by ensuring the following\nconfiguration parameters are provided and are in a valid combination. This gear has no\nfile inputs. This gear requires that the Reader Task Workflow be enabled on the instance\nit is run on.\n\nIf an `ohif_config.json` is being used to configure the OHIF Viewer, and you are\nusing it to capture form responses outside of the Reader Task workflow, you cannot use\nthis gear to retrieve the form responses from the sessions. See the [Example of\nRetrieving Form-Responses from Session Variables](#example-of-retrieving-form-responses-from-session-variables)\nsection for anexample of how to do this.\n\nIf the gear is run within a project for a protocol where the *protocol_name* is\nnot defined, the gear will fail.\n\nFor the *annotations-scope* configuration parameter, the following combinations are valid:\n\n- `task` and `both` settings require a valid *protocol_name* for a protocol defined\n within the project.\n- `non-task` and `none` settings do not require a valid *protocol_name*. This allows for\n the export of annotations and form responses that are not associated with a task.\n- if both *-scope* settings are set to `none`, the gear will fail as there will be no\n output.\n\nFor the *form-responses-scope* configuration parameter, the following combinations are valid:\n\n- `task` and `none` are the only valid combinations\n\nRunning this gear under a specific subject, session, or acquisition will constrain the\noutput to only those tasks, form-responses, and annotations that are associated with\nthe container and its children.\n\nThis gear will output select annotation properties for the following annotation types:\n\n- Ellipse\n- Circle\n- Rectangle\n- Freehand/Contour (closed)\n- Length\n- Annotate (Arrow)\n- Bidirectional\n- Angle\n\nThe gear will output the following annotation properties if available in the tool type:\n\n- Area\n- Length\n- Angle\n- Units (of measurement)\n- min/max X/Y coordinates of a bounding box of the annotation\n- perpendicular min/max X/Y of a Bidirectional annotation\n- ShortestDiameter/LongestDiameter of a Bidirectional annotation\n\n### Inputs\n\nThis gear has no file input. The exported form responses and annotations will depend\non the level at which the gear is launched (e.g. project, subject, session, acquisition)\nand the confiugration options selected.\n\n### Config\n\n- *debug*\n - **Type**: *boolean*\n - **Description**: *Log debug messages*\n - **Default**: *False*\n- *protocol_name*\n - **Type**: *string*\n - **Description**: *The name of the protocol to export data from.*\n - **Optional**: *True*\n- *annotations-scope*\n - **Type**: *string*\n - **Description**: *The scope of the exported annotations.*\n - **Default**: *task*\n- *form-responses-scope*\n - **Type**: *string*\n - **Description**: *The scope of the form responses.*\n - **Default**: *task*\n- *read_timeout*\n - **Type**: *integer*\n - **Description**: *The maximum time in seconds to wait for a response from the server.*\n - **Default**: *60*\n\n### Outputs\n\nThe Form and Annotations Exporter gear has the following outputs:\n\n- form-responses-\\<datestamp\\>.csv\n- annotations-\\<datestamp\\>.csv\n\nFor form responses and annotations that are coordinated with a task, the above outputs\nwill correspond to the same Task ID and the `Location` column of the annotations CSV\nwill correspond to the matching `Question` with a `Answer` of `yes`. The question will\ntake the form of `<question #>: <Location>` (e.g. `2: LV`).\n\nBoth output CSV files are in a \"narrow\" format where each row represents a single form\nresponse Question/Answer or annotation Property/Value pair. Each of these CSV files can\nbe converted to a \"wide\" format using the `pandas` Python library with the [`pivot`\ncommand](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pivot.html). A\n[data dictionary](./data_dictionary.csv) is provided for the CSV files.\n\n#### Example Conversion to Wide Format\n\n```python\nimport pandas as pd\nfrom pathlib import Path\nroot_dir = Path('~')\n# Read in the CSV file\nform_responses_path = root_dir / 'form-responses-2023-05-13_08-47-26.csv'\ndf = pd.read_csv(form_responses_path)\nindex_cols = [col for col in list(df.columns) if col not in ['Question', 'Answer']]\ndf_wide = df.pivot(index=index_cols, columns='Question', values='Answer').reset_index()\ndf_wide.to_csv(root / (form_responses_path.stem + '_wide.csv'))\n\n# Read in the CSV file\nannotations_path = root_dir / 'annotations-2023-05-13_08-47-26.csv'\ndf = pd.read_csv(annotations_path)\nindex_cols = [col for col in list(df.columns) if col not in ['Property', 'Value']]\ndf_wide = df.pivot(index=index_cols, columns='Property', values='Value').reset_index()\ndf_wide.to_csv(annotations_path.stem + '_wide.csv')\n```\n\n#### Example of Merging Form Responses and Annotations\n\n```python\nimport pandas as pd\n\nannotations_wide_df = pd.read_csv('annotations-2023-05-13_08-47-26_wide.csv')\nform_responses_wide_df = pd.read_csv('form-responses-2023-05-13_08-47-26_wide.csv')\n\n# Ensure that the common columns have the same datatypes\nform_responses_wide_df=form_responses_wide_df.astype(object)\nannotations_wide_df=annotations_wide_df.astype(object)\n\n# Get the common columns between the two dataframes\ncommon_columns = set(annotations_wide_df.columns)\ncommon_columns = list(common_columns.intersection(set(form_responses_wide_df.columns)))\ncommon_columns = [\n col for col in common_columns if col not in ['Created', 'Modified','Revision']\n]\n\n# Acquisition and File Name may not be common columns\ncommon_columns = [\n col\n for col in common_columns\n if col not in [\"Acquisition Label\", \"acquisition.id\", \"File Name\", \"file.id\"]\n]\n\n# Merge the two dataframes on the common columns\nmerged_df = pd.merge(\n annotations_wide_df, \n form_responses_wide_df, \n on=list(common_columns), \n how=\"outer\"\n)\n\n# More than one annotation per task.id will produce multiple rows for the same task.id\nmerged_df.to_csv('merged_annotations_and_form_responses.csv')\n```\n\nThe columns of each CSV output are described below.\n\n#### **form-responses-\\<datestamp\\>.csv**\n\nOn form-response-scope being `task`, `non-task`, or `both` and a non-empty response,\nthe gear will output a CSV file containing the form responses for the specified\nprotocol.\n\nThe file name will be prefixed with `form-responses-` and suffixed with the datestamp\nof the export (e.g. `form-responses-2023-05-13_08-47-26.csv`). The CSV will contain the\nfollowing columns:\n\n- **Task ID**: The ID of the task the form response is associated with (e.g. R-2-1)\n- **Task Type**: The type of the task the form response is associated with (e.g. Read)\n- **Protocol Label**: The label of the protocol the form response is associated with.\n- **Group**: The group the form response is associated with.\n- **Project Label**: The project label the form response is associated with.\n- **Subject Label**: The subject label the form response is associated with.\n- **Session Label**: The session label the form response is associated with.\n- **Session Timestamp**: The timestamp of the session.\n- **Acquisition Label**: The acquisition label the form response is associated with.\nCan be blank.\n- **File Name**: The name of the file the form response is associated with.\nCan be blank.\n- **Task Assignee**: The user who was assigned the task. Blank if non-task.\n- **Task Creator**: The user who created the task. Blank if non-task.\n- **Task Due Date**: The due date of the task. Blank if non-task.\n- **Task Status**: The status of the task (e.g. Complete, Todo, In_Progress).\nBlank if non-task.\n- **Question**: The text of a question (e.g. \"What is the patient's age?\")\n- **Answer**: The answer to the question (e.g. \"42\")\n- **Created**: The date the form response was created.\n- **Modified**: The date the form response was last modified.\n- **Revision**: The revision number of the form response.\n- **Url**: The URL of the session the form response is associated with.\n- **group**: The group.id.\n- **project.id**: The ID of the project the form response is associated with.\n- **subject.id**: The ID of the subject the form response is associated with.\n- **session.id**: The ID of the session the form response is associated with.\n- **acquisition.id**: The ID of the acquisition the form response is associated with.\n- **file.file_id**: The ID of the file the form response is associated with.\n- **formresponse.id**: The ID of the form response.\n- **form.id**: The ID of the form the form response is associated with.\n- **task.id**: The ID of the task the form response is associated with.\n\n#### **annotations-\\<datestamp\\>.csv**\n\nOn annotations-scope being `task`, `non-task`, or `both` and a non-empty response, the\ngear willoutput a CSV file containing the annotations for the specified protocol.\nThe file name will be prefixed with `annotations-` and suffixed with the datestamp\nof the export (e.g. `annotations-2023-05-13_08-47-26.csv`). The CSV will contain the\nfollowing columns:\n\n- **Task ID**: The ID of the task the annotation is associated with (e.g. R-2-1)\n- **Task Type**: The type of the task the annotation is associated with (e.g. Read)\n- **Group**: The group the annotation is associated with.\n- **Project Label**: The project label the annotation is associated with.\n- **Subject Label**: The subject label the annotation is associated with.\n- **Session Label**: The session label the annotation is associated with.\n- **Session Timestamp**: The timestamp of the session the annotation is associated with.\n- **Acquisition Label**: The acquisition label the annotation is associated with.\n- **File Name**: The name of the file the annotation is associated with.\n- **Task Assignee**: The user who was assigned the task. Blank if non-task annotation.\n- **Task Creator**: The user who created the task. Blank if non-task annotation.\n- **Task Due Date**: The due date of the task. Blank if non-task annotation.\n- **Task Status**: The status of the task (e.g. Complete, Todo, In_Progress).\nBlank if non-task annotation.\n- **SliceNumber**: The slice number of the image the annotation is drawn upon.\n- **Location**: The label of the annotation. Corresponds to the label in the\nform-responses.\n- **Annotation ID**: The ID of the annotation.\n- **Property**: The name of the property being reported on (e.g \"toolType\", \"Area\")\n- **Value**: The value of the property being reported on (e.g. \"Length\", \"859.075\")\n- **Created**: The date the annotation was created.\n- **Modified**: The date the annotation was last modified.\n- **Revision**: The revision number of the annotation.\n- **frameIndex**: The frame index of the annotation. This will be `0` for non-DICOM\n images and the slice number for DICOM images.\n- **imagePath**: This will be a `$$$`-separated string representing different attributes\nfor DICOM and non-DICOM images.\n - For DICOM images, the format is\n `StudyInstanceUID$$$instancSeriesInstanceUIDeUID$$$SOPInstanceUID$$$frameIndex`.\n - For NIfTI images, the format is\n `fileName$$$Orientation$$$api-address#<slice_features>`.\n - For other image types please see the\n [Flywheel Annotation Data Format](https://gitlab.com/flywheel-io/public/ohif-viewer/-/wikis/Annotation-Data-Format) wiki.\n- **group**: The group the annotation is associated with.\n- **project.id**: The ID of the project the annotation is associated with.\n- **subject.id**: The ID of the subject the annotation is associated with.\n- **session.id**: The ID of the session the annotation is associated with.\n- **acquisition.id**: The ID of the acquisition the annotation is associated with.\n- **file.file_id**: The ID of the file the annotation is associated with.\n- **File ID**: The ID of the file the annotation is associated with.\n- **File Version**: The version of the file the annotation is associated with.\n- **task.id**: The ID of the task the annotation is associated with.\n Blank if non-task annotation.\n\n#### Example of Retrieving Form-Responses from Session Variables\n\nWhen session forms have been filled outside of the Reader Task Workflow (i.e.\nusing a `ohif_config.json` stored that the project leve), the form\nresponses are stored in the session custom info variable (`session.info`).\n\nYou can export the responses in 2 ways:\n\n 1. Using a [DataView](https://docs.flywheel.io/hc/en-us/articles/4536056285075)\n to export as columns the responses you need.\n\n 2. Using the SDK. For instance, the script below can be used to retrieve the form responses from the\n session info and convert them to a CSV file.\n\n ```python\n import flywheel\n import os\n import json\n import pandas as pd\n\n api_key = os.environ['FW_LATEST_KEY']\n client = flywheel.Client(api_key)\n\n group=\"your_group\"\n project_label=\"form_and_annotation_export_project\"\n project = client.lookup(f\"{group}/{project_label}\")\n\n read_df = pd.DataFrame()\n df_indx = 0\n for session in project.sessions.iter():\n info = session.reload().info\n reads = info.get(\"ohifViewer\", {}).get(\"read\", {})\n reader_keys = info.get(\"ohifViewer\", {}).get(\"read\", {}).keys()\n for reader in reader_keys:\n read_df.at[df_indx, \"session_id\"] = session.id\n read_df.at[df_indx, \"session_label\"] = session.label \n read_df.at[df_indx, \"reader\"] = reader\n read_df.at[df_indx, \"date\"] = reads.get(reader, {}).get(\"date\", {})\n read_df.at[df_indx, \"readTime\"] = reads.get(reader, {}).get(\"readTime\", {})\n read_df.at[df_indx, \"readStatus\"] = reads.get(reader, {}).get(\"readStatus\", {})\n for k,v in reads.get(reader, {}).get(\"notes\", {}).items():\n read_df.at[df_indx, k] = v\n df_indx += 1\n\n read_df.to_csv(\"read_df.csv\", index=False)\n ```\n\n## Cite\n\n*License:* *MIT*\n\n## Contributing\n\nFor more information about how to get started contributing to that gear,\ncheckout [CONTRIBUTING.md](CONTRIBUTING.md).\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Export Form Responses and/or Annotations to CSV file(s).",
"version": "0.1.5",
"project_urls": {
"Homepage": "https://gitlab.com/flywheel-io/scientific-solutions/gears/fw-gear-form-and-annotations-exporter",
"Repository": "https://gitlab.com/flywheel-io/scientific-solutions/gears/fw-gear-form-and-annotations-exporter"
},
"split_keywords": [
"flywheel",
" gears"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "826249f6453df0495d5fe01a0199c4d002697d4642152c7ee71d961e27e5a6eb",
"md5": "0771eb39f7910d15c7e1aac4ee131425",
"sha256": "2f2fb8d97f6262c64d169c08cbc02a983b656ad4f2d80d3401284580f15019eb"
},
"downloads": -1,
"filename": "fw_gear_form_and_annotations_exporter-0.1.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0771eb39f7910d15c7e1aac4ee131425",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 18941,
"upload_time": "2024-08-06T20:32:51",
"upload_time_iso_8601": "2024-08-06T20:32:51.194999Z",
"url": "https://files.pythonhosted.org/packages/82/62/49f6453df0495d5fe01a0199c4d002697d4642152c7ee71d961e27e5a6eb/fw_gear_form_and_annotations_exporter-0.1.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-06 20:32:51",
"github": false,
"gitlab": true,
"bitbucket": false,
"codeberg": false,
"gitlab_user": "flywheel-io",
"gitlab_project": "scientific-solutions",
"lcname": "fw-gear-form-and-annotations-exporter"
}