Changeset d5014e4 in sasmodels
- Timestamp:
- Jan 17, 2018 10:21:59 AM (7 years ago)
- Children:
- 6ceca44
- Parents:
- 5ab99b7 (diff), ff431ca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 3 deleted
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/py2c.py
rd7f33e5 rd5014e4 112 112 # Update Notes 113 113 # ============ 114 # 11/22/2017, O.E.Each 'visit_*' method is to build a C statement string. It115 # shold insert 4 blanks per indentation level.116 # The 'body' method will combine all the strings, by adding117 # the'current_statement' to the c_proc string list118 # 11/2017, OE: variables, argument definition implemented.119 # Note: Anargument is considered an array if it is the target of an120 # assignment. In that case it is translated to <var>[0]121 # 11/27/2017, OE: 'pow' basicly working122 # /12/2017, OE: Multiple assignment: a1,a2,...,an=b1,b2,...bn implemented123 # /12/2017, OE: Power function, including special cases of114 # 2017-11-22, OE: Each 'visit_*' method is to build a C statement string. It 115 # shold insert 4 blanks per indentation level. The 'body' 116 # method will combine all the strings, by adding the 117 # 'current_statement' to the c_proc string list 118 # 2017-11-22, OE: variables, argument definition implemented. Note: An 119 # argument is considered an array if it is the target of an 120 # assignment. In that case it is translated to <var>[0] 121 # 2017-11-27, OE: 'pow' basicly working 122 # 2017-12-07, OE: Multiple assignment: a1,a2,...,an=b1,b2,...bn implemented 123 # 2017-12-07, OE: Power function, including special cases of 124 124 # square(x)(pow(x,2)) and cube(x)(pow(x,3)), implemented in 125 125 # translate_power, called from visit_BinOp 126 # 12/07/2017, OE: Translation of integer division, '\\' in python, implemented126 # 2017-12-07, OE: Translation of integer division, '\\' in python, implemented 127 127 # in translate_integer_divide, called from visit_BinOp 128 # 12/07/2017, OE: C variable definition handled in 'define_c_vars'128 # 2017-12-07, OE: C variable definition handled in 'define_c_vars' 129 129 # : Python integer division, '//', translated to C in 130 130 # 'translate_integer_divide' 131 # 12/15/2017, OE: Precedence maintained by writing opening and closing131 # 2017-12-15, OE: Precedence maintained by writing opening and closing 132 132 # parenthesesm '(',')', in procedure 'visit_BinOp'. 133 # 12/18/2017, OE: Added call to 'add_current_line()' at the beginning133 # 2017-12-18, OE: Added call to 'add_current_line()' at the beginning 134 134 # of visit_Return 135 135 # 2018-01-03, PK: Update interface for use in sasmodels … … 140 140 # 2018-01-03, PK: simplistic print function, for debugging 141 141 # 2018-01-03, PK: while expr: ... => while (expr) { ... } 142 # 2018-01-04, OE: Fixed bug in 'visit_If': visiting node.orelse in case else exists. 142 143 143 144 from __future__ import print_function … … 184 185 185 186 186 def to_source(tree, constants=None, fname=None, lineno=0): 187 """ 188 This function can convert a syntax tree into C sourcecode. 189 """ 190 generator = SourceGenerator(constants=constants, fname=fname, lineno=lineno) 191 generator.visit(tree) 192 c_code = "".join(generator.c_proc) 193 return c_code 194 187 # TODO: should not allow eval of arbitrary python 195 188 def isevaluable(s): 196 189 try: … … 329 322 except AttributeError: 330 323 arg_name = arg.id 331 w_str = (" Default Parameters are unknown to C: '%s =%s"324 w_str = ("C does not support default parameters: %s=%s" 332 325 % (arg_name, str(default.n))) 333 326 self.warnings.append(w_str) … … 508 501 self.current_function = node.name 509 502 503 # remember the location of the next warning that will be inserted 504 # so that we can stuff the function name ahead of the warning list 505 # if any warnings are generated by the function. 506 warning_index = len(self.warnings) 507 510 508 self.newline(extra=1) 511 509 self.decorators(node) … … 523 521 del self.c_pointers[:] 524 522 self.current_function = "" 523 if warning_index != len(self.warnings): 524 self.warnings.insert(warning_index, "Warning in function '" + node.name + "':") 525 525 526 526 def visit_ClassDef(self, node): … … 586 586 self.newline() 587 587 self.write_c('else {') 588 self.body( node.body)588 self.body(else_) 589 589 self.add_c_line('}') 590 590 break … … 615 615 return start, stop, step 616 616 617 def add_c_int_var(self, name): 618 if name not in self.c_int_vars: 619 self.c_int_vars.append(name) 620 617 621 def visit_For(self, node): 618 622 # node: for iterator is stored in node.target. … … 627 631 iterator = self.current_statement 628 632 self.current_statement = '' 629 if iterator not in self.c_int_vars: 630 self.c_int_vars.append(iterator) 633 self.add_c_int_var(iterator) 631 634 start, stop, step = self.get_for_range(node) 632 635 self.write_c("for (" + iterator + "=" + str(start) + … … 736 739 self.write_c('return') 737 740 else: 738 self.write_c('return (')741 self.write_c('return ') 739 742 self.visit(node.value) 740 self.write_c(')')741 743 self.add_semi_colon() 742 744 self.in_expr = False … … 855 857 name not in self.c_constants and not name.isdigit()): 856 858 if self.in_subscript: 857 self. c_int_vars.append(node.id)859 self.add_c_int_var(node.id) 858 860 else: 859 861 self.c_vars.append(node.id) … … 1252 1254 Convert a list of functions to a list of C code strings. 1253 1255 1256 Returns list of corresponding code snippets (with trailing lines in 1257 each block) and a list of warnings generated by the translator. 1258 1254 1259 A function is given by the tuple (source, filename, line number). 1255 1260 … … 1266 1271 """ 1267 1272 snippets = [] 1268 #snippets.append("#include <math.h>") 1269 #snippets.append("") 1273 warnings = [] 1270 1274 for source, fname, lineno in functions: 1271 1275 line_directive = '#line %d "%s"\n'%(lineno, fname.replace('\\', '\\\\')) … … 1275 1279 source = PRINT_STR.sub(SUBST_STR, source) 1276 1280 tree = ast.parse(source) 1277 c_code = to_source(tree, constants=constants, fname=fname, lineno=lineno) 1281 generator = SourceGenerator(constants=constants, fname=fname, lineno=lineno) 1282 generator.visit(tree) 1283 c_code = "".join(generator.c_proc) 1278 1284 snippets.append(c_code) 1279 return snippets 1280 1281 def main(): 1282 import os 1283 #print("Parsing...using Python" + sys.version) 1284 if len(sys.argv) == 1: 1285 print("""\ 1286 Usage: python py2c.py <infile> [<outfile>] 1287 1288 if outfile is omitted, output file is '<infile>.c' 1289 """) 1290 return 1291 1292 fname_in = sys.argv[1] 1293 if len(sys.argv) == 2: 1294 fname_base = os.path.splitext(fname_in)[0] 1295 fname_out = str(fname_base) + '.c' 1296 else: 1297 fname_out = sys.argv[2] 1298 1299 with open(fname_in, "r") as python_file: 1300 code = python_file.read() 1301 name = "gauss" 1302 code = (code 1303 .replace(name+'.n', 'GAUSS_N') 1304 .replace(name+'.z', 'GAUSS_Z') 1305 .replace(name+'.w', 'GAUSS_W') 1306 .replace('if __name__ == "__main__"', "def main()") 1307 ) 1308 1309 1310 c_code = "".join(translate([(code, fname_in, 1)])) 1311 c_code = c_code.replace("double main()", "int main(int argc, char *argv[])") 1312 1313 with open(fname_out, "w") as file_out: 1314 file_out.write(""" 1285 warnings.extend(generator.warnings) 1286 return snippets, warnings 1287 1288 def to_source(tree, constants=None, fname=None, lineno=0): 1289 """ 1290 This function can convert a syntax tree into C sourcecode. 1291 """ 1292 c_code = "".join(generator.c_proc) 1293 return c_code 1294 1295 1296 C_HEADER = """ 1315 1297 #include <stdio.h> 1316 1298 #include <stdbool.h> … … 1330 1312 return ans; 1331 1313 } 1332 1333 """) 1314 """ 1315 1316 USAGE = """\ 1317 Usage: python py2c.py <infile> [<outfile>] 1318 1319 if outfile is omitted, output file is '<infile>.c' 1320 """ 1321 1322 def main(): 1323 import os 1324 #print("Parsing...using Python" + sys.version) 1325 if len(sys.argv) == 1: 1326 print(USAGE) 1327 return 1328 1329 fname_in = sys.argv[1] 1330 if len(sys.argv) == 2: 1331 fname_base = os.path.splitext(fname_in)[0] 1332 fname_out = str(fname_base) + '.c' 1333 else: 1334 fname_out = sys.argv[2] 1335 1336 with open(fname_in, "r") as python_file: 1337 code = python_file.read() 1338 name = "gauss" 1339 code = (code 1340 .replace(name+'.n', 'GAUSS_N') 1341 .replace(name+'.z', 'GAUSS_Z') 1342 .replace(name+'.w', 'GAUSS_W') 1343 .replace('if __name__ == "__main__"', "def main()") 1344 ) 1345 1346 translation, warnings = translate([(code, fname_in, 1)]) 1347 c_code = "".join(translation) 1348 c_code = c_code.replace("double main()", "int main(int argc, char *argv[])") 1349 1350 with open(fname_out, "w") as file_out: 1351 file_out.write(C_HEADER) 1334 1352 file_out.write(c_code) 1353 1354 if warnings: 1355 print("\n".join(warnings)) 1335 1356 #print("...Done") 1336 1357 -
doc/guide/orientation/orientation.rst
r82592da r5fb0634 4 4 ================== 5 5 6 With two dimensional small angle diffraction data SasViewwill calculate6 With two dimensional small angle diffraction data sasmodels will calculate 7 7 scattering from oriented particles, applicable for example to shear flow 8 8 or orientation in a magnetic field. 9 9 10 10 In general we first need to define the reference orientation 11 of the particles with respect to the incoming neutron or X-ray beam. This 12 is done using three angles: $\theta$ and $\phi$ define the orientation of 13 the axis of the particle, angle $\Psi$ is defined as the orientation of 14 the major axis of the particle cross section with respect to its starting 15 position along the beam direction. The figures below are for an elliptical 16 cross section cylinder, but may be applied analogously to other shapes of 17 particle. 11 of the particle's $a$-$b$-$c$ axes with respect to the incoming 12 neutron or X-ray beam. This is done using three angles: $\theta$ and $\phi$ 13 define the orientation of the $c$-axis of the particle, and angle $\Psi$ is 14 defined as the orientation of the major axis of the particle cross section 15 with respect to its starting position along the beam direction (or 16 equivalently, as rotation about the $c$ axis). There is an unavoidable 17 ambiguity when $c$ is aligned with $z$ in that $\phi$ and $\Psi$ both 18 serve to rotate the particle about $c$, but this symmetry is destroyed 19 when $\theta$ is not a multiple of 180. 20 21 The figures below are for an elliptical cross section cylinder, but may 22 be applied analogously to other shapes of particle. 18 23 19 24 .. note:: … … 29 34 30 35 Definition of angles for oriented elliptical cylinder, where axis_ratio 31 b/a is shown >1 ,Note that rotation $\theta$, initially in the $x$-$z$36 b/a is shown >1. Note that rotation $\theta$, initially in the $x$-$z$ 32 37 plane, is carried out first, then rotation $\phi$ about the $z$-axis, 33 38 finally rotation $\Psi$ is around the axis of the cylinder. The neutron 34 or X-ray beam is along the $ z$ axis.39 or X-ray beam is along the $-z$ axis. 35 40 36 41 .. figure:: … … 40 45 with $\Psi$ = 0. 41 46 42 Having established the mean direction of the particle we can then apply 43 angular orientation distributions. This is done by a numerical integration 44 over a range of angles in a similar way to particle size dispersity. 45 In the current version of sasview the orientational dispersity is defined 46 with respect to the axes of the particle. 47 Having established the mean direction of the particle (the view) we can then 48 apply angular orientation distributions (jitter). This is done by a numerical 49 integration over a range of angles in a similar way to particle size 50 dispersity. The orientation dispersity is defined with respect to the 51 $a$-$b$-$c$ axes of the particle, with roll angle $\Psi$ about the $c$-axis, 52 yaw angle $\theta$ about the $b$-axis and pitch angle $\phi$ about the 53 $a$-axis. 54 55 More formally, starting with axes $a$-$b$-$c$ of the particle aligned 56 with axes $x$-$y$-$z$ of the laboratory frame, the orientation dispersity 57 is applied first, using the 58 `Tait-Bryan <https://en.wikipedia.org/wiki/Euler_angles#Conventions_2>`_ 59 $x$-$y'$-$z''$ convention with angles $\Delta\phi$-$\Delta\theta$-$\Delta\Psi$. 60 The reference orientation then follows, using the 61 `Euler angles <https://en.wikipedia.org/wiki/Euler_angles#Conventions>`_ 62 $z$-$y'$-$z''$ with angles $\phi$-$\theta$-$\Psi$. This is implemented 63 using rotation matrices as 64 65 .. math:: 66 67 R = R_z(\phi)\, R_y(\theta)\, R_z(\Psi)\, 68 R_x(\Delta\phi)\, R_y(\Delta\theta)\, R_z(\Delta\Psi) 69 70 To transform detector $(q_x, q_y)$ values into $(q_a, q_b, q_c)$ for the 71 shape in its canonical orientation, use 72 73 .. math:: 74 75 [q_a, q_b, q_c]^T = R^{-1} \, [q_x, q_y, 0]^T 76 77 78 The inverse rotation is easily calculated by rotating the opposite directions 79 in the reverse order, so 80 81 .. math:: 82 83 R^{-1} = R_z(-\Delta\Psi)\, R_y(-\Delta\theta)\, R_x(-\Delta\phi)\, 84 R_z(-\Psi)\, R_y(-\theta)\, R_z(-\phi) 85 47 86 48 87 The $\theta$ and $\phi$ orientation parameters for the cylinder only appear 49 when fitting 2d data. On introducing "Orientational Distribution" in 50 theangles, "distribution of theta" and "distribution of phi" parameters will88 when fitting 2d data. On introducing "Orientational Distribution" in the 89 angles, "distribution of theta" and "distribution of phi" parameters will 51 90 appear. These are actually rotations about the axes $\delta_1$ and $\delta_2$ 52 of the cylinder, the $b$ and $a$ axes of the cylinder cross section. (When 53 $\theta = \phi = 0$ these are parallel to the $Y$ and $X$ axes of the 54 instrument.) The third orientation distribution, in $\Psi$, is about the $c$ 55 axis of the particle. Some experimentation may be required to understand the 56 2d patterns fully. A number of different shapes of distribution are 57 available, as described for polydispersity, see :ref:`polydispersityhelp` . 91 of the cylinder, which correspond to the $b$ and $a$ axes of the cylinder 92 cross section. (When $\theta = \phi = 0$ these are parallel to the $Y$ and 93 $X$ axes of the instrument.) The third orientation distribution, in $\Psi$, 94 is about the $c$ axis of the particle. Some experimentation may be required 95 to understand the 2d patterns fully. A number of different shapes of 96 distribution are available, as described for size dispersity, see 97 :ref:`polydispersityhelp`. 58 98 59 Earlier versions of SasView had numerical integration issues in some 60 circumstances when distributions passed through 90 degrees. The distributions 61 in particle coordinates are more robust, but should still be approached with 62 care for large ranges of angle. 99 Given that the angular dispersion distribution is defined in cartesian space, 100 over a cube defined by 101 102 .. math:: 103 104 [-\Delta \theta, \Delta \theta] \times 105 [-\Delta \phi, \Delta \phi] \times 106 [-\Delta \Psi, \Delta \Psi] 107 108 but the orientation is defined over a sphere, we are left with a 109 `map projection <https://en.wikipedia.org/wiki/List_of_map_projections>`_ 110 problem, with different tradeoffs depending on how values in $\Delta\theta$ 111 and $\Delta\phi$ are translated into latitude/longitude on the sphere. 112 113 Sasmodels is using the 114 `equirectangular projection <https://en.wikipedia.org/wiki/Equirectangular_projection>`_. 115 In this projection, square patches in angular dispersity become wedge-shaped 116 patches on the sphere. To correct for the changing point density, there is a 117 scale factor of $\sin(\Delta\theta)$ that applies to each point in the 118 integral. This is not enough, though. Consider a shape which is tumbling 119 freely around the $b$ axis, with $\Delta\theta$ uniform in $[-180, 180]$. At 120 $\pm 90$, all points in $\Delta\phi$ map to the pole, so the jitter will have 121 a distinct angular preference. If the spin axis is along the beam (which 122 will be the case for $\theta=90$ and $\Psi=90$) the scattering pattern 123 should be circularly symmetric, but it will go to zero at $q_x = 0$ due to the 124 $\sin(\Delta\theta)$ correction. This problem does not appear for a shape 125 that is tumbling freely around the $a$ axis, with $\Delta\phi$ uniform in 126 $[-180, 180]$, so swap the $a$ and $b$ axes so $\Delta\theta < \Delta\phi$ 127 and adjust $\Psi$ by 90. This works with the current sasmodels shapes due to 128 symmetry. 129 130 Alternative projections were considered. 131 The `sinusoidal projection <https://en.wikipedia.org/wiki/Sinusoidal_projection>`_ 132 works by scaling $\Delta\phi$ as $\Delta\theta$ increases, and dropping those 133 points outside $[-180, 180]$. The distortions are a little less for middle 134 ranges of $\Delta\theta$, but they are still severe for large $\Delta\theta$ 135 and the model is much harder to explain. 136 The `azimuthal equidistance projection <https://en.wikipedia.org/wiki/Azimuthal_equidistant_projection>`_ 137 also improves on the equirectangular projection by extending the range of 138 reasonable values for the $\Delta\theta$ range, with $\Delta\phi$ forming a 139 wedge that cuts to the opposite side of the sphere rather than cutting to the 140 pole. This projection has the nice property that distance from the center are 141 preserved, and that $\Delta\theta$ and $\Delta\phi$ act the same. 142 The `azimuthal equal area projection <https://en.wikipedia.org/wiki/Lambert_azimuthal_equal-area_projection>`_ 143 is like the azimuthal equidistance projection, but it preserves area instead 144 of distance. It also has the same behaviour for $\Delta\theta$ and $\Delta\phi$. 145 The `Guyou projection <https://en.wikipedia.org/wiki/Guyou_hemisphere-in-a-square_projection>`_ 146 has an excellent balance with reasonable distortion in both $\Delta\theta$ 147 and $\Delta\phi$, as well as preserving small patches. However, it requires 148 considerably more computational overhead, and we have not yet derived the 149 formula for the distortion correction, measuring the degree of stretch at 150 the point $(\Delta\theta, \Delta\phi)$ on the map. 63 151 64 152 .. note:: 65 Note that the form factors for oriented particles are also performing 66 numerical integrations over one or more variables, so care should be taken, 67 especially with very large particles or more extreme aspect ratios. In such 68 cases results may not be accurate, particularly at very high Q, unless the model 69 has been specifically coded to use limiting forms of the scattering equations. 70 71 For best numerical results keep the $\theta$ distribution narrower than the $\phi$ 72 distribution. Thus for asymmetric particles, such as elliptical_cylinder, you may 73 need to reorder the sizes of the three axes to acheive the desired result. 74 This is due to the issues of mapping a rectangular distribution onto the 75 surface of a sphere. 153 Note that the form factors for oriented particles are performing 154 numerical integrations over one or more variables, so care should be 155 taken, especially with very large particles or more extreme aspect 156 ratios. In such cases results may not be accurate, particularly at very 157 high Q, unless the model has been specifically coded to use limiting 158 forms of the scattering equations. 76 159 77 Users can experiment with the values of *Npts* and *Nsigs*, the number of steps 78 used in the integration and the range spanned in number of standard deviations. 79 The standard deviation is entered in units of degrees. For a "rectangular" 80 distribution the full width should be $\pm \sqrt(3)$ ~ 1.73 standard deviations. 81 The new "uniform" distribution avoids this by letting you directly specify the 160 For best numerical results keep the $\theta$ distribution narrower than 161 the $\phi$ distribution. Thus for asymmetric particles, such as 162 elliptical_cylinder, you may need to reorder the sizes of the three axes 163 to acheive the desired result. This is due to the issues of mapping a 164 rectanglar distribution onto the surface of a sphere. 165 166 Users can experiment with the values of *Npts* and *Nsigs*, the number of steps 167 used in the integration and the range spanned in number of standard deviations. 168 The standard deviation is entered in units of degrees. For a "rectangular" 169 distribution the full width should be $\pm \sqrt(3)$ ~ 1.73 standard deviations. 170 The new "uniform" distribution avoids this by letting you directly specify the 82 171 half width. 83 172 84 The angular distributions will be truncated outside of the range -180 to +18085 degrees, so beware of using saying a broad Gaussian distribution with large value86 of *Nsigs*, as the array of *Npts* may be truncated to many fewer points than would 87 give a good integration,as well as becoming rather meaningless. (At some point 88 in the future the actual polydispersity arrays may be made available to the user 89 for inspection.)173 The angular distributions may be truncated outside of the range -180 to +180 174 degrees, so beware of using saying a broad Gaussian distribution with large 175 value of *Nsigs*, as the array of *Npts* may be truncated to many fewer 176 points than would give a good integration,as well as becoming rather 177 meaningless. (At some point in the future the actual dispersion arrays may be 178 made available to the user for inspection.) 90 179 91 180 Some more detailed technical notes are provided in the developer section of 92 181 this manual :ref:`orientation_developer` . 93 182 183 This definition of orientation is new to SasView 4.2. In earlier versions, 184 the orientation distribution appeared as a distribution of view angles. 185 This led to strange effects when $c$ was aligned with $z$, where changes 186 to the $\phi$ angle served only to rotate the shape about $c$, rather than 187 having a consistent interpretation as the pitch of the shape relative to 188 the flow field defining the reference orientation. Prior to SasView 4.1, 189 the reference orientation was defined using a Tait-Bryan convention, making 190 it difficult to control. Now, rotation in $\theta$ modifies the spacings 191 in the refraction pattern, and rotation in $\phi$ rotates it in the detector 192 plane. 193 194 94 195 *Document History* 95 196 96 197 | 2017-11-06 Richard Heenan 198 | 2017-12-20 Paul Kienzle -
doc/guide/plugin.rst
rc654160 r7e6bc45e 538 538 If the scattering is dependent on the orientation of the shape, then you 539 539 will need to include *orientation* parameters *theta*, *phi* and *psi* 540 at the end of the parameter table. Shape orientation uses *a*, *b* and *c* 541 axes, corresponding to the *x*, *y* and *z* axes in the laboratory coordinate 542 system, with *z* along the beam and *x*-*y* in the detector plane, with *x* 543 horizontal and *y* vertical. The *psi* parameter rotates the shape 544 about its *c* axis, the *theta* parameter then rotates the *c* axis toward 545 the *x* axis of the detector, then *phi* rotates the shape in the detector 546 plane. (Prior to these rotations, orientation dispersity will be applied 547 as roll-pitch-yaw, rotating *c*, then *b* then *a* in the shape coordinate 548 system.) A particular *qx*, *qy* point on the detector, then corresponds 549 to *qa*, *qb*, *qc* with respect to the shape. 550 551 The oriented C model is called as *Iqabc(qa, qb, qc, par1, par2, ...)* where 540 at the end of the parameter table. As described in the section 541 :ref:`orientation`, the individual $(q_x, q_y)$ points on the detector will 542 be rotated into $(q_a, q_b, q_c)$ points relative to the sample in its 543 canonical orientation with $a$-$b$-$c$ aligned with $x$-$y$-$z$ in the 544 laboratory frame and beam travelling along $-z$. 545 546 The oriented C model is called using *Iqabc(qa, qb, qc, par1, par2, ...)* where 552 547 *par1*, etc. are the parameters to the model. If the shape is rotationally 553 548 symmetric about *c* then *psi* is not needed, and the model is called -
explore/jitter.py
rff10479 r8cfb486 165 165 # constants in kernel_iq.c 166 166 'equirectangular', 'sinusoidal', 'guyou', 'azimuthal_equidistance', 167 'azimuthal_equal_area', 167 168 ] 168 169 def draw_mesh(ax, view, jitter, radius=1.2, n=11, dist='gaussian', -
sasmodels/autoc.py
r67cc0ff r15be191 4 4 from __future__ import print_function 5 5 6 import ast7 6 import inspect 8 from functools import reduce9 7 10 8 import numpy as np … … 95 93 constants[name] = obj 96 94 # Claim all constants are declared on line 1 97 snippets.append('#line 1 "%s" '%escaped_filename)98 snippets.append( define_constant(name, obj))95 snippets.append('#line 1 "%s"\n'%escaped_filename) 96 snippets.append(py2c.define_constant(name, obj)) 99 97 elif isinstance(obj, special.Gauss): 100 98 for var, value in zip(("N", "Z", "W"), (obj.n, obj.z, obj.w)): 101 99 var = "GAUSS_"+var 102 100 constants[var] = value 103 snippets.append('#line 1 "%s" '%escaped_filename)104 snippets.append( define_constant(var, value))101 snippets.append('#line 1 "%s"\n'%escaped_filename) 102 snippets.append(py2c.define_constant(var, value)) 105 103 #libs.append('lib/gauss%d.c'%obj.n) 106 104 source = (source.replace(name+'.n', 'GAUSS_N') … … 121 119 122 120 # translate source 123 ordered_code = [code[name] for name in ordered_dag(depends) if name in code]121 ordered_code = [code[name] for name in py2c.ordered_dag(depends) if name in code] 124 122 functions = py2c.translate(ordered_code, constants) 125 123 snippets.extend(functions) … … 127 125 # update model info 128 126 info.source = unique_libs 129 info.c_code = " \n".join(snippets)127 info.c_code = "".join(snippets) 130 128 info.Iq = info.Iqac = info.Iqabc = info.Iqxy = info.form_volume = None 131 132 def define_constant(name, value):133 if isinstance(value, int):134 parts = ["int ", name, " = ", "%d"%value, ";"]135 elif isinstance(value, float):136 parts = ["double ", name, " = ", "%.15g"%value, ";"]137 else:138 # extend constant arrays to a multiple of 4; not sure if this139 # is necessary, but some OpenCL targets broke if the number140 # of parameters in the parameter table was not a multiple of 4,141 # so do it for all constant arrays to be safe.142 if len(value)%4 != 0:143 value = list(value) + [0.]*(4 - len(value)%4)144 elements = ["%.15g"%v for v in value]145 parts = ["double ", name, "[]", " = ",146 "{\n ", ", ".join(elements), "\n};"]147 return "".join(parts)148 149 150 # Modified from the following:151 #152 # http://code.activestate.com/recipes/578272-topological-sort/153 # Copyright (C) 2012 Sam Denton154 # License: MIT155 def ordered_dag(dag):156 # type: (Dict[T, Set[T]]) -> Iterator[T]157 dag = dag.copy()158 159 # make leaves depend on the empty set160 leaves = reduce(set.union, dag.values()) - set(dag.keys())161 dag.update({node: set() for node in leaves})162 while True:163 leaves = set(node for node, links in dag.items() if not links)164 if not leaves:165 break166 for node in leaves:167 yield node168 dag = {node: (links-leaves)169 for node, links in dag.items() if node not in leaves}170 if dag:171 raise ValueError("Cyclic dependes exists amongst these items:\n%s"172 % ", ".join(str(node) for node in dag.keys())) -
sasmodels/modelinfo.py
r67cc0ff r5ab99b7 794 794 info.structure_factor = getattr(kernel_module, 'structure_factor', False) 795 795 info.profile_axes = getattr(kernel_module, 'profile_axes', ['x', 'y']) 796 info.c_code = getattr(kernel_module, 'c_code', None)797 796 info.source = getattr(kernel_module, 'source', []) 798 797 info.c_code = getattr(kernel_module, 'c_code', None) … … 810 809 info.sesans = getattr(kernel_module, 'sesans', None) # type: ignore 811 810 # Default single and opencl to True for C models. Python models have callable Iq. 812 info.opencl = getattr(kernel_module, 'opencl', not callable(info.Iq))813 info.single = getattr(kernel_module, 'single', not callable(info.Iq))814 811 info.random = getattr(kernel_module, 'random', None) 815 812 … … 827 824 except Exception as exc: 828 825 logger.warn(str(exc) + " while converting %s from C to python"%name) 826 827 # Needs to come after autoc.convert since the Iq symbol may have been 828 # converted from python to C 829 info.opencl = getattr(kernel_module, 'opencl', not callable(info.Iq)) 830 info.single = getattr(kernel_module, 'single', not callable(info.Iq)) 829 831 830 832 if callable(info.Iq) and parameters.has_2d: -
sasmodels/models/_cylpy.py
r67cc0ff rc01ed3e 140 140 py2c = True 141 141 142 # TODO: "#define INVALID (expr)" is not supported 142 143 def invalid(v): 143 144 return v.radius < 0 or v.length < 0 … … 206 207 phi_pd=10, phi_pd_n=5) 207 208 208 qx, qy = 0.2 * np.cos(2.5), 0.2 * np.sin(2.5)209 qx, qy = 0.2 * cos(2.5), 0.2 * sin(2.5) 209 210 # After redefinition of angles, find new tests values. Was 10 10 in old coords 210 211 tests = [
Note: See TracChangeset
for help on using the changeset viewer.