Changeset 4991048 in sasmodels


Ignore:
Timestamp:
Nov 1, 2017 4:16:45 PM (6 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
f475f90
Parents:
3a1fc7d
Message:

set projection used in theory to that selected in jitter.py

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • explore/jitter.py

    rde71632 r4991048  
    162162 
    163163PROJECTIONS = [ 
    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', 
    165167] 
    166168def draw_mesh(ax, view, jitter, radius=1.2, n=11, dist='gaussian', 
     
    239241        raise ValueError("expected dist to be gaussian, rectangle or uniform") 
    240242 
    241     if projection == 'equirectangular': 
     243    if projection == 'equirectangular':  #define PROJECTION 1 
    242244        def rotate(theta_i, phi_j): 
    243245            return Rx(phi_j)*Ry(theta_i) 
    244246        def weight(theta_i, phi_j, wi, wj): 
    245247            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 
    247269        def rotate(theta_i, phi_j): 
    248270            latitude = sqrt(theta_i**2 + phi_j**2) 
     
    282304            w = sin(radians(latitude))/latitude if latitude != 0 else 1 
    283305            return w*wi*wj if latitude < 180 else 0 
    284     elif projection == 'sinusoidal': 
    285         def rotate(theta_i, phi_j): 
    286             latitude = theta_i 
    287             scale = cos(radians(latitude)) 
    288             longitude = phi_j/scale if abs(phi_j) < abs(scale)*180 else 0 
    289             #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_i 
    293             scale = cos(radians(latitude)) 
    294             w = 1 if abs(phi_j) < abs(scale)*180 else 0 
    295             return w*wi*wj 
    296306    elif projection == 'azimuthal_equal_area': 
    297307        def rotate(theta_i, phi_j): 
     
    305315            w = sin(radians(latitude))/latitude if latitude != 0 else 1 
    306316            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_invert 
    310             #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*wj 
    315317    else: 
    316318        raise ValueError("unknown projection %r"%projection) 
     
    490492        vmin, vmax = calculator.limits 
    491493    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') 
    493497    #print("range",(vmin,vmax)) 
    494498    #qx, qy = np.meshgrid(qx, qy) 
     
    605609    *model_name* is one of the models available in :func:`select_model`. 
    606610    """ 
     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 
    607619    # set up calculator 
    608620    calculator, size = select_calculator(model_name, n=150, size=size) 
  • sasmodels/generate.py

    r6773b02 r4991048  
    179179except ImportError: 
    180180    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. 
     184PROJECTION = 1 
    181185 
    182186def get_data_path(external_dir, target_file): 
     
    764768    source.append("#define NUM_MAGNETIC %d" % partable.nmagnetic) 
    765769    source.append("#define MAGNETIC_PARS %s"%",".join(str(k) for k in magpars)) 
     770    source.append("#define PROJECTION %d"%PROJECTION) 
    766771 
    767772    # TODO: allow mixed python/opencl kernels? 
  • sasmodels/kernel_iq.c

    r767dca8 r4991048  
    3232//  INVALID(table) : test if the current point is feesible to calculate.  This 
    3333//      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. 
    4436 
    4537#ifndef _PAR_BLOCK_ // protected block so we can include this code twice. 
     
    457449// capture the differences in one spot so the rest of the code is easier 
    458450// to read. 
     451 
    459452#if defined(CALL_IQ) 
    460453  // unoriented 1D 
    461454  double qk; 
    462   #define SCALE_DPHI_AND_SET_WEIGHT() const double weight=weight0 
    463455  #define FETCH_Q() do { qk = q[q_index]; } while (0) 
    464456  #define BUILD_ROTATION() do {} while(0) 
     
    469461  // unoriented 2D 
    470462  double qx, qy; 
    471   #define SCALE_DPHI_AND_SET_WEIGHT() const double weight=weight0 
    472463  #define FETCH_Q() do { qx = q[2*q_index]; qy = q[2*q_index+1]; } while (0) 
    473464  #define BUILD_ROTATION() do {} while(0) 
     
    481472  double qa, qc; 
    482473  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. 
    506475  #define BUILD_ROTATION() qac_rotation(&rotation, theta, phi, dtheta, dphi); 
    507476  #define APPLY_ROTATION() qac_apply(rotation, qx, qy, &qa, &qc) 
     
    514483  double qa, qb, qc; 
    515484  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 
    516500  // Grab the "view" angles (theta, phi, psi) from the initial parameter table. 
    517   // These are separate from the "jitter" angles (dtheta, dphi, dpsi) which are 
    518   // stored with the dispersity values and copied to the local parameter 
    519   // table as we go through the mesh. 
    520501  const double theta = values[details->theta_par+2]; 
    521502  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 { \ 
    526509      dtheta = local_values.table.theta; \ 
    527510      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; \ 
    529517      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); \ 
    531519      else if (dphi != 0.0) weight = 0.; \ 
    532520      if (fabs(dphi) >= 180.) weight = 0.; \ 
    533521    } while (0) 
    534   #else 
    535     #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) 
    541522  #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 
    547525 
    548526// ====== construct the loops ======= 
     
    596574 
    597575//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(); 
    599576 
    600577  // ====== loop body ======= 
     
    603580  #endif 
    604581  { 
     582     APPLY_PROJECTION(); 
     583 
    605584    // Accumulate I(q) 
    606585    // Note: weight==0 must always be excluded 
     
    697676#undef PD_OPEN 
    698677#undef PD_CLOSE 
    699 #undef SCALE_DPHI_AND_SET_WEIGHT 
    700678#undef FETCH_Q 
     679#undef APPLY_PROJECTION 
    701680#undef BUILD_ROTATION 
    702681#undef APPLY_ROTATION 
Note: See TracChangeset for help on using the changeset viewer.