def UpdateSourceMaterials(instance, event): """Update remaining material for anything that was used in the solution """ mu = instance.materials_used if mu: for x in mu: # {'material title (key)':'mass/volume'(value),} brains = find(object_provides=IMaterial.__identifier__, Title=x) if brains: material = brains[0].getObject() temp = Decimal(material.remaining_amount) - Decimal(mu[x]) material.remaining_amount = float(temp) else: logger.warn( "%s: Update source materials: material not found: %s" % (instance, x)) su = instance.solutions_used if su: for x in su: # {'solution title (key)':'mass/volume'(value),} brains = find(object_provides=ISolution.__identifier__, Title=x) if brains: solution = brains[0].getObject() temp = Decimal(solution.remaining_amount) - Decimal(su[x]) solution.remaining_amount = float(temp) else: logger.warn( "%s: Update source materials: solution not found: %s" % (instance, x))
def get_aliquot_from_fn(self, fn): sample_id = fn.split('_')[0] brains = find(object_provides=ISample.__identifier__, id=sample_id) if not brains: msg = "%s: Can't find sample '%s'" % (fn, sample_id) raise RuntimeError(msg) sample = brains[0].getObject() # run through the plates, till we find one containing an aliquot # which is a child of this sample: aliquot = None for plate in self.run.plates: for key, value in plate.items(): try: obj = find(UID=value)[0].getObject() except IndexError: continue if obj.aq_parent.aq_parent == sample: aliquot = obj break if aliquot: break else: msg = "Aliquot not found for file: %s" % fn raise RuntimeError(msg) return aliquot
def get_assay_solutions(self): """Dynamically return a list of possible batches, for each type of solution required by the assay """ vocabs = [] assay = self.get_assay() if not assay: return vocabs if assay.needed_solutions: for solution_type_name in assay.needed_solutions: type_batches = find(Type=solution_type_name, expires={ 'query': datetime.today().date(), 'range': 'min' }, sort_on='expires') tmp = [] for batch in type_batches: tmp.append([ batch.id, batch.Title, batch.expires.strftime('%Y-%m-%d') ]) vocabs.append([solution_type_name, tmp]) return vocabs
def get_assay(self): assay_name = self.assay_name if assay_name: brains = find(portal_type='iChipAssay', Title=assay_name) if not brains: raise InvalidAssaySelected(self.assay_name) return brains[0].getObject()
def queryClinicalSamples(self, assay): """Get all the samples that are review_state='received', and which contain an "AssayRequest" who's title matches the assay_name, and who have a review_state of (re_run or to_be_tested). """ sample_data = [] for testable_state in ['re_run', 'to_be_tested']: # this does get Clinical Samples keep reading jp brains = find(portal_type="AssayRequest", Title=assay.title, review_state=testable_state) tmp = [] for brain in brains: assay_request = brain.getObject() sample = assay_request.aq_parent tmp.append({ 'uid': sample.UID(), 'draw_date': sample.collection_date, 'test_status': get_state(assay_request), 'sample': sample }) tmp = sorted(tmp, key=itemgetter('draw_date')) sample_data.extend(tmp) max_nr_samples = self.maxNumberOfSamplesToRun(assay) return sample_data[:max_nr_samples]
def getiChipsForTesting(self, assay): """Get ALL iChips that can be used for the selected assay [[<iChipLotID>,[<iChip>,<iChip>,<iChip>]]] """ ichips_for_assay = [] brains = find(portal_type='iChipLot', review_state='released', sort_on='expires') if not brains: raise NoIchipLotsFound ichiplots = [] for brain in brains: ichiplot = brain.getObject() if assay.title in ichiplot.intended_assay \ and int(ichiplot.frames) == int(assay.framecount): # commercial needs, correct assay # want to order the ichiplots in this list by exp date ichiplots.append(ichiplot) for ichiplot in ichiplots: ichips = ichiplot.objectValues() filtered = [ic for ic in ichips if get_state(ic) == 'released'] ichips_for_assay.append([ichiplot, filtered]) return ichips_for_assay
def __call__(self, context): """Pull all Veracis IDs for R&D and QC samples and get the next one. """ brains = find(portal_type=context.REQUEST.URL.split('++')[-1]) if not brains: return 1 return max([b.getObject().bottle_number for b in brains]) + 1
def __call__(self, context): brains = find(object_provides=IQCSample.__identifier__, review_state='in_use') items = [] for b in brains: items.append(SimpleVocabulary.createTerm(b.veracis_id)) return SimpleVocabulary(items)
def __call__(self, context): brains = find(IProvider.__identifer__) values = [b.getObject() for b in brains] names = [" ".join([str(v.site_ID), v.first_name, v.last_name]) for v in values] items = [(n, normalize(n)) for n in names] return SimpleVocabulary.fromItems(items)
def __call__(self, context): brains = find( object_provides='immunarray.lims.interfaces.material.IMaterial', remaining_amount={'query': 1, 'range': 'min'}, sort_on='sortable_title', **self.kwargs) return SimpleVocabulary.fromValues([brain.Title for brain in brains])
def process_raw_flipped(self, path): """Store flipped images in ichips """ flpath = join(path, 'Raw', 'Flipped') log = [] for fn in os.listdir(flpath): if 'jpg' not in fn: continue splits = fn.lower().split('_') ichip_id = splits[1].replace('.', '-') + "_%03d" % int(splits[2]) brains = find(object_provides=IiChip.__identifier__, id=ichip_id) if not brains: msg = "%s/%s: Can't find ichip '%s'" % (flpath, fn, ichip_id) raise RuntimeError(msg) ichip = brains[0].getObject() try: img = create(container=ichip, type='Image', id=fn, title=fn) except BadRequest as e: msg = "Run import has already been performed! (%s)" % e.message raise BadRequest(msg) except Unauthorized: msg = "Failed to create %s in ichip %s" % (fn, ichip.title) raise Unauthorized(msg) ts = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M") log.append(u"%s: Added image to ichip %s: %s" % (ts, ichip.id, img)) return log
def get_sequence_start(veracis_id): """Discover the next available aliquot number for the sample with the provided veracis_id. """ brains = find(object_provides=[IQCAliquot.__identifier__, IRandDAliquot.__identifier__], veracis_id=veracis_id) return len(brains) + 1
def __call__(self, context): values = find(object_provides=IQCSample.__identifier__) qcsample_ids = [v.UID for v in values] items = [] for uid in qcsample_ids: a = get(UID=uid) items.append(SimpleVocabulary.createTerm(a.veracis_id)) return SimpleVocabulary(items)
def get_aliquots(self, *interfaces): items = set() for plate in self.run.plates: for key, val in plate.items(): brains = find(object_provides=interfaces, UID=val) if brains: items.add(brains[0].getObject()) return items
def _get_navigation_root(context): """Find the correct navigation root.""" documents = content.find(portal_type='Document', id='front-page') if len(documents) == 0: return portal.get() front_page = documents[0].getObject() return portal.get_navigation_root(front_page)
def save_run(self): """Create initial run """ values = get_serializeArray_form_values(self.request) try: assay = find(object_provides=IiChipAssay.__identifier__, Title=values['assay_name'])[0].getObject() except IndexError: raise InvalidAssaySelected(values['assay_name']) plates, ichips, aliquots = self.transmogrify_inputs(values['plates']) plates = self.remove_empty_plates(plates) plates = self.reorder_plates(plates) solutions = [values[x] for x in values if x.startswith('solution-')] self.transition_plate_contents(ichips, aliquots, 'queue') lab_users = LabUsersUserVocabulary(self).by_value planner = lab_users.get(values['run_planner'], '') operator = lab_users.get(values['run_planner'], '') brain = find(object_provides=ITestRuns.__identifier__)[0] folder = brain.getObject() try: run_number = int(values['run_number']) except (ValueError, TypeError): raise TypeError("Run number must be a number.") run = create( folder, 'TestRun', title=values['assay_name'], assay_name=assay.title, assay_uid=assay.UID(), run_number=run_number, run_date=values['run_date'], run_planner=planner.title if planner else '', run_operator=operator.title if operator else '', plates=plates, solutions=solutions ) return run
def framecount(self): """Return the framecount from the assigned ichip-assay """ try: ia = find(UID=self.assay_uid)[0].getObject() except IndexError: msg = "Shouldn't happen, Can't resolve ichip assay for testrun." raise RuntimeError(msg) return ia.framecount if ia.framecount else 5
def patient_from_aliquot(self, aliquot): brains = find(object_provides=IPatient.__identifier__) sample = self.get_sample_from_aliquot(aliquot) for brain in brains: patient = brain.getObject() if sample.usn in patient.tested_unique_sample_ids: return patient aid = aliquot.id raise RuntimeError("Cannot find patient linked with aliquot %s" % aid)
def getQCSampleObject(self, veracis_id): """input veracis_id, get qc sample object """ brains = find(portal_type='QCSample', review_state='in_use', veracis_id=veracis_id) if not brains: raise QCSampleNotFound("Veracis ID: %s" % veracis_id) return brains[0].getObject()
def save_run(self): """Create initial run """ values = get_serializeArray_form_values(self.request) try: assay = find(object_provides=IiChipAssay.__identifier__, Title=values['assay_name'])[0].getObject() except IndexError: raise InvalidAssaySelected(values['assay_name']) plates, ichips, aliquots = self.transmogrify_inputs(values['plates']) plates = self.remove_empty_plates(plates) plates = self.reorder_plates(plates) solutions = [values[x] for x in values if x.startswith('solution-')] self.transition_plate_contents(ichips, aliquots, 'queue') lab_users = LabUsersUserVocabulary(self).by_value planner = lab_users.get(values['run_planner'], '') operator = lab_users.get(values['run_planner'], '') brain = find(object_provides=ITestRuns.__identifier__)[0] folder = brain.getObject() try: run_number = int(values['run_number']) except (ValueError, TypeError): raise TypeError("Run number must be a number.") run = create(folder, 'TestRun', title=values['assay_name'], assay_name=assay.title, assay_uid=assay.UID(), run_number=run_number, run_date=values['run_date'], run_planner=planner.title if planner else '', run_operator=operator.title if operator else '', plates=plates, solutions=solutions) return run
def __call__(self, context): """Pull all Veracis IDs for R&D and QC samples and get the next one. """ brains = find(portal_type=['QCSample', 'RandDSample'], sort_on='veracis_id', sort_order='reverse', limit=1) if brains: _id = str(int(brains[0].veracis_id) + 1) return unicode(_id) logger.info("assignVeracisId: No QC or RandD samples: using ID '1000'") return u"1000"
def provider_from_aliquot(self, aliquot): sample = self.get_sample_from_aliquot(aliquot) provider_name = sample.sample_ordering_healthcare_provider brains = find(object_provides=IProvider.__identifier__, Title=provider_name) if len(brains) > 1: raise RuntimeError("Found more than one provider with title='%s'" % provider_name) try: provider = brains[0].getObject() except IndexError: raise RuntimeError("Provider not found matching title='%s'" % provider_name) return provider
def update_kit_count(self, site_id): """Update site kits on hand count to be reduced by 1 """ site_objects = find(portal_type='Site') for i in site_objects: if i.Title == site_id: uid = i.UID site = api.content.get(UID=uid) site.kits_on_site -= 1 # Account for free kits, so that number counts down if site.free_kits_left > 0: site.free_kits_left -= 1
def __call__(self, context): wells = ["-A", "-B", "-C", "-D", "-E", "-F", "-H"] values = find(portal_type='iChip') ichips = [v.Title for v in values] unique_ichip_wells = [] for o in ichips: for w in wells: well_location = o + w unique_ichip_wells.append(well_location) items = [(i, normalize(i)) for i in unique_ichip_wells] return SimpleVocabulary.fromItems(items)
def __call__(self, context): """Pull all box numbers and get the next one. """ brains = find(portal_type=['CommercialBox', 'RandDBox', 'QCBox'], sort_on='box_number', sort_order='reverse', limit=1) if brains: _id = str(int(brains[0].box_number) + 1) return unicode(_id) logger.info("assignBoxNumber: No Boxes Exist: using ID '1'") return u"1"
def collectAliquots(self, sample_object, **kwargs): """Get in array of objects to see if they are the last in the chain and return a list of objects back. Check if each is a working aliquot that meets the needs of the assay Type is the value of the index called 'Type'. It's set (for aliquots) in the adapters/indexers.py. """ path = '/'.join(sample_object.getPhysicalPath()) brains = find(path={'query': path, 'depth': -1}, sort_on='id', **kwargs) items = [b.getObject() for b in brains] return items
def transmogrify_inputs(self, plates): """Convert titles to UIDs for all ichips and aliquots """ ichips, aliquots = [], [] # A single plate run must be converted to a list of plates if isinstance(plates, dict): plates = [plates] for plate in plates: for chip_nr in range(1, 5): for well_nr in range(1, 9): key = "chip-{}_well-{}".format(chip_nr, well_nr) if plate.get(key, False): brains = find(object_provides=IAliquot.__identifier__, Title=plate[key]) plate[key] = brains[0].UID aliquots.append(brains[0].getObject()) key = "chip-id-{}".format(chip_nr) if plate.get(key, False): brains = find(object_provides=IiChip.__identifier__, Title=plate[key]) plate[key] = brains[0].UID ichips.append(brains[0].getObject()) return plates, ichips, aliquots
def collectAliquots(self, sample_object, **kwargs): """Get in array of objects to see if they are the last in the chain and return a list of objects back. Check if each is a working aliquot that meets the needs of the assay Type is the value of the index called 'Type'. It's set (for aliquots) in the adapters/indexers.py. """ path = '/'.join(sample_object.getPhysicalPath()) brains = find(path={ 'query': path, 'depth': -1 }, sort_on='id', **kwargs) items = [b.getObject() for b in brains] return items
def get_run(self, path): run_nr = self.get_run_nr(path) # get the run nr so we can loop the plates brains = find(object_provides=IVeracisRunBase.__identifier__, run_number=run_nr) if not brains: msg = "No test run found with run_number=%s." % run_nr raise RuntimeError(msg) run = brains[0].getObject() # verify that run is in correct state for import. state = get_state(run) if state != 'scanning': if state == 'resulted': return None msg = "Test run %s is in state '%s'. Expected state: 'scanning'" \ % (run.title, state) raise RunInIncorrectState(msg) return run
def get_assay_solutions(self): """Dynamically return a list of possible batches, for each type of solution required by the assay """ vocabs = [] assay = self.get_assay() if not assay: return vocabs for solution_type_name in assay.needed_solutions: type_batches = find(Type=solution_type_name, expires={'query': datetime.today().date(), 'range': 'min'}, sort_on='expires') tmp = [] for batch in type_batches: tmp.append([batch.id, batch.Title, batch.expires.strftime('%Y-%m-%d')]) vocabs.append([solution_type_name, tmp]) return vocabs
def store_aliquot(self, uid, usn, aliquot_type, target_box_type): # get active box from workflow state, if one doesn't exist make it, # check for aliquot space in box, if none make a new box aliquot_type = aliquot_type # Bulk or Working target_box_type = target_box_type # CommercialBox, RandDBox, QCBox # find the active box of the type we need, brains = find(portal_type=target_box_type, review_state='active') if brains is not None: for brain in brains: cb = brain.getObject() if cb.box_type == aliquot_type: if cb.remaining_volume > 0: box_to_use = cb.UID entry_key = str(len(cb.aliquot.keys()) + 1) entry_value = [usn, uid] # Aliquot ID, UID # thing to add it to cb.aliquot_dic else: # change box workflow to full try: transition(cb, "filled") except: msg = "Could not transition %s, action='filled'" % \ cb.Title raise ObjectInInvalidState(msg) # see if rack has empty space, if not bail, and # alert user make a new aliquot_type, and return # this UID rack = cb.aq_parent new_box = api.content.create( container=rack, type=target_box_type, title="", box_type=aliquot_type, max_samples=81, remaining_volume=80, aliquot_dic={u'1', [usn, uid]}) else: print "No Active Box for Parameters sent"
def run_objects(instance): clinicalaliquots = [] qcaliquots = [] ichips = [] assayrequests = [] for plate in instance.plates: for key, value in plate.items(): brains = find(UID=value) if brains: obj = brains[0].getObject() _items = qcaliquots + clinicalaliquots + ichips + assayrequests if not obj or obj in _items: continue if IiChip.providedBy(obj): ichips.append(obj) elif IQCAliquot.providedBy(obj): qcaliquots.append(obj) elif IClinicalAliquot.providedBy(obj): clinicalaliquots.append(obj) # get assayrequest ar = get_assayrequest_from_aliquot(obj) assayrequests.append(ar) return assayrequests, clinicalaliquots, ichips, qcaliquots
def queryClinicalSamples(self, assay): """Get all the samples that are review_state='received', and which contain an "AssayRequest" who's title matches the assay_name, and who have a review_state of (re_run or to_be_tested). """ sample_data = [] for testable_state in ['re_run', 'to_be_tested']: # this does get Clinical Samples keep reading jp brains = find(portal_type="AssayRequest", Title=assay.title, review_state=testable_state) tmp = [] for brain in brains: assay_request = brain.getObject() sample = assay_request.aq_parent tmp.append({'uid': sample.UID(), 'draw_date': sample.collection_date, 'test_status': get_state(assay_request), 'sample': sample}) tmp = sorted(tmp, key=itemgetter('draw_date')) sample_data.extend(tmp) max_nr_samples = self.maxNumberOfSamplesToRun(assay) return sample_data[:max_nr_samples]
def process_results_xlsx(self, path): """Take values from path/Out/Results/SLEkey_Results.xlsx, and write them to the database """ run = self.get_run(path) # Get the first sheet filename = join(path, 'Out', 'Results', 'SLEkey_Results.xlsx') wb = openpyxl.load_workbook(filename) ws = wb.get_sheet_by_name('Sheet1') # header rows for blocks containg QC and Clinical aliquot/sample info qc_head_row = self.findnextSerial_Numberrow(ws, 1) clin_head_row = self.findnextSerial_Numberrow(ws, qc_head_row + 1) # get column letters of all qc headers that start with "ichip*" qc_ichip_cols = [] passfail_col = None for col in all_cols: coord = "%s%s" % (col, qc_head_row) val = "%s" % ws[coord].value if val: if val.lower().startswith("fina"): passfail_col = coord if val.lower().startswith("ichip"): qc_ichip_cols.append(col) ichip_passfail_combos = [] if passfail_col: for row in range(qc_head_row + 1, clin_head_row): passfail = "%s" % ws["%s%s" % (passfail_col, row)].value ichip_titles = [] for col in qc_ichip_cols: ichip_titles.append(ws["%s%s" % (col, row)].value) ichip_passfail_combos.append([ichip_titles, passfail]) # for each plate for plate in run.plates: plate_ichips = [] plate_ichiplot_titles = [] # get all unique ichip lot numbers in a list for key, uid in plate.items(): if key.startswith('ichip-id'): ichip = find(UID=uid)[0].getObject() plate_ichips.append(ichip) ichiplot_title = ichip.title.upper().split('-')[0] if ichiplot_title not in plate_ichiplot_titles: plate_ichiplot_titles.append(ichiplot_title) for combo in ichip_passfail_combos: if sorted(plate_ichiplot_titles) == sorted(combo[0]): for ichip in plate_ichips: transition(ichip, 'qc_' + combo[1].lower()) # 'consume' qc aliquots. for uid in plate.values(): brains = find(object_provides=IQCAliquot.__identifier__, UID=uid, review_state='in_process') if brains: transition(brains[0].getObject(), 'done') # find the column at which the following headers are located: cols = {'Sample_ID': '', 'SLE_key_Score': '', 'SLE_key_Classification': '', 'Assay_QC_Status': ''} if not all(cols): msg = "One of the column headers can't be located:" % pformat(cols) raise SpreadsheetParseError(msg) for col in all_cols: coord = "%s%s" % (col, clin_head_row) value = ws[coord].value if value in cols: cols[value] = col # get values from each row and colum into aliquot_results. results is: # {sample_id: [SLE_key_Score, # SLE_key_Classification, # Assay_QC_Status],} aliquot_results = {} first_empty = self.get_first_empty_row(ws, clin_head_row) for row in range(clin_head_row + 1, first_empty): sample_id = ws["%s%s" % (cols['Sample_ID'], row)].value score = ws["%s%s" % (cols['SLE_key_Score'], row)].value classif = ws["%s%s" % (cols['SLE_key_Classification'], row)].value status = ws["%s%s" % (cols['Assay_QC_Status'], row)].value aliquot_results[sample_id] = { 'SLE_key_Score': score, 'SLE_key_Classification': "%s" % classif, 'Assay_QC_Status': "%s" % status } log = [] _used_uids = [] for plate in run.plates: for uid in plate.values(): if uid in _used_uids: continue _used_uids.append(uid) brains = find(UID=uid) if not brains: continue aliquot = brains[0].getObject() if not IAliquot.providedBy(aliquot): continue sample = self.get_sample_from_aliquot(aliquot) if IClinicalSample.providedBy(sample): if sample.title not in aliquot_results: msg = "Sample '%s' not in spreadsheet results: %s" % \ (sample.title, pformat(aliquot_results)) raise RuntimeError(msg) result = aliquot_results[sample.title] ar = self.get_ar_from_sample(sample, run.assay_name) state = result['Assay_QC_Status'].lower() ar.aliquot_evaluated = aliquot.title ar.date_resulted = self.get_date(ws) # assayrequest is associated with multiple aliquots, # so we only transition if the AR's state is expected. if get_state(ar) == 'in_process': transition(ar, 'qc_' + state) aliquot.numeric_result = result['SLE_key_Score'] aliquot.text_result = result['SLE_key_Classification'] ts = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M") log.append("%s: Sample: %s, Aliquot: %s, Results: %s, %s" % ( ts, sample.title, aliquot.title, result['SLE_key_Score'], result['SLE_key_Classification'], )) return log
def is_lqc(self, sample): assay = find(UID=self.context.assay_uid)[0].getObject() lqc_id = assay.qc_low_choice return sample.id.split('-')[0] == lqc_id
def __call__(self): wb = self.load_workbook() ws = wb.get_sheet_by_name('Form') # A6 - add run number to 'FILE NAME' ws['A6'].value += ' (Veracis Test Run %s)' % self.context.run_number # A7 - PURPOSE ws['A7'].value += ' %s' % self.context.assay_name # A8 - DATE ws['A8'].value += ' %s' % self.context.run_date # D8 - PLANNED BY ws['D8'].value += ' %s' % self.context.run_planner # H8 - PERFORMED BY ws['H8'].value += ' %s' % self.context.run_operator # PLATE HEADERS are at 10, 27, 44, 61, 78 for plate_nr, plate_cell in enumerate([10, 27, 44, 61, 78]): plate_nr += 1 # verify plate header exists in spreadsheet plate_title = 'plate %s' % plate_nr plate_header_cell = ws['A%s' % plate_cell] assert plate_header_cell.value.lower() == plate_title # verify the plate exists in run.plates if len(self.context.plates) < plate_nr: break plate = self.context.plates[plate_nr - 1] # ALIQUOT WELL ROWS are PLATE HEADER+[2..9] in COLS B,D,F,H for chip_nr, chip_col in enumerate('BDFH'): for well_nr in range(8): uid = plate['chip-%s_well-%s' % (chip_nr + 1, well_nr + 1)] if uid: brain = find(UID=uid)[0] row = plate_cell + (well_nr + 2) cell = ws['%s%s' % (chip_col, row)] cell.value = brain.Title # +1 for ICHIP in rows C,E,G,I - and "COMMENTS" in J row = plate_cell + 10 for chip_nr, chip_col in enumerate('CEGI'): uid = plate['chip-id-%s' % (chip_nr + 1)] if not uid: raise MissingIChipForSlide("plate %s, slide %s" % (plate_nr, chip_nr + 1)) brain = find(UID=uid)[0] cell = ws['%s%s' % (chip_col, row)] cell.value = brain.Title # comments in J cell = ws['J%s' % row] cell.value = plate['comments-ichip-%s' % (chip_nr + 1)] # +1 for ICHIP in rows C,E,G,I - and "COMMENTS" in J row = plate_cell + 10 for chip_nr, chip_col in enumerate('CEGI'): uid = plate['chip-id-%s' % (chip_nr + 1)] if not uid: raise MissingIChipForSlide("plate %s, slide %s" % (plate_nr, chip_nr + 1)) brain = find(UID=uid)[0] cell = ws['%s%s' % (chip_col, row)] cell.value = brain.Title # comments in J cell = ws['J%s' % row] cell.value = plate['comments-ichip-%s' % (chip_nr + 1)] # +1 for SCAN SLOT C,E,G,I row = plate_cell + 11 for chip_nr, slot_col in enumerate('CEGI'): cell = ws['%s%s' % (slot_col, row)] cell.value = plate['scan-slot-%s' % (chip_nr + 1)] # +2 for COMMENTS in B,D,F,H row = plate_cell + 13 for chip_nr, comment_col in enumerate('CEGI'): cell = ws['%s%s' % (comment_col, row)] cell.value = plate['comments-ichip-%s' % (chip_nr + 1)] fn = "{}-{}".format(self.context.assay_name, self.context.run_number) fn = normalize(fn) + ".xlsx" setheader = self.request.RESPONSE.setHeader setheader('Content-Type', 'application/vnd.ms-excel') setheader("Content-Disposition", 'attachment;filename="%s"' % fn) fn = tempfile.mktemp() wb.save(fn) data = open(fn).read() self.request.RESPONSE.write(data)
def __call__(self): wb = self.load_workbook() ws = wb.get_sheet_by_name('Form') # A6 - add run number to 'FILE NAME' ws['A6'].value += ' (Veracis Test Run %s)' % self.context.run_number # A7 - PURPOSE ws['A7'].value += ' %s' % self.context.assay_name # A8 - DATE ws['A8'].value += ' %s' % self.context.run_date # D8 - PLANNED BY ws['D8'].value += ' %s' % self.context.run_planner # H8 - PERFORMED BY ws['H8'].value += ' %s' % self.context.run_operator # PLATE HEADERS are at 10, 27, 44, 61, 78 for plate_nr, plate_cell in enumerate([10, 27, 44, 61, 78]): plate_nr += 1 # verify plate header exists in spreadsheet plate_title = 'plate %s' % plate_nr plate_header_cell = ws['A%s' % plate_cell] assert plate_header_cell.value.lower() == plate_title # verify the plate exists in run.plates if len(self.context.plates) < plate_nr: break plate = self.context.plates[plate_nr - 1] # ALIQUOT WELL ROWS are PLATE HEADER+[2..9] in COLS B,D,F,H for chip_nr, chip_col in enumerate('BDFH'): for well_nr in range(8): uid = plate['chip-%s_well-%s' % (chip_nr + 1, well_nr + 1)] if uid: brain = find(UID=uid)[0] row = plate_cell + (well_nr + 2) cell = ws['%s%s' % (chip_col, row)] cell.value = brain.Title # +1 for ICHIP in rows C,E,G,I - and "COMMENTS" in J row = plate_cell + 10 for chip_nr, chip_col in enumerate('CEGI'): uid = plate['chip-id-%s' % (chip_nr + 1)] if not uid: raise MissingIChipForSlide( "plate %s, slide %s" % (plate_nr, chip_nr + 1)) brain = find(UID=uid)[0] cell = ws['%s%s' % (chip_col, row)] cell.value = brain.Title # comments in J cell = ws['J%s' % row] cell.value = plate['comments-ichip-%s' % (chip_nr + 1)] # +1 for ICHIP in rows C,E,G,I - and "COMMENTS" in J row = plate_cell + 10 for chip_nr, chip_col in enumerate('CEGI'): uid = plate['chip-id-%s' % (chip_nr + 1)] if not uid: raise MissingIChipForSlide( "plate %s, slide %s" % (plate_nr, chip_nr + 1)) brain = find(UID=uid)[0] cell = ws['%s%s' % (chip_col, row)] cell.value = brain.Title # comments in J cell = ws['J%s' % row] cell.value = plate['comments-ichip-%s' % (chip_nr + 1)] # +1 for SCAN SLOT C,E,G,I row = plate_cell + 11 for chip_nr, slot_col in enumerate('CEGI'): cell = ws['%s%s' % (slot_col, row)] cell.value = plate['scan-slot-%s' % (chip_nr + 1)] # +2 for COMMENTS in B,D,F,H row = plate_cell + 13 for chip_nr, comment_col in enumerate('CEGI'): cell = ws['%s%s' % (comment_col, row)] cell.value = plate['comments-ichip-%s' % (chip_nr + 1)] fn = "{}-{}".format(self.context.assay_name, self.context.run_number) fn = normalize(fn) + ".xlsx" setheader = self.request.RESPONSE.setHeader setheader('Content-Type', 'application/vnd.ms-excel') setheader("Content-Disposition", 'attachment;filename="%s"' % fn) fn = tempfile.mktemp() wb.save(fn) data = open(fn).read() self.request.RESPONSE.write(data)