Example #1
0
 def __get_1d_background_rgbs(self, qlwell):
     rgbs = [None, None]
     if well_channel_automatic_classification(qlwell, 0):
         rgbs[0] = AUTO_THRESHOLD_FAM_BGCOLOR
     else:
         rgbs[0] = MANUAL_THRESHOLD_FAM_BGCOLOR
     if well_channel_automatic_classification(qlwell, 1):
         rgbs[1] = AUTO_THRESHOLD_VIC_BGCOLOR
     else:
         rgbs[1] = MANUAL_THRESHOLD_VIC_BGCOLOR
     
     return rgbs
Example #2
0
    def cluster2d(self, id=None, *args, **kwargs):
        from qtools.lib.mplot import plot_cluster_2d, cleanup, render as plt_render
        from qtools.lib.nstats.peaks import accepted_peaks
        
        response.content_type = 'image/png'
        qlwell = self.__qlwell_from_threshold_form(id)
        self.__set_threshold_context(qlwell)
        max_amplitudes = [self.form_result['max_fam_amplitude'], self.form_result['max_vic_amplitude']]
        boundaries = (-2000,-2000,max_amplitudes[1],max_amplitudes[0])

        # to emulate current behavior -- include gated events
        peaks = accepted_peaks(qlwell)
        threshold_fallback = qlwell.clustering_method == QLWell.CLUSTERING_TYPE_THRESHOLD
        fig = plot_cluster_2d(peaks,
                              thresholds=(c.fam_threshold, c.vic_threshold),
                              boundaries=boundaries,
                              use_manual_clusters=not well_channel_automatic_classification(qlwell),
                              highlight_thresholds=threshold_fallback)
        response.content_type = 'image/png'
        imgdata = plt_render(fig, dpi=72)
        cleanup(fig)
        return imgdata
Example #3
0
    def command(self):
        from qtools.lib.mplot import plot_cluster_2d, cleanup as plt_cleanup
        app = self.load_wsgi_app()

        image_root = app.config['qlb.image_store']
        image_source = QLBImageSource(image_root)

        # enforce config.ini
        if len(self.args) < 2:
            raise ValueError, self.__class_.usage

        analysis_group_id = int(self.args[0])
        if len(self.args) == 3:
            reprocess_config = Session.query(ReprocessConfig).filter_by(code=self.args[1]).one()
            reprocess_config_id = reprocess_config.id
        else:
            reprocess_config = None
            reprocess_config_id = None

        if reprocess_config:
            data_root = app.config['qlb.reprocess_root']
            storage = QLPReprocessedFileSource(data_root, reprocess_config)
        else:
            storage = QLStorageSource(app.config)

        analysis_group = Session.query(AnalysisGroup).get(analysis_group_id)
        if not analysis_group:
            raise ValueError, "No analysis group for id %s" % analysis_group_id

        plates = analysis_group.plates
        for plate in plates:
            # TODO: UGH THIS CODE INVARIANT SUCKS (should merge QLReprocessedFile/QLStorageSources)
            if reprocess_config:
                plate_path = storage.full_path(analysis_group, plate)
            else:
                plate_path = storage.plate_path(plate)
            print "Reading %s" % plate_path
            qlplate = get_plate(plate_path)
            if not qlplate:
                print "Could not read plate: %s" % plate.name
                continue
            print "Generating thumbnails for %s" % plate.name
            for name, qlwell in sorted(qlplate.analyzed_wells.items()):
                # TODO abstract into utility image generation function (thumbnail.py?)

                threshold_fallback = qlwell.clustering_method == QLWell.CLUSTERING_TYPE_THRESHOLD
                fig = plot_cluster_2d(qlwell.peaks,
                                      width=60,
                                      height=60,
                                      thresholds=[qlwell.channels[0].statistics.threshold,
                                                  qlwell.channels[1].statistics.threshold],
                                      boundaries=[0,0,12000,24000],
                                      show_axes=False,
                                      antialiased=True,
                                      unclassified_alpha=0.5,
                                      use_manual_clusters=not well_channel_automatic_classification(qlwell),
                                      highlight_thresholds=threshold_fallback)
                image_path = image_source.get_path('%s/%s_2d.png' % (plate.qlbplate.id, name))
                print image_path
                fig.savefig(image_path, format='png', dpi=72)
                plt_cleanup(fig)
Example #4
0
def _compute_well_channel_metrics(qlwell, well_channel_metric, channel_num):
    """
    Internal method for populating a WellChannelMetric object from statistics
    determined by analyzing the QLWell's channel object.

    This will populate the well_channel_metric object with information such
    as positives and negatives, concentration, polydispersity, and other
    metrics that have separate values for FAM and VIC channels.

    :param qlwell: The QLWell object created by reading a QLP file.
    :param well_channel_metric: The WellChannelMetric object to populate.
    :param channel_num: Which channel to analyze.
    """
    # for convenience
    wcm = well_channel_metric
    stats = qlwell.channels[channel_num].statistics
    wcm.min_quality_gating = stats.min_quality_gate
    wcm.min_quality_gating_conf = stats.min_quality_gate_conf
    wcm.min_width_gate = stats.min_width_gate
    wcm.min_width_gate_conf = stats.min_width_gate_conf
    wcm.max_width_gate = stats.max_width_gate
    wcm.max_width_gate_conf = stats.max_width_gate_conf
    wcm.width_gating_sigma = stats.width_gating_sigma
    # TODO: try to guarantee automatic threshold here?
    wcm.threshold = stats.threshold
    wcm.threshold_conf = stats.threshold_conf
    wcm.auto_threshold_expected = False
    wcm.concentration = stats.concentration
    wcm.conc_lower_bound = stats.concentration_lower_bound
    wcm.conc_upper_bound = stats.concentration_upper_bound
    wcm.conc_calc_mode = stats.concentration_calc_mode
    wcm.clusters_automatic = well_channel_automatic_classification(qlwell, channel_num)

    wcm.decision_tree_flags = qlwell.channels[channel_num].decision_tree_flags

    ap = accepted_peaks(qlwell)
    
    if channel_num == 0:
        ampfunc = fam_amplitudes
    elif channel_num == 1:
        ampfunc = vic_amplitudes
    else:
        raise ValueError, "Incompatible channel number: %s" % channel_num

    wcm.amplitude_mean = np.mean(ampfunc(ap))
    wcm.amplitude_stdev = np.std(ampfunc(ap))

    allpeaks = qlwell.peaks
    wcm.total_events_amplitude_mean  = np.mean(ampfunc(allpeaks))
    wcm.total_events_amplitude_stdev = np.std(ampfunc(allpeaks))

    above_min_peaks = above_min_amplitude_peaks(qlwell)
    quality_gated_peaks = quality_rejected(above_min_peaks, wcm.min_quality_gating, channel_num, include_vertical_streak_flagged=False)
    wcm.quality_gated_peaks = len(quality_gated_peaks)
    width_gated_peaks = width_rejected(above_min_peaks, wcm.min_width_gate, wcm.max_width_gate, channel_num)
    wcm.width_gated_peaks = len(width_gated_peaks)
    # TODO add min amplitude, vertical streak

    wcm.s_value = separation_value(ap, channel_num, wcm.threshold)
    p_plus, p, p_minus = rain_pvalues(ap, channel_num, wcm.threshold)
   
    wcm.rain_p_plus = p_plus
    wcm.rain_p = p
    wcm.rain_p_minus = p_minus

    ## extra cluster events...
    NEW_DROPLET_CLUSTER_METRICS_CALCULATOR.compute(qlwell, qlwell.channels[channel_num], wcm)

#    DEFAULT_TEAVALS.compute(qlwell, qlwell.channels[channel_num], wcm)
    DEFAULT_POLYD_CALC.compute(qlwell, qlwell.channels[channel_num], wcm)
    DEFAULT_EXTRAC_CALC.compute(qlwell, qlwell.channels[channel_num], wcm)
    DEFAULT_NTC_POSITIVE_CALCULATOR.compute(qlwell, qlwell.channels[channel_num], wcm)

    wcm.baseline_mean = qlwell.channels[channel_num].statistics.baseline_mean
    wcm.baseline_stdev = qlwell.channels[channel_num].statistics.baseline_stdev
    wcm.cluster_conf = qlwell.channels[channel_num].statistics.cluster_conf

    positive_peaks, negative_peaks, unclassified_peaks = well_observed_positives_negatives(qlwell, channel_num)
    if len(positive_peaks) > 0 or len(negative_peaks) > 0:
        wcm.positive_peaks = len(positive_peaks)
        wcm.negative_peaks = len(negative_peaks)
        wcm.positive_mean = np.mean(ampfunc(positive_peaks))
        wcm.positive_stdev = np.std(ampfunc(positive_peaks))
        wcm.negative_mean = np.mean(ampfunc(negative_peaks))
        wcm.negative_stdev = np.std(ampfunc(negative_peaks))

        wcm.positive_skew = skew(positive_peaks, channel_num)
        wcm.positive_kurtosis = kurtosis(positive_peaks, channel_num)
        wcm.nonpositive_skew = skew(negative_peaks, channel_num)
        wcm.nonpositive_kurtosis = kurtosis(negative_peaks, channel_num)

        # CLUSTER-TODO: this is not going to be right for clusters.  Consider
        # changing this.
        wcm.concentration_rise_ratio = quartile_concentration_ratio(qlwell, peaks=ap,
                                                                    channel_num=channel_num, threshold=wcm.threshold,
                                                                    min_events=4000)

        del positive_peaks
        del negative_peaks
        del unclassified_peaks
    else:
        wcm.nonpositive_skew = skew(ap, channel_num)
        wcm.nonpositive_kurtosis = kurtosis(ap, channel_num)
    
    del ap
    # daisy chain just in case
    return wcm
Example #5
0
def write_images_stats_for_plate(dbplate, qlplate, image_source, overwrite=False, override_plate_type=None):
    """
    Write plate metrics to the database and thumbnails to local storage,
    as dictated by image_source.

    Metrics will be related to the supplied dbplate (Plate model)
    qlplate is a QLPlate object derived from reading the QLP file.
    """
    if image_source.subdir_exists(str(dbplate.id)):
        if not overwrite:
            return
    else:
        image_source.make_subdir(str(dbplate.id))
    
    max_amplitudes = (24000, 12000)
    show_only_gated = False # keep default behavior
    if qlplate:
        for well_name, qlwell in sorted(qlplate.analyzed_wells.items()):
            # TODO: common lib?
            if well_channel_automatic_classification(qlwell, 0):
                fig = plot_fam_peaks(qlwell.peaks,
                                     threshold=qlwell.channels[0].statistics.threshold,
                                     max_amplitude=max_amplitudes[0])
            else:
                fig = plot_fam_peaks(qlwell.peaks,
                                     threshold=qlwell.channels[0].statistics.threshold,
                                     threshold_color='red',
                                     max_amplitude=max_amplitudes[0],
                                     background_rgb=MANUAL_THRESHOLD_FAM_BGCOLOR)
            fig.savefig(image_source.get_path('%s/%s_%s.png' % (dbplate.id, well_name, 0)), format='png', dpi=72)
            plt_cleanup(fig)

            if well_channel_automatic_classification(qlwell, 1):
                fig = plot_vic_peaks(qlwell.peaks,
                                     threshold=qlwell.channels[1].statistics.threshold,
                                     max_amplitude=max_amplitudes[1])
            else:
                fig = plot_vic_peaks(qlwell.peaks,
                                     threshold=qlwell.channels[1].statistics.threshold,
                                     threshold_color='red',
                                     max_amplitude=max_amplitudes[1],
                                     background_rgb=MANUAL_THRESHOLD_VIC_BGCOLOR)
                
            fig.savefig(image_source.get_path('%s/%s_%s.png' % (dbplate.id, well_name, 1)), format='png', dpi=72)
            plt_cleanup(fig)

            if qlwell.clusters_defined:
                threshold_fallback = qlwell.clustering_method == QLWell.CLUSTERING_TYPE_THRESHOLD
                fig = plot_cluster_2d(qlwell.peaks,
                                      width=60,
                                      height=60,
                                      thresholds=[qlwell.channels[0].statistics.threshold,
                                                  qlwell.channels[1].statistics.threshold],
                                      boundaries=[0,0,12000,24000],
                                      show_axes=False,
                                      antialiased=True,
                                      unclassified_alpha=0.5,
                                      use_manual_clusters=not well_channel_automatic_classification(qlwell),
                                      highlight_thresholds=threshold_fallback)
                fig.savefig(image_source.get_path('%s/%s_2d.png' % (dbplate.id, well_name)), format='png', dpi=72)
                plt_cleanup(fig)
        
        pm = [pm for pm in dbplate.plate.metrics if pm.reprocess_config_id is None]
        for p in pm:
            Session.delete(p)

        plate = dbplate_tree(dbplate.plate.id)
        
        # override plate_type if supplied (another artifact of bad abstraction)
        if override_plate_type:
            plate.plate_type = override_plate_type

        # this relies on apply_template/apply_setup working correctly on plate addition
        # verify on DR 10005 plate that this works
        if plate.plate_type and plate.plate_type.code in beta_plate_types:
            plate_metrics = get_beta_plate_metrics(plate, qlplate)
        else:
            plate_metrics = process_plate(plate, qlplate)
        Session.add(plate_metrics)