source: sasmodels/Models/code_ellipse.py @ 099e053

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 099e053 was ca6c007, checked in by HMP1 <helen.park@…>, 10 years ago

further organizing

  • Property mode set to 100644
File size: 4.8 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import numpy as np
5import pyopencl as cl
6
7from weights import GaussianDispersion
8from sasmodel import card
9
10
11def set_precision(src, qx, qy, dtype):
12    qx = np.ascontiguousarray(qx, dtype=dtype)
13    qy = np.ascontiguousarray(qy, dtype=dtype)
14    if np.dtype(dtype) == np.dtype('float32'):
15        header = """\
16#define real float
17"""
18    else:
19        header = """\
20#pragma OPENCL EXTENSION cl_khr_fp64: enable
21#define real double
22"""
23    return header+src, qx, qy
24
25class GpuEllipse(object):
26    PARS = {
27    'scale':1, 'radius_a':1, 'radius_b':1, 'sldEll':1e-6, 'sldSolv':0, 'background':0, 'axis_theta':0, 'axis_phi':0,
28    }
29    PD_PARS = ['radius_a', 'radius_b', 'axis_theta', 'axis_phi']
30
31    def __init__(self, qx, qy, dtype='float32'):
32
33        ctx,_queue = card()
34        src, qx, qy = set_precision(open('Kernel/Kernel-Ellipse.cpp').read(), qx, qy, dtype=dtype)
35        self.prg = cl.Program(ctx, src).build()
36        self.qx, self.qy = qx, qy
37
38        #buffers
39        mf = cl.mem_flags
40        self.qx_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qx)
41        self.qy_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qy)
42        self.res_b = cl.Buffer(ctx, mf.WRITE_ONLY, qx.nbytes)
43        self.res = np.empty_like(self.qx)
44
45    def eval(self, pars):
46    #b_n = radius_b # want, a_n = radius_a # want, etc
47        _ctx,queue = card()
48        radius_a, radius_b, axis_theta, axis_phi = \
49            [GaussianDispersion(int(pars[base+'_pd_n']), pars[base+'_pd'], pars[base+'_pd_nsigma'])
50             for base in GpuEllipse.PD_PARS]
51
52        radius_a.value, radius_a.weight = radius_a.get_weights(pars['radius_a'], 0, 10000, True)
53        radius_b.value, radius_b.weight = radius_b.get_weights(pars['radius_b'], 0, 10000, True)
54        axis_theta.value, axis_theta.weight = axis_theta.get_weights(pars['axis_theta'], -90, 180, False)
55        axis_phi.value, axis_phi.weight = axis_phi.get_weights(pars['axis_phi'], -90, 180, False)
56
57        #Perform the computation, with all weight points
58        sum, norm, norm_vol, vol = 0.0, 0.0, 0.0, 0.0
59        size = len(axis_theta.weight)
60        sub = pars['sldEll'] - pars['sldSolv']
61        real = np.float32 if self.qx.dtype == np.dtype('float32') else np.float64
62
63        #Loop over radius weight points
64        for i in xrange(len(radius_a.weight)):
65            #Loop over length weight points
66            for j in xrange(len(radius_b.weight)):
67                #Average over theta distribution
68                for k in xrange(len(axis_theta.weight)):
69                    #Average over phi distribution
70                    for l in xrange(len(axis_phi.weight)):
71                        #call the kernel
72                        self.prg.EllipsoidKernel(queue, self.qx.shape, None, real(radius_a.weight[i]),
73                                        real(radius_b.weight[j]), real(axis_theta.weight[k]),
74                                        real(axis_phi.weight[l]), real(pars['scale']), real(radius_a.value[i]),
75                                        real(radius_b.value[j]), real(sub), real(axis_theta.value[k]),
76                                        real(axis_phi.value[l]), self.qx_b, self.qy_b, self.res_b,
77                                        np.uint32(self.qx.size), np.uint32(len(axis_theta.weight)))
78                        #copy result back from buffer
79                        cl.enqueue_copy(queue, self.res, self.res_b)
80                        sum += self.res
81                        vol += radius_a.weight[i]*radius_b.weight[j]*pow(radius_b.value[j], 2)*radius_a.value[i]
82                        norm_vol += radius_a.weight[i]*radius_b.weight[j]
83                        norm += radius_a.weight[i]*radius_b.weight[j]*axis_theta.weight[k]*axis_phi.weight[l]
84        # Averaging in theta needs an extra normalization
85        # factor to account for the sin(theta) term in the
86        # integration (see documentation).
87
88    #    if size > 1:
89     #       norm /= math.asin(1.0)
90        if vol != 0.0 and norm_vol != 0.0:
91            sum *= norm_vol/vol
92
93        return sum/norm+pars['background']
94
95
96def demo():
97    from time import time
98    import matplotlib.pyplot as plt
99
100    #create qx and qy evenly spaces
101    qx = np.linspace(-.02, .02, 128)
102    qy = np.linspace(-.02, .02, 128)
103    qx, qy = np.meshgrid(qx, qy)
104
105    #saved shape of qx
106    r_shape = qx.shape
107    #reshape for calculation; resize as float32
108    qx = qx.flatten()
109    qy = qy.flatten()
110
111    #int main
112    pars = EllipsoidParameters(.027, 60, 180, .297e-6, 5.773e-06, 4.9, 0, 90)
113
114    t = time()
115    result = GpuEllipse(qx, qy)
116    result.x = result.ellipsoid_fit(qx, qy, pars, b_n=35, t_n=35, a_n=1, p_n=1, sigma=3, b_w=.1, t_w=.1, a_w=.1, p_w=.1)
117    result.x = np.reshape(result.x, r_shape)
118    tt = time()
119    print("Time taken: %f" % (tt - t))
120
121    plt.pcolormesh(result.x)
122    plt.show()
123
124
125if __name__ == "__main__":
126    demo()
127
128
129
130
Note: See TracBrowser for help on using the repository browser.