Пример #1
0
    def test_plate_handler_patch_request(self):
        tester = Plate(21)
        user = User('*****@*****.**')

        # Incorrect path parameter
        regex = 'Incorrect path parameter'
        with self.assertRaisesRegex(HTTPError, regex):
            plate_handler_patch_request(user, 21, 'replace', '/name/newname',
                                        'NewName', None)

        # Unknown attribute
        regex = 'Attribute unknown not recognized'
        with self.assertRaisesRegex(HTTPError, regex):
            plate_handler_patch_request(user, 21, 'replace', '/unknown/',
                                        'NewName', None)

        # Unknown operation
        regex = ('Operation add not supported. Current supported '
                 'operations: replace')
        with self.assertRaisesRegex(HTTPError, regex):
            plate_handler_patch_request(user, 21, 'add', '/name/', 'NewName',
                                        None)

        # Plate doesn't exist
        regex = 'Plate 100 doesn\'t exist'
        with self.assertRaisesRegex(HTTPError, regex):
            plate_handler_patch_request(user, 100, 'replace', '/name/',
                                        'NewName', None)

        # Test success - Name
        plate_handler_patch_request(user, 21, 'replace', '/name/', 'NewName',
                                    None)
        self.assertEqual(tester.external_id, 'NewName')
        tester.external_id = 'Test plate 1'
Пример #2
0
 def test_patch_plate_handler(self):
     tester = Plate(21)
     data = {'op': 'replace', 'path': '/name/', 'value': 'NewName'}
     response = self.patch('/plate/21/', data)
     self.assertEqual(response.code, 200)
     self.assertEqual(tester.external_id, 'NewName')
     tester.external_id = 'Test plate 1'
Пример #3
0
    def post(self):
        plates_info = self.get_argument('plates_info')
        volume = self.get_argument('volume')
        preparation_date = self.get_argument('preparation_date')

        month, day, year = map(int, preparation_date.split('/'))
        preparation_date = date(year, month, day)

        processes = [
            LibraryPrep16SProcess.create(
                self.current_user,
                Plate(pid),
                Plate(pp),
                pn,
                Equipment(ep),
                Equipment(ep300),
                Equipment(ep50),
                ReagentComposition.from_external_id(mm),
                ReagentComposition.from_external_id(w),
                volume,
                preparation_date=preparation_date).id
            for pid, pn, pp, ep, ep300, ep50, mm, w in json_decode(plates_info)
        ]

        self.write({'processes': processes})
Пример #4
0
def get_primer_plate(is_96):
    plates = [
        Plate(item['plate_id']) for item in Plate.list_plates(['primer'])
    ]

    if is_96:
        # use different plates for 16S
        shuffle(plates)
        hit = None
        for plate in plates:
            pc = plate.plate_configuration
            if pc.description == '96-well microtiter plate':
                hit = plate
                break
        if hit is None:
            raise ValueError("Unable to identify a primer plate")
        return (hit, None)
    else:
        # not shuffling as the order of the plates implicitly matters
        hits = []
        for plate in plates:
            pc = plate.plate_configuration
            if pc.description == '384-well microtiter plate':
                if 'primer' in plate.external_id.lower():
                    hits.append(plate)
        hits = hits[:2]
        if len(hits) != 2:
            raise ValueError("Unable to identify two primer plates")
        return hits
Пример #5
0
 def test_patch_plate_discarded_handler(self):
     tester = Plate(21)
     data = {'op': 'replace', 'path': '/discarded/', 'value': True}
     response = self.patch('/plate/21/', data)
     self.assertEqual(response.code, 200)
     self.assertEqual(tester.discarded, True)
     tester.discarded = False
Пример #6
0
 def test_get_wells_by_sample(self):
     tester = Plate(21)
     exp = [Well(3073), Well(3121), Well(3169), Well(3217), Well(3265),
            Well(3313), Well(3361), Well(3409), Well(3457), Well(3505),
            Well(3553), Well(3601)]
     self.assertEqual(tester.get_wells_by_sample('1.SKB1.640202'), exp)
     self.assertEqual(tester.get_wells_by_sample('1.SKM1.640183'), [])
Пример #7
0
def create_shotgun_process(user, norm_plate):
    kappa = ReagentComposition(4)
    stub = ReagentComposition(5)
    shotgun_process = LibraryPrepShotgunProcess.create(
        user, norm_plate, 'Test Shotgun Library %s' % datetime.now(), kappa,
        stub, 4000, Plate(19), Plate(20))
    shotgun_plate = shotgun_process.plates[0]
    return shotgun_process, shotgun_plate
Пример #8
0
 def get(self):
     plate_type = self.get_argument('plate_type', None)
     res = {
         "data": [[
             p['plate_id'], p['external_id'],
             [s.title for s in Plate(p['plate_id']).studies]
         ] for p in Plate.list_plates(plate_type)]
     }
     self.write(res)
Пример #9
0
    def get(self):
        plate_ids = self.get_arguments('plate_id')
        process_id = self.get_argument('process_id', None)
        gdna_plate = None
        epmotion = None
        epmotion_tm300 = None
        epmotion_tm50 = None
        primer_plate = None
        master_mix = None
        water_lot = None
        volume = None
        prep_date = None
        if process_id is not None:
            try:
                process = LibraryPrep16SProcess(process_id)
            except LabmanUnknownIdError:
                raise HTTPError(404,
                                reason="Amplicon process %s doesn't exist" %
                                process_id)
            gdna_plate = process.gdna_plate.id
            epmotion = process.epmotion.id
            epmotion_tm300 = process.epmotion_tm300_tool.id
            epmotion_tm50 = process.epmotion_tm50_tool.id
            master_mix = process.mastermix.external_lot_id
            water_lot = process.water_lot.external_lot_id
            primer_plate = process.primer_plate.id
            volume = process.volume
            prep_date = process.date.strftime(process.get_date_format())

        robots = Equipment.list_equipment('EpMotion')
        tools_tm300_8 = Equipment.list_equipment(
            'tm 300 8 channel pipette head')
        tools_tm50_8 = Equipment.list_equipment('tm 50 8 channel pipette head')

        primer_plates = []
        for pp in Plate.list_plates(['primer']):
            plate = Plate(pp['plate_id'])
            if plate.process.primer_set.target_name == 'Amplicon':
                primer_plates.append(pp)

        self.render('library_prep_16S.html',
                    plate_ids=plate_ids,
                    robots=robots,
                    tools_tm300_8=tools_tm300_8,
                    tools_tm50_8=tools_tm50_8,
                    primer_plates=primer_plates,
                    process_id=process_id,
                    gdna_plate=gdna_plate,
                    epmotion=epmotion,
                    epmotion_tm300=epmotion_tm300,
                    epmotion_tm50=epmotion_tm50,
                    master_mix=master_mix,
                    water_lot=water_lot,
                    primer_plate=primer_plate,
                    preparationDate=prep_date,
                    volume=volume)
Пример #10
0
 def get(self):
     plate_type = self.get_argument('plate_type', None)
     only_quantified = self.get_argument('only_quantified', False)
     plate_type = (json_decode(plate_type)
                   if plate_type is not None else None)
     only_quantified = True if only_quantified == 'true' else False
     res = {"data": [[p['plate_id'], p['external_id'],
                      [s.title for s in Plate(p['plate_id']).studies]]
                     for p in Plate.list_plates(
                         plate_type, only_quantified=only_quantified)]}
     self.write(res)
Пример #11
0
 def test_get_wells_by_sample(self):
     tester = Plate(21)
     exp = [
         Well(3073),
         Well(3253),
         Well(3433),
         Well(3613),
         Well(3793),
         Well(3973)
     ]
     self.assertEqual(tester.get_wells_by_sample('1.SKB1.640202'), exp)
     self.assertEqual(tester.get_wells_by_sample('1.SKM1.640183'), [])
Пример #12
0
 def test_primer_set_attributes(self):
     obs = PrimerSet(1)
     self.assertEqual(obs.external_id, 'EMP 16S V4 primer set')
     self.assertEqual(obs.target_name, 'Amplicon')
     self.assertIsNone(obs.notes)
     self.assertEqual(obs.plates, [Plate(1), Plate(2), Plate(3), Plate(4),
                                   Plate(5), Plate(6), Plate(7), Plate(8)])
Пример #13
0
 def test_get_well(self):
     # Plate 21 - Defined in the test DB
     tester = Plate(21)
     self.assertEqual(tester.get_well(1, 1), Well(3073))
     self.assertEqual(tester.get_well(1, 2), Well(3088))
     self.assertEqual(tester.get_well(7, 2), Well(4168))
     self.assertEqual(tester.get_well(8, 12), Well(4498))
     with self.assertRaises(LabmanError):
         tester.get_well(8, 13)
     with self.assertRaises(LabmanError):
         tester.get_well(9, 12)
Пример #14
0
    def post(self):
        plate_id = self.get_argument('plate-id')
        concentrations = json_decode(self.get_argument('concentrations'))
        concentrations = np.asarray(concentrations)

        plate = Plate(plate_id)
        q_process = QuantificationProcess.create(self.current_user, plate,
                                                 concentrations)

        pool_name = 'Pool - %s' % plate.external_id

        input_compositions = []
        concentrations = q_process.concentrations
        total_vol = 0
        for conc in concentrations:
            in_vol = conc[1]
            total_vol += in_vol
            input_compositions.append({
                'composition': conc[0],
                'input_volume': in_vol,
                'percentage_of_output': in_vol
            })

        for ic in input_compositions:
            ic['percentage_of_output'] = ic['percentage_of_output'] / total_vol

        process = PoolingProcess.create(self.current_user, q_process,
                                        pool_name, total_vol,
                                        input_compositions)

        self.write({'process': process.id})
Пример #15
0
    def post(self):
        plates_info = json_decode(self.get_argument('plates-info'))

        results = []
        for pinfo in plates_info:
            plate_result = self._compute_pools(pinfo)
            plate = Plate(plate_result['plate_id'])
            pool_name = 'Pool from plate %s (%s)' % (
                plate.external_id,
                datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            # create input molar percentages
            pcts = calc_pool_pcts(plate_result['comp_vals'],
                                  plate_result['pool_vals'])
            quant_process = plate.quantification_process
            input_compositions = []
            for comp, _, _ in quant_process.concentrations:
                well = comp.container
                row = well.row - 1
                column = well.column - 1
                input_compositions.append(
                    {'composition': comp,
                     'input_volume': plate_result['pool_vals'][row][column],
                     'percentage_of_output': pcts[row][column]})
            robot = (Equipment(plate_result['robot'])
                     if plate_result['robot'] is not None else None)
            process = PoolingProcess.create(
                self.current_user, quant_process, pool_name,
                plate_result['pool_vals'].sum(), input_compositions,
                plate_result['func_data'], robot=robot,
                destination=plate_result['destination'])
            results.append({'plate-id': plate.id, 'process-id': process.id})

        self.write(json_encode(results))
Пример #16
0
 def get(self):
     plate_ids = self.get_arguments('plate_id')
     plates = [[p['plate_id'], p['external_id']]
               for p in Plate.list_plates('16S library prep')]
     self.render('parse_quantification.html',
                 plate_ids=plate_ids,
                 plates=plates)
Пример #17
0
    def post(self):
        user = self.current_user
        plates_info = self.get_argument('plates_info')
        water = self.get_argument('water')
        total_vol = self.get_argument('total_vol')
        ng = self.get_argument('ng')
        min_vol = self.get_argument('min_vol')
        max_vol = self.get_argument('max_vol')
        resolution = self.get_argument('resolution')
        reformat = self.get_argument('reformat')

        processes = [[
            plate_id,
            NormalizationProcess.create(
                user,
                Plate(plate_id).quantification_process,
                ReagentComposition.from_external_id(water),
                plate_name,
                total_vol=float(total_vol),
                ng=float(ng),
                min_vol=float(min_vol),
                max_vol=float(max_vol),
                resolution=float(resolution),
                reformat=reformat).id
        ] for plate_id, plate_name in json_decode(plates_info)]

        self.write({'processes': processes})
Пример #18
0
    def post(self):
        user = self.current_user
        plate_id = self.get_argument('plate_id')
        water = self.get_argument('water')
        plate_name = self.get_argument('plate_name')
        total_vol = self.get_argument('total_vol')
        ng = self.get_argument('ng')
        min_vol = self.get_argument('min_vol')
        max_vol = self.get_argument('max_vol')
        resolution = self.get_argument('resolution')
        reformat = self.get_argument('reformat')

        qprocess = Plate(plate_id).quantification_process

        process = NormalizationProcess.create(
            user,
            qprocess,
            ReagentComposition.from_external_id(water),
            plate_name,
            total_vol=float(total_vol),
            ng=float(ng),
            min_vol=float(min_vol),
            max_vol=float(max_vol),
            resolution=float(resolution),
            reformat=reformat)

        self.write({'process': process.id})
Пример #19
0
    def get(self):
        plate_ids = self.get_arguments('plate_id')
        process_id = self.get_argument('process_id', None)
        kappa = None
        stub = None
        volume = None
        norm_plate = None
        i5plate = None
        i7plate = None
        if process_id is not None:
            try:
                process = LibraryPrepShotgunProcess(process_id)
            except LabmanUnknownIdError:
                raise HTTPError(404,
                                reason="Shotgun library prep process %s "
                                "doesn't exist" % process_id)
            kappa = process.kappa_hyper_plus_kit.external_lot_id
            stub = process.stub_lot.external_lot_id
            norm_plate = process.normalized_plate.id
            i5plate = process.i5_primer_plate.id
            i7plate = process.i7_primer_plate.id
            volume = process.volume
        primer_plates = Plate.list_plates(['primer'])

        self.render('library_prep_shotgun.html',
                    plate_ids=plate_ids,
                    primer_plates=primer_plates,
                    process_id=process_id,
                    kappa=kappa,
                    stub=stub,
                    volume=volume,
                    norm_plate=norm_plate,
                    i5plate=i5plate,
                    i7plate=i7plate)
    def post(self):
        plate_name = self.get_argument('plate_name')
        volume = self.get_argument('volume')
        plate = self.get_argument('plate')
        i5_plate = self.get_argument('i5_plate')
        i7_plate = self.get_argument('i7_plate')
        kappa_hyper_plus_kit = self.get_argument('kappa_hyper_plus_kit')
        stub_lot = self.get_argument('stub_lot')

        process = LibraryPrepShotgunProcess.create(
            self.current_user, Plate(plate), plate_name,
            ReagentComposition.from_external_id(kappa_hyper_plus_kit),
            ReagentComposition.from_external_id(stub_lot), volume,
            Plate(i5_plate), Plate(i7_plate))

        self.write({'process': process.id})
Пример #21
0
    def post(self):
        user = self.current_user
        plates_info = self.get_argument('plates_info')
        volume = self.get_argument('volume')
        kappa_hyper_plus_kit = self.get_argument('kappa_hyper_plus_kit')
        stub_lot = self.get_argument('stub_lot')

        processes = [[
            pid,
            LibraryPrepShotgunProcess.create(
                user, Plate(pid), plate_name,
                ReagentComposition.from_external_id(kappa_hyper_plus_kit),
                ReagentComposition.from_external_id(stub_lot), volume,
                Plate(i5p), Plate(i7p)).id
        ] for pid, plate_name, i5p, i7p in json_decode(plates_info)]

        self.write({'processes': processes})
Пример #22
0
    def test_properties(self):
        # Plate 21 - Defined in the test DB
        tester = Plate(21)
        self.assertEqual(tester.external_id, 'Test plate 1')
        self.assertEqual(tester.plate_configuration, PlateConfiguration(1))
        self.assertFalse(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)

        # 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')
Пример #23
0
    def _compute_pools(self, plate_info):
        plate_id = plate_info['plate-id']
        func_name = plate_info['pool-func']
        func_info = POOL_FUNCS[func_name]
        function = func_info['function']
        plate = Plate(plate_id)
        quant_process = plate.quantification_process

        output = {}
        if func_name == 'amplicon':
            params = {}
            for arg, pfx in func_info['parameters']:
                param_key = '%s%s' % (pfx, plate_id)
                if param_key not in plate_info:
                    raise HTTPError(
                        400, reason='Missing parameter %s' % param_key)
                if arg in ('robot', 'destination'):
                    params[arg] = plate_info[param_key]
                else:
                    params[arg] = float(plate_info[param_key])
            # Amplicon
            output['robot'] = params.pop('robot')
            output['destination'] = params.pop('destination')
            output['func_data'] = {'function': 'amplicon',
                                   'parameters': params}
            # Compute the normalized concentrations
            quant_process.compute_concentrations(**params)
            # Compute the pooling values
            raw_concs, comp_concs = make_2D_arrays(plate, quant_process)
            output['raw_vals'] = raw_concs
            output['comp_vals'] = comp_concs
            output['pool_vals'] = comp_concs
        else:
            # Shotgun
            params = {}
            for arg, pfx in func_info['parameters']:
                param_key = '%s%s' % (pfx, plate_id)
                if param_key not in plate_info:
                    raise HTTPError(
                        400, reason='Missing parameter %s' % param_key)
                params[arg] = float(plate_info[param_key])
            # Compute the normalized concentrations
            output['func_data'] = {'function': func_name,
                                   'parameters': deepcopy(params)}
            size = params.pop('size')
            quant_process.compute_concentrations(size=size)
            # Compute the pooling values
            raw_concs, comp_concs = make_2D_arrays(plate, quant_process)
            output['raw_vals'] = raw_concs
            output['comp_vals'] = comp_concs
            output['pool_vals'] = function(comp_concs, **params)
            output['robot'] = None
            output['destination'] = None

        # Make sure the results are JSON serializable
        output['plate_id'] = plate_id
        output['pool_vals'] = output['pool_vals']
        return output
Пример #24
0
    def post(self):
        # We will receive as many files as plates the user has selected
        # The key of the self.request.files dictionary is of the form
        # plate-file-<PLATE_ID> so use the keys to know the plates
        # that we need to quantify
        plates = []
        for key in self.request.files:
            plate_id = key.rsplit('-', 1)[1]
            # The 0 is because for each key we have a single file
            file_content = self.request.files[key][0]['body'].decode('utf-8')
            plate = Plate(plate_id)
            pc = plate.plate_configuration
            concentrations = QuantificationProcess.parse(file_content,
                                                         rows=pc.num_rows,
                                                         cols=pc.num_columns)

            names = np.empty_like(plate.layout, dtype='object')
            blanks = np.zeros_like(plate.layout, dtype=bool)

            # fetch the sample names and whether or not the samples are blanks
            # by default these are set to be None and False.
            for i, full_row in enumerate(plate.layout):
                for j, well in enumerate(full_row):

                    # some wells have no compositions at all so skip those
                    if well is None:
                        continue
                    comp = well.composition

                    # cache the sample compositions to avoid extra intermediate
                    # queries
                    if isinstance(comp, GDNAComposition):
                        smp = comp.sample_composition
                    elif isinstance(comp, (CompressedGDNAComposition,
                                           LibraryPrep16SComposition)):
                        smp = comp.gdna_composition.sample_composition
                    elif isinstance(comp, LibraryPrepShotgunComposition):
                        smp = comp.normalized_gdna_composition\
                            .compressed_gdna_composition.gdna_composition\
                            .sample_composition
                    else:
                        raise ValueError('This composition type is not '
                                         'supported')

                    blanks[i][j] = smp.sample_composition_type == 'blank'
                    names[i][j] = smp.sample_id

            plates.append({
                'plate_name': plate.external_id,
                'plate_id': plate_id,
                'concentrations': concentrations.tolist(),
                'names': names.tolist(),
                'blanks': blanks.tolist(),
                'type': plate.process._process_type
            })

        self.render('quantification.html', plates=plates)
Пример #25
0
    def test_get_previously_plated_wells(self):
        tester = Plate(21)
        self.assertEqual(tester.get_previously_plated_wells(), {})

        # Create another plate and plate some samples in it
        spp = SamplePlatingProcess.create(
            User('*****@*****.**'), PlateConfiguration(1), 'New Plate For Prev')
        spp.update_well(1, 1, '1.SKD1.640179')
        exp = {}
        plate = spp.plate
        exp[Well(3208)] = [plate]
        exp[Well(3388)] = [plate]
        exp[Well(3568)] = [plate]
        exp[Well(3748)] = [plate]
        exp[Well(3928)] = [plate]
        exp[Well(4108)] = [plate]
        obs = tester.get_previously_plated_wells()
        self.assertEqual(obs, exp)
Пример #26
0
    def post(self):
        master_mix = self.get_argument('master_mix')
        water = self.get_argument('water')
        robot = self.get_argument('robot')
        tm300_8_tool = self.get_argument('tm300_8_tool')
        tm50_8_tool = self.get_argument('tm50_8_tool')
        volume = self.get_argument('volume')
        plates = self.get_argument('plates')

        plates = [(Plate(pid), Plate(ppid))
                  for pid, ppid in json_decode(plates)]

        process = LibraryPrep16SProcess.create(
            self.current_user, ReagentComposition.from_external_id(master_mix),
            ReagentComposition.from_external_id(water), Equipment(robot),
            Equipment(tm300_8_tool), Equipment(tm50_8_tool), volume, plates)

        self.write({'process': process.id})
Пример #27
0
    def get(self):
        plate_ids = self.get_arguments('plate_id')
        process_id = self.get_argument('process_id', None)
        input_plate = None
        pool_func_data = None
        pool_values = []
        pool_blanks = []
        plate_names = []
        plate_type = None
        if process_id is not None:
            try:
                process = PoolingProcess(process_id)
            except LabmanUnknownIdError:
                raise HTTPError(404,
                                reason="Pooling process %s doesn't exist" %
                                process_id)
            plate = process.components[0][0].container.plate
            input_plate = plate.id
            pool_func_data = process.pooling_function_data

            _, pool_values, pool_blanks, plate_names = \
                make_2D_arrays(plate, plate.quantification_process)

            pool_values = pool_values.tolist()
            pool_blanks = pool_blanks.tolist()
            plate_names = plate_names.tolist()

            if pool_func_data['function'] == 'amplicon':
                pool_func_data['parameters']['epmotion-'] = process.robot.id
                pool_func_data['parameters'][
                    'dest-tube-'] = process.destination
        elif len(plate_ids) > 0:
            content_types = {
                type(Plate(pid).get_well(1, 1).composition)
                for pid in plate_ids
            }
            if len(content_types) > 1:
                raise HTTPError(400,
                                reason='Plates contain different types '
                                'of compositions')
            plate_type = ('16S library prep'
                          if content_types.pop() == LibraryPrep16SComposition
                          else 'shotgun library prep')

        epmotions = Equipment.list_equipment('EpMotion')
        self.render('library_pooling.html',
                    plate_ids=plate_ids,
                    epmotions=epmotions,
                    pool_params=HTML_POOL_PARAMS,
                    input_plate=input_plate,
                    pool_func_data=pool_func_data,
                    process_id=process_id,
                    pool_values=pool_values,
                    plate_type=plate_type,
                    pool_blanks=pool_blanks,
                    plate_names=plate_names)
Пример #28
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))
Пример #29
0
    def post(self):
        plates = self.get_argument('plates')
        plate_ext_id = self.get_argument('plate_ext_id')

        plates = [Plate(pid) for pid in json_decode(plates)]

        process = GDNAPlateCompressionProcess.create(self.current_user, plates,
                                                     plate_ext_id)

        self.write({'process': process.id})
Пример #30
0
 def get(self, plate_id):
     urls = {
         SamplePlatingProcess: '/plate',
         GDNAExtractionProcess: '/process/gdna_extraction',
         LibraryPrep16SProcess: '/process/library_prep_16S',
         LibraryPrepShotgunProcess: '/process/library_prep_shotgun',
         NormalizationProcess: '/process/normalize',
         GDNAPlateCompressionProcess: '/process/gdna_compression'}
     process = Plate(plate_id).process
     self.redirect(urls[process.__class__] + '?process_id=%s' % process.id)