Coverage for biobb_mem/ambertools/cpptraj_density.py: 89%

65 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-05-28 14:30 +0000

1#!/usr/bin/env python3 

2 

3"""Module containing the Cpptraj Density class and the command line interface.""" 

4from pathlib import Path, PurePath 

5from biobb_common.generic.biobb_object import BiobbObject 

6from biobb_common.tools.file_utils import launchlogger 

7 

8 

9class CpptrajDensity(BiobbObject): 

10 """ 

11 | biobb_mem CpptrajDensity 

12 | Wrapper of the Ambertools Cpptraj module for calculating density profile along an axis of a given cpptraj compatible trajectory. 

13 | Cpptraj (the successor to ptraj) is the main program in Ambertools for processing coordinate trajectories and data files. The parameter names and defaults are the same as the ones in the official `Cpptraj manual <https://raw.githubusercontent.com/Amber-MD/cpptraj/master/doc/CpptrajManual.pdf>`_. 

14 

15 Args: 

16 input_top_path (str): Path to the input structure or topology file. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/data/ambertools/topology.pdb>`_. Accepted formats: top (edam:format_3881), pdb (edam:format_1476), prmtop (edam:format_3881), parmtop (edam:format_3881), zip (edam:format_3987). 

17 input_traj_path (str): Path to the input trajectory to be processed. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/data/ambertools/trajectory.xtc>`_. Accepted formats: mdcrd (edam:format_3878), crd (edam:format_3878), cdf (edam:format_3650), netcdf (edam:format_3650), nc (edam:format_3650), restart (edam:format_3886), ncrestart (edam:format_3886), restartnc (edam:format_3886), dcd (edam:format_3878), charmm (edam:format_3887), cor (edam:format_2033), pdb (edam:format_1476), mol2 (edam:format_3816), trr (edam:format_3910), gro (edam:format_2033), binpos (edam:format_3885), xtc (edam:format_3875), cif (edam:format_1477), arc (edam:format_2333), sqm (edam:format_2033), sdf (edam:format_3814), conflib (edam:format_2033). 

18 output_cpptraj_path (str): Path to the output processed density analysis. File type: output. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/reference/ambertools/density_default.dat>`_. Accepted formats: dat (edam:format_1637), agr (edam:format_2033), xmgr (edam:format_2033), gnu (edam:format_2033). 

19 output_traj_path (str) (Optional): Path to the output processed trajectory. File type: output. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/reference/ambertools/trajectory_out.dcd>`_. Accepted formats: mdcrd (edam:format_3878), crd (edam:format_3878), cdf (edam:format_3650), netcdf (edam:format_3650), nc (edam:format_3650), restart (edam:format_3886), ncrestart (edam:format_3886), restartnc (edam:format_3886), dcd (edam:format_3878), charmm (edam:format_3887), cor (edam:format_2033), pdb (edam:format_1476), mol2 (edam:format_3816), trr (edam:format_3910), gro (edam:format_2033), binpos (edam:format_3885), xtc (edam:format_3875), cif (edam:format_1477), arc (edam:format_2333), sqm (edam:format_2033), sdf (edam:format_3814), conflib (edam:format_2033). 

20 properties (dic - Python dictionary object containing the tool parameters, not input/output files): 

21 * **start** (*int*) - (1) [1~100000|1] Starting frame for slicing 

22 * **end** (*int*) - (-1) [-1~100000|1] Ending frame for slicing 

23 * **steps** (*int*) - (1) [1~100000|1] Step for slicing 

24 * **density_type** (*str*) - ("number") Number, mass, partial charge (q) or electron (Ne - q) density. Electron density will be converted to e-/Å3 by dividing the average area spanned by the other two dimensions. 

25 * **mask** (*str*) - ("*") Arbitrary number of masks for atom selection; a dataset is created and the output will contain entries for each mask.. Default: all atoms. 

26 * **delta** (*float*) - (0.25) Resolution, i.e. determines number of slices (i.e. histogram bins). 

27 * **axis** (*str*) - ("z") Coordinate (axis) for density calculation. Vales: x, y, z. 

28 * **bintype** (*str*) - ("bincenter") Determine whether histogram bin coordinates will be based on bin center (default) or bin edges. Values: bicenter, binedge. 

29 * **restrict** (*str*) - (None) If specified, only calculate the density within a cylinder or square shape from the specified axis as defined by a distance cutoff. Values: cylinder, square. 

30 * **cutoff** (*float*) - (None) The distance cutoff for 'restrict'. Required if 'restrict' is specified. 

31 * **binary_path** (*str*) - ("cpptraj") Path to the cpptraj executable binary. 

32 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files. 

33 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist. 

34 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory. 

35 * **container_path** (*str*) - (None) Container path definition. 

36 * **container_image** (*str*) - ('afandiadib/ambertools:serial') Container image definition. 

37 * **container_volume_path** (*str*) - ('/tmp') Container volume path definition. 

38 * **container_working_dir** (*str*) - (None) Container working directory definition. 

39 * **container_user_id** (*str*) - (None) Container user_id definition. 

40 * **container_shell_path** (*str*) - ('/bin/bash') Path to default shell inside the container. 

41 

42 Examples: 

43 This is a use example of how to use the building block from Python:: 

44 

45 from biobb_mem.ambertools.cpptraj_density import cpptraj_density 

46 prop = { 

47 'density_type': 'number' 

48 } 

49 cpptraj_density(input_top_path='/path/to/myTopology.top', 

50 input_traj_path='/path/to/myTrajectory.xtc', 

51 output_cpptraj_path='/path/to/newAnalysis.dat', 

52 properties=prop) 

53 

54 Info: 

55 * wrapped_software: 

56 * name: Ambertools Cpptraj 

57 * version: >=22.5 

58 * license: GNU 

59 * ontology: 

60 * name: EDAM 

61 * schema: http://edamontology.org/EDAM.owl 

62 

63 """ 

64 

65 def __init__(self, input_top_path, input_traj_path, output_cpptraj_path, 

66 output_traj_path=None, properties=None, **kwargs) -> None: 

67 properties = properties or {} 

68 

69 # Call parent class constructor 

70 super().__init__(properties) 

71 self.locals_var_dict = locals().copy() 

72 

73 # Input/Output files 

74 self.io_dict = { 

75 "in": {"input_top_path": input_top_path, "input_traj_path": input_traj_path}, 

76 "out": {"output_cpptraj_path": output_cpptraj_path, "output_traj_path": output_traj_path} 

77 } 

78 

79 # Properties specific for BB 

80 self.instructions_file = 'instructions.in' 

81 self.start = properties.get('start', 1) 

82 self.end = properties.get('end', -1) 

83 self.steps = properties.get('steps', 1) 

84 self.slice = f' {self.start} {self.end} {self.steps}' 

85 self.density_type = properties.get('density_type', 'number') 

86 self.mask = properties.get('mask', '*') 

87 self.delta = properties.get('delta', 0.25) 

88 self.axis = properties.get('axis', 'z') 

89 self.bintype = properties.get('bintype', 'bincenter') 

90 self.restrict = properties.get('restrict', None) 

91 self.cutoff = properties.get('cutoff', None) 

92 self.binary_path = properties.get('binary_path', 'cpptraj') 

93 self.properties = properties 

94 

95 # Check the properties 

96 self.check_properties(properties) 

97 self.check_arguments() 

98 

99 def create_instructions_file(self, stage_io_dict, out_log, err_log): 

100 """Creates an input file using the properties file settings.""" 

101 instructions_list = [] 

102 instructions_file_name = PurePath(self.instructions_file).name 

103 # Always create the instructions file in the host staged sandbox. 

104 # In container mode, this directory is mounted to container_volume_path. 

105 unique_dir = stage_io_dict.get("unique_dir", "") 

106 self.instructions_file = str(Path(unique_dir).joinpath(instructions_file_name)) 

107 

108 instructions_list.append('parm ' + PurePath(stage_io_dict["in"]["input_top_path"]).name) 

109 instructions_list.append('trajin ' + PurePath(stage_io_dict["in"]["input_traj_path"]).name + self.slice) 

110 density_command = f'density {self.density_type} out {PurePath(stage_io_dict["out"]["output_cpptraj_path"]).name} {self.mask} delta {self.delta} {self.axis} {self.bintype}' 

111 if self.restrict: 

112 density_command += f' restrict {self.restrict}' 

113 if self.cutoff: 

114 density_command += f' cutoff {self.cutoff}' 

115 instructions_list.append(density_command) 

116 

117 # trajout 

118 if stage_io_dict["out"].get("output_traj_path"): 

119 instructions_list.append('trajout ' + PurePath(stage_io_dict["out"]["output_traj_path"]).name) 

120 

121 # Create .in file 

122 with open(self.instructions_file, 'w') as mdp: 

123 for line in instructions_list: 

124 mdp.write(line.strip() + '\n') 

125 

126 return self.instructions_file 

127 

128 @launchlogger 

129 def launch(self) -> int: 

130 """Execute the :class:`CpptrajDensity <ambertools.cpptraj_density.CpptrajDensity>` object.""" 

131 

132 # Setup Biobb 

133 if self.check_restart(): 

134 return 0 

135 self.stage_files() 

136 

137 if self.container_path: 

138 working_dir = self.container_volume_path if self.container_volume_path else "/data" 

139 else: 

140 working_dir = self.stage_io_dict.get("unique_dir", "") 

141 

142 # create instructions file 

143 self.create_instructions_file(self.stage_io_dict, self.out_log, self.err_log) 

144 # create cmd and launch execution 

145 self.cmd = ["cd", working_dir, ";", self.binary_path, '-i', PurePath(self.instructions_file).name] 

146 # Run Biobb block 

147 self.run_biobb() 

148 # Copy files to host 

149 self.copy_to_host() 

150 # remove temporary folder(s) 

151 self.remove_tmp_files() 

152 self.check_arguments(output_files_created=True, raise_exception=False) 

153 return self.return_code 

154 

155 

156def cpptraj_density(input_top_path: str, 

157 input_traj_path: str, 

158 output_cpptraj_path: str, 

159 output_traj_path: str = None, 

160 properties: dict = None, 

161 **kwargs) -> int: 

162 """Execute the :class:`CpptrajDensity <ambertools.cpptraj_density.CpptrajDensity>` class and 

163 execute the :meth:`launch() <ambertools.cpptraj_density.CpptrajDensity.launch>` method.""" 

164 return CpptrajDensity(**dict(locals())).launch() 

165 

166 

167cpptraj_density.__doc__ = CpptrajDensity.__doc__ 

168main = CpptrajDensity.get_main(cpptraj_density, "Calculates the density along an axis of a given cpptraj compatible trajectory.") 

169 

170if __name__ == '__main__': 

171 main()