def command(self): self.load_wsgi_app() qlbplates = Session.query(QLBPlate).\ filter(and_(QLBPlate.file_id != None, QLBPlate.plate_id != None)).\ order_by(desc(QLBPlate.id)).\ options(joinedload_all(QLBPlate.plate, innerjoin=True)) for qlbplate in qlbplates: qlbplate.plate.score = Plate.compute_score(qlbplate.plate) print "%s: %s points" % (qlbplate.plate.id, qlbplate.plate.score) Session.commit()
def __scan_plate(file_source, image_source, path_id, path, mtime_dict, plate_type=None, file_lists=None): """ The method responsible for taking a QLP file on disk and creating thumbnails and adding/updating records in the database based off the contents of that file. This is a nasty abstraction, I apologize. TODO: make this more natural along add/update line, do not require use of mtime_dict or file_list (or return file_list as files touched) Returns the Plate object of the added/updated plate, or None if there was no touch/error. :param file_source: The source of the QLP files (QLStorageSource) :param image_source: The source/sink of thumbnails (QLStorageSource) :param path_id: The unique identifier of the plate file. Computed by run_id() :param path: The actual file path of the QLP. :param mtime_dict: A mapping between plates and their last updated times. This will indicate whether or not a plate is 'dirty' with respect to the DB. :param plate_type: A plate type. Supplying this will indicate that the special metrics corresponding to that plate type should be computed during the scan. :param file_lists: A logging object used in the scan to record files that are missing, poorly processed, etc. Side-effected by this method. """ if not file_lists: file_lists = defaultdict(list) # if the file is not being tracked, attempt to add it if not mtime_dict.has_key(path_id): print "Adding plate: %s" % path qlbfile, qlplate, valid_file = add_qlp_file_record(file_source, path) if not valid_file: print "Invalid file: %s" % path file_lists['invalid_plates'].append(path) return None elif path.endswith('HFE_Plate.qlp'): qlbfile.read_status = -7 print "Ignoring HFE Plate: %s" % path Session.commit() return None elif qlbfile.version is 'Unknown': qlbfile.read_status = -8 print "Ignoring plate run with unknown QS version: %s" % path Session.commit() return None if(qlbfile.version_tuple < (0,1,1,9)): # we don't recognize the QLP file version, ditch qlbfile.read_status = -2 Session.commit() return None qlbplate, valid_plate = add_qlp_plate_record(qlplate, qlbfile) if not valid_plate: # invalid plate print "Could not read plate: %s" % path qlbfile.read_status = -20 Session.commit() file_lists['unreadable_plates'].append(path) return None for well_name, proc_qlwell in sorted(qlplate.analyzed_wells.items()): # remove empty/blank wells generated by eng group if (well_name is None or well_name == ''): del qlplate.analyzed_wells[well_name] continue raw_qlwell = None # TODO: abstract? well_loc = "%s_%s_RAW.qlb" % (path[:-4], well_name) # process QLP only if not os.path.isfile(well_loc): print "Could not find well file: %s" % well_loc file_lists['missing_wells'].append(well_loc) well_file = None # proceed, as file may just not have been delivered valid_file = True else: well_file, raw_qlwell, valid_file = add_qlb_file_record(file_source, well_loc) if not valid_file: print "Invalid well file: %s" % well_loc file_lists['invalid_wells'].append(well_loc) continue qlbwell, valid_well = add_qlb_well_record(well_file, well_name, proc_qlwell, raw_qlwell) if valid_well: qlbplate.wells.append(qlbwell) # bug 829: if there are invalid wells, do not process the plate; # wait for the well files to complete processing, get on next run # # if file_lists['invalid_wells']: print "Skipping plate processing (invalid well): %s" % path Session.rollback() return None # continue plate plate_meta = plate_from_qlp(qlbplate) Session.add(plate_meta) qlbplate.plate = plate_meta validation_test = get_product_validation_plate(qlplate, plate_meta) if not validation_test: if not apply_setup_to_plate(qlplate, plate_meta): apply_template_to_plate(qlplate, plate_meta) # OK, try it now try: for well in qlbplate.wells: if well.file_id != -1: well.file.read_status = 1 qlbplate.file.read_status = 1 Session.commit() write_images_stats_for_plate(qlbplate, qlplate, image_source, override_plate_type=plate_type) Session.commit() qlbplate.plate.score = Plate.compute_score(qlbplate.plate) Session.commit() if validation_test: validation_test.plate_id = qlbplate.plate.id Session.add(validation_test) Session.commit() file_lists['added_plates'].append(path) return plate_meta except Exception, e: print e print "Could not process new plate: %s" % path file_lists['unwritable_plates'].append(path) Session.rollback() elif time_equals(mtime_dict[path_id][1], datetime.fromtimestamp(os.stat(path).st_mtime)): return None else: # strategy: reprocess the plate and update. qlbfile = Session.query(QLBFile).get(mtime_dict[path_id][0]) if not qlbfile: print "No file for path: %s" % path return None elif path.endswith('HFE_Plate.qlp'): qlbfile.mtime = datetime.fromtimestamp(os.stat(path).st_mtime) Session.commit() return None qlbplates = Session.query(QLBPlate).filter_by(file_id=qlbfile.id).\ options(joinedload_all(QLBPlate.wells, QLBWell.channels)).all() if not qlbplates: print "No plate for read file: %s" % path return None qlbplate = qlbplates[0] if not qlbplate.plate_id: print "No plate for read file (plate deleted): %s" % path qlbfile.mtime = datetime.fromtimestamp(os.stat(path).st_mtime) Session.commit() return None print "Updating plate %s/%s: %s" % (qlbplate.plate_id, qlbplate.id, path) qlplate = get_plate(path) updated = update_qlp_plate_record(qlbplate, qlplate) if not updated: print "Could not read updated file" Session.rollback() qlbplate.file.read_status = -30 Session.commit() file_lists['unreadable_plates'].append(path) return None # this is basically the same as on add -- abstract? # # TODO (GitHub Issue 30): handle case where a previously analyzed well is switched to 'Not Used' for well_name, proc_qlwell in sorted(qlplate.analyzed_wells.items()): raw_qlwell = None # TODO: abstract? well_loc = "%s_%s_RAW.qlb" % (path[:-4], well_name) qlbwells = [well for well in qlbplate.wells if well.well_name == well_name] if not qlbwells: # add qlb file record if not os.path.isfile(well_loc): print "Could not find well file: %s" % well_loc well_file = None valid_file = True file_lists['missing_wells'].append(well_loc) else: well_file, raw_qlwell, valid_file = add_qlb_file_record(file_source, well_loc) if not valid_file: print "Invalid well file: %s" % well_loc file_lists['invalid_wells'].append(well_loc) continue qlbwell, valid_well = add_qlb_well_record(well_file, well_name, proc_qlwell, raw_qlwell) if valid_well: qlbplate.wells.append(qlbwell) else: file_lists['invalid_wells'].append(well_loc) print "Could not add well %s: %s" % (well_name, well_loc) else: qlbwell = qlbwells[0] if not os.path.isfile(well_loc): print "Could not find well file to update: %s" % well_loc file_lists['missing_wells'].append(well_loc) update_qlb_well_record(qlbwell, well_name, proc_qlwell, None) else: if qlbwell.file_id == -1: well_file, raw_qlwell, valid_file = add_qlb_file_record(file_source, well_loc) if valid_file: qlbwell.file = well_file update_qlb_well_record(qlbwell, well_name, proc_qlwell, raw_qlwell) # in lieu of updating plate meta (though it maybe should be done) qlbplate.plate.program_version = qlbplate.host_software try: for well in qlbplate.wells: if well.file_id != -1 and well.file: well.file.read_status = 1 qlbplate.file.read_status = 1 qlbfile.mtime = datetime.fromtimestamp(os.stat(path).st_mtime) Session.commit() # this is where updating the dirty bits would come in handy write_images_stats_for_plate(qlbplate, qlplate, image_source, overwrite=True, override_plate_type=plate_type) Session.commit() qlbplate.plate.score = Plate.compute_score(qlbplate.plate) Session.commit() file_lists['updated_plates'].append(path) return qlbplate.plate except Exception, e: print e print "Could not update plate %s/%s: %s" % (qlbplate.plate_id, qlbplate.id, path) file_lists['unwritable_plates'].append(path) Session.rollback()