Title: Update MoCo Acquisition Label
Date: 04-03-2020
Description:
This notebook is used to rename MoCo Series based on the Scan Name, end with _moco
prefix
Functions:
get_scan_moco_label
: Identify the original scan labelmodify_acq_name
: Modify Acquisition name based on the session timepointupdate_acq_label
: Update the acquisition label on the FW instances# Install specific packages required for this notebook
!pip install flywheel-sdk pandas
# Import packages
from getpass import getpass
import logging
import os
import pandas as pd
import flywheel
from permission import check_user_permission
# Instantiate a logger
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
log = logging.getLogger('root')
Get a API_KEY. More on this at in the Flywheel SDK doc here.
API_KEY = getpass('Enter API_KEY here: ')
Instantiate the Flywheel API client
fw = flywheel.Client(API_KEY if 'API_KEY' in locals() else os.environ.get('FW_KEY'))
Show Flywheel logging information
log.info('You are now logged in as %s to %s', fw.get_current_user()['email'], fw.get_config()['site']['api_url'])
PROJECT_LABEL = input('Enter your project label here: ')
Before starting off, we want to check your permission on the Flywheel Instance in order to proceed in this notebook.
min_reqs = {
"site": "user",
"group": "ro",
"project": ['containers_modify_metadata','files_view_contents']
}
GROUP_ID = input('Please enter the Group ID that you will use in this notebook: ')
check_user_permission
will return True if both the group and project meet the minimum requirement, else a compatible list will be printed.
check_user_permission(fw, min_reqs, group=GROUP_ID, project=PROJECT_LABEL)
def update_moco_acq_label(acq_list):
"""Return `acq_list` with the updated MoCo label.
The `acq_label` is updated if the `acq_label` starts with ('MoCo') or ends with ('_moco') as well as the previous `acq_label` item in the `acq_list`.
Args:
acq_list : List of dictionaries that consists of
each acquisition label (`acq_label`),
acquisition id (`acq_id`) ,and
series number (`series_number`)
on one Session
Returns:
(list): `acq_list` with updated label name if label name is modified, NaN otherwise.
"""
for index, acq in enumerate(acq_list):
acq_label = acq['acq_label']
if acq_label.startswith('MoCo') or acq_label.endswith('_moco'):
# Get the original scan label (item before MoCo series is generated)
scan_acq_label = acq_list[index - 1]['acq_label']
scan_acq_id = acq_list[index - 1]['acq_id']
# modified the original scan label and update on the acquisition container
new_scan_label = modify_acq_name(scan_acq_label)
acq_list[index-1]['updated_label'] = new_scan_label
update_acq_label(scan_acq_id, new_scan_label)
# Rename the label for MoCo series with modified acq_label that ends with '_moco' prefix
moco_label = new_scan_label + '_moco'
acq_list[index]['updated_label'] = moco_label
update_acq_label(acq['acq_id'], moco_label)
return acq_list
def modify_acq_name(acq_name):
"""Get the modified Acquisition Label Name.
Note:
This function can be modified accordingly based on how you would like to structure your acquisition label.
Args:
acq_name (str) : Name for the Acquisition
Returns:
(str): `acq_name` with updated value if they matches the prefix
"""
separator = '_'
# In this use case, if the label ends either with `_0` or `_1` will be identified as run 2 (r2) and run 3 (r3) respectively
# if they do not match either of the prefix above, we will assume it ie run 1 (r1)
if acq_name.endswith('_0'):
split_name = acq_name.replace('0', 'r2').split(separator)
acq_name = split_name[0] + '_' + split_name[2]
elif acq_name.endswith('_1'):
split_name = acq_name.replace('_1', '_r3').split(separator)
acq_name = split_name[0] + '_' + split_name[2]
else:
acq_name = acq_name + '_r1'
return acq_name
def update_acq_label(acq_id, new_label):
"""Update the acquisition label on the project container.
Args:
acq_id (str) : Acquisition ID
new_label (str) : Updated Acquisition Label
"""
new_acq_object = flywheel.models.Acquisition(label = new_label)
# modifying the acquisition label here
fw.modify_acquisition(acquisition_id= acq_id, body = new_acq_object)
Here we will be iterating through each sessions and respective acquisitions, within the project container, to get the series_number
, acq_label
and the acq_id
. Then we will call the update_moco_acq_label
function to update the acquisition label.
# Get the project container
project = fw.projects.find_first(f'label={PROJECT_LABEL}')
# Generate an empty dataframe to be append later
df = pd.DataFrame()
for session in project.sessions.iter():
all_acq_list = []
for acquisition in session.acquisitions.iter():
# reload is necessary to load the entire acquisition
acquisition = acquisition.reload()
for file in acquisition.files:
if file['type'] == 'dicom':
item = {
'series_number': file.info.get('SeriesNumber'),
'acq_label': acquisition.label,
'acq_id': acquisition.id
}
all_acq_list.append(item)
# sort the list by their series number that is generated from the scanner
all_acq_list = sorted(all_acq_list, key=lambda k: k['series_number'])
acq_list = update_moco_acq_label(all_acq_list)
# to vizualize what has been modified in a tableview.
df = df.append(acq_list, ignore_index=True)
df.iloc[:, [0,1,3]].head(20)