Пример #1
0
 def to_xyz(self, fn):
     sites = []
     for pt in self.ref.pts:
         sites.append(Site('C', pt))
     for pt in self.var.pts:
         sites.append(Site('C', pt))
     Molecule.from_sites(sites).to('xyz', fn)
Пример #2
0
 def test_to_from_dict(self):
     d = self.disordered_site.to_dict
     site = Site.from_dict(d)
     self.assertEqual(site, self.disordered_site)
     self.assertNotEqual(site, self.ordered_site)
     d = self.propertied_site.to_dict
     site = Site.from_dict(d)
     self.assertEqual(site.magmom, 5.1)
     self.assertEqual(site.charge, 4.2)
Пример #3
0
    def unwrap_and_squeeze(pstructure: Structure):
        """
        after unwrapping, the mols can be far away from each other, this tries to translate them s.t. they stay together

        :param pstructure:
        :return:
        """
        mols, unwrap_structure, psiteblocks = PBCparser.unwrap(pstructure)
        if len(mols) > 1:
            refpoint = mols[0].center_of_mass
            refpoint = unwrap_structure.lattice.get_fractional_coords(refpoint)
            for i in range(1, len(mols)):
                varmol = mols[i]
                varpoint = varmol.center_of_mass
                varpoint = unwrap_structure.lattice.get_fractional_coords(varpoint)
                distance, fctrans = PBCparser.get_dist_and_trans(unwrap_structure.lattice, refpoint, varpoint)
                for j in range(len(psiteblocks[i])):
                    psiteblocks[i][j]._frac_coords += fctrans
            squeeze_psites = []
            squeeze_mols = []
            pblock: [PeriodicSite]
            for pblock in psiteblocks:
                squeeze_block = []
                for ps in pblock:
                    squeeze_psites.append(ps)
                    squeeze_block.append(
                        Site(ps.species_string, ps.coords, properties=ps.properties))  # do we need deepcopy?
                mol = Molecule.from_sites(squeeze_block)
                squeeze_mols.append(mol)
            squeeze_unwrap_structure = Structure.from_sites(squeeze_psites)
            return squeeze_mols, squeeze_unwrap_structure, psiteblocks


        else:
            return mols, unwrap_structure, psiteblocks
Пример #4
0
def conver2zindo(pmgmol):
    """
    this will replace elements that are not in Zindo_elements with elements in the same group
    """
    if pmgmol is None:
        return None
    sites = pmgmol.sites
    newsites = []
    for s in sites:
        if not s.species_string in Zindo_elements:
            group = Element(s.species_string).group
            samegroup_symbols = [symbol for symbol in Zindo_elements if Element(symbol).group == group]
            replacement = sorted(samegroup_symbols, key=lambda x: Element(x).number, reverse=True)[0]
            newsites.append(Site(replacement, s.coords))
        else:
            newsites.append(Site(s.species_string, s.coords))
    return Molecule.from_sites(newsites)
Пример #5
0
 def test_to_from_dict(self):
     d = self.site2.to_dict
     site = PeriodicSite.from_dict(d)
     self.assertEqual(site, self.site2)
     self.assertNotEqual(site, self.site)
     d = self.propertied_site.to_dict
     site = Site.from_dict(d)
     self.assertEqual(site.magmom, 5.1)
     self.assertEqual(site.charge, 4.2)
Пример #6
0
    def unwrap(pstructure: Structure):
        """
        unwrap the structure, extract isolated mols

        this will modify psites *in-place*, properties will be inherited and a new property
        'imol' will be written
        psite with imol=x is an element of both mols[x] and unwrap_pblock_list[x]

        this method is not supposed to modify siteid!

        :param pstructure: periodic structure obj from pymatgen
        :return: mols, unwrap_str_sorted, unwrap_pblock_list
        """

        psites = pstructure.sites
        cutoff_matrix = np.zeros((len(psites), len(psites)))
        for i in range(len(psites)):
            for j in range(i + 1, len(psites)):
                cutoff = AtomicRadius(psites[i]) + AtomicRadius(psites[j])
                cutoff *= 1.3
                cutoff_matrix[i][j] = cutoff
                cutoff_matrix[j][i] = cutoff

        if all('iasym' in s.properties for s in psites):
            sameiasym = True
            warnings.warn('if a percolating step involves hydrogens, only percolate to sites with the same iasym')
        else:
            sameiasym = False

        pindices = range(len(psites))
        visited = []
        block_list = []
        # unwrap = []
        unwrap_block_list = []
        unwrap_pblock_list = []
        while len(visited) != len(psites):
            # initialization
            unvisited = [idx for idx in pindices if idx not in visited]
            ini_idx = unvisited[0]
            block = [ini_idx]
            # unwrap.append(psites[ini_idx])
            unwrap_block = [Site(psites[ini_idx].species_string, psites[ini_idx].coords,
                                 properties=deepcopy(psites[ini_idx].properties))]
            unwrap_pblock = [psites[ini_idx]]
            pointer = 0
            while pointer != len(block):
                outside = [idx for idx in pindices if idx not in block and idx not in visited]
                for i in outside:
                    si = psites[i]
                    sj = psites[block[pointer]]
                    if sameiasym and (si.species_string == 'H' or sj.species_string == 'H'):
                        if si.properties['iasym'] != sj.properties['iasym']:
                            continue
                    distance, fctrans = PBCparser.get_dist_and_trans(pstructure.lattice,
                                                                     psites[block[pointer]].frac_coords,
                                                                     psites[i].frac_coords, )
                    fctrans = np.rint(fctrans)

                    cutoff = cutoff_matrix[block[pointer]][i]
                    if distance < cutoff:
                        block.append(i)
                        psites[i]._frac_coords += fctrans
                        # psites[i] = PeriodicSite(psites[i].species_string, psites[i].frac_coords + fctrans,
                        #                          pstructure.lattice, properties=deepcopy(psites[i].properties))
                        unwrap_block.append(
                            # Site(psites[i].species_string, psites[i].coords, properties=deepcopy(psites[i].properties))
                            Site(psites[i].species_string, psites[i].coords, properties=psites[i].properties)
                        )
                        unwrap_pblock.append(psites[i])
                visited.append(block[pointer])
                pointer += 1
            unwrap_block_list.append(unwrap_block)
            unwrap_pblock_list.append(unwrap_pblock)
            block_list.append(block)

        unwrap = []
        for i in range(len(unwrap_block_list)):
            for j in range(len(unwrap_block_list[i])):
                unwrap_block_list[i][j].properties['imol'] = i
                unwrap_pblock_list[i][j].properties['imol'] = i
                unwrap.append(unwrap_pblock_list[i][j])

        mols = [Molecule.from_sites(sites) for sites in unwrap_block_list]

        # unwrap_structure = Structure.from_sites(sorted(unwrap, key=lambda x: x.species_string))
        unwrap_structure = Structure.from_sites(unwrap, to_unit_cell=False)
        return mols, unwrap_structure, unwrap_pblock_list
Пример #7
0
    def nics_sigma_structure(self, normal_idx=0):
        """
        add hydrogen to all sites on lfr(largest fused rings), and sites that are connected to lfr with double bonds
        notice this could be different from backbone, as backbone contains other fr connected to lfr with single bond 
        (eg. BDT 3mer)


              :param normal_idx: 0, 1
        :return: a MSitelist objects
        """
        lgfr = self.lgfr

        if normal_idx == 0:
            ref_normal = lgfr[0].n1
        else:
            ref_normal = lgfr[0].n2
        normals = [r.normal_along(ref_normal) for r in lgfr]
        if any([n is None for n in normals]):
            warnings.warn(
                'W: nics_sigma_structure failed as largest_fused_ring maybe too twisted'
            )
            return None

        frsites = []
        for r in lgfr:
            for s in r.sites:
                if s not in frsites:
                    frsites.append(s)

        sigma_sites = deepcopy(self.omol.sites)

        terminated_sites_id = []
        added_hydrogens = []
        nbrmap = self.omol.get_nbrmap_based_on_siteid(1.3)

        for i in range(len(lgfr)):
            ringconf = lgfr[i]
            for s in ringconf.sites:
                nbs = nbrmap[s.properties['siteid']]
                unsaturation = _coordination_rule[s.species_string] - len(nbs)
                if unsaturation == 1 and s.properties[
                        'siteid'] not in terminated_sites_id:
                    terminated_sites_id.append(s.properties['siteid'])
                    hs = Site('H',
                              1.0 * normals[i] + s.coords,
                              properties={'siteid': -10})
                    added_hydrogens.append(hs)
                for nb in nbs:
                    nbsite = self.omol.get_site_byid(nb)
                    nb_unsaturation = _coordination_rule[
                        nbsite.species_string] - len(
                            nbrmap[nbsite.properties['siteid']])
                    if nb not in terminated_sites_id and nb_unsaturation == 1 and nbsite not in frsites and all(
                            nbsite not in ring.sites
                            for ring in self.omol.rings):
                        terminated_sites_id.append(nb)
                        hs = Site('H',
                                  1.0 * normals[i] + nbsite.coords,
                                  properties={'siteid': -10})
                        added_hydrogens.append(hs)
        return sigma_sites + added_hydrogens
Пример #8
0
def to_pymatgen_Molecule(mol):
    sites = []
    for atom, coord in zip(mol.atoms, mol.coords):
        sites.append(Site(atom, coord))
    return Molecule.from_sites(sites)
Пример #9
0
    def identify_heuristic(self):
        """
        return a dictionary, keys are

        n_close_azm_and_parallel,
        n_close_azm_and_notparallel,
        n_close_vertical_and_parallel,
        n_close_vertical_and_notparallel,
        n_parallel_and_overlap,
        n_notparallel_and_overlap, packing

        these keys are defined based on:
        close_vertical: d.oslip within [1.5, 4]
        parallel: d.oangle < 15 deg
        close_azm: d.oslip <= 1.5
        overlap: overlap > 1e-5

        variables used:
        1. is_not_identical: slip vector norm >= 1e-5
        2. is_close: minbonedist < 5.5
        3. overlap: project sites onto the plane defined by ovector of ref_mol and ref_mol.geoc,
            then get overlap of concave/convex hulls
        4. mindist2d: min distance between two hulls
        5. d.oslip: vertical slip
        6. d.oangle: angle between o_vector


        workflow:
        1. from bone config get all bone dimers, maxfold=2
        2. for each molecule (a) in the unit cell
            1. get first 27*z dimers, sorted by vslipnorm, whose ref_mol is (a)
            2. if identical or not_close, do nothing
            3. get values for the keys
            4. apply classification based on the keys
        :return:
        """
        bc_dimers, bc_dimers_transv_fcs = get_modeldimers_array(self.model_bones, self.latt, maxfold=2)

        report = OrderedDict()
        for i in range(self.z):
            n_close_azm_and_parallel = 0  # min distance between backbone proj<2, 1.5>oslip
            n_close_azm_and_notparallel = 0  # min distance between backbone proj<2, 1.5>oslip
            n_close_vertical_and_parallel = 0  # min distance between backbone proj<2, 4>oslip>1.5
            n_close_vertical_and_notparallel = 0
            n_parallel_and_overlap = 0
            n_notparallel_and_overlap = 0
            dimers_ref_i = bc_dimers[i].flatten()

            # dimers_ref_i = sorted(dimers_ref_i, key=lambda x: x.vslipnorm)[:27 * self.z]  # 3x3x3
            # 10.1039/c0ce00044b says 14 is enough
            dimers_ref_i = sorted(dimers_ref_i, key=lambda x: x.vslipnorm)[:16]

            sites = []
            bcd: ModelBoneDimer
            for bcd in dimers_ref_i:
                for pt in bcd.var.pts:
                    sites.append(Site('C', pt))
            for pt in dimers_ref_i[0].ref:
                sites.append(Site('N', pt))
            # Molecule.from_sites(sites).to('xyz', 'dccollection-{}.xyz'.format(i))

            dimers_ref_i = [d for d in dimers_ref_i if not d.is_identical and d.is_close]

            d: ModelBoneDimer
            for d in dimers_ref_i:
                # if d.is_not_identical and d.is_close:
                overlap, refboneproj, varboneproj, mindist2d = d.overlap(algo='convex')
                # print(d.minbonedist)
                # print(mindist2d)
                # debug += 1
                # d.to_xyz('dimer_{}.xyz'.format(debug))
                # overlap, refboneproj, varboneproj = d.mol_overlap()
                if 1e-5 < mindist2d < 2.5:  # exclude overlap as dist=0.0 that case
                    if 4 > d.oslip > 1.5:
                        if d.oangle < 15.0:
                            n_close_vertical_and_parallel += 1
                        else:
                            n_close_vertical_and_notparallel += 1
                    elif d.oslip <= 1.5:
                        if d.oangle < 15.0:
                            n_close_azm_and_parallel += 1
                        else:
                            n_close_azm_and_notparallel += 1
                if overlap > 1e-5:
                    if d.oangle < 15.0:
                        n_parallel_and_overlap += 1
                    else:
                        n_notparallel_and_overlap += 1

            if n_parallel_and_overlap > 2:
                packing = 'brickwork'

            elif n_close_vertical_and_parallel > 2 or n_close_azm_and_parallel > 2 or n_close_vertical_and_parallel + n_close_azm_and_parallel + n_parallel_and_overlap > 2:
                packing = 'edge_brickwork'

            elif n_parallel_and_overlap == 2:
                packing = 'slipped_stack'

            elif n_close_vertical_and_parallel == 2 or n_parallel_and_overlap + n_close_vertical_and_parallel + n_close_azm_and_parallel == 2:
                packing = 'edge_slipped_stack'

            elif n_notparallel_and_overlap >= 1:
                packing = 'herringbone'

            elif n_close_vertical_and_notparallel >= 1 or n_close_azm_and_notparallel >= 1:
                packing = 'edge_herringbone'

            elif n_parallel_and_overlap == 1 or n_close_vertical_and_parallel == 1:
                packing = 'dimerized'

            elif n_notparallel_and_overlap == n_parallel_and_overlap == n_close_azm_and_notparallel == n_close_azm_and_parallel == n_close_vertical_and_parallel == n_close_vertical_and_notparallel == 0:
                packing = 'sparse'

            else:
                packing = 'other'

            report[i] = OrderedDict(
                n_close_azm_and_parallel=n_close_azm_and_parallel,  # min distance between backbone proj<2, 1.5>oslip
                n_close_azm_and_notparallel=n_close_azm_and_notparallel,
                # min distance between backbone proj<2, 1.5>oslip
                n_close_vertical_and_parallel=n_close_vertical_and_parallel,
                # min distance between backbone proj<2, 4>oslip>1.5
                n_close_vertical_and_notparallel=n_close_vertical_and_notparallel,
                n_parallel_and_overlap=n_parallel_and_overlap,
                n_notparallel_and_overlap=n_notparallel_and_overlap,
                packing=packing,
            )

        return report