Changes in / [598a354:298d2d4] in sasmodels


Ignore:
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • doc/guide/sesans/sans_to_sesans.rst

    rf0fc507 rd7af1c6  
    3131 
    3232in which :math:`t` is the thickness of the sample and :math:`\lambda` is the wavelength of the neutrons. 
     33 
     34Log Spaced SESANS 
     35----------------- 
     36 
     37For computational efficiency, the integral in the Hankel transform is 
     38converted into a Reimann sum 
     39 
     40 
     41.. math:: G(\delta) \approx 
     42          2 \pi 
     43          \sum_{Q=q_{min}}^{q_{max}} J_0(Q \delta) 
     44          \frac{d \Sigma}{d \Omega} (Q) 
     45          Q \Delta Q \! 
     46 
     47However, this model approximates more than is strictly necessary. 
     48Specifically, it is approximating the entire integral, when it is only 
     49the scattering function that cannot be handled analytically.  A better 
     50approximation might be 
     51 
     52.. math:: G(\delta) \approx 
     53          \sum_{n=0} 2 \pi \frac{d \Sigma}{d \Omega} (q_n) 
     54          \int_{q_{n-1}}^{q_n} J_0(Q \delta) Q dQ 
     55          = 
     56          \sum_{n=0} \frac{2 \pi}{\delta} \frac{d \Sigma}{d \Omega} (q_n) 
     57          (q_n J_1(q_n \delta) - q_{n-1}J_1(q_{n-1} \delta))\!, 
     58 
     59Assume that vectors :math:`q_n` and :math:`I_n` represent the q points 
     60and corresponding intensity data, respectively.  Further assume that 
     61:math:`\delta_m` and :math:`G_m` are the spin echo lengths and 
     62corresponding Hankel transform value. 
     63 
     64.. math:: G_m = H_{nm} I_n 
     65 
     66where 
     67 
     68.. math:: H_{nm} = \frac{2 \pi}{\delta_m} 
     69          (q_n J_1(q_n \delta_m) - q_{n-1} J_1(q_{n-1} \delta_m)) 
     70 
     71Also not that, for the limit as :math:`\delta_m` approaches zero, 
     72 
     73.. math:: G(0) 
     74          = 
     75          \sum_{n=0} \pi \frac{d \Sigma}{d \Omega} (q_n) (q_n^2 - q_{n-1}^2) 
  • sasmodels/sesans.py

    rb297ba9 rb297ba9  
    1414import numpy as np  # type: ignore 
    1515from numpy import pi  # type: ignore 
    16 from scipy.special import j0 
     16from scipy.special import j1 
     17 
    1718 
    1819class SesansTransform(object): 
     
    3839 
    3940    # transform arrays 
    40     _H = None  # type: np.ndarray 
    41     _H0 = None # type: np.ndarray 
     41    _H = None   # type: np.ndarray 
     42    _H0 = None  # type: np.ndarray 
    4243 
    4344    def __init__(self, z, SElength, lam, zaccept, Rmax): 
    4445        # type: (np.ndarray, float, float) -> None 
    45         #import logging; logging.info("creating SESANS transform") 
    4646        self.q = z 
    4747        self._set_hankel(SElength, lam, zaccept, Rmax) 
     
    5959    def _set_hankel(self, SElength, lam, zaccept, Rmax): 
    6060        # type: (np.ndarray, float, float) -> None 
    61         # Force float32 arrays, otherwise run into memory problems on some machines 
     61        # Force float32 arrays, otherwise run into memory problems on 
     62        # some machines 
    6263        SElength = np.asarray(SElength, dtype='float32') 
    6364 
    64         #Rmax = #value in text box somewhere in FitPage? 
     65        # Rmax = #value in text box somewhere in FitPage? 
    6566        q_max = 2*pi / (SElength[1] - SElength[0]) 
    6667        q_min = 0.1 * 2*pi / (np.size(SElength) * SElength[-1]) 
    67         q = np.arange(q_min, q_max, q_min, dtype='float32') 
    68         dq = q_min 
     68        # q = np.arange(q_min, q_max, q_min, dtype='float32') 
     69        # q = np.exp(np.arange(np.log(q_min), np.log(q_max), np.log(2), 
     70        #                      dtype=np.float32)) 
     71        q = np.exp(np.linspace(np.log(q_min), np.log(q_max), 10*SElength.size, 
     72                               dtype=np.float32)) 
     73        q = np.hstack([[0], q]) 
    6974 
    70         H0 = np.float32(dq/(2*pi)) * q 
     75        H0 = np.pi * (q[1:]**2 - q[:-1]**2) 
    7176 
    72         repq = np.tile(q, (SElength.size, 1)).T 
    73         repSE = np.tile(SElength, (q.size, 1)) 
    74         H = np.float32(dq/(2*pi)) * j0(repSE*repq) * repq 
     77        # repq = np.tile(q, (SElength.size, 1)).T 
     78        H = np.outer(q, SElength) 
     79        j1(H, out=H) 
     80        H *= q.reshape((-1, 1)) 
     81        H = H[1:] - H[:-1] 
     82        H *= 2 * np.pi / SElength 
    7583 
    76         replam = np.tile(lam, (q.size, 1)) 
    77         reptheta = np.arcsin(repq*replam/2*np.pi) 
     84        lam = np.asarray(lam, dtype=np.float32) 
     85        reptheta = np.outer(q[1:], lam) 
     86        reptheta /= np.float32(2*np.pi) 
     87        np.arcsin(reptheta, out=reptheta) 
     88        # reptheta = np.arcsin(repq*replam/2*np.pi) 
    7889        mask = reptheta > zaccept 
    79         H[mask] = 0 
     90        # H[mask] = 0 
    8091 
    81         self.q_calc = q 
     92        # H = np.zeros((q.size, SElength.size), dtype=np.float32) 
     93        # H0 = q * 0 
     94        assert(H.shape == (q.size-1, SElength.size)) 
     95 
     96        self.q_calc = q[1:] 
    8297        self._H, self._H0 = H, H0 
Note: See TracChangeset for help on using the changeset viewer.