Skip to content

Commit 5f4138e

Browse files
committed
add curved apl cutoff parameter
1 parent 1a210c6 commit 5f4138e

File tree

2 files changed

+19
-60
lines changed

2 files changed

+19
-60
lines changed

domhmm/analysis/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ def __init__(
128128
n_init_hmm: int = 2,
129129
save_plots: bool = False,
130130
do_clustering: bool = True,
131+
curved_apl_cutoff: float = 30,
131132
**kwargs
132133
):
133134
# the below line must be kept to initialize the AnalysisBase class!
@@ -158,6 +159,7 @@ def __init__(
158159
self.n_init_hmm = n_init_hmm
159160
self.save_plots = save_plots
160161
self.do_clustering = do_clustering
162+
self.cutoff = curved_apl_cutoff
161163

162164
assert heads.keys() == tails.keys(), "Heads and tails don't contain same residue names"
163165

domhmm/analysis/domhmm.py

Lines changed: 17 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def _prepare(self):
6464
self.leaflet_assignment = np.zeros((len(self.membrane_unique_resids), self.n_frames), dtype=np.int32)
6565

6666
@staticmethod
67-
def calc_order_parameter_old(chain):
67+
def calc_order_parameter_z_axis(chain):
6868

6969
"""
7070
Calculate average Scc order parameters per acyl chain according to the equation:
@@ -96,7 +96,6 @@ def calc_order_parameter_old(chain):
9696
vec_norm = [np.sqrt((vec_i ** 2).sum(axis=-1)) for vec_i in vec]
9797

9898
vec = [vec_i / vec_norm_i.reshape(-1, 1) for vec_i, vec_norm_i in zip(vec, vec_norm)]
99-
# TODO z axis multiplication inside. It needs to be changed in future work
10099
# Choose the z-axis as membrane normal and take care of the machine precision
101100
dot_prod = [np.clip(vec_i[:, 2], -1., 1.) for vec_i in vec]
102101

@@ -193,7 +192,7 @@ def flat_sterols(self):
193192
# Iterate over each tail with chain id
194193
flat_sterol_idx = []
195194
for i, (resname, tail) in enumerate(self.sterol_tails_selection.items()):
196-
s_cc = self.calc_order_parameter_old(tail)
195+
s_cc = self.calc_order_parameter_z_axis(tail)
197196
idx = self.get_residue_idx(self.resids_index_map, np.unique(tail.resids))
198197
# Check s_cc < -0.25 mark as NaN in training data and return indexes of these lipids
199198
flat_scc = np.where(s_cc < -0.25)[0]
@@ -400,10 +399,6 @@ def detect_neighbors_cutoff(self, positions, cutoff, pbc=None):
400399
all_neighbors = tree.query_ball_point(positions, r=cutoff)
401400
else:
402401
Lx, Ly, Lz = pbc
403-
# shifts = np.array([[i * Lx, j * Ly, k * Lz]
404-
# for i in (-1, 0, 1)
405-
# for j in (-1, 0, 1)
406-
# for k in (-1, 0, 1)])
407402
shifts = np.array([[i * Lx, j * Ly, 0]
408403
for i in (-1, 0, 1)
409404
for j in (-1, 0, 1)])
@@ -495,50 +490,47 @@ def smooth_normals(normals, neighbor_lists):
495490

496491

497492
def tangent_plane_voronoi_weights(self, positions,
498-
k_neighbors=None,
499-
cutoff=None,
500-
pbc=None,
501-
min_neighbors=6,
502-
clip_factor=2.0):
493+
cutoff=30,
494+
pbc=None):
503495
"""
504496
Tangent-plane Voronoi with neighbor selection by cutoff or k-nearest.
505497
506498
Parameters
507499
----------
508500
positions : (N,3)
509501
3D coordinates of lipids.
510-
k_neighbors : int, optional
511-
Number of nearest neighbors (if cutoff not given).
512502
cutoff : float, optional
513-
Cutoff distance. Overrides k_neighbors if given.
503+
Cutoff distance in Armstrong.
514504
pbc : (3,), optional
515505
Box lengths for PBC.
516-
min_neighbors : int
517-
Minimum neighbors for PCA.
518-
clip_factor : float
519-
For clipping infinite regions.
520506
521507
Returns
522508
-------
523509
W : (N,N) array
524510
Symmetric weight matrix.
525511
areas : (N,) array
526512
Approximate Voronoi cell area in tangent plane.
513+
normals : (N,3) array
514+
Lipid normals for further Scc calculation
527515
"""
516+
517+
if pbc is None:
518+
log.error("Periodic boundary condition box size is required.")
519+
sys.exit(1)
520+
528521
positions = np.asarray(positions, dtype=float)
529522
N = positions.shape[0]
530523
W = np.zeros((N, N))
531524
areas = np.zeros(N)
532525

533526
# Get neighbor lists
534527
neighbor_lists, neighbors_pos = self.detect_neighbors_cutoff(positions, cutoff, pbc=pbc)
535-
# neighbor_lists, neighbors_pos = self.detect_neighbors_knn(positions, pbc=pbc, k_neighbors=16)
528+
536529
normals = np.zeros(shape=(N,3))
537530
for i in range(N):
538531
neigh_pos = neighbors_pos[i]
539532
P = neigh_pos - positions[i]
540533
# PCA for local normal
541-
# TODO We will use this normal for Scc calculation
542534
normals[i] = self._pca_normal(P)
543535
# TODO Error
544536
# smooth_normals = self.smooth_normals(normals, neighbor_lists)
@@ -548,10 +540,6 @@ def tangent_plane_voronoi_weights(self, positions,
548540
neigh_idx = neighbor_lists[i]
549541
neigh_pos = neighbors_pos[i]
550542
P = neigh_pos - positions[i]
551-
# PCA for local normal
552-
# TODO We will use this normal for Scc calculation
553-
# TODO Normal calculation with close neighbors and smoothing with neighbor normals
554-
# normal = self._pca_normal(P)
555543
u, v = self._build_tangent_basis(smooth_normals[i])
556544

557545
# Project
@@ -659,29 +647,23 @@ def _single_frame(self):
659647
raise ValueError("Atoms in both leaflets !")
660648

661649
# ------------------------------ Order parameter ------------------------------------------------------------- #
662-
# flat_sterol_idx = self.order_parameter()
663650
flat_sterol_idx = self.flat_sterols()
664-
# flat_sterol_idx = []
665651
flat_sterol_ids = [self.index_resid_map[idx] for idx in flat_sterol_idx]
666652
# Assign -1 in leaflet_assignment flat sterols
667653
self.leaflet_assignment[flat_sterol_idx, self.index] = -1
668654
# ------------------------------ Local Normals/Area per Lipid ------------------------------------------------ #
669655
boxdim = self.universe.trajectory.ts.dimensions[0:3]
670656
# Remove flat sterols those from coordinates and indexes for leaflets
671657
# Put NaN for flat lipids' APL Value
672-
673658
upper_mask = ~np.in1d(self.leaflet_selection["0"].resids, flat_sterol_ids)
674-
# TODO Delete later
675-
self.upper_mask = upper_mask
676659
upper_coor_xy = self.leaflet_selection["0"][upper_mask].positions
677660
uidx = uidx[upper_mask]
678661
lower_mask = ~np.in1d(self.leaflet_selection["1"].resids, flat_sterol_ids)
679662
lower_coor_xy = self.leaflet_selection["1"][lower_mask].positions
680663
lidx = lidx[lower_mask]
681664
# Check Transmembrane domain existence
682665
if self.tmd_protein is not None:
683-
# TODO Fix this - Calculate COG for every frame separately
684-
# tmd_upper_coor_xy = self.tmd_protein["0"]
666+
# Calculate COG for every frame separately
685667
tmd_upper_coor_xy = np.array([np.mean(bb.positions, axis=0) for bb in self.tmd_protein["0"]])
686668
# Check if dimension of coordinates is same in both array
687669
if tmd_upper_coor_xy.shape[1] == upper_coor_xy.shape[1]:
@@ -691,32 +673,9 @@ def _single_frame(self):
691673
# Check if dimension of coordinates is same in both array
692674
if tmd_lower_coor_xy.shape[1] == lower_coor_xy.shape[1]:
693675
lower_coor_xy = np.append(lower_coor_xy, tmd_lower_coor_xy, axis=0)
694-
# upper_vor, upper_apl_old, upper_pbc_idx = self.area_per_lipid_vor(coor_xy=upper_coor_xy, boxdim=boxdim,
695-
# frac=self.frac)
696-
# lower_vor, lower_apl_old, lower_pbc_idx = self.area_per_lipid_vor(coor_xy=lower_coor_xy, boxdim=boxdim,
697-
# frac=self.frac)
698-
# if self.tmd_protein is not None:
699-
# # Remove TMD Protein numbers from training data
700-
# upper_apl_old = np.array(upper_apl_old[:-len(tmd_upper_coor_xy)])
701-
# lower_apl_old = np.array(lower_apl_old[:-len(tmd_lower_coor_xy)])
702-
# self.results.train[uidx, self.index, 0] = upper_apl_old
703-
# self.results.train[lidx, self.index, 0] = lower_apl_old
704-
# self.results.train[flat_sterol_idx, self.index, 0] = None
705-
# # TODO Local normal calculation
706-
# # ------------------------------ Weight Matrix --------------------------------------------------------------- #
707-
# upper_weight_matrix = self.weight_matrix(upper_vor, pbc_idx=upper_pbc_idx, coor_xy=upper_coor_xy)
708-
# lower_weight_matrix = self.weight_matrix(lower_vor, pbc_idx=lower_pbc_idx, coor_xy=lower_coor_xy)
709-
# if self.tmd_protein is not None:
710-
# # Remove TMD Protein numbers from weight matrix
711-
# upper_weight_matrix = upper_weight_matrix[:-len(tmd_upper_coor_xy), :-len(tmd_upper_coor_xy)]
712-
# lower_weight_matrix = lower_weight_matrix[:-len(tmd_lower_coor_xy), :-len(tmd_lower_coor_xy)]
713-
714-
# Keep weight matrices in scipy.sparse.csr_array format since both is sparse matrices
715-
# self.results["upper_weight_all"].append(csr_array(upper_weight_matrix))
716-
# self.results["lower_weight_all"].append(csr_array(lower_weight_matrix))
717-
718-
upper_weight, upper_apl, upper_normal = self.tangent_plane_voronoi_weights(upper_coor_xy, cutoff=30, pbc=boxdim)
719-
lower_weight, lower_apl, lower_normal = self.tangent_plane_voronoi_weights(lower_coor_xy, cutoff=30, pbc=boxdim)
676+
677+
upper_weight, upper_apl, upper_normal = self.tangent_plane_voronoi_weights(upper_coor_xy, cutoff=self.cutoff, pbc=boxdim)
678+
lower_weight, lower_apl, lower_normal = self.tangent_plane_voronoi_weights(lower_coor_xy, cutoff=self.cutoff, pbc=boxdim)
720679

721680
if self.tmd_protein is not None:
722681
# Remove TMD Protein numbers from training data
@@ -731,8 +690,6 @@ def _single_frame(self):
731690
lipid_normals[uidx] = upper_normal
732691
lipid_normals[lidx] = lower_normal
733692

734-
# self.results["upper_weight_all"].append(csr_array(upper_weight))
735-
# self.results["lower_weight_all"].append(csr_array(lower_weight))
736693
self.order_parameter_lipid_normal(lipid_normals)
737694

738695
self.results.train[uidx, self.index, 0] = upper_apl

0 commit comments

Comments
 (0)