1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import sys
20 import os.path
21 import re
22 import wx
23 from diffpy.pdfgui.control.pdfguimacros import makeTemperatureSeries
24 from diffpy.pdfgui.gui.pdfpanel import PDFPanel
25 from diffpy.pdfgui.gui.tooltips import temperatureseriespanel as toolTips
26 from diffpy.pdfgui.gui.wxExtensions.listctrls import AutoWidthListCtrl
27 from diffpy.pdfgui.utils import numericStringSort
28
31 PDFPanel.__init__(self)
32
33 kwds["style"] = wx.TAB_TRAVERSAL
34 wx.Panel.__init__(self, *args, **kwds)
35 self.instructionsLabel = wx.StaticText(self, -1, "Select a fit from the tree on the left then add datasets and assign\ntemperatues below. If you have not set up a fit to be the template\nfor the series, hit cancel and rerun this macro once a fit has been\ncreated.")
36 self.listCtrlFiles = AutoWidthListCtrl(self, -1, style=wx.LC_REPORT|wx.LC_EDIT_LABELS|wx.SUNKEN_BORDER)
37 self.buttonUp = wx.BitmapButton(self, -1, wx.NullBitmap)
38 self.buttonDown = wx.BitmapButton(self, -1, wx.NullBitmap)
39 self.buttonAdd = wx.Button(self, wx.ID_ADD, "Add")
40 self.buttonDelete = wx.Button(self, wx.ID_DELETE, "Delete")
41 self.static_line_1 = wx.StaticLine(self, -1)
42 self.goButton = wx.Button(self, wx.ID_OK, "OK")
43 self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel")
44
45 self.__set_properties()
46 self.__do_layout()
47
48 self.Bind(wx.EVT_LIST_COL_CLICK, self.onColClick, self.listCtrlFiles)
49 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.onEndLabelEdit, self.listCtrlFiles)
50 self.Bind(wx.EVT_BUTTON, self.onUp, self.buttonUp)
51 self.Bind(wx.EVT_BUTTON, self.onDown, self.buttonDown)
52 self.Bind(wx.EVT_BUTTON, self.onAdd, id=wx.ID_ADD)
53 self.Bind(wx.EVT_BUTTON, self.onDelete, id=wx.ID_DELETE)
54 self.Bind(wx.EVT_BUTTON, self.onOK, id=wx.ID_OK)
55 self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL)
56
57 self.buttonUp.SetBitmapLabel(wx.ArtProvider.GetBitmap(wx.ART_GO_UP))
58 self.buttonDown.SetBitmapLabel(wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN))
59 self.__customProperties()
60
62
63 self.instructionsLabel.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))
64 self.buttonUp.SetSize(self.buttonUp.GetBestSize())
65 self.buttonDown.SetSize(self.buttonDown.GetBestSize())
66
67 self.setToolTips(toolTips)
68
70
71 sizer_1 = wx.BoxSizer(wx.VERTICAL)
72 sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
73 grid_sizer_1 = wx.GridSizer(1, 2, 10, 10)
74 sizer_2 = wx.BoxSizer(wx.VERTICAL)
75 sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
76 sizer_5 = wx.BoxSizer(wx.VERTICAL)
77 sizer_1.Add(self.instructionsLabel, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
78 sizer_4.Add(self.listCtrlFiles, 1, wx.ALL|wx.EXPAND, 5)
79 sizer_5.Add((0, 0), 1, wx.ADJUST_MINSIZE, 0)
80 sizer_5.Add(self.buttonUp, 0, wx.ALL|wx.ADJUST_MINSIZE, 5)
81 sizer_5.Add(self.buttonDown, 0, wx.ALL|wx.ADJUST_MINSIZE, 5)
82 sizer_5.Add((0, 0), 1, wx.ADJUST_MINSIZE, 0)
83 sizer_4.Add(sizer_5, 0, wx.EXPAND, 0)
84 sizer_2.Add(sizer_4, 1, wx.EXPAND, 0)
85 sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
86 grid_sizer_1.Add(self.buttonAdd, 0, wx.ADJUST_MINSIZE, 0)
87 grid_sizer_1.Add(self.buttonDelete, 0, wx.ADJUST_MINSIZE, 0)
88 sizer_1.Add(grid_sizer_1, 0, wx.ALL, 5)
89 sizer_1.Add(self.static_line_1, 0, wx.EXPAND, 0)
90 sizer_3.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
91 sizer_3.Add(self.goButton, 0, wx.ALL|wx.ADJUST_MINSIZE, 5)
92 sizer_3.Add(self.cancelButton, 0, wx.ALL|wx.ADJUST_MINSIZE, 5)
93 sizer_1.Add(sizer_3, 0, wx.EXPAND, 0)
94 self.SetAutoLayout(True)
95 self.SetSizer(sizer_1)
96 sizer_1.Fit(self)
97 sizer_1.SetSizeHints(self)
98
99
101 """Set the custom properties."""
102 self.fit = None
103 self.reverse = False
104 self.fullpath = '.'
105 self.datasets = []
106
107
108 self.listCtrlFiles.InsertColumn(0, "Temperature")
109 self.listCtrlFiles.InsertColumn(1, "Data Set")
110 self.listCtrlFiles.SetColumnWidth(0,-2)
111 return
112
114 """Update the temperature in the datasets."""
115 index = event.GetIndex()
116 text = event.GetText()
117 temperature = 300.0
118 try:
119 temperature = float(text)
120 except ValueError:
121 event.Veto()
122 return
123 if temperature <= 0:
124 event.Veto()
125 return
126
127 self.datasets[index][0] = temperature
128 self.reverse = False
129 return
130
131 - def onOK(self, event):
132 """Let's go!"""
133 paths = [tp[1] for tp in self.datasets]
134 temperatures = [tp[0] for tp in self.datasets]
135 org = makeTemperatureSeries(self.mainFrame.control, self.fit,
136 paths, temperatures)
137 self.treeCtrlMain.ExtendProjectTree(org, clear=False)
138 self.mainFrame.needsSave()
139 self.onCancel(event)
140 return
141
143 """Let's go, but not actually do anything."""
144 self.mainFrame.setMode("fitting")
145 self.treeCtrlMain.UnselectAll()
146 self.mainFrame.switchRightPanel("blank")
147 return
148
149 - def onUp(self, event):
150 """Move an item in the list up."""
151 index = self.listCtrlFiles.GetFirstSelected()
152 if index > 0:
153 temp = self.datasets[index]
154 self.datasets[index] = self.datasets[index-1]
155 self.datasets[index-1] = temp
156 self.fillList()
157 self.listCtrlFiles.Select(index-1)
158 return
159
161 """Move an item in the list down."""
162 index = self.listCtrlFiles.GetFirstSelected()
163 if index > -1 and index != len(self.datasets)-1:
164 temp = self.datasets[index]
165 self.datasets[index] = self.datasets[index+1]
166 self.datasets[index+1] = temp
167 self.fillList()
168 self.listCtrlFiles.Select(index+1)
169 return
170
172 """Append files to the list."""
173 dir, filename = os.path.split(self.fullpath)
174 if not dir:
175 dir = self.mainFrame.workpath
176
177 matchstring = "PDF data files (*.gr)|*.gr|PDF fit files (*.fgr)|*.fgr|PDF fit files (*.fit)|*.fit|PDF calculation files (*.cgr)|*.cgr|PDF calculation files (*.calc)|*.calc|All Files|*"
178 d = wx.FileDialog(None, "Choose files", dir, "", matchstring,
179 wx.OPEN|wx.FILE_MUST_EXIST|wx.MULTIPLE)
180 paths = []
181 if d.ShowModal() == wx.ID_OK:
182 paths = d.GetPaths()
183 d.Destroy()
184
185
186 newdatasets = []
187 for path in paths:
188 self.fullpath = path
189 self.mainFrame.workpath = os.path.dirname(path)
190
191
192 temperature = 300.0
193 rx = {'f' : r'(?:\d+(?:\.\d*)?|\d*\.\d+)' }
194
195
196
197
198 regexp = r"(?:[Tt](?:emp(?:erature)?)?(%(f)s))|(?:(%(f)s)[Kk])" % rx
199 res = re.search(regexp, os.path.basename(path))
200 if res:
201 groups = res.groups()
202 if groups[0] is not None:
203 temperature = float(res.groups()[0])
204 else:
205 temperature = float(res.groups()[1])
206 else:
207
208 infile = file(path,'r')
209 datastring = infile.read()
210 infile.close()
211
212 res = re.search(r'^#+ start data\s*(?:#.*\s+)*', datastring, re.M)
213
214 if res:
215 start_data = res.end()
216 else:
217 res = re.search(r'^[^#]', datastring, re.M)
218 if res:
219 start_data = res.start()
220 else:
221 start_data = 0
222 header = datastring[:start_data]
223
224 regexp = r"\b(?:temp|temperature|T)\ *=\ *(%(f)s)\b" % rx
225 res = re.search(regexp, header)
226 if res:
227 temperature = float(res.groups()[0])
228
229 if temperature <= 0: temperature = 300.0
230 newdatasets.append([temperature, path])
231
232
233
234 self.datasets.extend(newdatasets)
235 self.fillList()
236 return
237
239 """Delete selected files from the list."""
240 idxlist = []
241 item = self.listCtrlFiles.GetFirstSelected()
242 while item != -1:
243 idxlist.append(item)
244 item = self.listCtrlFiles.GetNextSelected(item)
245
246 idxlist.reverse()
247 for item in idxlist:
248 del self.datasets[item]
249 self.fillList()
250 return
251
253 """Sort by temperature."""
254 column = event.GetColumn()
255
256 if column == 0:
257 sortkey = lambda tf : float(tf[0])
258
259 elif column == 1:
260 filenames = [f for t, f in self.datasets]
261 numericStringSort(filenames)
262 order = dict(zip(filenames, range(len(filenames))))
263 sortkey = lambda tf : order[tf[1]]
264
265 else:
266 return
267 self.datasets.sort(key=sortkey, reverse=self.reverse)
268 self.reverse = not self.reverse
269 self.fillList()
270 return
271
272
274 """Fill the list with the datasets."""
275 self.listCtrlFiles.DeleteAllItems()
276 names = [pair[1] for pair in self.datasets]
277 cp = os.path.commonprefix(names)
278
279 idx = cp.rfind(os.path.sep)
280 if idx == -1: idx = len(cp)
281 for temperature, filename in self.datasets:
282 shortname = "..." + filename[idx:]
283 index = self.listCtrlFiles.InsertStringItem(sys.maxint, str(temperature))
284 self.listCtrlFiles.SetStringItem(index, 1, shortname)
285 return
286
287
289 """Set the current fit when the tree selection changes."""
290 nodetype = self.treeCtrlMain.GetNodeType(node)
291 if nodetype == 'fit':
292 self.fit = self.treeCtrlMain.GetControlData(node)
293 self.refresh()
294 return
295
296
298 """Block out OK button if there is no fit.
299
300 This also blocks OK if the fit has no datasets or structures.
301 """
302
303
304 node = None
305 nodetype = None
306 selections = self.treeCtrlMain.GetSelections()
307 if selections:
308 node = selections[0]
309 nodetype = self.treeCtrlMain.GetNodeType(node)
310
311 if node and nodetype == "fit" \
312 and self.fit and self.fit.hasDataSets() \
313 and self.fit.hasStructures():
314 self.goButton.Enable()
315 else:
316 self.goButton.Enable(False)
317 return
318
319
320
321 __id__ = "$Id: temperatureseriespanel.py 2980 2009-04-02 00:14:33Z juhas $"
322