Added illysam branch
[hooke.git] / plugins / export.py
1 #!/usr/bin/env python
2
3 '''
4 export.py
5
6 Export commands for Hooke.
7
8 Copyright 2010 by Dr. Rolf Schmidt (Concordia University, Canada)
9
10 This program is released under the GNU General Public License version 2.
11 '''
12
13 import lib.libhooke as lh
14 import wxversion
15 wxversion.select(lh.WX_GOOD)
16
17 import copy
18 import os.path
19 import time
20 import wx
21
22 class exportCommands(object):
23     '''
24     Export force curves, fits and results in different formats
25     '''
26
27     def _plug_init(self):
28         pass
29
30     def do_fits(self):#, ext='', folder='', prefix='', separator=''):
31         '''
32         Exports all approach and retraction files in a playlist and
33         all fitting results (if available) in a columnar ASCII format.
34         Please make sure that the number of points in the fit is smaller
35         or equal to the number of points in the approach/retraction.
36         For the time being, exports only one set of results (e.g. WLC
37         or FJC, not both).
38         '''
39
40         ext = self.GetStringFromConfig('export', 'fits', 'ext')
41         folder = self.GetStringFromConfig('export', 'fits', 'folder')
42         prefix = self.GetStringFromConfig('export', 'fits', 'prefix')
43         separator = self.GetStringFromConfig('export', 'fits', 'separator')
44         #TODO: add list for Tab, Space, Comma, Other
45         #add string for Other
46
47         active_file = self.GetActiveFile()
48         plot = self.GetDisplayedPlot()
49
50         #TODO: fix for multiple results
51         #add empty columns before adding new results if necessary
52         if plot is not None:
53             for results_str, results in plot.results.items():
54                 for curve in results.results:
55                     output = []
56                     header_str = ''
57                     if curve.visible:
58                         header_str += curve.label + '_x (' + curve.units.x + ')' + separator + curve.label + '_y (' + curve.units.y + ')'
59                         output.append(header_str)
60                         for index, row in enumerate(curve.x):
61                             output.append(separator.join([str(curve.x[index]), str(curve.y[index])]))
62                     if output:
63                         #TODO: add option to replace or add the new file extension
64                         #add option to rename file from default.000 to default_000
65                         filename = os.path.basename(active_file.filename)
66                         filename = ''.join([prefix, filename, '_', curve.label, '.', ext])
67                         filename = os.path.join(folder, filename)
68                         output_file = open(filename, 'w')
69                         output_file.write('\n'.join(output))
70                         output_file.close
71
72     def do_force_curve(self):
73         '''
74         TXT
75         Saves the current curve as a text file
76         Columns are, in order:
77         X1 , Y1 , X2 , Y2 , X3 , Y3 ...
78
79         -------------
80         Syntax: txt [filename] {plot to export}
81         '''
82
83         ext = self.GetStringFromConfig('export', 'force_curve', 'ext')
84         folder = self.GetStringFromConfig('export', 'force_curve', 'folder')
85         prefix = self.GetStringFromConfig('export', 'force_curve', 'prefix')
86         separator = self.GetStringFromConfig('export', 'force_curve', 'separator')
87         #TODO: add list for Tab, Space, Comma, Other
88         #add string for Other
89
90         active_file = self.GetActiveFile()
91         plot = self.GetActivePlot()
92         extension = plot.curves[lh.EXTENSION]
93         retraction = plot.curves[lh.RETRACTION]
94
95         output = []
96         header_str = ''
97         for index, curve in enumerate(plot.curves):
98             header_str += curve.label + '_x (' + curve.units.x + ')' + separator + curve.label + '_y (' + curve.units.y + ')'
99             if index < len(plot.curves) - 1:
100                 header_str += separator
101         output.append(header_str)
102         #TODO: add units
103         for index, row in enumerate(extension.x):
104             output.append(separator.join([str(extension.x[index]), str(extension.y[index]), str(retraction.x[index]), str(retraction.y[index])]))
105
106         if output:
107             #TODO: add option to replace or add the new file extension
108             #add option to rename file from default.000 to default_000
109             filename = os.path.basename(active_file.filename)
110             filename = ''.join([prefix, filename, '.', ext])
111             filename = os.path.join(folder, filename)
112             output_file = open(filename, 'w')
113             output_file.write('\n'.join(output))
114             output_file.close
115
116     def do_overlay(self):
117         '''
118         Exports all retraction files in a playlist with the same scale.
119         The files can then be overlaid in a graphing program to see which
120         ones have the same shape.
121         Use this export command only on filtered lists as it takes a long time
122         to complete even with a small number of curves.
123         '''
124         playlist = self.GetActivePlaylist()
125
126         filename_prefix = self.GetStringFromConfig('export', 'overlay', 'prefix')
127
128         differences_x = []
129         differences_y = []
130         number_of_curves = playlist.count
131         message_str = ''.join([str(number_of_curves), ' files to load.\n\n'])
132         progress_dialog = wx.ProgressDialog('Loading', message_str, maximum=number_of_curves, parent=self, style=wx.PD_APP_MODAL|wx.PD_SMOOTH|wx.PD_AUTO_HIDE)
133         for index, current_file in enumerate(playlist.files):
134             current_file.identify(self.drivers)
135             plot = current_file.plot
136
137             plot.raw_curves = copy.deepcopy(plot.curves)
138             #apply all active plotmanipulators and add the 'manipulated' data
139             for plotmanipulator in self.plotmanipulators:
140                 if self.GetBoolFromConfig('core', 'plotmanipulators', plotmanipulator.name):
141                     plot = plotmanipulator.method(plot, current_file)
142             #add corrected curves to plot
143             plot.corrected_curves = copy.deepcopy(plot.curves)
144
145             curve = current_file.plot.corrected_curves[lh.RETRACTION]
146             differences_x.append(curve.x[0] - curve.x[-1])
147             differences_y.append(curve.x[0] - curve.y[-1])
148             progress_dialog.Update(index, ''.join([message_str, 'Loading ', str(index + 1), '/', str(number_of_curves)]))
149         progress_dialog.Destroy()
150
151         max_x = max(differences_x)
152         max_y = max(differences_y)
153         message_str = ''.join([str(number_of_curves), ' files to export.\n\n'])
154         for index, current_file in enumerate(playlist.files):
155             curve = current_file.plot.corrected_curves[lh.RETRACTION]
156             first_x = curve.x[0]
157             first_y = curve.y[0]
158             new_x = [x - first_x for x in curve.x]
159             new_y = [y - first_y for y in curve.y]
160             new_x.append(-max_x)
161             new_y.append(-max_y)
162             output_str = ''
163             for row_index, row in enumerate(new_x):
164                 output_str += ''.join([str(new_x[row_index]), ', ', str(new_y[row_index]), '\n'])
165
166             if output_str != '':
167                 filename = ''.join([filename_prefix, current_file.name])
168                 filename = current_file.filename.replace(current_file.name, filename)
169                 output_file = open(filename, 'w')
170                 output_file.write(output_str)
171                 output_file.close
172         progress_dialog.Destroy()
173
174     def do_results(self, filename='', separator=''):
175         '''
176         EXPORTFITS
177         Exports all visible fit results in a playlist into a delimited text file
178         '''
179         if filename == '':
180             filename = self.GetStringFromConfig('export', 'results', 'filename')
181         if separator == '':
182             separator = self.GetStringFromConfig('export', 'results', 'separator')
183
184         playlist = self.GetActivePlaylist()
185         output_str = ''
186         header_str = ''
187         for current_file in playlist.files:
188             if len(current_file.plot.results) > 0:
189                 for key in current_file.plot.results.keys():
190                     #if there are different types of fit results in the playlist, the header might have to change
191                     #here, we generate a temporary header and compare it to the current header
192                     #if they are different, the tempeorary header is used
193                     #we get the header from the fit and add the 'filename' column
194                     temporary_header_str = ''.join([current_file.plot.results[key].get_header_as_str(), separator, 'Filename'])
195                     if temporary_header_str != header_str:
196                         header_str = ''.join([current_file.plot.results[key].get_header_as_str(), separator, 'Filename'])
197                         output_str = ''.join([output_str, header_str, '\n'])
198                     for index, result in enumerate(current_file.plot.results[key].results):
199                         if result.visible:
200                             #similar to above, we get the result from the fit and add the filename
201                             line_str = current_file.plot.results[key].get_result_as_string(index)
202                             line_str = ''.join([line_str, separator, current_file.filename])
203                             output_str = ''.join([output_str, line_str, '\n'])
204         if output_str != '':
205             output_str = ''.join(['Analysis started ', time.asctime(), '\n', output_str])
206             output_file = open(filename, 'w')
207             output_file.write(output_str)
208             output_file.close
209         else:
210             dialog = wx.MessageDialog(None, 'No results found, file not saved.', 'Info', wx.OK)
211             dialog.ShowModal()