Beispiel #1
0
def check_monomer(monomer, ff_file):
    """
Check whether monomer has proper number of branching points

    :str monomer:
    :str ff_file:
    :bool : object
    """
    try:
        f = bgf.BgfFile(monomer)
    except IOError:
        return False

    branch = 0
    head = 0

    for atom in f.a:
        atom.rNo = 0  # this residue number will be the key to distinguish body and the new block
        if atom.chain == "B":
            branch += 1
        if atom.chain == "H":
            head += 1
    if branch != 1:
        raise ValueError('More than two branch atoms inside ' + str(monomer))
        return False
    if head != 1:
        raise ValueError('More than two head atoms inside ' + str(monomer))
        return False

    mass = bgftools.getMass(f, ff_file)
    f.saveBGF(monomer)
    return mass
def getSlipLength(bgf_file,
                  trj_file,
                  ff_file,
                  interval,
                  n_step,
                  n_avg_step,
                  silent=False):
    """
	This calculates the profile of averaged velocity according to r. 
	NOTE: This is different from averaged velocity profile according to r.
	"""

    # const
    PI = math.pi
    vdw_r_C = 1.7

    # init
    timestep = 0
    l_timestep = []
    line = []
    n_header = 0
    output = ""
    t1 = 0
    t2 = 0
    # clock

    myBGF = bgf.BgfFile(bgf_file)
    myTRJ = open(trj_file)
    myTRJ.seek(0)
    myPkl = open(
        trj_file + ".profile.r_ave_vel-s" + str(n_step) + "k" + str(n_skip) +
        ".pickle", 'w')
    #f_dump = open(trj_file + ".profile.r_ave_vel.dump", 'w')
    #dump = "";

    # how many steps to go?
    n_timestep = len(lt.getTrjInfo(trj_file, silent=False))
    if n_step == 0:
        n_step = n_timestep

    if not silent:
        print("The trajectory contains " + str(n_timestep) + " timesteps.")

    # extract aNos of CNT in the BGF file
    aNo_CNT = []
    aNo_WAT_O = []
    aNo_WAT_all = []

    for atom in myBGF.a:
        # Carbons in CNT
        if "CNT" in atom.rName:
            aNo_CNT.append(atom.aNo)

        # Oxygen in water
        if "WAT" in atom.rName and "O" in atom.aName:
            aNo_WAT_O.append(atom.aNo)

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

    # check if there exists water properly
    if len(aNo_WAT_O) == 0:
        nu.die("No water molecules in the BGF file.")
    if len(aNo_CNT) == 0:
        nu.die("No CNT molecules in the BGF file.")

    # Find header of the trajectory file
    while 1:
        templine = myTRJ.readline()
        line.append(templine.strip('\n').strip('ITEM: '))
        n_header += 1
        if "ITEM: ATOMS" in templine:
            break

    # INITIAL trajectory information
    timestep = int(line[1])
    natoms = int(line[3])
    boxsize = [
        line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0],
        line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]
    ]
    boxsize = [float(i) for i in boxsize]
    keywords = line[8].strip('ATOMS ')

    # for every shot in the trajectory file update BGF and manipulate
    dumpatom = get_line(trj_file)
    processed_step = 0

    t1 = t2 = 0
    elapsed_time = 0

    # calculate radius_CNT
    avg_radius_CNT = 0.0
    x_CNT = 0.0
    y_CNT = 0.0
    if not silent:
        print(
            "Calculating the average radius of CNT throughout the averaging steps"
        )
    while 1:

        ### Show progress
        t1 = time.time()
        remaining_time = elapsed_time * (n_step - processed_step)

        ### Read
        try:
            chunk = [next(dumpatom) for i in range(natoms + n_header)]
        except StopIteration:
            break

        # skip if necessary
        if processed_step <= n_skip:
            processed_step += 1
            continue

        timestep = int(chunk[1])
        l_timestep.append(timestep)
        natoms = int(chunk[3])
        boxsize = [
            chunk[5].split(' ')[0], chunk[5].split(' ')[1],
            chunk[6].split(' ')[0], chunk[6].split(' ')[1],
            chunk[7].split(' ')[0], chunk[7].split(' ')[1]
        ]
        boxsize = [float(i) for i in boxsize]
        boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]),
                   (boxsize[5] - boxsize[4])]
        keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ')
        sys.stdout.write('\r' + "Fetched timestep: " + str(timestep) +
                         " (Remaining time: " +
                         "{0:4.1f}".format(remaining_time) + " seconds, " +
                         "{0:4.1f} minutes".format(remaining_time / 60) + ")")
        sys.stdout.flush()

        ### update myBGF with trajectory information ###
        natom_bgf = len(myBGF.a)  # number of atoms in BGF file

        mode = 'unwrapped'  # assume that "dump            1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input

        # actual coordinate
        coordinfo = chunk[9:]

        # modified for fast treatment
        for atomline in coordinfo:
            atomcoord = atomline.split(' ')
            atom = myBGF.getAtom(int(atomcoord[0]))

            atom.x = float(atomcoord[2])
            atom.y = float(atomcoord[3])
            atom.z = float(atomcoord[4])

            try:
                for i in range(0, 3):
                    myBGF.CRYSTX[i] = boxsize[i]
            except:
                pass

        # apply periodic condition
        #myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True)

        ### myBGF update complete! ###

        # for CNT atoms, calculate some properties
        min_x_CNT = 0.0
        max_x_CNT = 0.0
        radius_CNT = 0.0
        height_CNT = 0.0
        aNo_WAT_O_not_in_CNT = []
        temp = []
        min_y_CNT = 0.0
        max_y_CNT = 0.0
        min_z_CNT = 0.0
        max_z_CNT = 0.0
        CNT_orientation = ""

        l_radius_CNT = []
        l_x_CNT = []
        l_y_CNT = []

        for aNo in aNo_CNT:
            atom = myBGF.getAtom(aNo)

            # center of CNT
            l_x_CNT.append(atom.x)
            l_y_CNT.append(atom.y)

            # height
            if atom.z < min_z_CNT:
                min_z_CNT = atom.z
            if atom.z > max_z_CNT:
                max_z_CNT = atom.z

        x_CNT, a = nu.meanstdv(l_x_CNT)
        y_CNT, a = nu.meanstdv(l_y_CNT)
        z_diff = max_z_CNT - min_z_CNT

        # radius of CNT
        for aNo in aNo_CNT:
            atom = myBGF.getAtom(aNo)
            l_radius_CNT.append(
                math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2))

        radius_CNT, a = nu.meanstdv(l_radius_CNT)
        l_avg_radius_CNT.append(radius_CNT)

        if processed_step > 3:
            break

    avg_radius_CNT, s = nu.meanstdv(l_avg_radius_CNT)
    bins = np.arange(0.0, math.ceil(radius_CNT), interval)
    l_radial_vz_profile = np.zeros(len(bins) - 1)

    if not silent:
        print("\nAveraged CNT radius: " + str(avg_radius_CNT) + " A")
    if not silent: print("CNT center: " + str([x_CNT, y_CNT]))

    # calculate properties
    myTRJ.close()
    myTRJ = open(trj_file)
    myTRJ.seek(0)
    dumpatom = get_line(trj_file)
    processed_step = 0
    r = []
    vz = []
    # data container
    while 1:
        data = dict()
        # stores [r vz] for a timestep

        ### Show progress
        t1 = time.time()
        remaining_time = elapsed_time * (n_step - processed_step)

        ### Read
        try:
            chunk = [next(dumpatom) for i in range(natoms + n_header)]
        except StopIteration:
            break

        if processed_step <= n_skip:
            processed_step += 1
            continue

        timestep = int(chunk[1])
        l_timestep.append(timestep)
        natoms = int(chunk[3])
        boxsize = [
            chunk[5].split(' ')[0], chunk[5].split(' ')[1],
            chunk[6].split(' ')[0], chunk[6].split(' ')[1],
            chunk[7].split(' ')[0], chunk[7].split(' ')[1]
        ]
        boxsize = [float(i) for i in boxsize]
        boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]),
                   (boxsize[5] - boxsize[4])]
        keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ')
        sys.stdout.write('\r' + "Fetched timestep: " + str(timestep) +
                         " (Remaining time: " +
                         "{0:4.1f}".format(remaining_time) + " seconds, " +
                         "{0:4.1f} minutes".format(remaining_time / 60) + ")")
        sys.stdout.flush()

        ### update myBGF with trajectory information ###
        natom_bgf = len(myBGF.a)  # number of atoms in BGF file

        if not natom_bgf == natoms:
            nu.die(
                "Number of atoms in trajectory file does not match with BGF file."
            )

        mode = 'unwrapped'  # assume that "dump            1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input

        # actual coordinate
        coordinfo = chunk[9:]

        # modified for fast treatment
        for atomline in coordinfo:
            atomcoord = atomline.split(' ')
            atom = myBGF.getAtom(int(atomcoord[0]))

            atom.x = float(atomcoord[2])
            atom.y = float(atomcoord[3])
            atom.z = float(atomcoord[4])
            atom.vx = float(atomcoord[5])
            atom.vy = float(atomcoord[6])
            atom.vz = float(atomcoord[7])

            try:
                for i in range(0, 3):
                    myBGF.CRYSTX[i] = boxsize[i]
            except:
                pass
                #nu.warn("Crystal information error: is this file not periodic?")

        # apply periodic condition
        myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True)

        ### myBGF update complete! ###

        # calculate z-directional velocity of water molecules wrt r		vcm = sum vi mi / sum mi
        atom = myBGF.getAtom(aNo_WAT_O[0])
        mass_O = bgftools.getMass(myBGF, [aNo_WAT_O[0]], ff_file)
        atom = myBGF.getAtom(atom.CONECT[0])
        mass_H = bgftools.getMass(myBGF, [atom.aNo], ff_file)
        mass_H2O = mass_O + 2 * mass_H  # H2O mass

        for ano in aNo_WAT_O:
            atom = myBGF.getAtom(ano)  # oxygen

            # com & velocity calculation
            cmx = atom.x * mass_O
            cmy = atom.y * mass_O
            vcmz = atom.vz * mass_O

            for ano2 in atom.CONECT:
                atom2 = myBGF.getAtom(ano2)
                cmx += atom2.x * mass_H
                cmy += atom2.y * mass_H
                vcmz += atom2.vz * mass_H

            cmx /= mass_H2O
            cmy /= mass_H2O
            vcmz /= mass_H2O

            dist = math.sqrt((x_CNT - cmx)**2 + (y_CNT - cmy)**2)
            r.append(dist)
            vz.append(vcmz * 10**5)  # LAMMPS real unit conversion for velocity

        # timestep mark for starting average
        if l_avg_count == []:
            n_avg_count_step = timestep

        l_avg_count.append(timestep)

        # if the time has come.. average!
        if len(l_avg_count) == n_avg_step or processed_step == n_timestep - 1:
            if not silent:
                print(" Averaging invoked at timestep " + str(timestep) +
                      " (" + str(len(l_avg_count)) + " points)")

            # binning
            vz = np.array(vz)
            sum_vz = np.ma.array(np.histogram(r, bins, weights=vz)[0])
            sum_vz2 = np.ma.array(np.histogram(r, bins, weights=vz * vz)[0])
            n_vz = np.ma.array(np.histogram(r, bins)[0])
            #mask_n = ma.masked_values(n_vz, 0)

            mean = sum_vz / n_vz
            std = np.sqrt(sum_vz2 / n_vz - mean * mean)

            mean = np.ma.fix_invalid(mean, fill_value=0.0).data
            std = np.ma.fix_invalid(std, fill_value=0.0).data
            n_vz = np.ma.fix_invalid(n_vz, fill_value=0).data

            if len(mean) != len(bins) - 1 or len(std) != len(bins) - 1:
                nu.die("on numpy masked_array calculation!")

            l_result.append([l_avg_count, bins, n_vz, mean, std])

            # reset
            r = []
            vz = []
            l_radial_vz_profile = np.zeros(len(bins) - 1)
            l_avg_count = []

        t2 = time.time()  # time mark
        elapsed_time = t2 - t1
        processed_step += 1

    #f_dump.write(dump)
    pkl.dump(l_result, myPkl)

    print('')
    return 1
Beispiel #3
0
def main(primary,
         secondary,
         tertiary,
         ratio,
         mw,
         suffix,
         ff,
         n_requested_gen,
         isForce,
         silent,
         isPreserveCharge=False):
    """
    generate polymer by slow addition method

    :str primary: primary monomer BGF location
    :str secondary: secondary monomer BGF location
    :str tertiary: tertiary monomer BGF location
    :list ratio: primary, secondary, tertiary amines ratio
    :float mw: desired molecular weight
    :str suffix: used to make a log filename and generated structure filename
    :str ff: force field file
    :n_requested_gen: requested number of polymer generation
    :bool silent:
    :bool isPreserveCharge:
    input: - primary, secondary, tertiary BGF file marked with branching point B and head H
           - the amine ratio
           - the target molecular weight

    remarks: - connect B and H
             - hydrogens attached on H or B will be automatically removed with respect to their role.
             - iteration will go on until we spend all designated monomers.

    writes an output: an n-oligomer BGF file

    """

    ### 0. initialize
    # log: for different format for levels, see this: http://stackoverflow.com/questions/28635679/python-logging-different-formatters-for-the-same-log-file
    log = logging.getLogger(__name__)
    log.propagate = 0
    logging.basicConfig(level=logging.DEBUG)

    formatter_file = logging.Formatter(
        "[%(asctime)s] [%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S")
    formatter_debug = logging.Formatter("[%(levelname)s] %(message)s",
                                        "%Y-%m-%d %H:%M:%S")

    if not silent:
        streamhandler = logging.StreamHandler(sys.stdout)
        streamhandler.setFormatter(formatter_debug)
        streamhandler.setLevel(logging.INFO)

        log.addHandler(streamhandler)

    filehandler = logging.FileHandler(suffix + ".log")
    filehandler.setFormatter(formatter_file)
    filehandler.setLevel(logging.DEBUG)

    log.addHandler(filehandler)

    log.info(
        "***** Welcome to Hyperbranched Polymer Generator by Slow Addition Method *****"
    )
    log.info(str(sys.argv))

    # load primary, secondary, tertiary amines
    primary_mass = check_monomer(primary, ff)
    secondary_mass = check_monomer(secondary, ff)
    tertiary_mass = check_monomer(tertiary, ff)
    if not primary_mass or not secondary_mass or not tertiary_mass:
        log.error("Error found on reading monomers: Exiting.")
        sys.exit(0)

    # parameters for LAMMPS
    #mpi_command = os.environ["MPI"]
    #lammps_parallel_command = mpi_command + " " + lammps_command   # parallel not supported yet
    lammps_command = os.environ["EXEC"]
    curr_dir = os.path.abspath(".")
    temp_dir = curr_dir + ("/scratch/")
    if not os.path.isdir(temp_dir):
        os.makedirs(temp_dir)
    shutil.copy(primary, temp_dir)
    shutil.copy(secondary, temp_dir)
    shutil.copy(tertiary, temp_dir)
    os.chdir(temp_dir)

    # determine numbers of required amine blocks from requested Mw
    ratio = np.array(ratio)
    log.info("Requested ratio: " + str(ratio))

    masses = np.array([primary_mass, secondary_mass, tertiary_mass])
    log.info("Calculated monomer mass (T/L/D): " + str(masses))

    blocks = np.ceil(mw * ratio / masses)
    log.info("Calculated required monomer blocks (T/L/D): " + str(blocks))

    estimated_mw = np.sum(masses * blocks)
    log.info("Estimated hyperbranched polymer molecular weight: " +
             str(estimated_mw))

    monomers = [primary, secondary, tertiary]
    blocks = list(blocks)
    blocks = [int(i) for i in blocks]
    log.debug(str(blocks))

    log.info("The script will generate " + str(n_requested_gen) + " polymers.")

    n_generation = 0
    n_trial = 0
    branch_pt_profile = []
    while n_generation < n_requested_gen:

        n_trial += 1
        # make a pool
        # 0 = primary, 1 = secondary, 2 = tertiary
        pool = []
        for index, i in enumerate(blocks):
            log.debug("index, i: " + str(index) + " " + str(i))
            for j in range(i):
                pool.append(index)

        # the first block should not be primary(terminal)
        log.info("<<< Trial " + str(n_trial) + " >>>")
        log.info("Shuffling monomer blocks..")
        random.shuffle(pool)
        while pool[-1] == 0:
            log.debug("pool: " + str(pool))
            log.info("\tResuffle..")
            random.shuffle(pool)

        log.debug("pool: " + str(pool))

        # pick the initial block
        n_addition = 1
        init_block = pool.pop(
        )  # random pick: the last item of the shuffled list will be chosen for the first pick.
        body = bgf.BgfFile(monomers[init_block])  # the first monomer
        for atom in body.a:
            atom.rNo = n_addition  # mark

        branches = refresh_branch(body)
        branch_pt_profile.append([n_addition, len(branches)])

        log.info("*** iteration " + str(n_addition) + " ***")
        log.debug("init block: " + str(monomers[init_block]))

        is_generation_success = False
        tester = 0
        # addition iteration
        #while tester == 0:
        while len(pool) > 0:
            # tester ######
            tester = 1

            # counter
            n_addition += 1
            log.info("*** iteration " + str(n_addition) + " ***")

            ### find(update) branching points of the body
            branches = refresh_branch(body)
            branch_pt_profile.append([n_addition, len(branches)])
            log.debug("aNo for Possible branches: " + str(branches))
            if len(branches) == 0:
                log.warn(
                    "No possible branching points. Failed to generate a polymer. Retrying.."
                )
                os.system("rm in* dat* *trj *pbs *log")
                is_generation_success = False
                break

            ### if trials too many then quit the script.
            if not isForce and n_trial >= 3 * n_requested_gen:
                log.error(
                    "The generator does not seem to generate proper structures. Quit."
                )
                # branch point print
                output = "*** number of branching points ***"
                for i in branch_pt_profile:
                    output += i[0] + '\t' + i[1] + '\n'

                log.debug(output)
                sys.exit(0)

            if n_trial > 1000 and n_generation == 0:
                log.error(
                    "No single proper structure though many attemption. Quit.")
                # branch point print
                output = "*** number of branching points ***"
                for i in branch_pt_profile:
                    output += str(i[0]) + '\t' + str(i[1]) + '\n'

                log.debug(output)
                sys.exit(0)

            ### randomly pick a branch point
            random.shuffle(branches)
            branch_pt_body = branches.pop()
            log.debug("Selected branch point aNo: " + str(branch_pt_body))

            ### randomly pick a block (pop)
            random.shuffle(pool)
            monomer_type = pool.pop()
            monomer = bgf.BgfFile(monomers[monomer_type])
            for atom in monomer.a:
                atom.rNo = n_addition  # mark

            log.debug("Selected block: " + str(monomer_type))

            ### pick an atom from the branch atom of the body to make a bond
            branch_atom = body.getAtom(branch_pt_body)
            log.debug(str(branch_atom))
            bonding_candidate_body = []
            for ano in branch_atom.CONECT:
                atom = body.getAtom(ano)
                if "H_" in atom.ffType or "H" in atom.aName:
                    bonding_candidate_body.append(ano)
            #log.debug(str(bonding_candidate_body))
            bonding_candidate_body = random.choice(bonding_candidate_body)
            bonding_candidate_body_atom = body.getAtom(bonding_candidate_body)
            log.debug(str(bonding_candidate_body))
            log.debug(str(bonding_candidate_body_atom))

            ### translate a block
            (x, y, z) = (bonding_candidate_body_atom.x,
                         bonding_candidate_body_atom.y,
                         bonding_candidate_body_atom.z)
            log.debug("script will translate the block by -" + str((x, y, z)))
            for atom in monomer.a:
                atom.x += x
                atom.y += y
                atom.z += z

            ### merge
            body = body.merge(monomer)
            body.renumber()
            #log.debug(str(body))

            ### pick an atom from the head atom of a monomer
            head_atom_ano = 0
            for atom in body.a:
                if "H" in atom.chain and atom.rNo == n_addition:
                    head_atom_ano = atom.aNo
            head_atom = body.getAtom(head_atom_ano)
            #log.debug(str(head_atom))
            bonding_candidate_monomer = []
            for ano in head_atom.CONECT:
                atom = body.getAtom(ano)
                if "H" in atom.ffType and "H" in atom.aName:
                    bonding_candidate_monomer.append(ano)
            #log.debug(str(bonding_candidate_monomer))
            bonding_candidate_monomer = random.choice(
                bonding_candidate_monomer)
            bonding_candidate_monomer_atom = body.getAtom(
                bonding_candidate_monomer)
            #log.debug(str(bonding_candidate_monomer))
            #log.debug(str(bonding_candidate_monomer_atom))

            ### connect head(C) to tail(N)
            # branch_atom -- bonding_candidate_body ---- bonding_candidate_monomer -- head_atom
            # connect
            #log.debug("Connecting " + str(branch_atom.aNo) + " and " + str(head_atom.aNo))
            branch_atom.connect(head_atom)
            head_atom.connect(branch_atom)
            #log.debug(str(body))

            # charge
            branch_atom.charge += bonding_candidate_body_atom.charge
            head_atom.charge += bonding_candidate_monomer_atom.charge

            # remove
            delatoms = [
                body.a2i[bonding_candidate_body],
                body.a2i[bonding_candidate_monomer]
            ]
            body.delAtoms(delatoms)
            body.renumber()
            #log.debug(str(body))

            # translate
            _ = bgftools.getCom(body, ff)
            for atom in body.a:
                atom.x -= _[0]
                atom.y -= _[1]
                atom.z -= _[2]

            # refresh
            branches = refresh_branch(body)
            branch_pt_profile.append([n_addition, len(branches)])
            #log.debug(str(branches))

            # save
            temp_suffix = "_polymer_" + str(n_addition)
            temp_file = temp_suffix + ".bgf"  # ex) _polymer_1.bgf
            body.CRYSTX = [50.0, 50.0, 50.0, 90.0, 90.0, 90.0]
            body.PERIOD = "111"
            body.AXES = "ZYX"
            body.SGNAME = "P 1                  1    1"
            body.CELLS = [-1, 1, -1, 1, -1, 1]
            body.saveBGF(temp_file)

            # Minimization on LAMMPS
            createLammpsInput = "~tpascal/scripts/createLammpsInput.pl" + " -b " + temp_file + " -f " + ff + " -s " + temp_suffix + " -o 'no shake' -t min " + " > /dev/null"
            os.system(createLammpsInput)
            in_file = "in." + temp_suffix
            data_file = "data." + temp_suffix

            # LAMMPS input patch
            #os.system("sed -i 's/' " + in_file)
            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/lj\/charmm\/coul\/long\/opt 7.5 8.50000/lj\/cut\/coul\/debye 0.142 10/' "
                + in_file)

            # LAMMPS data patch
            os.system(
                "sed -i 's/0.000000  50.000000/-50.000000  50.000000/' " +
                data_file)
            os.system("sed -i 's/0 # X/0 0 # X/' " + data_file)
            os.system("sed -i 's/Impropers//' " + data_file)

            t1 = time.time()
            runLammps = lammps_command + " -in in." + temp_suffix + " -log " + temp_suffix + ".log " + "-screen none"
            log.debug("Running " + runLammps)
            os.system(runLammps)
            t2 = time.time()
            log.debug("Elapsed time for minimization: " + str(t2 - t1) +
                      " sec")

            # update coordinates
            trj_file = temp_suffix + ".min.lammpstrj"
            LAMMPS_trj2bgf.getLAMMPSTrajectory(temp_file, trj_file, temp_file,
                                               -1, False, True)
            body = bgf.BgfFile(temp_file)

            # end of a block addition
            is_generation_success = True

        # generation success
        if is_generation_success:
            n_generation += 1

            # amine group check
            _ = bgftools.getAmineGroupInfo(body)
            if _ == blocks:
                body.REMARK.append(
                    "Polymer generated with number of requested blocks.")
            else:
                log.warn(
                    "Requested monomer block does not match with the generated polymer."
                )
                break

            # charge check
            charge = 0.0
            for atom in body.a:
                charge += atom.charge
            if abs(charge) >= 0.00001:
                log.warn("Charge is not neutral: " + str(charge))

            # save the structure
            filename = suffix + "_" + str(n_generation) + ".bgf"
            body.DESCRP = "Polymer generated using " + os.path.basename(
                sys.argv[0]
            ) + " by " + os.environ["USER"] + " on " + time.asctime(
                time.gmtime())
            body.REMARK.insert(
                0, "Dendritic(tertiary) monomer with " +
                os.path.abspath(tertiary))
            body.REMARK.insert(
                0,
                "Linear(secondary) monomer with " + os.path.abspath(secondary))
            body.REMARK.insert(
                0,
                "Terminal(primary) monomer with " + os.path.abspath(primary))
            body.saveBGF(filename)
            shutil.copy(filename, curr_dir)
            log.info("\tSaving the structure to the filename " + filename)

            # wiener index
            idx = calculate_wiener_index(body)
            log.info("Wiener index: " + str(idx))
            body.REMARK.append("Requested Mw: " + str(mw))
            body.REMARK.append("Actual mass:" +
                               str(bgftools.getMass(body, ff)))
            body.REMARK.append("Wiener index: " + str(idx))

    log.info(str(n_generation) + " structure generated.")
    log.info("Number of trials: " + str(n_trial))

    # branch point print
    output = "*** number of branching points ***"
    for i in branch_pt_profile:
        output += i[0] + '\t' + i[1] + '\n'
    output += '\n'

    log.debug(output)
Beispiel #4
0
def dipole(bgf_file, trj_file, ff_file, out_file, avg_timestep, silent=False):

    ### init
    timestep = 0
    l_timestep = []
    line = []
    n_header = 0
    t1 = 0
    t2 = 0
    # clock
    vector = [0, 0, 1]
    # the axis of interest. in the acetone-water case, z direction.
    atominfo = dict()
    # atom data extracted from ff_file
    result = dict()
    axis = 2
    # for orientational distribution of dipole moments. 1: x-axis, 2: y-axis, 3: z-axis

    ### unit conversion for debye
    elementary_q = 1.602176487e-19  # elementary charge in C
    debye_conv = 3.33564e-30  # 1 Debye in C*m
    k = elementary_q * 1e-10 / debye_conv

    ### open files
    myBGF = bgf.BgfFile(bgf_file)
    myTRJ = open(trj_file)
    myTRJ.seek(0)
    myOUT = open(out_file + ".dat", 'w')
    #myOUT2 = open(out_file + ".angle.dat", 'w')
    myRESULT = open(out_file + ".pickle", 'w')
    myRESULT2 = open(out_file + ".histo.pickle", 'w')

    ### read residues from bgf_file
    residueNames = set()
    # kind of residues in BGF file
    residueNumbers = set()
    dict_residue = dict()
    # stores residue numbers per each residue. RES1: [1, 2, ..], RES2: [6, 7, ..]
    for i in myBGF.a:
        rname = string.strip(i.rName)
        residueNames.add(rname)

        rno = i.rNo
        residueNumbers.add(rno)

    temp = ""
    for i in residueNames:
        temp += i + " "
        dict_residue[i] = []

    if not silent:
        print("Found " + str(len(residueNames)) + " residues in BGF file: " +
              str(temp))

    ### bookkeep residue numbers for each residue
    molecules = bgftools.getMoleculeList(myBGF)
    for molecule in molecules:
        # get an atom
        atom = myBGF.getAtom(molecule[0])
        atomresname = string.strip(atom.rName)
        atomresno = atom.rNo

        # check if all molecule has same residue name and numbers
        for ano in molecule:
            atom2 = myBGF.getAtom(ano)
            temp_rno = atom2.rNo
            temp_rname = string.strip(atom2.rName)
            if temp_rno != atomresno or temp_rname != atomresname:
                nu.die(
                    "Different residue name or residue number in a same molecule: "
                    + str(atom2.aNo))

        # record resid for resnames
        dict_residue[atomresname].append(atom.rNo)

    ### read mass from ff_file
    try:
        parse = ff_file.split(" ")
    except:
        nu.die(
            "Error occurred when reading the force field file.. Check your " +
            str(ff_file))
    else:
        if not silent:
            print("Found " + str(len(parse)) + " Cerius2 Force Fields.")

    for i in parse:
        FF = dreiding.loadFF(i)
        temp_atominfo = dreiding.loadAtomTypes(FF)
        atominfo.update(temp_atominfo)

    ### read trajectory file
    # how many steps to go?
    wc_trj_file = popen("grep -A 1 TIMESTEP " + trj_file).read()
    wc_trj_file = wc_trj_file.split()
    l_timestep = []

    for i in wc_trj_file:
        if "ITEM" in i or "TIME" in i or "--" in i:
            pass
        else:
            l_timestep.append(i)

    l_timestep = [int(i) for i in l_timestep]
    l_timestep.sort()

    n_timestep = len(l_timestep)
    if not silent:
        print("The trajectory contains " + str(n_timestep) + " timesteps.")

    l_requested_timesteps = l_timestep[-avg_timestep:]  # requested timesteps
    if not silent:
        print("Only requested the last " + str(avg_timestep) + " timesteps. ")

    # Find header of the trajectory file
    while 1:
        templine = myTRJ.readline()
        line.append(templine.strip('\n').strip('ITEM: '))
        n_header += 1
        if "ITEM: ATOMS" in templine:
            break

    # INITIAL trajectory information
    timestep = int(line[1])
    natoms = int(line[3])
    boxsize = [
        line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0],
        line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]
    ]
    boxsize = [float(i) for i in boxsize]
    keywords = line[8].strip('ATOMS ')

    # for every shot in the trajectory file update BGF and manipulate
    dumpatom = get_line(trj_file)
    processed_step = 0

    t1 = t2 = 0
    elapsed_time = 0

    while 1:
        try:
            chunk = [next(dumpatom) for i in range(natoms + n_header)]
        except StopIteration:
            break

        timestep = int(chunk[1])

        if not timestep in l_requested_timesteps:
            continue

        #l_timestep.append(timestep)
        natoms = int(chunk[3])
        boxsize = [
            chunk[5].split(' ')[0], chunk[5].split(' ')[1],
            chunk[6].split(' ')[0], chunk[6].split(' ')[1],
            chunk[7].split(' ')[0], chunk[7].split(' ')[1]
        ]
        boxsize = [float(i) for i in boxsize]
        boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]),
                   (boxsize[5] - boxsize[4])]
        keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ')

        ### Show progress
        t1 = time.time()
        remaining_time = elapsed_time * (len(l_requested_timesteps) -
                                         processed_step)
        sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) +
                         " (Elapsed time for the previous step: " +
                         "{0:4.1f}".format(elapsed_time) +
                         " seconds, Remaining time: " +
                         "{0:4.1f}".format(remaining_time) + " seconds = " +
                         "{0:4.1f} minutes".format(remaining_time / 60) + ")")
        sys.stdout.flush()

        processed_step += 1

        ### update myBGF with trajectory information ###
        natom_bgf = len(myBGF.a)  # number of atoms in BGF file

        if not natom_bgf == natoms:
            nu.die(
                "Number of atoms in trajectory file does not match with BGF file."
            )

        mode = ""
        if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords:
            mode = 'scaled'
        elif 'x' in keywords or 'y' in keywords or 'z' in keywords:
            mode = 'normal'
        elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords:
            mode = 'unwrapped'

        # actual coordinate
        coordinfo = chunk[9:]

        # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz']
        for atomline in coordinfo:
            atomcoord = atomline.split(' ')
            atom = myBGF.getAtom(int(atomcoord[0]))

            if mode == 'scaled':
                atom.x = float(atomcoord[2]) * boxsize[0]
                atom.y = float(atomcoord[3]) * boxsize[1]
                atom.z = float(atomcoord[4]) * boxsize[2]

            elif mode == 'unwrapped':
                atom.x = float(atomcoord[2])
                atom.y = float(atomcoord[3])
                atom.z = float(atomcoord[4])

            elif mode == 'normal':
                try:
                    ix_index = keywords.index('ix')
                    iy_index = keywords.index('iy')
                    iz_index = keywords.index('iz')
                except ValueError:
                    nu.warn(
                        "No image information no the trajectory file. Will be treated as unwrapped."
                    )
                    atom.x = float(atomcoord[2])
                    atom.y = float(atomcoord[3])
                    atom.z = float(atomcoord[4])
                else:
                    atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float(
                        atomcoord[2])
                    atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float(
                        atomcoord[3])
                    atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float(
                        atomcoord[4])

            try:
                for i in range(0, 3):
                    myBGF.CRYSTX[i] = boxsize[i]
            except:
                pass
                #nu.warn("Crystal information error: is this file not periodic?")

        # apply periodic condition
        myBGF = bgftools.periodicMoleculeSort(myBGF, 0)

        ### DONE for updating trj on BGF file ###

        ### Now Dipole Moment Calculation
        # list of all molecules in BGF
        dipole_moments = dict()
        abs_dipole_moments = dict()
        angles = dict()
        temp_dict = dict()
        output_dipole = str(timestep) + "\t"
        output_abs_dipole = str(timestep) + "\t"
        output_angle = str(timestep) + "\t"

        ### find bin for orientational distribution of dipole moment
        min = 100000
        max = -100000
        for atom in myBGF.a:
            coord = [atom.x, atom.y, atom.z]
            if coord[axis] < min:
                min = coord[axis]
            if coord[axis] > max:
                max = coord[axis]

        if boxsize[axis] > max:
            max = boxsize[axis]
        if 0 < min:
            min = 0

        bins = np.arange(math.floor(min), math.ceil(max), 1.0)
        binned_rNo = dict()
        for r in residueNames:
            binned_rNo[r] = [[] for b in bins]
            # space for binned residue numbers (= molecules)
        binned_mu = copy.deepcopy(binned_rNo)

        ### For every molecule
        for molecule in molecules:
            n_atom = len(molecule)  # number of atoms in the molecule
            residue_no = myBGF.getAtom(molecule[0]).rNo
            # residue number of the molecule
            residue_name = myBGF.getAtom(molecule[0]).rName
            # residue name of the molecule
            m = bgftools.getMass(myBGF, molecule, ff_file)
            # molecule mass
            cm = [0, 0, 0]
            # center of mass
            mu = [0, 0, 0]
            # dipole moment
            coord = [0, 0, 0]
            # atom x, y, z

            for aNo in molecule:
                atom = myBGF.getAtom(aNo)
                coord = [atom.x, atom.y, atom.z]

                # error if residue numbers are different
                if atom.rNo != residue_no:
                    nu.die(
                        "Residue numbers in a same molecule are not consistent. Please check your BGF file."
                    )

                # error if mass is unreadable
                ffType = string.strip(atom.ffType)
                try:
                    aMass = atominfo[ffType]['MASS']
                except:
                    nu.die("Cannot read the atom type " + str(atom.ffType) +
                           " in the data file.")

                # calculate CM
                for index, i in enumerate(coord):
                    cm[index] += i * aMass

            cm = [i / m for i in cm]
            # center of mass
            #print(str(residue_no) + '\t' + str(cm))

            # REMARK: it seems to be okay without this process.
            """
			# translate the molecule to CM
			for aNo in molecule:
				atom = myBGF.getAtom(aNo)
				atom.x -= cm[0]
				atom.y -= cm[1]
				atom.z -= cm[2]
			"""

            # calculate dipole moment sum(qi * di)
            mu_i = []
            for aNo in molecule:
                atom = myBGF.getAtom(aNo)
                coord = [atom.x, atom.y, atom.z]
                mu_i.append([i * atom.charge * k for i in coord])

            # sum up
            mu = [0, 0, 0]
            for i in mu_i:
                mu[0] += i[0]
                mu[1] += i[1]
                mu[2] += i[2]

            # for acetone case
            #len_mu = math.sqrt(dot(mu, mu))
            #len_vector = math.sqrt(dot(vector, vector))
            len_mu = math.sqrt(dot(mu, mu))
            len_vector = 1.0

            #angle = dot(mu, vector) / ( len_mu * len_vector )
            angle = mu[2] / (len_mu * len_vector)  # for ACETONE case

            # results
            dipole_moments[residue_no] = mu
            abs_dipole_moments[residue_no] = len_mu
            angles[residue_no] = angle

            ### Orientational distribution of dipole moments
            # binning according to molecule's CM and store to binned_rNo
            for index, bin in enumerate(bins):
                try:
                    if bin < cm[axis] and bins[index + 1] > cm[axis]:
                        binned_rNo[residue_name][index].append(residue_no)
                except:
                    continue
            # binning is perfect so far!

        residueNumbers = list(residueNumbers)
        residueNames = list(residueNames)
        residueNumbers.sort()

        temp_dict = dict()
        temp_dict2 = dict()
        temp_dict2['MU'] = dipole_moments
        temp_dict2['ABSMU'] = abs_dipole_moments
        temp_dict2['ANGLES'] = angles
        temp_dict['TOTAL'] = temp_dict2

        ### paperworks per residue
        for resname in residueNames:
            temp_dict2 = dict()
            res_dipole_moments = dict()
            res_abs_dipole_moments = dict()
            res_angles = dict()

            # load residue numbers per residue type
            resnumbers = dict_residue[resname]
            for rno in resnumbers:
                res_dipole_moments[rno] = dipole_moments[rno]
                res_abs_dipole_moments[rno] = abs_dipole_moments[rno]
                res_angles[rno] = angles[rno]

            temp_dict2['MU'] = res_dipole_moments
            temp_dict2['ABSMU'] = res_abs_dipole_moments
            temp_dict2['ANGLES'] = res_angles
            temp_dict2['BIN'] = bins

            # for analyze
            #temp_dict2['RNO_DISTR'] = binned_rNo[resname]
            temp_dict2['DISTR_ANGLES'] = binned_mu[resname]
            temp_dict2['DISTR_ABSMU'] = binned_mu[resname]

            # write dipole moments
            for index, item in enumerate(binned_rNo[resname]):
                if len(item) == 0:
                    continue
                for i in item:
                    temp_dict2['DISTR_ANGLES'][index].append(
                        temp_dict2['ANGLES'][i])
                    #temp_dict2['DISTR_ABSMU'][index].append(temp_dict2['ABSMU'][i])

            temp_dict[resname] = temp_dict2

        # result: timestep - residue - MU, ANGLES, NATOMS
        result[timestep] = temp_dict

        t2 = time.time()  # time mark
        elapsed_time = t2 - t1

    ### Averaging orientational distribution of dipole moments over timesteps
    #del temp_dict1
    del temp_dict2
    temp_dict1 = dict()
    # angles with keys: bin
    temp_dict2 = dict()
    # |mu| with keys: bin

    # append
    for r in residueNames:
        temp_dict1[r] = dict()
        temp_dict2[r] = dict()

        for t in l_requested_timesteps:
            for index, b in enumerate(result[t][r]['BIN']):
                if not temp_dict1[r].has_key(b):
                    temp_dict1[r][b] = []
                if not temp_dict2[r].has_key(b):
                    temp_dict2[r][b] = []

                # append averaged values
                avg, std = meanstdv(result[t][r]['DISTR_ANGLES'][index])
                temp_dict1[r][b].append(avg)

                for i in result[t][r]['DISTR_ANGLES'][index]:
                    temp_dict2[r][b].append(i)

                #for i in result[t][r]['DISTR_ABSMU'][index]:
                #	temp_dict2[b].append(i)

    # average
    avg_angles = dict()
    avg_absmu = dict()
    avg_angles_stdev = dict()
    avg_absmu_stdev = dict()

    for r in residueNames:
        avg_angles[r] = dict()
        avg_absmu[r] = dict()
        avg_angles_stdev[r] = dict()
        avg_absmu_stdev[r] = dict()
        temp = temp_dict1[r].keys()
        temp.sort()
        for i in temp:
            avg_angles[r][i], avg_angles_stdev[r][i] = meanstdv(
                temp_dict1[r][i])
            avg_absmu[r][i], avg_absmu_stdev[r][i] = meanstdv(temp_dict2[r][i])

    # print for average
    print("")
    print("Averaged " + str(avg_timestep) + " timesteps out of " +
          str(n_timestep))
    for r in residueNames:
        print(r)
        for i in temp:
            #print(str(i) + '\t' + str(temp_dict1[i]))
            print(
                str(i) + '\t' + str(avg_angles[r][i]) + '\t' +
                str(avg_angles_stdev[r][i]))
        print("")

    # save for debug
    output = ""
    for r in residueNames:
        for i in temp:
            output += str(i) + '\t' + str(temp_dict1[r][i]) + '\n'

    myOUT.write(output)
    myOUT.close()

    # save the pickle object
    pkl.dump(result, myRESULT)
    myRESULT.close()

    pkl.dump(temp_dict2, myRESULT2)
    myRESULT2.close()

    print('')
    return 1
Beispiel #5
0
def get_mass(bgf_file, ff_file=''):
    mybgf = bgf.BgfFile(bgf_file)

    return bt.getMass(mybgf, ff_file=ff_file)
Beispiel #6
0
def count_layer(bgf_file, trj_file, ff_file='', out_file='', prefix=''):
    '''measures confined density of graphene interlayer
    '''
    # variables
    result = dict()
    r_vdw_C = 3.38383824 / 2

    # inner functions
    def get_line(file):
        with open(file, 'r') as f:
            for line in f:
                yield line

    # 1. Load BGF
    mybgf = bgf.BgfFile(bgf_file)
    N_BGF_ATOMS = len(mybgf.a)

    # 2. Read LAMMPS Trajectory
    mytrj = lt.lammpstrj(trj_file)
    timesteps = mytrj.load()
    N_HEADER = mytrj.nheader
    N_ATOMS = mytrj.natoms[0]
    N_BUFFER = N_HEADER + N_ATOMS
    if N_BGF_ATOMS != N_ATOMS:
        nu.die(
            "Number of atoms in trajectory file does not match with BGF file.")

    # 3. Determine dump style
    dump_keywords = mytrj.dumpstyle
    yes_scale = False
    if 'xs' in dump_keywords:
        yes_scale = True

    # Mass
    wat_ano = []
    for atom in mybgf.a:
        if atom.chain == "I":
            wat_ano.append(atom.aNo)

    mass = bt.getMass(mybgf, wat_ano, ff_file=ff_file)

    # 4. Update coordinates from the snapshot
    dump = get_line(trj_file)
    for t in tqdm.tqdm(timesteps, ncols=120, desc="Counting Atoms"):
        chunk = [next(dump) for i in range(N_BUFFER)]

        t = int(chunk[1])
        mybgf.CRYSTX = mytrj.pbc[t] + [90.0, 90.0, 90.0]

        coords = chunk[9:]
        for c in coords:
            c = c.split(' ')
            atom = mybgf.getAtom(int(c[0]))

            if yes_scale:
                atom.x = float(c[2]) * pbc[0]
                atom.y = float(c[3]) * pbc[1]
                atom.z = float(c[4]) * pbc[2]
            else:
                atom.x = float(c[2])
                atom.y = float(c[3])
                atom.z = float(c[4])

        mybgf = bt.periodicMoleculeSort(mybgf,
                                        mybgf.CRYSTX,
                                        ff_file=ff_file,
                                        silent=True)

        ### collect data
        def density():
            # variables
            density = dict()

            # height
            avg_gra_z1 = bt.atoms_average(
                mybgf,
                'atom.z',
                selection="'C_2G' in atom.ffType and atom.rNo == 1")
            avg_gra_z2 = bt.atoms_average(
                mybgf,
                'atom.z',
                selection="'C_2G' in atom.ffType and atom.rNo == 2")
            dist = avg_gra_z2 - avg_gra_z1
            eff_dist = avg_gra_z2 - avg_gra_z1 - 2 * r_vdw_C

            # volume
            x = mytrj.pbc[t][0]
            y = mytrj.pbc[t][1]
            volume = x * y * dist
            eff_volume = x * y * eff_dist

            # density
            density = mass / 6.022 / volume * 10
            eff_density = mass / 6.022 / eff_volume * 10

            return [
                x, y, dist, mass, volume, eff_volume, eff_dist, density,
                eff_density
            ]

        density = density()
        result[t] = density

    # 5. Analyze
    timesteps = sorted(result.keys())
    with open(prefix + '.trj.density.dat', 'w') as f:
        output = "#x\ty\tdist\tmass\tvolume\teff_volume\teff_dist\tdensity\teff_density\n"
        for t in timesteps:
            output += "%d " % t
            output += " ".join("%8.3f" % float(i) for i in result[t])

        f.write(output)
def countWaterCNT(bgf_file, trj_file, ff_file, n_step, do_hbonds, silent=False):

	# const
	PI = math.pi
	vdw_r_C = 1.7

	# init
	timestep = 0; l_timestep = []; line = []; n_header = 0;
	t1 = 0; t2 = 0; # clock

	myBGF = bgf.BgfFile(bgf_file)
	myTRJ = open(trj_file)
	myTRJ.seek(0)
	myDAT = open(bgf_file[:-4] + ".calcDensity.count.dat", "w")
	myDAT2 = open(bgf_file[:-4] + ".calcDensity.hbond.dat", "w")
	myDAT3 = open(bgf_file[:-4] + ".calcDensity.configuration.dat", "w")
	myDAT.write(str(sys.argv) + "\n")
	myDAT.write("Time\tmin_X\tmax_X\tHeight\tRadius\tNumber\tVolume\tEff_volume\tExact_mass\tMass\tExact_den\tMtOH_den\tExact_eff_den\tMtOH_eff_den\tn_hbond\n")

	# how many steps to go?
	wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read()
	n_timestep = int(wc_trj_file.split()[0]);
	if n_step == 0:
		n_step = n_timestep;

	print("The trajectory contains " + str(n_timestep) + " timesteps.")
	print("The script will proceed for the last " + str(n_step) + " timesteps.")

	# extract aNos of CNT in the BGF file
	aNo_CNT = []
	aNo_MtOH_C = []
	aNo_MtOH_all = []

	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

	# check if there exists MtOH properly
	if len(aNo_MtOH_C) == 0:
		nu.die("No MtOH molecules in the BGF file.")
	if len(aNo_CNT) == 0:
		nu.die("No CNT molecules in the BGF file.")

	# Find header of the trajectory file
	while 1:
		templine = myTRJ.readline()
		line.append(templine.strip('\n').strip('ITEM: '))
		n_header += 1
		if "ITEM: ATOMS" in templine:
			break;

	# INITIAL trajectory information
	timestep = int(line[1])
	natoms = int(line[3])
	boxsize = [line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]]
	boxsize = [float(i) for i in boxsize]
	keywords = line[8].strip('ATOMS ')

	# for every shot in the trajectory file update BGF and manipulate
	dumpatom = get_line(trj_file)
	processed_step = 0;

	t1 = t2 = 0; elapsed_time = 0;

	while 1:
		### Show progress
		t1 = time.time();
		remaining_time = elapsed_time * (n_step - processed_step)
		sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time/60) + ")")
		sys.stdout.flush()

		processed_step += 1;
		if processed_step == n_step:
			break;

		aNo_MtOH_C_atoms = []
		aNo_atoms_in_CNT = []


		### Read
		try:
			chunk = [next(dumpatom) for i in range(natoms+n_header)]
		except StopIteration:
			break;

		timestep = int(chunk[1])
		natoms = int(chunk[3])
		boxsize = [chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1]]; 
		boxsize = [float(i) for i in boxsize]; boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])]
		keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ')


		### update myBGF with trajectory information ###
		natom_bgf = len(myBGF.a)	# number of atoms in BGF file
	
		if not natom_bgf == natoms:
			nu.die("Number of atoms in trajectory file does not match with BGF file.")
	
		mode = ""
		if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords:
			mode = 'scaled'
		elif 'x' in keywords or 'y' in keywords or 'z' in keywords:
			mode = 'normal'
		elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords:
			mode = 'unwrapped'
	
		# actual coordinate
		coordinfo = chunk[9:]
	
		# assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz']
		for atomline in coordinfo:
			atomcoord = atomline.split(' ')
			atom = myBGF.getAtom(int(atomcoord[0]))
	
			if mode == 'scaled':
				atom.x = float(atomcoord[2]) * boxsize[0]
				atom.y = float(atomcoord[3]) * boxsize[1]
				atom.z = float(atomcoord[4]) * boxsize[2]
	
			elif mode == 'unwrapped':
				atom.x = float(atomcoord[2])
				atom.y = float(atomcoord[3])
				atom.z = float(atomcoord[4])
	
			elif mode == 'normal':
				try:
					ix_index = keywords.index('ix')
					iy_index = keywords.index('iy')
					iz_index = keywords.index('iz')
				except ValueError:
					nu.warn("No image information no the trajectory file. Will be treated as unwrapped.")
					atom.x = float(atomcoord[2])
					atom.y = float(atomcoord[3])
					atom.z = float(atomcoord[4])
				else:
					atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float(atomcoord[2]) 
					atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float(atomcoord[3]) 
					atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float(atomcoord[4]) 
	
			try:
				for i in range(0, 3):
					myBGF.CRYSTX[i] = boxsize[i]
			except:
				pass;
				#nu.warn("Crystal information error: is this file not periodic?")
				
		# apply periodic condition
		myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True)

		### myBGF update complete! ###

		aNo_MtOH_C_in_CNT = copy.deepcopy(aNo_MtOH_C)

		### Realign whole system to x axis
		sys.stdout.write(' Realigning.. ')
		sys.stdout.flush()
		# 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;

		# transpose for "all atoms in BGF": move COM of CNT as origin
		# 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

		# move
		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" rotation
		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])

		# for CNT atoms, calculate some properties
		min_x_CNT = 0.0; max_x_CNT = 0.0; radius_CNT = 0.0; height_CNT = 0.0; aNo_MtOH_C_not_in_CNT = []; temp = [];
		min_y_CNT = 0.0; max_y_CNT = 0.0;
		min_z_CNT = 0.0; max_z_CNT = 0.0;
		CNT_orientation = "";

		# check the orientation of CNT
		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
			if atom.y < min_y_CNT:
				min_y_CNT = atom.y
			if atom.y > max_y_CNT:
				max_y_CNT = atom.y
			if atom.z < min_z_CNT:
				min_z_CNT = atom.z
			if atom.z > max_z_CNT:
				max_z_CNT = atom.z
	
		x_diff = max_x_CNT - min_x_CNT
		y_diff = max_y_CNT - min_y_CNT
		z_diff = max_z_CNT - min_z_CNT

		if x_diff > y_diff and x_diff > z_diff:
			# CNT is aligned along x axis
			height_CNT = x_diff
			CNT_orientation = "x"
		elif y_diff > x_diff and y_diff > z_diff:
			# CNT is aligned along y axis
			height_CNT = y_diff
			CNT_orientation = "y"
		elif z_diff > x_diff and z_diff > y_diff:
			# CNT is aligned along z axis
			height_CNT = z_diff
			CNT_orientation = "z"

		if CNT_orientation == "x":
			for aNo in aNo_CNT:
				atom = myBGF.getAtom(aNo)
				radius_CNT += math.sqrt(atom.y**2 + atom.z**2)	# average radius of CNT
		elif CNT_orientation == "y":
			for aNo in aNo_CNT:
				atom = myBGF.getAtom(aNo)
				radius_CNT += math.sqrt(atom.x**2 + atom.z**2)	# average radius of CNT
		elif CNT_orientation == "z":
			for aNo in aNo_CNT:
				atom = myBGF.getAtom(aNo)
				radius_CNT += math.sqrt(atom.x**2 + atom.y**2)	# average radius of CNT

		radius_CNT = radius_CNT / N_CNT

		### Rotate y or z to x axis
		Tyx = numpy.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]])
		Tzx = numpy.array([[0, 0, -1], [0, 1, 0], [1, 0, 0]])
	
		if CNT_orientation == "y":
			for atom in myBGF.a:
				u = numpy.matrix([atom.x, atom.y, atom.z]).T
				Tu = Tyx*u
				atom.x = float(Tu[0])
				atom.y = float(Tu[1])
				atom.z = float(Tu[2])
				min_x_CNT = min_y_CNT;
				max_x_CNT = max_y_CNT;
	
		elif CNT_orientation == "z":
			for atom in myBGF.a:
				u = numpy.matrix([atom.x, atom.y, atom.z]).T
				Tu = Tzx*u
				atom.x = float(Tu[0])
				atom.y = float(Tu[1])
				atom.z = float(Tu[2])
				min_x_CNT = min_z_CNT;
				max_x_CNT = max_z_CNT;
	
		### get MtOHs in CNT
		sys.stdout.write('Density.. ')
		sys.stdout.flush()
		# 1. aNo_atoms_in_CNT: exact atoms within CNT
		for atom in myBGF.a:
			ano = atom.aNo
			dist = math.sqrt(atom.y**2 + atom.z**2)
			if not "CNT" in atom.rName and atom.x > min_x_CNT and atom.x < max_x_CNT and dist < radius_CNT:
				# inside
				aNo_atoms_in_CNT.append(ano)
			else:
				# outside
				pass;

		# 2. aNo_MtOH_C_atoms: molecules which C atom is within CNT
		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:
				# inside of the CNT
				pass;
			else:
				"""
				# delete atoms
				delete_list = [];
				dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), delete_list)
				for i in delete_list:
					aNo_MtOH_C_not_in_CNT.append(myBGF.a2i[i])
				"""
				# outside of the CNT
				aNo_MtOH_C_in_CNT.remove(aNo)

		for aNo in aNo_MtOH_C_in_CNT:
			anos = [];
			dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), anos)
			for i in anos:
				aNo_MtOH_C_atoms.append(i)

		# calculate volume of CNT
		# radius: average radius - can't be applied in bent CNTs
		# height: maximum height of CNT
		# volume: radius**2 + height
		volume = (radius_CNT**2) * height_CNT * PI
		eff_volume = (radius_CNT - vdw_r_C)**2 * height_CNT * PI

		# calculate mass in CNT
		MtOH_exact_mass = bgftools.getMass(myBGF, aNo_atoms_in_CNT, ff_file)
		MtOH_MtOH_C_mass = bgftools.getMass(myBGF, aNo_MtOH_C_atoms, ff_file)

		# calculate density: mass / 6.022 / vol * 10
		vol_exact_density = MtOH_exact_mass / 6.022 / volume * 10;
		vol_MtOH_density = MtOH_MtOH_C_mass / 6.022 / volume * 10;

		# calculate effective density ( radius - r_vdw )
		eff_vol_exact_density = MtOH_exact_mass / 6.022 / eff_volume * 10;
		eff_vol_MtOH_density = MtOH_MtOH_C_mass / 6.022 / eff_volume * 10;

		### Check MET status
		output = "";
		MeOH_align = [];

		# find O in MET: MeOH_align = [C.x, O.x]
		for ano in aNo_MtOH_C_in_CNT:
			atom = myBGF.getAtom(ano)
			for i in atom.CONECT:
				atom2 = myBGF.getAtom(i)
				if "O" in atom2.ffType:
					MeOH_align.append([atom.x, atom2.x])
	
		MeOH_align.sort(key=sortkey)

		# print MET align status
		for i in MeOH_align:
			if i[0] > i[1]:
				# C-O: 1
				output += "1 "
			else:
				# O-C: 0
				output += "0 "

		# n_hbond
		n_hbond = 0;
		"""
		# how many 10 or 01 (hydrogen bonds) in output?
		count += output.count("1 0")
		count += output.count("0 1")
		"""

		hbond_C_pairs = "";
		hbond_OH_pairs = [];
		if do_hbonds:
			### find hydrogen bonds
			### criteria: r(O..O) <= 3.5, r(O..HO) <= 2.6, A(HO-O..O) <= 30' (ref: Haughney et al., JPC 1987)
			###                       acceptor donor       donor   acceptor
			# for all pairs of MtOH molecules
			sys.stdout.write('Hbonds.. ')
			sys.stdout.flush()

			C_pairs = itertools.permutations(aNo_MtOH_C_in_CNT, 2)
			# count how many iterations on the permutations:
			#c_perm = 0;
			#for i in C_pairs:
			#	c_perm += 1;

			#print(str(len(aNo_MtOH_C_in_CNT)) + " " + str(c_perm))

			for p in C_pairs:
				(ano1, ano2) = p

				# Donor part
				# get C1
				C1 = myBGF.getAtom(ano1)
				# get O1
				for i in C1.CONECT:
					temp_atom = myBGF.getAtom(i)
					if "O" in temp_atom.ffType[0]:
						O1 = temp_atom
				# get H1
				for i in O1.CONECT:
					temp_atom = myBGF.getAtom(i)
					if "H" in temp_atom.ffType[0]:
						H1 = temp_atom

				# Acceptor part
				# get C2
				C2 = myBGF.getAtom(ano2)
				# get O2
				for i in C2.CONECT:
					temp_atom = myBGF.getAtom(i)
					if "O" in temp_atom.ffType[0]:
						O2 = temp_atom
				# get H2
				for i in O2.CONECT:
					temp_atom = myBGF.getAtom(i)
					if "H" in temp_atom.ffType[0]:
						H2 = temp_atom

				"""
				# H1 and O2 should be inside the CNT
				dist = math.sqrt(H1.y**2 + H1.z**2)
				if H1.x > min_x_CNT and H1.x < max_x_CNT and dist < radius_CNT:
					continue;

				dist = math.sqrt(O2.y**2 + O2.z**2)
				if O2.x > min_x_CNT and O2.x < max_x_CNT and dist < radius_CNT:
					continue;
				"""

				## determine hbond
				# calculate r(O1..O2)
				crit_1 = bgf.distance(O1, O2);
				# calculate r(O1..H2)
				crit_2 = bgf.distance(O2, H1);
				# calculate A(O1-H2..O2)
				crit_3 = bgf.angle(H1, O1, O2);

				#if crit_1 <= 3.5 and crit_2 <= 2.6 and crit_3 <= 30:
				if crit_1 <= 3.5 and crit_3 <= 30:
					# Hbond!!
					n_hbond += 1;
					OH_pair = [O2.aNo, H1.aNo];
					hbond_OH_pairs.append(OH_pair)
					#hbond_C_pairs += str(ano1) + "-" + str(ano2) + "\t"
				else:
					continue;

		hbond_pairs = hbond_OH_pairs
		#temp = nu.removeRepeat(hbond_OH_pairs)
		#hbond_pairs = nu.removeReverse(temp)

		sys.stdout.write('Done                                                        ')
		sys.stdout.flush()

		myDAT.write(str(timestep) + "\t")
		myDAT.write(str("{0:<8.3f}".format(min_x_CNT)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(max_x_CNT)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(height_CNT)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(radius_CNT)) + "\t")
		myDAT.write(str(len(aNo_MtOH_C_in_CNT)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(volume)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(eff_volume)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(MtOH_exact_mass)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(MtOH_MtOH_C_mass)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(vol_exact_density)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(vol_MtOH_density)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(eff_vol_exact_density)) + "\t")
		myDAT.write(str("{0:<8.3f}".format(eff_vol_MtOH_density) + "\t"))
		myDAT.write(str(len(hbond_pairs)) + "\n")
		myDAT2.write(str(hbond_pairs) + "\n")
		myDAT3.write(str(output) + "\n")
		#myDAT.write(str(aNo_MtOH_C_in_CNT) + "\n")

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

		t2 = time.time()	# time mark
		elapsed_time = t2 - t1;

	print('')

	myDAT.close()
	myDAT2.close()

	return 1
Beispiel #8
0
#!/home/noische/python

import sys
import os

import bgf
import bgftools
import dreiding

usage = "getMass.py bgffile fffile"
if len(sys.argv) < 2:
	print(usage)
	sys.exit(0)

bgf_file = sys.argv[1]
ff_file = sys.argv[2]

myBGF = bgf.BgfFile(bgf_file)
Mw = bgftools.getMass(myBGF, ff_file)

print(bgf_file + " mass: " + str(Mw))
Beispiel #9
0
Info)    Residues: 1630
Info)    Waters: 1629
Info)    Segments: 1
Info)    Fragments: 1630   Protein: 0   Nucleic: 0
"""

usage = """
BGF_info.py bgf_file ff_file
Prints information on BGF file. (mass, n_atoms, ff_types, ...)

"""
if len(sys.argv) < 3:
    print(usage)
    sys.exit(0)

bgf_file = sys.argv[1]
ff_file = sys.argv[2]

mybgf = bgf.BgfFile(bgf_file)

mw = bgftools.getMass(mybgf, ff_file)   # molecular weight
n_atoms = len(mybgf.a)  # n_atoms

d_fftypes = set()
for atom in mybgf.a:
    d_fftypes.add(atom.ffType)

print("Molecule mass: %f" % mw)
print("Number of molecules: %f" % n_atoms)
print("FF types in the molecule: %s" % str(list(d_fftypes)))
def getSlipLength(bgf_file,
                  trj_file,
                  ff_file,
                  n_step,
                  n_avg_step,
                  silent=False):

    # const
    PI = math.pi
    vdw_r_C = 1.7

    # init
    timestep = 0
    l_timestep = []
    line = []
    n_header = 0
    t1 = 0
    t2 = 0
    # clock

    l_data = []
    # stores [r vz]
    l_F_N = []
    l_F_N_inner = []
    l_F_N_outer = []
    # stores sum of friction force
    l_result = []
    l_avg_radius_CNT = []

    n_avg_count = 0
    n_avg_count_step = 0

    myBGF = bgf.BgfFile(bgf_file)
    myTRJ = open(trj_file)
    myTRJ.seek(0)
    myPkl = open(trj_file + ".method2.pickle", 'w')
    myOut = open(trj_file + ".method2.avg_vz.out", 'w')
    myOut.write(str(n_avg_step) + " steps are averaged.\n")
    myOut.write("AVG_STARTING_STEP\tAVG_vz\tF_N\tF_N_outer\tF_N_inner\n")

    # how many steps to go?
    if not silent: print("== Step 1. Loading LAMMPS Trajectory")
    wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read()
    n_timestep = int(wc_trj_file.split()[0])
    if n_step == 0:
        n_step = n_timestep

    print("The trajectory contains " + str(n_timestep) + " timesteps.")

    # extract aNos of CNT in the BGF file
    aNo_CNT = []
    aNo_WAT_O = []

    for atom in myBGF.a:
        # Carbons in CNT
        if "CNT" in atom.rName:
            aNo_CNT.append(atom.aNo)

        # Oxygen in water
        if "WAT" in atom.rName and "O" in atom.aName:
            aNo_WAT_O.append(atom.aNo)

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

    # check if there exists water properly
    if len(aNo_WAT_O) == 0:
        nu.die("No water molecules in the BGF file.")
    if len(aNo_CNT) == 0:
        nu.die("No CNT molecules in the BGF file.")

    # Find header of the trajectory file
    while 1:
        templine = myTRJ.readline()
        line.append(templine.strip('\n').strip('ITEM: '))
        n_header += 1
        if "ITEM: ATOMS" in templine:
            break

    # INITIAL trajectory information
    timestep = int(line[1])
    natoms = int(line[3])
    boxsize = [
        line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0],
        line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]
    ]
    boxsize = [float(i) for i in boxsize]
    keywords = line[8].strip(
        'ATOMS ')  # assume ATOMS id type xu yu zu vx vy vz fx fy fz

    # for every shot in the trajectory file update BGF and manipulate
    dumpatom = get_line(trj_file)
    processed_step = 0

    t1 = t2 = 0
    elapsed_time = 0

    while 1:
        ### Show progress
        t1 = time.time()
        remaining_time = elapsed_time * (n_step - processed_step)
        sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) +
                         " (Remaining time: " +
                         "{0:4.1f}".format(remaining_time) + " seconds, " +
                         "{0:4.1f} minutes".format(remaining_time / 60) + ")")
        sys.stdout.flush()

        if processed_step == n_step:
            break

        ### Read
        try:
            chunk = [next(dumpatom) for i in range(natoms + n_header)]
        except StopIteration:
            break

        timestep = int(chunk[1])
        l_timestep.append(timestep)
        natoms = int(chunk[3])
        boxsize = [
            chunk[5].split(' ')[0], chunk[5].split(' ')[1],
            chunk[6].split(' ')[0], chunk[6].split(' ')[1],
            chunk[7].split(' ')[0], chunk[7].split(' ')[1]
        ]
        boxsize = [float(i) for i in boxsize]
        boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]),
                   (boxsize[5] - boxsize[4])]
        keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ')

        ### update myBGF with trajectory information ###
        natom_bgf = len(myBGF.a)  # number of atoms in BGF file

        if not natom_bgf == natoms:
            nu.die(
                "Number of atoms in trajectory file does not match with BGF file."
            )

        mode = 'unwrapped'  # assume that "dump            1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz fx fy fz" in lammps input

        # actual coordinate
        coordinfo = chunk[9:]

        # modified for fast treatment
        for atomline in coordinfo:
            atomcoord = atomline.split(' ')
            atom = myBGF.getAtom(int(atomcoord[0]))

            atom.x = float(atomcoord[2])  # coord
            atom.y = float(atomcoord[3])
            atom.z = float(atomcoord[4])
            atom.vx = float(atomcoord[5])  # vel
            atom.vy = float(atomcoord[6])
            atom.vz = float(atomcoord[7])
            if 'fx' in keywords:
                atom.fx = float(atomcoord[8])  # force
                atom.fy = float(atomcoord[9])
                atom.fz = float(atomcoord[10])

            try:
                for i in range(0, 3):
                    myBGF.CRYSTX[i] = boxsize[i]
            except:
                pass
                #nu.warn("Crystal information error: is this file not periodic?")

        # apply periodic condition
        myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True)

        ### myBGF update complete! ###

        # for CNT atoms, calculate some properties on CNT
        min_x_CNT = 0.0
        max_x_CNT = 0.0
        radius_CNT = 0.0
        height_CNT = 0.0
        aNo_WAT_O_not_in_CNT = []
        temp = []
        min_y_CNT = 0.0
        max_y_CNT = 0.0
        min_z_CNT = 0.0
        max_z_CNT = 0.0
        CNT_orientation = ""

        l_radius_CNT = []
        l_x_CNT = []
        l_y_CNT = []
        for aNo in aNo_CNT:
            atom = myBGF.getAtom(aNo)

            # center of CNT
            l_x_CNT.append(atom.x)
            l_y_CNT.append(atom.y)

            # height
            if atom.z < min_z_CNT:
                min_z_CNT = atom.z
            if atom.z > max_z_CNT:
                max_z_CNT = atom.z

        # center of CNT
        x_CNT, a = nu.meanstdv(l_x_CNT)
        y_CNT, a = nu.meanstdv(l_y_CNT)
        z_diff = max_z_CNT - min_z_CNT

        # radius of CNT
        for aNo in aNo_CNT:
            atom = myBGF.getAtom(aNo)
            l_radius_CNT.append(
                math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2))

        radius_CNT, a = nu.meanstdv(l_radius_CNT)
        l_avg_radius_CNT.append(radius_CNT)

        ### get water molecules in CNT

        # inside the CNT := min_z_CNT <= z <= max_z_CNT and (x - (x_diff/2))**2 + (y - (y_diff/2))**2 < radius_CNT**2
        margin = 0
        # water molecules far from the margin will be only considered
        aNo_WAT_O_in_CNT = []
        for aNo in aNo_WAT_O:
            atom = myBGF.getAtom(aNo)
            dist_sq = (atom.x - x_CNT)**2 + (atom.y - y_CNT)**2
            if "WAT" in atom.rName and min_z_CNT + margin <= atom.z and atom.z <= max_z_CNT - margin and dist_sq < radius_CNT**2:
                aNo_WAT_O_in_CNT.append(aNo)
            else:
                pass

        ### find outer water layer and collect data
        aNo_WAT_outer = []
        for aNo in aNo_WAT_O_in_CNT:
            atom = myBGF.getAtom(aNo)
            r = math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2)

            # separate inner and outer water molecules	# for (12, 12) outer is r >= 3
            #if r >= 3: 	# 5 = 2 (depletion area) + 3 (outer shell)
            if radius_CNT - r <= 5:
                aNo_WAT_outer.append(aNo)
                #l_data.append(atom.vz*10**5)	# outer water velocity = v_slip, original velocity unit: A/fs = 10^5 m/s

        # calculate z-directional velocity of water molecules		vcm = sum vi mi / sum mi
        atom = myBGF.getAtom(aNo_WAT_outer[0])
        mass_O = bgftools.getMass(myBGF, [aNo_WAT_outer[0]], ff_file)
        atom = myBGF.getAtom(atom.CONECT[0])
        mass_H = bgftools.getMass(myBGF, [atom.aNo], ff_file)
        mass_H2O = mass_O + 2 * mass_H  # H2O mass

        for aNo in aNo_WAT_outer:
            atom = myBGF.getAtom(aNo)  # oxygen
            #vcmx = atom.vx * mass_O
            #vcmy = atom.vy * mass_O
            vcmz = atom.vz * mass_O

            for ano in atom.CONECT:
                atom2 = myBGF.getAtom(ano)
                #vcmx += atom.vx * mass_O
                #vcmy += atom.vy * mass_O
                vcmz += atom.vz * mass_H

            #vcmx /= mass_H2O
            #vcmy /= mass_H2O
            vcmz /= mass_H2O

            l_data.append(vcmz * 10**5)

        # calculate sum of forces on carbon atoms of CNT
        F_N = 0.0
        F_N_outer = 0.0
        F_N_inner = 0.0
        for aNo in aNo_CNT:
            atom = myBGF.getAtom(aNo)
            x, y = (atom.x - x_CNT, atom.y - y_CNT)
            theta = 0
            if y >= 0:
                theta = math.acos(x / (math.sqrt(x**2 + y**2)))
            else:
                theta = -math.acos(x / (math.sqrt(x**2 + y**2)))
            F_N += atom.fy * math.cos(theta) + atom.fx * math.sin(theta)
            #F_N += abs(atom.fx * math.cos(theta) + atom.fy * math.sin(theta))

        l_F_N.append(F_N)

        # timestep mark for starting average
        if n_avg_count == 0:
            n_avg_count_step = timestep

        n_avg_count += 1  # "Job's Done" counter

        # if the time comes.. average!
        if n_avg_count == n_avg_step:
            a = analyzeData(l_data)  # average vz
            l_result.append(
                [timestep, a]
            )  # note the the timestep here is not the timestep that the average started.

            t, s = nu.meanstdv(l_F_N)  # average force on CNT

            myOut.write(
                str(n_avg_count_step) + "\t" + str(a) + "\t" + str(t) + "\n")

            # reset
            l_data = []
            n_avg_count = 0
            l_F_N = []

        sys.stdout.write(
            'Done                                                        ')
        sys.stdout.flush()

        # ending for timestep treatment
        t2 = time.time()  # time mark
        elapsed_time = t2 - t1
        processed_step += 1

    # write output
    pkl.dump(l_result, myPkl)

    print('')
    return 1
def main(bgf_file, out_file, ff_file="", n=0, density=0.9, r=1.0):
    n_total_trial = 0
    # if molecule numbers are not specified, create the box with the existing molecules in the BGF file.
    # if molecule numbers specified, copy the molecules in the box as many as the number specified.
    if n:
        import copy
        mybgf = bgf.BgfFile()
        id = 0
        for i in tqdm.tqdm(range(int(n)), desc="Cloaning molecules",
                           ncols=120):
            id += 1
            mybgf2 = bgf.BgfFile(bgf_file)
            for i in mybgf2.a:
                i.rNo = id
            mybgf = mybgf.merge(mybgf2)
    else:
        mybgf = bgf.BgfFile(bgf_file)

    # calculate cubic size
    mass = bt.getMass(mybgf, ff_file=ff_file)
    target_density = density
    volume = mass / target_density / 6.022 * 10
    cell_x = math.pow(volume, 1.0 / 3)
    print("The script will generate a cubic with dimensions %f^3" % cell_x)
    mybgf.CRYSTX = [cell_x, cell_x, cell_x, 90.0, 90.0, 90.0]

    # get com
    redefined_coords = []
    molecules = bt.getMoleculeList(mybgf)
    for mol in tqdm.tqdm(molecules, ncols=120):
        #for index, mol in enumerate(molecules):
        n_trial = 0
        while True:
            n_trial += 1
            n_total_trial += 1
            cx, cy, cz = bt.getCom(mybgf, ff_file=ff_file, aNo_list=mol)
            new_pos = [random.uniform(0, cell_x) for i in range(3)]
            new_rot = [random.uniform(0, 2 * math.pi) for i in range(3)]
            U = mathtools.rotate_matrix(new_rot[0], new_rot[1], new_rot[2])

            # check the room before lying
            mol_coords = []
            for ano in sorted(mol):
                atom = mybgf.getAtom(ano)
                x = atom.x
                y = atom.y
                z = atom.z
                x -= cx
                y -= cy
                z -= cz

                # rotate
                v = np.matrix([x, y, z]).T
                Uv = U * v
                x = float(Uv[0])
                y = float(Uv[1])
                z = float(Uv[2])

                # move CM to new position
                x += new_pos[0]
                y += new_pos[1]
                z += new_pos[2]

                mol_coords.append([x, y, z])

            # only successful trials can quit the while loop
            if query_safe_coords(redefined_coords, mol_coords, r=r):
                for index, ano in enumerate(sorted(mol)):
                    atom = mybgf.getAtom(ano)
                    atom.x = mol_coords[index][0]
                    atom.y = mol_coords[index][1]
                    atom.z = mol_coords[index][2]

                redefined_coords += mol_coords
                break
            else:
                # fail if too many trials performed
                if n_trial > 1000:
                    print(
                        "Failed to find a suitable coordinates to insert a molecule %s"
                        % mol)
                    sys.exit(0)

    # check
    print("Checking bad contacts..")
    t = scipy.spatial.KDTree(redefined_coords)
    d = t.query_pairs(r)
    if not d:
        print("There are no bad contacts with distance < %.2f" % r)
    else:
        print("Looks there're %d bad contacts" % len(d))

    # save
    mybgf.saveBGF(out_file)
    print("File saved to %s" % out_file)
    print("\n** Stats **")
    print("Total generated coordinates: %d" % n_total_trial)
    print("Number of last trials: %d" % n_trial)
    print("Done.")
Beispiel #12
0
def densityProfile(bgf_file,
                   trj_file,
                   ff_file,
                   pickle_file,
                   out_file,
                   avg_timestep,
                   silent=False):

    nu.warn(
        "LAMMPS trajectory with NPT simulations will give you the wrong result."
    )

    ### init
    timestep = 0
    l_timestep = []
    line = []
    n_header = 0
    t1 = 0
    t2 = 0
    # clock
    atominfo = dict()
    # atom data extracted from ff_file
    result = dict()
    axis = 2
    # 1: x-axis, 2: y-axis, 3: z-axis

    ### open files
    myBGF = bgf.BgfFile(bgf_file)
    myTRJ = open(trj_file)
    myTRJ.seek(0)
    myPickle = open(pickle_file)
    f_debug = open("debug.dat", 'w')
    if not silent: print("Pickling..")
    Dipole = pickle.load(myPickle)  # dipole data

    ### read residues from bgf_file
    residue = set()
    # kind of residues in BGF file
    dict_residue = dict()
    # stores residue numbers per each residue. RES1: [1, 2, ..], RES2: [6, 7, ..]
    for i in myBGF.a:
        rname = string.strip(i.rName)
        residue.add(rname)
    output = ""
    for i in residue:
        output += i + " "
        dict_residue[i] = []

    if not silent:
        print("Found " + str(len(residue)) + " residues in BGF file: " +
              str(output))
    residue = list(residue)
    #residue.append('TOTAL')

    n_residue = len(residue)  # number of residues (including total)

    ### bookkeep residue numbers for each residue
    molecules = bgftools.getMoleculeList(myBGF)
    dict_rNo2rName = dict()

    for molecule in molecules:
        # get an atom
        atom = myBGF.getAtom(molecule[0])
        atomresname = string.strip(atom.rName)
        atomresno = atom.rNo

        # check if all molecule has same residue name and numbers
        for ano in molecule:
            atom2 = myBGF.getAtom(ano)
            temp_rno = atom2.rNo
            temp_rname = string.strip(atom2.rName)
            if temp_rno != atomresno or temp_rname != atomresname:
                nu.die(
                    "Different residue name or residue number in a same molecule: "
                    + str(atom2.aNo))

        # record resid for resnames
        dict_residue[atomresname].append(atom.rNo)
        dict_rNo2rName[atom.rNo] = atomresname

    #print(dict_residue)
    #print(dict_rNo2rName)

    ### read mass from ff_file
    try:
        parse = ff_file.split(" ")
    except:
        nu.die(
            "Error occurred when reading the force field file.. Check your " +
            str(ff_file))
    else:
        if not silent:
            print("Found " + str(len(parse)) + " Cerius2 Force Fields.")

    for i in parse:
        FF = dreiding.loadFF(i)
        temp_atominfo = dreiding.loadAtomTypes(FF)
        atominfo.update(temp_atominfo)

    ### read trajectory file
    # how many steps to go?
    wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read()
    n_timestep = int(wc_trj_file.split()[0])
    print("The trajectory contains " + str(n_timestep) + " timesteps.")

    # Find header of the trajectory file
    while 1:
        templine = myTRJ.readline()
        line.append(templine.strip('\n').strip('ITEM: '))
        n_header += 1
        if "ITEM: ATOMS" in templine:
            break

    # INITIAL trajectory information
    timestep = int(line[1])
    natoms = int(line[3])
    boxsize = [
        line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0],
        line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]
    ]
    boxsize = [float(i) for i in boxsize]
    keywords = line[8].strip('ATOMS ')

    # for every shot in the trajectory file update BGF and manipulate
    dumpatom = get_line(trj_file)
    processed_step = 0

    t1 = t2 = 0
    elapsed_time = 0

    while 1:
        try:
            chunk = [next(dumpatom) for i in range(natoms + n_header)]
        except StopIteration:
            break

        timestep = int(chunk[1])
        l_timestep.append(timestep)
        natoms = int(chunk[3])
        boxsize = [
            chunk[5].split(' ')[0], chunk[5].split(' ')[1],
            chunk[6].split(' ')[0], chunk[6].split(' ')[1],
            chunk[7].split(' ')[0], chunk[7].split(' ')[1]
        ]
        boxsize = [float(i) for i in boxsize]
        boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]),
                   (boxsize[5] - boxsize[4])]
        keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ')

        ########
        if timestep < avg_timestep:
            continue
        if timestep % 10000 != 0:
            continue
        ########

        ### Show progress
        t1 = time.time()
        remaining_time = elapsed_time * (n_timestep - processed_step)
        sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) +
                         " (Elapsed time for the previous step: " +
                         "{0:4.1f}".format(elapsed_time) +
                         " seconds, Remaining time: " +
                         "{0:4.1f}".format(remaining_time) + " seconds = " +
                         "{0:4.1f} minutes".format(remaining_time / 60) + ")")
        sys.stdout.flush()

        processed_step += 1

        ### update myBGF with trajectory information ###
        natom_bgf = len(myBGF.a)  # number of atoms in BGF file

        if not natom_bgf == natoms:
            nu.die(
                "Number of atoms in trajectory file does not match with BGF file."
            )

        mode = ""
        if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords:
            mode = 'scaled'
        elif 'x' in keywords or 'y' in keywords or 'z' in keywords:
            mode = 'normal'
        elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords:
            mode = 'unwrapped'

        # actual coordinate
        coordinfo = chunk[9:]

        # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz']
        for atomline in coordinfo:
            atomcoord = atomline.split(' ')
            atom = myBGF.getAtom(int(atomcoord[0]))

            if mode == 'scaled':
                atom.x = float(atomcoord[2]) * boxsize[0]
                atom.y = float(atomcoord[3]) * boxsize[1]
                atom.z = float(atomcoord[4]) * boxsize[2]

            elif mode == 'unwrapped':
                atom.x = float(atomcoord[2])
                atom.y = float(atomcoord[3])
                atom.z = float(atomcoord[4])

            elif mode == 'normal':
                try:
                    ix_index = keywords.index('ix')
                    iy_index = keywords.index('iy')
                    iz_index = keywords.index('iz')
                except ValueError:
                    nu.warn(
                        "No image information no the trajectory file. Will be treated as unwrapped."
                    )
                    atom.x = float(atomcoord[2])
                    atom.y = float(atomcoord[3])
                    atom.z = float(atomcoord[4])
                else:
                    atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float(
                        atomcoord[2])
                    atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float(
                        atomcoord[3])
                    atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float(
                        atomcoord[4])

            try:
                for i in range(0, 3):
                    myBGF.CRYSTX[i] = boxsize[i]
            except:
                pass
                #nu.warn("Crystal information error: is this file not periodic?")

        # apply periodic condition
        myBGF = bgftools.periodicMoleculeSort(myBGF, 0)

        ### DONE for updating trj on BGF file ###

        ### find bin  ## CAUTION: only for NVT
        min = 100000
        max = -100000
        for atom in myBGF.a:
            coord = [atom.x, atom.y, atom.z]
            if coord[axis] < min:
                min = coord[axis]
            if coord[axis] > max:
                max = coord[axis]

        if boxsize[axis] > max:
            max = boxsize[axis]
        if 0 < min:
            min = 0

        bins = np.arange(math.floor(min), math.ceil(max), interval)

        #print("Bins....:")
        #print(bins)

        ### find CM of every molecule
        res_z = []
        residues = []
        for molecule in molecules:
            n_atom = len(molecule)  # number of atoms in the molecule
            residue_no = myBGF.getAtom(molecule[0]).rNo
            # residue number of the molecule
            m = bgftools.getMass(myBGF, molecule, ff_file)
            # molecule mass
            cm = [0, 0, 0]
            # center of mass
            coord = [0, 0, 0]
            # atom x, y, z
            residues.append(residue_no)  # store residue numbers of molecules

            for aNo in molecule:
                atom = myBGF.getAtom(aNo)
                coord = [atom.x, atom.y, atom.z]

                # error if residue numbers are different
                if atom.rNo != residue_no:
                    nu.die(
                        "Residue numbers in a same molecule are not consistent. Please check your BGF file."
                    )

                # error if mass is unreadable
                ffType = string.strip(atom.ffType)
                try:
                    aMass = atominfo[ffType]['MASS']
                except:
                    nu.die("Cannot read the atom type " + str(atom.ffType) +
                           " in the data file.")

                # calculate CM
                for index, i in enumerate(coord):
                    cm[index] += i * aMass

            cm = [i / m for i in cm]
            # center of mass

            res_z.append([residue_no, cm[2]])

        ### binning according to z-axis
        bin_resno = []
        for index, bin in enumerate(bins):
            temp_resno = []
            for i in res_z:
                try:
                    if bin < i[1] and bins[index + 1] > i[1]:
                        temp_resno.append(i[0])
                except:
                    continue
            bin_resno.append([bin, temp_resno])

        ### refinement for residues
        bin_avg = []
        for r in residue:
            temp_per_r = []
            for b in bin_resno:
                temp_bin_res = []
                for i in b[1]:
                    if dict_rNo2rName[i] == r:
                        temp_bin_res.append(i)
                temp_per_r.append([b[0], temp_bin_res])
            bin_avg.append([r, temp_per_r])

        ### average
        #result = [];
        result_t = dict()
        for rdata in bin_avg:
            temp_per_r = []
            for b in rdata[1]:
                temp_bin_res = []
                avg_mag = 0
                avg_angle_cos = 0

                for i in b[1]:
                    avg_mag += Dipole[timestep][rdata[0]]['ABSMU'][i]

                    mu = Dipole[timestep][rdata[0]]['MU'][i]
                    # angle btwn z-axis and mu
                    angle_cos = mu[2] / math.sqrt(mu[0]**2 + mu[1]**2 +
                                                  mu[2]**2)
                    f_debug.write(
                        str(timestep) + '\t' + str(mu) + '\t' +
                        str(Dipole[timestep][rdata[0]]['ABSMU'][i]) + '\t' +
                        str(angle_cos) + '\n')
                    avg_angle_cos += angle_cos
                if not len(b[1]) == 0: avg_mag /= len(b[1])
                if not len(b[1]) == 0: avg_angle_cos /= len(b[1])
                temp_per_r.append([b[0], avg_angle_cos, avg_mag])
            #result.append(temp_per_r)
            result_t[rdata[0]] = temp_per_r

        result[timestep] = result_t

        ### end of loop: check elapsed time
        t2 = time.time()  # time mark
        elapsed_time = t2 - t1

    ### write pickle
    o = open(out_file + ".pickle", 'w')
    pickle.dump(result, o)

    ### return

    print('')
    return 1