Source code for muesr.i_o.sampleIO

import os, warnings
import numpy as np
from muesr.core.parsers  import parse_bool
from muesr.core.ninput   import *
from muesr.core.atoms    import Atoms
from muesr.core.sample   import Sample
from muesr.core.sampleErrors   import *
from muesr.core.spg      import spacegroup_from_data
from muesr.core.magmodel import MM


have_yaml = True


try:
    from yaml import load, dump
    try:
        from yaml import CLoader as Loader, CDumper as Dumper
    except ImportError:
        from yaml import Loader, Dumper
except:
    have_yaml = False



[docs]def save_sample(sample, filename="", fileobj=None, overwrite=False): """ This function saves the sample provided in YAML format. :param sample: the sample object :param str filename: the filename used to store data. :param file fileobj: a file object used in place of filename. :param overwrite bool: if selected file should be overwritten. :return: None :rtype: None :raises: TypeError, ValueError, IsADirectoryError """ if not have_yaml: warnings.warn("Warning, YAML python package not present!\n" + "You cannot use this function") return False if not isinstance(sample, Sample): raise TypeError('Sample argument must be a Sample object.') outdict = {} outdict['Name'] = sample.name lattdict = {} try: sample._check_lattice() lattdict['Cell'] = sample._cell.get_cell().tolist() lattdict['Symbols'] = sample._cell.get_chemical_symbols() lattdict['ScaledPositions'] = sample._cell.get_scaled_positions().tolist() except CellError: pass outdict['Lattice'] = lattdict muondict = {} try: sample._check_muon() muondict['Positions'] = [x.tolist() for x in sample.muons] except MuonError: pass outdict['Muon'] = muondict magdict = {} try: sample._check_magdefs() magdict['Size'] = sample.mm.size maglist = [] for md in sample._magdefs: #not nice, should use properties maglist.append( {'format':'b-c', 'k': md.k.tolist(), 'fc': np.hstack([md.fc.real,md.fc.imag]).tolist(), 'phi': md.phi.tolist(), 'desc': md.desc } ) if not (md.lattice_params is None): maglist[-1]['lattice'] = md.lattice_params.tolist() magdict['Orders'] = maglist except MagDefError: pass outdict['MagneticOrders'] = magdict symdict = {} try: sample._check_sym() symdict['Number'] = sample.sym.no symdict['Symbol'] = sample.sym.symbol symdict['Rotations'] = sample.sym.rotations.tolist() symdict['Translations'] = sample.sym.translations.tolist() except SymmetryError: pass outdict['Symmetry'] = symdict output = dump(outdict, Dumper=Dumper) if fileobj is None: if filename == "": raise ValueError("Specify filename or provide a file object") if os.path.isfile(filename) and (not overwrite): warnings.warn('File not (over)written.', RuntimeWarning) return False with open(filename,'w') as f: f.write(output) return True else: fileobj.write(output) return True
[docs]def load_sample(filename="", fileobj=None): """ This function load a sample from a file in YAML format. :param str filename: the filename used to store data. :param file fileobj: an optional file object. If specified, this supersede the filename input. :return: a sample object :rtype: :py:class:`~Sample` object or None :raises: ValueError, FileNotFoundError, IsADirectoryError """ # fail if YAML is not available if not have_yaml: warnings.warn("Warning, YAML python package not present!") return sample = Sample() data = {} if fileobj is None: if filename == "": raise ValueError("Specify filename or File object") with open(filename,'r') as f: data = load(f, Loader=Loader) else: data = load(fileobj, Loader=Loader) if not(type(data) is dict): raise ValueError('Invalid data file. (problems with YAML?)') if data is None: raise ValueError('Invalid/empty data file. (problems with YAML?)') if 'Name' in data.keys(): sample.name = str(data['Name']) if 'Lattice' in data.keys(): l = data['Lattice'] spos = None cpos = None if 'ScaledPositions' in l.keys(): spos = np.array(l['ScaledPositions']) elif 'CartesianPositions' in l.keys(): cpos = np.array(l['CartesianPositions']) cell = None if 'Cell' in l.keys(): cell = np.array(l['Cell']) symbols = None if 'Symbols' in l.keys(): symbols = l['Symbols'] if (cell is None) or (symbols is None): warnings.warn('Cell not loaded!', RuntimeWarning) else: if not spos is None: sample.cell = Atoms(symbols = symbols, scaled_positions = spos, cell=cell, pbc=True) elif not cpos is None: sample.cell = Atoms(symbols = symbols, positions = cpos, cell=cell, pbc=True) else: warnings.warn('Cell not loaded!', RuntimeWarning) else: warnings.warn('Cell not loaded!', RuntimeWarning) if 'Muon' in data.keys(): m = data['Muon'] if 'Positions' in m: for p in m['Positions']: sample.add_muon(p) else: warnings.warn('Muon positions not loaded!', RuntimeWarning) else: warnings.warn('Muon positions not loaded!', RuntimeWarning) if 'Symmetry' in data.keys(): s = data['Symmetry'] if ('Number' in s.keys()) and \ ('Symbol' in s.keys()) and \ ('Rotations' in s.keys()) and \ ('Translations' in s.keys()): sample.sym = spacegroup_from_data(s['Number'],s['Symbol'], rotations=np.array(s['Rotations']), translations=np.array(s['Translations'])) else: warnings.warn('Symmetry not loaded.', RuntimeWarning) else: warnings.warn('Symmetry not loaded!', RuntimeWarning) if 'MagneticOrders' in data.keys(): m = data['MagneticOrders'] if len(m) > 0: msize = int(m['Size']) for mo in m['Orders']: if 'lattice' in mo.keys(): n = MM(msize, \ np.array(mo['lattice'])) else: n = MM(msize) sample.mm = n sample.mm.k = np.array(mo['k']) sample.mm.phi = np.array(mo['phi']) if 'desc' in mo.keys(): sample.mm.desc = str(mo['desc']) rfcs, ifcs = np.hsplit(np.array(mo['fc']),2) if mo['format'].lower() in ['bohr-cartesian', 'b-c']: sample.mm.fcCart=(rfcs + 1.j*ifcs) elif mo['format'].lower() in ['bohr/angstrom-lattic', 'b/a-l']: sample.mm.fcLattBMA=(rfcs + 1.j*ifcs) elif mo['format'].lower() in ['bohr-lattice','b-l']: sample.mm.fcLattBM=(rfcs + 1.j*ifcs) else: raise ValueError('Invalid Fourier Components format specifier in YAML file.') else: warnings.warn('Magnetic definitions not loaded!', RuntimeWarning) else: warnings.warn('Magnetic definitions not loaded!', RuntimeWarning) return sample
if __name__ == '__main__': unittest.main()