Data Model¶
Hierarchy¶
Data in a Flywheel system is organized in a tree-like hierarchy, as indicated in the following diagram.

User
- An authorized entity, usually referenced by email address.Group
- A grouping of users and projects.Project
- A project represents a grouping of subjects and sessions, e.g. within a study.Subject
- An individual under study.Session
- A grouping of acquired data, typically data acquired within a limited timeframe.Acquisition
- A set of one or more files, typically acquired as part of the same process, at the same time.AnalysisOutput
- A set of one or more derivative files from analyzing files after they have been acquired.
Permissions¶
Permissions in Flywheel are managed at the Group and Project level. Users that belong to a Group or a Project have a Role, which is one of:
Admin (
admin
) - Administrators can perform administrative-level actions such as setting permissions or creating and deleting projects.Read-Write (
rw
) - Users can read, create and delete data, but cannot assign permissions or delete entire projects.Read-Only (
ro
) - Users can only read data
By default when a new Project is created belonging to a Group, permissions will be copied from the Group to the Project, keeping user roles intact. From that point on, permissions for that Project must be managed at that project, changes made to the Group will not propagate to the project.
# See project permissions
project = fw.get(projectId);
disp(project.permissions{1});
# Add permission to a project
project.addPermission(flywheel.model.Permission('id', 'justinehlert@flywheel.io', 'access', 'ro'));
# Remove permission from a project
project.deletePermission(projectId, 'justinehlert@flywheel.io');
Custom Roles [NEW]¶
Custom roles can also be defined for more refined control over project access. To define a role, a label and list of allowed actions (for a full list of actions, see Available Actions).
% Edit these values to match a real group id and a project label that belongs to that group
group_id='group_id';
project_label='project_label';
% These actions (read_only actions) are required for any new role definition
REQUIRED_ACTIONS = {'containers_view_metadata',
'files_view_metadata',
'tags_view',
'notes_view',
'project_permissions_view',
'data_views_view',
'session_templates_view',
'gear_rules_view',
'jobs_view'
};
%Actions to be added:
OTHER_ACTIONS = {'files_modify_metadata'};
% Add files_modify_metadata to list
action_list = [REQUIRED_ACTIONS; OTHER_ACTIONS];
% Create a structure defining label and actions
role = struct('label','role_a_d30','actions',{action_list});
% Add the role to flywheel
role_a_d30 = fw.addRole(role);
% Add the role to a group
role_in = struct('id', {role_a_d30.id});
fw.addRoleToGroup(group_id, role_in)
% Get a project
project = fw.lookup([group_id,'/',project_label]);
% Add role for a user not yet on the project (but has been added to the Flywheel instance)
% Replace new_user@example.com with an email address belonging to a real user
user_id = 'new_user@example.com'
permission = struct('id',user_id,'roleIds',{{role_in.id}});
project.addPermission(permission)
% Add role for user with existing permissions on the project
% Add containers_modify_metadata to list
action_list = [REQUIRED_ACTIONS; {'containers_modify_metadata'}]
% Create a dictionary defining label and actions
role_dict = struct('label', 'barrel_role', 'actions', {action_list});
% Add the role to flywheel
barrel_role = fw.addRole(role_dict)
% Add the role to a group
fw.addRoleToGroup(group_id, struct('id',barrel_role.id))
% Get the current permission dictionary for user
permission_dict = fw.getProjectUserPermission(project.id, user_id);
% Add role id to the current list of role ids
permission_dict.roleIds = [permission_dict.roleIds; barrel_role.id];
% Update the user's permissions with the modified permission_dict
project.updatePermission(user_id, permission_dict);
% Just kidding let's remove that role
permission_dict.roleIds = {role_in.id};
project.updatePermission(user_id, permission_dict);
% Role cannot be in use when deleted
% Delete the role from group
fw.removeRoleFromGroup(group_id, barrel_role.id);
% Delete the role
fw.deleteRole(barrel_role.id);
% List all roles
all_roles = fw.getAllRoles();
for i=1:length(all_roles)
role = all_roles{i};
disp(role.label)
end
% print all labels to make sure we deleted it
% List all group roles
group_roles = fw.getAllGroupRoles(group_id)
for i=1:length(group_roles)
role = group_roles{i};
disp(role.label)
end
Available Actions¶
Action |
Description |
---|---|
containers_view_metadata |
View Container Metadata |
containers_create_hierarchy |
Create Container Hierarchy |
containers_modify_metadata |
Modify Container Metadata |
containers_delete_hierarchy |
Delete Container Hierarchy |
containers_delete_project |
Delete Project (Project Permission) |
analyses_view_metadata |
View Analysis Metadata |
analyses_create_sdk |
Create Adhoc Analysis |
analyses_create_job |
Create Job-Based Analysis |
analyses_modify_metadata |
Modify Analysis Metadata |
analyses_delete |
Delete Analysis |
files_view_metadata |
View File Metadata |
files_view_contents |
View File Contents |
files_download |
Download File |
files_create_upload |
Create/Upload File |
files_modify_metadata |
Modify File Metadata |
files_delete_non_device_data |
Delete Non-Device File Data |
files_delete_device_data |
Delete Device File Data |
tags_view |
View Tags |
tags_manage |
Manage Tags |
notes_view |
View Notes |
notes_manage |
Manage Notes |
project_permissions_view |
View Project Permissions |
project_permissions_manage |
Manage Project Permissions |
gear_rules_view |
View Project Gear Rules |
gear_rules_manage |
Manage Project Gear Rules |
data_views_view |
View Data Views |
data_views_manage |
Manage Data Views |
session_templates_view |
View Session Templates |
session_templates_manage |
Manage Session Templates |
jobs_view |
View Jobs |
jobs_run_cancel |
Run and Cancel Jobs |
jobs_cancel_any |
Cancel Any Job |
Containers¶
Projects, Subjects, Sessions, Acquisitions and Analyses are all different types of Containers. Containers in Flywheel all support the following features:
Notes¶
Notes are user-entered, human readable metadata attached to a container. They are timestamped and attributed to the user that entered them.
# See notes on a session
session = fw.get(sessionId);
disp(session.notes{1});
# Add a note to a session
session.addNote('This is a note');
# Delete a note from a session
session.deleteNote(session.notes{1}.id);
Info¶
Info is free-form JSON metadata associated with a container or file.
# Print the info for an acquisition
acquisition = fw.get(acquisitionId);
disp(acquisition.info);
# Replace the entire contents of acquisition info
acquisition.replaceInfo(struct('splines', 34));
# Add additional fields to acquisition info
acquisition.updateInfo(struct('curve', 'bezier'));
# Delete fields from acquisition info
acquisition.deleteInfo({{'splines'; 'bezier'}});
Files¶
Files are a set of file attachments associated with a container. See also Dealing with Files.
# List files on an acquisition
acquisition = fw.get(acquisitionId);
for idx = 1:numel(acquisition.files)
fprintf('Name: %s, type: %s\n', acquisition.files{idx}.name, acquisition.files{idx}.type);
end
# Upload a file to an acquisition
acquisition.uploadFile('/path/to/file.txt');
# Download a file to disk
acquisition.downloadFile('file.txt', '/path/to/file.txt');
# Files can also have metadata
disp(acquisition.files{1}.info);
acquisition.replaceFileInfo('file.txt', struct('wordCount', 327));
File Classification¶
Flywheel supports an extensible, multi-dimenstional classification scheme for files. Each dimension of classification is referred to as an aspect. The available aspects are determined by the file’s modality.
For example, the MR
modality provides the Intent
, Measurement
and Features
aspects.
In addition, the Custom
aspect is always available, regardless of modality.
% Display the aspects defined in the MR modality
mr = fw.get_modality('MR');
keys = mr.classification.keys();
for i = 1:numel(keys)
aspectName = keys{i};
aspectValues = strjoin(mr.classification.(aspectName), ', ');
fprintf('%s: %s\n', aspectName, aspectValues);
end
% Replace a file's modality and classification
acquisition.replaceFileClassification('file.txt', ...
struct('Intent', {{'Structural'}}, 'Measurement', {{'T2'}}),
'modality', 'MR');
% Update a file's Custom classification, without changing
% existing values or modality
acquisition.updateFileClassification('file.txt', ...
struct('Custom', {{'value1', 'value2'}}));
% Delete 'value1' from Custom classification
acquisition.deleteFileClassification('file.txt', ...
struct('Custom', {{'value1'}}));
Timestamps [NEW]¶
Objects with timestamps and created/modified dates provide helper accessors to get those dates in the local (system) timezone, as well as the original timezone in the case of acquisition and session timestamps.
For example:
% Acquisition Timestamp (tz=UTC)
disp(acquisition.timestamp);
% Acquisition Timestamp (tz=Local Timezone)
disp(acquisition.localTimestamp);
% Acquisition Timestamp (tz=Original Timezone)
disp(acquisition.originalTimestamp);
Age at Time of Session [NEW]¶
Sessions have a field for subject age at the time of the session, in seconds. There are also helper accessors to get age in years, months, weeks and days.
For example:
% Subject age in seconds
fprintf('Subject was %0.2f seconds old\n', session.age);
% Subject age in years
fprintf('Subject was %0.2f years old\n', session.ageYears);