def select_cutoff(atoms): intervals = analyze_dimensionality(atoms, method='RDA', merge=False) m = intervals[0] if m.b == float("inf"): return m.a + 0.1 else: return (m.a + m.b) / 2
def select_cutoff(atoms): intervals = analyze_dimensionality(atoms, method='RDA', merge=False) dimtype = max(merge_intervals(intervals), key=lambda x: x.score).dimtype m = next(e for e in intervals if e.dimtype == dimtype) if m.b == float("inf"): return m.a + 0.1 else: return (m.a + m.b) / 2
def test_mx2(method): atoms = ase.build.mx2(formula='MoS2', kind='2H', a=3.18, thickness=3.19) atoms.cell[2, 2] = 7 atoms.set_pbc((1, 1, 1)) atoms *= 2 intervals = analyze_dimensionality(atoms, method=method) m = intervals[0] assert m.dimtype == '2D' assert intervals[0].dimtype == '2D' assert intervals[0].h == (0, 0, 2, 0) assert intervals[1].dimtype == '3D' assert intervals[1].h == (0, 0, 0, 1) assert intervals[2].dimtype == '0D' assert intervals[2].h == (24, 0, 0, 0)
def run(args, parser): files = [os.path.split(path)[1] for path in args.filenames] lmax = max([len(f) for f in files]) + 2 print('file'.ljust(lmax) + 'type score a b component counts') print('=' * lmax + '===============================================') merge = not args.no_merge # reading CIF files can produce a ton of distracting warnings with warnings.catch_warnings(): warnings.filterwarnings('ignore') for path, f in zip(args.filenames, files): for atoms in iread(path): result = analyze_dimensionality(atoms, merge=merge) if not args.full: result = result[:1] for i, entry in enumerate(result): dimtype = entry.dimtype.rjust(4) score = '{:.3f}'.format(entry.score).ljust(5) a = '{:.3f}'.format(entry.a).ljust(5) b = '{:.3f}'.format(entry.b).ljust(5) if i == 0: name = f.ljust(lmax) else: name = ' ' * lmax line = ('{}{}' + ' {}' * 4).format( name, dimtype, score, a, b, entry.h) print(line) if args.full: print()
def test_fcc(method): atoms = FaceCenteredCubic(size=(2, 2, 2), symbol='Cu', pbc=(1, 1, 1)) intervals = analyze_dimensionality(atoms, method=method) m = intervals[0] assert m.dimtype == '3D'
import ase.build from ase.lattice.cubic import FaceCenteredCubic from ase.geometry.dimensionality import analyze_dimensionality # 2D test atoms = ase.build.mx2(formula='MoS2', kind='2H', a=3.18, thickness=3.19) atoms.cell[2, 2] = 7 atoms.set_pbc((1, 1, 1)) atoms *= 2 intervals = analyze_dimensionality(atoms, method='TSA') m = intervals[0] assert m.dimtype == '2D' assert intervals[0].dimtype == '2D' assert intervals[0].h == (0, 0, 2, 0) assert intervals[1].dimtype == '3D' assert intervals[1].h == (0, 0, 0, 1) assert intervals[2].dimtype == '0D' assert intervals[2].h == (24, 0, 0, 0) intervals = analyze_dimensionality(atoms, method='RDA') m = intervals[0] assert m.dimtype == '2D' assert intervals[0].dimtype == '2D' assert intervals[0].h == (0, 0, 2, 0)
def on_click_parse(self, event): """Load the CIF, unwrap it to P1 using ASE, extract some info, and display it.""" from ase.io import read, write from ase.io.cif import write_cif from ase.geometry.dimensionality import analyze_dimensionality from ase.build import make_supercell from io import StringIO, BytesIO import re # turn "Add CIF" button primary, to remember clicking it again! self.btn_add_cif.button_type = 'primary' # assign the filename as the first guess for the COF name, which can be manually corrected self.inp_name.value = self.inp_cif.filename.split(".")[0] # read the CIF file and get useful information cif_str = self.inp_cif.value.decode() # print(self.inp_cif.param.get_param_values()) # Use for debug! atoms = read(StringIO(cif_str), format='cif') formula = atoms.get_chemical_formula() elements = [e for e in re.split(r'\d+', formula) if e] self.inp_elements.value = ",".join(elements) self.inp_modifications.value = 'none' # If the user selects the proper checkbox, rotate the cell if self.ckbox_relabel_cab.value: print("USER CHOICE: relabel cell vectors to CAB") a, b, c = atoms.cell atoms.set_cell([ c, a, b ]) if self.ckbox_relabel_bca.value: print("USER CHOICE: relabel cell vectors to BCA") a, b, c = atoms.cell atoms.set_cell([ b, c, a ]) # If the 2x replication was chosen go with that, otherwise check first if there is the need # NOTE: this is usefull because sometime the layers are close by and ASE recognizes it as a 3D frameworks, # but you want to force the choice of assuming it is a 2D COF and need 2 layers if self.ckbox_2x.value: print("USER CHOICE: force the frameworks to be 2D and duplicate 2x in C direction") self.inp_dimensionality.value = '2D' atoms = make_supercell(atoms, np.diag([1,1,2])) self.inp_modifications.value = 'replicated 2x in C direction' else: intervals = analyze_dimensionality(atoms, method='RDA') if intervals[0].dimtype == '2D': self.inp_dimensionality.value = '2D' # Check if it is correcly oriented, and extend to two layers if onyly one is present z_min_thr = 6 #if less, it is likely a single layer cell_lengths = atoms.get_cell_lengths_and_angles()[0:3] if cell_lengths[0] < z_min_thr or cell_lengths[1] < z_min_thr: # X or Y are perpendicular the layer self.inp_dimensionality.value = "ERROR: you need to rotate the axes to have the layers on XY plane." self.inp_modifications.value = "ERROR: you need to rotate the axes to have the layers on XY plane." if cell_lengths[2] < z_min_thr: # Z is perpendicular to a single layer atoms = make_supercell(atoms, np.diag([1,1,2])) self.inp_modifications.value = 'replicated 2x in C direction' else: self.inp_dimensionality.value = '3D' self.atoms = atoms import tempfile with tempfile.TemporaryFile() as handle: write(handle, atoms, format='cif') handle.seek(0) self.cif_str = handle.read() print(f"Display: {self.inp_cif.filename}") self.display(self.cif_str.decode())