3 # calibcant - tools for thermally calibrating AFM cantilevers
5 # Copyright (C) 2008-2010 W. Trevor King <wking@drexel.edu>
7 # This file is part of CalibCant.
9 # CalibCant is free software: you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public
11 # License as published by the Free Software Foundation, either
12 # version 3 of the License, or (at your option) any later version.
14 # CalibCant is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU Lesser General Public License for more details.
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with CalibCant. If not, see
21 # <http://www.gnu.org/licenses/>.
24 Separate the more general T_analyze() from the other T_*()
25 functions in calibcant. Also provide a command line interface
26 for analyzing data acquired through other workflows.
28 The relevant physical quantities are :
29 T Temperature at which thermal vibration measurements were aquired
35 from splittable_kwargs import splittableKwargsFunction, \
36 make_splittable_kwargs_function
43 "Convert Celsius -> Kelvin."
44 return celsius + 273.15
47 "Convert Kelvin -> Kelvin."
50 @splittableKwargsFunction()
51 def T_analyze(T, convert_to_K=C_to_K) :
53 Not much to do here, just convert to Kelvin.
54 Uses C_to_K (defined above) by default.
56 try : # if T is an array, convert element by element
57 for i in range(len(T)) :
58 T[i] = convert_to_K(T[i])
59 except TypeError : # otherwise, make an array from a single T
63 @splittableKwargsFunction()
64 def T_save(T, log_dir=None) :
66 Save either a single T (if you are crazy :p),
67 or an array of them (more reasonable)
69 T = numpy.array(T, dtype=numpy.float)
71 log = data_logger.data_log(log_dir, noclobber_logsubdir=False,
73 log.write_binary(T.tostring())
74 if config.LOG_DATA != None :
75 log = data_logger.data_log(config.LOG_DIR, noclobber_logsubdir=False,
77 log.write_binary(T.tostring())
79 def T_load(datafile=None) :
81 Load the saved T array (possibly of length 1), and return it. If
82 datafile == None, return an array of one config.DEFAULT_TEMP
86 return numpy.array([config.DEFAULT_TEMP], dtype=numpy.float)
88 dl = data_logger.data_load()
89 return dl.read_binary(datafile)
91 @splittableKwargsFunction()
92 def T_plot(T, plotVerbose=False) :
94 Umm, just print the temperature?
96 if plotVerbose or config.PYLAB_VERBOSE or config.TEXT_VERBOSE :
97 print "Temperature ", T
99 @splittableKwargsFunction((T_analyze, 'T', 'convert_to_K'),
101 def T_load_analyze_tweaked(tweak_file, convert_to_K=C_to_K, textVerboseFile=None, **kwargs) :
102 "Load all the T array files from a tweak file and return a single array"
103 T_analyze_kwargs,T_plot_kwargs = \
104 T_load_analyze_tweaked._splitargs(T_load_analyze_tweaked, kwargs)
106 for line in file(tweak_file, 'r') :
107 parsed = line.split()
108 path = parsed[0].strip()
109 if path[0] == '#': # a comment
111 if textVerboseFile != None :
112 print >> textVerboseFile, "Reading data from %s" % (path)
116 T_analyze(Ts, convert_to_K=convert_to_K)
117 return numpy.array(Ts, dtype=numpy.float)
119 # commandline interface functions
122 def read_data(ifile):
123 "ifile can be a filename string or open (seekable) file object"
124 if ifile == None : ifile = sys.stdin
125 unlabeled_data=scipy.io.read_array(ifile)
126 return unlabeled_data
128 if __name__ == '__main__' :
129 # command line interface
130 from optparse import OptionParser
132 usage_string = ('%prog <input-file>\n'
133 '2008, W. Trevor King.\n'
135 'There are two operation modes, one to analyze a single T (temperature) file,\n'
136 'and one to analyze tweak files.\n'
138 'Single file mode (the default) :\n'
139 'Reads in single column ASCII file of temperatures and... prints them back out.\n'
140 'No need to do this, but the option is available for consistency with the other\n'
141 'calibcant modules.\n'
144 'Runs the same analysis as in single file mode for each T file in\n'
145 'a tweak file. Each line in the tweak file specifies a single T file.\n'
146 'Blank lines and those beginning with a pound sign (#) are ignored.\n'
147 'A T file contains a sequence of 32 bit floats representing temperature in K.\n'
149 parser = OptionParser(usage=usage_string, version='%prog 0.1')
150 parser.add_option('-C', '--celsius', dest='celsius',
151 help='Use Celsius input temperatures instead of Kelvin (default %default)\n',
152 action='store_true', default=False)
153 parser.add_option('-o', '--output-file', dest='ofilename',
154 help='write output to FILE (default stdout)',
155 type='string', metavar='FILE')
156 parser.add_option('-c', '--comma-out', dest='comma_out', action='store_true',
157 help='Output comma-seperated values (default %default)',
159 parser.add_option('-t', '--tweak-mode', dest='tweakmode', action='store_true',
160 help='Run in tweak-file mode',
162 parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
163 help='Print lots of debugging information',
166 options,args = parser.parse_args()
168 assert len(args) >= 1, "Need an input file"
172 if options.ofilename != None :
173 ofile = file(options.ofilename, 'w')
176 if options.verbose == True :
180 config.TEXT_VERBOSE = options.verbose
181 config.PYLAB_VERBOSE = False
182 config.GNUPLOT_VERBOSE = False
184 convert_to_K = C_to_K
186 convert_to_K = K_to_K
188 if options.tweakmode == False :
189 data = read_data(ifilename)
190 Ts = T_analyze(data, convert_to_K)
191 else : # tweak file mode
192 Ts = T_load_analyze_tweaked(ifilename, convert_to_K, textVerboseFile=vfile)
194 if options.comma_out :
198 common.write_array(ofile, Ts, sep)
200 if options.ofilename != None :