Exemplo n.º 1
0
 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()
Exemplo n.º 2
0
def plate_from_qlp(qlbplate):
    """
    Given a QLBPlate, find out what information we can automatically determine
    from the file name and location.
    """
    dirname = qlbplate.file.dirname
    basename = qlbplate.file.basename
    complete_name = basename[:-4] # -- .qlp
    
    # assign box 2
    boxes = Session.query(Box2).all()
    
    # TODO: rename as to not contain timestamp?
    # TODO-- this is probably bad (assumes parent directory like Box 2 Alpha 03)
    plate_name = qlbplate.file.dirname.split('/')[-1]
    plate = Plate(name=plate_name, program_version=qlbplate.host_software,
                  run_time=datetime.strptime(qlbplate.host_datetime, '%Y:%m:%d %H:%M:%S') if qlbplate.host_datetime else None)
    for b in boxes:
        if qlbplate.file.dirname.startswith(b.src_dir):
            plate.box2 = b
    
    return plate
Exemplo n.º 3
0
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()