source: sasmodels/code_ellipse.py @ 2de9a5e

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

Update for Aaron

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