mempro 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mempro-0.2.0 → mempro-0.2.1}/PKG-INFO +2 -2
- {mempro-0.2.0 → mempro-0.2.1}/README.md +1 -1
- {mempro-0.2.0 → mempro-0.2.1}/mempro/MemPrO.py +62 -91
- {mempro-0.2.0 → mempro-0.2.1}/mempro.egg-info/PKG-INFO +2 -2
- {mempro-0.2.0 → mempro-0.2.1}/pyproject.toml +1 -1
- {mempro-0.2.0 → mempro-0.2.1}/LICENSE +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro/Insane4MemPrO.py +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro/__init__.py +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro/_cli.py +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro/martini_v3.itp +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro.egg-info/SOURCES.txt +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro.egg-info/dependency_links.txt +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro.egg-info/entry_points.txt +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro.egg-info/requires.txt +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/mempro.egg-info/top_level.txt +0 -0
- {mempro-0.2.0 → mempro-0.2.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mempro
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Membrane Protein Orientation in Lipid Bilayers
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -107,7 +107,7 @@ MemPrO is intended to be run on PDB files, and will output the following files:
|
|
|
107
107
|
|
|
108
108
|
**-ng, --grid_size** — Number of initial starting configurations. Defaults to 36. For best efficiency this should be a multiple of the number of CPUs being used. More starting configurations sample the space of minima better, but there are diminishing returns and generally no more than 40 are needed.
|
|
109
109
|
|
|
110
|
-
**-nc, --num_cpus** — Number of CPU cores to use. Defaults to all available cores. For best performance with `-ng`, set `-nc` to a value that divides `-ng` evenly.
|
|
110
|
+
**-nc, --num_cpus** — Number of CPU cores to use. Defaults to the number of performance cores where the system reports them (e.g. 4 on an Apple M4, whose 6 efficiency cores would slow each batch down), otherwise all available cores. For best performance with `-ng`, set `-nc` to a value that divides `-ng` evenly.
|
|
111
111
|
|
|
112
112
|
**-dev, --device** — Device to run on: `auto` (default; GPU if JAX can see one, otherwise CPU), `cpu` or `gpu`. On GPU, all starting configurations are minimised together in a single batch. GPU support needs `pip install "mempro[gpu]"` (Linux, NVIDIA).
|
|
113
113
|
|
|
@@ -94,7 +94,7 @@ MemPrO is intended to be run on PDB files, and will output the following files:
|
|
|
94
94
|
|
|
95
95
|
**-ng, --grid_size** — Number of initial starting configurations. Defaults to 36. For best efficiency this should be a multiple of the number of CPUs being used. More starting configurations sample the space of minima better, but there are diminishing returns and generally no more than 40 are needed.
|
|
96
96
|
|
|
97
|
-
**-nc, --num_cpus** — Number of CPU cores to use. Defaults to all available cores. For best performance with `-ng`, set `-nc` to a value that divides `-ng` evenly.
|
|
97
|
+
**-nc, --num_cpus** — Number of CPU cores to use. Defaults to the number of performance cores where the system reports them (e.g. 4 on an Apple M4, whose 6 efficiency cores would slow each batch down), otherwise all available cores. For best performance with `-ng`, set `-nc` to a value that divides `-ng` evenly.
|
|
98
98
|
|
|
99
99
|
**-dev, --device** — Device to run on: `auto` (default; GPU if JAX can see one, otherwise CPU), `cpu` or `gpu`. On GPU, all starting configurations are minimised together in a single batch. GPU support needs `pip install "mempro[gpu]"` (Linux, NVIDIA).
|
|
100
100
|
|
|
@@ -75,11 +75,27 @@ def _pre_parse_device_args():
|
|
|
75
75
|
_pre_parse_device_args()
|
|
76
76
|
|
|
77
77
|
#We need to force JAX to fully utilize a multi-core cpu
|
|
78
|
-
|
|
78
|
+
#By default one device per performance core: each batch of minimisations waits for its slowest device, so on CPUs with
|
|
79
|
+
#efficiency cores (e.g. Apple Silicon, 4P+6E on an M4) using every core is slower (4G1U: 24 s on 10 cores, 16 s on 4)
|
|
80
|
+
def default_device_count():
|
|
81
|
+
try:
|
|
82
|
+
import subprocess
|
|
83
|
+
perf_cores = subprocess.run(["sysctl","-n","hw.perflevel0.physicalcpu"],capture_output=True,text=True,timeout=5)
|
|
84
|
+
if perf_cores.returncode == 0 and perf_cores.stdout.strip().isdigit():
|
|
85
|
+
return int(perf_cores.stdout.strip())
|
|
86
|
+
except (OSError,subprocess.SubprocessError):
|
|
87
|
+
pass
|
|
88
|
+
return os.cpu_count()
|
|
89
|
+
no_cpu = int(os.environ.get("NUM_CPU", default_device_count()))
|
|
79
90
|
os.environ["XLA_FLAGS"] = (os.environ.get("XLA_FLAGS", "")+" --xla_force_host_platform_device_count="+str(no_cpu)).strip()
|
|
91
|
+
jax_version = tuple(int(v) for v in jax.__version__.split(".")[:3] if v.isdigit())
|
|
80
92
|
#The legacy (non-thunk) CPU runtime is faster for MemPrO's scan/cond-heavy loops but only exists up to JAX 0.6.0
|
|
81
|
-
if
|
|
93
|
+
if jax_version <= (0,6,0):
|
|
82
94
|
os.environ["XLA_FLAGS"] += " --xla_cpu_use_thunk_runtime=false"
|
|
95
|
+
#XLA's YNNPACK CPU fusions (JAX >= 0.9) intermittently overflow a worker thread's stack on the large vectorised
|
|
96
|
+
#potentials in MemPrO/MemPrOD (SIGBUS in slinky::eval_non_inlined); turning them off costs no measurable speed
|
|
97
|
+
if jax_version >= (0,9,0) and "xla_cpu_experimental_ynn_fusion_type" not in os.environ["XLA_FLAGS"]:
|
|
98
|
+
os.environ["XLA_FLAGS"] += " --xla_cpu_experimental_ynn_fusion_type="
|
|
83
99
|
|
|
84
100
|
|
|
85
101
|
#This is useful for debugging nans in grad
|
|
@@ -558,36 +574,19 @@ class PDB_helper:
|
|
|
558
574
|
total = get_sph_circ(total,jnp.array([0,0]),jnp.pi)
|
|
559
575
|
total_area = jnp.sum(total)
|
|
560
576
|
#jax.debug.print("TA{x}",x=total_area)
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
cen_x = jnp.arctan2(direc[1],direc[0])
|
|
575
|
-
ang_grid = get_sph_circ(ang_grid,jnp.array([cen_x,cen_y]),angle)
|
|
576
|
-
return ang_grid
|
|
577
|
-
ang_grid = jax.lax.cond((dist < srad*3)*(dist>1e-5),nfar,far,ang_grid)
|
|
578
|
-
return ang_grid,ind
|
|
579
|
-
ang_grid,_ = jax.lax.scan(sloopv3_2,ang_grid,jnp.arange(mrad))
|
|
580
|
-
perc = jnp.sum(ang_grid)/total_area
|
|
581
|
-
#jax.debug.print("Perc {x}",x=perc)
|
|
582
|
-
def gthresh(is_surf):
|
|
583
|
-
is_surf = is_surf.at[ind].set(1)
|
|
584
|
-
return is_surf
|
|
585
|
-
def lthresh(is_surf):
|
|
586
|
-
return is_surf
|
|
587
|
-
is_surf = jax.lax.cond(perc<thresh,gthresh,lthresh,is_surf)
|
|
588
|
-
return is_surf,ind
|
|
589
|
-
is_surf,_=jax.lax.scan(sloopv3_1,is_surf,jnp.arange(points.shape[0]))
|
|
590
|
-
return is_surf
|
|
577
|
+
#Each nearby bead (closer than 3*srad) covers a circle of directions; a bead is on the surface if less than
|
|
578
|
+
#thresh of its directions are covered. get_sph_circ sets cells, so overlapping circles combine as a logical OR
|
|
579
|
+
def is_surf_fun(pind):
|
|
580
|
+
direc = points[pind]-points[bpoints[pind]]
|
|
581
|
+
dist = jnp.linalg.norm(direc,axis=1)
|
|
582
|
+
angle = jnp.arccos(jnp.clip(dist/(2*srad),0,1))
|
|
583
|
+
cen_y = jnp.arctan2(direc[:,2],jnp.sqrt(direc[:,0]*direc[:,0]+direc[:,1]*direc[:,1]))
|
|
584
|
+
cen_x = jnp.arctan2(direc[:,1],direc[:,0])
|
|
585
|
+
circles = jax.vmap(get_sph_circ,in_axes=(None,0,0))(jnp.zeros((40,20)),jnp.stack((cen_x,cen_y),axis=1),angle)
|
|
586
|
+
covered = jnp.any((circles > 0)*((dist < srad*3)*(dist>1e-5))[:,None,None],axis=0)
|
|
587
|
+
perc = jnp.sum(jnp.where(covered,total,0.0))/total_area
|
|
588
|
+
return jnp.where(perc<thresh,1.0,0.0)
|
|
589
|
+
return jax.lax.map(is_surf_fun,jnp.arange(points.shape[0]),batch_size=64)
|
|
591
590
|
|
|
592
591
|
#This function gets the surface residues of a given cg protein
|
|
593
592
|
def get_surface(self):
|
|
@@ -602,26 +601,13 @@ class PDB_helper:
|
|
|
602
601
|
|
|
603
602
|
#Calculating normals at each point of the cg protein
|
|
604
603
|
timer = time.time()
|
|
605
|
-
|
|
604
|
+
#The normal at a bead points away from the mean of all beads within 32 A (beads processed in batches to bound memory)
|
|
606
605
|
def normal_fun_2(ind):
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
def in_sphere(normal,posa,posb):
|
|
610
|
-
normal = normal.at[3].set(normal[3]+1)
|
|
611
|
-
normal = normal.at[:3].set(normal[:3]+(-posa+posb))
|
|
612
|
-
return normal
|
|
613
|
-
def not_in_sphere(normal,posa,posb):
|
|
614
|
-
return normal
|
|
615
|
-
normal = jax.lax.cond(jnp.linalg.norm(self.poses[ind]-self.poses[ind_fix])<32,in_sphere,not_in_sphere,normal_count,self.poses[ind],self.poses[ind_fix])#8####################<--------------------------
|
|
616
|
-
return ind_fix,normal
|
|
617
|
-
|
|
618
|
-
_,normals = jax.lax.scan(normal_fun_1,ind,jnp.arange(self.poses.shape[0]))
|
|
619
|
-
normals_sum = jnp.sum(normals,axis=0)
|
|
620
|
-
normal = normals_sum[:3]/normals_sum[3]
|
|
606
|
+
near = jnp.linalg.norm(self.poses-self.poses[ind],axis=1)<32
|
|
607
|
+
normal = jnp.sum(jnp.where(near[:,None],self.poses[ind]-self.poses,0.0),axis=0)/jnp.sum(near)
|
|
621
608
|
normal = normal/jnp.linalg.norm(normal)
|
|
622
609
|
return normal
|
|
623
|
-
|
|
624
|
-
normals = normal_fun_2(shard_nns)
|
|
610
|
+
normals = jax.lax.map(normal_fun_2,jnp.arange(self.poses.shape[0]),batch_size=256)
|
|
625
611
|
|
|
626
612
|
self.normals = jnp.array(jax.device_get(normals))#jax.device_put(normals)#jax.device_put_sharded([normals],[devices[0]])
|
|
627
613
|
|
|
@@ -646,27 +632,13 @@ class PDB_helper:
|
|
|
646
632
|
timer = time.time()
|
|
647
633
|
#Each point on the surface had an asocciated sphere indicating directions which are exposed
|
|
648
634
|
#Here we flag the directions which are free
|
|
649
|
-
|
|
635
|
+
#A direction is free if no bead lies within 4 A of the point 4 A out along the normal plus that direction
|
|
650
636
|
def sphere_fun_3(ind):
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
return 1
|
|
657
|
-
return ind_fix,jax.lax.cond(jnp.linalg.norm(self.poses[ind_fix[0]]+normals[ind_fix[0]]*4-self.poses[ind]+self.ball[ind_fix[1]])<4,in_prot,not_in_prot)
|
|
658
|
-
_,on_surf_arr=jax.lax.scan(sphere_fun_1,jnp.array([ind_fix,ind]),jnp.arange(self.poses.shape[0]))
|
|
659
|
-
on_surf_arr = jnp.array(jax.device_get(on_surf_arr))
|
|
660
|
-
|
|
661
|
-
on_surf = jnp.prod(on_surf_arr)
|
|
662
|
-
return ind_fix,on_surf
|
|
663
|
-
_,on_surf_ball = jax.lax.scan(sphere_fun_2,ind,jnp.arange(self.ball.shape[0]))
|
|
664
|
-
ball_arr = on_surf_ball*self.surface[ind]
|
|
665
|
-
return ball_arr
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
shard_nn = jax.device_put(jnp.arange(self.poses.shape[0]),sharding0)
|
|
669
|
-
spheres = sphere_fun_3(shard_nn)
|
|
637
|
+
test_points = self.poses[ind]+normals[ind]*4+self.ball
|
|
638
|
+
dists = jnp.linalg.norm(test_points[:,None,:]-self.poses[None,:,:],axis=2)
|
|
639
|
+
on_surf_ball = jnp.all(jnp.logical_not(dists<4),axis=1).astype(int)
|
|
640
|
+
return on_surf_ball*self.surface[ind]
|
|
641
|
+
spheres = jax.lax.map(sphere_fun_3,jnp.arange(self.poses.shape[0]),batch_size=32)
|
|
670
642
|
|
|
671
643
|
self.poses = self.poses[:pos_num]
|
|
672
644
|
self.surface = self.surface[:pos_num,0]
|
|
@@ -680,12 +652,8 @@ class PDB_helper:
|
|
|
680
652
|
jax.block_until_ready(self.poses)
|
|
681
653
|
|
|
682
654
|
#Here we set the cartesean directions for each sphere (as before we only had flags)
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
timeser = jnp.transpose(jnp.array([surface_sphere[ind],surface_sphere[ind],surface_sphere[ind]]))
|
|
686
|
-
sphere_poses = sphere_poses.at[ind].set(sphere_poses[ind,:]+timeser*self.ball)
|
|
687
|
-
return sphere_poses,ind
|
|
688
|
-
self.spheres,_ = jax.lax.scan(set_sphere_poses_fun_2,self.spheres,jnp.arange(surface_sphere.shape[0]))
|
|
655
|
+
#surface_number counts the padding rows too (they match surface_poses), and their spheres stay zero
|
|
656
|
+
self.spheres = jnp.zeros((surface_number,self.ball.shape[0],3)).at[:surface_sphere.shape[0]].set(surface_sphere[:,:,None]*self.ball[None,:,:])
|
|
689
657
|
surf_mean = jnp.mean(self.surface_poses,axis=0)
|
|
690
658
|
self.surface_poses = self.surface_poses-surf_mean
|
|
691
659
|
self.poses = self.poses-surf_mean
|
|
@@ -3154,13 +3122,28 @@ def read_martini_lines(martini_file):
|
|
|
3154
3122
|
with open(martini_file,"r") as mfile:
|
|
3155
3123
|
return tuple(mfile.readlines())
|
|
3156
3124
|
|
|
3157
|
-
#
|
|
3125
|
+
#Index of the first line starting with each 12-character "%6s%6s" bead pair, as in [ nonbond_params ]
|
|
3126
|
+
@lru_cache(maxsize=None)
|
|
3127
|
+
def martini_pair_index(martini_file):
|
|
3128
|
+
index = {}
|
|
3129
|
+
for i,line in enumerate(read_martini_lines(martini_file)):
|
|
3130
|
+
index.setdefault(line[:12],i)
|
|
3131
|
+
return index
|
|
3132
|
+
|
|
3133
|
+
#A fucntion that reads a martini file to get interaction strengths (memoised: each pair is looked up once per run)
|
|
3134
|
+
#Pairs are found through martini_pair_index (one pass over the file); any pair not found at the start of a line
|
|
3135
|
+
#falls back to the original search for the first line containing it
|
|
3136
|
+
@lru_cache(maxsize=None)
|
|
3158
3137
|
def get_int_strength(bead_1,bead_2,martini_file):
|
|
3159
3138
|
if(bead_2 == "GHOST"):
|
|
3160
3139
|
return 0
|
|
3161
3140
|
string = " "*(6-len(bead_1))+bead_1+" "*(6-len(bead_2))+bead_2
|
|
3162
3141
|
string2 = " "*(6-len(bead_2))+bead_2+" "*(6-len(bead_1))+bead_1
|
|
3163
3142
|
content = read_martini_lines(martini_file)
|
|
3143
|
+
index = martini_pair_index(martini_file)
|
|
3144
|
+
found = [index[s] for s in (string,string2) if s in index]
|
|
3145
|
+
if found:
|
|
3146
|
+
return -float(content[min(found)][32:45])
|
|
3164
3147
|
for i,line in enumerate(content):
|
|
3165
3148
|
if(string in line or string2 in line):
|
|
3166
3149
|
return -float(line[32:45])
|
|
@@ -3405,21 +3388,9 @@ def get_sph_circ(grid,cen,angle):
|
|
|
3405
3388
|
dy = jnp.pi/n
|
|
3406
3389
|
xs = jnp.linspace(0,2*jnp.pi-dx,2*n)+dx/2
|
|
3407
3390
|
ys = jnp.linspace(0,jnp.pi-dy,n)+dy/2
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
dist = jnp.arccos(jnp.cos(cen[0])*jnp.cos(xs[ind1])+jnp.sin(cen[0])*jnp.sin(xs[ind1])*jnp.cos(cen[1]-ys[ind]))
|
|
3412
|
-
def langle(grid):
|
|
3413
|
-
grid = grid.at[ind1,ind].set(dx*(jnp.cos(ys[ind]-dy/2)-jnp.cos(ys[ind]+dy/2)))
|
|
3414
|
-
return grid
|
|
3415
|
-
def gangle(grid):
|
|
3416
|
-
return grid
|
|
3417
|
-
grid = jax.lax.cond(dist<angle,langle,gangle,grid)
|
|
3418
|
-
return grid,ind
|
|
3419
|
-
grid,_ = jax.lax.scan(scloop2,grid,jnp.arange(n))
|
|
3420
|
-
return grid,ind
|
|
3421
|
-
grid,_ = jax.lax.scan(scloop1,grid,jnp.arange(2*n))
|
|
3422
|
-
return grid
|
|
3391
|
+
dist = jnp.arccos(jnp.cos(cen[0])*jnp.cos(xs)[:,None]+jnp.sin(cen[0])*jnp.sin(xs)[:,None]*jnp.cos(cen[1]-ys)[None,:])
|
|
3392
|
+
cell_area = dx*(jnp.cos(ys-dy/2)-jnp.cos(ys+dy/2))
|
|
3393
|
+
return jnp.where(dist<angle,jnp.broadcast_to(cell_area[None,:],grid.shape),grid)
|
|
3423
3394
|
|
|
3424
3395
|
def add_Reses(Res, Resitp):
|
|
3425
3396
|
current_res_no = len(Reses)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mempro
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Membrane Protein Orientation in Lipid Bilayers
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -107,7 +107,7 @@ MemPrO is intended to be run on PDB files, and will output the following files:
|
|
|
107
107
|
|
|
108
108
|
**-ng, --grid_size** — Number of initial starting configurations. Defaults to 36. For best efficiency this should be a multiple of the number of CPUs being used. More starting configurations sample the space of minima better, but there are diminishing returns and generally no more than 40 are needed.
|
|
109
109
|
|
|
110
|
-
**-nc, --num_cpus** — Number of CPU cores to use. Defaults to all available cores. For best performance with `-ng`, set `-nc` to a value that divides `-ng` evenly.
|
|
110
|
+
**-nc, --num_cpus** — Number of CPU cores to use. Defaults to the number of performance cores where the system reports them (e.g. 4 on an Apple M4, whose 6 efficiency cores would slow each batch down), otherwise all available cores. For best performance with `-ng`, set `-nc` to a value that divides `-ng` evenly.
|
|
111
111
|
|
|
112
112
|
**-dev, --device** — Device to run on: `auto` (default; GPU if JAX can see one, otherwise CPU), `cpu` or `gpu`. On GPU, all starting configurations are minimised together in a single batch. GPU support needs `pip install "mempro[gpu]"` (Linux, NVIDIA).
|
|
113
113
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|