root / ase / gui / progress.py @ 4
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 |