Exemplo n.º 1
0
    def x2w(self, x):
        """
        Convert molar fraction of carbon to weight fraction
        Method only available if the chemical potentials are
        loaded from a Thermo-Calc generated file
        """
        from periodictable import elements

        if isinstance(x, list):
            x = np.array(x)
        # select X(*) like columns
        xcols = [
            c for c in self.chempot.columns
            if fnmatch(c, 'X(*)') and c != 'X(Z)'
        ]
        # created DataFrame with selected columns and rename them accordingly
        dfx = self.chempot[xcols].rename(mapper=lambda c: c[2:-1].title(),
                                         axis='columns')
        # get molar mass
        M = np.array([elements.symbol(el).mass for el in dfx.columns])
        # interpolate composition
        xcomp = interp1d(dfx['C'].values, dfx.values.T, axis=1)(x)
        if xcomp.ndim == 1:
            sumxcomp = float(np.sum(xcomp.T * M))
        else:
            sumxcomp = np.sum(xcomp.T * M, axis=1)

        return x * elements.symbol('C').mass / sumxcomp
Exemplo n.º 2
0
    def __init__(self, majorelement, x=None, w=None):
        if x is None:
            self.x = dict()
        else:
            self.x = x

        if w is None:
            self.w = dict()
        else:
            self.w = w

        self.major = majorelement  # element that's accounted by balance
        self.M = None  # average molar mass of the alloy

        # If major element passed in either x or w, then remove from respective dictionaries
        if self.major in self.x:
            print(
                'Major element composition should not be provided and will be ignored.'
            )
            self.x.pop(self.major)

        if self.major in self.w:
            print(
                'Major element composition should not be provided and will be ignored.'
            )
            self.w.pop(self.major)

        # Load molar masses of alloy elements
        self.Mi = {self.major: elements.symbol(self.major).mass}
        self.Mi.update({el: elements.symbol(el).mass for el in self.x.keys()})
        self.Mi.update({el: elements.symbol(el).mass for el in self.w.keys()})
Exemplo n.º 3
0
def generate_form_factors(N_atoms_uc, atom_list, hkl_interval):
    # Form Factor
    eval_pnts = np.linspace(hkl_interval[0],hkl_interval[1],hkl_interval[2])
    ff_list = []
    for i in range(N_atoms_uc):
        try:
            elSym = atom_list[i].label
            elSym = elements.symbol(elSym)
            elMass = atom_list[i].massNum
            if elMass == None: #The mass number will now generally be None -Tom 1/28/11
                el = elSym
            else:
                el = elSym[elMass]
            #print el
            val = atom_list[i].valence
            if val != None:
                Mq = el.magnetic_ff[val].M_Q(eval_pnts)
            else:
                Mq = el.magnetic_ff[0].M_Q(eval_pnts)
        except:
            Mq = np.zeros(len(eval_pnts))
        #Test to see how things look without ff
        #Mq = np.ones(len(eval_pnts))

        ff_list = Mq
#    fake = np.ones(len(kaprange))
    return np.array(ff_list)
Exemplo n.º 4
0
def generate_form_factors(N_atoms_uc, atom_list, hkl_interval):
    # Form Factor
    eval_pnts = np.linspace(hkl_interval[0],hkl_interval[1],hkl_interval[2])
    ff_list = []
    for i in range(N_atoms_uc):
        try:
            elSym = atom_list[i].label
            elSym = elements.symbol(elSym)
            elMass = atom_list[i].massNum
            if elMass == None: #The mass number will now generally be None -Tom 1/28/11
                el = elSym
            else:
                el = elSym[elMass]
            print el
            val = atom_list[i].valence
            if val != None:
                Mq = el.magnetic_ff[val].M_Q(eval_pnts)
            else:
                Mq = el.magnetic_ff[0].M_Q(eval_pnts)
        except:
            Mq = np.zeros(len(eval_pnts))
        #Test to see how things look without ff
        #Mq = np.ones(len(eval_pnts))
        
        ff_list = Mq
#    fake = np.ones(len(kaprange))
    return np.array(ff_list)
Exemplo n.º 5
0
    def convert_composition(comp, to_mole):
        """Convert from mole to mass fraction

        Will convert to fractions (i.e., not percentages)

        Input:
            comp - dict, key is element symbol, value is amount
            to_mole - boolean, whether to convert to mole fraction. Note that
                this method assumes that the method always needs to be converted
        """

        # Convert to other units
        total_weight = 0.0
        for e,a in comp.iteritems():
            weight = a / pt_elements.symbol(e).mass if to_mole else a * pt_elements.symbol(e).mass
            comp[e] = weight
            total_weight += weight
        for e,a in comp.iteritems():
            comp[e] = a / total_weight
Exemplo n.º 6
0
 def F(self, HKL):
     F = 0
     q = self.q(HKL)
     Q = np.sqrt(q.dot(q))
     for i in xrange(len(self.basis)):
         f = elements.symbol(self.basis[i][0]).xray.f0(Q)
         F += (f * np.exp(-2.j*np.pi * (HKL[0] * self.basis[i][1] +
                                        HKL[1] * self.basis[i][2] +
                                        HKL[2] * self.basis[i][3])))
     return F
Exemplo n.º 7
0
def _getMolecularGraph(molecule):
    """
    Generate a graph from the topology of molecule

    The graph nodes represent atoms and the graph edges represent bonds. Also, the graph nodes store element
    information.
    """

    graph = nx.Graph()
    for i, element in enumerate(molecule.element):
        graph.add_node(i, element=element, number=elements.symbol(element).number)
    graph.add_edges_from(molecule.bonds)

    return graph
Exemplo n.º 8
0
    def F(self, HKL, rod_int=False, rod_alpha=0.1):
        F = 0
        q = self.q(HKL)
        Q = np.sqrt(q.dot(q))
        for i in range(len(self.basis)):
            f = elements.symbol(self.basis[i][0]).xray.f0(Q)
            F += (f * np.exp(-2.j*np.pi * (HKL[0] * self.basis[i][1] +
                                           HKL[1] * self.basis[i][2] +
                                           HKL[2] * self.basis[i][3])))
        if(rod_int):
            qz111 = self.q([1,1,1])[2]
            return F/(1.-np.exp(-2.j*np.pi*HKL.dot([1,1,1])+rod_alpha))
            #return F/(1.-np.exp(-2.j*np.pi*q[2]/qz111))

        return F
Exemplo n.º 9
0
def _getMolecularGraph(molecule):
    """
    Generate a graph from the topology of molecule

    The graph nodes represent atoms and the graph edges represent bonds. Also, the graph nodes store element
    information.
    """

    graph = nx.Graph()
    for i, element in enumerate(molecule.element):
        graph.add_node(i,
                       element=element,
                       number=elements.symbol(element.capitalize()).number)
    graph.add_edges_from(molecule.bonds)

    return graph
Exemplo n.º 10
0
    def F_many(self, HKLs, qs=None):
        if (qs.any() == None):
            qs = self.q_many(HKLs)
        Q = np.sqrt(np.sum(qs * qs, axis=1))
        f_dict = dict()
        for el in self.unique_elements:
            f_dict[el] = elements.symbol(el).xray.f0(Q)
        f = []
        for el in self.basis_el:
            f.append(f_dict[el])
        f = np.array(f)

        H, x = np.meshgrid(HKLs.T[0], self.basis_xyz.T[0])
        K, y = np.meshgrid(HKLs.T[1], self.basis_xyz.T[1])
        L, z = np.meshgrid(HKLs.T[2], self.basis_xyz.T[2])

        return np.sum(f * np.exp(-2.j * np.pi * (H * x + K * y + L * z)),
                      axis=0)
Exemplo n.º 11
0
def solar_abundance(element):
    '''For a given atomic number, return solar abundance from Asplund et al. 2009.

    Input
    -----
    element : str
      The name of an element

    Output
    ------
    index : int
      The atomic number of the element
    abundance : float
      The solar abundance of the atom in dex
    '''
    abundance = solar.get(element, None)
    if abundance is None:
        return None, None
    index = elements.symbol(element).number
    return index, abundance
Exemplo n.º 12
0
def get_atomic_number_symbol(Z=None, symbol=None):
    """This function returns a tuple of matching arrays of atomic numbers
    (Z) and chemical symbols (symbol).

    :param Z: atomic numbers
    :type Z: int, array like object of int's
    :param symbol: chemical symbols
    :type symbol: str, array like object of str
    :return: arrays of atomic numbers and chemical symbols
    :rtype: tuple of :class:`numpy.ndarray`

    Note: If both Z and symbol are provided the symbol will win out and
    change the Z to match.

    """
    import numpy as np
    from periodictable import elements

    if isinstance(Z, int):
        Z = [Z]

    if isinstance(symbol, str):
        symbol = [symbol]

    if np.count_nonzero(symbol) == 0:
        if np.count_nonzero(Z) == 0:
            raise ValueError("Need to provide list of either Z's or symbols.")
        else:
            Z = np.asarray(Z)
            length = len(Z)
            symbol = np.empty(length, dtype='<U2')
            for i in range(length):
                symbol[i] = elements[Z[i]].symbol
    else:
        symbol = np.asarray(symbol)
        length = len(symbol)
        Z = np.empty(length, dtype=np.int64)
        for i in range(length):
            symbol[i] = symbol[i].capitalize()
            Z[i] = elements.symbol(symbol[i]).number
    return (Z, symbol)
Exemplo n.º 13
0
def w2x(wC, w={}, x={}, y=dict(Fe=1.), fullcomp=False):
    """
    Calculates the mole fraction of carbon from its weight fraction.

    Parameters
    ----------
    wC : float
        weight fraction of C
    w : dict, optional
        known full composition of the alloy in weight fraction
    x : dict, optional
        known full composition of the alloy in mole fraction
    y : dict, optional
        site fraction of the substitutional elements
    fullcomp : bool, optional
        if True, returns a dict with full composition.
        if False, returns only C composition
    """
    if w:
        w = {k: v*(1-wC)/(1-w['C']) for k, v in w.items()}
        w['C'] = wC
    elif x:
        w = x2w(0, x=x, fullcomp=True)
        w = {k: v*(1-wC) for k, v in w.items()}
        w['C'] = wC
    else:
        w = x2w(0, y=y, fullcomp=True)
        w = {k: v*(1-wC) for k, v in w.items()}
        w['C'] = wC

    x = {k: v/elements.symbol(k).mass for k, v in w.items()}
    sumx = sum(x.values())
    x = {k: v/sumx for k, v in x.items()}

    if fullcomp:
        return x
    else:
        return x['C']
Exemplo n.º 14
0
def x2w(xC, x={}, w={}, y=dict(Fe=1.), fullcomp=False):
    """
    Calculates the weight fraction of carbon from its mole fraction.

    Parameters
    ----------
    xC : float
        mole fraction of C
    x : dict, optional
        known full composition of the alloy in mole fraction
    w : dict, optional
        known full composition of the alloy in weight fraction
    y : dict, optional
        site fraction of the substitutional elements
    fullcomp : bool, optional
        if True, returns a dict with full composition.
        if False, returns only C composition
    """
    if x:
        x = {k: v*(1-xC)/(1-x['C']) for k, v in x.items()}
        x['C'] = xC
    elif w:
        x = w2x(0, w=w, fullcomp=True)
        x = {k: v*(1-xC) for k, v in x.items()}
        x['C'] = xC
    else:
        x = {k: v*(1-xC) for k, v in y.items()}
        x['C'] = xC

    w = {k: v*elements.symbol(k).mass for k, v in x.items()}
    sumw = sum(w.values())
    w = {k: v/sumw for k, v in w.items()}

    if fullcomp:
        return w
    else:
        return w['C']
Exemplo n.º 15
0
    def from_cif(filename,
                 HKL_normal=[0, 0, 1],
                 HKL_para_x=[1, 0, 0],
                 offset_angle=0,
                 E_keV=22.5,
                 override_a=None,
                 override_b=None,
                 override_c=None,
                 override_alpha=None,
                 override_beta=None,
                 override_gamma=None):
        # print(filename)
        cf = CifFile.ReadCif(open(filename))
        data = cf.first_block()

        # Load unit cell parameters
        a = override_a if override_a else float(
            strip_brackets(data['_cell_length_a']))
        b = override_b if override_b else float(
            strip_brackets(data['_cell_length_b']))
        c = override_c if override_c else float(
            strip_brackets(data['_cell_length_c']))
        alpha = override_alpha if override_alpha else float(
            strip_brackets(data['_cell_angle_alpha']))
        beta = override_beta if override_beta else float(
            strip_brackets(data['_cell_angle_beta']))
        gamma = override_gamma if override_gamma else float(
            strip_brackets(data['_cell_angle_gamma']))

        #a = float(strip_brackets(data['_cell_length_a']))
        #b = float(strip_brackets(data['_cell_length_b']))
        #c = float(strip_brackets(data['_cell_length_c']))
        #alpha = float(strip_brackets(data['_cell_angle_alpha']))
        #beta = float(strip_brackets(data['_cell_angle_beta']))
        #gamma = float(strip_brackets(data['_cell_angle_gamma']))

        # Create the basis.
        # In the CIF file, the coordinates of the basis atoms are given
        # in fractions of the unit cell vectors a, b, c.

        _basis = []
        atom_sites = data.GetLoop('_atom_site_label')
        elnames = atom_sites['_atom_site_label']
        fractxs = atom_sites['_atom_site_fract_x']
        fractys = atom_sites['_atom_site_fract_y']
        fractzs = atom_sites['_atom_site_fract_z']

        for i in range(len(elnames)):
            # In some files, the atoms have names like 'Co1', 'O1', 'O2',
            # and we need to strip the numbers to get the element name.
            elname = str.strip(str(elnames[i]), '123456789')
            el = elements.symbol(elname)
            max_E = 30
            f1, f2 = el.xray.scattering_factors(energy=min(max_E, E_keV))
            x = float(strip_brackets(fractxs[i]))
            y = float(strip_brackets(fractys[i]))
            z = float(strip_brackets(fractzs[i]))
            #TODO: test
            #_basis.append([f1 + 1.j * f2, np.array([x, y, z, 1])])
            _basis.append([elname, np.array([x, y, z, 1])])
        # The basis given by the atom_site_label entries is not the full
        # content of the unit cell.
        # We can create the full unit cell by applying the symmetry operations
        # defined by the crystal's space group to the atoms.
        # Luckily, we do not need to do this by ourselves, because all the
        # symmetry-equivalent positions are already given in the CIF file
        # under symmetry_equiv_pos_as_xyz.
        # "Copying" all atoms in atom_site_label to all symmetry-equivalent
        # positions will give the full unit cell.

        basis = []
        sym_pos_arr = data.GetLoop('_symmetry_equiv_pos_as_xyz')
        for sym_pos in sym_pos_arr:
            # Some CIF files use the format
            # x,y,z
            # Others use the format:
            # 1 'x, y, z'
            # This approach will handle both cases:
            symp = sym_pos[len(sym_pos) - 1]

            # We will create a translation matrix that we can apply to an
            # atom to move it to this symmetry-equivalent position
            toks = symp.split(',')
            pos = ['x', 'y', 'z']
            translation_matrix = np.zeros((4, 4))
            translation_matrix[3, 3] = 1  # [row, column]

            # Loop through the three coordinates
            # of the symmetry-equivalent position
            for i in range(len(toks)):
                # Moves by x, y, or z are expressed by an suitable entry
                # in the translation matrix. The summand is then deleted from
                # the string.
                for j in range(len(pos)):
                    if (('-%s' % (pos[j])) in toks[i]):
                        translation_matrix[i, j] = -1
                        toks[i] = toks[i].replace('-%s' % (pos[j]), '')
                        # break
                    elif (('+%s' % (pos[j])) in toks[i]):
                        translation_matrix[i, j] = 1
                        toks[i] = toks[i].replace('+%s' % (pos[j]), '')
                        # break
                    elif (('%s' % (pos[j])) in toks[i]):
                        translation_matrix[i, j] = 1
                        toks[i] = toks[i].replace('%s' % (pos[j]), '')
                        # break
                # Now, the string should only consist of a fractional
                # coordinate move along the respective axis,
                # which we also enter into the translation matrix
                translation_matrix[i, 3] = float(eval(toks[i] + '.0'))

            if (False):
                print(translation_matrix)

            # Copy all atoms using the translation matrix.
            # Atoms landing outside the unit cell will be moved inside,
            # and duplicates will be removed.
            for atom in _basis:
                x, y, z, w = translation_matrix.dot(atom[1])
                while (x < 0):
                    x += 1
                while (x >= 1):
                    x -= 1
                while (y < 0):
                    y += 1
                while (y >= 1):
                    y -= 1
                while (z < 0):
                    z += 1
                while (z >= 1):
                    z -= 1
                add_atom = True
                for i in range(len(basis)):
                    if ((basis[i][0] == atom[0])
                            and (np.round(basis[i][1], 10) == np.round(x, 10))
                            and (np.round(basis[i][2], 10) == np.round(y, 10))
                            and
                        (np.round(basis[i][3], 10) == np.round(z, 10))):
                        add_atom = False
                        break
                if (add_atom):
                    basis.append([atom[0], x, y, z])

        if (False):
            print('basis:', len(basis))
            print(basis)

        return lattice(a,
                       b,
                       c,
                       alpha,
                       beta,
                       gamma,
                       basis,
                       HKL_normal,
                       HKL_para_x,
                       offset_angle,
                       E_keV=E_keV)
    assert str(O[18])=='18-O'
    try:
        Fe[12]
    except KeyError,msg:
        assert msg.args[0] == '12 is not an isotope of Fe'

    # Check that "for el in elements" works and for iso in el works
    els = tuple(el for el in elements)
    assert els[0].number == 0
    assert els[1].number == 1
    isotopes = tuple(iso for iso in O)
    assert isotopes[0].isotope == 12  # 12 is the first oxygen isotope listed

    # Check that table lookup works and fails appropriately
    Fe.add_isotope(56)
    assert elements.symbol('Fe') == Fe
    assert elements.name('iron') == Fe
    assert elements.isotope('Fe') == Fe
    assert elements.isotope('56-Fe') == Fe[56]
    assert elements.isotope('D') == H[2]
    try:
        elements.symbol('Qu')
    except ValueError,msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.name('Qu')
    except ValueError,msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.isotope('Qu')
    except ValueError,msg:
Exemplo n.º 17
0
def cgi_call():
    form = cgi.FieldStorage()
    #print >>sys.stderr, form
    #print >>sys.stderr, "sample",form.getfirst('sample')
    #print >>sys.stderr, "mass",form.getfirst('mass')
    
    # Parse inputs
    errors = {};
    calculate = form.getfirst('calculate','all')
    if calculate not in ('scattering','activation','all'):
        errors['calculate'] = "calculate should be one of 'scattering', 'activation' or 'all'"
    try: chem = formula(form.getfirst('sample'))
    except: errors['sample'] = error()
    try: fluence = float(form.getfirst('flux',100000))
    except: errors['flux'] = error()
    try: fast_ratio = float(form.getfirst('fast','0'))
    except: errors['fast'] = error()
    try: Cd_ratio = float(form.getfirst('Cd','0'))
    except: errors['Cd'] = error()
    try: exposure = parse_hours(form.getfirst('exposure','1'))
    except: errors['exposure'] = error()
    try: 
        mass_str = form.getfirst('mass','1')
        if mass_str.endswith('kg'):
           mass = 1000*float(mass_str[:-2])
        elif mass_str.endswith('mg'):
           mass = 0.001*float(mass_str[:-2])
        elif mass_str.endswith('ug'):
           mass = 1e-6*float(mass_str[:-2])
        elif mass_str.endswith('g'):
           mass = float(mass_str[:-1])
        else:
           mass = float(mass_str)
    except: errors['mass'] = error()
    try: density_type,density_value = parse_density(form.getfirst('density','0'))
    except: errors['density'] = error()
    try: 
        #print >>sys.stderr,form.getlist('rest[]')
        rest_times = [parse_rest(v) for v in form.getlist('rest[]')]
        if not rest_times: rest_times = [0,1,24,360]
    except: errors['rest'] = error()
    try: decay_level = float(form.getfirst('decay','0.001'))
    except: errors['decay'] = error()
    try: thickness = float(form.getfirst('thickness', '1'))
    except: errors['thickness'] = error()
    try:
        wavelength_str = form.getfirst('wavelength','1').strip()
        if wavelength_str.endswith('meV'):
             wavelength = nsf.neutron_wavelength(float(wavelength_str[:-3]))
        elif wavelength_str.endswith('m/s'):
             wavelength = nsf.neutron_wavelength_from_velocity(float(wavelength_str[:-3]))
        elif wavelength_str.endswith('Ang'):
             wavelength = float(wavelength_str[:-3])
        else:
             wavelength = float(wavelength_str)
        #print >>sys.stderr,wavelength_str
    except: errors['wavelength'] = error()
    try:
        xray_source = form.getfirst('xray','Cu Ka').strip()
        if xray_source.endswith('Ka'):
            xray_wavelength = elements.symbol(xray_source[:-2].strip()).K_alpha
        elif xray_source.endswith('keV'):
            xray_wavelength = xsf.xray_wavelength(float(xray_source[:-3]))
        elif xray_source.endswith('Ang'):
            xray_wavelength = float(xray_source[:-3])
        elif xray_source[0].isalpha():
            xray_wavelength = elements.symbol(xray_source).K_alpha
        else:
            xray_wavelength = float(xray_source)
        #print >>sys.stderr,"xray",xray_source,xray_wavelength
    except: errors['xray'] = error()
    try:
        abundance_source = form.getfirst('abundance','IAEA')
        if abundance_source == "NIST":
            abundance = activation.NIST2001_isotopic_abundance
        elif abundance_source == "IAEA":
            abundance = activation.IAEA1987_isotopic_abundance
        else:
            raise ValueError("abundance should be NIST or IAEA")
    except: errors['abundance'] = error()
        

    if errors: return {'success':False, 'error':'invalid request', 'detail':errors}

    # Fill in defaults
    #print >>sys.stderr,density_type,density_value,chem.density
    if density_type == 'default' or density_value == 0:
        # default to a density of 1
        if chem.density is None: chem.density = 1
    elif density_type == 'volume':
        chem.density = chem.molecular_mass/density_value
    elif density_type == 'natural':
        # if density is given, assume it is for natural abundance
        chem.natural_density = density_value
    elif density_type == 'isotope':
        chem.density = density_value
    else:
        raise ValueError("unknown density type %r"%density_type)

    result = {'success': True}
    result['sample'] = {
            'formula': str(chem),
            'mass': mass,
            'density': chem.density,
            'thickness': thickness,
            'natural_density': chem.natural_density,
        }
        
    # Run calculations
    if calculate in ('activation', 'all'):
      try:
        env = activation.ActivationEnvironment(fluence=fluence,fast_ratio=fast_ratio, Cd_ratio=Cd_ratio)
        sample = activation.Sample(chem, mass=mass)
        sample.calculate_activation(env,exposure=exposure,rest_times=rest_times,abundance=abundance)
        decay_time = sample.decay_time(decay_level)
        total = [0]*len(sample.rest_times)
        rows = []
        for el,activity_el in activation.sorted_activity(sample.activity.items()):
            total = [t+a for t,a in zip(total,activity_el)]
            rows.append({'isotope':el.isotope,'reaction':el.reaction,'product':el.daughter,
                         'halflife':el.Thalf_str,'comments':el.comments,'levels':activity_el})
        result['activation'] = {
            'flux': fluence,
            'fast': fast_ratio,
            'Cd': Cd_ratio,
            'exposure': exposure,
            'rest': rest_times,
            'activity': rows, 
            'total': total,
            'decay_level': decay_level,
            'decay_time': decay_time,
        }
        #print >>sys.stderr,result
      except:
        result['activation'] = {"error": error()}
        
    #nsf_sears.replace_neutron_data()
    if calculate in ('scattering', 'all'):
      try: 
        sld,xs,penetration = neutron_scattering(chem, wavelength=wavelength)
        result['scattering'] = {
            'neutron': {
                'wavelength': wavelength,
                'energy': nsf.neutron_energy(wavelength),
                'velocity': nsf.VELOCITY_FACTOR/wavelength,
            },
            'xs': {'coh': xs[0], 'abs': xs[1], 'incoh': xs[2]},
            'sld': {'real': sld[0], 'imag': sld[1], 'incoh': sld[2]},
            'penetration': penetration,
            'transmission': 100*exp(-thickness/penetration),
        }
        
      except:
        missing = [str(el) for el in chem.atoms if not el.neutron.has_sld()]
        if any(missing):
            msg = "missing neutron cross sections for "+", ".join(missing)
        else:
            msg = error()
        result['scattering'] = {'error': msg }


      try: 
        xsld = xray_sld(chem, wavelength=xray_wavelength) 
        result['xray_scattering'] = {
            'xray': {
                'wavelength': xray_wavelength,
                'energy': xsf.xray_energy(xray_wavelength),
            },
            'sld': {'real': xsld[0], 'imag': xsld[1]},
        }
      except: 
        result['xray_scattering'] = {'error': error()}

    return result
Exemplo n.º 18
0
    def __init__(self,
                 a,
                 b,
                 c,
                 alpha=90,
                 beta=90,
                 gamma=90,
                 basis=[0, 0, 0],
                 HKL_normal=[0, 0, 1],
                 HKL_para_x=[1, 0, 0],
                 offset_angle=0,
                 energy_keV=22.5):
        self.a = a
        self.b = b
        self.c = c
        self.alpha = np.deg2rad(alpha)
        self.beta = np.deg2rad(beta)
        self.gamma = np.deg2rad(gamma)
        self.energy_keV = energy_keV
        self.k0 = id03.get_K_0(energy_keV)
        self.basis = basis  # list of [Atomic_form_factor, x, y, z]
        for i in xrange(len(self.basis)):
            if (isinstance(self.basis[i][0], basestring)):
                f1, f2 = elements.symbol(
                    self.basis[i][0]).xray.scattering_factors(
                        energy=energy_keV)
                self.basis[i][0] = f1 + 1.j * f2
        self.HKL_normal = HKL_normal
        self.HKL_para_x = HKL_para_x

        # calculate real space unit cell vectors
        self.A1 = np.array([self.a, 0, 0])
        self.A2 = np.array(
            [self.b * np.cos(self.gamma), b * np.sin(self.gamma), 0])
        A31 = self.c * np.cos(self.alpha)
        A32 = self.c / np.sin(self.gamma) * (
            np.cos(self.beta) - np.cos(self.gamma) * np.cos(self.alpha))
        A33 = np.sqrt(self.c**2 - A31**2 - A32**2)
        self.A3 = np.array([A31, A32, A33])
        self.RealTM = np.array([[self.A1[0], self.A2[0], self.A3[0]],
                                [self.A1[1], self.A2[1], self.A3[1]],
                                [self.A1[2], self.A2[2], self.A3[2]]])

        #TODO: remove
        if (0):
            from mayavi import mlab
            try:
                engine = mayavi.engine
            except NameError:
                from mayavi.api import Engine
                engine = Engine()
                engine.start()
            if len(engine.scenes) == 0:
                engine.new_scene(size=(600, 800))
            scene = engine.scenes[0]
            fig = mlab.gcf(engine)
            mlab.figure(figure=fig,
                        bgcolor=(1.0, 1.0, 1.0),
                        fgcolor=(0.0, 0.0, 0.0),
                        engine=engine)

            hkls = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1],
                    [1, 0, 1], [0, 1, 1], [1, 1, 1]]
            lines = [[0, 1], [0, 2], [0, 4], [5, 1], [5, 4], [5, 7], [3, 1],
                     [3, 2], [3, 7], [6, 4], [6, 2], [6, 7]]
            for line in lines:
                xyz1 = self.RealTM.dot(hkls[line[0]])
                xyz2 = self.RealTM.dot(hkls[line[1]])

                mlab.plot3d([xyz1[0], xyz2[0]], [xyz1[1], xyz2[1]],
                            [xyz1[2], xyz2[2]])

            mlab.show()

        # calculate reciprocal space unit cell vectors
        self._V_real = self.A1.dot(np.cross(self.A2, self.A3))
        self.B1 = 2 * np.pi * np.cross(self.A2, self.A3) / self._V_real
        self.B2 = 2 * np.pi * np.cross(self.A3, self.A1) / self._V_real
        self.B3 = 2 * np.pi * np.cross(self.A1, self.A2) / self._V_real
        self.RecTM = np.array([[self.B1[0], self.B2[0], self.B3[0]],
                               [self.B1[1], self.B2[1], self.B3[1]],
                               [self.B1[2], self.B2[2], self.B3[2]]])

        self._V_rec = self.B1.dot(np.cross(self.B2, self.B3))

        # align surface normal to z axis
        q_normal = self.q(HKL_normal)
        q_normal /= np.sqrt(q_normal.dot(q_normal))
        z = np.array([0, 0, 1])
        v = np.cross(q_normal, z)
        I = np.zeros((3, 3))
        I[0, 0] = 1
        I[1, 1] = 1
        I[2, 2] = 1
        R = np.zeros((3, 3))
        if (v[0] == 0 and v[1] == 0 and v[2] == 0):
            R = I  # unit matrix
        elif (q_normal[0] == 0 and q_normal[1] == 0 and q_normal[2] == -1):
            R = np.array([[1, 0, 0], [0, -1, 0],
                          [0, 0, -1]])  # rotation by 180deg around x
        else:
            vx = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]],
                           [-v[1], v[0], 0]])
            R = I + vx + vx.dot(vx) / (1. + q_normal.dot(z))

        self.RecTM = R.dot(self.RecTM)

        # align projection of HKL_para_x to x axis
        q = self.q(HKL_para_x)
        rot = -np.arctan2(q[1], q[0]) + np.deg2rad(offset_angle)
        R = np.array([[np.cos(rot), -np.sin(rot), 0],
                      [np.sin(rot), np.cos(rot), 0], [0, 0, 1]])
        self.RecTM = R.dot(self.RecTM)

        self.RecTMInv = inv(self.RecTM)
Exemplo n.º 19
0
    def __init__(self,
                 a,
                 b,
                 c,
                 alpha=90,
                 beta=90,
                 gamma=90,
                 basis=[0, 0, 0],
                 HKL_normal=[0, 0, 1],
                 HKL_para_x=[1, 0, 0],
                 offset_angle=0,
                 E_keV=22.5,
                 theta_x=0,
                 theta_y=0,
                 theta_z=0):
        self.a = a
        self.b = b
        self.c = c
        self.theta_x = theta_x
        self.theta_y = theta_y
        self.theta_z = theta_z

        self.alpha = np.deg2rad(alpha)
        self.beta = np.deg2rad(beta)
        self.gamma = np.deg2rad(gamma)

        self.E_keV = E_keV
        self.k0 = get_k0(E_keV)

        self.basis = basis  # list of [Atomic_form_factor, x, y, z]
        max_E = 30
        for i in range(len(self.basis)):
            if (isinstance(self.basis[i][0], str)):
                f1, f2 = (elements.symbol(
                    self.basis[i][0]).xray.scattering_factors(
                        energy=min(E_keV, max_E)))
                #TODO: test
                #self.basis[i][0] = f1 + 1.j*f2

        self.HKL_normal = HKL_normal
        self.HKL_para_x = HKL_para_x

        # Calculate real space unit cell vectors
        # We choose a Cartesian coordinate system, in which the a-vector
        # is parallel to the x-axis ...
        self.A1 = np.array([self.a, 0, 0])
        # ... and the b-vector lies in the xy-plane.
        self.A2 = np.array(
            [self.b * np.cos(self.gamma), b * np.sin(self.gamma), 0])
        # The c-vector in these Cartesian coordinates is then:
        A31 = self.c * np.cos(self.beta)
        A32 = (self.c / np.sin(self.gamma) *
               (np.cos(self.alpha) - (np.cos(self.beta) * np.cos(self.gamma))))
        A33 = np.sqrt(self.c**2 - (A31**2 + A32**2))
        self.A3 = np.array([A31, A32, A33])
        # Contact Finn / Tim for a more detailed explanation

        # RealTM * (a, b, c) = (x, y, z)
        self.RealTM = np.array([[self.A1[0], self.A2[0], self.A3[0]],
                                [self.A1[1], self.A2[1], self.A3[1]],
                                [self.A1[2], self.A2[2], self.A3[2]]])

        self.RealTMInv = inv(self.RealTM)
        # Calculate reciprocal space unit cell vectors
        self._V_real = self.A1.dot(np.cross(self.A2, self.A3))
        self.B1 = 2 * np.pi * np.cross(self.A2, self.A3) / self._V_real
        self.B2 = 2 * np.pi * np.cross(self.A3, self.A1) / self._V_real
        self.B3 = 2 * np.pi * np.cross(self.A1, self.A2) / self._V_real
        # RecTM * (a*, b*, c*) = (qx, qy, qz)
        self.RecTM = np.array([[self.B1[0], self.B2[0], self.B3[0]],
                               [self.B1[1], self.B2[1], self.B3[1]],
                               [self.B1[2], self.B2[2], self.B3[2]]])

        self._V_rec = self.B1.dot(np.cross(self.B2, self.B3))
        # Align surface normal to qz axis
        # In reciprocal space, the surface normal will point "up" (along qz)
        #self.RecTM = copy.deepcopy(self.RecTM_)
        q_normal = self.q(HKL_normal)
        q_normal /= np.linalg.norm(q_normal)

        z = np.array([0, 0, 1])
        v = np.cross(q_normal, z)  # Our rotation axis

        # I = Identity matrix
        I = np.zeros((3, 3))
        I[0, 0] = 1
        I[1, 1] = 1
        I[2, 2] = 1

        R = np.zeros((3, 3))

        if (v[0] == 0 and v[1] == 0 and v[2] == 0):
            R = I
            # If v = (0,0,0), q_normal is already parallel to q_z

        elif (q_normal[0] == 0 and q_normal[1] == 0 and q_normal[2] == -1):
            R = np.array([[1, 0, 0], [0, -1, 0], [0, 0, -1]])
            # If q_normal = (0,0,-1), q_normal is already antiparallel to q_z,
            # so we just need to rotate by 180 deg around the x-axis

        # If none of the previous two edge cases apply, we can use the
        # solution as per http://math.stackexchange.com/questions/180418
        else:
            vx = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]],
                           [-v[1], v[0], 0]])
            R = I + vx + vx.dot(vx) / (1. + q_normal.dot(z))

        self.RecTM = R.dot(self.RecTM)
        #self.RecTM = copy.deepcopy(self.RecTM_)

        # Align projection of HKL_para_x onto x-axis
        # After this, turn by an additional offset_angle
        q = self.q(HKL_para_x)
        rot = -np.arctan2(q[1], q[0]) + np.deg2rad(offset_angle)
        R = np.array([[np.cos(rot), -np.sin(rot), 0],
                      [np.sin(rot), np.cos(rot), 0], [0, 0, 1]])
        self.RecTM = R.dot(self.RecTM)
        self.RecTMInv = inv(self.RecTM)

        self.unique_elements = np.unique(np.array(self.basis).T[0])
        self.basis_xyz = []
        self.basis_el = []
        for atom in self.basis:
            self.basis_el.append(atom[0])
            self.basis_xyz.append([atom[1], atom[2], atom[3]])
        self.basis_xyz = np.array(self.basis_xyz)
        self.basis_el = np.array(self.basis_el)
        self.RealTM_ = copy.deepcopy(self.RealTM)
        self.RealTMInv_ = inv(self.RealTM_)
        self.RecTM_ = copy.deepcopy(self.RecTM)
        self.RecTMInv_ = inv(self.RecTM_)
        self.apply_xyz_rotation()
Exemplo n.º 20
0
def test():
    # Check that we can access element properties
    assert H.name == "hydrogen"
    assert H.symbol == "H"
    assert H.number == 1
    assert helium.symbol == 'He'

    # Check that isotopes work and produce the correct strings and symbols
    O.add_isotope(18)
    assert H[2].symbol == 'D'
    assert H[3].symbol == 'T'
    assert O[18].symbol == 'O'
    assert str(H[2]) == 'D'
    assert str(H[3]) == 'T'
    assert str(O[18]) == '18-O'
    try:
        Fe[12]
    except KeyError as msg:
        assert msg.args[0] == '12 is not an isotope of Fe'

    # Check that "for el in elements" works and for iso in el works
    els = tuple(el for el in elements)
    assert els[0].number == 0
    assert els[1].number == 1
    isotopes = tuple(iso for iso in O)
    assert isotopes[0].isotope == 12  # 12 is the first oxygen isotope listed

    # Check that table lookup works and fails appropriately
    Fe.add_isotope(56)
    assert elements.symbol('Fe') == Fe
    assert elements.name('iron') == Fe
    assert elements.isotope('Fe') == Fe
    assert elements.isotope('56-Fe') == Fe[56]
    assert elements.isotope('D') == H[2]
    try:
        elements.symbol('Qu')
    except ValueError as msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.name('Qu')
    except ValueError as msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.isotope('Qu')
    except ValueError as msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.isotope('4-D')
    except ValueError as msg:
        assert str(msg) == "unknown element 4-D"

    # Check that ions work
    assert Fe.ion[2].charge == 2
    assert Fe.ions == (2, 3)
    assert str(Fe.ion[2]) == "Fe{2+}"
    assert str(O.ion[-2]) == "O{2-}"
    try:
        Fe.ion[1]
        raise Exception("accepts invalid ions")
    except ValueError as msg:
        assert str(msg) == "1 is not a valid charge for Fe"

    assert data_files()[0][0] == "periodictable-data/xsf"
Exemplo n.º 21
0
def atomList2em(atomList, pixelSize, cubeSize, densityNegative=False):
    """
    atomList2em:
    @param atomList:
    @param pixelSize:
    @param cubeSize:
    @param densityNegative:
    @return:    
    """
    from math import floor
    from pytom_volume import vol

    if len(atomList) == 0:
        raise RuntimeError('atomList2em : Your atom list is empty!')

    # get map
    volume = vol(cubeSize, cubeSize, cubeSize)
    volume.setAll(0.0)

    centroidX = 0
    centroidY = 0
    centroidZ = 0

    for i in range(len(atomList)):
        centroidX += atomList[i].getX()
        centroidY += atomList[i].getY()
        centroidZ += atomList[i].getZ()

    centroidX = centroidX / len(atomList)
    centroidY = centroidY / len(atomList)
    centroidZ = centroidZ / len(atomList)

    centerX = floor(float(cubeSize) / 2.0)
    centerY = floor(float(cubeSize) / 2.0)
    centerZ = floor(float(cubeSize) / 2.0)

    shiftX = centroidX - centerX
    shiftY = centroidY - centerY
    shiftZ = centroidZ - centerZ

    for i in range(len(atomList)):
        atomList[i].setX(round(atomList[i].getX() / pixelSize) + centerX)
        atomList[i].setY(round(atomList[i].getY() / pixelSize) + centerY)
        atomList[i].setZ(round(atomList[i].getZ() / pixelSize) + centerZ)

    periodicTableAvailable = True
    try:
        # searching for periodic table library http://pypi.python.org/pypi/periodictable
        from periodictable import elements
    except ImportError:
        periodicTableAvailable = False

    for i in range(len(atomList)):
        x = int(atomList[i].getX())
        y = int(atomList[i].getY())
        z = int(atomList[i].getZ())

        if x >= cubeSize or y >= cubeSize or z >= cubeSize:
            raise RuntimeError(
                'Cube size is too small. Please specify a larger cube for PDB structure!'
            )

        currentValue = volume(x, y, z)

        if periodicTableAvailable:
            atomName = atomList[i].getAtomType()[0]
            element = elements.symbol(atomName)
            mass = element.mass
            volume.setV(currentValue + mass, x, y, z)
        else:
            if atomList[i].getAtomType()[0] == 'H':  ##maybe take this out
                volume.setV(currentValue + 1.0, x, y, z)
            elif atomList[i].getAtomType()[0] == 'C':
                volume.setV(currentValue + 6.0, x, y, z)
            elif atomList[i].getAtomType()[0] == 'N':
                volume.setV(currentValue + 7.0, x, y, z)
            elif atomList[i].getAtomType()[0] == 'O':
                volume.setV(currentValue + 8.0, x, y, z)
            elif atomList[i].getAtomType()[0] == 'P':
                volume.setV(currentValue + 15.0, x, y, z)
            elif atomList[i].getAtomType()[0] == 'S':
                volume.setV(currentValue + 16.0, x, y, z)

    if densityNegative:
        volume = volume * -1

    return volume
Exemplo n.º 22
0
def test():
    # Check that we can access element properties
    assert H.name == "hydrogen"
    assert H.symbol == "H"
    assert H.number == 1
    assert helium.symbol == 'He'

    # Check that isotopes work and produce the correct strings and symbols
    O.add_isotope(18)
    assert H[2].symbol == 'D'
    assert H[3].symbol == 'T'
    assert O[18].symbol == 'O'
    assert str(H[2]) == 'D'
    assert str(H[3]) == 'T'
    assert str(O[18]) == '18-O'
    try:
        Fe[12]
    except KeyError as msg:
        assert msg.args[0] == '12 is not an isotope of Fe'

    # Check that "for el in elements" works and for iso in el works
    els = tuple(el for el in elements)
    assert els[0].number == 0
    assert els[1].number == 1
    isotopes = tuple(iso for iso in O)
    assert isotopes[0].isotope == 12  # 12 is the first oxygen isotope listed

    # Check that table lookup works and fails appropriately
    Fe.add_isotope(56)
    assert elements.symbol('Fe') == Fe
    assert elements.name('iron') == Fe
    assert elements.isotope('Fe') == Fe
    assert elements.isotope('56-Fe') == Fe[56]
    assert elements.isotope('D') == H[2]
    try:
        elements.symbol('Qu')
    except ValueError as msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.name('Qu')
    except ValueError as msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.isotope('Qu')
    except ValueError as msg:
        assert str(msg) == "unknown element Qu"
    try:
        elements.isotope('4-D')
    except ValueError as msg:
        assert str(msg) == "unknown element 4-D"

    # Check that ions work
    assert Fe.ion[2].charge == 2
    assert Fe.ions == (-4, -2, -1, 1, 2, 3, 4, 5, 6, 7)
    assert str(Fe.ion[2]) == "Fe{2+}"
    assert str(O.ion[-2]) == "O{2-}"
    try:
        Fe.ion[-3]
        raise Exception("accepts invalid ions")
    except ValueError as msg:
        assert str(msg) == "-3 is not a valid charge for Fe"

    assert data_files()[0][0] == "periodictable-data/xsf"
Exemplo n.º 23
0
    def lattice_from_cif(filename,
                         HKL_normal=[0, 0, 1],
                         HKL_para_x=[1, 0, 0],
                         offset_angle=0,
                         energy_keV=22.5):
        cf = CifFile.ReadCif(filename)
        data = cf.first_block()
        a = float(data['_cell_length_a'])
        b = float(data['_cell_length_b'])
        c = float(data['_cell_length_c'])
        alpha = float(data['_cell_angle_alpha'])
        beta = float(data['_cell_angle_beta'])
        gamma = float(data['_cell_angle_gamma'])

        _basis = []
        atom_sites = data.GetLoop('_atom_site_label')
        for atom_site in atom_sites:
            f1, f2 = elements.symbol(
                atom_site[0]).xray.scattering_factors(energy=energy_keV)
            #_atom_site_x = atom_site['_atom_site_fract_x']
            #print _atom_site_x
            _basis.append([
                f1 + 1.j * f2,
                np.array([
                    float(atom_site[1]),
                    float(atom_site[2]),
                    float(atom_site[3]), 1
                ])
            ])

        basis = []
        sym_pos_arr = data.GetLoop('_symmetry_equiv_pos_as_xyz')
        for sym_pos in sym_pos_arr:
            toks = sym_pos[0].split(',')
            pos = ['x', 'y', 'z']
            translation_matrix = np.zeros((4, 4))
            translation_matrix[3, 3] = 1  # [row, column]

            for i in xrange(len(toks)):
                for j in xrange(len(pos)):
                    if (('-%s' % (pos[j])) in toks[i]):
                        translation_matrix[i, j] = -1
                        toks[i] = toks[i].replace('-%s' % (pos[j]), '')
                        break
                    elif (('+%s' % (pos[j])) in toks[i]):
                        translation_matrix[i, j] = 1
                        toks[i] = toks[i].replace('+%s' % (pos[j]), '')
                        break
                    elif (('%s' % (pos[j])) in toks[i]):
                        translation_matrix[i, j] = 1
                        toks[i] = toks[i].replace('%s' % (pos[j]), '')
                        break
                translation_matrix[i, 3] = float(eval(toks[i] + '.0'))

            #print translation_matrix

            for atom in _basis:
                x, y, z, w = translation_matrix.dot(atom[1])
                while (x < 0):
                    x += 1
                while (x >= 1):
                    x -= 1
                while (y < 0):
                    y += 1
                while (y >= 1):
                    y -= 1
                while (z < 0):
                    z += 1
                while (z >= 1):
                    z -= 1
                add_atom = True
                for i in xrange(len(basis)):
                    if (basis[i] == [atom[0], x, y, z]):
                        add_atom = False
                if (add_atom):
                    basis.append([atom[0], x, y, z])

        #print 'basis:', len(basis)
        #print basis

        return lattice(a,
                       b,
                       c,
                       alpha,
                       beta,
                       gamma,
                       basis,
                       HKL_normal,
                       HKL_para_x,
                       offset_angle,
                       energy_keV=energy_keV)