diff --git a/mrdna/model/arbdmodel.py b/mrdna/model/arbdmodel.py index 197bddbce8755f8e09fe87ec8beecd9988a8d1c6..de24a3a5675f60073a0cb629410740f0211d6083 100644 --- a/mrdna/model/arbdmodel.py +++ b/mrdna/model/arbdmodel.py @@ -1191,259 +1191,3 @@ run {num_steps:d} self.write_namd_configuration( output_name, output_directory = output_directory ) os.sync() - - """ oxDNA """ - ## https://dna.physics.ox.ac.uk/index.php/Documentation#Input_file - - - def _write_oxdna_configuration(self, filename): - - _angstroms_to_oxdna = 0.11739845 ## units "AA" "8.518e-10 m" - with open(filename,'w') as fh: - fh.write("""t = {temperature} -b = {dimX} {dimY} {dimZ} -E = 0 0 0 -""".format(temperature=self.temperature, - dimX = self.dimensions[0]*_angstroms_to_oxdna, - dimY = self.dimensions[1]*_angstroms_to_oxdna, - dimZ = self.dimensions[2]*_angstroms_to_oxdna)) - - base_vec = np.array((1,0,0)) # TODO - norm_vec = np.array((0,0,1)) # TODO - - ## Traverse 3'-to-5' - for nt in [nt for s in self.strands for nt in s.oxdna_nt[::-1]]: - data = dict() - # o = nt.collapsedOrientation() - o = nt.orientation - for k,v in zip('x y z'.split(),nt.collapsedPosition()): - data[k] = v * _angstroms_to_oxdna - for k,v in zip('x y z'.split(),o.dot(base_vec)): - data['b'+k] = v - for k,v in zip('x y z'.split(),o.dot(norm_vec)): - data['n'+k] = v - fh.write("{x} {y} {z} {bx} {by} {bz} {nx} {ny} {nz} 0 0 0 0 0 0\n".format(**data) - ) - - def _write_oxdna_topology(self,filename): - - strands = [s for s in self.strands if s.num_nt > 0] - with open(filename,'w') as fh: - - fh.write("{num_nts} {num_strands}\n".format( - num_nts = sum([s.num_nt for s in strands]), - num_strands = len(self.strands))) - - idx = 0 - sidx = 1 - for strand in strands: - prev = idx+len(strand.num_nt) if strand.is_circular else -1 - last = idx if strand.is_circular else -1 - - ## Traverse 3'-to-5' - sequence = [seq for s in strand.strand_segments - for seq in s.get_sequence()][::-1] - for seq in sequence[:-1]: - ## strand seq 3' 5' - fh.write("{} {} {} {}\n".format(sidx, seq, prev, idx+1)) - prev = idx - idx += 1 - seq = sequence[-1] - fh.write("{} {} {} {}\n".format(sidx, seq, prev, last)) - idx += 1 - sidx += 1 - - def _write_oxdna_input(self, filename, - topology, - conf_file, - trajectory_file, - last_conf_file, - log_file, - num_steps = 1e6, - interaction_type = 'DNA2', - salt_concentration = None, - print_conf_interval = None, - print_energy_every = None, - timestep = 0.003, - sim_type = "MD", - backend = None, - backend_precision = None, - seed = None, - newtonian_steps = 103, - diff_coeff = 2.50, - thermostat = "john", - list_type = "cells", - ensemble = "nvt", - delta_translation = 0.22, - delta_rotation = 0.22, - verlet_skin = 0.5, - max_backbone_force = 5, - ): - - if seed is None: - import random - seed = random.randint(1,99999) - - temperature = self.temperature - num_steps = int(num_steps) - newtonian_steps = int(newtonian_steps) - - if print_conf_interval is None: - # print_conf_interval = min(num_steps//100) - print_conf_interval = 10000 - print_conf_interval = int(print_conf_interval) - - if print_energy_every is None: - print_energy_every = print_conf_interval - print_energy_every = int(print_energy_every) - - if max_backbone_force is not None: - max_backbone_force = 'max_backbone_force = {}'.format(max_backbone_force) - - - if interaction_type in ('DNA2',): - if salt_concentration is None: - try: - ## units "80 epsilon0 295 k K / (2 (AA)**2 e**2/particle)" mM - salt_concentration = 9331.3126/self.debye_length**2 - except: - salt_concentration = 0.5 - salt_concentration = 'salt_concentration = {}'.format(salt_concentration) - else: - salt_concentration = '' - - if backend is None: - backend = 'CUDA' if sim_type == 'MD' else 'CPU' - - if backend_precision is None: - backend_precision = 'mixed' if backend == 'CUDA' else 'double' - - if sim_type == 'VMMC': - ensemble = 'ensemble = {}'.format(ensemble) - delta_translation = 'delta_translation = {}'.format(delta_translation) - delta_rotation = 'delta_rotation = {}'.format(delta_rotation) - else: - ensemble = '' - delta_translation = '' - delta_rotation = '' - - with open(filename,'w') as fh: - fh.write("""############################## -#### PROGRAM PARAMETERS #### -############################## -interaction_type = {interaction_type} -{salt_concentration} -sim_type = {sim_type} -backend = {backend} -backend_precision = {backend_precision} -#debug = 1 -seed = {seed} - -############################## -#### SIM PARAMETERS #### -############################## -steps = {num_steps:d} -newtonian_steps = {newtonian_steps:d} -diff_coeff = {diff_coeff} -thermostat = {thermostat} - -list_type = {list_type} -{ensemble} -{delta_translation} -{delta_rotation} - -T = {temperature:f} K -dt = {timestep} -verlet_skin = {verlet_skin} -{max_backbone_force} - -############################## -#### INPUT / OUTPUT #### -############################## -topology = {topology} -conf_file = {conf_file} -lastconf_file = {last_conf_file} -trajectory_file = {trajectory_file} -refresh_vel = 1 -log_file = {log_file} -no_stdout_energy = 1 -restart_step_counter = 1 -energy_file = {log_file}.energy.dat -print_conf_interval = {print_conf_interval} -print_energy_every = {print_energy_every} -time_scale = linear -external_forces = 0 -""".format( **locals() )) - - def simulate_oxdna(self, output_name, directory='.', output_directory='output', topology=None, configuration=None, oxDNA=None, **oxdna_args): - - if output_directory == '': output_directory='.' - d_orig = os.getcwd() - if not os.path.exists(directory): - os.makedirs(directory) - - os.chdir(directory) - try: - - if oxDNA is None: - for path in os.environ["PATH"].split(os.pathsep): - path = path.strip('"') - fname = os.path.join(path, "oxDNA") - if os.path.isfile(fname) and os.access(fname, os.X_OK): - oxDNA = fname - break - - if oxDNA is None: raise Exception("oxDNA was not found") - - if not os.path.exists(oxDNA): - raise Exception("oxDNA was not found") - if not os.path.isfile(oxDNA): - raise Exception("oxDNA was not found") - if not os.access(oxDNA, os.X_OK): - raise Exception("oxDNA is not executable") - - if not os.path.exists(output_directory): - os.makedirs(output_directory) - elif not os.path.isdir(output_directory): - raise Exception("output_directory '%s' is not a directory!" % output_directory) - - - if configuration is None: - configuration = "{}.conf".format(output_name) - self._write_oxdna_configuration(configuration) - # elif not Path(configuration).exists(): - # raise Exception("Unable to find oxDNA configuration file '{}'.".format(configuration)) - - if topology is None: - topology = "{}-topology.dat".format(output_name) - self._write_oxdna_topology(topology) - elif not Path(topology).exists(): - raise Exception("Unable to find oxDNA topology file '{}'.".format(topology)) - - last_conf_file = "{}/{}.last.conf".format(output_directory,output_name) - input_file = "{}-input".format(output_name) - - self._write_oxdna_input(input_file, - topology = topology, - conf_file = configuration, - trajectory_file = "{}/{}.dat".format(output_directory,output_name), - last_conf_file = last_conf_file, - log_file="{}/{}.log".format(output_directory,output_name), - **oxdna_args) - os.sync() - ## TODO: call oxdna - cmd = [oxDNA, input_file] - - cmd = tuple(str(x) for x in cmd) - - print("Running oxDNA with: %s" % " ".join(cmd)) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) - for line in process.stdout: - sys.stdout.write(line) - sys.stdout.flush() - - return topology,last_conf_file - finally: - os.chdir(d_orig) - - diff --git a/mrdna/segmentmodel.py b/mrdna/segmentmodel.py index 0273c5dbe183390f5b80110569f6b8cd97c54834..6f5efa809c6b7b118f87eb0ffbbe8732823200d0 100644 --- a/mrdna/segmentmodel.py +++ b/mrdna/segmentmodel.py @@ -3248,12 +3248,265 @@ proc calcforces {} { first_atomic_index = s.generate_atomic_model(scale,first_atomic_index) self._assign_basepairs() + """ OxDNA """ + ## https://dna.physics.ox.ac.uk/index.php/Documentation#Input_file def generate_oxdna_model(self, scale=1): self.clear_beads() self.children = self.strands for s in self.strands: s.generate_oxdna_model() + def _write_oxdna_configuration(self, filename): + + _angstroms_to_oxdna = 0.11739845 ## units "AA" "8.518e-10 m" + with open(filename,'w') as fh: + fh.write("""t = {temperature} +b = {dimX} {dimY} {dimZ} +E = 0 0 0 +""".format(temperature=self.temperature, + dimX = self.dimensions[0]*_angstroms_to_oxdna, + dimY = self.dimensions[1]*_angstroms_to_oxdna, + dimZ = self.dimensions[2]*_angstroms_to_oxdna)) + + base_vec = np.array((1,0,0)) # TODO + norm_vec = np.array((0,0,1)) # TODO + + ## Traverse 3'-to-5' + for nt in [nt for s in self.strands for nt in s.oxdna_nt[::-1]]: + data = dict() + # o = nt.collapsedOrientation() + o = nt.orientation + for k,v in zip('x y z'.split(),nt.collapsedPosition()): + data[k] = v * _angstroms_to_oxdna + for k,v in zip('x y z'.split(),o.dot(base_vec)): + data['b'+k] = v + for k,v in zip('x y z'.split(),o.dot(norm_vec)): + data['n'+k] = v + fh.write("{x} {y} {z} {bx} {by} {bz} {nx} {ny} {nz} 0 0 0 0 0 0\n".format(**data) + ) + + def _write_oxdna_topology(self,filename): + + strands = [s for s in self.strands if s.num_nt > 0] + with open(filename,'w') as fh: + + fh.write("{num_nts} {num_strands}\n".format( + num_nts = sum([s.num_nt for s in strands]), + num_strands = len(self.strands))) + + idx = 0 + sidx = 1 + for strand in strands: + prev = idx+len(strand.num_nt) if strand.is_circular else -1 + last = idx if strand.is_circular else -1 + + ## Traverse 3'-to-5' + sequence = [seq for s in strand.strand_segments + for seq in s.get_sequence()][::-1] + for seq in sequence[:-1]: + ## strand seq 3' 5' + fh.write("{} {} {} {}\n".format(sidx, seq, prev, idx+1)) + prev = idx + idx += 1 + seq = sequence[-1] + fh.write("{} {} {} {}\n".format(sidx, seq, prev, last)) + idx += 1 + sidx += 1 + + def _write_oxdna_input(self, filename, + topology, + conf_file, + trajectory_file, + last_conf_file, + log_file, + num_steps = 1e6, + interaction_type = 'DNA2', + salt_concentration = None, + print_conf_interval = None, + print_energy_every = None, + timestep = 0.003, + sim_type = "MD", + backend = None, + backend_precision = None, + seed = None, + newtonian_steps = 103, + diff_coeff = 2.50, + thermostat = "john", + list_type = "cells", + ensemble = "nvt", + delta_translation = 0.22, + delta_rotation = 0.22, + verlet_skin = 0.5, + max_backbone_force = 5, + ): + + if seed is None: + import random + seed = random.randint(1,99999) + + temperature = self.temperature + num_steps = int(num_steps) + newtonian_steps = int(newtonian_steps) + + if print_conf_interval is None: + # print_conf_interval = min(num_steps//100) + print_conf_interval = 10000 + print_conf_interval = int(print_conf_interval) + + if print_energy_every is None: + print_energy_every = print_conf_interval + print_energy_every = int(print_energy_every) + + if max_backbone_force is not None: + max_backbone_force = 'max_backbone_force = {}'.format(max_backbone_force) + + + if interaction_type in ('DNA2',): + if salt_concentration is None: + try: + ## units "80 epsilon0 295 k K / (2 (AA)**2 e**2/particle)" mM + salt_concentration = 9331.3126/self.debye_length**2 + except: + salt_concentration = 0.5 + salt_concentration = 'salt_concentration = {}'.format(salt_concentration) + else: + salt_concentration = '' + + if backend is None: + backend = 'CUDA' if sim_type == 'MD' else 'CPU' + + if backend_precision is None: + backend_precision = 'mixed' if backend == 'CUDA' else 'double' + + if sim_type == 'VMMC': + ensemble = 'ensemble = {}'.format(ensemble) + delta_translation = 'delta_translation = {}'.format(delta_translation) + delta_rotation = 'delta_rotation = {}'.format(delta_rotation) + else: + ensemble = '' + delta_translation = '' + delta_rotation = '' + + with open(filename,'w') as fh: + fh.write("""############################## +#### PROGRAM PARAMETERS #### +############################## +interaction_type = {interaction_type} +{salt_concentration} +sim_type = {sim_type} +backend = {backend} +backend_precision = {backend_precision} +#debug = 1 +seed = {seed} + +############################## +#### SIM PARAMETERS #### +############################## +steps = {num_steps:d} +newtonian_steps = {newtonian_steps:d} +diff_coeff = {diff_coeff} +thermostat = {thermostat} + +list_type = {list_type} +{ensemble} +{delta_translation} +{delta_rotation} + +T = {temperature:f} K +dt = {timestep} +verlet_skin = {verlet_skin} +{max_backbone_force} + +############################## +#### INPUT / OUTPUT #### +############################## +topology = {topology} +conf_file = {conf_file} +lastconf_file = {last_conf_file} +trajectory_file = {trajectory_file} +refresh_vel = 1 +log_file = {log_file} +no_stdout_energy = 1 +restart_step_counter = 1 +energy_file = {log_file}.energy.dat +print_conf_interval = {print_conf_interval} +print_energy_every = {print_energy_every} +time_scale = linear +external_forces = 0 +""".format( **locals() )) + + def simulate_oxdna(self, output_name, directory='.', output_directory='output', topology=None, configuration=None, oxDNA=None, **oxdna_args): + + if output_directory == '': output_directory='.' + d_orig = os.getcwd() + if not os.path.exists(directory): + os.makedirs(directory) + + os.chdir(directory) + try: + + if oxDNA is None: + for path in os.environ["PATH"].split(os.pathsep): + path = path.strip('"') + fname = os.path.join(path, "oxDNA") + if os.path.isfile(fname) and os.access(fname, os.X_OK): + oxDNA = fname + break + + if oxDNA is None: raise Exception("oxDNA was not found") + + if not os.path.exists(oxDNA): + raise Exception("oxDNA was not found") + if not os.path.isfile(oxDNA): + raise Exception("oxDNA was not found") + if not os.access(oxDNA, os.X_OK): + raise Exception("oxDNA is not executable") + + if not os.path.exists(output_directory): + os.makedirs(output_directory) + elif not os.path.isdir(output_directory): + raise Exception("output_directory '%s' is not a directory!" % output_directory) + + + if configuration is None: + configuration = "{}.conf".format(output_name) + self._write_oxdna_configuration(configuration) + # elif not Path(configuration).exists(): + # raise Exception("Unable to find oxDNA configuration file '{}'.".format(configuration)) + + if topology is None: + topology = "{}-topology.dat".format(output_name) + self._write_oxdna_topology(topology) + elif not Path(topology).exists(): + raise Exception("Unable to find oxDNA topology file '{}'.".format(topology)) + + last_conf_file = "{}/{}.last.conf".format(output_directory,output_name) + input_file = "{}-input".format(output_name) + + self._write_oxdna_input(input_file, + topology = topology, + conf_file = configuration, + trajectory_file = "{}/{}.dat".format(output_directory,output_name), + last_conf_file = last_conf_file, + log_file="{}/{}.log".format(output_directory,output_name), + **oxdna_args) + os.sync() + ## TODO: call oxdna + cmd = [oxDNA, input_file] + + cmd = tuple(str(x) for x in cmd) + + print("Running oxDNA with: %s" % " ".join(cmd)) + process = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) + for line in process.stdout: + sys.stdout.write(line) + sys.stdout.flush() + + return topology,last_conf_file + finally: + os.chdir(d_orig) + + """ Visualization """ def vmd_tube_tcl(self, file_name="drawTubes.tcl"): with open(file_name, 'w') as tclFile: tclFile.write("## beginning TCL script \n")