Example #1
0
def countWaterCNT(bgf_file, trj_file, silent=False):

    # init
    timestep = 0
    l_timestep = []

    myBGF = bgf.BgfFile(bgf_file)
    myTRJ = open(trj_file)
    myDAT = open(bgf_file[:-4] + ".count.dat", "w")
    myDAT.write("Time\tHeight\tRadius\tNumber\n")

    # extract aNos of CNT in the BGF file
    aNo_CNT = []
    aNo_MtOH_C = []
    for atom in myBGF.a:
        # Carbons in CNT
        if "CNT" in atom.rName:
            aNo_CNT.append(atom.aNo)

        # Carbons in MeOH
        if "MET" in atom.rName and "C" in atom.aName:
            aNo_MtOH_C.append(atom.aNo)

    N_CNT = len(aNo_CNT)  # the number of CNT atoms

    # for every shot in the trajectory file update BGF and manipulate
    myDUMP = dump.dump(trj_file, 0)  # sequential reading

    while 1:

        aNo_MtOH_C_in_CNT = copy.deepcopy(aNo_MtOH_C)

        # initialize for the moment of inertia and the center of mass calculation
        U = 0
        Ut = 0
        Uv = 0
        Ixx = 0
        Ixy = 0
        Ixz = 0
        Iyx = 0
        Iyy = 0
        Iyz = 0
        Izx = 0
        Izy = 0
        Izz = 0
        Mx = 0
        My = 0
        Mz = 0

        time = myDUMP.next()
        sys.stdout.write('\r' + "Reading timestep.. " + str(time))
        sys.stdout.flush()
        #print("Timestep: " + str(time))
        if time == -1:
            break

        nu.shutup()
        myDUMP.sort()
        nu.say()
        l_timestep = myDUMP.time()  # timesteps are 'appended' incrementally
        atoms = myDUMP.viz(len(l_timestep) - 1)[
            2]  # atom coordinate info: id,type,x,y,z for each atom as 2d array
        box = myDUMP.viz(len(l_timestep) -
                         1)[1]  # [xlo, ylo, zlo, xhi, yhi, zhi]
        box = [float(i) for i in box]
        boxsize = [box[3] - box[0], box[4] - box[1],
                   box[5] - box[1]]  # simbox size

        myBGF.CRYSTX = [
            boxsize[0], boxsize[1], boxsize[2], myBGF.CRYSTX[3],
            myBGF.CRYSTX[4], myBGF.CRYSTX[5]
        ]

        #print("l_atoms " + str(len(atoms)))

        # update the coordinates in the bgf file
        for atom in atoms:
            bgfatom = myBGF.getAtom(atom[0])
            bgfatom.x = float(atom[2])
            bgfatom.y = float(atom[3])
            bgfatom.z = float(atom[4])
        """
		# com of CNT
		for atom in myBGF.a:
			if "CNT" in atom.rName:
				Mx += atom.x / N_CNT
				My += atom.y / N_CNT
				Mz += atom.z / N_CNT
		"""

        myBGF = bgftools.periodicMoleculeSort(myBGF)

        #print(Mx, My, Mz)
        # transpose for "all atoms in BGF"
        for atom in myBGF.a:
            atom.x -= Mx
            atom.y -= My
            atom.z -= Mz

        # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF"
        for aNo in aNo_CNT:
            atom = myBGF.getAtom(aNo)
            Ixx += (atom.y**2 + atom.z**2) / N_CNT
            Iyy += (atom.x**2 + atom.z**2) / N_CNT
            Izz += (atom.x**2 + atom.y**2) / N_CNT
            Ixy -= (atom.x * atom.y) / N_CNT
            Ixz -= (atom.x * atom.z) / N_CNT
            Iyz -= (atom.y * atom.z) / N_CNT

        # the moment of inertia tensor
        I = numpy.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]])

        # eigenvalue & eigenvector calculation
        eigval, eigvec = numpy.linalg.eig(
            I)  # eigval[0] is the minimum among the values.

        # rearrange the U vector
        U = numpy.matrix(eigvec)
        Ut = U.T

        # "myBGF" transform
        for atom in myBGF.a:
            v = numpy.matrix([atom.x, atom.y, atom.z]).T
            Uv = Ut * v
            atom.x = float(Uv[0])
            atom.y = float(Uv[1])
            atom.z = float(Uv[2])

        # com of CNT
        Mx = 0
        My = 0
        Mz = 0
        for atom in myBGF.a:
            if "CNT" in atom.rName:
                Mx += atom.x / N_CNT
                My += atom.y / N_CNT
                Mz += atom.z / N_CNT
        #print(Mx, My, Mz)

        # transpose for "all atoms in BGF"
        for atom in myBGF.a:
            atom.x -= Mx
            atom.y -= My
            atom.z -= Mz
        """ ### THIS PART (UPDATING LAMMPSTRJ) DOES NOT WORK ###

		myDUMP.aselect.all(time)	# all atoms should be selected to be changed
		myDUMP.tselect.one(time)
		coordx = []; coordy = []; coordz = []
		for atom in myBGF.a:
			coordx.append(atom.x)
			coordy.append(atom.y)
			coordz.append(atom.z)
		myDUMP.setv("xu", coordx)
		myDUMP.setv("yu", coordy)
		myDUMP.setv("zu", coordz)
		"""
        """	### CHECKING ORIGIN by adding an atom at (0, 0, 0) and is okay. 110914 inkim
		origin = bgf.BgfAtom()
		origin.aTag = 0
		origin.aName = "ORIG"
		origin.ffType = "Ar"
		origin.chain = "A"
		origin.x = 0.0
		origin.y = 0.0
		origin.z = 0.0
		origin.rName = "ORG"
		myBGF.addAtom(origin)
		"""

        # for CNT atoms, calculate some properties
        min_x_CNT = 0.0
        max_x_CNT = 0.0
        radius_CNT = 0.0
        height_CNT = 0.0

        for aNo in aNo_CNT:
            atom = myBGF.getAtom(aNo)
            # minimum and maximum x coord of CNT: this will be the height of CNT
            if atom.x < min_x_CNT:
                min_x_CNT = atom.x
            if atom.x > max_x_CNT:
                max_x_CNT = atom.x
            radius_CNT += math.sqrt(atom.y**2 +
                                    atom.z**2)  # average radius of CNT

        radius_CNT = radius_CNT / N_CNT
        height_CNT = max_x_CNT - min_x_CNT

        # determine whether C in MtOH is in the CNT Cylinder
        for aNo in aNo_MtOH_C:
            atom = myBGF.getAtom(aNo)
            dist = math.sqrt(atom.y**2 + atom.z**2)
            if atom.x > min_x_CNT \
             and atom.x < max_x_CNT \
             and dist < radius_CNT:
                pass
            else:
                aNo_MtOH_C_in_CNT.remove(aNo)

        #print("Height of CNT: " + str(height_CNT) + " " + str(min_x_CNT) +  " " + str(max_x_CNT))
        #print("Average radius of CNT: " + str(radius_CNT))
        #print("Average number of methanols in CNT: " + str(len(aNo_MtOH_C_in_CNT)))
        myDAT.write(str(time) + "\t")
        myDAT.write(str("{0:<8.3f}".format(height_CNT)))
        myDAT.write(str("{0:<8.3f}".format(radius_CNT)))
        myDAT.write(str(len(aNo_MtOH_C_in_CNT)) + "\n")

        # write output
        myBGF.saveBGF(bgf_file[:-4] + "." + str(time) + ".bgf")

    #myDUMP.write(trj_file.split(".")[0] + "_mod." + trj_file.split(".")[1])

    print('')
    return 1
def crosslink(bgf_file, ff_file, suffix, init_script_original_file,
              crosslink_script_original_file, t, ratio, out_file):

    # *** variables ***

    # used for calculating the number of 1", 2", and 3" amines
    l_init_amines = []
    l_amines = []

    # used for log file output
    output = ""

    # used for storing number of cross_linking per each cycle
    n_crosslink_per_cycle = []

    # used for storing cumulative number of crosslink type
    n_crosslink_pripri = 0
    n_crosslink_prisec = 0
    n_crosslink_secsec = 0

    # initialization

    f_out_file = open(out_file, 'w')
    t1 = 0
    t2 = 0
    # clock for measuring time for a cycle

    f_out_file.write("crosslink.py: version " + str(version) + "\n")
    f_out_file.write("" + "\n")
    f_out_file.write("Job started at " + time.asctime(time.gmtime()) + " on " +
                     os.environ["HOSTNAME"] + " by " + os.environ["USER"] +
                     "\n")
    f_out_file.write("Command executed at " + os.getcwd() + "\n")
    f_out_file.write("Requested options: " + str(sys.argv) + "\n")
    f_out_file.write("" + "\n")
    f_out_file.write("Using MPI: " + str(mpi_command) + "\n")
    f_out_file.write("Using LAMMPS: " + str(lammps_command) + "\n")
    f_out_file.write("Using Initial input script: " +
                     str(init_script_original_file) + "\n")
    f_out_file.write("Using Crosslinking input script: " +
                     str(crosslink_script_original_file) + "\n")
    curr_dir = os.path.abspath(".")
    temp_dir = scratch_dir + "/" + suffix
    initial_bgf_file = bgf_file

    # LAMMPS executive command: defined in ~/scripts/clusterSettings.py
    lammps_parallel = mpi_command + " " + lammps_command

    n_crosslink = 0
    f_out_file.flush()

    f_out_file.write("\n* Initialization" + "\n")

    # determine the initial numbers of primary, secondary, and tertiary amines
    l_init_amines = bgftools.getAmineGroupInfo(initial_bgf_file)
    f_out_file.write(
        "\tNumber of primary, secondary, and tertiary amine groups: " +
        str(l_init_amines) + "\n")
    AmineGroupInfo = bgftools.setAmineGroupInfo(initial_bgf_file,
                                                initial_bgf_file)
    f_out_file.write(
        "\tNumber of primary, secondary, and tertiary amine groups are investigated and updated: "
        + str(AmineGroupInfo) + "\n")

    # check ratio
    n_initAvailAmineSites = AmineGroupInfo[0] + AmineGroupInfo[1]
    f_out_file.write("Requested ratio: " + str(ratio) + "\n")

    # scratch setting and file copy
    f_out_file.write("\tCreating scratch directory: " + temp_dir + "\n")
    if not os.path.isdir(temp_dir):
        os.makedirs(temp_dir)

    # managing hostfile: "COMMENTED"
    # Important Note: assume that "cat $PBS_NODEFILE > hostfile" is already executed in the .pbs file
    #hostfile = open(temp_dir + "/hostfile", 'w')
    #for i in range(0, 12): hostfile.write(os.environ["HOST"] + "\n")
    #hostfile.close()
    #shutil.copy("hostfile", temp_dir)
    #shutil.copy(initial_bgf_file, temp_dir)
    shutil.copy(ff_file, temp_dir)
    os.chdir(temp_dir)

    # LAMMPS input script files for crosslinking
    #init_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.noinit"
    #init_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.initialize"
    #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/procedures/in.xlnk_nvt_1ps_k1.0_r6_0ps"
    #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.xlnk_npt_1ps_k16_r28"
    #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.xlnk_npt_1ps_k8_r28"
    #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.xlnk_npt_1ps_k16_r35"

    shutil.copy(init_script_original_file, temp_dir)
    shutil.copy(crosslink_script_original_file, temp_dir)

    init_script_filename = init_script_original_file.split("/")[
        -1]  # initial script filename
    crosslink_script_filename = crosslink_script_original_file.split("/")[
        -1]  # crosslinking script filename

    createLammpsInput = "createLammpsInput.pl -b " + bgf_file + " -f " + ff_file + " -s " + suffix + " -o 'no shake' -t " + init_script_filename + " > /dev/null"
    os.system(createLammpsInput)
    initial_in_file = "in." + suffix

    # apply a patch for initialization
    patch_crosslink.pair_coeff_patch_wo_xlinker(initial_in_file, False)

    # first run
    t1 = time.time()
    runLammpsParallel = lammps_parallel + " -screen none -in " + initial_in_file + " -log " + os.path.join(
        temp_dir, suffix + ".log")
    f_out_file.write("\tRunning Lammps: see " +
                     str(os.path.join(temp_dir, suffix + ".log")) + "\n")
    os.system(runLammpsParallel)
    t2 = time.time()
    f_out_file.write("\tElapsed time for the initialization: " + str(t2 - t1) +
                     " sec\n")
    f_out_file.flush()

    # update coordinates
    initial_trj_file = suffix + "_init.lammpstrj"
    f_out_file.write("\tUpdating the BGF file " + initial_bgf_file +
                     " with LAMMPS trajectory file to _trj_updated.bgf" + "\n")
    #updatebgf(initial_bgf_file, initial_trj_file, "_trj_updated.bgf", True, silent=True);
    LAMMPS_trj2bgf.getLAMMPSTrajectory(initial_bgf_file, initial_trj_file,
                                       "_trj_updated.bgf", -1, False, True)

    f_out_file.write("\tReassigning the origin of " + "_trj_updated.bgf" +
                     " and saving " + "_centered.bgf" + "\n")
    #nu.shutup(); centerbgf("_trj_updated.bgf", "_centered.bgf", "", "com_center"); nu.say()
    nu.shutup()
    os.system("~tpascal/scripts/centerBGF.pl -b _trj_updated.bgf -f " +
              ff_file + " -s _centered.bgf -c com_center")
    nu.say()

    bgf_file = suffix + "1.bgf"
    shutil.copy("_centered.bgf", bgf_file)
    f_out_file.flush()

    # repeat
    if t == 0: t = 10

    n_process = 0
    endFlag = False
    # crosslinking start!
    for i in range(1, t + 1):
        print("====== " + str(i) + " ======")
        n_process = i
        t1 = time.time()
        N_prisecter = [0, 0, 0]
        # N counter init.
        f_out_file.write("\n\n====== Cycle " + str(i) + " ======" + "\n")

        sname = suffix + str(i)
        bgf_file = sname + ".bgf"
        input_file = "in." + sname

        f_out_file.flush()

        # create input
        f_out_file.write(
            "\n* Minimization, heating, and NVT dynamics for 1ps" + "\n")
        f_out_file.write("\tCreating Lammps input for " + bgf_file + "\n")
        ################## IMPORTANT: min heat nvt -> min nvt for crosslinking ##################### 2011.4.20.

        # crosslinking with spring
        createLammpsInput = "createLammpsInput.pl -b " + bgf_file + " -f " + ff_file + " -s " + sname + " -o 'no shake' -t 'min " + crosslink_script_filename + "' > /dev/null"

        nu.shutup()
        os.system(createLammpsInput)
        nu.say()

        ##### apply a patch after the first step
        if n_crosslink != 0:
            patch_crosslink.pair_coeff_patch_w_xlinker("in." + sname, False)
        else:
            patch_crosslink.pair_coeff_patch_wo_xlinker("in." + sname, False)

        f_out_file.flush()

        # run lammps
        f_out_file.write("\tRunning LAMMPS simulation on " + sname + "\n")
        f_out_file.write("\tRunning Lammps: see " +
                         str(os.path.join(temp_dir, sname + ".log")) + "\n")
        runLammpsParallel = lammps_parallel + " -screen none -in " + input_file + " -log " + sname + ".log"
        os.system(runLammpsParallel)

        # load trajectory
        f_out_file.write("\tLoading Trajectory." + "\n")
        initial_trj_file = sname + "_nvt.lammpstrj"

        # update bgf
        f_out_file.write("\tUpdating BGF file from trajectory." + "\n")
        ######updatebgf(bgf_file, temp_trj_file, "_trj_updated.bgf", True, silent=True)
        #updatebgf(bgf_file, initial_trj_file, "_trj_updated.bgf", True, silent=True)
        LAMMPS_trj2bgf.getLAMMPSTrajectory(bgf_file, initial_trj_file,
                                           "_trj_updated.bgf", -1, False, True)

        ## align bgf periodic box	### added at 110719
        #bgftools.periodicMoleculeSort("_trj_updated.bgf", "_aligned.bgf", silent=True)
        #bgftools.periodicMoleculeSort("_trj_updated.bgf", "_trj_updated.bgf", [], silent=True)

        # center bgf
        #nu.shutup(); centerbgf("_trj_updated.bgf", "_centered.bgf", "", "com_center"); nu.say()
        nu.shutup()
        os.system("~tpascal/scripts/centerBGF.pl -b _trj_updated.bgf -f " +
                  ff_file + " -s _centered.bgf -c com_center")
        nu.say()
        shutil.copy("_centered.bgf", bgf_file)

        f_out_file.flush()

        # check the criteria from BGF file
        ### 1. open the BGF file
        f_out_file.write("\n* Crosslinking module execution" + "\n")

        clusterBGF = BgfFile(bgf_file)
        clusterBGF.renumber()
        f_out_file.write("\tChecking the connectivities in " + bgf_file + "\n")

        ### 2. list up all N atoms
        N_index = []
        # REMARK: actually, this is aNo
        NN_dist_ok = []

        for atom in clusterBGF.a:
            if string.strip(atom.ffType) == "N_3":
                N_index.append(atom.aNo)
                """
				if "PRI" in atom.rName:
					N_prisecter[0] += 1
				elif "SEC" in atom.rName:
					N_prisecter[1] += 1
				elif "TER" in atom.rName:
					N_prisecter[2] += 1
				"""
        N_prisecter = bgftools.getAmineGroupInfo(clusterBGF, silent=True)
        f_out_file.write("\tThe number of 1', 2', and 3' amine: " +
                         str(N_prisecter) + "\n")
        N_number = len(N_index)

        criteria = 5.0

        ### 3. find N-N pairs which meet
        # 1st criteria: distance is between 5 and 6
        # 2nd criteria: only PRI or SEC amine
        # 3rd criteria: avoid repeating (removed)
        for x in range(N_number):
            for y in range(x + 1, N_number):
                if clusterBGF.distance(clusterBGF.a2i[N_index[x]], clusterBGF.a2i[N_index[y]]) < 6.0 \
                 and clusterBGF.distance(clusterBGF.a2i[N_index[x]], clusterBGF.a2i[N_index[y]]) > 5.0 \
                 and clusterBGF.getAtom(N_index[x]).rName != "TER" \
                 and clusterBGF.getAtom(N_index[y]).rName != "TER":
                    NN_dist_ok.append([N_index[x], N_index[y]])

        if not NN_dist_ok == []:
            f_out_file.write("\tCrosslinking candidate site: " +
                             str(NN_dist_ok) + "\n" +
                             "\tNow filtering out the candidate.\n")

        ##### Filtering out the nearest adjacent and the second nearst adjacent cross-linking
        if NN_dist_ok != []:
            f_out_file.write(
                "\tDeleting the nearest adjacent or second nearest adjacent from cross-link candidate site.\n"
            )
            f_out_file.write("\t\tConnectivity test 1:\n")
            for pair in NN_dist_ok:
                amine1 = clusterBGF.getAtom(pair[0])
                amine2 = clusterBGF.getAtom(pair[1])

                amine1_conect = dict()
                amine2_conect = dict()
                amine1_conect[amine1.aNo] = amine1.CONECT
                amine2_conect[amine2.aNo] = amine2.CONECT

                # 4-step connection for amine1
                for j in range(0, 4):
                    d_temp = copy.deepcopy(amine1_conect)
                    for ano in d_temp:
                        for conect_ano in d_temp[ano]:
                            tempatom = clusterBGF.getAtom(conect_ano)
                            amine1_conect[tempatom.aNo] = tempatom.CONECT

                # 4-step connection for amine2
                for j in range(0, 4):
                    d_temp = copy.deepcopy(amine2_conect)
                    for ano in d_temp:
                        for conect_ano in d_temp[ano]:
                            tempatom = clusterBGF.getAtom(conect_ano)
                            amine2_conect[tempatom.aNo] = tempatom.CONECT

                # now we get a small map for determining the connectivity
                amine1_conect.update(amine2_conect)

                # check the connectivity between two N atoms
                f_out_file.write("\t\t\t* Checking " + str(pair) +
                                 " (in residue " + str(amine1.rNo) + " and " +
                                 str(amine2.rNo) + "): ")
                amine1_to_amine2 = bgftools.findShortestPath(
                    amine1_conect, amine1.aNo, amine2.aNo)
                if not type(amine1_to_amine2) is NoneType:
                    if len(amine1_to_amine2) < 10:
                        f_out_file.write(
                            str(amine1_to_amine2) +
                            "\tAdjacent pair.. will not be cross-linked.\n")
                        NN_dist_ok.remove(pair)
                    else:
                        f_out_file.write(
                            str(amine1_to_amine2) +
                            "\tNot an Adjacent pair.. can be cross-linked.\n")
                else:
                    f_out_file.write(str(amine1_to_amine2) + ": No path.\n")

                # if they have same residue then test again

            f_out_file.write("\tFiltered pair list from test 1: " +
                             str(NN_dist_ok) + "\n")
            f_out_file.write("\t\tConnectivity test 2:\n")

            for pair in NN_dist_ok:
                amine1 = clusterBGF.getAtom(pair[0])
                amine2 = clusterBGF.getAtom(pair[1])
                amine1_aNo = amine1.aNo
                amine2_aNo = amine2.aNo
                amine1_rNo = amine1.rNo
                amine2_rNo = amine2.rNo

                tempBGF = bgf.BgfFile()
                for atom in clusterBGF.a:
                    if atom.rNo == amine1_rNo or atom.rNo == amine2_rNo:
                        tempBGF.addAtom(atom)
                amine1_to_amine2 = bgftools.getShortestPath(
                    tempBGF, amine1_aNo, amine2_aNo)
                f_out_file.write("\t\t\t* " + str(pair) + " ( in residue " +
                                 str(amine1.rNo) + " and " + str(amine2.rNo) +
                                 "): ")
                if not type(amine1_to_amine2) is NoneType:
                    if len(amine1_to_amine2) < 10:
                        f_out_file.write(
                            str(amine1_to_amine2) +
                            "\tAdjacent pair.. will not be cross-linked.\n")
                        NN_dist_ok.remove(pair)
                    else:
                        f_out_file.write(
                            str(amine1_to_amine2) +
                            "\tNot an Adjacent pair.. can be cross-linked.\n")
                else:
                    f_out_file.write(str(amine1_to_amine2) + "\n")

        ##### Filtering out the repeat
        # Tested with pair_candidate = [[1, 2], [1, 3], [1, 4], [3, 4], [3, 5], [5, 6], [7, 8], [9, 10], [9, 11]]
        if NN_dist_ok != []:
            f_out_file.write(
                "\tRemoving repeated crosslink candidate site: \n")

            result = []
            pair_candidate = copy.deepcopy(NN_dist_ok)
            pair_candidate_flatten = cu.flatten(pair_candidate)

            for pair in pair_candidate:
                if pair_candidate_flatten.count(
                        pair[0]) == 1 and pair_candidate_flatten.count(
                            pair[1]) == 1:
                    # unique pair in the candidate list
                    result.append(pair)
                    pair_candidate.remove(
                        pair
                    )  # unique pairs will be deleted from pair_candidate

            if pair_candidate != []:
                # grouping
                x = pair_candidate[0][0]
                templist = []
                grouped = []
                for pair in pair_candidate:
                    if pair[0] == x:
                        templist.append(pair)
                    else:
                        grouped.append(templist)
                        templist = []
                        x = pair[0]
                        templist.append(pair)
                grouped.append(templist)

                # shuffle pairs
                for group in grouped:
                    random.shuffle(group)
                random.shuffle(grouped)

                # selecting a pair from group
                for group in grouped:
                    pair = random.choice(group)
                    result.append(pair)

                # removing repeats
                temp_repeated = []
                result_flatten = cu.flatten(result)
                for element in result_flatten:
                    if result_flatten.count(element) != 1:  # if repeated..
                        temp_repeated.append(element)

                for element in temp_repeated:
                    templist = []
                    for pair in result:
                        if element in pair:
                            templist.append(pair)
                            result.remove(pair)
                    if templist != []:
                        selected = random.choice(templist)
                        result.append(selected)

                NN_dist_ok = result

                ##### end of filtering

        f_out_file.write("\t" + str(len(NN_dist_ok)) +
                         " N-N pairs which meets the criteria ( " +
                         str(criteria) + "A ) are found." + "\n")
        f_out_file.write("\t" +
                         "The following N-N pairs will be crosslinked: " +
                         str(NN_dist_ok) + "\n")
        f_out_file.flush()

        ### 4. attach crosslinker
        # NN_dist_ok is the list that will be get crosslinked
        if len(NN_dist_ok) > 0:
            # used for counting intra- and inter-molecular cross-linking during cycle
            n_intra = 0
            n_inter = 0
            n_crosslink_in_cycle = 0

            # if the required ratio reached, stop cross-linking
            r = float(n_crosslink) / float(n_initAvailAmineSites)
            f_out_file.write("degree of crosslinking: " + str(n_crosslink) +
                             " / " + str(n_initAvailAmineSites) + " = " +
                             str(r) + '\n')
            if r > ratio:
                f_out_file.write(
                    "************* Requested degree of cross-link reached: EXITING ************"
                )
                NN_dist_ok = []
                endFlag = True

            f_out_file.write("\n* Attaching the crosslinker to " + bgf_file +
                             "\n")
            for pair in NN_dist_ok:
                f_out_file.write("\tLinking " + str(pair) + " Nitrogens: ")

                ##### a) load a crosslinker
                xlinkerBGF_file = "/home/noische/research/dendrimer/xlinker/20111129/xlinker_new.bgf"
                #xlinkerBGF = BgfFile("/home/noische/research/dendrimer/structure/xlinker/xlnker.bgf")
                xlinkerBGF = BgfFile(xlinkerBGF_file)
                f_out_file.write("\tLoaded the crosslinker file " +
                                 str(xlinkerBGF_file) + "\n")

                head_xlnk = xlinkerBGF.a[0]  # head C of xlnk
                tail_xlnk = xlinkerBGF.a[2]  # tail C of xlnk

                ##### b) select a hydrogen to be detached
                #    /- head_detach_H(M) /- head_xlnk_detach_H(H)      /- tail_detach_H(N)
                # head_N(O) --- head_xlnk(J) --- tail_xlnk(K) --- tail_N(P)
                #                                    \- tail_xlnk_detach_H(I)
                # Detach one H atom at random connected with J which is marked as X
                # Detach one H atom at random connected with K which is marked as Xmar
                head_N = clusterBGF.getAtom(pair[0])
                tail_N = clusterBGF.getAtom(pair[1])
                head_N.chain = "O"
                tail_N.chain = "P"
                head_N_rNo = head_N.rNo
                tail_N_rNo = tail_N.rNo

                # check whether intra- or inter-molecular crosslinking
                if head_N_rNo == tail_N_rNo:
                    #f_out_file.write("\t\tintra-molecular crosslinking between ")
                    f_out_file.write(
                        "\t\tintra-molecular crosslinking between resNo " +
                        str(head_N.rNo) + " " + str(head_N.rName) + " and " +
                        "resNo " + str(head_N.rNo) + " " + str(tail_N.rName) +
                        " amines\n")
                    f_out_file.write(
                        "\t\tintra-molecular crosslinking will be passed.")
                    n_intra += 1
                    continue
                    # intramolecular crosslinking is prohibited
                else:
                    f_out_file.write(
                        "\t\tinter-molecular crosslinking between ")
                    f_out_file.write("resNo " + str(head_N.rNo) + " " +
                                     str(head_N.rName) + " and " + "resNo " +
                                     str(head_N.rNo) + " " +
                                     str(tail_N.rName) + " amines\n")
                    n_inter += 1
                n_crosslink_in_cycle += 1

                #f_out_file.write("resNo " + str(head_N.rNo) + " " + str(head_N.rName) + " and " + "resNo " + str(head_N.rNo) + " " + str(tail_N.rName) + " amines\n")	# intramolecular prohibition

                # count pri-pri, pri-sec, sec-sec crosslinking number
                if "PRI" in head_N.rName and "PRI" in tail_N.rName:
                    n_crosslink_pripri += 1
                elif "PRI" in head_N.rName and "SEC" in tail_N.rName:
                    n_crosslink_prisec += 1
                elif "SEC" in head_N.rName and "PRI" in tail_N.rName:
                    n_crosslink_prisec += 1
                elif "SEC" in head_N.rName and "SEC" in tail_N.rName:
                    n_crosslink_secsec += 1

                f_out_file.write(
                    "\t\tCumulative PRI-PRI crosslinking number: " +
                    str(n_crosslink_pripri) + "\n")
                f_out_file.write(
                    "\t\tCumulative PRI-SEC crosslinking number: " +
                    str(n_crosslink_prisec) + "\n")
                f_out_file.write(
                    "\t\tCumulative SEC-SEC crosslinking number: " +
                    str(n_crosslink_secsec) + "\n")
                f_out_file.write("\n")

                f_out_file.write("\t\tChoosing atoms..\n")

                # change the crosslinker's rNo as same as head_N
                for atom in xlinkerBGF.a:
                    atom.rNo = head_N_rNo

                # choose which H atom will be detached from head_N
                temp_list = []
                for ano in head_N.CONECT:
                    if clusterBGF.getAtom(ano).is_hydrogen():
                        temp_list.append(ano)

                if temp_list == []: continue

                head_H_detach_candidate_id = random.choice(temp_list)
                f_out_file.write("\t\t\tChoosing the hydrogen " +
                                 str(head_H_detach_candidate_id) + " from " +
                                 str(temp_list) + " attached to " +
                                 str(head_N.aNo) + "\n")

                # choose which H atom will be detached from tail_N
                temp_list = []
                for ano in tail_N.CONECT:
                    if clusterBGF.getAtom(ano).is_hydrogen():
                        temp_list.append(ano)

                if temp_list == []: continue

                tail_H_detach_candidate_id = random.choice(temp_list)
                f_out_file.write("\t\t\tChoosing the hydrogen " +
                                 str(tail_H_detach_candidate_id) + " from " +
                                 str(temp_list) + " attached to " +
                                 str(tail_N.aNo) + "\n")

                head_detach_H = clusterBGF.getAtom(
                    head_H_detach_candidate_id)  # H which will be detached
                tail_detach_H = clusterBGF.getAtom(
                    tail_H_detach_candidate_id)  # also
                head_detach_H.chain = "M"
                tail_detach_H.chain = "N"
                head_detach_H_charge = head_detach_H.charge
                tail_detach_H_charge = tail_detach_H.charge

                # choose which hydrogen will be detached from J
                temp_list = []
                for atom in xlinkerBGF.a:
                    if atom.chain == "X":
                        temp_list.append(atom.aNo)
                head_xlnk_detach_H_aNo = random.choice(temp_list)
                head_xlnk_detach_H = xlinkerBGF.getAtom(head_xlnk_detach_H_aNo)
                head_xlnk_detach_H.chain = "H"
                head_xlnk_detach_H_charge = head_xlnk_detach_H.charge
                f_out_file.write("\t\t\tH atom " +
                                 str(head_xlnk_detach_H_aNo) +
                                 " in the cross-linker will be deleted.\n")

                ##### c) move xlinker near to the place: let N-H bond is 1.0 A: move C to 1.4 * N-H bond
                #delta = [ head_detach_H.x - head_xlnk.x, head_detach_H.y - head_xlnk.y, head_detach_H.z - head_xlnk.z ]	# old method: moves head_xlnk to head_detach_H
                #deltax = 1.4 * head_detach_H.x - 0.4 * head_N.x - head_xlnk.x
                #deltay = 1.4 * head_detach_H.y - 0.4 * head_N.y - head_xlnk.y
                #deltaz = 1.4 * head_detach_H.z - 0.4 * head_N.z - head_xlnk.z
                #delta = [deltax, deltay, deltaz]
                delta = (1.4 * head_detach_H.x - 0.4 * head_N.x - head_xlnk.x,
                         1.4 * head_detach_H.y - 0.4 * head_N.y - head_xlnk.y,
                         1.4 * head_detach_H.z - 0.4 * head_N.z - head_xlnk.z
                         )  # new method
                #moveBGF(xlinkerBGF, -deltax, -deltay, -deltaz )

                ##### c2) rotate xlinker toward tail_N and move
                vec = (tail_N.x - head_N.x, tail_N.y - head_N.y,
                       tail_N.z - head_N.z)
                xlinkerBGF = rotateBGF(xlinkerBGF, 1, 3, vec,
                                       0)  # 0 means return as BgfFile
                moveBGF(xlinkerBGF, delta[0], delta[1], delta[2])

                ##### c3) find which tail_detach_H is the nearst to tail_N
                temp_list = []
                temp_dist = 100
                for atom in xlinkerBGF.a:
                    if atom.chain == "Y":
                        temp_list.append(atom.aNo)
                tail_xlnk_detach_H_aNo = 0

                for ano in temp_list:
                    temp = clusterBGF.distance(clusterBGF.a2i[tail_N.aNo],
                                               xlinkerBGF.a2i[ano])
                    if temp < temp_dist:
                        temp_dist = temp
                        tail_xlnk_detach_H_aNo = ano
                tail_xlnk_detach_H = xlinkerBGF.getAtom(tail_xlnk_detach_H_aNo)
                tail_xlnk_detach_H.chain = "I"
                tail_xlnk_detach_H_charge = tail_xlnk_detach_H.charge

                ##### d) merge
                clusterBGF = clusterBGF.merge(xlinkerBGF, True)
                clusterBGF.saveBGF("_xlnk_temp.bgf")
                clusterBGF = BgfFile("_xlnk_temp.bgf")

                ##### e) detach head_detach_H and connect head_N-head_xlnk and tail_N-tail_xlnk

                for atom in clusterBGF.a:
                    if atom.chain == "O":
                        head_N = atom
                    if atom.rName == "XLK":
                        if atom.chain == "J":
                            head_xlnk = atom
                    if atom.chain == "P":
                        tail_N = atom
                    if atom.rName == "XLK":
                        if atom.chain == "K":
                            tail_xlnk = atom
                    if atom.chain == "H":
                        head_xlnk_detach_H = atom
                    if atom.chain == "I":
                        tail_xlnk_detach_H = atom

                # disconnect Hydrogens from head_N and tail_N
                f_out_file.write("\t\t\tDisconnecting Hydrogen(aNo: " +
                                 str(head_detach_H.aNo) +
                                 ") from Nitrogen(aNo: " + str(head_N.aNo) +
                                 ") - Head" + "\n")
                f_out_file.write("\t\t\tDisconnecting Hydrogen(aNo: " +
                                 str(tail_detach_H.aNo) +
                                 ") from Nitrogen(aNo: " + str(tail_N.aNo) +
                                 ") - Tail" + "\n")
                clusterBGF.disconnect(clusterBGF.a2i[head_N.aNo],
                                      clusterBGF.a2i[head_detach_H.aNo])
                clusterBGF.disconnect(clusterBGF.a2i[tail_N.aNo],
                                      clusterBGF.a2i[tail_detach_H.aNo])

                # detach Hydrogens from head_N and tail_N
                if head_detach_H.aNo > tail_detach_H.aNo:
                    f_out_file.write("\t\t\tDetaching Hydrogen atom: " +
                                     str(head_detach_H.aNo) + "\n")
                    clusterBGF.delAtom(clusterBGF.a2i[head_detach_H.aNo])
                    f_out_file.write("\t\t\tDetaching Hydrogen atom: " +
                                     str(tail_detach_H.aNo) + "\n")
                    clusterBGF.delAtom(clusterBGF.a2i[tail_detach_H.aNo])
                else:
                    f_out_file.write("\t\t\tDetaching Hydrogen atom: " +
                                     str(tail_detach_H.aNo) + "\n")
                    clusterBGF.delAtom(clusterBGF.a2i[tail_detach_H.aNo])
                    f_out_file.write("\t\t\tDetaching Hydrogen atom: " +
                                     str(head_detach_H.aNo) + "\n")
                    clusterBGF.delAtom(clusterBGF.a2i[head_detach_H.aNo])

                # disconnect H-J and delete H
                clusterBGF.disconnect(clusterBGF.a2i[head_xlnk.aNo],
                                      clusterBGF.a2i[head_xlnk_detach_H.aNo])
                clusterBGF.delAtom(clusterBGF.a2i[head_xlnk_detach_H.aNo])

                # disconnect K-I and delete I
                clusterBGF.disconnect(clusterBGF.a2i[tail_xlnk.aNo],
                                      clusterBGF.a2i[tail_xlnk_detach_H.aNo])
                clusterBGF.delAtom(clusterBGF.a2i[tail_xlnk_detach_H.aNo])

                # connect O-J
                clusterBGF.connect(
                    clusterBGF.a2i[head_N.aNo],
                    clusterBGF.a2i[head_xlnk.aNo])  # O-J connection

                # connect K-P
                clusterBGF.connect(
                    clusterBGF.a2i[tail_N.aNo],
                    clusterBGF.a2i[tail_xlnk.aNo])  # K-P connection

                # residue update
                f_out_file.write("\t\t\tUpdating residue information." + "\n")
                if head_N.rName == "PRI":
                    head_N.rName = "SEC"
                elif head_N.rName == "SEC":
                    head_N.rName = "TER"
                if tail_N.rName == "PRI":
                    tail_N.rName = "SEC"
                elif tail_N.rName == "SEC":
                    tail_N.rName = "TER"

                # chain update
                f_out_file.write("\t\t\tUpdating chain information." + "\n")
                head_N.chain = "V"
                tail_N.chain = "V"
                head_xlnk.chain = "A"
                tail_xlnk.chain = "A"

                f_out_file.write("\n")

                # charge
                f_out_file.write("\t\tCalculating charges..\n")
                f_out_file.write("\t\t\tCharge of the amine group 1: " +
                                 str("{0:8.5f}".format(head_N.charge)) + "\n")
                f_out_file.write("\t\t\tCharge of the amine group 2: " +
                                 str("{0:8.5f}".format(tail_N.charge)) + "\n")
                f_out_file.write(
                    "\t\t\tCharge of the head C in the cross-link: " +
                    str("{0:8.5f}".format(head_xlnk.charge)) + "\n")
                f_out_file.write(
                    "\t\t\tCharge of the tail C in the cross-link: " +
                    str("{0:8.5f}".format(tail_xlnk.charge)) + "\n")
                f_out_file.write(
                    "\t\t\tCharge of the H detached from amine group 1: " +
                    str("{0:8.5f}".format(head_detach_H_charge)) + "\n")
                f_out_file.write(
                    "\t\t\tCharge of the H detached from amine group 2: " +
                    str("{0:8.5f}".format(tail_detach_H_charge)) + "\n")
                f_out_file.write(
                    "\t\t\tCharge of the H detached from head C in the cross-link: "
                    + str("{0:8.5f}".format(head_xlnk_detach_H_charge)) + "\n")
                f_out_file.write(
                    "\t\t\tCharge of the H detached from tail C in the cross-link: "
                    + str("{0:8.5f}".format(tail_xlnk_detach_H_charge)) + "\n")
                #head_N.charge += head_detach_H_charge
                #tail_N.charge += tail_detach_H_charge
                #tail_xlnk.charge += tail_xlnk_detach_H_charge
                #head_xlnk.charge += head_xlnk_detach_H_charge
                head_xlnk.charge += head_detach_H_charge
                tail_xlnk.charge += tail_detach_H_charge
                head_N.charge += head_xlnk_detach_H_charge
                tail_N.charge += tail_xlnk_detach_H_charge

                #leftoverCharge = clusterBGF.charge() / 2.0
                #head_N.charge -= leftoverCharge
                #tail_N.charge -= leftoverCharge
                leftoverCharge = clusterBGF.charge()
                f_out_file.write("\t\t\tExcess Charge: " +
                                 str("{0:8.5f}".format(leftoverCharge)) + "\n")
                f_out_file.write(
                    "\t\t\tExcess Charge will be added to head N atom.\n")
                head_N.charge -= leftoverCharge

                f_out_file.write("\t\tModified charge of the amine group 1: " +
                                 str("{0:8.5f}".format(head_N.charge)) + "\n")
                f_out_file.write("\t\tModified charge of the amine group 2: " +
                                 str("{0:8.5f}".format(tail_N.charge)) + "\n")
                f_out_file.write("\t\tThe charge of the system is " +
                                 str("{0:8.5f}".format(clusterBGF.charge())) +
                                 "\n")
                f_out_file.write("" + "\n")

                n_crosslink += 1
                f_out_file.flush()
                ##### The end of the crosslinking step

            ##### Minimization
            f_out_file.flush()
            clusterBGF.renumber()

            f_out_file.write("\tSaving the crosslinked file to " +
                             "_linked.bgf" + "\n")
            clusterBGF.saveBGF("_linked.bgf")

            f_out_file.write(
                "\n* Crosslinking step is finished. Entering minimizing step."
                + "\n")

            # remove bad contacts
            #f_out_file.write("\tRemoving bad contacts after crosslinking." + "\n")
            #nu.shutup(); removebadcontacts("_linked.bgf", "_removed.bgf", 2.0); nu.say();

            # create input for minimization
            #createLammpsInput = "createLammpsInput.pl -b _removed.bgf -f " + ff_file + " -s minimization -o 'no shake' -t 'min' > /dev/null"
            createLammpsInput = "createLammpsInput.pl -b _linked.bgf -f " + ff_file + " -s minimization -o 'no shake' -t 'min' > /dev/null"
            runLammpsParallel = lammps_parallel + " -screen none -in in.minimization -log minimization.log"
            f_out_file.write("\tMaking LAMMPS input script for minimization." +
                             "\n")
            nu.shutup()
            os.system(createLammpsInput)
            nu.say()

            # patch for minimization ## added at 110524
            if n_crosslink != 0:
                patch_crosslink.pair_coeff_patch_w_xlinker(
                    "in.minimization", False)
            else:
                patch_crosslink.pair_coeff_patch_wo_xlinker(
                    "in.minimization", False)
            f_out_file.write("\tApplied a patch on in.minimization file.\n")

            # run lammps
            f_out_file.write("\tMinimizing the structure." + "\n")
            f_out_file.write("\tRunning Lammps: see " +
                             str(os.path.join(temp_dir, "minimization.log")) +
                             "\n")
            os.system(runLammpsParallel)

            # load trajectory
            f_out_file.write(
                "\tLoading Trajectory from the minimization result." + "\n")
            update_trj_file = "minimization.min.lammpstrj"

            # update bgf
            f_out_file.write(
                "\tUpdating BGF file from the minimization result." + "\n")
            ###updatebgf("_removed.bgf", "_temp.lammpstrj", "_trj_updated.bgf", silent=True)
            ###updatebgf("_linked.bgf", "_temp.lammpstrj", "_trj_updated.bgf", True, silent=True)
            #updatebgf("_linked.bgf", "minimization_min.lammpstrj", "_trj_updated.bgf", True, silent=True)
            LAMMPS_trj2bgf.getLAMMPSTrajectory("_linked.bgf",
                                               "minimization_min.lammpstrj",
                                               "_trj_updated.bgf", -1, False,
                                               True)

            # align bgf periodic box	### added at 110719
            #bgftools.periodicMoleculeSort("_trj_updated.bgf", "_trj_updated.bgf", [], silent=True)

            # center bgf
            f_out_file.write("\tAligning BGF file." + "\n")
            #nu.shutup(); centerbgf("_trj_updated.bgf", "_centered.bgf", "", "com_center"); nu.say()
            nu.shutup()
            os.system("~tpascal/scripts/centerBGF.pl -b _trj_updated.bgf -f " +
                      ff_file + " -s _centered.bgf -c com_center")
            nu.say()
            shutil.copy("_centered.bgf", suffix + str(i + 1) + ".bgf")

            # store the number of cross-link
            n_crosslink_per_cycle.append([i, len(NN_dist_ok)])

            f_out_file.write("" + "\n")
            f_out_file.write("--- " + str(len(NN_dist_ok)) +
                             " times of crosslinking occured at the cycle " +
                             str(i) + "\n")
            f_out_file.write(
                "--- " + str(n_intra) +
                " times of intra-molecular crosslinking occured at the cycle "
                + str(i) + "\n")
            f_out_file.write(
                "--- " + str(n_inter) +
                " times of inter-molecular crosslinking occured at the cycle "
                + str(i) + "\n")
            f_out_file.write("--- End of the crosslinking process for cycle " +
                             str(i) + "\n")
            f_out_file.write("--- See " + suffix + str(i + 1) +
                             ".bgf for output. \n" + "\n")
            f_out_file.flush()

            if endFlag:
                break
        else:
            n_crosslink_per_cycle.append([i, 0])
            f_out_file.write("--- Passing the crosslinking step in cycle " +
                             str(i) + "\n" + "\n")
            f_out_file.write(
                "--- 0 times of crosslinking occured at the cycle " + str(i) +
                "\n")
            f_out_file.write(
                "--- 0 times of intra-molecular crosslinking occured at the cycle "
                + str(i) + "\n")
            f_out_file.write(
                "--- 0 times of inter-molecular crosslinking occured at the cycle "
                + str(i) + "\n")
            shutil.copy(bgf_file, suffix + str(i + 1) + ".bgf")
            f_out_file.flush()

            if endFlag:
                break

        t2 = time.time()
        f_out_file.write("Elapsed time for the cycle: " + str(t2 - t1) +
                         " sec\n")

        ##### The end of the crosslinking cycle (1ps)

    f_out_file.write("\n\nJob completed at " + time.asctime(time.gmtime()) +
                     "\n")
    f_out_file.write("Output structure on " + suffix + "_out.bgf" + "\n")
    f_out_file.write("The number of crosslinking through this job: " +
                     str(n_crosslink) + "\n")

    f_out_file.write("\n\n*** Statistics for Crosslinking ***\n")
    f_out_file.write("Cycle\tFrequency\n")
    for i in n_crosslink_per_cycle:
        f_out_file.write(str(i[0]) + "\t" + str(i[1]) + "\n")

    f_out_file.close()

    shutil.copy(suffix + str(t + 1) + ".bgf", suffix + "_out.bgf")
Example #3
0
# minimization
nu.shutup()
createLammpsInput = "~tpascal/scripts/createLammpsInput.pl" + " -b temp.bgf " + " -f /home/noische/ff/DREIDING2.21.ff" + " -s temp " + " -o 'no shake' -t min " + " > /dev/null"
_ = os.system(createLammpsInput)
in_file = "in.temp"
data_file = "data.temp"
os.system("sed -i 's/dielectric      1/dielectric      72/' " + in_file)
os.system("sed -i 's/kspace_style    pppm 0.0001/kspace_style    none/' " +
          in_file)
os.system("sed -i 's/boundary        p p p/boundary        s s s/' " + in_file)
os.system("sed -i 's/1.0e-4 1.0e-4 500 5000/1.0e-6 1.0e-6 5000 50000/' " +
          in_file)
#os.system("sed -i 's/2.0 multi/5.0 multi/' " + in_file)
os.system(
    "sed -i 's/lj\/charmm\/coul\/long\/opt 7.5 8.50000/lj\/cut\/coul\/debye 0.142 10/' "
    + in_file)
os.system("sed -i 's/every 2 delay 4/every 1 delay 0/' " + in_file)
#os.system("sed -i 's/0.000000  50.000000/-10.000000  10.000000/' " + data_file)
os.system("sed -i 's/0 # X/0 0 # X/' " + data_file)
os.system("sed -i 's/Impropers//' " + data_file)
runLammps = mpi_command + lammps_command + " -in in.temp -log lammps.log >> temp.log"
_ = os.system(runLammps)
LAMMPS_trj2bgf.getLAMMPSTrajectory("temp.bgf", "temp.min.lammpstrj",
                                   "temp.bgf", -1, False, True)

mybgf = bgf.BgfFile('temp.bgf')
nu.say()

mybgf.saveBGF(out_file)
Example #4
0
def anneal(bgf_dir, ff_file, suffix, out_file):

    # *** variables ***

    # used for log file output
    output = ""

    # initialization
    #t1 = 0; t2 = 0;	# clock for measuring time for a cycle

    curr_dir = os.path.abspath(bgf_dir)
    temp_dir = curr_dir + "/anneal/"

    # LAMMPS executive command: defined in ~/scripts/clusterSettings.py
    #lammps_parallel = mpi_command + " -np 8 " + lammps_command
    lammps_parallel = "/home/tpascal/codes/openmpi/1.4.3/bin/mpirun -np 8 " + lammps_command

    # Annealing procedure
    anneal_proc = "/home/noische/script/dat/in.lammps.anneal"

    # get BGF file list in the directory
    pei_files = glob.glob(bgf_dir + "/*.bgf")
    pei_files.sort()

    os.chdir(bgf_dir)

    #print("pei_files: ", pei_files)

    # for file in the directory
    for file in pei_files:
        ### working filename
        print("*** Working on %s" % file)

        filename = file.split(".bgf")[0]
        print("filename: " + filename)

        # centerBGF
        print("Centering %s" % file)
        cmd_centerbgf = "/home/tpascal/scripts/centerBGF.pl -b " + file + " -f " + ff_file + " -s " + filename + ".center.bgf" + " -c com_center"
        nu.shutup()
        os.system(cmd_centerbgf)
        nu.say()

        filename = filename.split("/")[-1]
        print("filename: " + filename)

        # createLammps: with finite options
        # Note that the script refers /home/noische/script/data/in.lammps.anneal for the annealing process
        cmd_createLammpsInput = "/home/tpascal/scripts/createLammpsInput.pl -b " + filename + ".center.bgf" + " -f " + ff_file + " -t /home/noische/script/data/in.lammps.anneal " + " -s " + filename + " -o finite "
        nu.shutup()
        os.system(cmd_createLammpsInput)
        nu.say()

        # patch in.lammps file
        print("Patching infile")
        cmd_sed = "sed -i 's/2 5.0 90/2 4.5 5.0 90/' in." + filename
        nu.shutup()
        os.system(cmd_sed)
        nu.say()

        # patch data.lammps file
        print("Patching datafile")
        cmd_mv = "mv data." + filename + " data." + filename + ".bak"
        os.system(cmd_mv)
        file1 = open("data." + filename, "w")
        file2 = open("data." + filename + ".bak")
        while 1:
            line = file2.readline()
            if not line: break
            if "xlo" in line:
                line = "-50.0 50.0 xlo xhi\n"
                file1.write(line)
            elif "ylo" in line:
                line = "-50.0 50.0 ylo yhi\n"
                file1.write(line)
            elif "zlo" in line:
                line = "-50.0 50.0 zlo zhi\n"
                file1.write(line)
            elif "# X N_3 C_3 X" in line:
                line = line.replace("# X N_3 C_3 X", "0 # X N_3 C_3 X")
                file1.write(line)
            elif "# X C_3 C_3 X" in line:
                line = line.replace("# X C_3 C_3 X", "0 # X C_3 C_3 X")
                file1.write(line)
            else:
                file1.write(line)

        # run
        print("Running simulation")
        lammps_thermo_log_file = filename + ".anneal.log"
        cmd_lammps = lammps_parallel + " -log " + lammps_thermo_log_file
        nu.shutup()
        os.system(cmd_lammps)
        nu.say()

        # read potential energy from file
        # in in.lammps.anneal: "poteng" is the averaged value of potential energy after cooldown
        print("Treating Potential Energy")
        poteng = []
        poteng_files = glob.glob(filename + "*poteng")
        for poteng_file in poteng_files:
            f_poteng_file = open(poteng_file)
            while 1:
                line = f_poteng_file.readline()
                if not line:
                    break
                if not line[0] == "#":
                    parse = line.split()
                    poteng.append([parse[0], float(parse[1])])
        poteng = nu.removeRepeat(poteng)

        ### print potential energy
        for i in poteng:
            print(i)

        # when is the minimum energy during annealing?
        min_poteng = 0
        min_poteng_step = 0
        # usually poteng < 0
        for i in poteng:
            if i[1] < min_poteng:
                min_poteng_step = i[0]
                min_poteng = i[1]

        # convert that timestep into BGF
        trj_file = filename + ".lammpstrj"
        anneal_output_bgf_file = filename + ".annealed.bgf"
        result = LAMMPS_trj2bgf.getLAMMPSTrajectory(pei_file, trj_file,
                                                    anneal_output_bgf_file,
                                                    min_poteng_step, False)
        print("The lowest potential energy structure found")

        # create LAMMPS input for annealed BGF file

        # run the NVT simulation at 300 K

        # average the potential energy

        # average Rg

        # write data: filename, the minimum structure, avr_poteng, avr_Rg
    """