Statistiques
| Révision :

root / ase / gui / progress.py @ 20

Historique | Voir | Annoter | Télécharger (12,33 ko)

1 1 tkerber
# encoding: utf-8
2 1 tkerber
3 1 tkerber
import gtk
4 1 tkerber
import numpy as np
5 1 tkerber
from ase.gui.widgets import pack, oops, AseGuiCancelException
6 1 tkerber
import sys
7 1 tkerber
import re
8 1 tkerber
import time
9 1 tkerber
10 1 tkerber
11 1 tkerber
class DummyProgressIndicator:
12 1 tkerber
    def begin(self, **kwargs):
13 1 tkerber
        pass
14 1 tkerber
15 1 tkerber
    def end(self):
16 1 tkerber
        pass
17 1 tkerber
18 1 tkerber
class DefaultProgressIndicator(gtk.Window):
19 1 tkerber
    "Window for reporting progress."
20 1 tkerber
    waittime = 3  # Time (in sec) after which a progress bar appears.
21 1 tkerber
    def __init__(self):
22 1 tkerber
        gtk.Window.__init__(self)
23 1 tkerber
        self.set_title("Progress")
24 1 tkerber
        self.globalbox = gtk.VBox()
25 1 tkerber
26 1 tkerber
        # Scaling deformation progress frame
27 1 tkerber
        self.scalebox = gtk.VBox()
28 1 tkerber
        self.scaleframe = gtk.Frame("Scaling deformation:")
29 1 tkerber
        vbox = gtk.VBox()
30 1 tkerber
        self.scaleframe.add(vbox)
31 1 tkerber
        pack(self.scalebox, [self.scaleframe])
32 1 tkerber
        pack(self.scalebox, gtk.Label(""))
33 1 tkerber
34 1 tkerber
        self.label_scale_stepno_format = "Step number %s of %s."
35 1 tkerber
        self.label_scale_stepno = gtk.Label(
36 1 tkerber
            self.label_scale_stepno_format % ("-" , "-"))
37 1 tkerber
        pack(vbox, [self.label_scale_stepno])
38 1 tkerber
        self.scale_progress = gtk.ProgressBar()
39 1 tkerber
        self.scale_progress.modify_bg(gtk.STATE_PRELIGHT,
40 1 tkerber
                                      gtk.gdk.color_parse('#00AA00'))
41 1 tkerber
        pack(vbox, [self.scale_progress])
42 1 tkerber
43 1 tkerber
        vbox.show()
44 1 tkerber
        self.scaleframe.show()
45 1 tkerber
        self.globalbox.pack_start(self.scalebox)
46 1 tkerber
47 1 tkerber
        # Minimization progress frame
48 1 tkerber
        self.minbox = gtk.VBox()  # Box containing frame and spacing
49 1 tkerber
        self.minframe = gtk.Frame("Energy minimization:")
50 1 tkerber
        vbox = gtk.VBox()         # Box containing the frames content.
51 1 tkerber
        self.minframe.add(vbox)
52 1 tkerber
        pack(self.minbox, [self.minframe])
53 1 tkerber
        pack(self.minbox, gtk.Label(""))
54 1 tkerber
55 1 tkerber
        self.label_min_stepno = gtk.Label("-")
56 1 tkerber
        pack(vbox, [gtk.Label("Step number: "), self.label_min_stepno])
57 1 tkerber
        lbl = gtk.Label()
58 1 tkerber
        lbl.set_markup("F<sub>max</sub>: ")
59 1 tkerber
        self.minimize_progress = gtk.ProgressBar()
60 1 tkerber
        pack(vbox, [lbl, self.minimize_progress])
61 1 tkerber
        self.label_min_fmax = gtk.Label("-")
62 1 tkerber
        lbl = gtk.Label()
63 1 tkerber
        lbl.set_markup("Convergence criterion: F<sub>max</sub> = ")
64 1 tkerber
        pack(vbox, [lbl, self.label_min_fmax])
65 1 tkerber
        self.label_min_maxsteps = gtk.Label("-")
66 1 tkerber
        pack(vbox, [gtk.Label("Max. number of steps: "),
67 1 tkerber
                    self.label_min_maxsteps])
68 1 tkerber
69 1 tkerber
        vbox.show()
70 1 tkerber
        self.minframe.show()
71 1 tkerber
        self.globalbox.pack_start(self.minbox)
72 1 tkerber
        self.globalbox.show()
73 1 tkerber
        self.add(self.globalbox)
74 1 tkerber
75 1 tkerber
        # Make the cancel button
76 1 tkerber
        self.cancelbut = gtk.Button(stock=gtk.STOCK_CANCEL)
77 1 tkerber
        self.cancelbut.connect('clicked', self.cancel)
78 1 tkerber
        pack(self.globalbox, [self.cancelbut], end=True, bottom=True)
79 1 tkerber
80 1 tkerber
    def begin(self, mode=None, algo=None, fmax=None, steps=None,
81 1 tkerber
              scalesteps=None):
82 1 tkerber
        self.mode = mode
83 1 tkerber
        # Hide all mode-specific boxes
84 1 tkerber
        self.scalebox.hide()
85 1 tkerber
        self.minbox.hide()
86 1 tkerber
        # Activate any relevant box
87 1 tkerber
        if mode == "scale" or mode == "scale/min":
88 1 tkerber
            self.scalesteps = int(scalesteps)
89 1 tkerber
            self.scalebox.show()
90 1 tkerber
            self.set_scale_progress(0, init=True)
91 1 tkerber
        if mode == "min" or mode == "scale/min":
92 1 tkerber
            # It is a minimization.
93 1 tkerber
            self.minbox.show()
94 1 tkerber
            self.label_min_stepno.set_text("-")
95 1 tkerber
            self.label_min_fmax.set_text("%.3f" % (fmax,))
96 1 tkerber
            self.label_min_maxsteps.set_text(str(steps))
97 1 tkerber
            self.minimize_progress.set_fraction(0)
98 1 tkerber
            self.minimize_progress.set_text("unknown")
99 1 tkerber
        # Record starting time
100 1 tkerber
        self.starttime = time.time()
101 1 tkerber
        self.active = None  # Becoming active
102 1 tkerber
        self.raisecancelexception = False
103 1 tkerber
104 1 tkerber
    def end(self):
105 1 tkerber
        self.hide()
106 1 tkerber
        self.active = False
107 1 tkerber
108 1 tkerber
    def activity(self):
109 1 tkerber
        "Register that activity occurred."
110 1 tkerber
        if self.active is None and time.time() > self.starttime + self.waittime:
111 1 tkerber
            # This has taken so long that a progress bar is needed.
112 1 tkerber
            self.show()
113 1 tkerber
            self.active = True
114 1 tkerber
        # Allow GTK to update display
115 1 tkerber
        while gtk.events_pending():
116 1 tkerber
            gtk.main_iteration()
117 1 tkerber
        if self.raisecancelexception:
118 1 tkerber
            self.cancelbut.set_sensitive(True)
119 1 tkerber
            raise AseGuiCancelException
120 1 tkerber
121 1 tkerber
    def cancel(self, widget):
122 1 tkerber
        print "CANCEL pressed."
123 1 tkerber
        # We cannot raise the exception here, as this function is
124 1 tkerber
        # called by the GTK main loop.
125 1 tkerber
        self.raisecancelexception = True
126 1 tkerber
        self.cancelbut.set_sensitive(False)
127 1 tkerber
128 1 tkerber
    def set_scale_progress(self, step, init=False):
129 1 tkerber
        "Set the step number in scaling deformation."
130 1 tkerber
        self.label_scale_stepno.set_text(
131 1 tkerber
            self.label_scale_stepno_format % (step, self.scalesteps))
132 1 tkerber
        percent = 1.0 * step / self.scalesteps
133 1 tkerber
        self.scale_progress.set_fraction(percent)
134 1 tkerber
        self.scale_progress.set_text("%i%%" % (round(100*percent),))
135 1 tkerber
        if not init:
136 1 tkerber
            self.activity()
137 1 tkerber
138 1 tkerber
    def logger_write(self, line):
139 1 tkerber
        if self.mode == "min" or self.mode == "scale/min":
140 1 tkerber
            # Update the minimization progress bar.
141 1 tkerber
            w = line.split()
142 1 tkerber
            fmax = float(w[-1])
143 1 tkerber
            step = w[1]
144 1 tkerber
            self.minimize_progress.set_fraction(fmax / 1.0)
145 1 tkerber
            self.minimize_progress.set_text(w[-1])
146 1 tkerber
            self.label_min_stepno.set_text(step)
147 1 tkerber
        else:
148 1 tkerber
            raise RuntimeError(
149 1 tkerber
                "ProgressIndicator.logger_write called unexpectedly")
150 1 tkerber
        self.activity()
151 1 tkerber
152 1 tkerber
    def get_logger_stream(self):
153 1 tkerber
        return LoggerStream(self)
154 1 tkerber
155 1 tkerber
156 1 tkerber
class GpawProgressIndicator(DefaultProgressIndicator):
157 1 tkerber
    "Window for reporting GPAW progress."
158 1 tkerber
159 1 tkerber
    def __init__(self):
160 1 tkerber
        DefaultProgressIndicator.__init__(self)
161 1 tkerber
162 1 tkerber
        # GPAW progress frame
163 1 tkerber
        self.gpawframe = gtk.Frame("GPAW progress:")
164 1 tkerber
        vbox = self.gpawvbox = gtk.VBox()
165 1 tkerber
        self.gpawframe.add(vbox)
166 1 tkerber
        self.table = gtk.Table(1, 2)
167 1 tkerber
        self.tablerows = 0
168 1 tkerber
        pack(vbox, self.table)
169 1 tkerber
        self.status = gtk.Label("-")
170 1 tkerber
        self.tablepack([gtk.Label("Status: "), self.status])
171 1 tkerber
        self.iteration = gtk.Label("-")
172 1 tkerber
        self.tablepack([gtk.Label("Iteration: "), self.iteration])
173 1 tkerber
        self.tablepack([gtk.Label("")])
174 1 tkerber
        lbl = gtk.Label()
175 1 tkerber
        lbl.set_markup("log<sub>10</sub>(change):")
176 1 tkerber
        self.tablepack([gtk.Label(""), lbl])
177 1 tkerber
        self.wfs_progress = gtk.ProgressBar()
178 1 tkerber
        self.tablepack([gtk.Label("Wave functions: "), self.wfs_progress])
179 1 tkerber
        self.dens_progress = gtk.ProgressBar()
180 1 tkerber
        self.tablepack([gtk.Label("Density: "), self.dens_progress])
181 1 tkerber
        self.energy_progress = gtk.ProgressBar()
182 1 tkerber
        self.tablepack([gtk.Label("Energy: "), self.energy_progress])
183 1 tkerber
        self.tablepack([gtk.Label("")])
184 1 tkerber
        self.versionlabel = gtk.Label("")
185 1 tkerber
        self.tablepack([gtk.Label("GPAW version: "), self.versionlabel])
186 1 tkerber
        self.natomslabel = gtk.Label("")
187 1 tkerber
        self.tablepack([gtk.Label("Number of atoms: "), self.natomslabel])
188 1 tkerber
        self.memorylabel = gtk.Label("N/A")
189 1 tkerber
        self.tablepack([gtk.Label("Memory estimate: "), self.memorylabel])
190 1 tkerber
        self.globalbox.pack_start(self.gpawframe)
191 1 tkerber
        self.gpawframe.show()
192 1 tkerber
193 1 tkerber
        vbox.show()
194 1 tkerber
        self.active = False
195 1 tkerber
196 1 tkerber
    def tablepack(self, widgets):
197 1 tkerber
        self.tablerows += 1
198 1 tkerber
        self.table.resize(self.tablerows, 2)
199 1 tkerber
        for i, w in enumerate(widgets):
200 1 tkerber
            self.table.attach(w, i, i+1, self.tablerows-1, self.tablerows)
201 1 tkerber
            if hasattr(w, "set_alignment"):
202 1 tkerber
                w.set_alignment(0, 0.5)
203 1 tkerber
            w.show()
204 1 tkerber
205 1 tkerber
    def begin(self, **kwargs):
206 1 tkerber
        DefaultProgressIndicator.begin(self, **kwargs)
207 1 tkerber
        # Set GPAW specific stuff.
208 1 tkerber
        self.active = True
209 1 tkerber
        self.oldenergy = None
210 1 tkerber
        self.poscount = None
211 1 tkerber
        self.reset_gpaw_bars()
212 1 tkerber
        # With GPAW, all calculations are slow: Show progress window
213 1 tkerber
        # immediately.
214 1 tkerber
        self.show()
215 1 tkerber
        while gtk.events_pending():
216 1 tkerber
            gtk.main_iteration()
217 1 tkerber
218 1 tkerber
    def reset_gpaw_bars(self):
219 1 tkerber
        for lbl in (self.status, self.iteration):
220 1 tkerber
            lbl.set_text("-")
221 1 tkerber
        for bar in (self.wfs_progress, self.dens_progress,
222 1 tkerber
                    self.energy_progress):
223 1 tkerber
            bar.set_fraction(0.0)
224 1 tkerber
            bar.set_text("No info")
225 1 tkerber
226 1 tkerber
    def gpaw_write(self, txt):
227 1 tkerber
        #if not self.active:
228 1 tkerber
        #    self.begin()
229 1 tkerber
        sys.stdout.write(txt)
230 1 tkerber
        versearch = re.search("\|[ |_.]+([0-9]+\.[0-9]+\.[0-9]+)", txt)
231 1 tkerber
        if versearch:
232 1 tkerber
            # Starting a gpaw calculation.
233 1 tkerber
            self.versionlabel.set_text(versearch.group(1))
234 1 tkerber
            self.status.set_text("Initializing")
235 1 tkerber
        elif txt.startswith("Positions:"):
236 1 tkerber
            # Start counting atoms
237 1 tkerber
            self.poscount = True
238 1 tkerber
            self.reset_gpaw_bars()
239 1 tkerber
            self.status.set_text("Starting calculation")
240 1 tkerber
            self.oldenergy = None
241 1 tkerber
        elif txt.strip() == "":
242 1 tkerber
            # Stop counting atoms
243 1 tkerber
            self.poscount = False
244 1 tkerber
        elif self.poscount:
245 1 tkerber
            # Count atoms.
246 1 tkerber
            w = txt.split()
247 1 tkerber
            assert(len(w) == 5)
248 1 tkerber
            self.natoms = int(w[0]) + 1
249 1 tkerber
            self.natomslabel.set_text(str(self.natoms))
250 1 tkerber
        elif txt.startswith("iter:"):
251 1 tkerber
            # Found iteration line.
252 1 tkerber
            wfs = txt[self.wfs_idx:self.density_idx].strip()
253 1 tkerber
            dens = txt[self.density_idx:self.energy_idx].strip()
254 1 tkerber
            energy = txt[self.energy_idx:self.fermi_idx].strip()
255 1 tkerber
            if wfs:
256 1 tkerber
                p = fraction(float(wfs), -9.0)
257 1 tkerber
                self.wfs_progress.set_fraction(p)
258 1 tkerber
                self.wfs_progress.set_text(wfs)
259 1 tkerber
            if dens:
260 1 tkerber
                p = fraction(float(dens), -4.0)
261 1 tkerber
                self.dens_progress.set_fraction(p)
262 1 tkerber
                self.dens_progress.set_text(dens)
263 1 tkerber
            if energy:
264 1 tkerber
                if self.oldenergy is None:
265 1 tkerber
                    self.oldenergy = float(energy)
266 1 tkerber
                else:
267 1 tkerber
                    de = abs(self.oldenergy - float(energy))
268 1 tkerber
                    self.oldenergy = float(energy)
269 1 tkerber
                    if de > 1e-10:
270 1 tkerber
                        de = np.log10(de/self.natoms)
271 1 tkerber
                        p = fraction(de, -3.0)
272 1 tkerber
                        self.energy_progress.set_fraction(p)
273 1 tkerber
                        self.energy_progress.set_text("%.1f" % de)
274 1 tkerber
                    else:
275 1 tkerber
                        self.energy_progress.set_fraction(1)
276 1 tkerber
                        self.energy_progress.set_text("unchanged")
277 1 tkerber
            words = txt.split()
278 1 tkerber
            self.iteration.set_text(words[1])
279 1 tkerber
        elif (-1 < txt.find("WFS") < txt.find("Density") < txt.find("Energy")
280 1 tkerber
               < txt.find("Fermi")):
281 1 tkerber
            # Found header of convergence table
282 1 tkerber
            self.wfs_idx = txt.find("WFS")
283 1 tkerber
            self.density_idx = txt.find("Density")
284 1 tkerber
            self.energy_idx = txt.find("Energy")
285 1 tkerber
            self.fermi_idx = txt.find("Fermi")
286 1 tkerber
            self.status.set_text("Self-consistency loop")
287 1 tkerber
            self.iteration.set_text("0")
288 1 tkerber
        elif txt.find("Converged After") != -1:
289 1 tkerber
            # SCF loop has converged.
290 1 tkerber
            words = txt.split()
291 1 tkerber
            self.status.set_text("Calculating forces")
292 1 tkerber
            self.iteration.set_text(words[2]+" (converged)")
293 1 tkerber
        elif -1 < txt.find("Calculator") < txt.find("MiB"):
294 1 tkerber
            # Memory estimate
295 1 tkerber
            words = txt.split()
296 1 tkerber
            self.memorylabel.set_text(words[1]+" "+words[2])
297 1 tkerber
        self.activity()
298 1 tkerber
299 1 tkerber
    def get_gpaw_stream(self):
300 1 tkerber
        return GpawStream(self)
301 1 tkerber
302 1 tkerber
303 1 tkerber
304 1 tkerber
class LoggerStream:
305 1 tkerber
    "A file-like object feeding minimizer logs to GpawProgressWindow."
306 1 tkerber
    def __init__(self, progresswindow):
307 1 tkerber
        self.window = progresswindow
308 1 tkerber
309 1 tkerber
    def write(self, txt):
310 1 tkerber
        self.window.logger_write(txt)
311 1 tkerber
312 1 tkerber
    def flush(self):
313 1 tkerber
        pass
314 1 tkerber
315 1 tkerber
316 1 tkerber
class GpawStream:
317 1 tkerber
    "A file-like object feeding GPAWs txt file to GpawProgressWindow."
318 1 tkerber
    def __init__(self, progresswindow):
319 1 tkerber
        self.window = progresswindow
320 1 tkerber
321 1 tkerber
    def write(self, txt):
322 1 tkerber
        if txt == "":
323 1 tkerber
            return
324 1 tkerber
        endline = txt[-1] == '\n'
325 1 tkerber
        if endline:
326 1 tkerber
            txt = txt[:-1]
327 1 tkerber
        lines = txt.split("\n")
328 1 tkerber
        if endline:
329 1 tkerber
            for l in lines:
330 1 tkerber
                self.window.gpaw_write(l+'\n')
331 1 tkerber
        else:
332 1 tkerber
            for l in lines[:-1]:
333 1 tkerber
                self.window.gpaw_write(l+'\n')
334 1 tkerber
            self.window.gpaw_write(lines[-1])
335 1 tkerber
336 1 tkerber
    def flush(self):
337 1 tkerber
        pass
338 1 tkerber
339 1 tkerber
def fraction(value, maximum):
340 1 tkerber
    p = value/maximum
341 1 tkerber
    if p < 0.0:
342 1 tkerber
        return 0.0
343 1 tkerber
    elif p > 1.0:
344 1 tkerber
        return 1.0
345 1 tkerber
    else:
346 1 tkerber
        return p
347 1 tkerber