Skip to content

Commit

Permalink
provides Waasmaier and Kirfel form factor approximations
Browse files Browse the repository at this point in the history
  • Loading branch information
ddale committed Jul 20, 2012
1 parent fe0a620 commit 8564b26
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 2 deletions.
4 changes: 2 additions & 2 deletions praxes/io/spec/mapping.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import abc
import collections


cdef class Mapping:
Expand Down Expand Up @@ -35,4 +35,4 @@ cdef class Mapping:
return self._index.values()


abc.Mapping.register(Mapping)
collections.Mapping.register(Mapping)
3 changes: 3 additions & 0 deletions praxes/physref/waasmaier/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .atomicdata import AtomicData

atomic_data = AtomicData()
114 changes: 114 additions & 0 deletions praxes/physref/waasmaier/atomicdata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
"""
Parameters for calculating the atomic scattering factors for free
atoms and ions, as reported by D. Waasmaier and A. Kirfel, Acta.
Cryst. A, v 51, p 416-431 (1995)
┌ ┐ ┌ ┐
│a│ │a₁ a₂ a₃ a₄ a₅│
│b│=│b₁ b₂ b₃ b₄ b₅│
│c│ │c₁ 0 0 0 0 │
└ ┘ └ ┘
"""

#from __future__ import absolute_import

import json
import os
import sqlite3

import numpy as np

from praxes.physref.lib.mapping import Mapping
from praxes.lib.decorators import memoize

class AtomicData(Mapping):

@Mapping._keys.getter
def _keys(self):
cursor = self.__db.cursor()
res = cursor.execute(
'''select ion from f0 order by id'''
)
return tuple(i[0] for i in res)

def __init__(self):
self.__db = sqlite3.connect(
os.path.join(os.path.split(__file__)[0], 'waasmaier_kirfel.db')
)

def __hash__(self):
hash(type(self))

def __getitem__(self, key):
if key not in self:
raise KeyError(
'Form factor approximations not reported for %s' % key
)
return FormFactor(key, self.__db)


class FormFactor(object):
"""
NondispersiveScatterer('Si')
NondispersiveScatterer instances are elements with methods to
calculate nondispersive scattering factors and properties based
on these values.
Parameters for calculating the nondispersive scattering factors
for free atoms and ions, as reported by D. Waasmaier and A.
Kirfel, Acta. Cryst. A, v 51, p 416-431 (1995)
┌ ┐ ┌ ┐
│a│ │a₁ a₂ a₃ a₄ a₅│
│b│=│b₁ b₂ b₃ b₄ b₅│
│c│ │c₁ 0 0 0 0 │
└ ┘ └ ┘
"""

def _get_data(self, id):
cursor = self.__db.cursor()
result = cursor.execute('''select %s from f0
where ion=?''' % id, (self._symbol, )
).fetchone()
assert result is not None
return result[0]

@property
@memoize
def _a(self):
return tuple(json.loads(self._get_data('scale')))

@property
@memoize
def _b(self):
return tuple(json.loads(self._get_data('exponent')))

@property
@memoize
def _c(self):
return self._get_data('offset')

def __init__(self, symbol, db):
"""symbol is a string, like 'Ca' or 'Ca2+'"""
self._symbol = symbol
self.__db = db

def __call__(self, Q):
"""
Calculate the Q-dependent, energy-independent, scattering
factors:
f = f₀(Q)
Q-dependence is appproximated as reported by D. Waasmaier and
A. Kirfel, Acta. Cryst. A, v 51, p 416-431 (1995):
f₀(Q) = ∑_i a_i exp[-b_i(|Q|/4π)²] + c
This approximation is valid for |Q| ≤ 75 Å⁻¹
"""
Q = Q.rescale('1/angstrom').magnitude
f = Q * 0.0 + self._c
for a, b in np.array([self._a, self._b]).transpose():
f += a * np.exp(-b * (Q / (4 * np.pi))**2)
return f
9 changes: 9 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,18 @@ def process_elam(self):
'praxes/physref/elam/elam.db'
)

def process_waasmaier(self):
return (
sys.executable,
'praxes/physref/waasmaier/create_db',
'praxes/physref/waasmaier/waasmaier_kirfel.dat',
'praxes/physref/waasmaier/waasmaier_kirfel.db'
)

def run(self):
to_process = [
self.process_elam(),
self.process_waasmaier(),
]

if sys.platform.startswith('win'):
Expand Down

0 comments on commit 8564b26

Please sign in to comment.