Esempio n. 1
0
def test_get_predefined_label_for_scan_in_task__predefined_label(
        prepare_environment: Any) -> None:
    """Test for fetching Predefined Label that exists."""
    # Step 1. Prepare a structure for the test
    dataset = DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.RECTANGLE], task.id)
    scan = ScansRepository.add_new_scan(dataset, 0)
    user_id = UsersRepository.add_new_user(
        User('user@medtagger', 'HASH', 'Admin', 'Admin'))
    user = UsersRepository.get_user_by_id(user_id)

    # Step 2. Add Label which is predefined
    label = LabelsRepository.add_new_label(scan.id,
                                           task.key,
                                           user,
                                           LabelingTime(0),
                                           is_predefined=True)

    # Step 3. Check if there is is Predefined Label
    predefined_label = LabelsRepository.get_predefined_label_for_scan_in_task(
        scan, task)
    assert predefined_label
    assert predefined_label.id == label.id
Esempio n. 2
0
def test_add_point_label(prepare_environment: Any,
                         synchronous_celery: Any) -> None:
    """Test for adding a Label made with Point tool."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.POINT], task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 3}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    scan_id = json_response['scan_id']

    # Step 3. Label it with Point Tool
    payload = {
        'elements': [{
            'slice_index': 0,
            'x': 0.25,
            'y': 0.5,
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.POINT.value,
        }],
        'labeling_time':
        12.34,
    }
    data = {
        'label': json.dumps(payload),
    }
    response = api_client.post(
        '/api/v1/scans/{}/MARK_KIDNEYS/label'.format(scan_id),
        data=data,
        headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    label_id = json_response['label_id']
    assert isinstance(label_id, str)
    assert len(label_id) >= 1

    # Step 4. Fetch details about above Label
    response = api_client.get('/api/v1/labels/' + label_id,
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    assert len(json_response['elements']) == 1
    assert json_response['elements'][0]['x'] == 0.25
    assert json_response['elements'][0]['y'] == 0.5
Esempio n. 3
0
def test_ownership(prepare_environment: Any, synchronous_celery: Any) -> None:
    """Test for checking scan and label ownership."""
    api_client = get_api_client()

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('LUNGS', 'Lungs')
    task = TasksRepository.add_task('FIND_NODULES', 'Find Nodules', 'path/to/image', ['LUNGS'], '', [], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag', [LabelTool.RECTANGLE], task.id)
    admin_id, _ = create_user(ADMIN_EMAIL, ADMIN_PASSWORD, ADMIN_FIRST_NAME, ADMIN_LAST_NAME)
    set_user_role(admin_id, 'admin')

    # Step 2. Admin user logs in
    payload: Dict[str, Any] = {'email': ADMIN_EMAIL, 'password': ADMIN_PASSWORD}
    response = api_client.post('/api/v1/auth/sign-in', data=json.dumps(payload),
                               headers=get_headers(json=True))
    json_response = json.loads(response.data)
    admin_user_token = json_response['token']
    assert response.status_code == 200

    # Step 3. Add Scan to the system
    payload = {'dataset': 'LUNGS', 'number_of_slices': 1}
    response = api_client.post('/api/v1/scans', data=json.dumps(payload),
                               headers=get_headers(token=admin_user_token, json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    owner_id = json_response['owner_id']
    assert owner_id == admin_id
    scan_id = json_response['scan_id']

    # Step 4. Send slices
    with open('tests/assets/example_scan/slice_1.dcm', 'rb') as image:
        response = api_client.post('/api/v1/scans/{}/slices'.format(scan_id), data={
            'image': (image, 'slice_1.dcm'),
        }, content_type='multipart/form-data', headers=get_headers(token=admin_user_token))
    assert response.status_code == 201

    # Step 5. Label
    payload = {
        'elements': [{
            'x': 0.5,
            'y': 0.5,
            'slice_index': 0,
            'width': 0.1,
            'height': 0.1,
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.RECTANGLE.value,
        }],
        'labeling_time': 12.34,
    }
    response = api_client.post('/api/v1/scans/{}/FIND_NODULES/label'.format(scan_id),
                               data={'label': json.dumps(payload)},
                               headers=get_headers(token=admin_user_token, multipart=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    owner_id = json_response['owner_id']
    assert owner_id == admin_id
def test_add_label_with_tag_from_other_task(prepare_environment: Any,
                                            synchronous_celery: Any) -> None:
    """Test for adding a Label with Tag from other Task."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    left_task = TasksRepository.add_task('MARK_LEFT', 'Mark Left',
                                         'path/to/image', ['KIDNEYS'], '', [],
                                         [])
    right_task = TasksRepository.add_task('MARK_RIGHT', 'Mark Left',
                                          'path/to/image', ['KIDNEYS'], '', [],
                                          [])
    LabelTagsRepository.add_new_tag('TAG_LEFT', 'Tag Left', [LabelTool.POINT],
                                    left_task.id)
    LabelTagsRepository.add_new_tag('TAG_RIGHT', 'Tag Right',
                                    [LabelTool.POINT], right_task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 3}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    scan_id = json_response['scan_id']

    # Step 3. Label it with an element with Tag from another Task
    payload = {
        'elements': [{
            'slice_index': 0,
            'x': 0.25,
            'y': 0.5,
            'tag': 'TAG_RIGHT',
            'tool': LabelTool.POINT.value,
        }],
        'labeling_time':
        12.34,
    }
    data = {
        'label': json.dumps(payload),
    }
    response = api_client.post(
        '/api/v1/scans/{}/MARK_LEFT/label'.format(scan_id),
        data=data,
        headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 400
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    assert json_response['message'] == 'Invalid arguments.'
    assert json_response[
        'details'] == 'Tag TAG_RIGHT is not part of Task MARK_LEFT.'
Esempio n. 5
0
def test_get_predefined_label_for_scan_in_task__no_predefined_label(
        prepare_environment: Any) -> None:
    """Test for fetching Predefined Label that does not exist."""
    # Step 1. Prepare a structure for the test
    dataset = DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.RECTANGLE], task.id)
    scan = ScansRepository.add_new_scan(dataset, 0)

    # Step 2. Check if there is no Predefined Label
    predefined_label = LabelsRepository.get_predefined_label_for_scan_in_task(
        scan, task)
    assert not predefined_label
Esempio n. 6
0
def test_add_chain_label_not_enough_points(prepare_environment: Any,
                                           synchronous_celery: Any) -> None:
    """Test for adding a Label made with Chain tool."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.CHAIN], task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 3}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    scan_id = json_response['scan_id']

    # Step 3. Label it with Chain Tool
    payload = {
        'elements': [{
            'slice_index': 0,
            'points': [
                {
                    'x': 0.2,
                    'y': 0.3,
                },
            ],
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.CHAIN.value,
            'loop': False,
        }],
        'labeling_time':
        12.34,
    }
    data = {
        'label': json.dumps(payload),
    }
    response = api_client.post(
        '/api/v1/scans/{}/MARK_KIDNEYS/label'.format(scan_id),
        data=data,
        headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 400
Esempio n. 7
0
def test_get_predefined_brush_label_elements(prepare_environment: Any) -> None:
    """Test for fetching Predefined Brush Label Elements."""
    # Step 1. Prepare a structure for the test
    dataset = DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    label_tag = LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                                [LabelTool.RECTANGLE], task.id)
    scan = ScansRepository.add_new_scan(dataset, 3)
    user_id = UsersRepository.add_new_user(
        User('user@medtagger', 'HASH', 'Admin', 'Admin'))
    user = UsersRepository.get_user_by_id(user_id)

    # Step 2. Add Label with Brush Elements
    label = LabelsRepository.add_new_label(scan.id,
                                           task.key,
                                           user,
                                           LabelingTime(0),
                                           is_predefined=True)
    LabelsRepository.add_new_brush_label_element(label.id, 0, 0, 0, b'',
                                                 label_tag)
    LabelsRepository.add_new_brush_label_element(label.id, 1, 0, 0, b'',
                                                 label_tag)
    LabelsRepository.add_new_brush_label_element(label.id, 2, 0, 0, b'',
                                                 label_tag)

    # Step 3. Check if there is is Predefined Label
    brush_label_elements = LabelsRepository.get_predefined_brush_label_elements(
        scan.id, task.id, 0, 3)
    assert len(brush_label_elements) == 3
    brush_label_elements = LabelsRepository.get_predefined_brush_label_elements(
        scan.id, task.id, 0, 1)
    assert len(brush_label_elements) == 1
def _add_label_tag(tag: Dict, db_task_id: TaskID) -> None:
    """Add Label Tag or reuse previously created one.

    :param tag: configuration of a Label Tag
    :param db_task_id: TaskID which should be connected with this Label Tag
    """
    tools = [LabelTool[tool] for tool in tag['tools']]
    try:
        LabelTagsRepository.add_new_tag(tag['key'], tag['name'], tools, db_task_id)
    except IntegrityError:
        # Such Label Tag could be previously used in another Task
        logger.warning('Reusing previously existing Label Tag (%s)! This may cause data inconsistency! '
                       'Make sure you know what you are doing and clear database entries if necessary!',
                       tag['key'])
        LabelTagsRepository.update(tag['key'], tag['name'], tools, db_task_id)
        LabelTagsRepository.enable(tag['key'])
def test_add_label_non_existing_tag(prepare_environment: Any) -> None:
    """Test application for situation when users provides non existing tag."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], '', [], [])
    LabelTagsRepository.add_new_tag('LEFT_KIDNEY', 'Left Kidney',
                                    [LabelTool.RECTANGLE], task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 3}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    scan_id = json_response['scan_id']

    # Step 3. Create label
    payload = {
        'elements': [{
            'x': 0.5,
            'y': 0.5,
            'slice_index': 0,
            'width': 0.1,
            'height': 0.1,
            'tag': 'NON_EXISTING',
            'tool': LabelTool.RECTANGLE.value,
        }],
        'labeling_time':
        12.34,
    }
    response = api_client.post(
        '/api/v1/scans/{}/MARK_KIDNEYS/label'.format(scan_id),
        data={'label': json.dumps(payload)},
        headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 400
    json_response = json.loads(response.data)
    assert json_response[
        'details'] == 'Tag NON_EXISTING is not part of Task MARK_KIDNEYS.'
def test_delete_scan_without_slices(prepare_environment: Any,
                                    synchronous_celery: Any) -> None:
    """Test deleting scan without any slices."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.RECTANGLE], task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 0}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    scan_id: ScanID = json_response['scan_id']
    assert isinstance(scan_id, str)
    assert len(scan_id) >= 1

    # Step 3. Get scan
    response = api_client.get('/api/v1/scans/{}'.format(scan_id),
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    assert json_response['scan_id'] == scan_id
    assert json_response['number_of_slices'] == 0

    # Step 4. Delete scan from the system
    ScansRepository.delete_scan_by_id(scan_id)

    # Step 5. Check that scan has been deleted
    response = api_client.get('/api/v1/scans/{}'.format(scan_id),
                              headers=get_headers(token=user_token))
    assert response.status_code == 404
Esempio n. 11
0
def prepare_scan_and_tag_for_labeling() -> Tuple[models.Scan, models.LabelTag]:
    """Create needed Scan and Label Tag for labeling purpose."""
    dataset = DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    label_tag = LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                                [definitions.LabelTool.POINT],
                                                task.id)
    scan = ScansRepository.add_new_scan(dataset, number_of_slices=3)
    for _ in range(3):
        scan.add_slice()
    return scan, label_tag
def test_get_predefined_label_for_scan_in_task__predefined_label_for_given_task(
        prepare_environment: Any) -> None:
    """Test for fetching Predefined Label only for specific Task."""
    # Step 1. Prepare a structure for the test
    dataset = DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task_left = TasksRepository.add_task('MARK_LEFT', 'Mark Left',
                                         'path/to/image', ['KIDNEYS'], '', [],
                                         [])
    task_right = TasksRepository.add_task('MARK_RIGHT', 'Mark Right',
                                          'path/to/image', ['KIDNEYS'], '', [],
                                          [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.RECTANGLE], task_left.id)
    scan = ScansRepository.add_new_scan(dataset, 0)
    user_id = UsersRepository.add_new_user(
        User('user@medtagger', 'HASH', 'Admin', 'Admin'))
    user = UsersRepository.get_user_by_id(user_id)

    # Step 2. Add Labels for each Task
    label_left = LabelsRepository.add_new_label(scan.id,
                                                task_left.key,
                                                user,
                                                LabelingTime(0),
                                                is_predefined=True)
    label_right = LabelsRepository.add_new_label(scan.id,
                                                 task_right.key,
                                                 user,
                                                 LabelingTime(0),
                                                 is_predefined=True)

    # Step 3. Check if there are these Predefined Labels
    predefined_label = LabelsRepository.get_predefined_label_for_scan_in_task(
        scan, task_left)
    assert predefined_label
    assert predefined_label.id == label_left.id
    predefined_label = LabelsRepository.get_predefined_label_for_scan_in_task(
        scan, task_right)
    assert predefined_label
    assert predefined_label.id == label_right.id
Esempio n. 13
0
def test_basic_flow_with_predefined_label(prepare_environment: Any,
                                          synchronous_celery: Any) -> None:
    """Test application with basic flow that uses Predefined Label in Scan."""
    api_client = get_api_client()
    web_socket_client = get_web_socket_client(namespace='/slices')
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.RECTANGLE, LabelTool.BRUSH],
                                    task.id)

    # Step 2. Get all datasets
    response = api_client.get('/api/v1/datasets',
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, list)
    dataset = json_response[0]
    dataset_key = dataset['key']
    task_key = dataset['tasks'][0]['key']

    # Step 3. Add Scan to the system
    payload = {'dataset': dataset_key, 'number_of_slices': 1}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    scan_id = json_response['scan_id']

    # Step 4. Send slices
    with open('tests/assets/example_scan/slice_1.dcm', 'rb') as image:
        response = api_client.post('/api/v1/scans/{}/slices'.format(scan_id),
                                   data={
                                       'image': (image, 'slice_1.dcm'),
                                   },
                                   content_type='multipart/form-data',
                                   headers=get_headers(token=user_token))
    assert response.status_code == 201

    # Step 5. Send Predefined Label
    payload = {
        'elements': [{
            'x': 0.5,
            'y': 0.5,
            'slice_index': 0,
            'width': 0.1,
            'height': 0.1,
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.RECTANGLE.value,
        }, {
            'slice_index': 0,
            'width': 128,
            'height': 128,
            'image_key': 'SLICE_1',
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.BRUSH.value,
        }],
        'labeling_time':
        None,
    }
    with open('tests/assets/example_labels/binary_mask.png', 'rb') as image:
        data = {
            'label': json.dumps(payload),
            'SLICE_1': (image, 'slice_1'),
        }
        response = api_client.post(
            '/api/v1/scans/{}/MARK_KIDNEYS/label?is_predefined=true'.format(
                scan_id),
            data=data,
            headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    predefined_label_id = json_response['label_id']
    assert type(predefined_label_id), str
    assert predefined_label_id

    # Step 6. Get random scan
    response = api_client.get('/api/v1/scans/random?task={}'.format(task_key),
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    assert json_response['scan_id'] == scan_id
    assert json_response['number_of_slices'] == 1
    assert json_response['width'] == 512
    assert json_response['height'] == 512
    assert json_response['predefined_label_id'] == predefined_label_id

    # Step 7. Get slices from the server
    payload = {
        'scan_id': scan_id,
        'task_key': task_key,
        'begin': 0,
        'count': 1
    }
    web_socket_client.emit('request_slices', payload, namespace='/slices')
    responses = web_socket_client.get_received(namespace='/slices')
    assert len(responses) == 2
    slice_response = next(response for response in responses
                          if response['name'] == 'slice')
    assert slice_response['args'][0]['scan_id'] == scan_id
    assert slice_response['args'][0]['index'] == 0
    assert isinstance(slice_response['args'][0]['image'], bytes)
    brush_label_response = next(response for response in responses
                                if response['name'] == 'brush_labels')
    assert brush_label_response['args'][0]['scan_id'] == scan_id
    assert brush_label_response['args'][0]['tag_key'] == 'EXAMPLE_TAG'
    assert brush_label_response['args'][0]['index'] == 0
    assert isinstance(brush_label_response['args'][0]['image'], bytes)

    # Step 8. Label it
    payload = {
        'elements': [{
            'x': 0.5,
            'y': 0.5,
            'slice_index': 0,
            'width': 0.1,
            'height': 0.1,
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.RECTANGLE.value,
        }],
        'labeling_time':
        12.34,
    }
    response = api_client.post(
        '/api/v1/scans/{}/MARK_KIDNEYS/label'.format(scan_id),
        data={'label': json.dumps(payload)},
        headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    label_id = json_response['label_id']
    assert isinstance(label_id, str)
    assert len(label_id) >= 1

    # Step 9. Get random label for validation
    response = api_client.get('/api/v1/labels/random',
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    assert json_response['label_id'] == label_id
Esempio n. 14
0
def test_adding_new_survey(prepare_environment: Any) -> None:
    """Test for adding new Survey and fetching it through API."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('volunteer')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    label_tag = LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                                [LabelTool.RECTANGLE], task.id)

    # Step 2. Add an example of Survey
    survey = Survey(name='Colors Survey',
                    initial_element_key=SurveyElementKey('FIRST_QUESTION'))
    survey.elements = [
        SurveySingleChoiceQuestion(
            key=SurveyElementKey('FIRST_QUESTION'),
            title='What is your favourite color?',
            possible_answers={
                'Red': SurveyElementKey('SECOND_QUESTION'),
                'Green': None,
                'Blue': None,
            },
        ),
        SurveySingleChoiceQuestion(
            key=SurveyElementKey('SECOND_QUESTION'),
            title='Why do you like Red?',
            possible_answers={
                'It is nice': None,
                'Love it': None,
                'I do not know': None,
            },
        ),
    ]
    label_tag.actions.append(survey)
    label_tag.save()

    # Step 3.1 Check if it's available through API
    response = api_client.get('/api/v1/labels/actions/1',
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert set(json_response) == {'action_id', 'action_type', 'details'}
    assert json_response['action_id'] == 1
    assert json_response['action_type'] == 'Survey'
    assert isinstance(json_response['details'], dict)

    # Step 3.2. Make sure that Survey details have all necessary fields
    assert set(json_response['details']) == {
        'name', 'initial_element_key', 'elements'
    }
    assert json_response['details']['name'] == 'Colors Survey'
    assert json_response['details']['initial_element_key'] == 'FIRST_QUESTION'
    assert isinstance(json_response['details']['elements'], list)

    # Step 3.3. Check what elements does this Survey contain
    all_elements = json_response['details']['elements']
    assert len(all_elements) == 2
    all_element_keys = {element['key'] for element in all_elements}
    assert all_element_keys == {'FIRST_QUESTION', 'SECOND_QUESTION'}

    # Step 3.4. Check what does first question has inside
    first_question = next(element for element in all_elements
                          if element['key'] == 'FIRST_QUESTION')
    assert first_question == {
        'key': 'FIRST_QUESTION',
        'instant_next_element': None,
        'type': 'SurveySingleChoiceQuestion',
        'title': 'What is your favourite color?',
        'possible_answers': {
            'Red': 'SECOND_QUESTION',
            'Green': None,
            'Blue': None,
        },
    }

    # Step 3.5. Check what second question has inside
    first_question = next(element for element in all_elements
                          if element['key'] == 'SECOND_QUESTION')
    assert first_question == {
        'key': 'SECOND_QUESTION',
        'instant_next_element': None,
        'type': 'SurveySingleChoiceQuestion',
        'title': 'Why do you like Red?',
        'possible_answers': {
            'It is nice': None,
            'Love it': None,
            'I do not know': None,
        },
    }

    # Step 4. Check if we can fetch any unavailable Action through API
    response = api_client.get('/api/v1/labels/actions/2',
                              headers=get_headers(token=user_token))
    assert response.status_code == 404
    json_response = json.loads(response.data)
    assert json_response == {
        'message': 'Requested object does not exist.',
        'details': 'Action "2" not found.',
    }

    # Step 5. Check if above Action is available from Task endpoint
    response = api_client.get('/api/v1/tasks',
                              headers=get_headers(token=user_token))
    json_response = json.loads(response.data)
    mark_kidneys_task = next(task for task in json_response
                             if task['key'] == 'MARK_KIDNEYS')
    example_tag = next(tag for tag in mark_kidneys_task['tags']
                       if tag['key'] == 'EXAMPLE_TAG')
    assert example_tag['actions_ids'] == [1]
Esempio n. 15
0
def test_add_brush_label(prepare_environment: Any,
                         synchronous_celery: Any) -> None:
    """Test for adding a Label made with Brush tool."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.BRUSH], task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 3}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    scan_id = json_response['scan_id']

    # Step 3. Label it with Brush
    payload = {
        'elements': [{
            'slice_index': 0,
            'width': 128,
            'height': 128,
            'image_key': 'SLICE_1',
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.BRUSH.value,
        }],
        'labeling_time':
        12.34,
        'task_id':
        TasksRepository.get_task_by_key('MARK_KIDNEYS').id,
    }
    with open('tests/assets/example_labels/binary_mask.png', 'rb') as image:
        data = {
            'label': json.dumps(payload),
            'SLICE_1': (image, 'slice_1'),
        }
        response = api_client.post(
            '/api/v1/scans/{}/MARK_KIDNEYS/label'.format(scan_id),
            data=data,
            headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    label_id = json_response['label_id']
    assert isinstance(label_id, str)
    assert len(label_id) >= 1

    # Step 4. Fetch details about above Label and check image storage
    response = api_client.get('/api/v1/labels/' + label_id,
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    label_element_id = json_response['elements'][0]['label_element_id']
    brush_label_element = BrushLabelElement.get(id=label_element_id)
    assert brush_label_element.image
def test_delete_scan_with_slices(prepare_environment: Any,
                                 synchronous_celery: Any) -> None:
    """Test deleting scan with at least 1 slice."""
    api_client = get_api_client()
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag',
                                    [LabelTool.RECTANGLE], task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 1}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    scan_id: ScanID = json_response['scan_id']
    assert isinstance(scan_id, str)
    assert len(scan_id) >= 1

    # Step 3. Send slices
    with open('tests/assets/example_scan/slice_1.dcm', 'rb') as image:
        response = api_client.post('/api/v1/scans/{}/slices'.format(scan_id),
                                   data={
                                       'image': (image, 'slice_1.dcm'),
                                   },
                                   content_type='multipart/form-data',
                                   headers=get_headers(token=user_token))
        assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    slice_id: SliceID = json_response['slice_id']
    assert isinstance(slice_id, str)
    assert len(slice_id) >= 1

    # Step 4. Get scan
    response = api_client.get('/api/v1/scans/{}'.format(scan_id),
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    assert json_response['scan_id'] == scan_id
    assert json_response['number_of_slices'] == 1
    assert json_response['width'] == 512
    assert json_response['height'] == 512

    # Step 5. Delete scan from the system
    ScansRepository.delete_scan_by_id(scan_id)

    # Step 6. Check that scan has been deleted
    response = api_client.get('/api/v1/scans/{}'.format(scan_id),
                              headers=get_headers(token=user_token))
    assert response.status_code == 404

    # Step 7. Check that slices has been deleted
    with pytest.raises(NoResultFound):
        SliceRepository.get_slice_by_id(slice_id)
def test_delete_scan_with_labels(prepare_environment: Any,
                                 synchronous_celery: Any) -> None:
    """Test deleting scan with at least 1 slice and with labels made with all tools."""
    api_client = get_api_client()
    web_socket_client = get_web_socket_client(namespace='/slices')
    user_token = get_token_for_logged_in_user('admin')

    # Step 1. Prepare a structure for the test
    DatasetsRepository.add_new_dataset('KIDNEYS', 'Kidneys')
    task = TasksRepository.add_task('MARK_KIDNEYS', 'Mark Kidneys',
                                    'path/to/image', ['KIDNEYS'], [])
    LabelTagsRepository.add_new_tag('EXAMPLE_TAG', 'Example Tag', [
        LabelTool.RECTANGLE, LabelTool.CHAIN, LabelTool.POINT, LabelTool.BRUSH
    ], task.id)

    # Step 2. Add Scan to the system
    payload = {'dataset': 'KIDNEYS', 'number_of_slices': 1}
    response = api_client.post('/api/v1/scans',
                               data=json.dumps(payload),
                               headers=get_headers(token=user_token,
                                                   json=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    scan_id: ScanID = json_response['scan_id']
    assert isinstance(scan_id, str)
    assert len(scan_id) >= 1

    # Step 3. Send slices
    with open('tests/assets/example_scan/slice_1.dcm', 'rb') as image:
        response = api_client.post('/api/v1/scans/{}/slices'.format(scan_id),
                                   data={
                                       'image': (image, 'slice_1.dcm'),
                                   },
                                   content_type='multipart/form-data',
                                   headers=get_headers(token=user_token))
        assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    slice_id: SliceID = json_response['slice_id']
    assert isinstance(slice_id, str)
    assert len(slice_id) >= 1

    # Step 4. Get scan
    response = api_client.get('/api/v1/scans/{}'.format(scan_id),
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    assert json_response['scan_id'] == scan_id
    assert json_response['number_of_slices'] == 1
    assert json_response['width'] == 512
    assert json_response['height'] == 512

    # Step 5. Get slices from the server
    payload = {
        'scan_id': scan_id,
        'task_key': 'MARK_KIDNEYS',
        'begin': 0,
        'count': 1
    }
    web_socket_client.emit('request_slices', payload, namespace='/slices')
    responses = web_socket_client.get_received(namespace='/slices')
    assert len(responses) == 1
    response = responses[0]
    assert response['name'] == 'slice'
    assert response['args'][0]['scan_id'] == scan_id
    assert response['args'][0]['index'] == 0
    assert isinstance(response['args'][0]['image'], bytes)

    # Step 6. Label it with all available tools
    payload = {
        'elements': [{
            'x': 0.5,
            'y': 0.5,
            'slice_index': 0,
            'width': 0.1,
            'height': 0.1,
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.RECTANGLE.value,
        }, {
            'slice_index': 0,
            'width': 128,
            'height': 128,
            'image_key': 'SLICE_1',
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.BRUSH.value,
        }, {
            'slice_index': 0,
            'x': 0.25,
            'y': 0.5,
            'tag': 'EXAMPLE_TAG',
            'tool': LabelTool.POINT.value,
        }, {
            'slice_index':
            0,
            'points': [
                {
                    'x': 0.2,
                    'y': 0.3,
                },
                {
                    'x': 0.5,
                    'y': 0.8,
                },
            ],
            'tag':
            'EXAMPLE_TAG',
            'tool':
            LabelTool.CHAIN.value,
            'loop':
            False,
        }],
        'labeling_time':
        12.34,
    }
    with open('tests/assets/example_labels/binary_mask.png', 'rb') as image:
        data = {
            'label': json.dumps(payload),
            'SLICE_1': (image, 'slice_1'),
        }
        response = api_client.post(
            '/api/v1/scans/{}/MARK_KIDNEYS/label'.format(scan_id),
            data=data,
            headers=get_headers(token=user_token, multipart=True))
    assert response.status_code == 201
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    label_id = json_response['label_id']
    assert isinstance(label_id, str)
    assert len(label_id) >= 1

    # Step 7. Fetch details about above Label and check image storage
    response = api_client.get('/api/v1/labels/' + label_id,
                              headers=get_headers(token=user_token))
    assert response.status_code == 200
    json_response = json.loads(response.data)
    assert isinstance(json_response, dict)
    label_element_id = json_response['elements'][1]['label_element_id']
    brush_label_element = BrushLabelElement.get(id=label_element_id)
    assert brush_label_element.image

    # Step 7. Delete scan from the system
    ScansRepository.delete_scan_by_id(scan_id)

    # Step 8. Check that scan has been deleted
    response = api_client.get('/api/v1/scans/{}'.format(scan_id),
                              headers=get_headers(token=user_token))
    assert response.status_code == 404

    # Step 9. Check that slices has been deleted
    with pytest.raises(NoResultFound):
        SliceRepository.get_slice_by_id(slice_id)

    # Step 10. Check that slices original image has been deleted from storage
    with pytest.raises(DoesNotExist):
        OriginalSlice.get(id=slice_id)

    # Step 11. Check that slices processed image has been deleted from storage
    with pytest.raises(DoesNotExist):
        ProcessedSlice.get(id=slice_id)

    # Step 12. Check that labels has been deleted
    response = api_client.get('/api/v1/labels/{}'.format(label_id),
                              headers=get_headers(token=user_token))
    assert response.status_code == 404

    # Step 13. Check that Brush Label was deleted from storage
    with pytest.raises(DoesNotExist):
        BrushLabelElement.get(id=label_element_id)