Tutorial

Login to your account

All actions in the platform need to be authenticated. In qmenta.core, the platform.post() function has an instance of qmenta.core.platform.Auth for authentication. In order to create an Auth instance, you must use the login() function:

from qmenta.core.auth import Auth

auth = Auth.login('tutorial@qmenta.com', 'MyPassword1%')

The returned auth object is used in all the post() calls in the remainder of this tutorial.

Instead of hard-coding the password, it is recommended to use getpass.getpass() or to read it from a configuration file.

Projects

All requests to the platform can be done using a post() call. We use parse_response() to check the validity of the response and to extract the JSON information from the Response object:

from qmenta.core.platform import post, parse_response

projects = parse_response(post(
    auth, 'projectset_manager/get_projectset_list'
))

The returned value will be a list of dictionaries, where each dictionary represents a project and its information. For example:

print(projects)

>>>
[   {   '_id': 1,
        'user_id': 'tutorial@qmenta.com',
        'tags': ['test', 'example'],
        'name': 'Example project',
        'description': 'Example project for the qmenta.core tutorial',
        'time_created': '2020-01-01 08:00:14'
    },
    {   '_id': 2,
        'user_id': 'tutorial@qmenta.com'
        'tags': ['example'],
        'name': 'Another example project',
        'description': 'Of course you can have more than one project',
        'time_created': '2020-01-02 9:00:00'
    }
]

To find a project with a specific name you can use, for example:

[p for p in projects if p['name'].startswith('Example')

>>>

[   {   '_id': 1,
        'user_id': 'tutorial@qmenta.com',
        'tags': ['test', 'example'],
        'name': 'Example project',
        'description': 'Example project for the qmenta.core tutorial',
        'time_created': '2020-01-01 08:00:14'
    }
]

Subjects

Get existing subjects

To get the list of existing subjects in a project, you first activate the project, and then request the list of subjects:

post(auth, 'projectset_manager/activate_project', data={'project_id': 6})
subjects = parse_response(post(auth, 'patient_manager/get_patient_list'))

You can then view the subject data as a dict:

print(subjects[0])

>>>
{   '_id': 5395.0,
    'age_at_scan': None,
    'config':   {   'time_created': {'$date': 1545840544017},
                    'time_modified': {'$date': 1545840557867}
                },
    'container_id': 26817,
    'data_location': 'us',
    'date_at_scan': None,
    'owner': 'Tutorial user',
    'patient_secret_name': '123_4567',
    'qa_comments': '',
    'qa_status': '',
    'site': '',
    'ssid': '1',
    'tags': ['healthy'],
    'user_id': 'tutorial@qmenta.com'
}

Create a new session

To add a new subject to an existing project, you only need to specify its name:

resp = post(
    auth, 'patient_manager/upsert_patient', data={'secret_name': 'john-doe'}
)

parse_response(resp)

>>>
{   'success': 1,
    'message': 'Session data inserted successfully !',
    'ssid': '1'
}

This will automatically create the first session, with session ID ssid = 1. Executing the same command again will add another session with ssid = 2 to the subject. To get the Session IDs belonging to the newly added subject with the given patient_secret_name, execute:

subjects = parse_response(post(auth, 'patient_manager/get_patient_list'))

[(s['_id'], s['patient_secret_name'], s['ssid']) for s in subjects
    if s['patient_secret_name'] == 'john-doe']

>>>
[   (416522.0, 'john-doe', '1'),
    (416523.0, 'john-doe', '2')
]

Upload data

Sessions can be uploaded using the qmenta.core.upload module. To upload a single ZIP file to a project with Project ID 100, use:

from qmenta.core.upload import SingleUpload, FileInfo

upload = SingleUpload(
    auth, '/home/tutorial/data/file0.zip', FileInfo(project_id=100)
)
upload.start()

It is optional to add name, subject_name and session_id as attributes of FileInfo. If they are not specified, values will be chosen automatically. Instead of specifying a ZIP file to be uploaded, a directory may be given, and it will automatically be zipped before uploading.

When uploading a large amount of files, use MultipleThreadedUploads:

from qmenta.core.upload import MultiThreadedUploads, FileInfo

multi_upload = MultipleThreadedUploads(auth)
pid = 100

multi_upload.add_upload(
   '/home/tutorial/data/file1.zip',
   FileInfo(project_id=pid, name='file1')
)

multi_upload.add_upload(
    '/home/tim/data/file2.zip',
    FileInfo(project_id=pid, name='file2')
)

When using MultipleThreadedUploads, the uploads are started automatically, and multiple files will be uploaded in parallel.

In order to see the upload progress, connect to the blinker signals upload-status and upload-progress before starting the uploads. For example:

from blinker import signal

def progress_changed(caller, upload_index):
    single_upload = caller
    bytes_in_mb = 1024.0 * 1024.0
    percentage = (100.0 * single_upload.bytes_uploaded /
                single_upload.file_size)
    progress_message = ('[{:.0f}%] Progress for upload {} ({}): {:.2f}'
                        ' / {:.2f} MB').format(
        percentage,
        upload_index, single_upload.upload_filename,
        single_upload.bytes_uploaded / bytes_in_mb,
        single_upload.file_size / bytes_in_mb
    )
    print(progress_message)


def status_changed(caller, upload_index):
    single_upload = caller
    print('Status changed to {}'.format(single_upload.status.name))


on_progress = signal('upload-progress')
on_progress.connect(progress_changed)
on_status = signal('upload-status')
on_status.connect(status_changed)