From: W. Trevor King Date: Tue, 4 May 2010 07:09:59 +0000 (-0400) Subject: Merged with trunk X-Git-Url: http://git.tremily.us/?p=hooke.git;a=commitdiff_plain;h=41ef0130e16c0cf8d2c0f1acc9e06986d62f7607;hp=cd7b8ff4687547d3661c23180d7145d4ccc898ae Merged with trunk --- diff --git a/bin/hooke b/bin/hooke index 5a57baa..7bf1b13 100755 --- a/bin/hooke +++ b/bin/hooke @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python import hooke.hooke diff --git a/conf/hooke.conf b/conf/hooke.conf index c1d8d7b..9236b81 100644 --- a/conf/hooke.conf +++ b/conf/hooke.conf @@ -42,7 +42,9 @@ since it's to find the config file(s) before your read them. fc_showimposed="0" fc_interesting="0" tccd_threshold="0" - tccd_coincident="0"/> + tccd_coincident="0" + centerzero="1" +/> + @@ -70,20 +73,25 @@ This section defines which plugins have to be loaded by Hooke. + + + - - + + + + (+100-10) + + peak_location[i]=index_pk + return peak_location,peak_size @@ -310,6 +325,9 @@ class flatfiltsCommands(object): item.curve=None #empty the item object, to further avoid memory leak notflat_list.append(item) + for i in range(1000): + k=0 + #Warn that no flattening had been done. if not ('flatten' in self.config['plotmanips']): print 'Flatten manipulator was not found. Processing was done without flattening.' diff --git a/hooke/plugin/generalvclamp.py b/hooke/plugin/generalvclamp.py index 45cfa2c..5f6657b 100644 --- a/hooke/plugin/generalvclamp.py +++ b/hooke/plugin/generalvclamp.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-1 -*- + ''' generalvclamp.py @@ -118,10 +121,10 @@ class generalvclampCommands(object): print str(forcebase*(10**12))+' pN' to_dump='forcebase '+self.current.path+' '+str(forcebase*(10**12))+' pN' self.outlet.push(to_dump) - + def plotmanip_multiplier(self, plot, current): ''' - Multiplies all the Y values of an SMFS curve by a value stored in the 'force_multiplier' + Multiplies all the Y values of an SMFS curve by a value stored in the 'force_multiplier' configuration variable. Useful for calibrations and other stuff. ''' @@ -135,17 +138,17 @@ class generalvclampCommands(object): #multiplier is 1... if (self.config['force_multiplier']==1): - return plot - + return plot + for i in range(len(plot.vectors[0][1])): - plot.vectors[0][1][i]=plot.vectors[0][1][i]*self.config['force_multiplier'] - - for i in range(len(plot.vectors[1][1])): - plot.vectors[1][1][i]=plot.vectors[1][1][i]*self.config['force_multiplier'] - - return plot + plot.vectors[0][1][i]=plot.vectors[0][1][i]*self.config['force_multiplier'] + for i in range(len(plot.vectors[1][1])): + plot.vectors[1][1][i]=plot.vectors[1][1][i]*self.config['force_multiplier'] + return plot + + def plotmanip_flatten(self, plot, current, customvalue=False): ''' Subtracts a polynomial fit to the non-contact part of the curve, as to flatten it. @@ -180,7 +183,17 @@ class generalvclampCommands(object): valn=[[] for item in range(max_exponent)] yrn=[0.0 for item in range(max_exponent)] errn=[0.0 for item in range(max_exponent)] - + + #Check if we have a proper numerical value + try: + zzz=int(max_cycles) + except: + #Loudly and annoyingly complain if it's not a number, then fallback to zero + print '''Warning: flatten value is not a number! + Use "set flatten" or edit hooke.conf to set it properly + Using zero.''' + max_cycles=0 + for i in range(int(max_cycles)): x_ext=plot.vectors[0][0][contact_index+delta_contact:] @@ -240,30 +253,34 @@ class generalvclampCommands(object): if fitspan == 0: # Gets the Xs of two clicked points as indexes on the current curve vector print 'Click twice to delimit chunk' - clickedpoints=[] points=self._measure_N_points(N=2,whatset=1) - clickedpoints=[points[0].index,points[1].index] - clickedpoints.sort() else: print 'Click once on the leftmost point of the chunk (i.e.usually the peak)' - clickedpoints=[] points=self._measure_N_points(N=1,whatset=1) - clickedpoints=[points[0].index-fitspan,points[0].index] + + slope=self._slope(points,fitspan) - # Calls the function linefit_between + # Outputs the relevant slope parameter + print 'Slope:' + print str(slope) + to_dump='slope '+self.current.path+' '+str(slope) + self.outlet.push(to_dump) + + def _slope(self,points,fitspan): + # Calls the function linefit_between parameters=[0,0,[],[]] + try: + clickedpoints=[points[0].index,points[1].index] + clickedpoints.sort() + except: + clickedpoints=[points[0].index-fitspan,points[0].index] + try: parameters=self.linefit_between(clickedpoints[0],clickedpoints[1]) except: print 'Cannot fit. Did you click twice the same point?' return - - # Outputs the relevant slope parameter - print 'Slope:' - print str(parameters[0]) - to_dump='slope '+self.current.path+' '+str(parameters[0]) - self.outlet.push(to_dump) - + # Makes a vector with the fitted parameters and sends it to the GUI xtoplot=parameters[2] ytoplot=[] @@ -287,12 +304,15 @@ class generalvclampCommands(object): else: lineplot.styles+=[None,'scatter'] if lineplot.colors==[]: - lineplot.styles=[None,None,None,None] + lineplot.colors=[None,None,'black',None] else: - lineplot.colors+=[None,None] + lineplot.colors+=['black',None] + + + self._send_plot([lineplot]) + return parameters[0] - self._send_plot([lineplot]) def linefit_between(self,index1,index2,whatset=1): ''' diff --git a/hooke/plugin/jumpstat.py b/hooke/plugin/jumpstat.py new file mode 100755 index 0000000..9175b5c --- /dev/null +++ b/hooke/plugin/jumpstat.py @@ -0,0 +1,204 @@ +# -*- coding: utf-8 -*- +from ..libhooke import WX_GOOD, ClickedPoint +import wxversion +wxversion.select(WX_GOOD) +from wx import PostEvent +import numpy as np +import scipy as sp +import copy +import os.path +import time +import sys +import warnings +warnings.simplefilter('ignore',np.RankWarning) + + +class jumpstatCommands(): + + def do_jumpstat(self,args): + ''' + JUMPSTAT + jumpstat.py + Based on the convolution recognition automatically give: + - the delta distance between the peaks, + - the delta-force from the top of the peaks and subsequent relaxation, + - the delta-force from the top of the peaks and the baseline + The command allow also to remove the unwanted peaks that can be due to interference. + When you first issue the command, it will ask for the filename. If you are giving the filename + of an existing file, autopeak will resume it and append measurements to it. If you are giving + a new filename, it will create the file and append to it until you close Hooke. + You can also define a minimun deviation of the peaks. + + Syntax: + jumpstat [deviation] + deviation = number of times the convolution signal is above the noise absolute deviation. + ''' + + + #finding the max and the minimum positions for all the peaks + noflatten=False + #we use if else only to avoid a "bad input" message from find_current_peaks + if (len(args)==0): + max_peaks_location, peak_size=self.find_current_peaks(noflatten) + min_peaks_location, pks2=self.find_current_peaks(noflatten, True, False) + else: + max_peaks_location, peak_size=self.find_current_peaks(noflatten, args) + min_peaks_location, pks2=self.find_current_peaks(noflatten, args, False) + + + #print "max_peaks_location: "+str(len(max_peaks_location)) + #print "min_peaks_location: "+str(len(min_peaks_location)) + + #if no peaks, we have nothing to plot. exit. + if len(max_peaks_location)==0: + print "No peaks on this curve." + return + + if len(max_peaks_location)!=len(min_peaks_location): + print "Something went wrong in peaks recognition, number of minima is different from number of maxima. Exiting." + return + + #otherwise, we plot the peak locations. + xplotted_ret=self.plots[0].vectors[1][0] + yplotted_ret=self.plots[0].vectors[1][1] + xgood=[xplotted_ret[index] for index in max_peaks_location] + ygood=[yplotted_ret[index] for index in max_peaks_location] + + xafter=[xplotted_ret[index] for index in min_peaks_location] + yafter=[yplotted_ret[index] for index in min_peaks_location] + + recplot=self._get_displayed_plot() + recplot2=self._get_displayed_plot() + recplot.vectors.append([xgood,ygood]) + recplot2.vectors.append([xafter,yafter]) + + if recplot.styles==[]: + recplot.styles=[None,None,'scatter'] + recplot.colors=[None,None,None] + else: + recplot.styles+=['scatter'] + recplot.colors+=[None] + + if recplot2.styles==[]: + recplot2.styles=[None,None,None] + recplot2.colors=[None,'1.0',None] + else: + recplot2.styles+=['scatter'] + recplot2.colors+=['0.5'] + + self._send_plot([recplot]) + self._send_plot([recplot2]) + + + #finding the baseline + self.basepoints=self.baseline_points(max_peaks_location, recplot) + boundaries=[self.basepoints[0].index, self.basepoints[1].index] + boundaries.sort() + to_average=recplot.vectors[1][1][boundaries[0]:boundaries[1]] #y points to average + avg=np.mean(to_average) + + + dist=[] + jumpforce=[] + force=[] + + #we calculate the distance vector + for g in range(len(max_peaks_location)-1): + dist.append((10**9)*(xplotted_ret[max_peaks_location[g]]-xplotted_ret[max_peaks_location[g+1]])) + print "Distance values for the peaks in nm:" + print dist + + #the jump-force vector + for g in range(len(max_peaks_location)): + jumpforce.append((10**12) *(yplotted_ret[min_peaks_location[g]] -yplotted_ret[max_peaks_location[g]]) ) + print "Force values for the jumps of the peaks in pN:" + print jumpforce + + #the force from baseline vector + for g in range(len(max_peaks_location)): + force.append((10**12)*(avg-yplotted_ret[max_peaks_location[g]])) + print "Force values for the peaks in pN:" + print force + + + + #Now ask for the peaks that we don't want + print 'Peaks to ignore (0,1...n from contact point,return to take all)' + print 'N to discard measurement' + exclude_raw=raw_input('Input:') + if exclude_raw=='N': + print 'Discarded.' + return + + if not exclude_raw=='': + exclude=exclude_raw.split(',') + #we convert in numbers the input + try: + exclude=[int(item) for item in exclude] + except: + print 'Bad input, taking nothing.' + return + +# we remove the peaks that we don't want from the list, we need a counter beacause if we remove +# a peaks the other peaks in the list are shifted by one at each step + count=0 + for a in exclude: + if (a==0): + max_peaks_location=max_peaks_location[1:] + min_peaks_location=min_peaks_location[1:] + else: + new_a=a-count + max_peaks_location= max_peaks_location[0:new_a]+max_peaks_location[new_a+1:] + min_peaks_location= min_peaks_location[0:new_a]+min_peaks_location[new_a+1:] + peak_size= peak_size[0:new_a]+peak_size[new_a+1:] + count+=1 + + + #print "max_peaks_location: "+str(len(max_peaks_location)) + #print "min_peaks_location: "+str(len(min_peaks_location)) + + + dist=[] + jumpforce=[] + force=[] + #we recalculate the distances and the forces after the removing of the unwanted peaks + for g in range(len(max_peaks_location)-1): + dist.append(xplotted_ret[max_peaks_location[g]]-xplotted_ret[max_peaks_location[g+1]]) + for g in range(len(max_peaks_location)): + jumpforce.append( yplotted_ret[min_peaks_location[g]] - yplotted_ret[max_peaks_location[g]] ) + for g in range(len(max_peaks_location)): + force.append(avg - yplotted_ret[max_peaks_location[g]]) + + + + + + #Save file info + if self.autofile=='': + self.autofile=raw_input('Jumpstat filename? (return to ignore) ') + if self.autofile=='': + print 'Not saved.' + return + + if not os.path.exists(self.autofile): + f=open(self.autofile,'w+') + f.write('Analysis started '+time.asctime()+'\n') + f.write('----------------------------------------\n') + f.write('; Delta Distance length (m); Jump Force pN; Standard Force pN\n') + f.write(self.current.path+'\n') + for k in range(len(dist)): + f.write(";") + f.write(str(dist[k])+";"+str(jumpforce[k])+";"+str(force[k])+"\n" ) + f.write("\n") + f.close() + + else: + f=open(self.autofile,'a+') + f.write(self.current.path+'\n') + for k in range(len(dist)): + f.write(";") + f.write(str(dist[k])+";"+str(jumpforce[k])+";"+str(force[k])+"\n" ) + f.write("\n") + f.close() + + print 'Saving...' diff --git a/hooke/plugin/multidistance.py b/hooke/plugin/multidistance.py index 9db5f5d..e2370b6 100644 --- a/hooke/plugin/multidistance.py +++ b/hooke/plugin/multidistance.py @@ -32,27 +32,10 @@ class multidistanceCommands(object): deviation = number of times the convolution signal is above the noise absolute deviation. ''' - def find_current_peaks(noflatten, a): - #Find peaks. - if len(a)==0: - a=self.convfilt_config['mindeviation'] - try: - abs_devs=float(a) - except: - print "Bad input, using default." - abs_devs=self.convfilt_config['mindeviation'] - - defplot=self.current.curve.default_plots()[0] - if not noflatten: - flatten=self._find_plotmanip('flatten') #Extract flatten plotmanip - defplot=flatten(defplot, self.current, customvalue=1) #Flatten curve before feeding it to has_peaks - pk_loc,peak_size=self.has_peaks(defplot, abs_devs) - return pk_loc, peak_size - - + noflatten=False - peaks_location, peak_size=find_current_peaks(noflatten, args) - + peaks_location, peak_size=self.find_current_peaks(noflatten) + #if no peaks, we have nothing to plot. exit. if len(peaks_location)==0: return diff --git a/hooke/plugin/multifit.py b/hooke/plugin/multifit.py new file mode 100644 index 0000000..2e620fd --- /dev/null +++ b/hooke/plugin/multifit.py @@ -0,0 +1,385 @@ +#!/usr/bin/env python + +''' +multifit.py + +Alberto Gomez-Casado, (c) 2010, University of Twente (The Netherlands) +Licensed under GNU GPL v2 +''' + +#FIXME clean this, probably some dependencies are not needed + +from ..libhooke import WX_GOOD, ClickedPoint +import wxversion +wxversion.select(WX_GOOD) +from wx import PostEvent +import numpy as np +import scipy as sp +import copy +import os.path +import time +import tempfile +import warnings +warnings.simplefilter('ignore',np.RankWarning) +import Queue + +global measure_wlc +global EVT_MEASURE_WLC + +global events_from_fit +events_from_fit=Queue.Queue() #GUI ---> CLI COMMUNICATION + + +class multifitCommands: + + def do_multifit(self,args): + ''' + MULTIFIT + (multifit.py) + Presents curves for manual analysis in a comfortable mouse-only fashion. + Obtains contour length, persistance length, rupture force and + slope - loading rate. + WLC is shown in red, eFJC in blue. + ------------- + Syntax: + multifit [pl=value] [kl=value] [t=value] [slopew=value] [basew=value] + [slope2p] [justone] + + pl=[value] and kl=[value]: Use a fixed persistent length (WLC) or Kuhn + length (eFJC) for the fit. If pl is not given, the fit will be + a 2-variable fit. + DO NOT put spaces between 'pl', '=' and the value. + eFJC fit works better with a fixed kl + The value must be in nanometers. + + t=[value] : Use a user-defined temperature. The value must be in + kelvins; by default it is 293 K. + DO NOT put spaces between 't', '=' and the value. + + slopew and basew : width in points for slope fitting (points to the + right of clicked rupture) and base level fitting (points to + the left of clicked top of rupture). + If slopew is not provided, the routine will ask for a 5th + point to fit the slope. + DO NOT put spaces between 'slopew' or 'basew', '=' value. + + slope2p : calculates the slope from the two clicked points, + instead of fitting data between them + + justone : performs the fits over current curve instead of iterating + + See fit command help for more information on the options and fit + procedures. + NOTE: centerzero plot modifier should be activated (set centerzero 1). + ''' + + #NOTE duplicates a lot of code from do_fit in fit.py, a call to it could be used directly + #but it is easier to control the program flow bypassing it + + pl_value=None + kl_value=None + T=self.config['temperature'] + slopew=None + basew=15 + justone=False + twops=False + + #FIXME spaces are not allowed between pl or t and value + for arg in args.split(): + #look for a persistent length argument. + if 'pl=' in arg: + pl_expression=arg.split('=') + pl_value=float(pl_expression[1]) #actual value + if 'kl=' in arg: + kl_expression=arg.split('=') + kl_value=float(kl_expression[1]) #actual value + #look for a T argument. + if ('t=' in arg) or ('T=' in arg): + t_expression=arg.split('=') + T=float(t_expression[1]) + #look for a basew argument. + if ('basew=' in arg): + basew_expression=arg.split('=') + basew=int(basew_expression[1]) + #look for a slopew argument. + if ('slopew=' in arg): + slopew_expression=arg.split('=') + slopew=int(slopew_expression[1]) + if('justone' in arg): + justone=True + if('slope2p' in arg): + twops=True + + counter=0 + savecounter=0 + curveindex=0 + + if not justone: + print 'What curve no. you would like to start? (enter for ignoring)' + skip=raw_input() + + if skip.isdigit()==False: + skip=0 + else: + skip=int(skip)-1 + print 'Skipping '+str(skip)+ ' curves' + else: + skip=0 + #begin presenting curves for analysis + while curveindex curveindex: + curveindex+=1 + continue + + #give periodically the opportunity to stop the analysis + if counter%20==0 and counter>0: + print '\nYou checked '+str(counter)+' curves. Do you want to continue?' + self.current=curve + self.do_plot(0) + if self.YNclick(): + print 'Going on...' + else: + break + else: + self.current=curve + self.do_plot(0) + else: + curve=self.current + self.do_plot(0) + if not justone: + print '\nCurve '+str(curveindex+1)+' of '+str(len(self.current_list)) + print 'Click contact point or left end (red area)of the curve to skip' + #hightlights an area dedicated to reject current curve + sizeret=len(self.plots[0].vectors[1][0]) + noarea=self.plots[0].vectors[1][0][-sizeret/6:-1] + noareaplot=copy.deepcopy(self._get_displayed_plot()) + #noise dependent slight shift to improve visibility + noareaplot.add_set(noarea,np.ones_like(noarea)*5.0*np.std(self.plots[0].vectors[1][1][-sizeret/6:-1])) + noareaplot.styles+=['scatter'] + noareaplot.colors+=["red"] + self._send_plot([noareaplot]) + contact_point=self._measure_N_points(N=1, whatset=1)[0] + contact_point_index=contact_point.index + noareaplot.remove_set(-1) + #remove set leaves some styles disturbing the next graph, fixed by doing do_plot + self.do_plot(0) + if contact_point_index>5.0/6.0*sizeret: + if justone: + break + curveindex+=1 + continue + + self.wlccontact_point=contact_point + self.wlccontact_index=contact_point.index + self.wlccurrent=self.current.path + + print 'Now click two points for the fitting area (one should be the rupture point)' + wlcpoints=self._measure_N_points(N=2,whatset=1) + print 'And one point of the top of the jump' + toppoint=self._measure_N_points(N=1,whatset=1) + slopepoint=ClickedPoint() + if slopew==None: + print 'Click a point to calculate slope' + slopepoint=self._measure_N_points(N=1,whatset=1) + + fitpoints=[contact_point]+wlcpoints + #use the currently displayed plot for the fit + displayed_plot=self._get_displayed_plot() + + #use both fit functions + try: + wlcparams, wlcyfit, wlcxfit, wlcfit_errors,wlc_qstd = self.wlc_fit(fitpoints, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1],pl_value,T, return_errors=True ) + wlcerror=False + except: + print 'WLC fit not possible' + wlcerror=True + + try: + fjcparams, fjcyfit, fjcxfit, fjcfit_errors,fjc_qstd = self.efjc_fit(fitpoints, displayed_plot.vectors[1][0], displayed_plot.vectors[1][1],kl_value,T, return_errors=True ) + fjcerror=False + except: + print 'eFJC fit not possible' + fjcerror=True + + #Measure rupture force + ruptpoint=ClickedPoint() + if wlcpoints[0].graph_coords[1] contact_point=self._clickize(itplot[0].vectors[1][0], itplot[0].vectors[1][1], cindex) self.basepoints=[] - base_index_0=peak_location[-1]+fit_interval_nm(peak_location[-1], itplot[0], self.config['auto_right_baseline'],False) + base_index_0=peak_location[-1]+self.fit_interval_nm(peak_location[-1], itplot[0], self.config['auto_right_baseline'],False) self.basepoints.append(self._clickize(itplot[0].vectors[1][0],itplot[0].vectors[1][1],base_index_0)) - base_index_1=self.basepoints[0].index+fit_interval_nm(self.basepoints[0].index, itplot[0], self.config['auto_left_baseline'],False) + base_index_1=self.basepoints[0].index+self.fit_interval_nm(self.basepoints[0].index, itplot[0], self.config['auto_left_baseline'],False) self.basepoints.append(self._clickize(itplot[0].vectors[1][0],itplot[0].vectors[1][1],base_index_1)) self.basecurrent=self.current.path boundaries=[self.basepoints[0].index, self.basepoints[1].index] diff --git a/hooke/plugin/procplots.py b/hooke/plugin/procplots.py index b8baa15..b7826ae 100644 --- a/hooke/plugin/procplots.py +++ b/hooke/plugin/procplots.py @@ -157,6 +157,41 @@ class procplotsCommands(object): return plot + + def plotmanip_centerzero(self, plot, current, customvalue=None): + ''' + Centers the force curve so the median (the free level) corresponds to 0 N + Assumes that: + - plot.vectors[0][1] is the Y of extension curve + - plot.vectors[1][1] is the Y of retraction curve + + + ''' + #use only for force spectroscopy experiments! + if current.curve.experiment != 'smfs': + return plot + + if customvalue != None: + execute_me=customvalue + else: + execute_me=self.config['centerzero'] + if not execute_me: + return plot + + + + #levelapp=float(np.median(plot.vectors[0][1])) + levelret=float(np.median(plot.vectors[1][1][-300:-1])) + + level=levelret + + approach=[i-level for i in plot.vectors[0][1]] + retract=[i-level for i in plot.vectors[1][1]] + + plot.vectors[0][1]=approach + plot.vectors[1][1]=retract + return plot + ''' def plotmanip_detriggerize(self, plot, current, customvalue=None): #DEPRECATED diff --git a/hooke/plugin/review.py b/hooke/plugin/review.py new file mode 100644 index 0000000..ef2ee51 --- /dev/null +++ b/hooke/plugin/review.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python + +'''review.py +Alberto Gomez-Casado (c) 2010 University of Twente +''' + +from ..libhooke import WX_GOOD +import wxversion +wxversion.select(WX_GOOD) +from wx import PostEvent +import numpy as np +import shutil +import libinput as linp +import copy +import os.path + +import warnings +warnings.simplefilter('ignore',np.RankWarning) + + +class reviewCommands: + + def do_review(self,args): + ''' + REVIEW + (review.py) + Presents curves (in current playlist) in groups of ten. User can indicate which curves will be selected to be saved in a separate directory for further analysis. + By default curves are presented separated -30 nm in x and -100 pN in y. + Curve number one of each set is the one showing the approach. + ------------ + Syntax: + review [x spacing (nm)] [y spacing (pN] + + ''' + + args=args.split() + + if len(args)==2: + try: + xgap=int(args[0])*1e-9 #scale to SI units + ygap=int(args[1])*1e-12 + except: + print 'Spacings must be numeric! Using defaults' + xgap=-30*1e-9 + ygap=-100*1e-12 + else: + xgap=-30*1e-9 + ygap=-100*1e-12 + + print 'Processing playlist...' + print '(Please wait)' + keep_list=[] + + c=0 + print 'You can stop the review at any moment by entering \'q\' you can go back ten curves entering \'b\'' + print 'What curve no. you would like to start? (Enter for starting from the first)' + skip=raw_input() + + if skip.isdigit()==False: + skip=0 + else: + skip=int(skip) + print 'Skipping '+str(skip)+ ' curves' + c=skip + + while c < len(self.current_list): + + + #take a group of ten curves and plot them with some spacing + + curveset=self.current_list[c:c+10] + + base=curveset[0] + self.current=base + self.do_plot(0) + multiplot=copy.deepcopy(self._get_displayed_plot(0)) + self.current.curve.close_all() + + for i in range(1,10): + if i >= len(curveset): + print 'End of the list' + print 'WARNING: maybe you want to finish!' + break + nextitem=curveset[i] + if not nextitem.identify(self.drivers): + continue + nextplot=self.plotmanip_correct(nextitem.curve.default_plots()[0],nextitem) + nextvect=nextplot.vectors + nextitem.curve.close_all() + + nextx=nextvect[1][0] + nexty=nextvect[1][1] + #center y around 0 + ymedian=np.median(nexty) + pos=0 + for j in range(0,len(nextx)): + nextx[j]=nextx[j]+i*xgap + nexty[j]=nexty[j]+i*ygap-ymedian + multiplot.add_set(nextx,nexty) + multiplot.styles.append('lines') + multiplot.colors.append(None) + + self._send_plot([multiplot]) + + + print 'Which ones you want to keep?' + keep=raw_input() + if keep.isalpha(): + if keep=='b': + print 'Going back ten curves' + c-=10 + if c<0: + print 'We are already at the start' + c=0 + continue + if keep=='q': + break + else: + for i in keep.split(): + if i.isdigit() and int(i)>0 and int(i)<11: #if it is not digit the int() call is never made, so no exception should be happening + keep_item=curveset[int(i)-1].path + if keep_item in keep_list: + print 'This curve ('+keep_item+') was already selected, skipping' + else: + keep_list.append(keep_item) + else: + print 'You entered an invalid value: '+i + + c+=10 + + #FIXME I don't know why the print below gives errors sometimes + try: + print 'Kept '+str(len(keep_list))+' curves from '+str(min(c+i+1,len(self.current_list))) + except: + print 'Display error, never mind, we continue. Below the amount of kept and total curves:' + print str(len(keep_list)) + print str(len(self.current_list)) + + allok=0 #flag to keep from losing all the work in a slight mistake + while allok==0: + if len(keep_list) == 0: + return + save=linp.safeinput('Do you want to save the selected curves?',['y','n']) + if save=='y': + savedir=linp.safeinput('Destination directory?') + savedir=os.path.abspath(savedir) + if not os.path.isdir(savedir): + print 'Destination is not a directory. Try again' + continue + if save=='n': + allok=1 + return + + for item in keep_list: + try: + shutil.copy(item, savedir) + allok=1 + except (OSError, IOError): + print 'Cannot copy file. '+item+' Perhaps you gave me a wrong directory?' + allok=0 + break + + return diff --git a/mfp_igor_scripts/FMjoin.py b/mfp_igor_scripts/FMjoin.py new file mode 100644 index 0000000..311892b --- /dev/null +++ b/mfp_igor_scripts/FMjoin.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +''' +FMjoin.py +Copies all .ibw files contained in a folder and its subfolders into a single folder. Useful for force maps. + +Usage: +python FMjoin.py origindir destdir + + +Alberto Gomez-Casado (c) 2010, University of Twente (The Netherlands) +This program is released under the GNU General Public License version 2. +''' + +import os +import shutil +import sys + +def main(*args): + if len(sys.argv) < 2: + print 'You must at least specify origin and destination folders.' + return 0 + origin=sys.argv[1] + dest=sys.argv[2] + + if os.path.exists(origin): + if os.path.exists(dest): + if os.listdir(dest)!=[]: + print 'Destination folder is not empty! Use another folder.' + return 0 + else: + print 'Destination folder does not exist, will create it' + os.mkdir(dest) + else: + print 'You provided a wrong origin folder name, try again.' + + origin=os.path.abspath(origin) + dest=os.path.abspath(dest) + + for root, dirs, files in os.walk(origin): + for filename in files: + if filename.split('.')[1]!="ibw": + continue + filepath=os.path.join(root,filename) + #to avoid overwriting, we collapse unique paths into filenames + rawdest=filepath.split(os.path.commonprefix([origin, filepath]))[1] + rawdest=rawdest.replace('/','') #for linux + rawdest=rawdest.replace('\\','') #for windows + destfile=os.path.join(dest,rawdest) + print 'Copying '+rawdest + shutil.copy(filepath,destfile) + + return 0 + +if __name__ == '__main__': + sys.exit(main(*sys.argv)) + + diff --git a/mfp_igor_scripts/h5export.py b/mfp_igor_scripts/h5export.py new file mode 100644 index 0000000..f49b3a8 --- /dev/null +++ b/mfp_igor_scripts/h5export.py @@ -0,0 +1,49 @@ +import h5py +import numpy +import os +import sys + +h5file=os.path.realpath(sys.argv[-1]) +h5dir=os.path.dirname(h5file) + +f=h5py.File(h5file) + +exportdir=os.path.join(h5dir,'exported') +try: + os.mkdir(exportdir) +except: + print 'mkdir error, maybe the export directory already exists?' + +def h5exportfunc(name): + Deflname=name + if Deflname.endswith('Defl'): #search for _Defl dataset + LVDTname=str.replace(Deflname,'Defl','LVDT') #and correspondant LVDT dataset + Defldata=f[Deflname][:] #store the data in local var + LVDTdata=f[LVDTname][:] + #find useful attr (springc) + try: + notes=f[Deflname].attrs['IGORWaveNote'] + springmatch=notes.index("SpringConstant: ")+len("SpringConstant: ") + springc=notes[springmatch:].split("\r",1)[0] #probably extracting the leading numbers can be way more elegant than this + print Deflname + except: + print 'Something bad happened with '+Deflname+', ignoring it' + return None + #returning anything but None halts the visit procedure + + fp=open(os.path.join(exportdir,name.replace('/',''))+'.txt','w') + #uses the full HDF5 path (slashes out) to avoid potential overwriting + #write attr + fp.writelines("IGP-HDF5-Hooke\n") + fp.writelines('SpringConstant: '+springc+'\n\n') + fp.writelines('App x\tApp y\tRet x\tRet y\n') + #write LVDT and Defl data + half=Defldata.size/2 + for i in numpy.arange(0,half): + fp.writelines(str(LVDTdata[i])+'\t'+str(Defldata[i])+'\t'+str(LVDTdata[i+half])+'\t'+str(Defldata[i+half])+'\n') + #close the file + fp.close() + return None + + +f.visit(h5exportfunc)