예제 #1
0
    def quantify_chromatogram(self):
        time, _ = zip(*self.chrom_data)
        self.peaks = []

        # Iterate over peaks
        for i in self.master.reference:

            self.peak_name = i[0]
            self.peak_time = i[1]
            self.peak_window = i[2]

            self.peak = Peak(self)

            # Ignore peaks outside the Trace RT window
            if self.peak_time < self.settings.start+self.settings.background_window \
                    or self.peak_time > self.settings.end-self.settings.background_window:
                continue

            # Background correct
            self.peak.determine_background_and_noise()
            if self.peak.background < 0.:
                self.peak.background_correct()
                self.peak.determine_background_and_noise()

            # Determine Areas, background and noise
            self.peak.determine_peak_area()
            self.peak.determine_background_area()
            self.peak.determine_peak_noise()
            self.peak.determine_signal_noise()
            self.peak.determine_total_area()

            # Data Subset (based on second derivative)
            self.peak.determine_spline_and_derivative()
            self.peak.determine_breakpoints()
            self.peak.subset_data()

            # Gaussian fit
            try:
                self.peak.determine_gaussian_coefficients()
                if self.peak.coeff.size > 0:
                    self.peak.determine_gaussian_area()
                    self.peak.determine_gaussian_parameters()
                    self.peak.determine_height()
                self.peak.determine_actual_time()
                self.peak.determine_residual()
            except AttributeError:
                self.logger.warning('Unable to determine Gaussian fit for' +
                                    f'{self.peak_name}')
                pass

            # Results
            self.peaks.append(self.peak)
예제 #2
0
    def determine_peak_parameters(self):
        x_data, _ = zip(*self.peak_buffer.peak_maximum_data)

        self.peak_name = None
        self.peak_window = (x_data[-1] - x_data[0]) / 2
        self.peak_time = self.peak_window + x_data[0]
        peak = Peak(self)

        peak.determine_spline_and_derivative()
        peak.determine_breakpoints()
        peak.subset_data()
        peak.determine_gaussian_coefficients()

        self.peak = peak
예제 #3
0
    def explore_chromatogram(self):
        self.peak_name = None
        self.peak_window = (self.settings.end - self.settings.start) / 2
        self.peak_time = self.peak_window + self.settings.start
        peak_buffer = Peak(self)

        peak_buffer.determine_spline_and_derivative()
        peak_buffer.determine_breakpoints()
        peak_buffer.subset_data()

        self.peak_buffer = peak_buffer
예제 #4
0
    def determine_calibration_timepairs(self):
        self.calibration_time_pairs = []

        for i in self.master.reference:

            self.peak_name = i[0]
            self.peak_time = i[1]
            self.peak_window = i[2]

            self.peak = Peak(self)
            self.peak.determine_background_and_noise()
            self.peak.determine_signal_noise()

            time, intensity = zip(
                *self.peak.peak_data[self.peak.low:self.peak.high])
            max_value = max(intensity)
            max_index = intensity.index(max_value)

            if self.peak.signal_noise >= self.settings.min_peak_SN:
                self.calibration_time_pairs.append((i[1], time[max_index]))
예제 #5
0
class Chromatogram(object):
    def __init__(self, master):
        self.filename = master.filename
        self.settings = master.settings
        self.master = master
        self.logger = master.logger
        self.axes = master.axes
        self.chrom_data = None
        self.peaks = []

    def baseline_correction(self):
        # Background determination
        background = []
        chunks = [
            self.chrom_data[x:x + self.settings.points]
            for x in range(0, len(self.chrom_data), self.settings.points)
        ]
        for j in chunks:
            buff1, buff2 = zip(*j)
            min_index, _ = min(enumerate(buff2), key=operator.itemgetter(1))
            if buff1[0] > self.settings.start and buff1[-1] < self.settings.end:
                background.append((buff1[min_index], buff2[min_index]))

        # Baseline function
        time, intensity = zip(*background)
        func = polyfit(time, intensity, self.settings.baseline_order)
        p = poly1d(func)

        # Transform
        time = [a for a, b in self.chrom_data]
        new_chrom_intensity = [b - p(a) for a, b in self.chrom_data]

        # Uplift
        low = bisect_left(time, self.settings.start)
        high = bisect_right(time, self.settings.end)
        offset = abs(min(min(new_chrom_intensity[low:high]), 0))

        self.chrom_data = list(
            zip(time, [x + offset for x in new_chrom_intensity]))

    def calibrate_chromatogram(self):
        time, intensity = zip(*self.chrom_data)
        time = self.calibration_function(time)
        self.chrom_data = list(zip(time, intensity))

    def determine_calibration_timepairs(self):
        self.calibration_time_pairs = []

        for i in self.master.reference:

            self.peak_name = i[0]
            self.peak_time = i[1]
            self.peak_window = i[2]

            self.peak = Peak(self)
            self.peak.determine_background_and_noise()
            self.peak.determine_signal_noise()

            time, intensity = zip(
                *self.peak.peak_data[self.peak.low:self.peak.high])
            max_value = max(intensity)
            max_index = intensity.index(max_value)

            if self.peak.signal_noise >= self.settings.min_peak_SN:
                self.calibration_time_pairs.append((i[1], time[max_index]))

    def determine_calibration_function(self):
        expected, observed = zip(*self.calibration_time_pairs)
        z = polyfit(observed, expected, 2)
        self.calibration_function = poly1d(z)

    def generate_pdf_report(self):
        pdf = Pdf(self)
        pdf.plot_overview()
        for self.peak in self.peaks:
            pdf.plot_individual()
        pdf.close()

    def normalize_chromatogram(self):
        time, intensity = zip(*self.chrom_data)

        # Normalize to maximum intensity
        maximum = max(
            intensity[bisect_left(time, self.settings.start
                                  ):bisect_right(time, self.settings.end)])
        normalized_intensity = [b / maximum for a, b, in self.chrom_data]

        self.chrom_data = list(zip(time, normalized_intensity))

    def open_chromatogram(self):
        file_parser(self)

    def plot_chromatogram(self):
        label = PurePath(self.filename).stem
        time, intensity = zip(*self.chrom_data)
        self.axes.plot(time, intensity, label=str(label))

    def quantify_chromatogram(self):
        time, _ = zip(*self.chrom_data)
        self.peaks = []

        # Iterate over peaks
        for i in self.master.reference:

            self.peak_name = i[0]
            self.peak_time = i[1]
            self.peak_window = i[2]

            self.peak = Peak(self)

            # Ignore peaks outside the Trace RT window
            if self.peak_time < self.settings.start+self.settings.background_window \
                    or self.peak_time > self.settings.end-self.settings.background_window:
                continue

            # Background correct
            self.peak.determine_background_and_noise()
            if self.peak.background < 0.:
                self.peak.background_correct()
                self.peak.determine_background_and_noise()

            # Determine Areas, background and noise
            self.peak.determine_peak_area()
            self.peak.determine_background_area()
            self.peak.determine_peak_noise()
            self.peak.determine_signal_noise()
            self.peak.determine_total_area()

            # Data Subset (based on second derivative)
            self.peak.determine_spline_and_derivative()
            self.peak.determine_breakpoints()
            self.peak.subset_data()

            # Gaussian fit
            try:
                self.peak.determine_gaussian_coefficients()
                if self.peak.coeff.size > 0:
                    self.peak.determine_gaussian_area()
                    self.peak.determine_gaussian_parameters()
                    self.peak.determine_height()
                self.peak.determine_actual_time()
                self.peak.determine_residual()
            except AttributeError:
                self.logger.warning('Unable to determine Gaussian fit for' +
                                    f'{self.peak_name}')
                pass

            # Results
            self.peaks.append(self.peak)

    def smooth_chromatogram(self):
        # Apply Savitzky-Golay filter
        # TODO: Allow user to specify Smoothing method
        time, intensity = zip(*self.chrom_data)
        new = savgol_filter(intensity, 21, 3)
        self.chrom_data = list(zip(time, new))

    def save_chromatogram(self):
        with open(self.filename, 'w') as fw:
            for data_point in self.trace.chrom_data:
                fw.write(
                    str(
                        format(data_point[0], '0.' +
                               str(self.settings.decimal_numbers) + 'f')) +
                    '\t' + str(
                        format(data_point[1], '0.' +
                               str(self.settings.decimal_numbers) + 'f')) +
                    '\n')
예제 #6
0
    def detect_peaks(self, master):

        orig_time, orig_intensity = zip(*self.chrom.trace.chrom_data)
        curr_intensity = orig_intensity

        time_start = bisect_left(orig_time, self.settings.start)
        time_end = bisect_right(orig_time, self.settings.end)

        # Loop till intensity falls below specified threshold
        while (max(curr_intensity[time_start:time_end]) >
               self.settings.peak_detection_min *
               max(orig_intensity[time_start:time_end])):

            self.window = (self.settings.end - self.settings.start) / 2
            self.time = self.window + self.settings.start

            # Determine breaks and get subset of data
            self.breaks = self.functions.determine_breakpoints(self)
            self.data_subset = self.functions.subset_data(self)

            # Get time and intensity lists
            x_data, _ = zip(*self.data_subset)

            # Create Peak() object
            self.peak = None
            self.window = (x_data[-1] - x_data[0]) / 2
            self.time = self.window + x_data[0]
            self.peak = Peak(self)

            # Gaussian fit
            self.peak.determine_gaussian_coefficients(self)
            if self.peak.coeff.any():
                new_intensity = []
                for index, i in enumerate(curr_intensity):
                    new_intensity.append(i - Fitting().gauss_function(
                        orig_time[index], *self.peak.coeff))
                curr_intensity = new_intensity

            # Subtract Gaussian intensity from the current intensity
            self.chrom.trace.chrom_data = list(zip(orig_time, curr_intensity))

            # Create Gaussian data at 3 sigma width
            gauss_start = self.time - 3 * self.peak.coeff[2]
            gauss_end = self.time + 3 * self.peak.coeff[2]
            gauss_time = linspace(gauss_start, gauss_end,
                                  (gauss_end - gauss_start) * 1000)
            gauss_intensity = Fitting().gauss_function(gauss_time,
                                                       *self.peak.coeff)

            # Store detected peak
            self.detected_peaks.append({
                'data':
                list(zip(gauss_time, gauss_intensity)),
                'coeff':
                self.peak.coeff,
                'central_time':
                self.time
            })

        # Sort by retention time
        self.detected_peaks = sorted(self.detected_peaks,
                                     key=lambda x: x['central_time'])

        # Restore original data
        self.chrom.trace.chrom_data = list(zip(orig_time, orig_intensity))
예제 #7
0
class PeakDetection(object):
    def __init__(self, master):
        self.settings = master.settings
        self.logger = logging.getLogger(__name__)
        self.functions = master.functions
        self.chrom = master.chrom
        self.detected_peaks = []

    def detect_peaks(self, master):

        orig_time, orig_intensity = zip(*self.chrom.trace.chrom_data)
        curr_intensity = orig_intensity

        time_start = bisect_left(orig_time, self.settings.start)
        time_end = bisect_right(orig_time, self.settings.end)

        # Loop till intensity falls below specified threshold
        while (max(curr_intensity[time_start:time_end]) >
               self.settings.peak_detection_min *
               max(orig_intensity[time_start:time_end])):

            self.window = (self.settings.end - self.settings.start) / 2
            self.time = self.window + self.settings.start

            # Determine breaks and get subset of data
            self.breaks = self.functions.determine_breakpoints(self)
            self.data_subset = self.functions.subset_data(self)

            # Get time and intensity lists
            x_data, _ = zip(*self.data_subset)

            # Create Peak() object
            self.peak = None
            self.window = (x_data[-1] - x_data[0]) / 2
            self.time = self.window + x_data[0]
            self.peak = Peak(self)

            # Gaussian fit
            self.peak.determine_gaussian_coefficients(self)
            if self.peak.coeff.any():
                new_intensity = []
                for index, i in enumerate(curr_intensity):
                    new_intensity.append(i - Fitting().gauss_function(
                        orig_time[index], *self.peak.coeff))
                curr_intensity = new_intensity

            # Subtract Gaussian intensity from the current intensity
            self.chrom.trace.chrom_data = list(zip(orig_time, curr_intensity))

            # Create Gaussian data at 3 sigma width
            gauss_start = self.time - 3 * self.peak.coeff[2]
            gauss_end = self.time + 3 * self.peak.coeff[2]
            gauss_time = linspace(gauss_start, gauss_end,
                                  (gauss_end - gauss_start) * 1000)
            gauss_intensity = Fitting().gauss_function(gauss_time,
                                                       *self.peak.coeff)

            # Store detected peak
            self.detected_peaks.append({
                'data':
                list(zip(gauss_time, gauss_intensity)),
                'coeff':
                self.peak.coeff,
                'central_time':
                self.time
            })

        # Sort by retention time
        self.detected_peaks = sorted(self.detected_peaks,
                                     key=lambda x: x['central_time'])

        # Restore original data
        self.chrom.trace.chrom_data = list(zip(orig_time, orig_intensity))

    def plot_peaks(self, master):
        for index, peak in enumerate(self.detected_peaks):
            x_array, y_array = zip(*peak['data'])
            master.axes.fill_between(x_array,
                                     0,
                                     y_array,
                                     alpha=0.5,
                                     label='Peak ' + str(index + 1))

    def write_peaks(self, master):
        save_file = filedialog.asksaveasfilename(title='Save Annotation File')
        with Path(save_file).open('w') as fw:
            fw.write('Index\tTime\tWindow\n')
            for index, peak in enumerate(self.detected_peaks):
                time, intensity = zip(*peak['data'])
                max_intensity_index = intensity.index(max(intensity))

                peak_maximum = time[max_intensity_index]
                if self.settings.peak_detection_edge == 'Sigma':
                    window = (self.settings.peak_detection_edge_value *
                              peak['coeff'][2])
                elif self.settings.peak_detection_edge == 'FWHM':
                    window = abs(2 * peak['coeff'][2] * sqrt(2 * log(2)))
                else:
                    window = None

                fw.write(
                    str(index + 1) + '\t' + str(
                        format(peak_maximum, '0.' +
                               str(self.settings.decimal_numbers) + 'f')) +
                    '\t' + str(
                        format(window, '0.' +
                               str(self.settings.decimal_numbers) + 'f')) +
                    '\n')