Skip to content

Commit d0ee140

Browse files
committed
Update OCL modules to use logging_utils.
1 parent de2e62b commit d0ee140

File tree

8 files changed

+219
-260
lines changed

8 files changed

+219
-260
lines changed

examples/Generator/inverse_trainer_xyz.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
from ppafm.ocl.AFMulator import AFMulator
1212
from ppafm.ocl.oclUtils import init_env
1313

14+
# from ppafm.logging_utils import configure_logging
15+
# configure_logging(log_performance=True)
16+
1417

1518
class ExampleTrainer(InverseAFMtrainer):
1619
# We override this callback method in order to augment the samples with randomized tip distance and tilt
@@ -57,7 +60,6 @@ def on_sample_start(self):
5760
QZs=[[0.1, 0, -0.1, 0]],
5861
Qs=[[-10, 20, -10, 0]],
5962
)
60-
# trainer.bRuntime = True
6163

6264
# Augment molecule list with rotations and shuffle
6365
trainer.augment_with_rotations_entropy(sphereTangentSpace(n=100), 30)

examples/pyridineDensOverlap/run_gpu.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
import ppafm.ocl.field as FFcl
1010
import ppafm.ocl.oclUtils as oclu
11+
from ppafm.logging_utils import configure_logging
1112
from ppafm.ocl.AFMulator import AFMulator
1213

1314
# Initialize an OpenCL environment. You can change i_platform to select the device to use
1415
oclu.init_env(i_platform=0)
15-
FFcl.bRuntime = True # Print timings
16+
configure_logging(log_performance=True) # Print timings
1617

1718
# Load all input files
1819
rho_tip, xyzs_tip, Zs_tip = FFcl.TipDensity.from_file("tip/density_CO.xsf")

ppafm/cli/gui/ppafm_gui.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,6 @@ def __init__(self, input_files=None, device=0, verbose=0):
140140
if verbose > 0:
141141
print(f"Verbosity level = {verbose}")
142142
self.verbose = verbose
143-
self.afmulator.verbose = verbose
144-
self.afmulator.forcefield.verbose = verbose
145-
self.afmulator.scanner.verbose = verbose
146-
FFcl.bRuntime = verbose > 1
147-
self.afmulator.bRuntime = verbose > 1
148143

149144
# --- init QtMain
150145
QtWidgets.QMainWindow.__init__(self)

ppafm/logging_utils.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import logging
22
import os
33
import sys
4-
from copy import deepcopy
54
from typing import Optional, Union
65

76
# Setup the root logger for the ppafm package. All other loggers will be derived from this one.
@@ -12,7 +11,9 @@
1211

1312
# Setup another logger for performance benchmarking
1413
_perf_logger = logging.getLogger("ppafm.perf")
14+
_perf_logger.propagate = False
1515
_perf_log_format = "[%(asctime)s - %(name)s] %(message)s"
16+
_perf_log_enabled = False
1617

1718

1819
def configure_logging(
@@ -40,6 +41,7 @@ def configure_logging(
4041
global _log_handler
4142
global _log_format
4243
global _log_path
44+
global _perf_log_enabled
4345

4446
if level is None:
4547
try:
@@ -67,14 +69,19 @@ def configure_logging(
6769
if log_performance is None:
6870
log_performance = "PPAFM_LOG_PERFORMANCE" in os.environ
6971
if log_performance:
70-
perf_log_handler = deepcopy(_log_handler)
72+
if _log_path is None:
73+
perf_log_handler = logging.StreamHandler(sys.stdout)
74+
else:
75+
perf_log_handler = logging.FileHandler(_log_path)
7176
perf_log_handler.setFormatter(logging.Formatter(fmt=_perf_log_format))
7277
for handler in _perf_logger.handlers:
7378
_perf_logger.removeHandler(handler)
7479
_perf_logger.addHandler(perf_log_handler)
7580
_perf_logger.setLevel(logging.INFO)
81+
_perf_log_enabled = True
7682
else:
7783
_perf_logger.setLevel(logging.CRITICAL)
84+
_perf_log_enabled = False
7885

7986
if format is None:
8087
try:
@@ -101,6 +108,10 @@ def get_perf_logger(name: str) -> logging.Logger:
101108
return _perf_logger.getChild(name)
102109

103110

111+
def perf_log_enabled() -> bool:
112+
return _perf_log_enabled
113+
114+
104115
class ProgressLogger:
105116
"""Print gradual progress as a percent number."""
106117

ppafm/ocl/AFMulator.py

Lines changed: 30 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import numpy as np
88

99
from .. import common, elements, io
10+
from ..logging_utils import get_logger, get_perf_logger, perf_log_enabled
1011
from ..PPPlot import plotImages
1112
from . import field as FFcl
1213
from . import oclUtils as oclu
@@ -15,6 +16,9 @@
1516

1617
VALID_SIZES = np.array([16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048])
1718

19+
logger = get_logger("AFMulator")
20+
perf_logger = get_perf_logger("AFMulator")
21+
1822

1923
class AFMulator:
2024
"""
@@ -67,14 +71,12 @@ class AFMulator:
6771
"""
6872

6973
bMergeConv = False # Should we use merged kernel relaxStrokesTilted_convZ or two separated kernells ( relaxStrokesTilted, convolveZ )
70-
bRuntime = False # Print timings during execution
7174

7275
# --- Relaxation
7376
relaxParams = [0.5, 0.1, 0.1 * 0.2, 0.1 * 5.0] # (dt,damp, .., .. ) parameters of relaxation, in the moment just dt and damp are used
7477

7578
# --- Output
7679
bSaveFF = False # Save debug ForceField as .xsf
77-
verbose = 0 # Print information during excecution
7880

7981
# ==================== Methods =====================
8082

@@ -161,15 +163,13 @@ def eval(self, xyzs, Zs, qs, rho_sample=None, sample_lvec=None, rot=np.eye(3), r
161163
Returns:
162164
X: np.ndarray. Output AFM images. If input X is not None, this is the same array object as X with values overwritten.
163165
"""
164-
if self.bRuntime:
165-
t0 = time.perf_counter()
166+
t0 = time.perf_counter()
166167
self.prepareFF(xyzs, Zs, qs, rho_sample, sample_lvec, rot, rot_center, REAs)
167168
self.prepareScanner()
168169
X = self.evalAFM(X)
169170
if plot_to_dir:
170171
self.plot_images(X, outdir=plot_to_dir)
171-
if self.bRuntime:
172-
print("runtime(AFMulator.eval) [s]: ", time.perf_counter() - t0)
172+
perf_logger.info(f"eval [s]: {time.perf_counter() - t0}")
173173
return X
174174

175175
def __call__(self, *args, **kwargs):
@@ -186,8 +186,7 @@ def eval_(self, mol):
186186
def setLvec(self, lvec=None, pixPerAngstrome=None):
187187
"""Set forcefield lattice vectors. If lvec is not given it is inferred from the scan window."""
188188

189-
if self.bRuntime:
190-
t0 = time.perf_counter()
189+
t0 = time.perf_counter()
191190

192191
if pixPerAngstrome is not None:
193192
self.pixPerAngstrome = pixPerAngstrome
@@ -207,14 +206,12 @@ def setLvec(self, lvec=None, pixPerAngstrome=None):
207206
FEin_shape = self.forcefield.nDim if (self._old_nDim != self.forcefield.nDim).any() else None
208207
self.scanner.prepareBuffers(lvec=self.lvec, FEin_shape=FEin_shape)
209208

210-
if self.bRuntime:
211-
print("runtime(AFMulator.setLvec) [s]: ", time.perf_counter() - t0)
209+
perf_logger.info(f"setLvec [s]: {time.perf_counter() - t0}")
212210

213211
def setScanWindow(self, scan_window=None, scan_dim=None, df_steps=None):
214212
"""Set scanner scan window."""
215213

216-
if self.bRuntime:
217-
t0 = time.perf_counter()
214+
t0 = time.perf_counter()
218215

219216
if scan_window is not None:
220217
self.scan_window = scan_window
@@ -241,8 +238,7 @@ def setScanWindow(self, scan_window=None, scan_dim=None, df_steps=None):
241238
self.scanner.updateBuffers(WZconv=self.dfWeight)
242239
self.scanner.preparePosBasis(start=self.scan_window[0][:2], end=self.scan_window[1][:2])
243240

244-
if self.bRuntime:
245-
print("runtime(AFMulator.setScanWindow) [s]: ", time.perf_counter() - t0)
241+
perf_logger.info(f"setScanWindow [s]: {time.perf_counter() - t0}")
246242

247243
def setRho(self, rho=None, sigma=0.71, B_pauli=1.0):
248244
"""Set tip charge distribution.
@@ -252,8 +248,7 @@ def setRho(self, rho=None, sigma=0.71, B_pauli=1.0):
252248
sigma: float. Tip charge density distribution when rho is a dict.
253249
B_pauli: float. Pauli repulsion exponent for tip density when using FDBM.
254250
"""
255-
if self.bRuntime:
256-
t0 = time.perf_counter()
251+
t0 = time.perf_counter()
257252
if rho is not None:
258253
self.sigma = sigma
259254
self.B_pauli = B_pauli
@@ -270,8 +265,7 @@ def setRho(self, rho=None, sigma=0.71, B_pauli=1.0):
270265
if not isinstance(rho, TipDensity):
271266
raise ValueError(f"rho should of type `TipDensity`, but got `{type(rho)}`")
272267
self.rho = rho
273-
if self.verbose > 0:
274-
print("AFMulator.setRho: Preparing buffers")
268+
logger.debug("setRho: Preparing buffers")
275269
if not np.allclose(B_pauli, 1.0):
276270
rho_power = self.rho.power_positive(p=self.B_pauli, in_place=False)
277271
if self.minimize_memory:
@@ -282,13 +276,12 @@ def setRho(self, rho=None, sigma=0.71, B_pauli=1.0):
282276
self._rho = None
283277
self.rho = None
284278
if self.forcefield.rho is not None:
285-
if self.verbose > 0:
286-
print("AFMulator.setRho: Releasing buffers")
279+
logger.debug("setRho: Releasing buffers")
287280
self.forcefield.rho.release()
288281
self.forcefield.rho = None
289-
if self.bRuntime:
282+
if perf_log_enabled():
290283
self.forcefield.queue.finish()
291-
print("runtime(AFMulator.setRho) [s]: ", time.perf_counter() - t0)
284+
perf_logger.info(f"setRho [s]: {time.perf_counter() - t0}")
292285

293286
def setBPauli(self, B_pauli=1.0):
294287
"""Set Pauli repulsion exponent used in FDBM."""
@@ -300,22 +293,18 @@ def setRhoDelta(self, rho_delta=None):
300293
Arguments:
301294
rho_delta: :class:`.TipDensity` or None. Tip electron delta-density. If None, the existing density is deleted.
302295
"""
303-
if self.bRuntime:
304-
t0 = time.perf_counter()
296+
t0 = time.perf_counter()
305297
self.rho_delta = rho_delta
306298
if self.rho_delta is not None:
307299
if not isinstance(rho_delta, TipDensity):
308300
raise ValueError(f"rho_delta should of type `TipDensity`, but got `{type(rho_delta)}`")
309-
if self.verbose > 0:
310-
print("AFMulator.setRhoDelta: Preparing buffers")
301+
logger.debug("setRhoDelta: Preparing buffers")
311302
self.forcefield.prepareBuffers(rho_delta=self.rho_delta, bDirect=True, minimize_memory=self.minimize_memory)
312303
elif self.forcefield.rho_delta is not None:
313-
if self.verbose > 0:
314-
print("AFMulator.setRhoDelta: Releasing buffers")
304+
logger.debug("setRhoDelta: Releasing buffers")
315305
self.forcefield.rho_delta.release()
316306
self.forcefield.rho_delta = None
317-
if self.bRuntime:
318-
print("runtime(AFMulator.setRhoDelta) [s]: ", time.perf_counter() - t0)
307+
perf_logger.info(f"setRhoDelta [s]: {time.perf_counter() - t0}")
319308

320309
def setQs(self, Qs, QZs):
321310
"""Set tip point charges."""
@@ -348,18 +337,14 @@ def prepareFF(self, xyzs, Zs, qs, rho_sample=None, sample_lvec=None, rot=np.eye(
348337
rot_center: np.ndarray of shape (3,). Center for rotation. Defaults to center of atom coordinates.
349338
REAs: np.ndarray of shape (num_atoms, 4). Lennard Jones interaction parameters. Calculated automatically if None.
350339
"""
351-
if self.bRuntime:
352-
t0 = time.perf_counter()
340+
t0 = time.perf_counter()
353341

354342
# Check if the scan window extends over any non-periodic boundaries and issue a warning if it does
355343
self.check_scan_window()
356344

357345
# (Re)initialize force field if the size of the grid changed since last run.
358346
if (self._old_nDim != self.forcefield.nDim).any():
359-
if self.verbose > 0:
360-
print("(Re)initializing force field buffers.")
361-
if self.verbose > 1:
362-
print(f"old nDim: {self._old_nDim}, new nDim: {self.forcefield.nDim}")
347+
logger.debug(f"(Re)initializing force field buffers. Old nDim: {self._old_nDim}, new nDim: {self.forcefield.nDim}")
363348
self.forcefield.tryReleaseBuffers()
364349
if self._rho is not None:
365350
# The grid size changed so we need to recompute/reinterpolate the tip density grid
@@ -441,14 +426,12 @@ def prepareFF(self, xyzs, Zs, qs, rho_sample=None, sample_lvec=None, rot=np.eye(
441426
if self.bSaveFF:
442427
self.saveFF()
443428

444-
if self.bRuntime:
445-
print("runtime(AFMulator.prepareFF) [s]: ", time.perf_counter() - t0)
429+
perf_logger.info(f"prepareFF [s]: {time.perf_counter() - t0}")
446430

447431
def prepareScanner(self):
448432
"""Prepare scanner. Run after preparing force field."""
449433

450-
if self.bRuntime:
451-
t0 = time.perf_counter()
434+
t0 = time.perf_counter()
452435

453436
# Copy forcefield array to scanner buffer
454437
self.scanner.updateFEin(self.forcefield.cl_FE)
@@ -459,8 +442,7 @@ def prepareScanner(self):
459442
# Prepare tip position array
460443
self.scanner.setScanRot(self.pos0, rot=np.eye(3), tipR0=self.tipR0)
461444

462-
if self.bRuntime:
463-
print("runtime(AFMulator.prepareScanner) [s]: ", time.perf_counter() - t0)
445+
perf_logger.info(f"prepareScanner [s]: {time.perf_counter() - t0}")
464446

465447
def evalAFM(self, X=None):
466448
"""
@@ -474,8 +456,7 @@ def evalAFM(self, X=None):
474456
X: np.ndarray. Output AFM images. If input X is not None, this is the same array object as X with values overwritten.
475457
"""
476458

477-
if self.bRuntime:
478-
t0 = time.perf_counter()
459+
t0 = time.perf_counter()
479460

480461
if self.bMergeConv:
481462
FEout = self.scanner.run_relaxStrokesTilted_convZ()
@@ -493,8 +474,7 @@ def evalAFM(self, X=None):
493474
)
494475
X[:, :, :] = FEout[:, :, :, 2]
495476

496-
if self.bRuntime:
497-
print("runtime(AFMulator.evalAFM) [s]: ", time.perf_counter() - t0)
477+
perf_logger.info(f"evalAFM [s]: {time.perf_counter() - t0}")
498478

499479
return X
500480

@@ -597,15 +577,13 @@ def saveFF(self):
597577
FFx.flat[mask] *= (Fbound / Fr).flat[mask]
598578
FFy.flat[mask] *= (Fbound / Fr).flat[mask]
599579
FFz.flat[mask] *= (Fbound / Fr).flat[mask]
600-
if self.verbose > 0:
601-
print("FF.shape ", FF.shape)
580+
logger.debug(f"FF.shape {FF.shape}")
602581
self.saveDebugXSF_FF(self.saveFFpre + "FF_x.xsf", FFx)
603582
self.saveDebugXSF_FF(self.saveFFpre + "FF_y.xsf", FFy)
604583
self.saveDebugXSF_FF(self.saveFFpre + "FF_z.xsf", FFz)
605584

606585
def saveDebugXSF_FF(self, fname, F):
607-
if self.verbose > 0:
608-
print("saveDebugXSF : ", fname)
586+
logger.debug(f"saveDebugXSF: {fname}")
609587
io.saveXSF(fname, F, self.lvec)
610588

611589
def check_scan_window(self):
@@ -621,8 +599,8 @@ def check_scan_window(self):
621599
scan_start -= self.tipR0[2]
622600
scan_end -= self.tipR0[2]
623601
if (scan_start < lvec_start) or (scan_end > lvec_end):
624-
print(
625-
f"Warning: The edge of the scan window in {dim} dimension is very close or extends over "
602+
logger.warning(
603+
f"The edge of the scan window in {dim} dimension is very close or extends over "
626604
f"the boundary of the force-field grid which is not periodic in {dim} dimension. "
627605
"If you get artifacts in the images, please check the boundary conditions and "
628606
"the size of the scan window and the force field grid."

0 commit comments

Comments
 (0)