def find_cutters(self): # process assay sequence_group = self.__sequence_group_for_id(self.form_result['assay']) left_padding = self.form_result['left_padding'] right_padding = self.form_result['right_padding'] c.assay_id = self.form_result['assay'] c.left_padding = self.form_result['left_padding'] c.right_padding = self.form_result['right_padding'] c.enzymes = self.form_result['enzymes'] c.allow_methylation = self.form_result['allow_methylation'] and 1 or '' if sequence_group is None: abort(404) c.assay = sequence_group enzymes = self.__enzymes_from_form() ecache = dict([(enz.name, enz) for enz in enzymes]) amplicon_tuples = pcr_sequences_snps_for_group(sequence_group, padding_pos5=c.left_padding, padding_pos3=c.right_padding) if len(amplicon_tuples) == 0: c.found_sequence = False return render('/cutter/results.html') c.found_sequence = True # flatten sequences sequences = [] for amp, pseqs in amplicon_tuples: sequences.extend(pseqs) sequence_cut_data = self.__cuts_for_sequences(sequences, enzymes) for seq in sequence_cut_data: if self.form_result['singles_as_doubles']: seq[1]['left_cutters'].extend(seq[1]['around_cutters']) seq[1]['right_cutters'].extend(seq[1]['around_cutters']) seq[1]['double_digests'] = self.__compute_double_digests(seq[1]['left_cutters'], seq[1]['right_cutters']) # decorate with prices for enz in seq[1]['around_cutters']: enz['cost'] = ecache[enz['name']].VendorEnzyme.unit_cost_1 enz['cost_bin'] = ecache[enz['name']].VendorEnzyme.unit_cost_bin for enz in seq[1]['double_digests']: enz['cost'] = ecache[enz['pair'][0]].VendorEnzyme.unit_cost_1 + ecache[enz['pair'][1]].VendorEnzyme.unit_cost_1 enz['cost_bin'] = max(ecache[enz['pair'][0]].VendorEnzyme.unit_cost_bin, ecache[enz['pair'][1]].VendorEnzyme.unit_cost_bin) enz['buffer'] = ecache[enz['pair'][0]].VendorEnzyme.buffer.name # TODO: right to do here or in the template? seq[1]['left_cutters'] = [lcut['name'] for lcut in seq[1]['left_cutters']] seq[1]['right_cutters'] = [rcut['name'] for rcut in seq[1]['right_cutters']] seq[1]['around_cutters'] = self.__score_digests(seq[1]['around_cutters'], self.form_result['scoring_function']) seq[1]['double_digests'] = self.__score_digests(seq[1]['double_digests'], self.form_result['scoring_function']) c.cut_results = sequence_cut_data return render('/cutter/results.html')
def sequence(self): enzymes = self.__enzymes_from_form() c.form = h.LiteralForm( value = {'enzymes': ''}, option = {'enzymes': [('','--')]+[(e.cutseq, e.name) for e in enzymes]} ) assay = self.__sequence_group_for_id(self.form_result['assay']) c.assay = assay c.assay_id = c.assay.id c.assay_name = assay.name if assay is None: abort(404) left_padding = self.form_result['left_padding'] right_padding = self.form_result['right_padding'] c.left_padding = left_padding c.right_padding = right_padding c.enzymes = self.form_result['enzymes'] sequences = [] amplicon_tuples = pcr_sequences_snps_for_group(assay, padding_pos5=left_padding, padding_pos3=right_padding) for amp, pseqs in amplicon_tuples: sequences.extend(pseqs) if len(sequences) == 0: c.found_sequence = False return render('/cutter/sequence.html') # TODO: handle multi-sequence case sequence = sequences[0] c.found_sequence = True c.amplicon_width = len(sequence.amplicon) c.prefix_width = len(sequence.left_padding) if sequence.left_padding else 0 c.suffix_width = len(sequence.right_padding) if sequence.right_padding else 0 total_len = float(sequence.width) c.prefix_pct = 100*(c.prefix_width/total_len) c.amplicon_pct = 100*(c.amplicon_width/total_len) c.suffix_pct = 100*(c.suffix_width/total_len) c.amplicon_offset_pos = c.prefix_width c.amplicon_offset_neg = c.suffix_width c.sequence = sequence.merged_positive_sequence c.positive_sequence = sequence.merged_positive_sequence.sequence c.negative_sequence = sequence.merged_negative_sequence.sequence c.positive_sequence_fasta = sequence.merged_positive_sequence.fasta c.negative_sequence_fasta = sequence.merged_negative_sequence.fasta return render('/cutter/sequence.html')
def process_snp(self): snp_source = HG19Source() seq_source = UCSCSequenceSource() left_padding = 1000 right_padding = 1000 snps = snp_source.snps_by_rsid(self.form_result["snp_rsid"]) c.assay_form = h.LiteralForm() c.snp_rsid = self.form_result["snp_rsid"] c.width = self.form_result["width"] # override if not snps or len(snps) == 0: # TODO: figure out how to make this appear on the field error instead session["flash"] = "Could not find a SNP with the name %s" % self.form_result["snp_rsid"] session["flash_class"] = "error" session.save() return render("/assay/snp_output.html") sequences = [] for snp in snps: chromStart = snp["chromStart"] chromEnd = snp["chromEnd"] # handle insertions and single variations, normally the chromStart # refers to the gap just before the base # if snp["chromStart"] == snp["chromEnd"]: chromStart = chromEnd else: chromStart += 1 sequence = seq_source.sequence_around_region( snp["chrom"][3:], chromStart, chromEnd, self.form_result["width"], left_padding, right_padding ) # sequence.snps = self._get_snps(sequence.chromosome, sequence.start, sequence.end) sequences.append(sequence) c.left_padding = left_padding c.right_padding = right_padding c.sequences = sequences for seq in c.sequences: seq.snps = self._get_snps(seq.chromosome, seq.start, seq.end) seq.positive_display_sequence = seq.amplicon.positive_strand_sequence.lower() seq.negative_display_sequence = seq.amplicon.negative_strand_sequence.lower()[::-1] assayutil.set_amplicon_snps(c.sequences) return render("/assay/snp_output.html")
def by_well_tag(self): well_tag_field = fl.well_tag_field(str(self.form_result['well_tag'])) c.group_by_plate = self.form_result['group_by_plate'] c.tag_id = self.form_result['well_tag'] c.tag_name = Session.query(WellTag).get(c.tag_id).name c.form = h.LiteralFormSelectPatch( value = {'well_tag': well_tag_field['value'], 'group_by_plate': [u'1' if c.group_by_plate else u'0']}, option = {'well_tag': [('--','--')]+well_tag_field['options'], 'group_by_plate': [(u'1', '')]} ) well_tags = Session.query(WellTag).\ filter_by(id=c.tag_id).\ options(joinedload_all(WellTag.tag_wells, QLBWell.plate, QLBPlate.file, innerjoin=True), joinedload_all(WellTag.tag_wells, QLBWell.plate, QLBPlate.plate, innerjoin=True)).\ all() c.label_names = [] if not len(well_tags): c.wells = [] c.well_groups = [] elif c.group_by_plate: wells = sorted(well_tags[0].wells, key=lambda well: (well.plate_id, well.well_name)) well_groups = [(plate, list(wells)) for plate, wells in itertools.groupby(wells, lambda well: well.plate)] c.well_groups = sorted(well_groups, key=lambda tup: tup[0].host_datetime) c.well_groups.reverse() else: c.wells = sorted(well_tags[0].wells, key=lambda well: well.host_datetime) c.wells.reverse() return render('/box2/by_well_tag.html')
def manual(self): c.assay_name = "Manual Entry" seq = self.form_result['sequence'] c.amplicon_width = len(seq) c.prefix_width = 0 c.suffix_width = 0 enzymes = self.__enzymes_from_form() c.form = h.LiteralForm( value = {'enzyme': ''}, option = {'enzyme': [('','--')]+[(e.cutseq, e.name) for e in enzymes]} ) # TODO helper function for later (shared with sequence) c.prefix_pct = 0 c.amplicon_pct = 100 c.suffix_pct = 0 c.amplicon_offset_pos = c.prefix_width c.amplicon_offset_neg = c.suffix_width c.positive_sequence = seq c.negative_sequence = reverse_complement(seq) c.found_sequence = True c.left_padding = 0 c.right_padding = 0 c.assay_id = '' c.enzymes = self.form_result['enzymes'] c.form = h.LiteralForm( value = {'enzymes': ''}, option = {'enzymes': [('','--')]+[(e.cutseq, e.name) for e in enzymes]} ) return render('/cutter/sequence.html')
def enzyme_conc_edit(self, id=None): if id is None: abort(404) conc = Session.query(EnzymeConcentration).get(id) if not conc: abort(404) c.conc = conc enzyme_field = fl.enzyme_field(selected=unicode(conc.enzyme_id)) assay_field = fl.assay_field(blank=True, selected=unicode(conc.assay.id)) author_field = fl.person_field(selected=unicode(conc.author_id)) c.plate = None c.form = h.LiteralFormSelectPatch( value={ "enzyme_id": enzyme_field["value"], "assay_id": assay_field["value"], "author_id": author_field["value"], "minimum_conc": conc.minimum_conc, "maximum_conc": conc.maximum_conc, "source_plate_id": conc.source_plate_id, "notes": conc.notes, }, option={ "enzyme_id": enzyme_field["options"], "assay_id": assay_field["options"], "author_id": author_field["options"], }, ) return render("/assay/enzyme/edit.html")
def batch_filter(self): criteria = self.form_result['plate_type'] consumable_methods = (ManufacturingPlateBatch.DG_METHOD_WEIDMANN_V5, ManufacturingPlateBatch.DG_METHOD_THINXXS_V2A, ManufacturingPlateBatch.DG_METHOD_THINXXS_V2B, ManufacturingPlateBatch.DG_METHOD_THINXXS_V2C) if criteria == 'CS' or criteria == 'CC': query = query_plate_type_dg_method(plate_type_code='mfgcc') elif criteria == 'CO': query = query_plate_type_dg_method(plate_type_code='mfgco') elif criteria == 'CSFV': query = query_plate_type_dg_method(plate_type_code='fvtitr') elif criteria == 'QP': query = query_plate_type_dg_method(plate_type_code='scc') else: query = Session.query(ManufacturingPlateBatch) query = query.order_by('creation_date desc, mfg_plate_batch.name') c.paginator = paginate.Page( query, page=int(request.params.get('page', 1)), items_per_page = 15 ) c.pager_kwargs = {'plate_type': self.form_result['plate_type']} c.plate_type_field = dg_plate_type_field() response = render('/product/batch/list.html') # TODO: need to do from_python? return h.render_bootstrap_form(response, defaults=self.form_result)
def runs(self, id=None): c.dg = Session.query(DropletGenerator).get(int(id)) if not c.dg: abort(404) reprocess_config_id = request.params.get('rp_id', None) if reprocess_config_id: reprocess_config_id = int(reprocess_config_id) runs = Session.query(DropletGeneratorRun).filter( and_(DropletGeneratorRun.droplet_generator_id == c.dg.id, DropletGeneratorRun.run_number != None)).all() run_dict = dict([(run.run_number, run) for run in runs]) wells = Session.query(WellMetric, QLBWell.id, QLBWell.sample_name, QLBWell.dg_run_number, QLBWell.consumable_channel_num)\ .join(QLBWell)\ .join(PlateMetric)\ .filter(and_(QLBWell.droplet_generator_id == id, QLBWell.dg_run_number != None, PlateMetric.reprocess_config_id == reprocess_config_id))\ .order_by(QLBWell.dg_run_number, QLBWell.consumable_channel_num).all() sorted_runs = sorted(groupinto(wells, lambda tup: (tup[3])), key=operator.itemgetter(0)) c.runs = [(run_id, run_dict[run_id], sorted(info, key=operator.itemgetter(4))) for run_id, info in sorted_runs if run_dict.get(run_id, None)] #raise Exception, c.runs return render('/product/dg/runs.html')
def detectors(self, admin=True): detectors = self.__detector_modules() c.admin = admin c.readers = detectors c.active_type = 'detectors' c.reader_title = 'Detector Module' return render('/admin/prod_table.html')
def _multipick_base(self): assay_field = fl.sequence_group_field() enzyme_field = fl.enzyme_select_field() c.assays = assay_field c.enzymes = enzyme_field c.scoring_function = self.__multi_scoring_function_field() return render('/cutter/multipick.html')
def reader_history(self, id=None, admin=True): box2 = self.__setup_box2_context_by_code(id) c.admin = admin != 'False' logs = Session.query(Box2Log).filter_by(box2_id=box2.id)\ .order_by('time_effective desc')\ .options(joinedload_all(Box2Log.circuit))\ .all() statuses = Session.query(DRStatusLog).filter_by(box2_id=box2.id)\ .order_by('time_effective desc')\ .options(joinedload_all(DRStatusLog.reporter))\ .all() fixes = Session.query(DRFixLog).filter_by(box2_id=box2.id)\ .order_by('time_effective desc')\ .all() log_pairs = [(logs[i].time_effective, [logs[i],(logs[i+1] if i < len(logs)-1 else None)]) for i in range(len(logs))] for pair in log_pairs: pair[1].append((sorted(box2log_mv.labeleditems(pair[1][0]).items()), sorted(box2log_mv.labeleditems(pair[1][1]).items()))) status_pairs = [(status.time_effective, status) for status in statuses] fix_pairs = [(fix.time_effective, fix) for fix in fixes] changes = log_pairs + status_pairs + fix_pairs c.changes = sorted(changes, key=operator.itemgetter(0)) c.changes.reverse() return render('/admin/reader_history.html')
def gmap(self): addresses = self.form_result['addresses'] address_row_map = defaultdict(list) for a in addresses: address_row_map[a['address']].append(a['row']) if addresses: known_address_tuples = Session.query(MapCache.address, MapCache)\ .filter(MapCache.address.in_([a['address'] for a in addresses])).all() known_address_json = [] for a, k in known_address_tuples: if not k.verified: continue rows = address_row_map[a] for r in rows: known_address_json.append([r, a, k.lat, k.lon]) c.known_address_json = json.dumps(known_address_json) unknown_address_json = [] known_addresses = [a for a, k in known_address_tuples] for a in addresses: if a['address'] not in known_addresses: unknown_address_json.append((a['row'], a['address'])) c.unknown_address_json = json.dumps(sorted(unknown_address_json)) # todo make config c.api_key = 'AIzaSyCJmLePQj0ZLMbxVvJorxcL65AKUp8OH9w' c.origin = config['qtools.map.origin'] return render('/map/gmap.html')
def __show_list(self, query): if c.beta: query = query.order_by(PlateSetup.id) beta_project = get_beta_project() validation_project = get_validation_project() query = query.filter(and_(PlateSetup.project_id.in_((beta_project.id, validation_project.id)), PlateSetup.completed == False, PlateSetup.donotrun != True)) else: query = query.order_by('time_updated desc') beta_project = get_beta_project() validation_project = get_validation_project() query = query.filter(not_(PlateSetup.project_id.in_((beta_project.id, validation_project.id)))) c.paginator = paginate.Page( query, page=int(request.params.get('page', 1)), items_per_page = 20 ) # decorate items for setup in c.paginator: myItems = json.loads(setup.setup or '{}') if ( type( myItems ) is not list ): setup.stage = self.__check_progress(myItems) else: setup.stage = self.__check_progress({}) #setup.stage = self.__check_progress(json.loads(setup.setup or '{}')) c.pager_kwargs = {} if hasattr(c, 'project_id'): c.pager_kwargs['project_id'] = c.project_id if hasattr(c, 'author_id'): c.pager_kwargs['author_id'] = c.author_id return render('/setup/list.html')
def process_primer(self): source = UCSCSequenceSource() left_padding = 1000 right_padding = 1000 sequences = source.sequences_for_primers( self.form_result["primer_fwd"], self.form_result["primer_rev"], left_padding, right_padding ) # TODO: better selective update method c.primer_fwd = self.form_result["primer_fwd"] c.primer_rev = self.form_result["primer_rev"] c.left_padding = left_padding c.right_padding = right_padding c.sequences = sequences for seq in c.sequences: seq.snps = self._get_snps(seq.chromosome, seq.start, seq.end) self.__add_sequence_primer_display_attrs( seq, primer_fwd=self.form_result["primer_fwd"], primer_rev=self.form_result["primer_rev"] ) assayutil.set_amplicon_snps(c.sequences) c.assay_form = h.LiteralForm( value={"primer_fwd": self.form_result["primer_fwd"], "primer_rev": self.form_result["primer_rev"]} ) return render("/assay/primer_output.html")
def process_location(self): source = UCSCSequenceSource() left_padding = 1000 right_padding = 1000 sequence = source.sequence_around_loc( self.form_result["chromosome"], self.form_result["location"], self.form_result["width"], left_padding, right_padding, ) # TODO: better selective update method c.chromosome = self.form_result["chromosome"] c.location = self.form_result["location"] c.width = self.form_result["width"] c.left_padding = left_padding c.right_padding = right_padding c.sequence = sequence c.sequences = [sequence] for seq in c.sequences: seq.snps = self._get_snps(seq.chromosome, seq.start, seq.end) seq.positive_display_sequence = seq.amplicon.positive_strand_sequence.lower() seq.negative_display_sequence = seq.amplicon.negative_strand_sequence.lower() assayutil.set_amplicon_snps(c.sequences) c.assay_form = h.LiteralForm() return render("/assay/location_output.html")
def enzyme_conc_new(self): enzyme_field = fl.enzyme_field() assay_field = fl.assay_field(blank=True, empty="", selected=request.params.get("assay_id", None)) author_field = fl.person_field() c.plate = None if request.params.get("plate_id", None): plate = Session.query(Plate).get(int(request.params.get("plate_id"))) if plate: c.plate = plate c.form = h.LiteralFormSelectPatch( value={ "enzyme_id": enzyme_field["value"], "assay_id": assay_field["value"], "author_id": author_field["value"], }, option={ "enzyme_id": enzyme_field["options"], "assay_id": assay_field["options"], "author_id": author_field["options"], }, ) return render("/assay/enzyme/new.html")
def modules(self, admin=True): modules = self.__fluidics_modules() c.admin = admin c.readers = modules c.active_type = 'modules' c.reader_title = 'Fluidics Module' return render('/admin/prod_table.html')
def _process_and_display_trends(self, query, objects_expected): from qtools.lib.nstats import moving_average_by_interval from numpy import histogram import numpy as np group_by_plate = self.form_result['group_by_plate'] if objects_expected: results = execute_built_query(query, group_by_plate, True, self.form_result['metric'][1]) else: results = execute_built_query(query, group_by_plate, False) epoch_results = [(float(stat), time.mktime(dt.timetuple()), id, name) for stat, dt, id, name in results if stat is not None] exclude_func = create_exclude_function(self.form_result) filtered_results = [tup for tup in epoch_results if exclude_func(tup[0])] c.yaxis_title = fl.comparable_metric_display(MetricPattern.from_python(self.form_result['metric'])) c.mean_value = 'N/A' c.std_value = 'N/A' c.metric_name = fl.comparable_metric_display(MetricPattern.from_python(self.form_result['metric'])) c.table_data =[] if group_by_plate: moving_average = 10 epoch_url_results = [(stat, stamp*1000, url(controller='plate', action='view', id=id), name) for stat, stamp, id, name in filtered_results] else: moving_average = 50 epoch_url_results = [(stat, stamp*1000, url(controller='well', action='view', id=id), name) for stat, stamp, id, name in filtered_results] if epoch_url_results: c.stats = {} stats, time_points, urls, names = zip(*epoch_url_results) c.stats = h.literal(json.dumps(zip(time_points, stats))) c.table_data = zip( names, stats, time_points ) #update if we can. c.mean_value = str( np.mean( stats ) ) c.std_value = str( np.std( stats ) ) INTERVAL = 24*60*60*1000 ma = moving_average_by_interval(stats, time_points, INTERVAL, 10) c.moving_avg = h.literal(json.dumps(ma)) c.urls = h.literal(json.dumps(urls)) c.names = h.literal(json.dumps(names)) # get histogram of points by day #raise Exception, len(ma) density, edges = histogram(time_points, bins=len(ma), range=(ma[0][0], ma[-1][0])) c.densities = h.literal(json.dumps(zip([m[0] for m in ma], [int(d) for d in density]))) c.max_density_axis = 3*max(density) else: c.stats = {} c.moving_avg = {} c.urls = {} c.names = {} c.densities = {} c.max_density_axis = 3 return render('/trend/results.html')
def prod(self, admin=True): box2s = self.__prod_readers() # todo start adding c.admin = admin c.readers = box2s c.active_type = 'readers' c.reader_title = 'Reader' return render('/admin/prod_table.html')
def robocopy_generate(self): self.__setup_robocopy_context() box2 = Session.query(Box2).get(self.form_result['box2_id']) c.src_dir = box2.src_dir c.params = ' ' # reserve later to do QLP-only response.content_type = 'text/cmd' h.set_download_response_header(request, response, 'Robocopy %s.cmd' % box2.name) return render('/box2/robocopy.mako')
def _algorithms_base(self): storage = QSAlgorithmSource(config) existing_folders = [tup[0] for tup in Session.query(ReprocessConfig.original_folder).all()] new_folders = [folder for folder in storage.algorithm_folder_iter() if folder not in existing_folders] c.folder_opts = {'value': '', 'options': [(fld, fld.split('/')[0]) for fld in sorted(new_folders)]} return render('/product/algorithms/register.html')
def carryover(self): c_field = self.__carryover_plate_field() c.form = h.LiteralFormSelectPatch( value = {'start': c_field['value'], 'end': c_field['value']}, option = {'start': c_field['options'], 'end': c_field['options']} ) return render('/product/carryover.html')
def _list_base(self): groove_test = Session.query(Project).filter_by(name="GrooveTest").first() query = Session.query(PlateSetup).filter_by(project_id=groove_test.id).order_by("time_updated desc, name") c.paginator = paginate.Page(query, page=int(request.params.get("page", 1)), items_per_page=20) c.pager_kwargs = {} c.plate_type_field = groove_plate_type_field() return render("/product/groove/list.html")
def batch_size(self, id=None): c.batch_test = self.__batch_test(id) c.batch = self.__batch(id) if not c.batch: abort(404) c.form = h.LiteralForm(value={"pixel_calibration": 0.645}) return render("/product/consumable/batch_size.html")
def _new_base(self): self.__setup_groove_fields() c.title = "Create Groove Plate" c.submit_action = url(controller="groove", action="create") c.call_to_action = "Create Plate" c.record_exists = False c.allow_delete = False return render("/product/groove/edit.html")
def edit(self, id): """ Edits an assay. """ assay_q = Session.query(Assay) assay = assay_q.filter_by(id=id).first() dye_field = fl.assay_dye_field(assay.dye) quencher_field = fl.assay_quencher_field(assay.quencher) secondary_structure = fl.tertiary_field(assay.secondary_structure) if assay is None: abort(404) else: c.assay = assay owner_field = fl.person_field(c.assay.owner_id) c.form = h.LiteralFormSelectPatch( value={ "dye": dye_field["value"], "quencher": quencher_field["value"], "owner_id": unicode(owner_field["value"]), "secondary_structure": secondary_structure["value"], }, option={ "chromosome": [("", "--")] + [(chr, chr) for chr in Chromosome.chrom_list], "owner_id": owner_field["options"], "dye": dye_field["options"], "quencher": quencher_field["options"], "secondary_structure": secondary_structure["options"], }, ) values = { "name": assay.name, "gene": assay.gene, "owner_id": unicode(assay.owner_id), "primer_fwd": assay.primer_fwd, "primer_rev": assay.primer_rev, "chromosome": assay.chromosome, "probe_pos": assay.probe_pos, "probe_seq": assay.probe_seq, "dye": assay.dye, "quencher": assay.quencher, "secondary_structure": secondary_structure["value"], "amplicon_width": assay.amplicon_width, "snp_rsid": assay.snp_rsid, "notes": assay.notes, "reference_source": assay.reference_source, "optimal_anneal_temp": assay.optimal_anneal_temp, } if assay.assay_type == Assay.TYPE_LOCATION: c.selectedTab = 1 elif assay.assay_type == Assay.TYPE_SNP: c.selectedTab = 2 else: c.selectedTab = 0 return htmlfill.render(render("/assay/edit.html"), values)
def _pick_base(self): assay_field = fl.sequence_group_field(blank=True, selected=request.params.get('assay', None)) enzyme_field = fl.enzyme_select_field() c.assays = assay_field c.enzymes = enzyme_field c.scoring_function = self.__scoring_function_field() # probably need a wowo on which return render('/cutter/pick.html')
def name(self, id=None): self.__load_context() setup, struct = self.__load_setup(id) if not setup: abort(404) c.new_setup_form = c.name_form = self.__plate_setup_name_form(setup) c.next_url = url(controller='setup', action='save_name', id=setup.id, beta=c.beta) return render('/setup/name.html')
def well_distinct(self): values = Session.query(self.form_result['column']).distinct() c.form = h.LiteralForm( option = {self.form_result['field_name']: sorted([(tup[0], str(tup[0])) for tup in values if tup[0] is not None])} ) c.field_name = self.form_result['field_name'] return render('/box2/select.html')
def well_tag(self): well_tag_field = fl.well_tag_field() c.form = h.LiteralFormSelectPatch( value = {'well_tag': well_tag_field['value'], 'group_by_plate': [u'0']}, option = {'well_tag': [('--','--')]+well_tag_field['options'], 'group_by_plate': [(u'1', '')]} ) return render('/box2/well_tag.html')