Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #!/usr/bin/env python
0002 """
0003 tests/CSGOptiXSimtraceTest.py
0004 ==============================
0005 
0006 * see notes/issues/simtrace-shakedown.rst
0007 
0008 
0009 See also:
0010 
0011 csg/tests/CSGFoundry_MakeCenterExtentGensteps_Test.sh
0012 
0013 
0014 This allows interactive visualization of workstation 
0015 generated intersect data fphoton.npy on remote machines such as 
0016 user laptops that support pyvista. 
0017 
0018 
0019 FEAT envvar controlling intersect coloring and legend titles
0020 --------------------------------------------------------------
0021 
0022 pid
0023     uses cf.primIdx_meshname_dict()
0024 bnd
0025     uses cf.sim.bndnamedict
0026 ins
0027     uses cf.insnamedict
0028 
0029     instance identity : less different feature colors normally 
0030     but interesting to see what is in which instance and what is in ins0 the global instance, 
0031     the legend names are for example : ins37684 ins42990 ins0 ins43029
0032 
0033 
0034 ISEL envvar selects simtrace geometry intersects by their features, according to frequency order
0035 -------------------------------------------------------------------------------------------------------
0036 
0037 FEAT=ins ISEL=0
0038     only show the instance with the most intersects
0039 FEAT=ins ISEL=0,1
0040     only show the two instances with the most and 2nd most intersects
0041 FEAT=bnd ISEL=0,1
0042     ditto for boundaries
0043 
0044 FEAT=pid ISEL=0,1
0045 
0046 
0047 
0048 pyvista GUI keys
0049 ----------------------
0050 
0051 * https://docs.pyvista.org/api/plotting/plotting.html
0052 
0053 * to zoom out/in : slide two fingers up/down on trackpad. 
0054 * to pan : hold down shift and one finger tap-lock, then move finger around  
0055 
0056 
0057 Too many items in the legend
0058 -----------------------------
0059 
0060 When not using MASK=pos the legend may be filled with feature item lines 
0061 that are not visible in the frame 
0062 
0063 
0064 FramePhotons vs Photons
0065 ---------------------------
0066 
0067 Using frame photons is a trick to effectively see results 
0068 from many more photons that have to pay the costs for transfers etc.. 
0069 Frame photons lodge photons onto a frame of pixels limiting 
0070 the maximumm number of photons to handle. 
0071 
0072 ISEL allows plotting of a selection of feature values only, picked by descending frequency index
0073 -------------------------------------------------------------------------------------------------
0074 
0075 ::
0076 
0077     cx ; ./cxs_Hama.sh  grab
0078     cx ; ./cxs_Hama.sh  ana 
0079 
0080 Old instructions, not recently exercised::
0081 
0082     cx ; ./cxs_grab.sh   ## NO LONGER USED ?
0083 
0084     ISEL=0,1         ./cxs.sh    # ISEL=0,1 picks the 2 most frequent feature values (eg boundaries when FEAT=bnd)
0085     ISEL=0,1,2,3,4   ./cxs.sh 
0086 
0087     ISEL=Hama        ./cxs.sh    # select boundaries via strings in the bndnames, assuming FEAT=bnd
0088     ISEL=NNVT        ./cxs.sh 
0089     ISEL=Pyrex       ./cxs.sh 
0090     ISEL=Pyrex,Water ./cxs.sh 
0091 
0092 
0093 """
0094 import os, sys, logging, numpy as np
0095 np.set_printoptions(suppress=True, edgeitems=5, linewidth=200,precision=3)
0096 log = logging.getLogger(__name__)
0097 
0098 from opticks.ana.eget import efloatlist_, elookce_, elook_epsilon_, eint_
0099 
0100 SIZE = np.array([1280, 720])   ## SIZE*2 [2560, 1440]
0101 XCOMPARE_SIMPLE = "XCOMPARE_SIMPLE" in os.environ
0102 XCOMPARE = "XCOMPARE" in os.environ
0103 GUI = not "NOGUI" in os.environ
0104 MP =  not "NOMP" in os.environ 
0105 PV =  not "NOPV" in os.environ 
0106 PVGRID = not "NOPVGRID" in os.environ
0107 LEGEND =  not "NOLEGEND" in os.environ # when not MASK=pos legend often too many lines, so can switch it off 
0108 SIMPLE = "SIMPLE" in os.environ
0109 MASK = os.environ.get("MASK", "pos")
0110 FEAT = os.environ.get("FEAT", "pid" )  
0111 ALLOWED_MASK = ("pos", "t", "non" )
0112 assert MASK in ALLOWED_MASK, "MASK %s is not in ALLOWED_MASK list %s " % (MASK, str(ALLOWED_MASK))
0113 GSPLOT = eint_("GSPLOT", "0")
0114 PIDX = eint_("PIDX", "0")
0115 
0116 
0117 from opticks.CSG.CSGFoundry import CSGFoundry 
0118 from opticks.ana.p import *       # including cf loaded from CFBASE
0119 from opticks.ana.fold import Fold
0120 from opticks.ana.feature import SimtraceFeatures
0121 from opticks.ana.simtrace_positions import SimtracePositions
0122 from opticks.ana.simtrace_plot import SimtracePlot
0123 from opticks.ana.framegensteps import FrameGensteps
0124 from opticks.ana.npmeta import NPMeta
0125 from opticks.sysrap.sframe import sframe , X, Y, Z
0126 from opticks.ana.pvplt import * 
0127 
0128 import matplotlib
0129 if GUI == False:
0130     log.info("set pdf backend as GUI False")
0131     matplotlib.use("agg")
0132 pass
0133 
0134 if MP:
0135     try:
0136         import matplotlib.pyplot as mp
0137     except ImportError:
0138         mp = None
0139     pass
0140 else:
0141     mp = None
0142 pass
0143 
0144 if PV:
0145     try:
0146         import pyvista as pv
0147         themes = ["default", "dark", "paraview", "document" ]
0148         pv.set_plot_theme(themes[1])
0149     except ImportError:
0150         pv = None
0151     pass
0152 else:
0153     pv = None
0154 pass
0155 
0156 if GUI == False:
0157     log.info("disabling pv as GUI False")
0158     pv = None
0159 pass
0160 
0161 
0162 
0163 def pvplt_simple(xyz, label):
0164     """
0165     :param xyz: (n,3) shaped array of positions
0166     :param label: to place on plot 
0167 
0168     KEEP THIS SIMPLE : FOR DEBUGGING WHEN LESS BELLS AND WHISTLES IS AN ADVANTAGE
0169     """
0170     pl = pv.Plotter(window_size=SIZE*2 )  # retina 2x ?
0171     pl.add_text( "pvplt_simple %s " % label, position="upper_left")
0172     pl.add_points( xyz, color="white" )        
0173     pl.show_grid()
0174     cp = pl.show() if GUI else None
0175     return cp
0176 
0177 
0178 
0179 def xcompare_simple( pos, x_gpos, x_lpos, local=True ):
0180     """
0181     :param pos: SimtracePositions instance
0182     :param x_gpos: global photon step positions
0183     :param x_lpos: local photon step positions
0184     """
0185     pl = pv.Plotter(window_size=SIZE*2 )  # retina 2x ?
0186     if local == False:
0187         pl.add_points( pos.gpos[:,:3], color="white" )        
0188         pvplt_add_contiguous_line_segments(pl, x_gpos[:,:3])
0189     else:
0190         pl.add_points( pos.lpos[:,:3], color="white" )        
0191         pvplt_add_contiguous_line_segments(pl, x_lpos[:,:3])
0192     pass
0193     pl.show_grid()
0194 
0195     outpath = "/tmp/xcompare_simple.png" 
0196     log.info("outpath %s " % outpath)
0197     #pl.screenshot(outpath)  segments
0198 
0199     cp = pl.show(screenshot=outpath) if GUI else None
0200     return pl 
0201 
0202 
0203 def simple(pl, pos):
0204     """
0205     :param pos: SimtracePositions instance
0206     """
0207     pvplt_simple(pl, pos.gpos[:,:3], "pos.gpos[:,:3]" )
0208     pvplt_simple(pl, pos.lpos[:,:3], "pos.lpos[:,:3]" )
0209 
0210 
0211 if __name__ == '__main__':
0212     logging.basicConfig(level=logging.INFO)
0213 
0214     t = Fold.Load("$CFBASE/CSGOptiXSimtraceTest", symbol="t"); 
0215     x = Fold.Load("$CFBASE/CSGOptiXSimTest", symbol="x")
0216 
0217     if not x is None:
0218         x_nib = seqnib_(x.seq[:,0])  # valid steppoint records from seqhis count_nibbles
0219         x_gpos_ = x.record[PIDX,:x_nib[PIDX],0,:3]  # global frame photon step record positions of single PIDX photon
0220         x_gpos  = np.ones( (len(x_gpos_), 4 ), dtype=np.float32 )
0221         x_gpos[:,:3] = x_gpos_
0222         x_lpos = np.dot( x_gpos, t.sframe.w2m ) 
0223     pass
0224 
0225     SimtracePositions.Check(t.simtrace)
0226 
0227     local = True 
0228 
0229     gs = FrameGensteps(t.genstep, t.sframe, local=local, symbol="gs" )  ## get gs positions in target frame
0230 
0231     t_pos = SimtracePositions(t.simtrace, gs, t.sframe, local=local, mask=MASK, symbol="t_pos" )
0232 
0233     if SIMPLE:
0234        pl = pvplt_plotter()
0235        simple(pl, t_pos)
0236        pl.show()
0237        raise Exception("SIMPLE done")
0238     pass
0239     if XCOMPARE_SIMPLE and not x is None:
0240        pl = xcompare_simple( t_pos, x_gpos, x_lpos, local=True )
0241        #raise Exception("XCOMPARE done")
0242     pass
0243 
0244     pf = SimtraceFeatures(t_pos, cf, featname=FEAT, symbol="pf" ) 
0245 
0246     pl = SimtracePlot.MakePVPlotter()
0247 
0248     plt = SimtracePlot(pl, pf.feat, gs, t.sframe, t_pos, outdir=os.path.join(t.base, "figs") )
0249 
0250     if not x is None:       
0251         plt.x_lpos = x_lpos   
0252     pass
0253 
0254     if not mp is None:
0255         plt.positions_mpplt()
0256         ax = plt.ax
0257     pass
0258 
0259     if not pv is None:
0260         plt.positions_pvplt()
0261     pass
0262 pass