def _compute_pools(self, plate_info):
        self.plate_id = plate_info['plate-id']
        self.func_name = plate_info['pool-func']
        self.plate_type = plate_info['plate-type']
        self.quant_process_id = plate_info['quant-process-id']
        func_info = POOL_FUNCS[self.func_name]
        self.function = func_info['function']

        plate = Plate(self.plate_id)
        quant_process = QuantificationProcess(self.quant_process_id)

        # make params dictionary for function
        params = {}
        for arg, pfx in func_info['parameters']:
            param_key = '%s%s' % (pfx, self.plate_id)
            if param_key not in plate_info:
                raise HTTPError(400, reason='Missing parameter %s' % param_key)
            # empty strings are sent when we have disabled inputs.
            # we are testing for them explicitly where expected.
            if plate_info[param_key] != '':
                params[arg] = float(plate_info[param_key])
            else:
                params[arg] = plate_info[param_key]

        self.params = params

        # compute molar concentrations
        quant_process.compute_concentrations(size=params['size'])

        # calculate pooled values
        self.raw_concs, self.comp_concs, self.comp_blanks, \
        self.plate_names = make_2D_arrays(plate, quant_process)
Beispiel #2
0
 def post(self):
     pool_name = self.get_argument('pool_name')
     pools_info = json_decode(self.get_argument('pools_info'))
     concentrations = []
     input_compositions = []
     for p_info in pools_info:
         pool_comp = PoolComposition(p_info['pool_id'])
         concentrations.append({
             'composition': pool_comp,
             'concentration': p_info['concentration']
         })
         input_compositions.append({
             'composition':
             pool_comp,
             'input_volume':
             p_info['volume'],
             'percentage_of_output':
             p_info['percentage']
         })
     # Create the quantification process (DNA conc)
     q_process = QuantificationProcess.create_manual(
         self.current_user, concentrations)
     # Create the pool - Magic number 5 - > the volume for this pooling
     # is always 5 according to the wet lab.
     p_process = PoolingProcess.create(self.current_user, q_process,
                                       pool_name, 5, input_compositions, {
                                           "function": "amplicon_pool",
                                           "parameters": {}
                                       })
     self.write({'process': p_process.id})
Beispiel #3
0
def create_pool_quantification_process(user, pools):
    concentrations = np.around(np.random.rand(len(pools)), 6)
    concentrations = [{
        'composition': p,
        'concentration': c
    } for p, c in zip(pools, concentrations)]
    return QuantificationProcess.create_manual(user, concentrations)
    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'])

            # calculate estimated molar fraction for each element of pool
            amts = plate_result['comp_vals'] * plate_result['pool_vals']
            pcts = amts / amts.sum()

            quant_process = QuantificationProcess(
                plate_result['quant-process-id'])
            pool_name = 'Pool from plate %s (%s)' % (
                plate.external_id, datetime.now().strftime(
                    quant_process.get_date_format()))
            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))
    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)
    def post(self):
        plates_info = json_decode(self.get_argument('plates-info'))
        processes = []
        for pinfo in plates_info:
            plate = Plate(pinfo['plate_id'])
            concentrations = np.asarray(pinfo['concentrations'])

            processes.append(QuantificationProcess.create(
                self.current_user, plate, concentrations).id)

        self.write({'processes': processes})
    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')
        # NB: JavaScript uses true and false, posting converts them to strings
        reformat = reformat == 'true'

        processes = [
            [plate_id, NormalizationProcess.create(
                user, QuantificationProcess(quantification_process_id),
                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, quantification_process_id in
            json_decode(plates_info)]

        self.write({'processes': processes})
    def _compute_pools(self, plate_info):
        plate_id = plate_info['plate-id']
        func_name = plate_info['pool-func']
        plate_type = plate_info['plate-type']
        quant_process_id = plate_info['quant-process-id']
        func_info = POOL_FUNCS[func_name]
        function = func_info['function']

        plate = Plate(plate_id)
        quant_process = QuantificationProcess(quant_process_id)

        # make params dictionary for function
        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)
            # empty strings are sent when we have disabled inputs.
            # we are testing for them explicitly where expected.
            if plate_info[param_key] != '':
                params[arg] = float(plate_info[param_key])
            else:
                params[arg] = plate_info[param_key]

        # compute molar concentrations
        quant_process.compute_concentrations(size=params['size'])

        # calculate pooled values
        raw_concs, comp_concs, comp_blanks, \
        plate_names = make_2D_arrays(plate, quant_process)

        # for 16S, we calculate each sample independently
        pool_type = PLATE_TYPE_TO_POOL_TYPE[plate_type]
        params['total_each'] = POOL_TYPE_PARAMS[pool_type]['total_each']
        params['vol_constant'] = POOL_TYPE_PARAMS[pool_type]['vol_constant']
        pool_vals = function(raw_concs, **params)

        # if adjust blank volume, do that
        if params['blank_vol'] != '':
            pool_vals = PoolingProcess.adjust_blank_vols(pool_vals,
                                                         comp_blanks,
                                                         params['blank_vol'])

        # if only pool some blanks, do that
        if params['blank_num'] != '':
            pool_vals = PoolingProcess.select_blanks(pool_vals,
                                                     raw_concs,
                                                     comp_blanks,
                                                     int(params['blank_num']))

        # estimate pool volume and concentration
        total_c, total_v = PoolingProcess.estimate_pool_conc_vol(pool_vals,
                                                                 comp_concs)

        # store output values
        output = {}
        output['func_data'] = {'function': func_name,
                               'parameters': params}
        output['raw_vals'] = raw_concs
        output['comp_vals'] = comp_concs
        output['pool_vals'] = pool_vals
        output['pool_blanks'] = comp_blanks.tolist()
        output['plate_names'] = plate_names.tolist()
        output['plate_id'] = plate_id
        output['destination'] = params['destination']
        output['robot'] = params['robot']
        output['blank_vol'] = params['blank_vol']
        output['blank_num'] = params['blank_num']
        output['total_conc'] = total_c
        output['total_vol'] = total_v
        output['quant-process-id'] = quant_process_id

        return output
Beispiel #9
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")
Beispiel #10
0
def create_quantification_process(user, plate):
    plate_config = plate.plate_configuration
    concentrations = np.around(
        np.random.rand(plate_config.num_rows, plate_config.num_columns), 6)
    quant_process = QuantificationProcess.create(user, plate, concentrations)
    return quant_process