def progress_bar(proc, func_input_dict, tail_line_num=20): """ Monitor ``.log`` file timestep. The ``func_input_dict`` should contains several keys: * `nsteps`: Total number of steps during the simulation * `log`: path of the log file (Defined in ``os_command.run_background()``) * `refresh_time`: time interval to refresh log extract (default=1.0 s) :param proc: running subprocess :type proc: subprocess object :param func_input_dict: dictionnary containing parameters for log extract :type func_input_dict: dict :param tail_line_num: number of line to read at the end of ``.log`` file :type tail_line_num: int, default=20 Example: >>> TEST_OUT = str(getfixture('tmpdir')) >>> import sys >>> sys.path.insert(0, os.path.abspath(os.path.join(MONITOR_LIB_DIR, \ '../..'))) >>> from gromacs_py import gmx #doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS <BLANKLINE> ... >>> prot = gmx.GmxSys(name='1y0m', coor_file=TEST_PATH+'/1y0m.pdb') >>> ################################### >>> #### Create the topologie: ### >>> ################################### >>> prot.prepare_top(out_folder=os.path.join(TEST_OUT, 'top_SH3'), \ vsite='hydrogens') #doctest: +ELLIPSIS pdb2pqr... --ff CHARMM --ffout CHARMM --chain --ph-calc-method=propka \ --with-ph=7.00 tmp_pdb2pqr.pdb 00_1y0m.pqr gmx pdb2gmx -f 01_1y0m_good_his.pdb -o 1y0m_pdb2gmx.pdb -p \ 1y0m_pdb2gmx.top -i 1y0m_posre.itp -water tip3p -ff charmm36-jul2017 -ignh \ -vsite hydrogens >>> ###################################### >>> ### Monitor an energy minimisation ### >>> ###################################### >>> monitor = PROGRESS_BAR >>> prot.em(out_folder=os.path.join(TEST_OUT, 'em_SH3'), nsteps=50,\ constraints='none', create_box_flag=True, monitor=monitor, nstlog=1)\ #doctest: +ELLIPSIS gmx editconf -f .../top_SH3/1y0m_pdb2gmx.pdb -o \ .../top_SH3/1y0m_pdb2gmx_box.pdb -bt dodecahedron -d 1.0 gmx grompp -f 1y0m.mdp -c ../top_SH3/1y0m_pdb2gmx_box.pdb -r \ ../top_SH3/1y0m_pdb2gmx_box.pdb -p ../top_SH3/1y0m_pdb2gmx.top -po \ out_1y0m.mdp -o 1y0m.tpr -maxwarn 1 gmx mdrun -s 1y0m.tpr -deffnm 1y0m -nt 0 -ntmpi 0 -nsteps -2 \ -nocopyright """ if isnotebook(): from tqdm.notebook import tqdm else: from tqdm import tqdm log_to_check = func_input_dict['log'] time_modif = None file_time = None count = 1 if 'refresh_time' in func_input_dict: refresh_time = func_input_dict['refresh_time'] else: refresh_time = 1.0 pbar = tqdm(total=func_input_dict['nsteps']) last_time = 0 while proc.poll() is None: time.sleep(refresh_time) count += 1 if os_command.check_file_exist(log_to_check): file_time = os.stat(log_to_check).st_mtime if time_modif != file_time: time_modif = file_time log_dict = extract_log_dict(func_input_dict) if 'step' in log_dict: pbar.update(log_dict['step'] - last_time) last_time = log_dict['step'] pbar.update(func_input_dict['nsteps'] - last_time) pbar.close()
def print_log_file(proc, func_input_dict, tail_line_num=20): """ Monitor ``.log`` file information. The ``func_input_dict`` should contains several keys: * `terms`: list of energetic terms to extract, eg. ['Potential', 'Temperature'] * `log`: path of the log file (Defined in ``os_command.run_background()``) * `refresh_time`: time interval to refresh log extract (default=1.0 s) :param proc: running subprocess :type proc: subprocess object :param func_input_dict: dictionnary containing parameters for log extract :type func_input_dict: dict :param tail_line_num: number of line to read at the end of ``.log`` file :type tail_line_num: int, default=20 Example: >>> TEST_OUT = str(getfixture('tmpdir')) >>> import sys >>> sys.path.insert(0, os.path.abspath(os.path.join(MONITOR_LIB_DIR, \ '../..'))) >>> from gromacs_py import gmx #doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS <BLANKLINE> ... >>> prot = gmx.GmxSys(name='1y0m', coor_file=TEST_PATH+'/1y0m.pdb') >>> ################################### >>> #### Create the topologie: ### >>> ################################### >>> prot.prepare_top(out_folder=os.path.join(TEST_OUT, 'top_SH3'), \ vsite='hydrogens') #doctest: +ELLIPSIS pdb2pqr... --ff CHARMM --ffout CHARMM --chain --ph-calc-method=propka \ --with-ph=7.00 tmp_pdb2pqr.pdb 00_1y0m.pqr gmx pdb2gmx -f 01_1y0m_good_his.pdb -o 1y0m_pdb2gmx.pdb -p \ 1y0m_pdb2gmx.top -i 1y0m_posre.itp -water tip3p -ff charmm36-jul2017 -ignh \ -vsite hydrogens >>> ###################################### >>> ### Monitor an energy minimisation ### >>> ###################################### >>> monitor = {'function': print_log_file,\ 'terms':['Potential'],\ 'file_check_ext':'log'} >>> prot.em(out_folder=os.path.join(TEST_OUT, 'em_SH3'), nsteps=50,\ constraints='none', create_box_flag=True, monitor=monitor, nstlog=1)\ #doctest: +ELLIPSIS gmx editconf -f .../top_SH3/1y0m_pdb2gmx.pdb -o \ .../top_SH3/1y0m_pdb2gmx_box.pdb -bt dodecahedron -d 1.0 gmx grompp -f 1y0m.mdp -c ../top_SH3/1y0m_pdb2gmx_box.pdb -r \ ../top_SH3/1y0m_pdb2gmx_box.pdb -p ../top_SH3/1y0m_pdb2gmx.top -po \ out_1y0m.mdp -o 1y0m.tpr -maxwarn 1 gmx mdrun -s 1y0m.tpr -deffnm 1y0m -nt 0 -ntmpi 0 -nsteps -2 \ -nocopyright... """ log_to_check = func_input_dict['log'] time_modif = None file_time = None count = 1 if 'refresh_time' in func_input_dict: refresh_time = func_input_dict['refresh_time'] else: refresh_time = 1.0 while proc.poll() is None: time.sleep(refresh_time) count += 1 if os_command.check_file_exist(log_to_check): file_time = os.stat(log_to_check).st_mtime if time_modif != file_time: time_modif = file_time log_dict = extract_log_dict(func_input_dict) if 'time' in log_dict: print("time = {:6.1f} ".format(log_dict['time']), end='') for keys in func_input_dict['terms']: if keys in log_dict: print(" {} = {:5.1f} ".format(keys, log_dict[keys]), end='') print()
def correct_charge_type(self, forcefield, index_list=None): """ Correct the charge and atom type of an itp object, base on a ff `.rtp` file. This is specially usefull, to correct charge of termini resiudes of a cyclicized peptide. if index_list is None, will correct all atom charges, if not, only atoms listed in index_list. """ # First extract charge and type from the ff .rtp file forcefield_path = forcefield['path'] rtp_path = os.path.abspath( os.path.join(os_command.get_directory(forcefield_path), 'aminoacids.rtp')) if not os_command.check_file_exist(rtp_path): rtp_path = os.path.abspath( os.path.join(os_command.get_directory(forcefield_path), 'merged.rtp')) logger.info('Read rtp file : {}'.format(rtp_path)) ff_rtp = Rtp(rtp_path) # Correct charges and type: # for atom_num, atom in self.atom_dict.items(): if index_list is None: index_list = self.atom_dict.keys() for atom_num in index_list: atom = self.atom_dict[atom_num] res_name = atom['res_name'] resid = atom['res_num'] atom_name = atom['atom_name'] # With Amber disulfide cys are called CYX in the rtp and CYS in # the itp. # Don't get sense but need to check the protonation state of cys # By counting atoms # With charmm disuldie cys is CYS2 if res_name == 'CYS': if len( self.get_selection_index(selec_dict={ 'res_num': [resid], 'res_name': ['CYS'] })) == 10: if forcefield['name'].startswith('amber'): res_name = 'CYX' elif forcefield['name'].startswith('charmm'): res_name = 'CYS2' # print(res_name) # With gromacs all histidine are called HIS ! if res_name == 'HIS': if len( self.get_selection_index(selec_dict={ 'res_num': [resid], 'res_name': ['HIS'] })) == 18: if forcefield['name'].startswith('amber'): res_name = 'HIP' elif forcefield['name'].startswith('charmm'): res_name = 'HSP' elif len( self.get_selection_index(selec_dict={ 'res_num': [resid], 'atom_name': ['HE2'] })) == 1: if forcefield['name'].startswith('amber'): res_name = 'HIE' elif forcefield['name'].startswith('charmm'): res_name = 'HSE' else: if forcefield['name'].startswith('amber'): res_name = 'HID' elif forcefield['name'].startswith('charmm'): res_name = 'HSD' # print(atom) # print(ff_rtp.res_dict[res_name]['atom'][atom_name]) if atom_name in ff_rtp.res_dict[res_name]['atom']: atom_type = \ ff_rtp.res_dict[res_name]['atom'][atom_name]['type'] atom_charge = \ ff_rtp.res_dict[res_name]['atom'][atom_name]['charge'] # print('Correct residue {:4} atom {:4} atom type {:4} ' # 'to {:4}'.format(res_name, atom['atom_name'], # atom['atom_type'], atom_type)) # print('Correct charge {:4} ' # 'to {:4}'.format(self.atom_dict[atom_num]['charge'], # atom_charge)) if atom_type != atom['atom_type']: logger.warning('Correct residue {:4} atom {:4} atom ' 'type {:4} to {:4}'.format( res_name, atom['atom_name'], atom['atom_type'], atom_type)) else: logger.warning('Can\'t find residue {:4} atom {:4} atom ' 'type {:4} parameters in forcefield'.format( res_name, atom['atom_name'], atom['atom_type'])) self.atom_dict[atom_num]['atom_type'] = atom_type self.atom_dict[atom_num]['charge'] = atom_charge
def simulation_plot(proc, func_input_dict, refresh_time=1.0): """ This function is used for monitoring a simulation in real time. Function can be excecuted by the gromacs.tools.os_command.run_background() function. The function monitors a trajectory file, and launch the analysis if the file has been modified. It can plot as function of time an analysis of a simulation. Analysis is passed as input function. .. warning:: Need to add the following lines to be run in jupyter notebook: * ``%matplotlib notebook`` Example: >>> TEST_OUT = str(getfixture('tmpdir')) >>> import sys >>> # print(os.path.abspath(os.path.join(MONITOR_LIB_DIR, \ '../..'))) >>> sys.path.insert(0, os.path.abspath(os.path.join(MONITOR_LIB_DIR, \ '../..'))) >>> from gromacs_py import gmx #doctest: +ELLIPSIS >>> prot = gmx.GmxSys(name='1y0m', coor_file=TEST_PATH+'/1y0m.pdb') >>> ################################### >>> #### Create the topologie: ### >>> ################################### >>> prot.prepare_top(out_folder=os.path.join(TEST_OUT, 'top_SH3'), \ vsite='hydrogens') #doctest: +ELLIPSIS pdb2pqr... --ff CHARMM --ffout CHARMM --chain --ph-calc-method=propka \ --with-ph=7.00 tmp_pdb2pqr.pdb 00_1y0m.pqr gmx pdb2gmx -f 01_1y0m_good_his.pdb -o 1y0m_pdb2gmx.pdb -p \ 1y0m_pdb2gmx.top -i 1y0m_posre.itp -water tip3p -ff charmm36-jul2017 -ignh \ -vsite hydrogens >>> ###################################### >>> ### Monitor an energy minimisation ### >>> ###################################### >>> monitor = {'function': simulation_plot,\ 'extract_func': [{'func': extract_log_dict,\ 'term': 'Potential'},\ {'func': extract_log_dict,\ 'term': 'Temperature'}],\ 'file_check_ext':'log'} >>> prot.em(out_folder=os.path.join(TEST_OUT, 'em_SH3'), nsteps=50,\ constraints='none', create_box_flag=True, monitor=monitor, nstlog=10)\ #doctest: +ELLIPSIS gmx editconf -f ...top_SH3/1y0m_pdb2gmx.pdb -o \ ...top_SH3/1y0m_pdb2gmx_box.pdb -bt dodecahedron -d 1.0 gmx grompp -f 1y0m.mdp -c .../top_SH3/1y0m_pdb2gmx_box.pdb \ -r .../top_SH3/1y0m_pdb2gmx_box.pdb -p .../top_SH3/1y0m_pdb2gmx.top \ -po out_1y0m.mdp -o 1y0m.tpr -maxwarn 1 gmx mdrun -s 1y0m.tpr -deffnm 1y0m -nt 0 -ntmpi 0 -nsteps -2 -nocopyright """ file_to_check = func_input_dict[func_input_dict['file_check_ext']] function_list = func_input_dict['extract_func'] time_modif = None file_time = None count = 1 x_list = [] y_list = [] notebook = isnotebook() ################### # Set up the plot # ################### # Remove the matplotlib window buttons: matplotlib.rcParams['toolbar'] = 'None' # Create the plot in interactive mode plt.ion() # fig = plt.figure() fig, axarr = plt.subplots(len(function_list), sharex=True) for i, function in enumerate(function_list): y_list.append([]) x_list.append([]) axarr[i].set_xlabel('time (ps)') axarr[i].set_ylabel(function['term']) axarr[i].plot(x_list[i], y_list[i], 'ko-', markersize=2, linewidth=0.5, color='blue') # show the window # figure will be in foreground, but the user may move it to background if not notebook: fig.show() fig.canvas.set_window_title(file_to_check[:-4]) while proc.poll() is None: time.sleep(refresh_time) count += 1 if os_command.check_file_exist(file_to_check): file_time = os.stat(file_to_check).st_mtime if time_modif != file_time: time_modif = file_time for i, function in enumerate(function_list): anal = function['func'](func_input_dict) # print(anal) if 'time' in anal and function['term'] in anal: x_list[i].append(anal['time']) y_list[i].append(anal[function['term']]) # set plot data axarr[i].lines[0].set_data(x_list[i], y_list[i]) # recompute the data limits axarr[i].relim() # automatic axis scaling axarr[i].autoscale_view() # except KeyError: # print('Energy could not be extract, # simulation is probably finished.') # Update the plot and take care of window events # (like resizing etc.) fig.canvas.flush_events() if notebook: # Needed when launched in notebook fig.canvas.draw()
def read_file(self, top_in): field = None ifdef = False bond_list = [] angle_list = [] dihed_list = [] with open(top_in) as topfile: for line in topfile: # print("line: ",line) # Check #ifdef field: if line[:6] == '#ifdef': ifdef = True if line[:6] == '#endif': ifdef = False # Check include files if not ifdef and line.startswith('#include'): # get the file name to include: file_name = line.split()[1][1:-1] # remove '"' , path and .itp: include = (file_name.split("/")[-1]).split(".")[0] # Look if the itp is in the top path: # print("Path 1: ",self.folder+"/"+file_name) # print("Path 2: ",FORCEFIELD_PATH_LIST+"/"+file_name) itp_found = False if os_command.check_file_exist( os.path.join(self.folder, file_name)): path = os.path.abspath( os.path.join(self.folder, file_name)) itp_found = True else: for forcefield in FORCEFIELD_PATH_LIST: if os_command.check_file_exist( os.path.join(forcefield, file_name)): path = os.path.abspath( os.path.join(forcefield, file_name)) itp_found = True break if not itp_found: raise IOError('Itp ' + file_name + ' not found') # print("name =", include, "fullname =", file_name, # "path =",path) if include == "forcefield": self.forcefield = { 'name': file_name.split('.')[0], 'fullname': file_name, 'path': path } else: self.add_mol_itp(path) # Check field elif not ifdef and line.startswith("["): # Remove space and [ ] field = line.strip()[1:-1].strip() # print(field) # As intermolecular_inter field is empty # (filled with bonds, angles, ...) # It has to be checked now: if field == 'intermolecular_interactions': self.inter_interact = True continue # Check in the field : elif (not ifdef and not line[0].startswith(";") and line.strip() != ""): if field == 'moleculetype': # in the case where mol param are present in the top # file, convert the top to an itp # If mol_name variable is defined, give to the mol # param this name name_itp = os.path.basename(top_in)[:-3] + "itp" logger.info("Molecule topologie present in {} " ", extract the topologie in a separate" " file: {}".format(top_in, name_itp)) # Store and write the itp file: top_itp = Itp(name=name_itp, fullname=name_itp, path=os.path.abspath(top_in)) top_itp.write_file(os.path.join(self.folder, name_itp)) top_itp.display() # Add the itp to the itp_list self.add_mol_itp(os.path.join(self.folder, name_itp)) self.include_itp = True # Name of the system elif field == 'system': self.name = line.strip() # Molecule composition of the system elif field == 'molecules': line_list = line.strip().split() self.mol_comp.append({ 'name': line_list[0], 'num': line_list[1] }) # Following command concern # intermolecular interactions elif field == 'bonds': bond_list.append(line.strip().split()) elif field == 'angles': angle_list.append(line.strip().split()) elif field == 'dihedrals': dihed_list.append(line.strip().split()) if self.inter_interact: self.add_intermolecular_restr(bond_list=bond_list, angle_list=angle_list, dihed_list=dihed_list)