From ab78b669b4763312bb54a4e70966d8c97ea8ec5a Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Mon, 17 Jun 2024 22:08:51 -0400 Subject: [PATCH 1/7] AnalysisRunner --- pytraj/all_actions.py | 115 ++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/pytraj/all_actions.py b/pytraj/all_actions.py index 9e45ab133..32d046e7e 100644 --- a/pytraj/all_actions.py +++ b/pytraj/all_actions.py @@ -85,6 +85,28 @@ class DatasetType(StrEnum): XYMESH = 'xymesh' MATRIX3x3 = 'matrix3x3' +class AnalysisRunner: + def __init__(self, analysis_class): + self.datasets = CpptrajDatasetList() + self.analysis = analysis_class() + + def add_dataset(self, dataset_type, dataset_name, data): + if dataset_type == DatasetType.COORDS: + crdname = '_DEFAULTCRD_' + self.datasets.add(dataset_type.value, name=crdname) + self.datasets[0].top = data.top + for frame in data: + self.datasets[0].append(frame) + else: + self.datasets.add(dataset_type, dataset_name) + if dataset_type == DatasetType.XYMESH: + self.datasets[-1]._append_from_array(data.T) + else: + self.datasets[-1].data = np.asarray(data).astype('f8') + + def run_analysis(self, command): + self.analysis(command, dslist=self.datasets) + return self.datasets def _assert_mutable(trajiter): @@ -1935,18 +1957,14 @@ def timecorr(vec0, vec1, order=2, tstep=1., tcorr=10000., norm=False, dtype='nda norm : bool, default False dtype : str, default 'ndarray' """ - time_correlation_action = c_analysis.Analysis_Timecorr() - action_datasets = CpptrajDatasetList() - - action_datasets.add(DatasetType.VECTOR, "_vec0") - action_datasets.add(DatasetType.VECTOR, "_vec1") - action_datasets[0].data = np.asarray(vec0).astype('f8') - action_datasets[1].data = np.asarray(vec1).astype('f8') + runner = AnalysisRunner(c_analysis.Analysis_Timecorr) + runner.add_dataset(DatasetType.VECTOR, "_vec0", vec0) + runner.add_dataset(DatasetType.VECTOR, "_vec1", vec1) command = f"vec1 _vec0 vec2 _vec1 order {order} tstep {tstep} tcorr {tcorr} {'norm' if norm else ''}" - time_correlation_action(command, dslist=action_datasets) + runner.run_analysis(command) - return get_data_from_dtype(action_datasets[2:], dtype=dtype) + return get_data_from_dtype(runner.datasets[2:], dtype=dtype) @super_dispatch() @@ -2079,17 +2097,13 @@ def crank(data0, data1, mode='distance', dtype='ndarray'): ----- Same as `crank` in cpptraj """ - action_datasets = CpptrajDatasetList() - action_datasets.add(DatasetType.DOUBLE, "d0") - action_datasets.add(DatasetType.DOUBLE, "d1") - - action_datasets[0].data = np.asarray(data0) - action_datasets[1].data = np.asarray(data1) + runner = AnalysisRunner(c_analysis.Analysis_CrankShaft) + runner.add_dataset(DatasetType.DOUBLE, "d0", data0) + runner.add_dataset(DatasetType.DOUBLE, "d1", data1) - act = c_analysis.Analysis_CrankShaft() command = ' '.join((mode, 'd0', 'd1')) with capture_stdout() as (out, err): - act(command, dslist=action_datasets) + runner.run_analysis(command) return out.read() @@ -2768,14 +2782,12 @@ def lowestcurve(data, points=10, step=0.2): data = np.asarray(data).T - action_datasets = CpptrajDatasetList() - action_datasets.add(DatasetType.XYMESH, 'mydata') - action_datasets[0]._append_from_array(data) + runner = AnalysisRunner(c_analysis.Analysis_LowestCurve) + runner.add_dataset(DatasetType.XYMESH, 'mydata', data) - analysis_lowest_curve = c_analysis.Analysis_LowestCurve() - analysis_lowest_curve(command, dslist=action_datasets) + runner.run_analysis(command) - return np.array([action_datasets[-1]._xcrd(), np.array(action_datasets[-1].values)]) + return np.array([runner.datasets[-1]._xcrd(), np.array(runner.datasets[-1].values)]) def acorr(data, dtype='ndarray', option=''): @@ -2793,15 +2805,13 @@ def acorr(data, dtype='ndarray', option=''): ----- Same as `autocorr` in cpptraj """ - action_datasets = CpptrajDatasetList() - action_datasets.add(DatasetType.DOUBLE, "d0") - - action_datasets[0].data = np.asarray(data) + runner = AnalysisRunner(c_analysis.Analysis_AutoCorr) + runner.add_dataset(DatasetType.DOUBLE, "d0", np.asarray(data)) - act = c_analysis.Analysis_AutoCorr() command = "d0 out _tmp.out" - act(command, dslist=action_datasets) - return get_data_from_dtype(action_datasets[1:], dtype=dtype) + runner.run_analysis(command) + + return get_data_from_dtype(runner.datasets[1:], dtype=dtype) auto_correlation_function = acorr @@ -2820,17 +2830,14 @@ def xcorr(data0, data1, dtype='ndarray'): ----- Same as `corr` in cpptraj """ + runner = AnalysisRunner(c_analysis.Analysis_Corr) + runner.add_dataset(DatasetType.DOUBLE, "d0", np.asarray(data0)) + runner.add_dataset(DatasetType.DOUBLE, "d1", np.asarray(data1)) - action_datasets = CpptrajDatasetList() - action_datasets.add(DatasetType.DOUBLE, "d0") - action_datasets.add(DatasetType.DOUBLE, "d1") - - action_datasets[0].data = np.asarray(data0) - action_datasets[1].data = np.asarray(data1) + command = "d0 d1 out _tmp.out" + runner.run_analysis(command) - act = c_analysis.Analysis_Corr() - act("d0 d1 out _tmp.out", dslist=action_datasets) - return get_data_from_dtype(action_datasets[2:3], dtype=dtype) + return get_data_from_dtype(runner.datasets[2:3], dtype=dtype) cross_correlation_function = xcorr @@ -2900,7 +2907,6 @@ def strip(obj, mask): def rotdif(matrices, command): """ - Parameters ---------- matrices : 3D array, shape=(n_frames, 3, 3) @@ -2917,18 +2923,15 @@ def rotdif(matrices, command): ----- This method interface will be changed. """ - # TODO: update this method if cpptraj dumps data to CpptrajDatasetList matrices = np.asarray(matrices) - action_datasets = CpptrajDatasetList() - action_datasets.add(DatasetType.MATRIX3x3, name='myR0') - action_datasets[-1].aspect = "RM" - action_datasets[-1]._append_from_array(matrices) + runner = AnalysisRunner(c_analysis.Analysis_Rotdif) + runner.add_dataset(DatasetType.MATRIX3x3, "myR0", matrices) command = 'rmatrix myR0[RM] ' + command - act = c_analysis.Analysis_Rotdif() with capture_stdout() as (out, _): - act(command, dslist=action_datasets) + runner.run_analysis(command) + return out.read() @@ -2964,19 +2967,11 @@ def wavelet(traj, command): >>> command = ' '.join((c0, c1)) >>> wavelet_dict = pt.wavelet(traj, command) """ - - action_datasets = CpptrajDatasetList() - crdname = '_DEFAULTCRD_' - action_datasets.add(DatasetType.COORDS.value, name=crdname) - action_datasets[0].top = traj.top - - for frame in traj: - action_datasets[0].append(frame) - - act = c_analysis.Analysis_Wavelet() - act(command, dslist=action_datasets) - action_datasets.remove_set(action_datasets[crdname]) - return get_data_from_dtype(action_datasets, dtype='dict') + runner = AnalysisRunner(c_analysis.Analysis_Wavelet) + runner.add_dataset(DatasetType.COORDS, "_DEFAULTCRD_", traj) + runner.run_analysis(command) + runner.datasets.remove_set(runner.datasets["_DEFAULTCRD_"]) + return get_data_from_dtype(runner.datasets, dtype='dict') def atom_map(traj, ref, rmsfit=False): From be127965a295ae114ef2fc7c20fcf2e8be0685ef Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Mon, 17 Jun 2024 22:13:47 -0400 Subject: [PATCH 2/7] more --- pytraj/all_actions.py | 46 +++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/pytraj/all_actions.py b/pytraj/all_actions.py index 32d046e7e..23b3b0c17 100644 --- a/pytraj/all_actions.py +++ b/pytraj/all_actions.py @@ -101,6 +101,11 @@ def add_dataset(self, dataset_type, dataset_name, data): self.datasets.add(dataset_type, dataset_name) if dataset_type == DatasetType.XYMESH: self.datasets[-1]._append_from_array(data.T) + elif dataset_type == DatasetType.MATRIX_DBL: + self.datasets[-1].data = np.asarray(data).astype('f8') + elif dataset_type == DatasetType.MODES: + # For MODES, we don't set the data immediately + pass else: self.datasets[-1].data = np.asarray(data).astype('f8') @@ -3118,19 +3123,21 @@ def analyze_modes(mode_type, scalar_type='mwcovar', options='', dtype='dict'): - analysis_modes = c_analysis.Analysis_Modes() - action_datasets = CpptrajDatasetList() + runner = AnalysisRunner(c_analysis.Analysis_Modes) my_modes = 'my_modes' - modes = action_datasets.add('modes', name=my_modes) + runner.add_dataset(DatasetType.MODES, my_modes, None) + + modes = runner.datasets[-1] modes.scalar_type = scalar_type - # cpptraj will use natoms = modes.NavgCrd() modes._allocate_avgcoords(eigenvectors.shape[1]) modes._set_modes(False, eigenvectors.shape[0], eigenvectors.shape[1], eigenvalues, eigenvectors.flatten()) + command = ' '.join((mode_type, 'name {}'.format(my_modes), options)) - analysis_modes(command, dslist=action_datasets) - action_datasets._pop(0) - return get_data_from_dtype(action_datasets, dtype=dtype) + runner.run_analysis(command) + + runner.datasets._pop(0) + return get_data_from_dtype(runner.datasets, dtype=dtype) def ti(fn, options=''): @@ -3154,16 +3161,19 @@ def ti(fn, options=''): - EXPERIMENTAL """ from pytraj import io - action_datasets = io.read_data(fn, 'name TI_set index 1') - act = c_analysis.Analysis_TI() + data = io.read_data(fn, 'name TI_set index 1') + + runner = AnalysisRunner(c_analysis.Analysis_TI) + runner.add_dataset(DatasetType.DOUBLE, "TI_set", data) + command = 'TI_set ' + options - act(command, dslist=action_datasets) - return action_datasets + runner.run_analysis(command) + + return runner.datasets def hausdorff(matrix, options='', dtype='ndarray'): """ - Parameters ---------- matrix : 2D array @@ -3178,17 +3188,15 @@ def hausdorff(matrix, options='', dtype='ndarray'): ----- - cpptraj help: pytraj.info('hausdorff') """ - action_datasets = CpptrajDatasetList() - matrix_dataset = action_datasets.add('matrix_dbl', name='my_matrix') - matrix_dataset.data = np.asarray(matrix, dtype='f8') + runner = AnalysisRunner(c_analysis.Analysis_Hausdorff) + runner.add_dataset(DatasetType.MATRIX_DBL, "my_matrix", matrix) - act = c_analysis.Analysis_Hausdorff() command = f"my_matrix {options}" - act(command, dslist=action_datasets) + runner.run_analysis(command) - action_datasets._pop(0) + runner.datasets._pop(0) - data = get_data_from_dtype(action_datasets, dtype) + data = get_data_from_dtype(runner.datasets, dtype) return data From fbd9853fdca02e80d7a9eeb22e27af14f32394ae Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Mon, 17 Jun 2024 22:30:38 -0400 Subject: [PATCH 3/7] fix --- pytraj/all_actions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytraj/all_actions.py b/pytraj/all_actions.py index 23b3b0c17..2e12ddc4a 100644 --- a/pytraj/all_actions.py +++ b/pytraj/all_actions.py @@ -84,6 +84,7 @@ class DatasetType(StrEnum): MODES = 'modes' XYMESH = 'xymesh' MATRIX3x3 = 'matrix3x3' + MATRIX_DBL = 'matrix_dbl' class AnalysisRunner: def __init__(self, analysis_class): From fb128ca76774d260e00acdf0bdd07cf9fd3a617f Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Mon, 17 Jun 2024 22:31:57 -0400 Subject: [PATCH 4/7] fix more --- pytraj/all_actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytraj/all_actions.py b/pytraj/all_actions.py index 2e12ddc4a..c69a8cc51 100644 --- a/pytraj/all_actions.py +++ b/pytraj/all_actions.py @@ -101,7 +101,7 @@ def add_dataset(self, dataset_type, dataset_name, data): else: self.datasets.add(dataset_type, dataset_name) if dataset_type == DatasetType.XYMESH: - self.datasets[-1]._append_from_array(data.T) + self.datasets[-1]._append_from_array(data) elif dataset_type == DatasetType.MATRIX_DBL: self.datasets[-1].data = np.asarray(data).astype('f8') elif dataset_type == DatasetType.MODES: From a620671a2476b981e25b0e9290972b49e48cc53a Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Mon, 17 Jun 2024 23:35:07 -0400 Subject: [PATCH 5/7] fix --- pytraj/all_actions.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pytraj/all_actions.py b/pytraj/all_actions.py index c69a8cc51..b93fc984c 100644 --- a/pytraj/all_actions.py +++ b/pytraj/all_actions.py @@ -91,7 +91,7 @@ def __init__(self, analysis_class): self.datasets = CpptrajDatasetList() self.analysis = analysis_class() - def add_dataset(self, dataset_type, dataset_name, data): + def add_dataset(self, dataset_type, dataset_name, data, aspect=None): if dataset_type == DatasetType.COORDS: crdname = '_DEFAULTCRD_' self.datasets.add(dataset_type.value, name=crdname) @@ -107,6 +107,9 @@ def add_dataset(self, dataset_type, dataset_name, data): elif dataset_type == DatasetType.MODES: # For MODES, we don't set the data immediately pass + elif dataset_type == DatasetType.MATRIX3x3: + self.datasets[-1].aspect = aspect + self.datasets[-1]._append_from_array(data) else: self.datasets[-1].data = np.asarray(data).astype('f8') @@ -2932,7 +2935,7 @@ def rotdif(matrices, command): matrices = np.asarray(matrices) runner = AnalysisRunner(c_analysis.Analysis_Rotdif) - runner.add_dataset(DatasetType.MATRIX3x3, "myR0", matrices) + runner.add_dataset(DatasetType.MATRIX3x3, "myR0", matrices, aspect='RH') command = 'rmatrix myR0[RM] ' + command with capture_stdout() as (out, _): @@ -3162,15 +3165,11 @@ def ti(fn, options=''): - EXPERIMENTAL """ from pytraj import io - data = io.read_data(fn, 'name TI_set index 1') - - runner = AnalysisRunner(c_analysis.Analysis_TI) - runner.add_dataset(DatasetType.DOUBLE, "TI_set", data) - + action_datasets = io.read_data(fn, 'name TI_set index 1') + act = c_analysis.Analysis_TI() command = 'TI_set ' + options - runner.run_analysis(command) - - return runner.datasets + act(command, dslist=action_datasets) + return action_datasets def hausdorff(matrix, options='', dtype='ndarray'): From a4253dc976b832794d7f720706f5364be91738c2 Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Mon, 17 Jun 2024 23:37:52 -0400 Subject: [PATCH 6/7] small refactoring --- pytraj/all_actions.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pytraj/all_actions.py b/pytraj/all_actions.py index b93fc984c..62e2655b0 100644 --- a/pytraj/all_actions.py +++ b/pytraj/all_actions.py @@ -99,19 +99,19 @@ def add_dataset(self, dataset_type, dataset_name, data, aspect=None): for frame in data: self.datasets[0].append(frame) else: - self.datasets.add(dataset_type, dataset_name) + dataset = self.datasets.add(dataset_type, dataset_name) if dataset_type == DatasetType.XYMESH: - self.datasets[-1]._append_from_array(data) + dataset._append_from_array(data) elif dataset_type == DatasetType.MATRIX_DBL: - self.datasets[-1].data = np.asarray(data).astype('f8') + dataset.data = np.asarray(data).astype('f8') elif dataset_type == DatasetType.MODES: # For MODES, we don't set the data immediately pass elif dataset_type == DatasetType.MATRIX3x3: - self.datasets[-1].aspect = aspect - self.datasets[-1]._append_from_array(data) + dataset.aspect = aspect + dataset._append_from_array(data) else: - self.datasets[-1].data = np.asarray(data).astype('f8') + dataset.data = np.asarray(data).astype('f8') def run_analysis(self, command): self.analysis(command, dslist=self.datasets) From 2d60660f8ffafe835ee2e79a3ea202c0a887a7d5 Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Mon, 17 Jun 2024 23:53:00 -0400 Subject: [PATCH 7/7] restore rotdif --- pytraj/all_actions.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pytraj/all_actions.py b/pytraj/all_actions.py index 62e2655b0..2075d0b79 100644 --- a/pytraj/all_actions.py +++ b/pytraj/all_actions.py @@ -2914,8 +2914,10 @@ def strip(obj, mask): raise ValueError('object must be either Trajectory or Topology') +# FIXME: use AnalysisRunner def rotdif(matrices, command): """ + Parameters ---------- matrices : 3D array, shape=(n_frames, 3, 3) @@ -2932,15 +2934,20 @@ def rotdif(matrices, command): ----- This method interface will be changed. """ + # TODO: update this method if cpptraj dumps data to CpptrajDatasetList matrices = np.asarray(matrices) - runner = AnalysisRunner(c_analysis.Analysis_Rotdif) - runner.add_dataset(DatasetType.MATRIX3x3, "myR0", matrices, aspect='RH') + + action_datasets = CpptrajDatasetList() + action_datasets.add(DatasetType.MATRIX3x3, name='myR0') + action_datasets[-1].aspect = "RM" + action_datasets[-1]._append_from_array(matrices) + command = 'rmatrix myR0[RM] ' + command + act = c_analysis.Analysis_Rotdif() with capture_stdout() as (out, _): - runner.run_analysis(command) - + act(command, dslist=action_datasets) return out.read()