1 | """ |
---|
2 | Validation tests for real-space simulation of I(q) |
---|
3 | |
---|
4 | @copyright: University of Tennessee, 2007 |
---|
5 | @license: This software is provided as part of the DANSE project |
---|
6 | """ |
---|
7 | import math, time, pylab |
---|
8 | |
---|
9 | try: |
---|
10 | import VolumeCanvas |
---|
11 | print "Testing local version" |
---|
12 | except: |
---|
13 | print "Testing installed version" |
---|
14 | import sans.realspace.VolumeCanvas as VolumeCanvas |
---|
15 | |
---|
16 | class Validator: |
---|
17 | |
---|
18 | def __init__(self): |
---|
19 | self.density = 0.1 |
---|
20 | self.create() |
---|
21 | |
---|
22 | def create(self): |
---|
23 | pass |
---|
24 | |
---|
25 | def run_sim(self, q, density=None): |
---|
26 | """ |
---|
27 | Calculate the mean and error of the simulation |
---|
28 | @param q: q-value to calculate at |
---|
29 | @param density: point density of simulation |
---|
30 | #return: mean, error |
---|
31 | """ |
---|
32 | if not density == None: |
---|
33 | self.density = density |
---|
34 | self.create() |
---|
35 | |
---|
36 | return self.canvas.getIqError(q) |
---|
37 | |
---|
38 | def run_ana(self, q): |
---|
39 | """ |
---|
40 | Return analytical value |
---|
41 | @param q: q-value to evaluate at [float] |
---|
42 | @return: analytical output [float] |
---|
43 | """ |
---|
44 | return self.ana.run(q) |
---|
45 | |
---|
46 | class SphereValidator(Validator): |
---|
47 | |
---|
48 | def __init__(self, radius=15, density = 0.01): |
---|
49 | from sans.models.SphereModel import SphereModel |
---|
50 | |
---|
51 | self.name = 'sphere' |
---|
52 | self.radius = radius |
---|
53 | self.density = density |
---|
54 | |
---|
55 | self.ana = SphereModel() |
---|
56 | self.ana.setParam('scale', 1.0) |
---|
57 | self.ana.setParam('contrast', 1.0) |
---|
58 | self.ana.setParam('background', 0.0) |
---|
59 | self.ana.setParam('radius', radius) |
---|
60 | self.create() |
---|
61 | |
---|
62 | def create(self): |
---|
63 | canvas = VolumeCanvas.VolumeCanvas() |
---|
64 | canvas.setParam('lores_density', self.density) |
---|
65 | handle = canvas.add('sphere') |
---|
66 | canvas.setParam('%s.radius' % handle, self.radius) |
---|
67 | canvas.setParam('scale' , 1.0) |
---|
68 | canvas.setParam('%s.contrast' % handle, 1.0) |
---|
69 | canvas.setParam('background' , 0.0) |
---|
70 | self.canvas = canvas |
---|
71 | |
---|
72 | class CylinderValidator(Validator): |
---|
73 | |
---|
74 | def __init__(self, radius=15, length=100, density = 0.01): |
---|
75 | from sans.models.CylinderModel import CylinderModel |
---|
76 | |
---|
77 | self.name = 'cylinder' |
---|
78 | self.radius = radius |
---|
79 | self.length = length |
---|
80 | self.density = density |
---|
81 | |
---|
82 | self.ana = CylinderModel() |
---|
83 | self.ana.setParam('scale', 1.0) |
---|
84 | self.ana.setParam('contrast', 1.0) |
---|
85 | self.ana.setParam('background', 0.0) |
---|
86 | self.ana.setParam('radius', radius) |
---|
87 | self.ana.setParam('length', length) |
---|
88 | self.create() |
---|
89 | |
---|
90 | def create(self): |
---|
91 | canvas = VolumeCanvas.VolumeCanvas() |
---|
92 | canvas.setParam('lores_density', self.density) |
---|
93 | handle = canvas.add('cylinder') |
---|
94 | canvas.setParam('%s.radius' % handle, self.radius) |
---|
95 | canvas.setParam('%s.length' % handle, self.length) |
---|
96 | canvas.setParam('scale' , 1.0) |
---|
97 | canvas.setParam('%s.contrast' % handle, 1.0) |
---|
98 | canvas.setParam('background' , 0.0) |
---|
99 | self.canvas = canvas |
---|
100 | |
---|
101 | class EllipsoidValidator(Validator): |
---|
102 | |
---|
103 | def __init__(self, radius_a=60, radius_b=10, density = 0.01): |
---|
104 | from sans.models.EllipsoidModel import EllipsoidModel |
---|
105 | #from sans.models.SphereModel import SphereModel |
---|
106 | |
---|
107 | self.name = 'ellipsoid' |
---|
108 | self.radius_a = radius_a |
---|
109 | self.radius_b = radius_b |
---|
110 | self.density = density |
---|
111 | |
---|
112 | self.ana = EllipsoidModel() |
---|
113 | #self.ana = SphereModel() |
---|
114 | self.ana.setParam('scale', 1.0) |
---|
115 | self.ana.setParam('contrast', 1.0) |
---|
116 | self.ana.setParam('background', 0.0) |
---|
117 | self.ana.setParam('radius_a', radius_a) |
---|
118 | self.ana.setParam('radius_b', radius_b) |
---|
119 | #self.ana.setParam('radius', radius_a) |
---|
120 | |
---|
121 | self.create() |
---|
122 | |
---|
123 | def create(self): |
---|
124 | canvas = VolumeCanvas.VolumeCanvas() |
---|
125 | canvas.setParam('lores_density', self.density) |
---|
126 | handle = canvas.add('ellipsoid') |
---|
127 | canvas.setParam('%s.radius_x' % handle, self.radius_a) |
---|
128 | canvas.setParam('%s.radius_y' % handle, self.radius_b) |
---|
129 | canvas.setParam('%s.radius_z' % handle, self.radius_b) |
---|
130 | canvas.setParam('scale' , 1.0) |
---|
131 | canvas.setParam('%s.contrast' % handle, 1.0) |
---|
132 | canvas.setParam('background' , 0.0) |
---|
133 | self.canvas = canvas |
---|
134 | |
---|
135 | class HelixValidator(Validator): |
---|
136 | |
---|
137 | def __init__(self, density = 0.01): |
---|
138 | self.name = 'helix' |
---|
139 | self.density = density |
---|
140 | self.create() |
---|
141 | |
---|
142 | def create(self): |
---|
143 | canvas = VolumeCanvas.VolumeCanvas() |
---|
144 | canvas.setParam('lores_density', self.density) |
---|
145 | handle = canvas.add('singlehelix') |
---|
146 | canvas.setParam('scale' , 1.0) |
---|
147 | canvas.setParam('%s.contrast' % handle, 1.0) |
---|
148 | canvas.setParam('background' , 0.0) |
---|
149 | self.canvas = canvas |
---|
150 | # just to write the parameters to the output file |
---|
151 | self.ana = canvas |
---|
152 | |
---|
153 | def run_ana(self, q): |
---|
154 | return 1 |
---|
155 | |
---|
156 | |
---|
157 | class CoreShellValidator(Validator): |
---|
158 | |
---|
159 | def __init__(self, radius=15, thickness=5, density = 0.01): |
---|
160 | from sans.models.CoreShellModel import CoreShellModel |
---|
161 | |
---|
162 | self.name = 'coreshell' |
---|
163 | self.radius = radius |
---|
164 | |
---|
165 | core_vol = 4.0/3.0*math.pi*radius*radius*radius |
---|
166 | self.outer_radius = radius+thickness |
---|
167 | shell_vol = 4.0/3.0*math.pi*self.outer_radius*self.outer_radius*self.outer_radius - core_vol |
---|
168 | self.shell_sld = -1.0*core_vol/shell_vol |
---|
169 | |
---|
170 | self.density = density |
---|
171 | |
---|
172 | # Core-shell |
---|
173 | sphere = CoreShellModel() |
---|
174 | # Core radius |
---|
175 | sphere.setParam('radius', self.radius) |
---|
176 | # Shell thickness |
---|
177 | sphere.setParam('thickness', thickness) |
---|
178 | sphere.setParam('core_sld', 1.0) |
---|
179 | sphere.setParam('shell_sld', self.shell_sld) |
---|
180 | sphere.setParam('solvent_sld', 0.0) |
---|
181 | sphere.setParam('background', 0.0) |
---|
182 | sphere.setParam('scale', 1.0) |
---|
183 | self.ana = sphere |
---|
184 | self.create() |
---|
185 | |
---|
186 | def create(self): |
---|
187 | canvas = VolumeCanvas.VolumeCanvas() |
---|
188 | canvas.setParam('lores_density', self.density) |
---|
189 | |
---|
190 | handle = canvas.add('sphere') |
---|
191 | canvas.setParam('%s.radius' % handle, self.outer_radius) |
---|
192 | canvas.setParam('%s.contrast' % handle, self.shell_sld) |
---|
193 | |
---|
194 | handle2 = canvas.add('sphere') |
---|
195 | canvas.setParam('%s.radius' % handle2, self.radius) |
---|
196 | canvas.setParam('%s.contrast' % handle2, 1.0) |
---|
197 | |
---|
198 | canvas.setParam('scale' , 1.0) |
---|
199 | canvas.setParam('background' , 0.0) |
---|
200 | self.canvas = canvas |
---|
201 | |
---|
202 | def validate_model(validator, q_min, q_max, n_q): |
---|
203 | """ |
---|
204 | Validate a model |
---|
205 | An output file containing a comparison between |
---|
206 | simulation and the analytical solution will be |
---|
207 | produced. |
---|
208 | |
---|
209 | @param validator: validator object |
---|
210 | @param q_min: minimum q |
---|
211 | @param q_max: maximum q |
---|
212 | @param n_q: number of q points |
---|
213 | @param N: number of times to evaluate each simulation point |
---|
214 | """ |
---|
215 | |
---|
216 | q_list = pylab.arange(q_min, q_max*1.0001, (q_max-q_min)/(n_q-1)) |
---|
217 | |
---|
218 | output = open('%s_d=%g_Iq.txt' % (validator.name, validator.density), 'w') |
---|
219 | output.write("PARS: %s\n" % validator.ana.params) |
---|
220 | output.write("<q> <ana> <sim> <err>\n") |
---|
221 | for q in q_list: |
---|
222 | ana = validator.run_ana(q) |
---|
223 | sim, err = validator.run_sim(q) |
---|
224 | print "q=%-g ana=%-g sim=%-g err=%-g diff=%-g (%-g) %s" % (q, ana, sim, err, |
---|
225 | (sim-ana), sim/ana, str(math.fabs(sim-ana)>err)) |
---|
226 | output.write("%g %g %g %g\n" % (q, ana, sim, err)) |
---|
227 | output.close() |
---|
228 | |
---|
229 | def check_density(validator, q, d_min, d_max, n_d): |
---|
230 | """ |
---|
231 | Check simulation output as a function of the density |
---|
232 | An output file containing a comparison between |
---|
233 | simulation and the analytical solution will be |
---|
234 | produced. |
---|
235 | |
---|
236 | @param validator: validator object |
---|
237 | @param q: q-value to evaluate at |
---|
238 | @param d_min: minimum density |
---|
239 | @param d_max: maximum density |
---|
240 | @param n_d: number of density points |
---|
241 | @param N: number of times to evaluate each simulation point |
---|
242 | """ |
---|
243 | d_list = pylab.arange(d_min, d_max*1.0001, (d_max-d_min)/(n_d-1.0)) |
---|
244 | |
---|
245 | output = open('%s_%g_density.txt' % (validator.name, q), 'w') |
---|
246 | output.write("PARS: %s\n" % validator.ana.params) |
---|
247 | output.write("<density> <ana_d> <sim_d> <err_d>\n") |
---|
248 | ana = validator.run_ana(q) |
---|
249 | for d in d_list: |
---|
250 | sim, err = validator.run_sim(q, density=d) |
---|
251 | print "d=%-g ana=%-g sim=%-g err=%-g diff=%-g (%g) %s" % \ |
---|
252 | (d, ana, sim, err, (sim-ana), (sim-ana)/ana, |
---|
253 | str(math.fabs(sim-ana)>err)) |
---|
254 | output.write("%g %g %g %g \n" % (d, ana, sim, err)) |
---|
255 | output.close() |
---|
256 | |
---|
257 | |
---|
258 | if __name__ == '__main__': |
---|
259 | #vali = CoreShellValidator(radius = 15, thickness=5, density = 0.01) |
---|
260 | #validate_model(vali, q_min=0.001, q_max=1, n_q=50, N=40) |
---|
261 | |
---|
262 | #vali = SphereValidator(radius = 20, density = 0.02) |
---|
263 | #validate_model(vali, q_min=0.001, q_max=0.5, n_q=25, N=20) |
---|
264 | |
---|
265 | vali = CylinderValidator(radius = 20, length=100, density = 0.1) |
---|
266 | validate_model(vali, q_min=0.001, q_max=0.5, n_q=25) |
---|
267 | |
---|
268 | #vali = EllipsoidValidator(radius_a = 20, radius_b=15, density = 0.05) |
---|
269 | #validate_model(vali, q_min=0.001, q_max=0.5, n_q=25) |
---|
270 | |
---|
271 | #vali = HelixValidator(density = 0.05) |
---|
272 | #validate_model(vali, q_min=0.001, q_max=0.5, n_q=25) |
---|
273 | |
---|
274 | |
---|