tmquick 1.0.0__py3-none-any.whl

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.
tmq/core/diff2graph.py ADDED
@@ -0,0 +1,75 @@
1
+ """ Render a difference heatmap (A - B) and return the figure
2
+
3
+ """
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ import matplotlib.pyplot as plt
8
+ import seaborn as sns
9
+ from matplotlib.ticker import MultipleLocator
10
+ from ..utils.utils import compute_mat_diff
11
+
12
+
13
+
14
+
15
+ def diff_map(matrix1, matrix2, vmax, residue_start, residue_end):
16
+
17
+ D = compute_mat_diff(matrix1, matrix2)
18
+
19
+ # Internal style settings
20
+ x_minor = 20
21
+ y_major = 50
22
+ y_minor = 10
23
+
24
+ frames = D.shape[1]
25
+
26
+ if frames <= 100:
27
+ x_step = 10
28
+ elif frames <= 500:
29
+ x_step = 50
30
+ else:
31
+ x_step = 100
32
+
33
+ fig, ax = plt.subplots(figsize=(12, 8))
34
+
35
+ #handle NAN
36
+ mask = np.isnan(D)
37
+
38
+ sns.heatmap(D, cmap="bwr", center=0, vmin=-vmax, vmax=vmax, mask=mask, cbar=False)
39
+
40
+ xticks = np.arange(0, frames + 1, x_step)
41
+ ax.set_xticks(xticks)
42
+ ax.set_xticklabels(xticks, rotation=0, fontsize=14)
43
+ ax.xaxis.set_minor_locator(MultipleLocator(x_minor))
44
+
45
+ for tick in ax.get_xticklabels():
46
+ tick.set_fontweight("bold")
47
+
48
+ # Y ticks
49
+ residues = D.shape[0]
50
+ ax.set_yticks(np.arange(0, residues, y_major))
51
+ ax.set_yticklabels(np.arange(residue_start, residue_end, y_major), fontsize=14)
52
+ ax.yaxis.set_minor_locator(MultipleLocator(y_minor))
53
+
54
+ for tick in ax.get_yticklabels():
55
+ tick.set_fontweight("bold")
56
+
57
+ ax.invert_yaxis()
58
+
59
+ # Labels
60
+ ax.set_title("Difference Map", fontsize=20, fontweight="bold")
61
+ ax.set_ylabel("Residue", fontsize=20, fontweight="bold")
62
+ ax.set_xlabel("Frames", fontsize=20, fontweight="bold")
63
+
64
+ # Colorbar
65
+ im = ax.collections[0]
66
+ cbar = fig.colorbar(im, fraction=0.029, pad=0.028)
67
+ cbar.set_label("Shift (Å)", fontsize=14, fontweight="bold")
68
+
69
+ for t in cbar.ax.get_yticklabels():
70
+ t.set_fontweight("bold")
71
+ t.set_fontsize(16)
72
+
73
+ plt.tight_layout()
74
+ plt.close()
75
+ return fig
tmq/core/hotspot.py ADDED
@@ -0,0 +1,164 @@
1
+ """ Core logic for generating shift graphs of detected
2
+ peak regions of a protein in an automated way
3
+
4
+ """
5
+
6
+ import numpy as np
7
+ import pandas as pd
8
+ import matplotlib
9
+ matplotlib.use("Agg")
10
+ import matplotlib.pyplot as plt
11
+ from matplotlib.ticker import MultipleLocator
12
+ from ..utils.utils import detect, extract_region_submatrices, slice_matrix2shift, auto_limits
13
+
14
+
15
+ def detect_shifts(matrix, window, mindist, hotspot):
16
+ regions, mean_shift, smooth = detect(
17
+ matrix=matrix,
18
+ window=window,
19
+ mindist=mindist,
20
+ hotspot=hotspot,)
21
+ return mean_shift, smooth, regions
22
+
23
+ def create_submatrices(matrix, window, mindist, hotspot):
24
+ regions, mean_shift, smooth = detect(
25
+ matrix=matrix,
26
+ window=window,
27
+ mindist=mindist,
28
+ hotspot=hotspot)
29
+
30
+ regions_only = [(start, end) for (start, peak, end) in regions]
31
+ submatrices = extract_region_submatrices(matrix, regions_only)
32
+ return submatrices, regions, mean_shift, smooth
33
+
34
+ def plot_shift_regions(shift_data, start_residue, end_residue, color="blue", window=10, title=None):
35
+ df = pd.DataFrame(shift_data)
36
+ roll = df.rolling(window, center=True, min_periods=1).mean()
37
+ x_min, x_max, y_min, y_max = auto_limits(df)
38
+
39
+ fig, ax = plt.subplots(figsize=(10, 6))
40
+ ax.plot(df, linewidth=0.3, color=color,
41
+ label=f"residues {start_residue}-{end_residue}")
42
+ ax.plot(roll, linewidth=3.0, color=color)
43
+ ax.legend(loc='upper left', fancybox=True, shadow=True,
44
+ prop={'size': 14, 'weight': 'bold'})
45
+
46
+ ax.set_xlim(x_min, x_max)
47
+ ax.set_ylim(y_min, y_max)
48
+ x_range = x_max - x_min
49
+ if x_range <= 500:
50
+ x_step = 50
51
+ elif x_range <= 1000:
52
+ x_step = 100
53
+ else:
54
+ x_step = 200
55
+ ax.set_xticks(np.arange(x_min, x_max + 1, x_step))
56
+ ax.tick_params(axis='x', labelsize=16)
57
+ y_range = y_max - y_min
58
+ if y_range <= 2:
59
+ y_step = 0.2
60
+ elif y_range <= 5:
61
+ y_step = 0.5
62
+ elif y_range <= 10:
63
+ y_step = 1
64
+ else:
65
+ y_step = 5
66
+ ax.set_yticks(np.arange(y_min, y_max + 0.5, y_step))
67
+ ax.tick_params(axis='y', labelsize=16)
68
+ ax.set_yticklabels([f"{y:.2f}" for y in ax.get_yticks()])
69
+ for tick in ax.get_xticklabels():
70
+ tick.set_fontweight("bold")
71
+ for tick in ax.get_yticklabels():
72
+ tick.set_fontweight("bold")
73
+ ax.set_title(title if title else f"Shift Graph {start_residue}-{end_residue}",
74
+ fontsize=20, fontweight="bold")
75
+ ax.set_xlabel("Frames", fontsize=20, fontweight="bold")
76
+ ax.set_ylabel("Shift / Å", fontsize=20, fontweight="bold")
77
+ ax.xaxis.set_minor_locator(MultipleLocator((x_max - x_min) / 50))
78
+ fig.tight_layout()
79
+ plt.close(fig)
80
+ return fig
81
+
82
+
83
+ def slice_shifts(matrix, window, mindist, hotspot):
84
+ regions, mean_shift, smooth = detect(
85
+ matrix=matrix,
86
+ window=window,
87
+ mindist=mindist,
88
+ hotspot=hotspot)
89
+
90
+ regions_only = [(start, end) for (start, peak, end) in regions]
91
+ submatrices = extract_region_submatrices(matrix, regions_only)
92
+ results = []
93
+
94
+ for start, end, submatrix in submatrices:
95
+ params = [0, submatrix.shape[0] - 1, 0, submatrix.shape[1] - 1]
96
+ shift_data = slice_matrix2shift(submatrix, params)
97
+ shift_data = shift_data[2:]
98
+ results.append((start, end, shift_data))
99
+ return results
100
+
101
+
102
+ def plot_slice_regions(shift_data, start, end):
103
+ return plot_shift_regions(
104
+ shift_data=shift_data,
105
+ start_residue=start,
106
+ end_residue=end,
107
+ title=f"Region {start}-{end}" )
108
+
109
+
110
+ def plot_hotspot_regions(mean_shift, smooth, regions, title="Residue Shift Hotspots"):
111
+ residues = np.arange(len(mean_shift))
112
+ df = pd.DataFrame(mean_shift)
113
+ x_min, x_max, y_min, y_max = auto_limits(df)
114
+
115
+ fig, ax = plt.subplots(figsize=(10, 6))
116
+ ax.plot(residues, mean_shift, color="gray", alpha=0.4, linewidth=0.8, label="Mean shift")
117
+ ax.plot(residues, smooth, color="blue", linewidth=3.5, label="Smoothed")
118
+
119
+ for (start, peak, end) in regions:
120
+ ax.axvspan(start, end, color="white", alpha=0.7)
121
+ ax.plot(peak, smooth[peak], "ro")
122
+ ax.text(peak, smooth[peak], f" {peak}", color="red", fontsize=9, fontweight="bold")
123
+
124
+ ax.legend(loc='upper left', fancybox=True, shadow=True,
125
+ prop={'size': 8, 'weight': 'bold'})
126
+ ax.set_xlim(x_min, x_max)
127
+ ax.set_ylim(y_min, y_max)
128
+ x_range = x_max - x_min
129
+ if x_range <= 200:
130
+ x_step = 25
131
+ elif x_range <= 500:
132
+ x_step = 50
133
+ elif x_range <= 1000:
134
+ x_step = 100
135
+ else:
136
+ x_step = 200
137
+ ax.set_xticks(np.arange(x_min, x_max + 1, x_step))
138
+ ax.tick_params(axis='x', labelsize=12)
139
+
140
+ y_range = y_max - y_min
141
+ if y_range <= 2:
142
+ y_step = 0.2
143
+ elif y_range <= 5:
144
+ y_step = 0.5
145
+ elif y_range <= 10:
146
+ y_step = 1
147
+ else:
148
+ y_step = 5
149
+ ax.set_yticks(np.arange(y_min, y_max + 0.5, y_step))
150
+ ax.tick_params(axis='y', labelsize=12)
151
+ for tick in ax.get_xticklabels():
152
+ tick.set_fontweight("bold")
153
+ for tick in ax.get_yticklabels():
154
+ tick.set_fontweight("bold")
155
+
156
+ ax.set_title(title, fontsize=18, fontweight="bold")
157
+ ax.set_xlabel("Residue index", fontsize=16, fontweight="bold")
158
+ ax.set_ylabel("Mean shift / Å", fontsize=16, fontweight="bold")
159
+ ax.xaxis.set_minor_locator(MultipleLocator((x_max - x_min) / 50))
160
+ ax.yaxis.set_minor_locator(MultipleLocator((y_max - y_min) / 50))
161
+ ax.grid(True, alpha=0.3)
162
+ fig.tight_layout()
163
+ plt.close(fig)
164
+ return fig
tmq/core/pdb2csv.py ADDED
@@ -0,0 +1,53 @@
1
+ """ This module loops over the Multi-model pdb and
2
+ compute residual fluctuations across the frames
3
+
4
+ """
5
+
6
+ import pandas as pd
7
+ import numpy as np
8
+ from ..utils.utils import (load_pdb_models, build_residue_lookup, get_ca_coord, get_backbone_com, distance)
9
+
10
+
11
+ def pdb2csv(pdb_file, residue_start, residue_end, mode):
12
+ weights = {"N": 14.0, "CA": 12.0, "C": 12.0, "O": 16.0}
13
+ residue_numbers = list(range(residue_start, residue_end + 1))
14
+
15
+ models = load_pdb_models(pdb_file)
16
+ n_frames = len(models)
17
+
18
+ ref_lookup = build_residue_lookup(models[0])
19
+
20
+ ref_coords = {}
21
+ for resnum in residue_numbers:
22
+ if resnum in ref_lookup:
23
+ residue = ref_lookup[resnum]
24
+ if mode == "ca":
25
+ ref_coords[resnum] = get_ca_coord(residue)
26
+ else:
27
+ ref_coords[resnum] = get_backbone_com(residue, weights)
28
+ else:
29
+ ref_coords[resnum] = np.zeros(3)
30
+
31
+ matrix = pd.DataFrame(0.0, index=residue_numbers, columns=range(n_frames))
32
+
33
+ """ Compute distances for frames 1..N-1
34
+ """
35
+
36
+ for t in range(1, n_frames):
37
+ lookup = build_residue_lookup(models[t])
38
+
39
+ for resnum in residue_numbers:
40
+ ref = ref_coords[resnum]
41
+
42
+ if resnum in lookup:
43
+ residue = lookup[resnum]
44
+ if mode == "ca":
45
+ cur = get_ca_coord(residue)
46
+ else:
47
+ cur = get_backbone_com(residue, weights)
48
+ else:
49
+ cur = np.zeros(3)
50
+
51
+ matrix.loc[resnum, t] = distance(cur, ref)
52
+
53
+ return matrix
@@ -0,0 +1,63 @@
1
+ """ Core logic for making the shift plot
2
+
3
+ """
4
+
5
+
6
+ import numpy as np
7
+ import matplotlib
8
+ matplotlib.use("Agg")
9
+ import matplotlib.pyplot as plt
10
+ from matplotlib.ticker import MultipleLocator
11
+ from ..utils.utils import auto_limits, rolling_average
12
+
13
+
14
+ def shift2graph(df, residue_label, window=10):
15
+ roll_df = rolling_average(df, window)
16
+ x_min, x_max, y_min, y_max = auto_limits(df)
17
+ color = "blue"
18
+ fig, ax = plt.subplots(figsize=(10, 6))
19
+
20
+ ax.plot(df, linewidth=0.3, color=color, label=f"residues {residue_label}")
21
+ ax.plot(roll_df, linewidth=3.0, color=color)
22
+ ax.legend(loc='upper left', fancybox=True, shadow=True,
23
+ prop={'size': 14, 'weight': 'bold'})
24
+
25
+ ax.set_xlim(x_min, x_max)
26
+ ax.set_ylim(y_min, y_max)
27
+ x_range = x_max - x_min
28
+ if x_range <= 100:
29
+ x_step = 10
30
+ elif x_range <= 500:
31
+ x_step = 50
32
+ elif x_range <= 1000:
33
+ x_step = 100
34
+ else:
35
+ x_step = 200
36
+ ax.set_xticks(np.arange(x_min, x_max + 1, x_step))
37
+ ax.tick_params(axis='x', labelsize=14)
38
+
39
+ y_range = y_max - y_min
40
+ if y_range <= 2:
41
+ y_step = 0.2
42
+ elif y_range <= 5:
43
+ y_step = 0.5
44
+ elif y_range <= 10:
45
+ y_step = 1
46
+ else:
47
+ y_step = 5
48
+ ax.set_yticks(np.arange(y_min, y_max + 0.5, y_step))
49
+ ax.tick_params(axis='y', labelsize=14)
50
+ ax.set_yticklabels([f"{y:.2f}" for y in ax.get_yticks()])
51
+ for tick in ax.get_xticklabels():
52
+ tick.set_fontweight("bold")
53
+ for tick in ax.get_yticklabels():
54
+ tick.set_fontweight("bold")
55
+
56
+ ax.set_title("Shift Graph", fontsize=20, fontweight="bold")
57
+ ax.set_xlabel("Frames", fontsize=18, fontweight="bold")
58
+ ax.set_ylabel("Shift / Å", fontsize=18, fontweight="bold")
59
+
60
+ ax.yaxis.set_minor_locator(MultipleLocator((y_max - y_min) / 10))
61
+ fig.tight_layout()
62
+ plt.close(fig)
63
+ return fig
tmq/core/traj2pdb.py ADDED
@@ -0,0 +1,12 @@
1
+ """ This is the engine for the conversion of trajectory files into multi-model PDB
2
+
3
+ """
4
+
5
+ from ..utils.utils import (load_traj, select_backbone, align_to_first_frame)
6
+
7
+
8
+ def traj2pdb(topology, trajectory, stride):
9
+ traj = load_traj(topology, trajectory, stride)
10
+ traj = select_backbone(traj)
11
+ traj = align_to_first_frame(traj)
12
+ return traj
tmq/core/trajmap.py ADDED
@@ -0,0 +1,52 @@
1
+ """ This module instantiates the trajectory map plot
2
+ for the residue range specified by the user
3
+
4
+ """
5
+
6
+ import numpy as np
7
+ import matplotlib
8
+ matplotlib.use("Agg")
9
+ import matplotlib.pyplot as plt
10
+ import matplotlib.pyplot as plt
11
+ from matplotlib.ticker import MultipleLocator
12
+ from ..utils.utils import choose_cmap, choose_aspect
13
+
14
+
15
+ def trajmap(matrix, residue_start, residue_end, vmax):
16
+ x_minor = 20
17
+ y_major = 50
18
+ y_minor = 10
19
+ vmin = matrix.iloc[:, 1:].values.min()
20
+ cmap = choose_cmap('viridis_capped')
21
+ aspect = choose_aspect('auto')
22
+ frames = matrix.shape[1]
23
+ if frames <= 100:
24
+ x_step = 10
25
+ elif frames <= 500:
26
+ x_step = 50
27
+ else:
28
+ x_step = 100
29
+
30
+ fig, ax = plt.subplots(figsize=(12, 8))
31
+ im = ax.imshow(matrix, cmap=cmap, vmin=vmin, vmax=vmax, aspect=aspect)
32
+ ax.invert_yaxis()
33
+
34
+ ax.set_xticks(np.arange(0, frames + 1, step=x_step))
35
+ ax.tick_params(axis='x', labelsize=14)
36
+ ax.set_yticks(np.arange(residue_start, residue_end, step=y_major),)
37
+ ax.tick_params(axis='y', labelsize=14)
38
+ ax.yaxis.set_minor_locator(MultipleLocator(y_minor))
39
+ ax.xaxis.set_minor_locator(MultipleLocator(x_minor))
40
+ for tick in ax.get_xticklabels():
41
+ tick.set_fontweight("bold")
42
+ for tick in ax.get_yticklabels():
43
+ tick.set_fontweight("bold")
44
+
45
+ ax.set_title("Trajectory Map", fontsize=20, fontweight="bold")
46
+ ax.set_ylabel("Residue", fontsize=18, fontweight="bold")
47
+ ax.set_xlabel("Frames", fontsize=18, fontweight="bold")
48
+ cbar = fig.colorbar(im, fraction=0.029, pad=0.028)
49
+ cbar.set_label("Shift / Å", fontsize=12, fontweight="bold")
50
+ fig.tight_layout()
51
+ plt.close(fig)
52
+ return fig
tmq/utils/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ __version__ = "1.0"
2
+
tmq/utils/utils.py ADDED
@@ -0,0 +1,233 @@
1
+ """ This contains all the utility functions used in the core modules and CLI wrappers
2
+
3
+ """
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ import mdtraj as mdt
8
+ from Bio.PDB import PDBParser
9
+
10
+
11
+
12
+ def ensure_pdb_extension(name):
13
+ return name if name.endswith(".pdb") else name + ".pdb"
14
+
15
+ def load_traj(topology, trajectories, stride):
16
+ return mdt.load(trajectories, top=topology, stride=stride)
17
+
18
+ def select_backbone(traj):
19
+ idx = traj.topology.select("backbone")
20
+ return traj.atom_slice(idx)
21
+
22
+ def align_to_first_frame(traj):
23
+ return traj.superpose(traj, 0)
24
+
25
+
26
+ def load_pdb_models(file):
27
+ parser = PDBParser(QUIET=True)
28
+ structure = parser.get_structure("prot", file)
29
+ return list(structure.get_models())
30
+
31
+ def build_residue_lookup(model):
32
+ lookup = {}
33
+ for residue in model.get_residues():
34
+ het, resnum, icode = residue.get_id()
35
+ if het == " ":
36
+ lookup[resnum] = residue
37
+ return lookup
38
+
39
+
40
+ def get_ca_coord(residue):
41
+ if "CA" in residue:
42
+ return np.array(residue["CA"].coord, dtype=float)
43
+ return np.zeros(3)
44
+
45
+ def get_backbone_com(residue, weights):
46
+ coords = []
47
+ w = []
48
+ for atom_name in ["N", "CA", "C", "O"]:
49
+ if atom_name in residue:
50
+ atom = residue[atom_name]
51
+ coords.append(atom.coord * weights[atom_name])
52
+ w.append(weights[atom_name])
53
+ if coords:
54
+ return np.sum(coords, axis=0) / np.sum(w)
55
+ return np.zeros(3)
56
+
57
+ def distance(a, b):
58
+ return np.linalg.norm(a - b)
59
+
60
+ def ensure_csv_extension(name):
61
+ return name if name.endswith(".csv") else name + ".csv"
62
+
63
+
64
+ def csv2matrix(csv_file):
65
+ matrix = pd.read_csv(csv_file, index_col=0)
66
+ return matrix
67
+
68
+
69
+ def matrix2shift(matrix, params):
70
+
71
+ matrix_array = np.array(matrix)
72
+
73
+ res1 = params[0]
74
+ res2 = params[1]
75
+ time1 = params[2]
76
+ time2 = params[3]
77
+
78
+ output = pd.DataFrame(data=np.arange(time1, time2, 1, dtype=float))
79
+
80
+ if res1 == res2:
81
+ output = matrix_array[res1]
82
+ else:
83
+ y = matrix_array[res1:res2, time1:time2]
84
+
85
+ i = 0
86
+ while i < len(output):
87
+ output.iloc[i] = np.average(y[:, i])
88
+ i = i + 1
89
+
90
+ return output
91
+
92
+
93
+ def csv2matrix(file):
94
+ return pd.read_csv(file, index_col=None)
95
+
96
+ def choose_cmap(cmap_choice):
97
+ if cmap_choice == 0:
98
+ return "magma"
99
+ elif cmap_choice == 1:
100
+ return "seismic"
101
+ elif cmap_choice == 5:
102
+ return "Greys"
103
+ elif cmap_choice == 6:
104
+ return "turbo"
105
+ return "viridis"
106
+
107
+ def choose_aspect(aspect):
108
+ if aspect == 0:
109
+ return "auto"
110
+ elif aspect == 1:
111
+ return "equal"
112
+ return "auto"
113
+
114
+ def ensure_png_extension(name):
115
+ return name if name.endswith(".png") else name + ".png"
116
+
117
+
118
+ def shift_to_dataframe(shift_data):
119
+ df = pd.read_csv(shift_data, header=None)
120
+ df = df.astype(float)
121
+ df = df.iloc[2:].reset_index(drop=True)
122
+ return df
123
+
124
+ def rolling_average(df, window):
125
+ return df.rolling(window).mean()
126
+
127
+ def auto_limits(df):
128
+ col = df.iloc[:, 0]
129
+ y_min = float(col.min())
130
+ y_max = float(col.max() + 0.5)
131
+ x_min = 0
132
+ x_max = len(df) - 1
133
+ return x_min, x_max, y_min, y_max
134
+
135
+
136
+
137
+ def parse_range(s):
138
+ """
139
+ Parse a residue range string like '110-125' into (110, 125).
140
+ """
141
+ try:
142
+ start, end = map(int, s.split("-"))
143
+ return start, end
144
+ except Exception:
145
+ raise ValueError("Residue range must be in the form start-end, e.g., 110-125")
146
+
147
+
148
+ import numpy as np
149
+ import pandas as pd
150
+ from scipy.signal import find_peaks
151
+
152
+ def detect(matrix, window, mindist, hotspot):
153
+ return extract_residue_shift_regions(
154
+ matrix,
155
+ window,
156
+ mindist,
157
+ hotspot,
158
+ )
159
+
160
+
161
+ def extract_residue_shift_regions(matrix, window, min_distance, top_n):
162
+
163
+ mat = np.array(matrix, dtype=float)
164
+
165
+ mean_shift = mat.mean(axis=1)
166
+
167
+ smooth = pd.Series(mean_shift).rolling(window, center=True).mean()
168
+ smooth = smooth.bfill().ffill()
169
+
170
+ peaks, props = find_peaks(smooth, distance=min_distance, prominence=0.1)
171
+
172
+ if len(peaks) == 0:
173
+ return []
174
+
175
+ prominences = props["prominences"]
176
+ ranked = np.argsort(prominences)[::-1]
177
+ top_peaks = peaks[ranked][:top_n]
178
+
179
+ regions = []
180
+ for p in top_peaks:
181
+ left = p
182
+ while left > 0 and smooth[left] > smooth[p] * 0.5:
183
+ left -= 1
184
+
185
+ right = p
186
+ while right < len(smooth)-1 and smooth[right] > smooth[p] * 0.5:
187
+ right += 1
188
+
189
+ regions.append((left, p, right))
190
+
191
+ return regions, mean_shift, smooth
192
+
193
+
194
+ def extract_region_submatrices(matrix, regions_only):
195
+ mat = matrix.values
196
+ submatrices = []
197
+ for start, end in regions_only:
198
+ sub = mat[start:end+1, :]
199
+ submatrices.append((start, end, sub))
200
+ return submatrices
201
+
202
+
203
+ def slice_matrix2shift(matrix, params):
204
+
205
+ matrix_array = np.array(matrix)
206
+
207
+ res1 = params[0]
208
+ res2 = params[1]
209
+ time1 = params[2]
210
+ time2 = params[3]
211
+
212
+ output = np.zeros(time2 - time1)
213
+
214
+ if res1 == res2:
215
+ output[:] = matrix_array[res1, time1:time2]
216
+ else:
217
+ y = matrix_array[res1:res2+1, time1:time2]
218
+ for i in range(output.shape[0]):
219
+ output[i] = np.mean(y[:, i])
220
+
221
+ return output
222
+
223
+
224
+
225
+ def load_matrix_4_diff_map(csv_path):
226
+ """Load a CSV file into a numeric matrix."""
227
+ return pd.read_csv(csv_path, header=None).values
228
+
229
+ def compute_mat_diff(A, B):
230
+ """Compute A - B with NaN mask."""
231
+ if A.shape != B.shape:
232
+ raise ValueError(f"Matrix shapes do not match: {A.shape} vs {B.shape}")
233
+ return A - B
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: tmquick
3
+ Version: 1.0.0
4
+ Summary: TrajMapQuick: Towards Fast Trajectory Map Analysis and Visualization
5
+ Author: Wande M. Oluyemi (PhD), Adeniyi T. Adewumi (PhD), Shadrach C. Eze, Stephen C. Nnemolisa, @ Research Laboratory for Rational Design of Drugs and Biomaterials (ResLaR Labs), Afe Babalola University, Ado-Ekiti Nigeria
6
+ Project-URL: Homepage, https://github.com/SHEDOOMTC/TrajMapQuick.git
7
+ Project-URL: Documentation, https://github.com/SHEDOOMTC/TrajMapQuick/blob/7997b0076a6c31bd725dba3ccdca4349b43250d4/README.md
8
+ Project-URL: DOI, https://github.com/SHEDOOMTC/TrajMapQuick.git
9
+ Requires-Python: >=3.9
10
+ License-File: LICENSE.md
11
+ Requires-Dist: numpy
12
+ Requires-Dist: pandas
13
+ Requires-Dist: matplotlib
14
+ Requires-Dist: seaborn
15
+ Requires-Dist: tqdm
16
+ Requires-Dist: biopython
17
+ Requires-Dist: scipy
18
+ Requires-Dist: netcdf4
19
+ Requires-Dist: colorama
20
+ Provides-Extra: md
21
+ Requires-Dist: mdtraj; extra == "md"
22
+ Dynamic: license-file
23
+ Dynamic: requires-python