+++ /dev/null
-# Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
-#
-# This file is part of Hooke.
-#
-# Hooke is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# Hooke is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
-# Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with Hooke. If not, see
-# <http://www.gnu.org/licenses/>.
-
-"""Force spectroscopy curves filtering of flat curves
-
-Other plugin dependencies:
-procplots.py (plot processing plugin)
-"""
-
-import xml.dom.minidom
-
-import wx
-#import scipy
-import numpy
-from numpy import diff
-import os.path
-
-#import pickle
-
-import libpeakspot as lps
-#import curve as lhc
-import hookecurve as lhc
-import libhooke as lh
-import wxversion
-wxversion.select(lh.WX_GOOD)
-
-
-class flatfiltsCommands:
-
- def do_flatfilt(self):
- '''
- FLATFILT
- (flatfilts.py)
- Filters out flat (featureless) curves of the current playlist,
- creating a playlist containing only the curves with potential
- features.
- ------------
- Syntax:
- flatfilt [min_npks min_deviation]
-
- min_npks = minmum number of points over the deviation
- (default=4)
-
- min_deviation = minimum signal/noise ratio
- (default=9)
-
- If called without arguments, it uses default values, that
- should work most of the times.
- '''
- #TODO: should this be optional?
- medianfilter = 7
-
- self.AppendToOutput('Processing playlist...')
- self.AppendToOutput('(Please wait)')
- features = []
- playlist = self.GetActivePlaylist()
- curves = playlist.curves
- curve_index = 0
- for curve in curves:
- curve_index += 1
- try:
- notflat = self.has_features(curve)
- feature_string = ''
- if notflat != 1:
- if notflat > 0:
- feature_string = str(notflat) + ' features'
- else:
- feature_string = 'no features'
- else:
- feature_string = '1 feature'
- output_string = ''.join(['Curve ', curve.name, '(', str(curve_index), '/', str(len(curves)), '): ', feature_string])
- except:
- notflat = False
- output_string = ''.join(['Curve ', curve.name, '(', str(curve_index), '/', str(len(curves)), '): cannot be filtered. Probably unable to retrieve force data from corrupt file.'])
- self.AppendToOutput(output_string)
- if notflat:
- curve.features = notflat
- features.append(curve_index - 1)
- if not features:
- self.AppendToOutput('Found nothing interesting. Check the playlist, could be a bug or criteria could be too stringent.')
- else:
- if len(features) < playlist.count:
- self.AppendToOutput(''.join(['Found ', str(len(features)), ' potentially interesting curves.']))
- self.AppendToOutput('Regenerating playlist...')
- playlist_filtered = playlist.filter_curves(features)
- self.AddPlaylist(playlist_filtered, name='flatfilt')
- else:
- self.AppendToOutput('No curves filtered. Try different filtering criteria.')
-
- def has_features(self, curve):
- '''
- decides if a curve is flat enough to be rejected from analysis: it sees if there
- are at least min_npks points that are higher than min_deviation times the absolute value
- of noise.
-
- Algorithm original idea by Francesco Musiani, with my tweaks and corrections.
- '''
- medianfilter = 7
- mindeviation = self.GetIntFromConfig('flatfilts', 'flatfilt', 'min_deviation')
- minpeaks = self.GetIntFromConfig('flatfilts', 'flatfilt', 'min_npks')
- #medianfilter = self.GetIntFromConfig('flatfilt', 'median_filter')
- #mindeviation = self.GetIntFromConfig('convfilt', 'mindeviation')
- #minpeaks = self.GetIntFromConfig('convfilt', 'minpeaks')
-
- retvalue = 0
-
- #item.identify(self.drivers)
- #we assume the first is the plot with the force curve
- #do the median to better resolve features from noise
- flat_plot = self.plotmanip_median(curve.driver.default_plots()[0], curve, customvalue=medianfilter)
- flat_vects = flat_plot.vectors
- curve.driver.close_all()
- #needed to avoid *big* memory leaks!
- #del item.driver
- #del item
-
- #absolute value of derivate
- yretdiff=diff(flat_vects[1][1])
- yretdiff=[abs(value) for value in yretdiff]
- #average of derivate values
- diffmean=numpy.mean(yretdiff)
- yretdiff.sort()
- yretdiff.reverse()
- c_pks=0
- for value in yretdiff:
- if value/diffmean > mindeviation:
- c_pks += 1
- else:
- break
-
- if c_pks >= minpeaks:
- retvalue = c_pks
-
- del flat_plot, flat_vects, yretdiff
-
- return retvalue
-
- ################################################################
- #-----CONVFILT-------------------------------------------------
- #-----Convolution-based peak recognition and filtering.
- #Requires the libpeakspot.py library
-
- def has_peaks(self, plot, curve=None):
- '''
- Finds peak position in a force curve.
- FIXME: should be moved to libpeakspot.py
- '''
-
- blindwindow = self.GetFloatFromConfig('flatfilts', 'convfilt', 'blindwindow')
- #need to convert the string that contains the list into a list
- convolution = eval(self.GetStringFromConfig('flatfilts', 'convfilt', 'convolution'))
- maxcut = self.GetFloatFromConfig('flatfilts', 'convfilt', 'maxcut')
- mindeviation = self.GetFloatFromConfig('flatfilts', 'convfilt', 'mindeviation')
- positive = self.GetBoolFromConfig('flatfilts', 'convfilt', 'positive')
- seedouble = self.GetIntFromConfig('flatfilts', 'convfilt', 'seedouble')
- stable = self.GetFloatFromConfig('flatfilts', 'convfilt', 'stable')
-
- xret = plot.vectors[1][0]
- yret = plot.vectors[1][1]
- #Calculate convolution
- convoluted = lps.conv_dx(yret, convolution)
-
- #surely cut everything before the contact point
- cut_index = self.find_contact_point(plot, curve)
- #cut even more, before the blind window
- start_x = xret[cut_index]
- blind_index = 0
- for value in xret[cut_index:]:
- if abs((value) - (start_x)) > blindwindow * (10 ** -9):
- break
- blind_index += 1
- cut_index += blind_index
- #do the dirty convolution-peak finding stuff
- noise_level = lps.noise_absdev(convoluted[cut_index:], positive, maxcut, stable)
- above = lps.abovenoise(convoluted, noise_level, cut_index, mindeviation)
- peak_location, peak_size = lps.find_peaks(above, seedouble=seedouble)
- #take the maximum
- for i in range(len(peak_location)):
- peak = peak_location[i]
- maxpk = min(yret[peak - 10:peak + 10])
- index_maxpk = yret[peak - 10:peak + 10].index(maxpk) + (peak - 10)
- peak_location[i] = index_maxpk
-
- return peak_location, peak_size
-
- def exec_has_peaks(self, curve):
- '''
- encapsulates has_peaks for the purpose of correctly treating the curve objects in the convfilt loop,
- to avoid memory leaks
- '''
- #item.identify(self.drivers)
- #we assume the first is the plot with the force curve
- plot = curve.driver.default_plots()[0]
-
- if self.HasPlotmanipulator('plotmanip_flatten'):
- #If flatten is present, use it for better recognition of peaks...
- #flatten = self._find_plotmanip('flatten') #extract flatten plot manipulator
- #plot = flatten(plot, item, customvalue=1)
- plot = self.plotmanip_flatten(plot, curve, customvalue=1)
-
- peak_location, peak_size = self.has_peaks(plot, curve)
- #close all open files
- curve.driver.close_all()
- #needed to avoid *big* memory leaks!
- #del item.driver
- #del item
- return peak_location, peak_size
-
- #------------------------
- #------commands----------
- #------------------------
- def do_peaks(self):
- '''
- PEAKS
- (flatfilts.py)
- Test command for convolution filter / test.
- ----
- Syntax: peaks [deviations]
- absolute deviation = number of times the convolution signal is above the noise absolute deviation.
- Default is 5.
- '''
-
- #TODO: check if the following line gives us what we need
- curve = self.GetActiveCurve()
- defplots = curve.driver.default_plots()[0] #we need the raw, uncorrected plots
-
- #if 'flatten' in self.config['plotmanips']:
- if self.HasPlotmanipulator('plotmanip_flatten'):
- #flatten=self._find_plotmanip('flatten') #extract flatten plot manipulator
- #defplots=flatten(defplots, self.current)
- defplots = self.plotmanip_flatten(defplots, curve, customvalue=0)
- else:
- self.AppendToOutput('The flatten plot manipulator is not loaded. Enabling it could give better results.')
-
- peak_location, peak_size = self.has_peaks(defplots, curve)
- self.AppendToOutput('Found ' + str(len(peak_location)) + ' peaks.')
- self.AppendToOutput('peaks ' + curve.filename + ' ' + str(len(peak_location)))
- #to_dump = 'peaks ' + current_curve.filename + ' ' + str(len(peak_location))
- #self.outlet.push(to_dump)
-
- #if no peaks, we have nothing to plot. exit.
- if peak_location:
- #otherwise, we plot the peak locations.
- xplotted_ret = curve.plots[0].vectors[1][0]
- yplotted_ret = curve.plots[0].vectors[1][1]
- xgood = [xplotted_ret[index] for index in peak_location]
- ygood = [yplotted_ret[index] for index in peak_location]
-
- curve.plots[0].add_set(xgood, ygood)
- curve.plots[0].styles.append('scatter')
- curve.plots[0].colors.append('indigo')
-
- #recplot = self._get_displayed_plot()
- #recplot.vectors.append([xgood,ygood])
- #if recplot.styles == []:
- #recplot.styles = [None, None, 'scatter']
- #recplot.colors = [None, None, None]
- #else:
- #recplot.styles += ['scatter']
- #recplot.colors += [None]
-
- #self._send_plot([recplot])
- self.UpdatePlot()
-
- def do_convfilt(self):
- '''
- CONVFILT
- (flatfilts.py)
- Filters out flat (featureless) curves of the current playlist,
- creating a playlist containing only the curves with potential
- features.
- ------------
- Syntax:
- convfilt [min_npks min_deviation]
-
- min_npks = minmum number of peaks
- (to set the default, see convfilt.conf file; CONVCONF and SETCONF commands)
-
- min_deviation = minimum signal/noise ratio *in the convolution*
- (to set the default, see convfilt.conf file; CONVCONF and SETCONF commands)
-
- If called without arguments, it uses default values.
- '''
-
- self.AppendToOutput('Processing playlist...')
- self.AppendToOutput('(Please wait)')
- minpeaks = self.GetIntFromConfig('flatfilts', 'convfilt', 'minpeaks')
- features = []
- playlist = self.GetActivePlaylist()
-
- curves = self.GetActivePlaylist().curves
- curve_index = 0
- for curve in curves:
- curve_index += 1
- try:
- peak_location, peak_size = self.exec_has_peaks(curve)
- number_of_peaks = len(peak_location)
- if number_of_peaks != 1:
- if number_of_peaks > 0:
- feature_string = str(number_of_peaks) + ' features'
- else:
- feature_string = 'no features'
- else:
- feature_string = '1 feature'
- if number_of_peaks >= minpeaks:
- feature_string += '+'
- output_string = ''.join(['Curve ', curve.name, '(', str(curve_index), '/', str(len(curves)), '): ', feature_string])
- except:
- peak_location = []
- peak_size = []
- output_string = ''.join(['Curve ', curve.name, '(', str(curve_index), '/', str(len(curves)), '): cannot be filtered. Probably unable to retrieve force data from corrupt file.'])
- self.AppendToOutput(output_string)
- if number_of_peaks >= minpeaks:
- curve.peak_location = peak_location
- curve.peak_size = peak_size
- features.append(curve_index - 1)
-
- #TODO: do we need this? Flattening might not be necessary/desired
- #Warn that no flattening had been done.
- if not self.HasPlotmanipulator('plotmanip_flatten'):
- self.AppendToOutput('Flatten manipulator was not found. Processing was done without flattening.')
- self.AppendToOutput('Try to enable it in the configuration file for better results.')
- if not features:
- self.AppendToOutput('Found nothing interesting. Check the playlist, could be a bug or criteria could be too stringent.')
- else:
- if len(features) < playlist.count:
- self.AppendToOutput(''.join(['Found ', str(len(features)), ' potentially interesting curves.']))
- self.AppendToOutput('Regenerating playlist...')
- playlist_filtered = playlist.filter_curves(features)
- self.AddPlaylist(playlist_filtered, name='convfilt')
- else:
- self.AppendToOutput('No curves filtered. Try different filtering criteria.')
-
+++ /dev/null
-#!/usr/bin/env python
-
-'''
-flatfilts.py
-
-Force spectroscopy files filtering of flat files.
-
-Plugin dependencies:
-procplots.py (plot processing plugin)
-
-Copyright 2008 Massimo Sandal, Fabrizio Benedetti
-with modifications by Dr. Rolf Schmidt (Concordia University, Canada)
-
-This program is released under the GNU General Public License version 2.
-'''
-
-import lib.libhooke as lh
-import wxversion
-wxversion.select(lh.WX_GOOD)
-
-import copy
-from numpy import diff, mean
-
-import lib.peakspot as lps
-import lib.curve
-
-class flatfiltsCommands:
-
- def do_flatfilt(self):
- '''
- FLATFILT
- (flatfilts.py)
- Filters out flat (featureless) files of the current playlist,
- creating a playlist containing only the files with potential
- features.
- ------------
- Syntax:
- flatfilt [min_npks min_deviation]
-
- min_npks = minmum number of points over the deviation
- (default=4)
-
- min_deviation = minimum signal/noise ratio
- (default=9)
-
- If called without arguments, it uses default values, that
- should work most of the times.
- '''
-
- self.AppendToOutput('Processing playlist...')
- self.AppendToOutput('(Please wait)')
- features = []
- playlist = self.GetActivePlaylist()
- files = playlist.files
- file_index = 0
- for current_file in files:
- file_index += 1
- try:
- current_file.identify(self.drivers)
- notflat = self.has_features(copy.deepcopy(current_file))
- feature_string = ''
- if notflat != 1:
- if notflat > 0:
- feature_string = str(notflat) + ' features'
- else:
- feature_string = 'no features'
- else:
- feature_string = '1 feature'
- output_string = ''.join(['Curve ', current_file.name, '(', str(file_index), '/', str(len(files)), '): ', feature_string])
- except:
- notflat = False
- output_string = ''.join(['Curve ', current_file.name, '(', str(file_index), '/', str(len(files)), '): cannot be filtered. Probably unable to retrieve force data from corrupt file.'])
- self.AppendToOutput(output_string)
- if notflat:
- current_file.features = notflat
- features.append(file_index - 1)
- if not features:
- self.AppendToOutput('Found nothing interesting. Check the playlist, could be a bug or criteria could be too stringent.')
- else:
- if len(features) < playlist.count:
- self.AppendToOutput(''.join(['Found ', str(len(features)), ' potentially interesting files.']))
- self.AppendToOutput('Regenerating playlist...')
- playlist_filtered = playlist.filter_curves(features)
- self.AddPlaylist(playlist_filtered, name='flatfilt')
- else:
- self.AppendToOutput('No files filtered. Try different filtering criteria.')
-
- def has_features(self, current_file):
- '''
- decides if a curve is flat enough to be rejected from analysis: it sees if there
- are at least min_npks points that are higher than min_deviation times the absolute value
- of noise.
-
- Algorithm original idea by Francesco Musiani, with my tweaks and corrections.
- '''
- #TODO: shoudl medianfilter be variable?
- medianfilter = 7
- #medianfilter = self.GetIntFromConfig('flatfilts', 'flatfilt', 'median_filter')
- mindeviation = self.GetIntFromConfig('flatfilts', 'flatfilt', 'min_deviation')
- minpeaks = self.GetIntFromConfig('flatfilts', 'flatfilt', 'min_npks')
-
- retvalue = 0
-
- #we assume the first is the plot with the force curve
- #do the median to better resolve features from noise
- flat_curve = self.plotmanip_median(current_file.plot, current_file, customvalue=medianfilter)
-
- #absolute value of derivate
- yretdiff = diff(flat_curve.curves[lh.RETRACTION].y)
- yretdiff = [abs(value) for value in yretdiff]
- #average of derivate values
- diffmean = mean(yretdiff)
- yretdiff.sort()
- yretdiff.reverse()
- c_pks = 0
- for value in yretdiff:
- if value / diffmean > mindeviation:
- c_pks += 1
- else:
- break
-
- if c_pks >= minpeaks:
- retvalue = c_pks
-
- return retvalue
-
- ################################################################
- #-----CONVFILT-------------------------------------------------
- #-----Convolution-based peak recognition and filtering.
- #Requires the peakspot.py library
-
- def has_peaks(self, plot=None, plugin=None):
- '''
- Finds peak position in a force curve.
- '''
-
- if plugin is None:
- blindwindow = self.GetFloatFromConfig('flatfilts', 'convfilt', 'blindwindow')
- #need to convert the string that contains the list into a list
- convolution = eval(self.GetStringFromConfig('flatfilts', 'convfilt', 'convolution'))
- maxcut = self.GetFloatFromConfig('flatfilts', 'convfilt', 'maxcut')
- mindeviation = self.GetFloatFromConfig('flatfilts', 'convfilt', 'mindeviation')
- positive = self.GetBoolFromConfig('flatfilts', 'convfilt', 'positive')
- seedouble = self.GetIntFromConfig('flatfilts', 'convfilt', 'seedouble')
- stable = self.GetFloatFromConfig('flatfilts', 'convfilt', 'stable')
- else:
- blindwindow = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'blindwindow')
- #need to convert the string that contains the list into a list
- convolution = eval(self.GetStringFromConfig(plugin.name, plugin.section, plugin.prefix + 'convolution'))
- maxcut = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'maxcut')
- mindeviation = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'mindeviation')
- positive = self.GetBoolFromConfig(plugin.name, plugin.section, plugin.prefix + 'positive')
- seedouble = self.GetIntFromConfig(plugin.name, plugin.section, plugin.prefix + 'seedouble')
- stable = self.GetFloatFromConfig(plugin.name, plugin.section, plugin.prefix + 'stable')
-
- if plot is None:
- plot = self.GetDisplayedPlotCorrected()
-
- retraction = plot.curves[lh.RETRACTION]
- #Calculate convolution
- convoluted = lps.conv_dx(retraction.y, convolution)
-
- #surely cut everything before the contact point
- cut_index = self.find_contact_point(plot)
- #cut even more, before the blind window
- start_x = retraction.x[cut_index]
- blind_index = 0
- for value in retraction.x[cut_index:]:
- if abs((value) - (start_x)) > blindwindow * (10 ** -9):
- break
- blind_index += 1
- cut_index += blind_index
- #do the dirty convolution-peak finding stuff
- noise_level = lps.noise_absdev(convoluted[cut_index:], positive, maxcut, stable)
- above = lps.abovenoise(convoluted, noise_level, cut_index, mindeviation)
- peak_location, peak_size = lps.find_peaks(above, seedouble=seedouble)
- #take the maximum
- for i in range(len(peak_location)):
- peak = peak_location[i]
- maxpk = min(retraction.y[peak - 10:peak + 10])
- index_maxpk = retraction.y[peak - 10:peak + 10].index(maxpk) + (peak - 10)
- peak_location[i] = index_maxpk
-
- return peak_location, peak_size
-
- def do_peaks(self, plugin=None, peak_location=None, peak_size=None):
- '''
- Test command for convolution filter.
- ----
- Syntax: peaks [deviations]
- absolute deviation = number of times the convolution signal is above the noise absolute deviation.
- Default is 5.
- '''
-
- if plugin is None:
- color = self.GetColorFromConfig('flatfilts', 'peaks', 'color')
- size = self.GetIntFromConfig('flatfilts', 'peaks', 'size')
- else:
- color = self.GetColorFromConfig(plugin.name, plugin.section, plugin.prefix + 'color')
- size = self.GetIntFromConfig(plugin.name, plugin.section, plugin.prefix + 'size')
-
- plot = self.GetDisplayedPlotCorrected()
-
- if peak_location is None and peak_size is None:
- if not self.AppliesPlotmanipulator('flatten'):
- self.AppendToOutput('The flatten plot manipulator is not loaded. Enabling it could give better results.')
-
- peak_location, peak_size = self.has_peaks(plot)
- if len(peak_location) != 1:
- peak_str = ' peaks.'
- else:
- peak_str = ' peak.'
- self.AppendToOutput('Found ' + str(len(peak_location)) + peak_str)
-
- if peak_location:
- retraction = plot.curves[lh.RETRACTION]
-
- peaks = lib.curve.Curve()
- peaks.color = color
- peaks.size = size
- peaks.style = 'scatter'
- peaks.title = 'Peaks'
- peaks.x = [retraction.x[index] for index in peak_location]
- peaks.y = [retraction.y[index] for index in peak_location]
-
- plot.curves.append(peaks)
-
- self.UpdatePlot(plot)
-
- def do_convfilt(self):
- '''
- Filters out flat (featureless) files of the current playlist,
- creating a playlist containing only the files with potential
- features.
- ------------
- min_npks: minmum number of peaks
- min_deviation: minimum signal/noise ratio *in the convolution*
- '''
-
- self.AppendToOutput('Processing playlist...')
- self.AppendToOutput('(Please wait)')
- apply_plotmanipulators = self.GetStringFromConfig('flatfilts', 'convfilt', 'apply_plotmanipulators')
- minpeaks = self.GetIntFromConfig('flatfilts', 'convfilt', 'minpeaks')
- features = []
- playlist = self.GetActivePlaylist()
-
- files = self.GetActivePlaylist().files
- file_index = 0
- for current_file in files:
- number_of_peaks = 0
- file_index += 1
- try:
- current_file.identify(self.drivers)
- if apply_plotmanipulators == 'all':
- plot = self.ApplyPlotmanipulators(current_file.plot, current_file)
- if apply_plotmanipulators == 'flatten':
- plotmanipulator = self.GetPlotmanipulator('flatten')
- plot = plotmanipulator.method(current_file.plot, current_file)
- if apply_plotmanipulators == 'none':
- plot = copy.deepcopy(current_file.plot)
-
- peak_location, peak_size = self.has_peaks(plot)
- number_of_peaks = len(peak_location)
- if number_of_peaks != 1:
- if number_of_peaks > 0:
- feature_string = str(number_of_peaks) + ' features'
- else:
- feature_string = 'no features'
- else:
- feature_string = '1 feature'
- if number_of_peaks >= minpeaks:
- feature_string += '+'
- output_string = ''.join(['Curve ', current_file.name, '(', str(file_index), '/', str(len(files)), '): ', feature_string])
- except:
- peak_location = []
- peak_size = []
- output_string = ''.join(['Curve ', current_file.name, '(', str(file_index), '/', str(len(files)), '): cannot be filtered. Probably unable to retrieve force data from corrupt file.'])
- self.AppendToOutput(output_string)
- if number_of_peaks >= minpeaks:
- current_file.peak_location = peak_location
- current_file.peak_size = peak_size
- features.append(file_index - 1)
-
- #Warn that no flattening had been done.
- if not self.HasPlotmanipulator('plotmanip_flatten'):
- self.AppendToOutput('Flatten manipulator was not found. Processing was done without flattening.')
- else:
- if not self.AppliesPlotmanipulator('flatten'):
- self.AppendToOutput('Flatten manipulator was not applied.')
- self.AppendToOutput('Try to enable the flatten plotmanipulator for better results.')
-
- if not features:
- self.AppendToOutput('Found nothing interesting. Check the playlist, could be a bug or criteria could be too stringent.')
- else:
- if len(features) < playlist.count:
- self.AppendToOutput(''.join(['Found ', str(len(features)), ' potentially interesting files.']))
- self.AppendToOutput('Regenerating playlist...')
- playlist_filtered = playlist.filter_curves(features)
- self.AddPlaylist(playlist_filtered, name='convfilt')
- else:
- self.AppendToOutput('No files filtered. Try different filtering criteria.')
-