Began versioning.
[calibcant.git] / calibcant / T_analyze.py
1 #!/usr/bin/python
2 #
3 # calibcant - tools for thermally calibrating AFM cantilevers
4 #
5 # Copyright (C) 2007,2008, William Trevor King
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation; either version 3 of the
10 # License, or (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 # See the GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 # 02111-1307, USA.
21 #
22 # The author may be contacted at <wking@drexel.edu> on the Internet, or
23 # write to Trevor King, Drexel University, Physics Dept., 3141 Chestnut St.,
24 # Philadelphia PA 19104, USA.
25
26 """
27 Separate the more general T_analyze() from the other T_*()
28 functions in calibcant.  Also provide a command line interface
29 for analyzing data acquired through other workflows.
30
31 The relevant physical quantities are :
32  T Temperature at which thermal vibration measurements were aquired
33 """
34
35 import numpy
36 import common # common module for the calibcant package
37 import config # config module for the calibcant package
38 import data_logger
39 import z_piezo_utils
40 import linfit
41
42 def C_to_K(celsius) :
43     "Convert Celsius -> Kelvin."
44     return celsius + 273.15
45
46 def T_analyze(T, convert_to_K=C_to_K) :
47     """
48     Not much to do here, just convert to Kelvin.
49     Uses C_to_K (defined above) by default.
50     """
51     try : # if T is an array, convert element by element
52         for i in range(len(T)) :
53             T[i] = convert_to_K(T[i])
54     except TypeError : # otherwise, make an array from a single T
55         T = [convert_to_K(T)]
56     return T
57
58 def T_save(T, log_dir=None) :
59     """
60     Save either a single T (if you are crazy :p),
61     or an array of them (more reasonable)
62     """
63     T = numpy.array(T, dtype=numpy.float)
64     if log_dir != None :
65         log = data_logger.data_log(log_dir, noclobber_logsubdir=False,
66                                    log_name="T_float")
67         log.write_binary(T.tostring())
68     if LOG_DATA != None :
69         log = data_logger.data_log(LOG_DIR, noclobber_logsubdir=False,
70                                    log_name="T_float")
71         log.write_binary(T.tostring())
72         
73 def T_load(datafile=None) :
74     """
75     Load the saved T array (possibly of length 1), and return it.  If
76     datafile == None, return an array of one config.DEFAULT_TEMP
77     instead.
78     """
79     if datafile == None :
80         return numpy.array([config.DEFAULT_TEMP], dtype=numpy.float)
81     else :
82         dl = data_logger.data_load()
83         return dl.read_binary(datafile)
84
85 def T_plot(T, plotVerbose) :
86     """
87     Umm, just print the temperature?
88     """
89     if plotVerbose or PYLAB_VERBOSE or TEXT_VERBOSE :
90         print "Temperature ", T
91
92 def T_load_analyze_tweaked(tweak_file, convert_to_K=C_to_K, textVerboseFile=None) :
93     "Load all the T array files from a tweak file and return a single array"
94     Ts = []
95     for line in file(tweak_file, 'r') :
96         parsed = line.split()
97         path = parsed[0].split('\n')[0]
98         if textVerboseFile != None :
99             print >> textVerboseFile, "Reading data from %s" % (path)
100         # read the data
101         data = T_load(path)
102         Ts.extend(data)
103     return numpy.array(Ts, dtype=numpy.float)
104
105 # commandline interface functions
106 import scipy.io, sys
107
108 def read_data(ifile):
109     "ifile can be a filename string or open (seekable) file object"
110     if ifile == None :  ifile = sys.stdin
111     unlabeled_data=scipy.io.read_array(ifile)
112     return unlabeled_data
113
114 if __name__ == '__main__' :
115     # command line interface
116     from optparse import OptionParser
117     
118     usage_string = ('%prog <input-file>\n'
119                     '2008, W. Trevor King.\n'
120                     '\n'
121                     'There are two operation modes, one to analyze a single T (temperature) file,\n'
122                     'and one to analyze tweak files.\n'
123                     '\n'
124                     'Single file mode (the default) :\n'
125                     'Reads in single column ASCII file of temperatures and... prints them back out.\n'
126                     'No need to do this, but the option is available for consistency with the other\n'
127                     'calibcant modules.\n'
128                     '\n'
129                     'Tweak file mode:\n'
130                     'Runs the same analysis as in single file mode for each T file in\n'
131                     'a tweak file.  Each line in the tweak file specifies a single T file.\n'
132                     'A T file contains a sequence of 32 bit floats representing temperature in K.\n'
133                     )
134     parser = OptionParser(usage=usage_string, version='%prog 0.1')
135     parser.add_option('-C', '--celsius', dest='celsius',
136                       help='Use Celsius input temperatures instead of Kelvin (defaul %default)\n',
137                       action='store_true', default=False)
138     parser.add_option('-o', '--output-file', dest='ofilename',
139                       help='write output to FILE (default stdout)',
140                       type='string', metavar='FILE')
141     parser.add_option('-c', '--comma-out', dest='comma_out', action='store_true',
142                       help='Output comma-seperated values (default %default)',
143                       default=False)
144     parser.add_option('-t', '--tweak-mode', dest='tweakmode', action='store_true',
145                       help='Run in tweak-file mode',
146                       default=False)
147     parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
148                       help='Print lots of debugging information',
149                       default=False)
150
151     options,args = parser.parse_args()
152     parser.destroy()
153     assert len(args) >= 1, "Need an input file"
154         
155     ifilename = args[0]
156
157     if options.ofilename != None :
158         ofile = file(options.ofilename, 'w')
159     else :
160         ofile = sys.stdout
161     if options.verbose == True :
162         vfile = sys.stderr
163     else :
164         vfile = None
165     config.TEXT_VERBOSE = options.verbose
166     config.PYLAB_VERBOSE = False
167     config.GNUPLOT_VERBOSE = False
168     if options.celsius :
169         convert_to_K = C_to_K
170     else :
171         convert_to_K = lambda T : T # no-change function
172
173     if options.tweakmode == False :
174         data = read_data(ifilename)
175         Ts = T_analyze(T, convert_to_K)
176     else : # tweak file mode
177         Ts = T_load_analyze_tweaked(ifilename, convert_to_K, textVerboseFile=vfile)
178
179     if options.comma_out :
180         sep = ','
181     else :
182         sep = '\n'
183     common.write_array(ofile, Ts, sep)
184     
185     if options.ofilename != None :
186         ofile.close()