Skip to content

Commit 119d8f4

Browse files
committed
ED-AFM stats scripts
1 parent 9c496ae commit 119d8f4

File tree

5 files changed

+673
-0
lines changed

5 files changed

+673
-0
lines changed

Diff for: papers/ed-afm/figures/stats/stats_distance.py

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
2+
import random
3+
import time
4+
from pathlib import Path
5+
6+
import numpy as np
7+
import ppafm.ml.AuxMap as aux
8+
import ppafm.ocl.field as FFcl
9+
import ppafm.ocl.oclUtils as oclu
10+
import ppafm.ocl.relax as oclr
11+
import torch
12+
from ppafm.ml.Generator import InverseAFMtrainer
13+
from ppafm.ocl.AFMulator import AFMulator
14+
15+
import mlspm.preprocessing as pp
16+
from mlspm.datasets import download_dataset
17+
from mlspm.models import EDAFMNet
18+
19+
def apply_preprocessing(batch):
20+
Xs, Ys, _ = batch
21+
Xs = [x[...,2:8] for x in Xs]
22+
pp.add_norm(Xs)
23+
pp.add_noise(Xs, c=0.08, randomize_amplitude=False)
24+
return Xs, Ys
25+
26+
if __name__ == "__main__":
27+
28+
# Indepenent tips model
29+
model_type = "base" # Type of pretrained weights to use
30+
save_file = Path("mse_independent.csv") # File to save MSE values into
31+
32+
# # Matched tips model
33+
# model_type = "matched-tips" # Type of pretrained weights to use
34+
# save_file = Path("mse_matched.csv") # File to save MSE values into
35+
36+
device = "cuda" # Device to run inference on
37+
molecules_dir = Path("../../molecules") # Path to molecule database
38+
test_heights = np.linspace(4.9, 5.7, 21) # Test heights to run
39+
n_samples = 3000 # Number of samples to run
40+
41+
if save_file.exists():
42+
raise RuntimeError("Save file already exists")
43+
44+
afmulator_args = {
45+
"pixPerAngstrome" : 20,
46+
"scan_dim" : (128, 128, 19),
47+
"scan_window" : ((2.0, 2.0, 6.0), (18.0, 18.0, 7.9)),
48+
"df_steps" : 10,
49+
"tipR0" : [0.0, 0.0, 4.0]
50+
}
51+
52+
generator_kwargs = {
53+
"batch_size" : 30,
54+
"distAbove" : 5.3,
55+
"iZPPs" : [8, 54],
56+
"Qs" : [[ -10, 20, -10, 0 ], [ 30, -60, 30, 0 ]],
57+
"QZs" : [[ 0.1, 0, -0.1, 0 ], [ 0.1, 0, -0.1, 0 ]]
58+
}
59+
60+
# Set random seed for reproducibility
61+
random.seed(0)
62+
63+
# Initialize OpenCL environment on GPU
64+
env = oclu.OCLEnvironment( i_platform = 0 )
65+
FFcl.init(env)
66+
oclr.init(env)
67+
68+
# Define AFMulator
69+
afmulator = AFMulator(**afmulator_args)
70+
afmulator.npbc = (0,0,0)
71+
72+
# Define AuxMaps
73+
aux_maps = [
74+
aux.ESMapConstant(
75+
scan_dim = afmulator.scan_dim[:2],
76+
scan_window = [afmulator.scan_window[0][:2], afmulator.scan_window[1][:2]],
77+
height = 4.0,
78+
vdW_cutoff = -2.0,
79+
Rpp = 1.0
80+
)
81+
]
82+
83+
# Download molecules if not already there
84+
download_dataset("ED-AFM-molecules", molecules_dir)
85+
86+
# Define generator
87+
xyz_paths = (molecules_dir / "test").glob("*.xyz")
88+
trainer = InverseAFMtrainer(afmulator, aux_maps, xyz_paths, **generator_kwargs)
89+
90+
# Pick samples
91+
random.shuffle(trainer.molecules)
92+
trainer.molecules = trainer.molecules[:n_samples]
93+
94+
# Make model
95+
model = EDAFMNet(device=device, pretrained_weights=model_type)
96+
97+
# Initialize save file
98+
with open(save_file, "w") as f:
99+
pass
100+
101+
# Calculate MSE at every height for every batch
102+
start_time = time.time()
103+
total_len = len(test_heights)*len(trainer)
104+
for ih, height in enumerate(test_heights):
105+
106+
print(f"Height = {height:.2f}")
107+
trainer.distAboveActive = height
108+
109+
mses = []
110+
for ib, batch in enumerate(trainer):
111+
112+
X, ref = apply_preprocessing(batch)
113+
X = [torch.from_numpy(x).unsqueeze(1).to(device) for x in X]
114+
ref = [torch.from_numpy(r).to(device) for r in ref]
115+
116+
with torch.no_grad():
117+
pred, _ = model(X)
118+
pred = pred[0]
119+
120+
diff = pred - ref[0]
121+
for d in diff:
122+
mses.append((d**2).mean().cpu().numpy())
123+
124+
eta = (time.time() - start_time) * (total_len / (ih*len(trainer)+ib+1) - 1)
125+
print(f"Batch {ib+1}/{len(trainer)} - ETA: {eta:.1f}s")
126+
127+
with open(save_file, "a") as f:
128+
f.write(f"{height:.2f},")
129+
f.write(",".join([str(v) for v in mses]))
130+
f.write("\n")

Diff for: papers/ed-afm/figures/stats/stats_distance_Xe.py

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
2+
import random
3+
import time
4+
from pathlib import Path
5+
6+
import numpy as np
7+
import ppafm.ml.AuxMap as aux
8+
import ppafm.ocl.field as FFcl
9+
import ppafm.ocl.oclUtils as oclu
10+
import ppafm.ocl.relax as oclr
11+
import torch
12+
from ppafm.ml.Generator import InverseAFMtrainer
13+
from ppafm.ocl.AFMulator import AFMulator
14+
15+
import mlspm.preprocessing as pp
16+
from mlspm.datasets import download_dataset
17+
from mlspm.models import EDAFMNet
18+
19+
20+
class Trainer(InverseAFMtrainer):
21+
22+
# Override this method to set the Xe tip at a different height
23+
def handle_distance(self):
24+
if self.afmulator.iZPP == 54:
25+
self.distAboveActive = self.distAboveXe
26+
super().handle_distance()
27+
if self.afmulator.iZPP == 54:
28+
self.distAboveActive = self.distAbove
29+
30+
def apply_preprocessing(batch):
31+
Xs, Ys, _ = batch
32+
Xs = [x[...,2:8] for x in Xs]
33+
pp.add_norm(Xs)
34+
pp.add_noise(Xs, c=0.08, randomize_amplitude=False)
35+
return Xs, Ys
36+
37+
if __name__ == "__main__":
38+
39+
# # Independent tips model
40+
# model_type = "base" # Type of pretrained weights to use
41+
# save_file = Path("mse_independent_Xe.csv") # File to save MSE values into
42+
43+
# Matched tips model
44+
model_type = "matched-tips" # Type of pretrained weights to use
45+
save_file = Path("./mse_matched_Xe.csv") # File to save MSE values into
46+
47+
device = "cuda" # Device to run inference on
48+
molecules_dir = Path("../../molecules") # Path to molecule database
49+
test_heights = np.linspace(4.9, 5.7, 21) # Test heights to run
50+
n_samples = 3000 # Number of samples to run
51+
52+
if save_file.exists():
53+
raise RuntimeError("Save file already exists")
54+
55+
afmulator_args = {
56+
"pixPerAngstrome" : 20,
57+
"scan_dim" : (128, 128, 19),
58+
"scan_window" : ((2.0, 2.0, 6.0), (18.0, 18.0, 7.9)),
59+
"df_steps" : 10,
60+
"tipR0" : [0.0, 0.0, 4.0]
61+
}
62+
63+
generator_kwargs = {
64+
"batch_size" : 30,
65+
"distAbove" : 5.3,
66+
"iZPPs" : [8, 54],
67+
"Qs" : [[ -10, 20, -10, 0 ], [ 30, -60, 30, 0 ]],
68+
"QZs" : [[ 0.1, 0, -0.1, 0 ], [ 0.1, 0, -0.1, 0 ]]
69+
}
70+
71+
# Set random seed for reproducibility
72+
random.seed(0)
73+
74+
# Initialize OpenCL environment on GPU
75+
env = oclu.OCLEnvironment( i_platform = 0 )
76+
FFcl.init(env)
77+
oclr.init(env)
78+
79+
# Define AFMulator
80+
afmulator = AFMulator(**afmulator_args)
81+
afmulator.npbc = (0,0,0)
82+
83+
# Define AuxMaps
84+
aux_maps = [
85+
aux.ESMapConstant(
86+
scan_dim = afmulator.scan_dim[:2],
87+
scan_window = [afmulator.scan_window[0][:2], afmulator.scan_window[1][:2]],
88+
height = 4.0,
89+
vdW_cutoff = -2.0,
90+
Rpp = 1.0
91+
)
92+
]
93+
94+
# Download molecules if not already there
95+
download_dataset("ED-AFM-molecules", molecules_dir)
96+
97+
# Define generator
98+
xyz_paths = (molecules_dir / "test").glob("*.xyz")
99+
trainer = Trainer(afmulator, aux_maps, xyz_paths, **generator_kwargs)
100+
101+
# Pick samples
102+
random.shuffle(trainer.molecules)
103+
trainer.molecules = trainer.molecules[:n_samples]
104+
105+
# Make model
106+
model = EDAFMNet(device=device, pretrained_weights=model_type)
107+
108+
# Initialize save file
109+
with open(save_file, "w") as f:
110+
pass
111+
112+
# Calculate MSE at every height for every batch
113+
start_time = time.time()
114+
total_len = len(test_heights)*len(trainer)
115+
for ih, height in enumerate(test_heights):
116+
117+
print(f"Height = {height:.2f}")
118+
trainer.distAboveXe = height
119+
120+
mses = []
121+
for ib, batch in enumerate(trainer):
122+
123+
X, ref = apply_preprocessing(batch)
124+
X = [torch.from_numpy(x).unsqueeze(1).to(device) for x in X]
125+
ref = [torch.from_numpy(r).to(device) for r in ref]
126+
127+
with torch.no_grad():
128+
pred, _ = model(X)
129+
pred = pred[0]
130+
131+
diff = pred - ref[0]
132+
for d in diff:
133+
mses.append((d**2).mean().cpu().numpy())
134+
135+
eta = (time.time() - start_time) * (total_len / (ih*len(trainer)+ib+1) - 1)
136+
print(f"Batch {ib+1}/{len(trainer)} - ETA: {eta:.1f}s")
137+
138+
with open(save_file, "a") as f:
139+
f.write(f"{height:.2f},")
140+
f.write(",".join([str(v) for v in mses]))
141+
f.write("\n")

0 commit comments

Comments
 (0)