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