Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-10 07:49:16

0001 #!/usr/bin/env python
0002 #
0003 # Copyright (c) 2019 Opticks Team. All Rights Reserved.
0004 #
0005 # This file is part of Opticks
0006 # (see https://bitbucket.org/simoncblyth/opticks).
0007 #
0008 # Licensed under the Apache License, Version 2.0 (the "License"); 
0009 # you may not use this file except in compliance with the License.  
0010 # You may obtain a copy of the License at
0011 #
0012 #   http://www.apache.org/licenses/LICENSE-2.0
0013 #
0014 # Unless required by applicable law or agreed to in writing, software 
0015 # distributed under the License is distributed on an "AS IS" BASIS, 
0016 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
0017 # See the License for the specific language governing permissions and 
0018 # limitations under the License.
0019 #
0020 
0021 """
0022 Genstep Sequence Material Mismatch
0023 ===================================
0024 
0025 Comparing material codes of the first intersection with the 
0026 material code of the genstep observe many mismatches.
0027 
0028 Current understanding of problem
0029 ------------------------------------
0030 
0031 ::
0032 
0033      GdLS     |Ac|   LS    |Ac|   MO
0034               |  |         |  |      
0035               |  |         |  |
0036        *---------x         |  |
0037               |  |         |  |
0038               |  |         |  | 
0039               |  |         |  |
0040        *------x  |         |  |
0041               |  |         |  |
0042 
0043 Many (~14%) photons with gensteps in Gd have a 1st boundary intersection 
0044 with Ac/LS when expected to intersect with Gd/Ac
0045 
0046 Questions
0047 -----------
0048 
0049 * geometric epsilon 
0050 * thin acrylic problem ?
0051 
0052   * make simplified geometry: concentric spheres (or boxes) with varying Ac thickness 
0053 
0054 Analytic Geometry
0055 -----------------
0056 
0057 * including GDML elements within in G4DAE exported COLLADA extra elements
0058   would provide the analytic geometry description needed to swap out 
0059   triangulated for analytic geometry in some cases
0060 
0061   * OpenGL needs triangulated, the analytic can be applied to OptiX geometry
0062 
0063 
0064 
0065 Confirmed Geometric Problem : inner AV top lid is not intersecting 
0066 --------------------------------------------------------------------
0067 
0068 Using a "torch" at AD center all photons with less than 0.31pi (AV top lid)
0069 to the zenith are not intersecting with Gd/Ac but rather Ac/LS.
0070 The problem area coincides with OpenGL renderering z-fighting flickering.  
0071 
0072 To chop out or focus on the problem area::
0073 
0074     ggv --torchconfig "zenith_azimuth:0.31,1.0,0,1"
0075     ggv --torchconfig "zenith_azimuth:0,0.31,0,1"
0076 
0077 Focus on just the problematic 1st step::
0078 
0079     ggv --torchconfig "zenith_azimuth:0,0.31,0,1" --bouncemax 1
0080 
0081 TODO: orthographic projection would be useful for eyeballing geometry in cross section 
0082 
0083 
0084 Material Codes
0085 -----------------
0086 
0087 *gs.MaterialIndex*
0088       from Geant4, converted into wavelength texture line number in G4StepNPY
0089 
0090 *m1/m2/su*
0091       OptiX intersects with a triangle, reading the assigned boundary code, sign 
0092       from cosTheta of angle between photon and triangle normal
0093       pulled from optical buffer using the absolute boundary code and its sign
0094       to map inner/outer to m1/m2 
0095 
0096 
0097 OptiX epsilon
0098 --------------
0099 
0100 ::
0101 
0102      324 void OEngine::preprocess()
0103      325 {
0104      326     LOG(info)<< "OEngine::preprocess";
0105      327 
0106      328     m_context[ "scene_epsilon"]->setFloat(m_composition->getNear());
0107      329 
0108      330     float pe = 0.1f ;
0109      331     m_context[ "propagate_epsilon"]->setFloat(pe);  // TODO: check impact of changing propagate_epsilon
0110      332 
0111 
0112 cu/generate.cu::
0113 
0114     171         rtTrace(top_object, optix::make_Ray(p.position, p.direction, propagate_ray_type, propagate_epsilon, RT_DEFAULT_MAX), prd );
0115 
0116 
0117 
0118 Extent of Problem : 9 percent
0119 -------------------------------
0120 
0121 Test using Aux buffer containing in 1st slot of each set of 10  
0122 
0123 * m1
0124 * m2
0125 * "m1" translated from genstep material line
0126 * signed boundary code
0127 
0128 ::
0129 
0130     In [1]: a = auc_(1).reshape(-1,10,4)
0131     INFO:opticks.ana.types:loading /usr/local/env/dayabay/aucerenkov/1.npy 
0132     -rw-r--r--  1 blyth  staff  49027360 Sep 19 13:01 /usr/local/env/dayabay/aucerenkov/1.npy
0133 
0134     In [39]: aa = a[:500000]   ## exclude tail where there are geometry misses (still using sub-geometry), so no boundary-m1 to compare with 
0135 
0136     # TODO: move to fuller geometry include radslabs around pool to avoid misses, can still skip RPC 
0137 
0138     In [40]: aa
0139     Out[40]: 
0140     array([[[  6,   6,   6, -12],     ## 1st and 3rd indices here should match  boundary-m1 and genstep-m1 
0141             [  6,  12,   4, -13],
0142             [ 12,   4,   0, -14],
0143             ..., 
0144             [  0,   0,   0,   0],
0145             [  0,   0,   0,   0],
0146             [  0,   0,   0,   0]],
0147 
0148 
0149     In [47]: ix = np.arange(len(aa))[aa[:,0,0] != aa[:,0,2]]
0150 
0151     In [48]: ix
0152     Out[48]: array([  3006,   8521,   8524, ..., 497348, 497349, 497350])
0153 
0154     In [49]: len(ix)
0155     Out[49]: 44479
0156 
0157     In [50]: len(aa)
0158     Out[50]: 500000
0159 
0160     In [54]: float(len(ix))/float(len(aa))   ## 9 percent level mismatch 
0161     Out[54]: 0.088958
0162 
0163 
0164 How often can match be made using material from other side of boundary ? Only 1 percent
0165 ----------------------------------------------------------------------------------------
0166 
0167 Suggests not a geometric normal (vertex winding order) problem. 
0168 
0169 ::
0170 
0171     In [58]: aa[:,0][ix]
0172     Out[58]: 
0173     array([[  4,  14,   6, -20],
0174            [  4,  11,   6, -23],
0175            [  4,  11,   6, -23],
0176            ..., 
0177            [  4,   3,   3, -25],
0178            [  4,  14,   3, -20],
0179            [  4,  14,   3, -20]], dtype=int16)
0180 
0181 ::
0182 
0183     In [64]: aaa = aa[:,0][ix]
0184 
0185     In [66]: farside = np.arange(len(aaa))[aaa[:,1] == aaa[:,2]]
0186 
0187     In [70]: float(len(farside))/len(aaa)
0188     Out[70]: 0.011398637559297646
0189 
0190 
0191 
0192 Is there preponderance of particular genstep materials with mismatch ? yes: Gd dominates
0193 -------------------------------------------------------------------------------------------
0194 
0195 ::
0196 
0197     In [81]: count_unique(aaa[:,2])
0198     Out[81]: 
0199     array([[    1, 43666],
0200            [    2,   419],
0201            [    3,   390],
0202            [    4,     1],
0203            [    6,     3]])
0204 
0205     In [82]: im_ = lambda _:im.get(_,'?')
0206 
0207     In [83]: map(im_,[1,2,3,4,6])
0208     Out[83]: ['GdDopedLS', 'LiquidScintillator', 'Acrylic', 'MineralOil', 'IwsWater']
0209 
0210 
0211 How about the boundary ?  predominantly imat:Acrylic omat:LiquidScintillator
0212 -------------------------------------------------------------------------------
0213 
0214 TODO: visualize where the problem is, suspect AD lids 
0215 
0216 ::
0217 
0218     In [85]: count_unique(aaa[:,3])
0219     Out[85]: 
0220     array([[  -25,   125],
0221            [  -23,     5],
0222            [  -21,     1],
0223            [  -20,    12],
0224            [  -18,   123],
0225            [  -17,   137],
0226            [  -16,     8],
0227            [  -15,    11],
0228            [   15,   411],
0229            [   16,   103],
0230            [   17, 43543]])     imat:Acrylic omat:LiquidScintillator
0231 
0232 ::
0233 
0234     delta:ggeo blyth$ ./GBoundaryLibMetadata.py 
0235     INFO:__main__:['./GBoundaryLibMetadata.py']
0236       0 :  1 :                      Vacuum                    Vacuum                         -                         - 
0237       1 :  2 :                        Rock                    Vacuum                         -                         - 
0238       2 :  3 :                         Air                      Rock                         -                         - 
0239       3 :  4 :                         PPE                       Air                         - __dd__Geometry__PoolDetails__NearPoolSurfaces__NearPoolCoverSurface 
0240       4 :  5 :                   Aluminium                       Air                         -                         - 
0241       5 :  6 :                        Foam                 Aluminium                         -                         - 
0242       6 :  7 :                         Air                       Air                         -                         - 
0243       7 :  8 :                   DeadWater                      Rock                         -                         - 
0244       8 :  9 :                       Tyvek                 DeadWater                         - __dd__Geometry__PoolDetails__NearPoolSurfaces__NearDeadLinerSurface 
0245       9 : 10 :                    OwsWater                     Tyvek __dd__Geometry__PoolDetails__NearPoolSurfaces__NearOWSLinerSurface                         - 
0246      10 : 11 :                       Tyvek                  OwsWater                         -                         - 
0247      11 : 12 :                    IwsWater                  IwsWater                         -                         - 
0248      12 : 13 :              StainlessSteel                  IwsWater                         - __dd__Geometry__AdDetails__AdSurfacesNear__SSTWaterSurfaceNear1 
0249      13 : 14 :                  MineralOil            StainlessSteel __dd__Geometry__AdDetails__AdSurfacesAll__SSTOilSurface                         - 
0250      14 : 15 :                     Acrylic                MineralOil                         -                         - 
0251      15 : 16 :          LiquidScintillator                   Acrylic                         -                         - 
0252      16 :*17*:                     Acrylic        LiquidScintillator                         -                         - 
0253      17 : 18 :                   GdDopedLS                   Acrylic                         -                         - 
0254      18 : 19 :                   GdDopedLS        LiquidScintillator                         -                         - 
0255      19 : 20 :                       Pyrex                MineralOil                  
0256 
0257 
0258 
0259 What boundaries do GdLs gensteps have ?
0260 ------------------------------------------
0261 
0262 ::
0263 
0264     In [96]: gd = np.arange(len(aa))[aa[:,0,2] == 1]
0265 
0266     In [97]: gd
0267     Out[97]: array([ 90402,  90403,  90404, ..., 453773, 453774, 453775])
0268 
0269     In [98]: aa[gd]
0270     Out[98]: 
0271     array([[[ 1,  3,  1, 18],
0272             [ 1,  3,  1, 18],
0273             [ 0,  0,  0,  0],
0274             ..., 
0275             [ 0,  0,  0,  0],
0276             [ 0,  0,  0,  0],
0277             [ 0,  0,  0,  0]],
0278 
0279     In [99]: aa[gd][:,0,3]
0280     Out[99]: array([18, 18, 18, ..., 17, 17, 17], dtype=int16)
0281 
0282     In [100]: count_unique(aa[gd][:,0,3])
0283     Out[100]: 
0284     array([[   -18,    123],
0285            [    17,  43543],
0286            [    18, 308763]])
0287 
0288 ::
0289 
0290     In [103]: 43543./308763.
0291     Out[103]: 0.14102402166062644
0292 
0293 ::
0294 
0295          +1
0296 
0297      16 :*17*:                     Acrylic        LiquidScintillator                         -                         - 
0298      17 :*18*:                   GdDopedLS                   Acrylic                         -                         - 
0299  
0300 
0301 
0302 What 1st boundaries do LS gensteps have ?  Only 0.4% mismatch
0303 ---------------------------------------------------------------
0304 
0305 Hmm low level mismatch ? Something special regards inner AV.
0306 
0307 ::
0308 
0309     In [105]: ls = np.arange(len(aa))[aa[:,0,2] == 2]
0310 
0311     In [125]: ac = np.arange(len(aa))[aa[:,0,2] == 3]
0312 
0313     In [106]: count_unique(aa[ls][:,0,3])
0314     Out[106]: 
0315     array([[  -17, 51348],   #  Ac/LS but negated so from Ls 
0316            [  -16,     8],   #  LS/Ac but negated so from Ac?  
0317            [   15,   411],   #  Ac/MO
0318            [   16, 43249]])  #  LS/Ac 
0319 
0320 
0321 ::
0322 
0323      GdLS     |Ac|       LS    |Ac|   MO
0324               |  |             |  |      
0325               |  | -17         |  |
0326               |  x------*      |  |
0327               |  |             |  |
0328               |  |             |  | 
0329               |  |        +16  |  |
0330               |  |      *------x  |
0331               |  |             |  |
0332 
0333 
0334 ::
0335 
0336          (+1)
0337      14 : 15 :                     Acrylic                MineralOil                         -                         - 
0338      15 : 16 :          LiquidScintillator                   Acrylic                         -                         - 
0339      16 :*17*:                     Acrylic        LiquidScintillator                         -                         - 
0340      17 : 18 :                   GdDopedLS                   Acrylic                         -                         - 
0341 
0342 ::
0343 
0344     In [116]: bb = aa[ls]
0345 
0346     In [119]: obb = np.arange(len(bb))[bb[:,0,0] != bb[:,0,2]]
0347 
0348     In [121]: len(obb)
0349     Out[121]: 419
0350     
0351 ::
0352 
0353     In [123]: float(len(obb))/len(bb)
0354     Out[123]: 0.004409783615391092
0355 
0356 
0357     
0358 First boundaries of Ac gensteps
0359 --------------------------------
0360 
0361 ::
0362 
0363     In [126]: acb = count_unique(aa[ac][:,0,3])
0364     Out[126]: 
0365     array([[ -25,  125],
0366            [ -23,    3],
0367            [ -20,   11],
0368            [ -18, 1977],
0369            [ -17,  137],
0370            [ -16, 1699],
0371            [ -15,   11],
0372            [  15, 1565],
0373            [  16,  103],
0374            [  17,  791]])
0375 
0376     In [173]: bnd = bnd_()
0377 
0378     In [168]: bd_ = lambda _:bnd[_]
0379 
0380     In [174]: map(bd_, acb[:,0] )
0381     Out[174]: 
0382     [u'(-25) Acrylic/MineralOil/-/RSOilSurface ',
0383      u'(-23) UnstStainlessSteel/MineralOil/-/- ',
0384      u'(-20) Pyrex/MineralOil/-/- ',
0385      u'(-18) GdDopedLS/Acrylic/-/- ',
0386      u'(-17) Acrylic/LiquidScintillator/-/- ',
0387      u'(-16) LiquidScintillator/Acrylic/-/- ',
0388      u'(-15) Acrylic/MineralOil/-/- ',
0389      u'(+15) Acrylic/MineralOil/-/- ',
0390      u'(+16) LiquidScintillator/Acrylic/-/- ',
0391      u'(+17) Acrylic/LiquidScintillator/-/- ']
0392      
0393 
0394 Observations from Aux buffer : boundary 0 (MISS)
0395 -------------------------------------------------
0396 
0397 ::
0398 
0399     In [1]: a = auc_(1).reshape(-1,10,4)
0400     INFO:opticks.ana.types:loading /usr/local/env/dayabay/aucerenkov/1.npy 
0401     -rw-r--r--  1 blyth  staff  49027360 Sep 19 11:59 /usr/local/env/dayabay/aucerenkov/1.npy
0402 
0403     In [2]: a
0404     Out[2]: 
0405     array([[[  6,   6,   0, -12],
0406             [  6,  12,   4, -13],
0407             [ 12,   4,   0, -14],
0408             ..., 
0409             [  0,   0,   0,   0],
0410             [  0,   0,   0,   0],
0411             [  0,   0,   0,   0]],
0412 
0413 
0414     In [7]: im = imat_()
0415     INFO:opticks.ana.types:parsing json for key ~/.opticks/GMaterialIndexLocal.json
0416 
0417     In [11]: map(lambda _:im[_], [6,6,6,12,12,4] )
0418     Out[11]: 
0419     ['IwsWater',
0420      'IwsWater',
0421      'IwsWater',
0422      'StainlessSteel',
0423      'StainlessSteel',
0424      'MineralOil']
0425 
0426 
0427 
0428 
0429 
0430 
0431 
0432 What could go wrong ? The normal ?
0433 ------------------------------------
0434 
0435 Winding order of vertex indices in indexBuffer determines the sidedness
0436 of the triangle (ie in/out direction of the normal).
0437 
0438 TODO: duplicate normal calc in geometry shader to visualize the normals
0439 
0440 
0441 env/graphics/optixrap/cu/TriangleMesh.cu::
0442 
0443      34 RT_PROGRAM void mesh_intersect(int primIdx)
0444      35 {
0445      36     int3 index = indexBuffer[primIdx];
0446      37 
0447      38     //  tried flipping vertex order in unsuccessful attempt to 
0448      39     //  get normal shader colors to match OpenGL
0449      40     //  observe with touch mode that n.z often small
0450      41     //  ... this is just because surfaces are very often vertical
0451      42     //
0452      43     float3 p0 = vertexBuffer[index.x];
0453      44     float3 p1 = vertexBuffer[index.y];
0454      45     float3 p2 = vertexBuffer[index.z];
0455      46 
0456      47     float3 n;
0457      48     float  t, beta, gamma;
0458      49     if(intersect_triangle(ray, p0, p1, p2, n, t, beta, gamma))
0459      50     {
0460      51         if(rtPotentialIntersection( t ))
0461      52         {
0462      53             // attributes should be set between rtPotential and rtReport
0463      54             geometricNormal = normalize(n);
0464      55 
0465      56             nodeIndex = nodeBuffer[primIdx];
0466      57             boundaryIndex = boundaryBuffer[primIdx];
0467      58             sensorIndex = sensorBuffer[primIdx];
0468      59 
0469      60             // doing calculation here might (depending on OptiX compiler cleverness) 
0470      61             // repeat for all intersections encountered unnecessarily   
0471      62             // instead move the calculation into closest_hit
0472      63             //
0473      64             // intersectionPosition = ray.origin + t*ray.direction  ; 
0474      65             // http://en.wikipedia.org/wiki/Line–plane_intersection
0475      66 
0476      67             rtReportIntersection(0);
0477 
0478 
0479 
0480 
0481 /Developer/OptiX/include/optixu/optixu_math_namespace.h::
0482 
0483     2022 /** Intersect ray with CCW wound triangle.  Returns non-normalize normal vector. */
0484     2023 OPTIXU_INLINE RT_HOSTDEVICE bool intersect_triangle(const Ray&    ray,
0485     2024                                                     const float3& p0,
0486     2025                                                     const float3& p1,
0487     2026                                                     const float3& p2,
0488     2027                                                           float3& n,
0489     2028                                                           float&  t,
0490     2029                                                           float&  beta,
0491     2030                                                           float&  gamma)
0492     2031 {
0493     2032   return intersect_triangle_branchless(ray, p0, p1, p2, n, t, beta, gamma);
0494     2033 }
0495     ....
0496     1956 /** Branchless intesection avoids divergence.
0497     1957 */
0498     1958 OPTIXU_INLINE RT_HOSTDEVICE bool intersect_triangle_branchless(const Ray&    ray,
0499     1959                                                                const float3& p0,
0500     1960                                                                const float3& p1,
0501     1961                                                                const float3& p2,
0502     1962                                                                      float3& n,
0503     1963                                                                      float&  t,
0504     1964                                                                      float&  beta,
0505     1965                                                                      float&  gamma)
0506     1966 {
0507     1967   const float3 e0 = p1 - p0;
0508     1968   const float3 e1 = p0 - p2;
0509     1969   n  = cross( e1, e0 );
0510     1970 
0511     1971   const float3 e2 = ( 1.0f / dot( n, ray.direction ) ) * ( p0 - ray.origin );
0512     1972   const float3 i  = cross( ray.direction, e2 );
0513     1973 
0514     1974   beta  = dot( i, e1 );
0515     1975   gamma = dot( i, e0 );
0516     1976   t     = dot( n, e2 );
0517     1977 
0518     1978   return ( (t<ray.tmax) & (t>ray.tmin) & (beta>=0.0f) & (gamma>=0.0f) & (beta+gamma<=1) );
0519     1979 }
0520 
0521 
0522 
0523 
0524 """
0525 
0526 import sys
0527 import numpy as np
0528 from opticks.ana.types import phc_, iflags_, imat_, iabmat_, ihex_, seqhis_, seqmat_, stc_, c2g_
0529 
0530 
0531 def sequence(h,a,b, gm, qm):
0532     #np.set_printoptions(formatter={'int':lambda x:hex(int(x))})
0533    
0534     im = imat_()
0535 
0536     for i,p in enumerate(h[a:b]):
0537         ix = a+i
0538         his,mat = p[0],p[1]
0539         print " %7d : %16s %16s : %30s %30s : %10s %10s " % ( ix,ihex_(his),ihex_(mat), 
0540                    seqhis_(his), seqmat_(mat),
0541                    im[gm[ix]], im[qm[ix]] 
0542                   )    
0543 
0544 
0545 if __name__ == '__main__':
0546 
0547     tag = 1 
0548 
0549     gs = stc_(tag)                                       # gensteps 
0550     seq = phc_(tag).reshape(-1,2)                        # flag,material sequence
0551     c2g = c2g_()                                      # chroma index to ggeo custom int
0552     im = iabmat_()
0553 
0554     gsnph = gs.view(np.int32)[:,0,3]                     # genstep: num photons 
0555     gspdg = gs.view(np.int32)[:,3,0]
0556 
0557     gsmat_c = gs.view(np.int32)[:,0,2]                     # genstep: material code  : in chroma material map lingo
0558     gsmat   = np.array( map(lambda _:c2g.get(_,-1), gsmat_c ), dtype=np.int32)   # translate chroma indices into ggeo custom ones
0559 
0560 
0561     p_gsmat   = np.repeat(gsmat, gsnph)                    # photon: genstep material code  
0562     p_seqmat = seq[:,1] & 0xF                             # first material in seqmat 
0563     off = np.arange(len(p_gsmat))[ p_gsmat != p_seqmat ]
0564 
0565     p_gsidx = np.repeat(np.arange(len(gsnph)), gsnph )    # photon: genstep index
0566 
0567 
0568     #n = len(sys.argv)
0569     #a = int(sys.argv[1]) if n > 1 else 0
0570     #b = int(sys.argv[2]) if n > 2 else a + 40
0571     #
0572     #print n,a,b
0573     #sequence(seq,a,b, p_gsmat, p_seqmat)
0574 
0575     for i in off:
0576         his,mat = seq[i,0],seq[i,1]
0577         seqhis = seqhis_(his)
0578         if 'MI' in seqhis:continue
0579         print " %7d : %16s %16s : %30s %30s : gs:%2s sq:%2s " % ( i,ihex_(his),ihex_(mat), 
0580                    seqhis, seqmat_(mat),
0581                    im[p_gsmat[i]], im[p_seqmat[i]] 
0582                   )    
0583 
0584 
0585 
0586 
0587    
0588 
0589 
0590 
0591