def distance_table(self, struc_list, mass_wt_pw, digits=4): """ Return a table with the RMSDs between the structures in struc_list. <digits> specifies how many digits after the decimal point are printed out. """ tm = file_handler.table_maker([5] + (len(struc_list)-1) * [digits+4]) tm.write_line([''] + [struc.name for struc in struc_list[1:]]) for i,struc1 in enumerate(struc_list[:-1]): tm.write_line([struc1.name] + [''] * i + [locale.format("%.*f", (digits, self.distance(struc1, struc2, mass_wt_pw=mass_wt_pw))) for struc2 in struc_list[i+1:]]) return tm.return_table()
def ret_FRCOORD_table(struc): """ Create the FRCOORD part in the molden file. """ tblmaker = file_handler.table_maker([4, 21, 21, 21]) for i in xrange(struc.ret_num_at()): atom = struc.mol.GetAtom(i + 1) vec = atom.GetVector() tblmaker.write_line([struc.ret_symbol(i + 1)] + [atom.x() / b_in_a] + [atom.y() / b_in_a] + [atom.z() / b_in_a]) return tblmaker.return_table()
def ret_Atoms_table(struc): """ Create the atoms part in the molden file. """ tblmaker = file_handler.table_maker([6, 4, 3, 21, 21, 21]) for i in xrange(struc.ret_num_at()): atom = struc.mol.GetAtom(i + 1) tblmaker.write_line( [struc.ret_symbol(i + 1), i + 1, atom.GetAtomicNum()] + [atom.x() / b_in_a] + [atom.y() / b_in_a] + [atom.z() / b_in_a]) return tblmaker.return_table()
def autocorr(self, mass_mat=None, out_file='RESULTS/autocorr.txt'): """ Compute the autocorrelation function. """ # +++ tm = file_handler.table_maker(2 * [20]) ac_list = [] for disp in xrange(self.num_tsteps): print disp ac_list += [self.ret_autocorr_disp(disp=disp, mass_mat=mass_mat)] for disp in xrange(self.num_tsteps): tm.write_line([float(disp) * self.dt, ac_list[disp]]) tm.write_to_file(out_file)
def print_xyz_file(self, file_path): """ Creates an xyz file with the vibrational information. """ out_str = '' for vib in self.vibs: out_str += str(len(self.atoms)) + '\n' out_str += 'Frequency ' + str(vib.frequency) + '\n' tmaker = file_handler.table_maker([5] + 6 * [20]) for at_ind, atom in enumerate(self.atoms): tmaker.write_line([' ' + atom.name] + atom.pos + vib.vector_list[at_ind]) out_str += tmaker.return_table() xyzfile = open(file_path, 'w') xyzfile.write(out_str) xyzfile.close()
def normal_mode_analysis(self, nma_mat, def_struc, header=None, out_file='nma.txt', abs_list=[], timestep=1.0): """ Perform a normal mode analysis and print the result to <out_file>. Normal modes are specified by numpy.array <nma_mat> (in cartesian coordinates), <nma_mat> is the inverse of the normal mode matrix. The <def_struc> should be the same structure that trajectories were superimposed onto. A matrix with all the nma vectors is returned. <abs_list> constains a list of normal mode numbers where the absolute value is taken (the first mode's index is 1) """ # +++ include weighting for every mode # for example according to zero point vibrations # abs_list would better only be considered with the averaging def_vect = def_struc.ret_vector() tm = file_handler.table_maker([35] + len(def_vect) * [20]) if header == None: header = [i + 1 for i in xrange(len(def_vect))] tm.write_header_line(header[0]) tm.write_header_line(header[1]) tm.write_header_line(header[2]) nma_list = [] for istruct, structure in enumerate(self.structures): diff = structure.ret_vector() - def_vect nma_vect = numpy.dot( diff, nma_mat) # one time step in the normal mode basis for i in abs_list: nma_vect[i - 1] = abs(nma_vect[i - 1]) tm.write_line([timestep * istruct] + [coor for coor in nma_vect]) nma_list += [nma_vect] tm.write_to_file(out_file) return numpy.array(nma_list)
def nm_analysis(INFOS): """ Normal mode analysis. Typically this script is carried out. """ print 'Preparing NMA ...' num_steps = INFOS['numsteps'] descr = INFOS['descr'] out_dir = os.path.join('NMA', descr) ref_struc_file = INFOS['refstruc'] ref_struc_type = INFOS['reftype'] ana_ints = INFOS['interval'] vibration_file = INFOS['refvib'] dt = INFOS['timestep'] abs_list = INFOS['symmmodes'] neg_list = INFOS['negmodes'] plot = INFOS['plot'] mawe = INFOS['massweight'] try: os.makedirs(out_dir) except OSError: print 'Output directory could not be created. It either already exists or you do not have writing access.' # shutil.copy('nma.inp',out_dir) ref_struc = struc_linalg.structure( 'ref_struc' ) # define the structure that all the time step structures are superimposed onto ref_struc.read_file(ref_struc_file, ref_struc_type) num_at = ref_struc.ret_num_at() mol_calc = struc_linalg.mol_calc(def_file_path=ref_struc_file, file_type=ref_struc_type) # read in data from the vibration file vmol = vib_molden.vib_molden() vmol.read_molden_file(vibration_file) nma_mat = numpy.linalg.pinv( vmol.ret_vib_matrix()) # this way it is a coordinate transformation # +++ the alternative would be an orthogonal projection, e.g. if only a few modes are chosen if mawe == True: mass_mat = mol_calc.ret_mass_matrix( power=0.5 ) # the mass matrix is for the mass weighted skalar product, it is the unit matrix if mass_wt_pw=0 nma_mat_mawe = numpy.dot(mass_mat, nma_mat) nma_mat = nma_mat_mawe header = vmol.ret_nma_header() # eff_mass_array = numpy.array(vmol.ret_eff_masses(mol_calc=mol_calc, mass_wt_pw = mass_wt_pw)) num_vib = len(nma_mat[0]) mult_array = numpy.zeros( num_vib, float) # for final summary files, output is multiplied with this list for i in xrange(num_vib): if i + 1 in neg_list: mult_array[i] = -1 else: mult_array[i] = 1 # used for computing the variance for each mode over all trajectories and timesteps num_points = numpy.zeros( len(ana_ints) ) # number of all timesteps in all the trajectories for each interval analysed sum_array = numpy.zeros( [len(ana_ints), num_vib], float) # a number for every time interval analysed and normal mode sum_sq_array = numpy.zeros([len(ana_ints), num_vib], float) # used for computing time resolved mean and variance cross_num_array = numpy.zeros(num_steps) cross_sum_array = numpy.zeros( [num_steps, num_vib], float ) # a number for every time step and normal mode; sum, has to be divided by cross_num_array cross_mean_array = numpy.zeros([num_steps, num_vib], float) # cross_sum_array / cross_num_array cross_sum_sq_array = numpy.zeros([num_steps, num_vib], float) #not_list = [] forbidden = ['crashed', 'running', 'dead', 'dont_analyze'] width = 30 files = [] ntraj = 0 print 'Checking the directories...' for idir in INFOS['paths']: ls = os.listdir(idir) for itraj in ls: if not 'TRAJ_' in itraj: continue path = idir + '/' + itraj s = path + ' ' * (width - len(path)) pathfile = path + '/output.xyz' if not os.path.isfile(pathfile): s += '%s NOT FOUND' % (pathfile) print s continue lstraj = os.listdir(path) valid = True for i in lstraj: if i.lower() in forbidden: s += 'DETECTED FILE %s' % (i.lower()) print s valid = False break if not valid: continue s += 'OK' print s ntraj += 1 files.append(pathfile) print 'Number of trajectories: %i' % (ntraj) if ntraj == 0: print 'No valid trajectories found, exiting...' sys.exit(0) #Numtraj=(last_traj+1)-first_traj for i in xrange(ntraj): # ls=os.listdir(os.getcwd()) # numfile=len(ls) # k=i+first_traj # string=str(k).rjust(5, '0') # trajfolder=None # j=0 # for j in range(numfile): # trajfolder=re.search(string,str(ls[j])) # if trajfolder!=None: # break # trajcheck=None # if trajfolder !=None: # trajcheck=re.search('TRAJ',str(ls[j])) # if trajcheck !=None: print 'Reading trajectory ' + str(files[i]) + ' ...' folder_name = str(files[i])[:-10] trajectory = traj_manip.trajectory(folder_name, ref_struc, dt=dt) # actual normal mode analysis try: nma_list = trajectory.normal_mode_analysis( nma_mat, ref_struc, header=header, out_file=folder_name + '/nma_' + descr + '.txt', abs_list=abs_list, timestep=dt )[: num_steps] # +++ abs_list should actually only be considered when averaging except: print ' *** Error: Coordinate transformation failed for trajectory ' + str( i) + '. Is there a proper calculation?' print ' Trajectory skipped ...' #not_list += [i] else: # addition for total std and for trajectory specific average and std tm_traj_av = file_handler.table_maker([35] + num_vib * [20]) tm_traj_av.write_header_line(['Nr'] + header[0][:-1]) tm_traj_av.write_header_line(['Wavenumber (1/cm)'] + header[1][1:]) tm_traj_av.write_header_line(['Period (fs)'] + header[2][1:]) tm_traj_std = file_handler.table_maker([35] + num_vib * [20]) tm_traj_std.write_header_line(['Nr'] + header[0][:-1]) tm_traj_std.write_header_line(['Wavenumber (1/cm)'] + header[1][1:]) tm_traj_std.write_header_line(['Period (fs)'] + header[2][1:]) for ii, interv in enumerate(ana_ints): st = interv[0] en = interv[1] np = nma_list[st:en].shape[0] num_points[ii] += np sa = numpy.add.reduce( nma_list[st:en]) # add the values in one column vector sum_array[ii] += sa sqa = numpy.add.reduce(nma_list[st:en]**2) sum_sq_array[ii] += sqa # determine average and std for this trajectory and interval if not np == 0: exp = sa / np exp2 = sqa / np std_array = ( np / (np - 1) * (exp2 - exp**2))**.5 # empirical standard deviation tm_traj_av.write_line([str(st) + '-' + str(en)] + exp.tolist()) tm_traj_std.write_line([str(st) + '-' + str(en)] + std_array.tolist()) # output of trajectory specific information tm_traj_av.write_to_file( str(folder_name) + '/nma_' + descr + '_av.txt') tm_traj_std.write_to_file( str(folder_name) + '/nma_' + descr + '_std.txt') # addition for time resolved trajectory averages for nr, tstep in enumerate(numpy.array(nma_list)): cross_num_array[nr] += 1 cross_sum_array[nr] += tstep cross_sum_sq_array[nr] += tstep**2 #for i in not_list: # print 'TRAJ' + str(i), print 'Processing data ...' for inum, num in enumerate(cross_num_array): if num == 0: print '*** WARNING: No trajectory found for step %i. Will perform analysis only until step %i.' % ( inum, inum - 1) num_steps = inum - 1 break #sys.exit() # determine the total standard deviation tm_tot_std = file_handler.table_maker([35] + num_vib * [20]) tm_tot_std.write_header_line(['Nr'] + header[0][:-1]) tm_tot_std.write_header_line(['Wavenumber (1/cm)'] + header[1][1:]) tm_tot_std.write_header_line(['Period (fs)'] + header[2][1:]) for i, interv in enumerate(ana_ints): exp_x = sum_array[i] / num_points[i] # expected values of x and x**2 exp_x2 = sum_sq_array[i] / num_points[i] std = (num_points[i] / (num_points[i] - 1) * (exp_x2 - exp_x**2))**.5 # empirical standard deviation std = std * mult_array tm_tot_std.write_line([str(interv[0]) + '-' + str(interv[1])] + std.tolist()) tm_tot_std.write_to_file(out_dir + '/total_std.txt') # time resolved average curves tm_mean = file_handler.table_maker(num_vib * [20]) tm_std = file_handler.table_maker(num_vib * [20]) tm_mean.write_header_line(header[0][:-1]) tm_std.write_header_line(header[0][:-1]) tm_mean.write_header_line(header[1][1:]) tm_std.write_header_line(header[1][1:]) tm_mean.write_header_line(header[2][1:]) tm_std.write_header_line(header[2][1:]) std_list = [0 for i in xrange(num_vib)] for i in xrange(num_steps): tm_mean.write_line( [coor / cross_num_array[i] for coor in cross_sum_array[i]]) cross_mean_array[i] = cross_sum_array[i] / cross_num_array[i] for j in xrange(num_vib): exp_x = cross_sum_array[i, j] / cross_num_array[i] exp_x2 = cross_sum_sq_array[i, j] / cross_num_array[i] std_list[j] = ( cross_num_array[i] / (cross_num_array[i] - 1) * (exp_x2 - exp_x**2))**.5 # empirical standard deviation tm_std.write_line(std_list) tm_mean.write_to_file(out_dir + '/mean_against_time.txt') tm_std.write_to_file(out_dir + '/std_against_time.txt') # get the variance of the time averaged structures tm_av_var = file_handler.table_maker([35] + num_vib * [20]) tm_av_var.write_header_line(['Nr'] + header[0][:-1]) tm_av_var.write_header_line(['Wavenumber (1/cm)'] + header[1][1:]) tm_av_var.write_header_line(['Period (fs)'] + header[2][1:]) for st, en in ana_ints: av_exp = numpy.add.reduce(cross_mean_array[st:en]) / ( en - st ) # the way python defines this the field really has en-st entries, not en-st+1 av_exp2 = numpy.add.reduce(cross_mean_array[st:en]**2) / (en - st) av_std_array = ( (en - st) / (en - st - 1) * (av_exp2 - av_exp**2))**.5 # empirical standard deviation av_std_array = av_std_array * mult_array tm_av_var.write_line([str(st) + '-' + str(en)] + av_std_array.tolist()) tm_av_var.write_to_file(out_dir + '/cross_av_std.txt') print 'Data processing finished.' if plot: plot_summary(INFOS)