def test_sample_composition_attributes(self):
        # Test a sample
        obs = SampleComposition(1)
        self.assertEqual(obs.sample_composition_type, 'experimental sample')
        self.assertEqual(obs.sample_id, '1.SKB1.640202')
        self.assertEqual(obs.content, '1.SKB1.640202.Test.plate.1.A1')
        self.assertEqual(obs.upstream_process, SamplePlatingProcess(11))
        self.assertEqual(obs.container, Well(3073))
        self.assertEqual(obs.total_volume, 10)
        self.assertIsNone(obs.notes)
        obs.notes = 'New Notes'
        self.assertEqual(obs.notes, 'New Notes')
        obs.notes = None
        self.assertIsNone(obs.notes)
        self.assertEqual(obs.composition_id, 3082)
        self.assertEqual(obs.study, Study(1))

        # Test a control sample
        obs = SampleComposition(8)
        self.assertEqual(obs.sample_composition_type, 'blank')
        self.assertIsNone(obs.sample_id)
        self.assertEqual(obs.content, 'blank.Test.plate.1.H1')
        self.assertEqual(obs.upstream_process, SamplePlatingProcess(11))
        self.assertEqual(obs.container, Well(3115))
        self.assertEqual(obs.total_volume, 10)
        self.assertIsNone(obs.notes)
        self.assertEqual(obs.composition_id, 3124)
        self.assertIsNone(obs.study)
    def post(self):
        user = self.current_user
        plate_config_id = self.get_argument('plate_configuration')
        plate_ext_id = self.get_argument('plate_name')

        spp = SamplePlatingProcess.create(user,
                                          PlateConfiguration(plate_config_id),
                                          plate_ext_id)

        self.write({'plate_id': spp.plate.id, 'process_id': spp.id})
Example #3
0
 def test_properties(self):
     tester = Well(3073)
     self.assertEqual(tester.plate, Plate(21))
     self.assertEqual(tester.row, 1)
     self.assertEqual(tester.column, 1)
     self.assertEqual(tester.remaining_volume, 10)
     self.assertIsNone(tester.notes)
     self.assertEqual(tester.latest_process, SamplePlatingProcess(11))
     self.assertEqual(tester.container_id, 3082)
     self.assertEqual(tester.composition, SampleComposition(1))
Example #4
0
def create_sample_plate_process(user, samples, is_96):
    plate_config = get_target_plate_configuration(is_96)
    num_rows = plate_config.num_rows
    num_cols = plate_config.num_columns
    sp_process = SamplePlatingProcess.create(user, plate_config,
                                             'Test plate %s' % datetime.now())

    # Plate the samples
    for idx, sample in enumerate(samples):
        i = int(idx / num_cols) + 1
        j = (idx % num_cols) + 1

        # Make sure that the user didn't pass more samples than wells
        if i > num_rows:
            break

        sp_process.update_well(i, j, sample)

    sample_plate = sp_process.plate
    return sp_process, sample_plate
Example #5
0
def plate_map_handler_get_request(process_id):
    plate_id = None
    if process_id is not None:
        try:
            process = SamplePlatingProcess(process_id)
        except LabControlUnknownIdError:
            raise HTTPError(404,
                            reason="Plating process %s doesn't exist" %
                            process_id)
        plate_id = process.plate.id

    plate_confs = [[pc.id, pc.description, pc.num_rows, pc.num_columns]
                   for pc in PlateConfiguration.iter()
                   if 'plate map' not in pc.description]
    cdesc = SampleComposition.get_control_sample_types_description()
    return {
        'plate_confs': plate_confs,
        'plate_id': plate_id,
        'process_id': process_id,
        'controls_description': cdesc
    }
Example #6
0
    def test_get_previously_plated_wells(self):
        tester = Plate(21)
        three_plates_list = [Plate(27), Plate(30), Plate(33)]
        exp = {
            Well(3073): three_plates_list,
            Well(3079): three_plates_list,
            Well(3085): three_plates_list,
            Well(3091): three_plates_list,
            Well(3097): three_plates_list,
            Well(3103): three_plates_list,
            Well(3121): three_plates_list,
            Well(3127): three_plates_list,
            Well(3133): three_plates_list,
            Well(3139): three_plates_list,
            Well(3145): three_plates_list,
            Well(3151): three_plates_list,
            Well(3169): three_plates_list,
            Well(3175): three_plates_list,
            Well(3181): three_plates_list,
            Well(3187): three_plates_list,
            Well(3193): three_plates_list,
            Well(3199): three_plates_list,
            Well(3217): three_plates_list,
            Well(3223): three_plates_list,
            Well(3229): three_plates_list,
            Well(3235): three_plates_list,
            Well(3241): three_plates_list,
            Well(3247): three_plates_list,
            Well(3265): three_plates_list,
            Well(3271): three_plates_list,
            Well(3277): three_plates_list,
            Well(3283): three_plates_list,
            Well(3289): three_plates_list,
            Well(3295): three_plates_list,
            Well(3313): three_plates_list,
            Well(3319): three_plates_list,
            Well(3325): three_plates_list,
            Well(3331): three_plates_list,
            Well(3337): three_plates_list,
            Well(3343): three_plates_list,
            Well(3361): three_plates_list,
            Well(3367): three_plates_list,
            Well(3373): three_plates_list,
            Well(3379): three_plates_list,
            Well(3385): three_plates_list,
            Well(3391): three_plates_list,
            Well(3409): three_plates_list,
            Well(3415): three_plates_list,
            Well(3421): three_plates_list,
            Well(3427): three_plates_list,
            Well(3433): three_plates_list,
            Well(3439): three_plates_list,
            Well(3457): three_plates_list,
            Well(3463): three_plates_list,
            Well(3469): three_plates_list,
            Well(3475): three_plates_list,
            Well(3481): three_plates_list,
            Well(3487): three_plates_list,
            Well(3505): three_plates_list,
            Well(3511): three_plates_list,
            Well(3517): three_plates_list,
            Well(3523): three_plates_list,
            Well(3529): three_plates_list,
            Well(3535): three_plates_list,
            Well(3553): three_plates_list,
            Well(3559): three_plates_list,
            Well(3565): three_plates_list,
            Well(3571): three_plates_list,
            Well(3577): three_plates_list,
            Well(3583): three_plates_list,
            Well(3601): three_plates_list,
            Well(3607): three_plates_list,
            Well(3613): three_plates_list,
            Well(3619): three_plates_list,
            Well(3625): three_plates_list
        }
        obs = tester.get_previously_plated_wells()
        self.assertEqual(obs, exp)

        # Create another plate and put a sample on it that isn't anywhere else
        spp = SamplePlatingProcess.create(User('*****@*****.**'),
                                          PlateConfiguration(1),
                                          'New Plate For Prev')
        spp.update_well(1, 1, '1.SKM1.640184')
        obs = spp.plate.get_previously_plated_wells()
        self.assertEqual(obs, {})
Example #7
0
    def test_properties(self):
        # Plate 21 - Defined in the test DB
        tester = Plate(21)

        obs = tester.creation_timestamp
        obs = str(datetime.datetime(obs.year, obs.month, obs.day))
        exp = datetime.datetime.now()
        exp = str(datetime.datetime(exp.year, exp.month, exp.day))
        self.assertEqual(obs, exp)
        self.assertEqual(tester.external_id, 'Test plate 1')
        self.assertEqual(tester.plate_configuration, PlateConfiguration(1))
        self.assertFalse(tester.discarded)
        tester.discarded = True
        self.assertTrue(tester.discarded)
        self.assertIsNone(tester.notes)
        obs_layout = tester.layout
        self.assertEqual(len(obs_layout), 8)
        for row in obs_layout:
            self.assertEqual(len(row), 12)
        self.assertEqual(tester.studies, {Study(1)})
        self.assertListEqual(tester.quantification_processes, [])
        self.assertEqual(tester.process, SamplePlatingProcess(11))

        # Test changing the name of the plate
        tester.external_id = 'Some new name'
        self.assertEqual(tester.external_id, 'Some new name')
        tester.external_id = 'Test plate 1'
        self.assertEqual(tester.external_id, 'Test plate 1')

        self.assertEqual(len(Plate(23).quantification_processes), 1)
        self.assertEqual(
            Plate(23).quantification_processes[0], QuantificationProcess(1))
        self.assertEqual(Plate(22).process, GDNAExtractionProcess(1))

        exp = {
            '1.SKB1.640202': [[Well(3073), '1.SKB1.640202.Test.plate.1.A1'],
                              [Well(3121), '1.SKB1.640202.Test.plate.1.A2'],
                              [Well(3169), '1.SKB1.640202.Test.plate.1.A3'],
                              [Well(3217), '1.SKB1.640202.Test.plate.1.A4'],
                              [Well(3265), '1.SKB1.640202.Test.plate.1.A5'],
                              [Well(3313), '1.SKB1.640202.Test.plate.1.A6'],
                              [Well(3361), '1.SKB1.640202.Test.plate.1.A7'],
                              [Well(3409), '1.SKB1.640202.Test.plate.1.A8'],
                              [Well(3457), '1.SKB1.640202.Test.plate.1.A9'],
                              [Well(3505), '1.SKB1.640202.Test.plate.1.A10'],
                              [Well(3553), '1.SKB1.640202.Test.plate.1.A11'],
                              [Well(3601), '1.SKB1.640202.Test.plate.1.A12']],
            '1.SKB2.640194': [[Well(3079), '1.SKB2.640194.Test.plate.1.B1'],
                              [Well(3127), '1.SKB2.640194.Test.plate.1.B2'],
                              [Well(3175), '1.SKB2.640194.Test.plate.1.B3'],
                              [Well(3223), '1.SKB2.640194.Test.plate.1.B4'],
                              [Well(3271), '1.SKB2.640194.Test.plate.1.B5'],
                              [Well(3319), '1.SKB2.640194.Test.plate.1.B6'],
                              [Well(3367), '1.SKB2.640194.Test.plate.1.B7'],
                              [Well(3415), '1.SKB2.640194.Test.plate.1.B8'],
                              [Well(3463), '1.SKB2.640194.Test.plate.1.B9'],
                              [Well(3511), '1.SKB2.640194.Test.plate.1.B10'],
                              [Well(3559), '1.SKB2.640194.Test.plate.1.B11'],
                              [Well(3607), '1.SKB2.640194.Test.plate.1.B12']],
            '1.SKB3.640195': [[Well(3085), '1.SKB3.640195.Test.plate.1.C1'],
                              [Well(3133), '1.SKB3.640195.Test.plate.1.C2'],
                              [Well(3181), '1.SKB3.640195.Test.plate.1.C3'],
                              [Well(3229), '1.SKB3.640195.Test.plate.1.C4'],
                              [Well(3277), '1.SKB3.640195.Test.plate.1.C5'],
                              [Well(3325), '1.SKB3.640195.Test.plate.1.C6'],
                              [Well(3373), '1.SKB3.640195.Test.plate.1.C7'],
                              [Well(3421), '1.SKB3.640195.Test.plate.1.C8'],
                              [Well(3469), '1.SKB3.640195.Test.plate.1.C9'],
                              [Well(3517), '1.SKB3.640195.Test.plate.1.C10'],
                              [Well(3565), '1.SKB3.640195.Test.plate.1.C11'],
                              [Well(3613), '1.SKB3.640195.Test.plate.1.C12']],
            '1.SKB4.640189': [[Well(3091), '1.SKB4.640189.Test.plate.1.D1'],
                              [Well(3139), '1.SKB4.640189.Test.plate.1.D2'],
                              [Well(3187), '1.SKB4.640189.Test.plate.1.D3'],
                              [Well(3235), '1.SKB4.640189.Test.plate.1.D4'],
                              [Well(3283), '1.SKB4.640189.Test.plate.1.D5'],
                              [Well(3331), '1.SKB4.640189.Test.plate.1.D6'],
                              [Well(3379), '1.SKB4.640189.Test.plate.1.D7'],
                              [Well(3427), '1.SKB4.640189.Test.plate.1.D8'],
                              [Well(3475), '1.SKB4.640189.Test.plate.1.D9'],
                              [Well(3523), '1.SKB4.640189.Test.plate.1.D10'],
                              [Well(3571), '1.SKB4.640189.Test.plate.1.D11'],
                              [Well(3619), '1.SKB4.640189.Test.plate.1.D12']],
            '1.SKB5.640181': [[Well(3097), '1.SKB5.640181.Test.plate.1.E1'],
                              [Well(3145), '1.SKB5.640181.Test.plate.1.E2'],
                              [Well(3193), '1.SKB5.640181.Test.plate.1.E3'],
                              [Well(3241), '1.SKB5.640181.Test.plate.1.E4'],
                              [Well(3289), '1.SKB5.640181.Test.plate.1.E5'],
                              [Well(3337), '1.SKB5.640181.Test.plate.1.E6'],
                              [Well(3385), '1.SKB5.640181.Test.plate.1.E7'],
                              [Well(3433), '1.SKB5.640181.Test.plate.1.E8'],
                              [Well(3481), '1.SKB5.640181.Test.plate.1.E9'],
                              [Well(3529), '1.SKB5.640181.Test.plate.1.E10'],
                              [Well(3577), '1.SKB5.640181.Test.plate.1.E11'],
                              [Well(3625), '1.SKB5.640181.Test.plate.1.E12']],
            '1.SKB6.640176': [[Well(3103), '1.SKB6.640176.Test.plate.1.F1'],
                              [Well(3151), '1.SKB6.640176.Test.plate.1.F2'],
                              [Well(3199), '1.SKB6.640176.Test.plate.1.F3'],
                              [Well(3247), '1.SKB6.640176.Test.plate.1.F4'],
                              [Well(3295), '1.SKB6.640176.Test.plate.1.F5'],
                              [Well(3343), '1.SKB6.640176.Test.plate.1.F6'],
                              [Well(3391), '1.SKB6.640176.Test.plate.1.F7'],
                              [Well(3439), '1.SKB6.640176.Test.plate.1.F8'],
                              [Well(3487), '1.SKB6.640176.Test.plate.1.F9'],
                              [Well(3535), '1.SKB6.640176.Test.plate.1.F10'],
                              [Well(3583), '1.SKB6.640176.Test.plate.1.F11']]
        }
        self.assertEqual(tester.duplicates, exp)
        self.assertEqual(tester.unknown_samples, [])
        exp = tester.get_well(1, 1)
        exp.composition.update('Unknown')
        self.assertEqual(tester.unknown_samples, [exp])
        exp.composition.update('1.SKB1.640202')

        # test that the quantification_processes attribute correctly
        # orders multiple processes in order from oldest to newest
        tester2 = Plate(26)
        self.assertEqual(len(tester2.quantification_processes), 2)
        # we are going to test the dates as string because in the database we
        # have the full date (including seconds)
        obs_date = str(tester2.quantification_processes[0].date)
        self.assertEqual(obs_date, "2017-10-25 19:10:25")
        obs_date = str(tester2.quantification_processes[1].date)
        self.assertEqual(obs_date, "2017-10-26 03:10:25")
def sample_plating_process_handler_patch_request(user, process_id, req_op,
                                                 req_path, req_value,
                                                 req_from):
    """Performs the patch operation on the sample plating process

    Parameters
    ----------
    user: labcontrol.db.user.User
        User performing the request
    process_id: int
        The SamplePlatingProcess to apply the patch operation
    req_op: string
        JSON PATCH op parameter
    req_path: string
        JSON PATCH path parameter
    req_value: string
        JSON PATCH value parameter
    req_from: string
        JSON PATCH from parameter

    Returns
    -------
    dict
        The results of the patch operation

    Raises
    ------
    HTTPError
        400: If req_op is not a supported operation
        400: If req_path is incorrect
    """
    if req_op == 'replace':
        req_path = [v for v in req_path.split('/') if v]
        if len(req_path) != 5:
            raise HTTPError(400, 'Incorrect path parameter')
        attribute = req_path[0]

        if attribute == 'well':
            row = req_path[1]
            col = req_path[2]
            study_id = int(req_path[3])
            well_attribute = req_path[4]

            # The default values of the variables sample_id and
            # blank_or_unknown are set before the try, and these are the values
            # that are used if either (a) study_id is not 0 OR (b) the try
            # fails with a ValueError (see comment in try below). If the try
            # fails with anything other than a ValueError then the entire
            # function bails, so it doesn't matter what these variables are set
            # to. If and only if the try succeeds are these variables set to
            # the values within the try.
            sample_id = req_value
            blank_or_unknown = True

            # It actually IS possible to plate a plate without specifying
            # separate study id(s); can plate just all blanks, or can provide
            # the fully qualified sample id(s)--i.e., <studyid>.<sampleid>.
            if study_id != 0:
                try:
                    # Note that the try fails iff the
                    # Study(study_id).specimen_id_to_sample_id() call fails,
                    # as the blank_or_unknown = False can't really fail ...
                    # this assures that we can't realistically end up in an
                    # inconsistent situation where sample_id has been set
                    # during the try but blank_or_unknown has not.
                    #
                    # Thus, the ordering of these two statements within the try
                    # is really important: do not change it unless you
                    # understand all of the above!
                    the_study = Study(study_id)
                    sample_id = the_study.specimen_id_to_sample_id(req_value)
                    blank_or_unknown = False
                except ValueError:
                    pass
                # end try/except
            # end if

            if well_attribute == 'sample':
                if req_value is None or not req_value.strip():
                    raise HTTPError(
                        400, 'A new value for the well should be provided')

                plates = Plate.search(samples=[sample_id])
                process = SamplePlatingProcess(process_id)
                plates = set(plates) - {process.plate}
                prev_plates = [{
                    'plate_id': p.id,
                    'plate_name': p.external_id
                } for p in plates]
                content, sample_ok = process.update_well(row, col, sample_id)

                if blank_or_unknown:
                    req_value = content

                return {
                    'sample_id': req_value,
                    'previous_plates': prev_plates,
                    'sample_ok': sample_ok
                }
            elif well_attribute == 'notes':
                if req_value is not None:
                    # If the user provides an empty string, just store None
                    # in the database
                    req_value = (req_value.strip()
                                 if req_value.strip() else None)
                SamplePlatingProcess(process_id).comment_well(
                    row, col, req_value)
                return {'comment': req_value}
            else:
                raise HTTPError(404,
                                'Well attribute %s not found' % well_attribute)
        else:
            raise HTTPError(404, 'Attribute %s not found' % attribute)

    else:
        raise HTTPError(
            400, 'Operation %s not supported. Current supported '
            'operations: replace' % req_op)
 def post(self):
     process = SamplePlatingProcess(self.get_argument('process_id'))
     process.notes = self.get_argument('notes')
     self.finish()