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})
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))
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
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 }
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, {})
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()