Esempio n. 1
0
    def dump(self, requested_ts=[], desc=""):
        if not self._is_loaded:
            nu.warn(
                "LAMMPS trajectory file not loaded. Use load() function first."
            )
            return

        dumpatom = self._get_line(self.trj_file)

        if not desc: desc = "Dumping trajectories"
        for t in tqdm.tqdm(self.timesteps, ncols=120, desc=desc):
            tinfo = {}
            chunk = [next(dumpatom) for i in range(self._nchunk)]
            if requested_ts:
                if not t in requested_ts:
                    del (chunk)
                    continue

            coords = chunk[9:]
            for line in coords:
                atominfo = {}
                coord = line.split()
                id = int(coord[self._dump_keywords_r['id']])
                type = int(coord[self._dump_keywords_r['type']])
                atominfo['id'] = id
                atominfo['type'] = type
                for index, i in enumerate(coord[2:]):
                    atominfo[self._dump_keywords[index + 2]] = float(i)

                tinfo[id] = atominfo
            self.coord[t] = tinfo

        if len(self.coord) == len(self.timesteps):
            self._is_dumped = True  # True only if timesteps in the trajectory file are fully loaded.
Esempio n. 2
0
def getMass(myBGF, aNo_list=[], ff_file="", silent=False):
    """
def getMass(myBGF, aNo_list, ff_file):
    Returns a sum of atom masses in aNo_list.
    """

    if ff_file:
        parse = ff_file.split()
        update_mass(parse)

    total_mass = 0

    if not aNo_list:
        for atom in myBGF.a:
            aNo_list.append(atom.aNo)

    for ano in aNo_list:
        atom = myBGF.getAtom(ano)
        fftype = atom.ffType.strip()
        try:
            total_mass += float(atom_mass[fftype])
        except KeyError:
            nu.warn("No atom mass found for atomtype %s!" % fftype)
            total_mass += 0.0

    return total_mass
Esempio n. 3
0
    def load(self, force=False):
        '''
        Read timestep from trajectory file and stores it to self.timesteps
        '''
        def timesteps_remove_repeat():
            # prevent repeat
            self.timesteps = list(set(self.timesteps))
            self.timesteps.sort()

        if self._is_loaded and not force:
            #nu.warn("Trajectory file already loaded!")
            timesteps_remove_repeat()
            return

        if not self.nheader or not self.natoms:
            nu.warn("Trajectory file %s seems to be empty." % self.trj_file)
            return 0

        dumpatom = self._get_line(self.trj_file)

        while 1:
            try:
                chunk = [next(dumpatom) for i in range(self._nchunk)]
            except StopIteration:
                break

            t = int(chunk[1])
            self.timesteps.append(t)

            #if not self.silent:
            sys.stdout.write(
                '\rGetting information from LAMMPS trajectory file %s .. Fetched timestep: %d'
                % (self.trj_file, t))
            sys.stdout.flush()

            self.natoms[t] = int(chunk[3])
            self.xlo[t] = float(chunk[5].split(' ')[0])
            self.xhi[t] = float(chunk[5].split(' ')[1])
            self.ylo[t] = float(chunk[6].split(' ')[0])
            self.yhi[t] = float(chunk[6].split(' ')[1])
            self.zlo[t] = float(chunk[7].split(' ')[0])
            self.zhi[t] = float(chunk[7].split(' ')[1])

            self.pbc[t] = [
                self.xhi[t] - self.xlo[t], self.yhi[t] - self.ylo[t],
                self.zhi[t] - self.zlo[t]
            ]

        sys.stdout.write('\n')
        sys.stdout.flush()

        # save the information to pickle
        with open(self.data_file, 'wb') as f:
            timemark = time.ctime(os.path.getmtime(self.trj_file))
            pickle.dump(timemark, f)
            pickle.dump(self, f)

        timesteps_remove_repeat()

        self._is_loaded = True
Esempio n. 4
0
def check_connectivity():
    # connectivity check-up
    print("Checking nanotube connectivity..")
    for atom in mybgf.a:
        if not "C" in atom.ffType:
            continue
        if len(atom.CONECT) != 3:
            nu.warn("Defect on nanotube connection found: " +
                    str(atom.CONECTline()))
Esempio n. 5
0
def setAmineGroupInfo(bgf_file, out_file, silent=True):
    """
setAmineGroupInfo(bgf_file, silent=True):
    get a BGF file or BgfFile class object
    returns a BgfFile or 1 with  primary, secondary, and tertiary amines information corrected.

    Note that corrections WILL BE applied to the original BGF file.
    """
    n_pri = 0
    n_sec = 0
    n_ter = 0
    n_garbage = 0

    # open bgf
    if isinstance(bgf_file, bgf.BgfFile):
        myBGF = bgf_file
    else:
        if not silent: print("Reading " + bgf_file + " ..")
        myBGF = bgf.BgfFile(bgf_file)

    # get nitrogen ano lists
    l_nitrogen_ano = []
    for atom in myBGF.a:
        if "N_" in atom.ffType: l_nitrogen_ano.append(atom.aNo)

    # for every nitrogen
    for aNo in l_nitrogen_ano:
        n_carbon = 0
        connected_ano = myBGF.getAtom(aNo).CONECT
        ## for every connection
        for aNo2 in connected_ano:
            if "C_" in myBGF.getAtom(aNo2).ffType:
                n_carbon += 1

        ### no carbon: primary, 1 carbons: secondary, 2 carbons: tertiary
        if n_carbon == 1:
            myBGF.getAtom(aNo).rName = "PRI"
        elif n_carbon == 2:
            myBGF.getAtom(aNo).rName = "SEC"
        elif n_carbon == 3:
            myBGF.getAtom(aNo).rName = "TER"
        else:
            n_garbage += 1
            # what are you??

    if n_garbage != 0:
        nu.warn("Suspicious amine groups are found!")
        return 0

    # save
    if isinstance(out_file, str):
        if not silent: print("Saving information to " + out_file + " ..")
        myBGF.saveBGF(out_file)
        return getAmineGroupInfo(myBGF)
    else:
        return getAmineGroupInfo(myBGF)
Esempio n. 6
0
 def update_pbc(self, pbc):
     if len(pbc) < 3:
         nu.warn(
             "update_pbc(): Wrong assignment for the dimension of the model. Must be 3."
         )
     elif len(pbc) == 3:
         self.bgfmodel.CRYSTX = pbc + [90.0, 90.0, 90.0]
         self.pbc = pbc
     elif len(pbc) == 6:
         self.bgfmodel.CRYSTX = pbc
         self.pbc = pbc[:3]
Esempio n. 7
0
    def adjust_pbc(self, out_file=""):
        """
        adjust pbc of BGF model for infinite connectivity.
        """
        if not self.isRadiusCalc:
            nu.warn(
                "adjust_pbc: You are adjusting PBC without calculating height and radius of CNT."
            )
            self.calc_height_radius()

        # set PBC
        _dim = self.pbc

        margin = 0.0
        val = raw_input("Do you want to change the margin [N]? ")
        if "y" in val.lower():
            val = raw_input(
                "Margin from the radius to the pbc [%3.1f]? " % margin) or 0.0

            if self.orientation == "x":
                _dim = [
                    self.height + 1.0, self.radius + margin,
                    self.radius + margin
                ]
            elif self.orientation == "y":
                _dim = [
                    self.radius + margin, self.height + 1.0,
                    self.radius + margin
                ]
            elif self.orientation == "z":
                _dim = [
                    self.radius + margin, self.radius + margin,
                    self.height + 1.0
                ]

        else:
            if self.orientation == "x":
                _dim[0] = self.height + 1.0
            if self.orientation == "y":
                _dim[1] = self.height + 1.0
            if self.orientation == "z":
                _dim[2] = self.height + 1.0

        self.update_pbc(_dim)

        # move CM to boxcenter
        boxcenter = np.array(self.pbc) / 2
        cm = np.array(self.get_nt_center())
        delta = boxcenter - cm
        coord = self.coord2nparray(self.bgfmodel.a)

        self.set_coord(coord + delta)

        self.isPBCadjusted = True
Esempio n. 8
0
    def find_NT_atoms(self):
        _NT_atoms = []
        for atom in self.bgfmodel.a:
            if "NT" in atom.rName:
                _NT_atoms.append(atom)
        if _NT_atoms == []:
            nu.warn("find_NT_atoms: No atoms with residue name NT found.")

        print("find_NT_atoms(): found " + str(len(_NT_atoms)) +
              " atoms for the nanotube in BGF file.")
        return _NT_atoms
Esempio n. 9
0
 def check_connectivity(self):
     # connectivity check-up
     print("Checking nanotube connectivity..")
     try:
         for atom in self.NTatoms:
             if len(atom.CONECT) != 3:
                 raise ValueError
     except ValueError:
         nu.warn("Defect on nanotube connection found: " +
                 str(atom.CONECTline()))
     else:
         print("  No connectivity error found.")
Esempio n. 10
0
    def find_WAT_atoms(self):
        _WAT_atoms = []
        for atom in self.bgfmodel.a:
            if "WAT" in atom.rName:
                _WAT_atoms.append(atom)
        if _WAT_atoms == []:
            nu.warn("find_WAT_atoms: No atoms with residue name WAT found.")

        print("find_WAT_atoms(): found " + str(len(_WAT_atoms)) +
              " atoms for water in BGF file. (" + str(len(_WAT_atoms) / 3) +
              " molecules)")
        return _WAT_atoms
Esempio n. 11
0
    def __init__(self, fname, *args, **kwargs):

        bgf_file = ""
        if fname:
            bgf_file = fname

            if isinstance(bgf_file, bgf.BgfFile):
                self.bgfmodel = bgf_file
                self.model_filename = ""  # if the model is directly from bgf object, no filename will be assigned.
            else:
                self.bgfmodel = bgf.BgfFile(bgf_file)
                self.model_filename = bgf_file

            #
            # Determine nanotube type and atom types
            #
            self.NTatoms = self.find_NT_atoms()
            self.WATatoms = self.find_WAT_atoms()
            self.otheratoms = self.find_other_atoms()
            self.find_type()
            self.set_ff()

            #
            # Set number of atoms
            #
            self.n_allatoms = len(self.bgfmodel.a)
            self.n_nanotube = len(self.NTatoms)
            self.n_water = len(self.WATatoms)

            #
            # Properties of CNT: requires special treatment so not automatically calculated.
            #
            self.isAligned = False
            self.isRadiusCalc = False
            self.isPBCadjusted = False
            self.orientation = None
            self.radius = None
            self.height = None
            self.zhi = None
            self.zlo = None
            self.water_position_determined = False

            # model check-up: total charge
            chg = bgftools.charge(self.bgfmodel)
            if chg != 0 and abs(chg) > 1e-10:
                nu.warn("Charge is not neutral: " + str(chg))

            if self.bgfmodel.CRYSTX != []:
                self.pbc = self.bgfmodel.CRYSTX[:3]
        else:
            nu.warn("Nanotube class: An empty object created.")
Esempio n. 12
0
    def saveBGF(self, *args):
        if self._bgf == None:
            nu.warn("No BGF model converted from " + self._filename +
                    ": save failed.")
            return 0

        if len(args) != 1:
            tempfile = os.path.abspath('.') + "/" + "POSCAR.bgf"
            nu.warn("Output filename not specified. " + self._filename +
                    " will be stored at " + tempfile)
            self._bgf.saveBGF(tempfile)
        else:
            print(self._filename + " file saved to " + str(args[0]))
            self._bgf.saveBGF(args[0])
Esempio n. 13
0
    def check_branching_condition(self, monomer_id, branch_type):
        # number of branches check
        num_current_branch = len(self.neighbors(monomer_id))
        if num_current_branch > self.max_num_branch:
            nu.warn("Cannot add a monomer: branch already full.")
            return False

        # type check
        for i in self[monomer_id]:
            if monomer_id < i and self[monomer_id][i]['branch'] == branch_type:
                nu.warn("Cannot add a monomer: branch already exists.")
                return False

        return True
Esempio n. 14
0
    def calc_height_radius(self):
        """
        sets center, height, orientation, axis
        """
        if not self.isAligned:
            nu.warn(
                "calc_height_radius: Nanotube is not aligned along axes. Values may be inaccurate."
            )

        nt_coord = self.coord2nparray(self.NTatoms)

        min_x, min_y, min_z = nt_coord.min(axis=0)
        max_x, max_y, max_z = nt_coord.max(axis=0)

        range = np.array([[min_x, max_x], [min_y, max_y], [min_z, max_z]])
        diff = [max_x - min_x, max_y - min_y, max_z - min_z]

        #self.center = np.mean(nt_coord, axis=0)        # set nanotube center
        self.center = self.get_nt_center()
        # set nanotube center
        #std_c = np.std(nt_coord, axis=0)

        # height and orientation estimation: can be inaccurate
        self.height = np.max(diff)  # set nanotube height
        if np.argmax(diff) == 0:
            self.orientation = "x"
            self.axis = np.array([0, 1, 1])
            self.axismask = np.array([1, 0, 0])
        if np.argmax(diff) == 1:
            self.orientation = "y"
            self.axis = np.array([1, 0, 1])
            self.axismask = np.array([0, 1, 0])
        if np.argmax(diff) == 2:
            self.orientation = "z"
            self.axis = np.array([1, 1, 0])
            self.axismask = np.array([0, 0, 1])

        self.zlo, self.zhi = np.sum(range.T * self.axismask, axis=1)
        self.radius = np.mean(
            np.sqrt(((nt_coord * self.axis - self.center * self.axis)**2).sum(
                axis=-1)))  # set nanotube radius
        self.bgfmodel.REMARK.append("Nanotube center: %s" % self.center)
        self.bgfmodel.REMARK.append("Nanotube height: %8.3f" % self.height)
        self.bgfmodel.REMARK.append("Nanotube radius: %8.3f" % self.radius)

        print("\t* Nanotube height: " + str(self.height))
        print("\t* Nanotube radius: " + str(self.radius))

        self.isRadiusCalc = True
Esempio n. 15
0
    def add_monomer(self, monomer_id, branch_type):
        """
        branch_type:  1: left,  2: right
        """
        if not self.check_branching_condition(monomer_id, branch_type):
            nu.warn("Failed to add monomer.")
            return False

        self.num_monomer += 1
        new_monomer_id = self.num_monomer

        self.add_node(self.num_monomer)  # add a new monomer
        self.add_edge(monomer_id, new_monomer_id, branch=branch_type)

        return new_monomer_id
Esempio n. 16
0
def getCom(myBGF, ff_file='', aNo_list=[], silent=False):
    """
getCom(myBGF):
    Returns a (x, y, z) of the center of mass of the molecule.
    """

    # init
    mrx = 0
    mry = 0
    mrz = 0
    m = 0

    # if aNo_list not specified, CoM of whole molecule will be returned.
    if not aNo_list:
        for atom in myBGF.a:
            aNo_list.append(atom.aNo)

    # read atom mass from the dictionary
    for i in aNo_list:
        atom = myBGF.getAtom(i)
        fftype_key = atom.ffType.strip()
        if not fftype_key in atom_mass:
            parse = ff_file.split()
            update_mass(parse, silent=silent)

        if not fftype_key in atom_mass:
            nu.die(
                "No ffType %s found in the atom mass dictionary. You have to specify a ff_file to countinue."
                % fftype_key)

        mrx += (atom.x * float(atom_mass[fftype_key]))
        mry += (atom.y * float(atom_mass[fftype_key]))
        mrz += (atom.z * float(atom_mass[fftype_key]))
        m += float(atom_mass[fftype_key])

    try:
        x = mrx / m
        y = mry / m
        z = mrz / m
    except:
        nu.warn(
            "Total mass is zero for the molecule while calculating center of mass!"
        )
        x = 0
        y = 0
        z = 0

    return (x, y, z)
Esempio n. 17
0
    def write(self, out_file, zip=False):
        if zip:
            nu.warn(
                "Atoms will be specified in range if possible. (i.e. xx - yy)")
        else:
            nu.warn("Atom numbers will be recorded in full specification.")

        with open(out_file, 'w') as f:
            n_group = len(self.grp.keys())
            groups = self.grp.keys()
            groups.sort()

            f.write("Total Groups: %d\n" % n_group)

            for i in groups:
                atoms = sorted(self.grp[i]['atoms'])
                f.write("Group %d Atoms %d\n" % (i, len(atoms)))
                if zip:
                    f.write(''.join(
                        (('%i - %i ' % r) if len(r) == 2 else '%i' % r)
                        for r in nu.range_extract(atoms)) + "\n")
                else:
                    f.write(''.join("%d " % i for i in atoms) + "\n")

            f.write("Constraints" + "\n")
            f.write(''.join("%d " % self.grp[i]['constraints']
                            for i in groups) + "\n")

            f.write("RotationalSymmetryNumber" + "\n")
            f.write(''.join("%d " % self.grp[i]['rotsym']
                            for i in groups) + "\n")

            f.write("LinearMoleculeFlag" + "\n")
            f.write(''.join("%d " % self.grp[i]['linear']
                            for i in groups) + "\n")

            if self.grp[1]['volume']:
                f.write("GroupVolume" + "\n")
                f.write(''.join("%-16.5f " % self.grp[i]['volume']
                                for i in groups) + "\n")

            if self.grp[1]['energy']:
                f.write("GroupEnergy" + "\n")
                f.write(''.join("%-16.5f " % self.grp[i]['energy']
                                for i in groups) + "\n")
Esempio n. 18
0
def bgf2qcin(bgf_file, qchem_in_file, rem_file):

    # bgf open
    print("Reading " + bgf_file + " ..")
    myBGF = bgf.BgfFile(bgf_file)

    # output
    output = [
        "$comment\n",
        "from " + bgf_file + " at " + time.asctime(time.gmtime()) + " on " +
        os.environ["HOSTNAME"] + " by " + os.environ["USER"] + "\n", "$end\n"
    ]

    # charge and multiplicity
    output += ["\n$molecule\n"]
    chg = myBGF.charge()
    if abs(chg) < 0.000001:
        output += ["0" + "\t" + "1" + "\n"]
    else:
        nu.warn("Charge is not neutral. Charge will be written as " +
                "{0:<4.1f}".format(chg))
        output += ["{0:<4.1f}".format(chg) + "\t" + "1" + "\n"]

    # coordinates
    for atom in myBGF.a:
        output += [
            atom.ffType.split("_")[0] + "\t" +
            "{0:10.6f} {1:10.6f} {2:10.6f}".format(atom.x, atom.y, atom.z) +
            "\n"
        ]

    output += ["$end\n\n"]

    # rem
    remf = open(rem_file)
    remline = remf.readlines()
    output += remline

    # target file
    qcinf = open(qchem_in_file, 'w')
    qcinf.writelines(output)
    qcinf.close()

    print("Generated " + qchem_in_file + " . Done.")
Esempio n. 19
0
    def build_random(self):
        if self.num_target_node == 0:
            nu.warn("Number of target monomers not specified.")
            raise BuildError

        # while the polymer reach to the target nodes
        while self.num_monomer < self.num_target_node:

            # update_branch
            avail_branch = self.update_branch()
            if len(avail_branch) == 0:
                nu.warn("No more available branch sites.")
                break

            # pick one site
            pick = random.choice(avail_branch)

            # attach
            self.add_monomer(pick[0], pick[1])  # pick = [monomer_id, monomer_type]
Esempio n. 20
0
def get_density(bgf_file,
                trj_file,
                ff_file="",
                draw=False,
                out_file="",
                n=0,
                silent=False):
    mass = get_mass(bgf_file, ff_file=ff_file)  # float
    volume = get_volume(trj_file)  # dict
    density = {d: mass / volume[d] / 6.022 * 10 for d in volume.keys()}

    df = pd.DataFrame(density, index=['density'])
    df = df.T

    if n < len(df):
        df = df[-n:]
    else:
        nu.warn(
            "Not enough sample shots to calculate density with requested number of last snapshots."
        )

    density = float(df.mean())

    if not silent:
        print(df)
        print("Average density: {0:<11.5f}".format(density))

    if draw:
        import matplotlib.pyplot as plt
        plt.figure()
        df.plot()
        plt.legend(loc='best')
        fr = plt.gca()
        fr.axes.set_ylim(bottom=0)
        plt.show()

    if out_file:
        df.to_csv(out_file, sep=' ', index_label='t')
        nu.warn(
            "the character # should be added to the first of the line 1 if you want to plot the file on gnuplot."
        )

    return density
Esempio n. 21
0
    def make_bulk_infinite(self, *args):
        """
        calculate nanotube height, trim water molecules outside the box,
        and connect the two ends to make infinite nanotube.
        """
        self.make_pbc()
        self.calc_height_radius()
        self.adjust_pbc()

        # trim
        temp_list = []
        for atom in self.bgfmodel.a:
            if "O" in atom.ffType and "WAT" in atom.rName:
                if atom.z > self.pbc[2] or atom.z < 0.0:
                    temp_list.append(atom.aNo)
                    temp_list += atom.CONECT

        temp_list = list(set(temp_list))
        print("\tFound " + str(len(temp_list)) +
              " atoms for water outside of the box: will be removed.")
        del_list = []
        for i in temp_list:
            del_list.append(self.bgfmodel.a2i[i])
        self.bgfmodel.delAtoms(del_list, False)
        self.bgfmodel.renumber()
        print('\tTrim successful!')
        self.update()

        # connect
        if len(args) == 0:
            self.make_infinite()
        elif len(args) == 1:
            self.make_infinite(args[0])
        else:
            nu.warn("Wrong arguments passed.")
            return 0
Esempio n. 22
0
    def find_S_bonds(self):
        if self._bgf == None:
            nu.warn("Cannot make bonds--BGF model unassigned.")
            return 0

        aNo_pair = []
        for atom1 in self._bgf.a:
            if not "S" in atom1.ffType: continue
            x1 = np.array([atom1.x, atom1.y, atom1.z])
            for atom2 in self._bgf.a:
                if atom1 == atom2: continue
                if not "S" in atom2.ffType: continue

                x2 = np.array([atom2.x, atom2.y, atom2.z])
                dist = self.distance(x1, x2, self._latticeVectors,
                                     self._inv_latticeVectors)
                if 1.95 <= dist <= 2.15:
                    aNo_pair.append([atom1.aNo, atom2.aNo])

        for i in aNo_pair:
            self._bgf.connectAtoms(i[0], i[1])

        print(this + ": " + str(len(aNo_pair)) + " bonds are created.")
        return 1
Esempio n. 23
0
def make_periodic(*args):
    """
    MakePeriodic() returns 0
    MakePeriodic(bgf_file) returns BgfFile() object with CRYSTX {0 0 0 90 90 90}
    MakePeriodic(bgf_file, pbc) returns BgfFile() object with CRYSTX {x y z 90 90 90}
    MakePeriodic(bgf_file, CRYSTX) returns BgfFile() object with CRYSTX {x y z a b c}
    MakePeriodic(bgf_file, out_file, pbc) records out_file and returns 1
    MakePeriodic(bgf_file, out_file, CRYSTX) records out_file and returns 1
    """
    if len(args) == 0:
        nu.warn("No BGF file or instance specified.")
        return 0
    elif len(args) >= 1:
        mybgf = args[0]
        if isinstance(mybgf, str):
            mybgf = bgf.BgfFile(mybgf)

        mybgf.PERIOD = "111"
        mybgf.AXES = "ZYX"
        mybgf.SGNAME = "P 1                  1    1"
        mybgf.CELLS = [-1, 1, -1, 1, -1, 1]

        if len(args) == 1:
            mybgf.CRYSTX = [0.0, 0.0, 0.0, 90.0, 90.0, 90.0]
            nu.warn("PBC set to [0.0, 0.0, 0.0, 90.0, 90.0, 90.0]")
            return mybgf
        elif len(args) >= 2:
            if len(args[-1]) == 3:
                mybgf.CRYSTX = args[1] + [90.0, 90.0, 90.0]
            elif len(args[-1]) == 6:
                mybgf.CRYSTX = args[1]
            else:
                nu.warn("Wrong pbc provided.")
                return 0
            if len(args) == 2:
                return mybgf
            elif len(args) == 3:
                mybgf.saveBGF(args[1])
                return 1
            else:
                nu.warn("Too many parameters (>4) provided.")
                return 0
Esempio n. 24
0
    def adjust_interior_water(self, n_water):

        if not self._water_position_determined:
            nu.warn("You have to run determine_water_position() first.")
            return

        if not n_water:
            nu.warn(
                "You must specify the number of water molecules inside the Nanotube."
            )
            return

        self.bgfmodel = bgftools.renumberMolecules(self.bgfmodel, 0, False)

        waters = set()
        for atom in self.bgfmodel.a:
            if atom.chain == 'I':
                waters.add(atom.rNo)
        waters = list(waters)
        print("\tFound %d interior water molecules." % len(waters))
        if len(waters) < n_water:
            nu.warn("Too few solvent molecules to choose %d molecules." %
                    n_water)
            return

        rNos = random.sample(waters, n_water)
        print("%d water molecules are randomly chosen. Others are removed." %
              n_water)
        delist = []
        for atom in self.bgfmodel.a:
            if atom.chain == 'I' and not atom.rNo in rNos:
                delist.append(self.bgfmodel.a2i[atom.aNo])
        delist.sort()
        self.bgfmodel.delAtoms(delist, False)
        self.bgfmodel.renumber()
        self.bgfmodel = bgftools.renumberMolecules(self.bgfmodel, 0, False)
        self.update()
Esempio n. 25
0
def countWaterCNT(bgf_file, trj_file, step, doSave, silent=False):

    # 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] + ".count.dat", "w")
    myDAT.write("Time\tmin_X\tmax_X\tHeight\tRadius\tNumber\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])
    print("The trajectory contains " + str(n_timestep) + " timesteps.")

    # 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

    # 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])
        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 * (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

        ### if step is specified, then save only for that step.
        if step != 0:
            if timestep == step:
                pass
            else:
                continue
        else:
            pass

        ### 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)

        #myBGF.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".trjupdated.bgf")
        ### myBGF update complete! ###

        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

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

		# transpose for "all atoms in BGF": move COM of CNT as origin
		for atom in myBGF.a:
			atom.x -= Mx
			atom.y -= My
			atom.z -= Mz
		"""

        # 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

        # determine whether C in MtOH is in the CNT Cylinder
        if doSave:
            myBGF2 = copy.deepcopy(myBGF)
            for aNo in aNo_MtOH_C:
                atom = myBGF.getAtom(aNo)
                if CNT_orientation == "x":
                    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)
                elif CNT_orientation == "y":
                    dist = math.sqrt(atom.x**2 + atom.z**2)
                    if atom.y > min_y_CNT and atom.y < max_y_CNT and dist < radius_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)
                elif CNT_orientation == "z":
                    dist = math.sqrt(atom.x**2 + atom.y**2)
                    if atom.z > min_z_CNT and atom.z < max_z_CNT and dist < radius_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)

            myBGF2.delAtoms(aNo_MtOH_C_not_in_CNT)
            myBGF2.renumber()

        myDAT.write(str(timestep) + "\t")
        myDAT.write(str("{0:<8.3f}".format(min_x_CNT)))
        myDAT.write(str("{0:<8.3f}".format(max_x_CNT)))
        myDAT.write(str("{0:<8.3f}".format(min_y_CNT)))
        myDAT.write(str("{0:<8.3f}".format(max_y_CNT)))
        myDAT.write(str("{0:<8.3f}".format(min_z_CNT)))
        myDAT.write(str("{0:<8.3f}".format(max_z_CNT)))
        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")
        #myDAT.write(str(aNo_MtOH_C_in_CNT) + "\n")

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

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

    print('')
    return 1
Esempio n. 26
0
    def add_ions_inside_nanotube(self, n_ion):
        """
        Add Na+ and Cl- ions inside nanotube.
        """
        if not self.isRadiusCalc == True:
            nu.warn("Nanotube radius not defined. Exiting.")
            return 0

        ### find the last atom before resname WAT
        aNo_lastatom = 0
        for i in self.bgfmodel.a:
            aNo = i.aNo
            if not "WAT" in i.rName:
                if aNo > aNo_lastatom:
                    aNo_lastatom = aNo

        ### add
        n_add = 0
        while n_add < n_ion:
            x = random.uniform(0, self.pbc[0])
            y = random.uniform(0, self.pbc[1])
            z = random.uniform(0, self.pbc[2])

            xyz = np.array([x, y, z])
            r = np.sqrt(
                ((xyz * self.axis - self.center * self.axis)**2).sum(axis=-1))
            h = (xyz * self.axismask).sum()

            if r < self.radius and self.zlo < h < self.zhi:

                # Na+ ion
                atom_Na = bgf.BgfAtom()
                atom_Na.x = x
                atom_Na.y = y
                atom_Na.z = z
                atom_Na.aTag = 1  # HETATM
                atom_Na.ffType = "Na"
                atom_Na.rName = "ION"
                atom_Na.aName = "Na"
                atom_Na.charge = 1.00
                atom_Na.rNo = 0
                atom_Na.chain = "X"

                # Cl- ion
                atom_Cl = bgf.BgfAtom()
                atom_Cl.x = x + 2
                atom_Cl.y = y + 2
                atom_Cl.z = z + 2
                atom_Cl.aTag = 1  # HETATM
                atom_Cl.ffType = "Cl"
                atom_Cl.rName = "ION"
                atom_Cl.aName = "Cl"
                atom_Cl.charge = -1.00
                atom_Cl.rNo = 0
                atom_Cl.chain = "X"

                self.bgfmodel.addAtom(atom_Na,
                                      self.bgfmodel.a2i[aNo_lastatom + 1])
                self.bgfmodel.addAtom(atom_Cl,
                                      self.bgfmodel.a2i[aNo_lastatom + 2])

                n_add += 1

        self.bgfmodel.renumber()
        print("%d atoms added to the nanotube." % n_add)
Esempio n. 27
0
    def determine_water_position(self, *args):
        print("Marking water molecules whether internal or external..")
        if self.isRadiusCalc == False:
            nu.warn("Nanotube radius not calculated.")
            return 0

        tempBGF = bgf.BgfFile()
        tempBGF = bgftools.make_periodic(tempBGF, self.pbc)
        self.make_pbc(self.pbc, self.bgfmodel.CRYSTX)

        # copy Nanotube atoms
        for atom in self.NTatoms + self.otheratoms:
            atom2 = copy.deepcopy(atom)
            tempBGF.addAtom(atom2)
        tempBGF.renumber()

        # mark rNames to Oxygen atoms
        n_oxygen_inside = 0
        n_oxygen_outside = 0

        for atom in self.WATatoms:
            if "H" in atom.ffType:
                continue

            xyz = np.array([atom.x, atom.y, atom.z])
            r = np.sqrt(
                ((xyz * self.axis - self.center * self.axis)**2).sum(axis=-1))
            h = (xyz * self.axismask).sum()

            if r < self.radius:
                # inside O
                atom.chain = "I"
                n_oxygen_inside += 1
            else:
                # outside O
                atom.chain = "O"
                n_oxygen_outside += 1

        print("Interior oxygens: " + str(n_oxygen_inside) +
              ", exterior oxygens: " + str(n_oxygen_outside))

        self.n_inside_water = n_oxygen_inside
        self.n_outside_water = n_oxygen_outside

        # write water molecules
        chain = ["I", "O"]
        for cname in chain:
            print("Passing " + cname)
            for atom in self.WATatoms:
                if cname in atom.chain and "O" in atom.ffType:
                    tempBGF.addAtom(atom)  #
                    l_Hatoms = atom.CONECT
                    for index, ano in enumerate(l_Hatoms):
                        atom2 = self.bgfmodel.getAtom(ano)
                        atom2.chain = cname
                        tempBGF.addAtom(atom2)  #
        self.bgfmodel = tempBGF
        self.bgfmodel.renumber()
        self.bgfmodel = bgftools.renumberMolecules(self.bgfmodel, 0, False)
        self.update()
        print(
            "Water molecules are identified into interior(I) and exterior(O).")

        if len(args) == 0:
            nu.warn(
                "Residue name and coords for water molecules are modified.")
        elif len(args) == 1:
            print("Modified BGF file is saved to " + str(args[0]))
            self.bgfmodel.saveBGF(args[0])

        self._water_position_determined = True
Esempio n. 28
0
    def make_infinite(self, *args):
        '''
        args: filename to save
        '''
        print("CNT.py: make_infinite()")
        if len(args) > 1:
            nu.warn("make_infinite(): Too many arguments.")

        if not self.isPBCadjusted:
            nu.warn(
                "make_infinite(): You are trying to make infinite NT without adjusting PBC."
            )
            #return 0;

        print("\t* Found " + str(len(self.NTatoms)) +
              " atoms for the nanotube.")
        print("\t* Found " + str(len(self.WATatoms)) + " atoms for water.")

        if self.type == "BNT":
            self.detach_hydrogen()

        aNo_pair = []
        for atom in self.NTatoms:
            if len(atom.CONECT) == 3:
                continue

            x = np.array([atom.x, atom.y, atom.z])
            min_atom_aNo = 100000
            # placeholder
            min_atom_d = 10000.0

            for atom2 in self.NTatoms:
                if (not atom2.aNo in atom.CONECT) and len(atom2.CONECT) == 2:
                    if (atom.rName == atom2.rName) and (
                            self.type == "CNT" or atom.ffType != atom2.ffType):
                        y = np.array([atom2.x, atom2.y, atom2.z])
                        if -1.0 < ((x - y) * self.axismask).sum() < 1.0:
                            continue
                            # prevent adjacent atoms
                        d = nu.pbc_dist(x, y, self.pbc)
                        if d < min_atom_d:
                            min_atom_aNo = atom2.aNo
                            min_atom_d = d

            aNo_pair.append([atom.aNo, min_atom_aNo])

        for i in aNo_pair:
            self.bgfmodel.connectAtoms(i[0], i[1])

        self.check_connectivity()
        self.bgfmodel.renumber()

        if len(args) == 0:
            value = raw_input(
                "Do you want to save the infinite Nanotube structure to BGF file [N]? "
            )
            if "y" in value.lower():
                filename = self.model_filename[:-4] + ".infinite.bgf"
                value = raw_input("Filename to save [" + filename +
                                  "]? ") or filename
                self.bgfmodel.saveBGF(value)
        elif len(args) == 1:
            self.bgfmodel.saveBGF(args[0])
Esempio n. 29
0
 def find_type(self):
     #_NT_atoms = self.find_NT_atoms()
     if len(self.NTatoms) != 0:
         self.type = self.NTatoms[0].rName
     else:
         nu.warn("find_type(): Failed to find Nanotube types.")
Esempio n. 30
0
 def set_type(self, _type=""):
     if _type != "":
         nu.warn(
             "set_type(): You are manually assigning the nanotube type.")
         self.type = _type