Changeset ff10479 in sasmodels
- Timestamp:
- Nov 2, 2017 4:27:16 PM (7 years ago)
- Branches:
- master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 9d9fcbd
- Parents:
- cf8b630
- git-author:
- Paul Kienzle <pkienzle@…> (11/01/17 18:16:45)
- git-committer:
- Paul Kienzle <pkienzle@…> (11/02/17 16:27:16)
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
explore/jitter.py
rde71632 rff10479 162 162 163 163 PROJECTIONS = [ 164 'equirectangular', 'azimuthal_equidistance', 'sinusoidal', 'guyou', 164 # in order of PROJECTION number; do not change without updating the 165 # constants in kernel_iq.c 166 'equirectangular', 'sinusoidal', 'guyou', 'azimuthal_equidistance', 165 167 ] 166 168 def draw_mesh(ax, view, jitter, radius=1.2, n=11, dist='gaussian', … … 239 241 raise ValueError("expected dist to be gaussian, rectangle or uniform") 240 242 241 if projection == 'equirectangular': 243 if projection == 'equirectangular': #define PROJECTION 1 242 244 def rotate(theta_i, phi_j): 243 245 return Rx(phi_j)*Ry(theta_i) 244 246 def weight(theta_i, phi_j, wi, wj): 245 247 return wi*wj*abs(cos(radians(theta_i))) 246 elif projection == 'azimuthal_equidistance': 248 elif projection == 'sinusoidal': #define PROJECTION 2 249 def rotate(theta_i, phi_j): 250 latitude = theta_i 251 scale = cos(radians(latitude)) 252 longitude = phi_j/scale if abs(phi_j) < abs(scale)*180 else 0 253 #print("(%+7.2f, %+7.2f) => (%+7.2f, %+7.2f)"%(theta_i, phi_j, latitude, longitude)) 254 return Rx(longitude)*Ry(latitude) 255 def weight(theta_i, phi_j, wi, wj): 256 latitude = theta_i 257 scale = cos(radians(latitude)) 258 w = 1 if abs(phi_j) < abs(scale)*180 else 0 259 return w*wi*wj 260 elif projection == 'guyou': #define PROJECTION 3 (eventually?) 261 def rotate(theta_i, phi_j): 262 from guyou import guyou_invert 263 #latitude, longitude = guyou_invert([theta_i], [phi_j]) 264 longitude, latitude = guyou_invert([phi_j], [theta_i]) 265 return Rx(longitude[0])*Ry(latitude[0]) 266 def weight(theta_i, phi_j, wi, wj): 267 return wi*wj 268 elif projection == 'azimuthal_equidistance': # Note: Rz Ry, not Rx Ry 247 269 def rotate(theta_i, phi_j): 248 270 latitude = sqrt(theta_i**2 + phi_j**2) … … 282 304 w = sin(radians(latitude))/latitude if latitude != 0 else 1 283 305 return w*wi*wj if latitude < 180 else 0 284 elif projection == 'sinusoidal':285 def rotate(theta_i, phi_j):286 latitude = theta_i287 scale = cos(radians(latitude))288 longitude = phi_j/scale if abs(phi_j) < abs(scale)*180 else 0289 #print("(%+7.2f, %+7.2f) => (%+7.2f, %+7.2f)"%(theta_i, phi_j, latitude, longitude))290 return Rx(longitude)*Ry(latitude)291 def weight(theta_i, phi_j, wi, wj):292 latitude = theta_i293 scale = cos(radians(latitude))294 w = 1 if abs(phi_j) < abs(scale)*180 else 0295 return w*wi*wj296 306 elif projection == 'azimuthal_equal_area': 297 307 def rotate(theta_i, phi_j): … … 305 315 w = sin(radians(latitude))/latitude if latitude != 0 else 1 306 316 return w*wi*wj if latitude < 180 else 0 307 elif projection == 'guyou':308 def rotate(theta_i, phi_j):309 from guyou import guyou_invert310 #latitude, longitude = guyou_invert([theta_i], [phi_j])311 longitude, latitude = guyou_invert([phi_j], [theta_i])312 return Rx(longitude[0])*Ry(latitude[0])313 def weight(theta_i, phi_j, wi, wj):314 return wi*wj315 317 else: 316 318 raise ValueError("unknown projection %r"%projection) … … 490 492 vmin, vmax = calculator.limits 491 493 else: 492 vmin, vmax = clipped_range(Iqxy, portion=0.95, mode='top') 494 vmax = Iqxy.max() 495 vmin = vmax*10**-7 496 #vmin, vmax = clipped_range(Iqxy, portion=portion, mode='top') 493 497 #print("range",(vmin,vmax)) 494 498 #qx, qy = np.meshgrid(qx, qy) … … 605 609 *model_name* is one of the models available in :func:`select_model`. 606 610 """ 611 # projection number according to 1-order position in list, but 612 # only 1 and 2 are implemented so far. 613 from sasmodels import generate 614 generate.PROJECTION = PROJECTIONS.index(projection) + 1 615 if generate.PROJECTION > 2: 616 print("*** PROJECTION %s not implemented in scattering function ***"%projection) 617 generate.PROJECTION = 2 618 607 619 # set up calculator 608 620 calculator, size = select_calculator(model_name, n=150, size=size) -
sasmodels/generate.py
r6773b02 rff10479 179 179 except ImportError: 180 180 pass 181 182 # jitter projection to use in the kernel code. See explore/jitter.py 183 # for details. To change it from a program, set generate.PROJECTION. 184 PROJECTION = 1 181 185 182 186 def get_data_path(external_dir, target_file): … … 764 768 source.append("#define NUM_MAGNETIC %d" % partable.nmagnetic) 765 769 source.append("#define MAGNETIC_PARS %s"%",".join(str(k) for k in magpars)) 770 source.append("#define PROJECTION %d"%PROJECTION) 766 771 767 772 # TODO: allow mixed python/opencl kernels? -
sasmodels/kernel_iq.c
r767dca8 rff10479 32 32 // INVALID(table) : test if the current point is feesible to calculate. This 33 33 // will be defined in the kernel definition file. 34 35 // Set SCALED_PHI to 1 if dphi represents distance rather than longitude. 36 // That is, in order to make an equally spaced mesh on a curved surface, 37 // you will need to scale longitude displacement by cos(latitude) to account 38 // for the reduction in distance per degree latitude as you move away from 39 // the equator. Points on the mesh with scaled dphi values more than 180 40 // degrees are not included in the dispersity calculation. This should make 41 // the integral over the entire surface work by sampling fewer points near 42 // the poles. 43 # define USE_SCALED_DPHI 1 34 // PROJECTION : equirectangular=1, sinusoidal=2 35 // see explore/jitter.py for definitions. 44 36 45 37 #ifndef _PAR_BLOCK_ // protected block so we can include this code twice. … … 457 449 // capture the differences in one spot so the rest of the code is easier 458 450 // to read. 451 459 452 #if defined(CALL_IQ) 460 453 // unoriented 1D 461 454 double qk; 462 #define SCALE_DPHI_AND_SET_WEIGHT() const double weight=weight0463 455 #define FETCH_Q() do { qk = q[q_index]; } while (0) 464 456 #define BUILD_ROTATION() do {} while(0) … … 469 461 // unoriented 2D 470 462 double qx, qy; 471 #define SCALE_DPHI_AND_SET_WEIGHT() const double weight=weight0472 463 #define FETCH_Q() do { qx = q[2*q_index]; qy = q[2*q_index+1]; } while (0) 473 464 #define BUILD_ROTATION() do {} while(0) … … 481 472 double qa, qc; 482 473 QACRotation rotation; 483 // Grab the "view" angles (theta, phi) from the initial parameter table. 484 // These are separate from the "jitter" angles (dtheta, dphi) which are 485 // stored with the dispersity values and copied to the local parameter 486 // table as we go through the mesh. 487 const double theta = values[details->theta_par+2]; 488 const double phi = values[details->theta_par+3]; 489 double dtheta, dphi, weight; 490 #if USE_SCALED_DPHI 491 #define SCALE_DPHI_AND_SET_WEIGHT() do { \ 492 dtheta = local_values.table.theta; \ 493 dphi = local_values.table.phi; \ 494 weight = weight0; \ 495 if (dtheta != 90.0) dphi /= fabs(cos(dtheta*M_PI_180)); \ 496 else if (dphi != 0.0) weight = 0.; \ 497 if (fabs(dphi) >= 180.) weight = 0.; \ 498 } while (0) 499 #else 500 #define SCALE_DPHI_AND_SET_WEIGHT() do { \ 501 dtheta = local_values.table.theta; \ 502 dphi = local_values.table.phi; \ 503 weight = fabs(cos(dtheta*M_PI_180)) * weight0; \ 504 } while (0) 505 #endif 474 // theta, phi, dtheta, dphi are defined below in projection to avoid repeated code. 506 475 #define BUILD_ROTATION() qac_rotation(&rotation, theta, phi, dtheta, dphi); 507 476 #define APPLY_ROTATION() qac_apply(rotation, qx, qy, &qa, &qc) … … 514 483 double qa, qb, qc; 515 484 QABCRotation rotation; 485 // theta, phi, dtheta, dphi are defined below in projection to avoid repeated code. 486 // psi and dpsi are only for IQ_ABC, so they are processed here. 487 const double psi = values[details->theta_par+4]; 488 #define BUILD_ROTATION() qabc_rotation(&rotation, theta, phi, psi, dtheta, dphi, local_values.table.psi) 489 #define APPLY_ROTATION() qabc_apply(rotation, qx, qy, &qa, &qb, &qc) 490 #define CALL_KERNEL() CALL_IQ_ABC(qa, qb, qc, local_values.table) 491 #endif 492 493 // Doing jitter projection code outside the previous if block so that we don't 494 // need to repeat the identical logic in the IQ_AC and IQ_ABC branches. This 495 // will become more important if we implement more projections, or more 496 // complicated projections. 497 #if defined(CALL_IQ) || defined(CALL_IQ_A) 498 #define APPLY_PROJECTION() const double weight=weight0 499 #else // !spherosymmetric projection 516 500 // Grab the "view" angles (theta, phi, psi) from the initial parameter table. 517 // These are separate from the "jitter" angles (dtheta, dphi, dpsi) which are518 // stored with the dispersity values and copied to the local parameter519 // table as we go through the mesh.520 501 const double theta = values[details->theta_par+2]; 521 502 const double phi = values[details->theta_par+3]; 522 const double psi = values[details->theta_par+4]; 523 double dtheta, dphi, dpsi, weight; 524 #if USE_SCALED_DPHI 525 #define SCALE_DPHI_AND_SET_WEIGHT() do { \ 503 // The "jitter" angles (dtheta, dphi, dpsi) are stored with the 504 // dispersity values and copied to the local parameter table as 505 // we go through the mesh. 506 double dtheta, dphi, weight; 507 #if PROJECTION == 1 508 #define APPLY_PROJECTION() do { \ 526 509 dtheta = local_values.table.theta; \ 527 510 dphi = local_values.table.phi; \ 528 dpsi = local_values.table.psi; \ 511 weight = fabs(cos(dtheta*M_PI_180)) * weight0; \ 512 } while (0) 513 #elif PROJECTION == 2 514 #define APPLY_PROJECTION() do { \ 515 dtheta = local_values.table.theta; \ 516 dphi = local_values.table.phi; \ 529 517 weight = weight0; \ 530 if (dtheta != 90.0) dphi /= fabs(cos(dtheta*M_PI_180)); \518 if (dtheta != 90.0) dphi /= cos(dtheta*M_PI_180); \ 531 519 else if (dphi != 0.0) weight = 0.; \ 532 520 if (fabs(dphi) >= 180.) weight = 0.; \ 533 521 } while (0) 534 #else535 #define SCALE_DPHI_AND_SET_WEIGHT() do { \536 dtheta = local_values.table.theta; \537 dphi = local_values.table.phi; \538 dpsi = local_values.table.psi; \539 weight = fabs(cos(dtheta*M_PI_180)) * weight0; \540 } while (0)541 522 #endif 542 #define BUILD_ROTATION() qabc_rotation(&rotation, theta, phi, psi, dtheta, dphi, dpsi) 543 #define APPLY_ROTATION() qabc_apply(rotation, qx, qy, &qa, &qb, &qc) 544 #define CALL_KERNEL() CALL_IQ_ABC(qa, qb, qc, local_values.table) 545 546 #endif 523 #endif // !spherosymmetric projection 524 547 525 548 526 // ====== construct the loops ======= … … 596 574 597 575 //if (q_index==0) {printf("step:%d of %d, pars:",step,pd_stop); for (int i=0; i < NUM_PARS; i++) printf("p%d=%g ",i, local_values.vector[i]); printf("\n");} 598 SCALE_DPHI_AND_SET_WEIGHT();599 576 600 577 // ====== loop body ======= … … 603 580 #endif 604 581 { 582 APPLY_PROJECTION(); 583 605 584 // Accumulate I(q) 606 585 // Note: weight==0 must always be excluded … … 697 676 #undef PD_OPEN 698 677 #undef PD_CLOSE 699 #undef SCALE_DPHI_AND_SET_WEIGHT700 678 #undef FETCH_Q 679 #undef APPLY_PROJECTION 701 680 #undef BUILD_ROTATION 702 681 #undef APPLY_ROTATION
Note: See TracChangeset
for help on using the changeset viewer.