Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:21

0001 #!/usr/bin/env python
0002 """
0003 sreport.py
0004 ======================
0005 
0006 ::
0007 
0008     PLOT=Substamp_ONE_Delta PICK=A ~/o/sreport.sh
0009     PLOT=Substamp_ONE_Delta PICK=B ~/o/sreport.sh
0010 
0011     PLOT=Substamp_ONE_Etime PICK=A ~/o/sreport.sh
0012     PLOT=Substamp_ONE_Etime PICK=B ~/o/sreport.sh
0013     
0014     PLOT=Substamp_ONE_maxb_scan PICK=A ~/o/sreport.sh
0015     PLOT=Substamp_ONE_maxb_scan PICK=B ~/o/sreport.sh
0016 
0017     PLOT=Ranges_ONE ~/o/sreport.sh
0018     PLOT=Ranges_SPAN ~/o/sreport.sh
0019 
0020     PLOT=Substamp_ALL_Etime_vs_Photon ~/o/sreport.sh
0021     PLOT=Substamp_ALL_Hit_vs_Photon   ~/o/sreport.sh
0022     PLOT=Substamp_ALL_RATIO_vs_Photon ~/o/sreport.sh
0023 
0024     PLOT=Subprofile_ONE PICK=A ~/o/sreport.sh
0025     PLOT=Subprofile_ONE PICK=B ~/o/sreport.sh
0026  
0027     PLOT=Subprofile_ALL ~/o/sreport.sh
0028     PLOT=Runprof_ALL    ~/o/sreport.sh    
0029 
0030 """
0031 
0032 import os, numpy as np
0033 from opticks.ana.fold import Fold
0034 from opticks.ana.npmeta import NPMeta
0035 
0036 def format_large_number(number):
0037     if number//1000000 == 0:
0038         if number % 1000 == 0:
0039             num_K = number//1000
0040             num = "%dK" % num_K
0041         else:
0042             num = "%d" % number
0043         pass
0044     elif number//1000000 > 0:
0045         if number % 1000000 == 0:
0046             num_M = number//1000000
0047             num = "%dM" % num_M
0048         else:
0049             num = "%d" % number
0050         pass
0051     else:
0052         num = "%d" % number
0053     pass
0054     return num
0055 
0056 
0057 
0058 COMMANDLINE = os.environ.get("COMMANDLINE", "")
0059 STEM =  os.environ.get("STEM", "")
0060 HEADLINE = "%s ## %s " % (COMMANDLINE, STEM ) 
0061 JOB =  os.environ.get("JOB", "")
0062 PLOT =  os.environ.get("PLOT", "")
0063 STEM =  os.environ.get("STEM", "")
0064 MODE =  int(os.environ.get("MODE", "2"))
0065 PICK =  os.environ.get("PICK", "AB")
0066 TLIM =  np.array(list(map(int,os.environ.get("TLIM", "0,0").split(","))),dtype=np.int32)
0067 
0068 
0069 if MODE != 0:
0070     from opticks.ana.pvplt import * 
0071 pass
0072 
0073 labels_ = lambda l:l.view("|S%d" % l.shape[1])[:,0]  
0074 tv_     = lambda a:a.view("datetime64[us]")  
0075 
0076 # https://matplotlib.org/stable/gallery/color/named_colors.html
0077 palette = ["red","green", "blue", 
0078            "cyan", "magenta", "yellow", 
0079            "tab:orange", "tab:pink", "tab:olive",
0080            "tab:purple", "tab:grey", "tab:cyan"
0081            ]
0082 
0083 
0084 def make_title(meta, method, symbol):
0085     base = meta.base.replace("/data/blyth/opticks/GEOM/", "")
0086     smry = meta.smry("GPUMeta,prefix,creator")
0087     sfmt = meta.smry("stampFmt") 
0088     titl = "%s:%s %s " % (symbol,method, sfmt) 
0089     title = " ".join([titl,base,smry]) 
0090     return title
0091 
0092 smry__ = lambda _:NPMeta.Summarize(_)
0093 smry_ = lambda _:list(map(smry__, _))
0094 
0095 
0096 class Subprofile(object):
0097     """
0098     Why VM is so large with CUDA
0099 
0100     * https://forums.developer.nvidia.com/t/high-virtual-memory-consumption-on-linux-for-cuda-programs-is-it-possible-to-avoid-it/67706/4
0101 
0102     """
0103     FONTSIZE = 20 
0104     XLABEL = "Time from 1st sprof.h stamp (seconds)"
0105     YLABEL = "VM and/or RSS sprof.h memory (GB) "
0106 
0107     @classmethod
0108     def Time_VM_RS(cls, f):
0109         subprofile = f.subprofile
0110         assert len(subprofile.shape) == 3
0111         t0 = subprofile[0,0,0] 
0112         sp = subprofile.reshape(-1,3)   
0113         tp = (sp[:,0] - t0)/1e6   ## seconds from start
0114         vm = sp[:,1]/1e6          ## GB
0115         rs = sp[:,2]/1e6          ## GB
0116         return tp, vm, rs 
0117 
0118     @classmethod
0119     def Title(cls, f):
0120         meta = f.subprofile_meta
0121         base = meta.base.replace("/data/blyth/opticks/GEOM/", "")
0122         smry = meta.smry("GPUMeta,prefix,creator")
0123         sfmt = meta.smry("stampFmt") 
0124         title = "\n".join([base,smry,sfmt]) 
0125         return title
0126 
0127 
0128 class Subprofile_ALL(object):
0129     """
0130     RSS vs time for both "a" and "b"
0131     """
0132     def __init__(self, fold, symbol="fold.subprofile"):
0133         base = eval(symbol)
0134         label = RUN_META.Title(fold)
0135 
0136         fontsize = Subprofile.FONTSIZE
0137         if MODE == 2:
0138             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=label, equal=False)
0139             ax = axs[0]
0140             for sym in base.ff:
0141                 f = getattr(base, sym)
0142                
0143                 tp,vm,rs = Subprofile.Time_VM_RS(f)
0144 
0145                 if "VM" in os.environ:
0146                     ax.scatter( tp, vm, label="%s : VM(GB) vs time(s)" % sym.upper())
0147                     ax.plot(    tp, vm )
0148                 pass
0149                 ax.scatter( tp, rs, label="%s : RSS(GB) vs time(s)" % sym.upper())
0150                 ax.plot( tp, rs )
0151             pass
0152             ax.set_xlabel(Subprofile.XLABEL, fontsize=Subprofile.FONTSIZE )
0153             ax.set_ylabel(Subprofile.YLABEL, fontsize=Subprofile.FONTSIZE )
0154             ax.legend()
0155             fig.show()
0156 
0157 
0158 class Runprof_ALL(object):
0159     """
0160     PLOT=Runprof_ALL ~/o/sreport.sh 
0161     """
0162     def __init__(self, fold, symbol="fold.runprof"):
0163         rp = eval(symbol)
0164         label = "Runprof_ALL " 
0165         fontsize = Subprofile.FONTSIZE
0166         if MODE == 2:
0167             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=label, equal=False)
0168             ax = axs[0]
0169 
0170             tp = (rp[:,0] - rp[0,0])/1e6
0171             vm = rp[:,1]/1e6
0172             rs = rp[:,2]/1e6 
0173 
0174             if "VM" in os.environ:
0175                 ax.scatter( tp, vm, label="%s : VM(GB) vs time(s)" % symbol)
0176                 ax.plot(    tp, vm )
0177             pass
0178             ax.scatter( tp, rs, label="%s : RSS(GB) vs time(s)" % symbol )
0179             ax.plot( tp, rs )
0180             pass
0181             ax.set_xlabel(Subprofile.XLABEL, fontsize=Subprofile.FONTSIZE )
0182             ax.set_ylabel(Subprofile.YLABEL, fontsize=Subprofile.FONTSIZE )
0183 
0184             yl = ax.get_ylim()
0185             ax.vlines( tp[::4], yl[0], yl[1], color="blue", label="nBeg" ) 
0186             ax.vlines( tp[1::4], yl[0], yl[1], color="red", label="nEnd" ) 
0187             ax.vlines( tp[2::4], yl[0], yl[1], color="cyan", label="pBeg" ) 
0188             ax.vlines( tp[3::4], yl[0], yl[1], color="pink", label="pEnd" ) 
0189 
0190             ax.legend()
0191             fig.show()
0192         pass  
0193 
0194 
0195 class Subprofile_ONE(object):
0196     """
0197     PLOT=Subprofile_ONE ~/o/sreport.sh 
0198     """
0199     def __init__(self, fold, symbol="fold.subprofile.a"):
0200         f = eval(symbol)
0201 
0202         meta = f.subprofile_meta
0203         names = f.subprofile_names
0204         labels = f.subprofile_labels
0205         title = RUN_META.Title(fold) 
0206 
0207         tp,vm,rs = Subprofile.Time_VM_RS(f)
0208 
0209         if MODE == 2:
0210             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0211             ax = axs[0]
0212             if "VM" in os.environ:
0213                 ax.scatter( tp, vm, label="VM(GB) vs time(s)")
0214                 ax.plot( tp, vm )
0215             pass
0216             ax.scatter( tp, rs, label="RSS(GB) vs time(s)")
0217             ax.plot( tp, rs )
0218             ax.set_xlabel(Subprofile.XLABEL, fontsize=Subprofile.FONTSIZE )
0219             ax.set_ylabel(Subprofile.YLABEL, fontsize=Subprofile.FONTSIZE )
0220             ax.legend()
0221             fig.show()
0222         pass  
0223 
0224 
0225 class Substamp(object):
0226     @classmethod
0227     def ETime(cls, f):
0228         etime = f.delta_substamp[:,-1]/1e6  
0229         return etime
0230     @classmethod
0231     def Subcount(cls, f, label="photon"):
0232         _icol = np.where(f.subcount_labels == label)[0] 
0233         icol = _icol[0] if len(_icol) == 1 else -1 
0234         subcount = f.subcount[:,icol] if icol > -1 else None
0235         return subcount
0236     @classmethod
0237     def Labels(cls, f):
0238         labels = f.substamp_labels
0239         labels_s = smry_(labels)
0240         return labels_s
0241     @classmethod
0242     def DeltaColumn(cls, f, label ):
0243         _c = np.where( f.substamp_labels == label )[0]
0244         c = _c[0] if len(_c) == 1 else -1 
0245         return f.delta_substamp[:,c] if c > -1 else None
0246 
0247     @classmethod
0248     def Hdr(cls, f):
0249         labels_s = cls.Labels(f)
0250         hdr = (" " * 8  + " %4s " * len(labels_s) ) % tuple(labels_s) 
0251         return hdr
0252     @classmethod
0253     def Title(cls, f, symbol="a"):
0254         meta = f.substamp_meta
0255         title = make_title(meta, method="Substamp", symbol=symbol)
0256         return title 
0257 
0258 
0259 class Substamp_ONE_Etime(object):
0260     """
0261     Switches from using subcount_photon to submeta_NumPhotonCollected 
0262     as that avoids needing to gather and save large photons arrays. 
0263     """
0264     def __init__(self, fold, symbol="fold.substamp.a", esym="a" ):
0265 
0266         f = eval(symbol)
0267 
0268         substamp = f.substamp
0269         meta = f.substamp_meta
0270         names = f.substamp_names
0271         delta = f.delta_substamp 
0272 
0273         photon = SUB_META.NumPhotonCollected(fold, esym)/1e6
0274         etime = Substamp.ETime(f) 
0275 
0276         title = RUN_META.Title(fold)
0277         #title = Substamp.Title(f, symbol=symbol)
0278         hdr = Substamp.Hdr(f)
0279 
0280         desc = "\n".join([title, hdr, symbol, repr(delta)])
0281         print(desc)
0282 
0283         assert len(substamp.shape) == 2 
0284         assert delta.shape == substamp.shape 
0285         fontsize = 20 
0286 
0287         deg = 1  # linear   
0288         linefit = np.poly1d(np.polyfit(photon, etime, deg))
0289         linefit_label = "line fit:  slope %10.2f    intercept %10.2f " % (linefit.coef[0], linefit.coef[1])
0290 
0291         if MODE == 2:
0292             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0293             ax = axs[0]
0294             ax.scatter( photon, etime, label="etime(s)_vs_photon (millions)")
0295             ax.plot( photon, linefit(photon), label=linefit_label )
0296 
0297             ax.set_yscale('log')
0298             ax.set_ylabel("Event time (seconds)", fontsize=fontsize )
0299             ax.set_xlabel("Number of Photons (Millions)", fontsize=fontsize )
0300             ax.legend()
0301             fig.show()
0302         pass  
0303 
0304 
0305 class Substamp_ALL_Hit_vs_Photon(object):
0306     def __init__(self, fold, symbol="fold.substamp", ):
0307         base = eval(symbol)
0308         title = RUN_META.Title(fold)
0309         fontsize = 20 
0310         if MODE == 2:
0311             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0312             ax = axs[0]
0313             for sym in base.ff:
0314                 f = getattr(base, sym)
0315 
0316                 p_symbol = "fold.submeta_NumPhotonCollected.%s[:,0]" % sym 
0317                 #_photon = Substamp.Subcount(f, "photon")
0318                 _photon = eval(p_symbol)
0319 
0320                 _hit = Substamp.Subcount(f, "hit")
0321 
0322                 photon = _photon/1e6
0323                 hit = _hit/1e6
0324 
0325                 deg = 1  # linear   
0326                 linefit = np.poly1d(np.polyfit(photon, hit, deg))
0327                 linefit_label = "%s:line fit:  slope %10.3f    intercept %10.3f " % (sym.upper(), linefit.coef[0], linefit.coef[1])
0328 
0329                 ax.scatter( photon, hit, label="%s : hit_vs_photon (millions)" % sym.upper() )
0330                 ax.plot( photon, linefit(photon), linestyle="dotted", label=linefit_label,  )
0331             pass
0332             #ax.set_yscale('log')
0333             ax.set_ylabel("Number of Hits (Millions)", fontsize=fontsize )
0334             ax.set_xlabel("Number of Photons (Millions)", fontsize=fontsize )
0335             ax.legend()
0336             ax.legend()
0337             fig.show()
0338         pass
0339 
0340 
0341 class Substamp_ALL_Etime_vs_Photon(object):
0342     def __init__(self, fold, symbol="fold.substamp"):
0343         base = eval(symbol)
0344         title = RUN_META.Title(fold)
0345         fontsize = 20 
0346         YSCALE = os.environ.get("YSCALE", "log")
0347         YMIN = float(os.environ.get("YMIN", "1e-2"))
0348         YMAX = float(os.environ.get("YMAX", "1e4"))
0349 
0350         if MODE == 2:
0351             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0352             ax = axs[0]
0353             for sym in base.ff:
0354                 f = getattr(base, sym)
0355 
0356                 etime = Substamp.ETime(f) 
0357                 p_symbol = "fold.submeta_NumPhotonCollected.%s[:,0]" % sym 
0358                 _photon = eval(p_symbol)
0359                 photon = _photon/1e6
0360 
0361                 deg = 1  # linear   
0362                 linefit = np.poly1d(np.polyfit(photon, etime, deg))
0363                 linefit_label = "%s : line fit:  slope %10.3f    intercept %10.3f " % (sym.upper(), linefit.coef[0], linefit.coef[1])
0364 
0365                 ax.scatter( photon, etime, label="%s : etime(s)_vs_photon (millions)" % sym.upper() )
0366                 ax.plot( photon, linefit(photon), label=linefit_label )
0367             pass
0368             ax.set_xlim( -5, 105 ); 
0369             ax.set_ylim( YMIN, YMAX );  # 50*200 = 1e4
0370             ax.set_yscale(YSCALE)
0371             ax.set_ylabel("Event time (seconds)", fontsize=fontsize )
0372             ax.set_xlabel("Number of Photons (Millions)", fontsize=fontsize )
0373             ax.legend()
0374             ax.legend()
0375             fig.show()
0376         pass
0377 
0378 
0379 class Substamp_ALL_RATIO_vs_Photon(object):
0380     """
0381     PLOT=Substamp_ALL_RATIO_vs_Photon ~/o/sreport.sh
0382     """
0383     def __init__(self, fold, symbol="fold.substamp"):
0384         base = eval(symbol)
0385         #title = "Substamp_ALL_RATIO_vs_Photon"
0386         title = RUN_META.Title(fold)
0387 
0388         fontsize = 20 
0389         if MODE == 2:
0390             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0391             ax = axs[0]
0392             assert "a" in base.ff
0393             assert "b" in base.ff
0394 
0395             a_photon = fold.submeta_NumPhotonCollected.a[:,0]/1e6
0396             b_photon = fold.submeta_NumPhotonCollected.b[:,0]/1e6
0397             assert np.all( a_photon == b_photon )
0398 
0399             a_etime = Substamp.ETime(base.a)
0400             b_etime = Substamp.ETime(base.b)
0401             boa_etime = b_etime/a_etime 
0402 
0403             ax.scatter( a_photon, boa_etime, label="boa_etime(s)_vs_photon (millions)"  )
0404             ax.plot( a_photon, boa_etime, label=None, linestyle="dotted" )  
0405             pass
0406             ax.set_ylabel("Geant4/Opticks Event time ratio", fontsize=fontsize )
0407             ax.set_xlabel("Number of Photons (Millions)", fontsize=fontsize )
0408             ax.set_ylim( 0, 250)
0409             ax.set_xlim( -5, 105)
0410             #ax.set_yscale('log')
0411             #ax.set_xscale('log')
0412             ax.legend(loc="lower right")
0413             fig.show()
0414         pass
0415 
0416 
0417 class Substamp_ONE_Delta(object):
0418     def __init__(self, fold, symbol="fold.substamp.a" ):
0419         f = eval(symbol)
0420         delta = f.delta_substamp 
0421         #title = Substamp.Title(f, symbol=symbol)
0422         title = RUN_META.Title(fold)
0423 
0424         labels_s = Substamp.Labels(f)
0425  
0426         ax = None
0427         if MODE == 2:
0428             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0429             ax = axs[0]
0430             if TLIM[1] > TLIM[0]:
0431                 ax.set_xlim(*TLIM)
0432             pass
0433             for i in range(len(delta)):
0434                 for j in range(len(delta[i])):
0435                     label = None if i > 0 else labels_s[j]
0436                     color = palette[j % len(palette)]
0437                     ax.vlines( delta[i,j], i-0.5, i+0.5, label=label , colors=[color] ) 
0438                 pass
0439             pass
0440             ax.legend(loc="center")
0441             fig.show()
0442         pass  
0443         self.ax = ax
0444 
0445 class Substamp_ONE_maxb_scan(object):
0446     def __init__(self, fold, symbol="fold.substamp.a", esym="a" ):
0447         f = eval(symbol) 
0448         delta = f.delta_substamp 
0449         photon = SUB_META.NumPhotonCollected(fold, esym)/1e6
0450         u_photon = np.unique(photon)
0451         assert len(u_photon) == 1, u_photon
0452         n_photon = u_photon[0]
0453         num = format_large_number(n_subcount_photon)
0454 
0455         _subcount_hit = Substamp.Subcount(f, "hit")   ## TODO : include num hit into metadata
0456 
0457         title0 = Substamp.Title(f, symbol=symbol)
0458         if PLOT.endswith("_HIT"):
0459             title1 = "Hit count for %s photons vs MAX_BOUNCE "  % num
0460         else:
0461             title1 = "Launch Time[us] for %s photons vs MAX_BOUNCE "  % num
0462         pass
0463         title = "\n".join([title0, title1])
0464 
0465         labels_s = Substamp.Labels(f)
0466 
0467         pre = Substamp.DeltaColumn(f, "t_PreLaunch")        
0468         pos = Substamp.DeltaColumn(f, "t_PostLaunch")        
0469         launch = pos - pre 
0470         mxb = np.arange(len(launch))
0471 
0472         sel = slice(18)
0473         deg = 1  # linear   
0474         linefit = np.poly1d(np.polyfit(mxb[sel], launch[sel], deg))
0475         linefit_label = "%s : line fit:  slope %10.2f    intercept %10.2f " % (symbol, linefit.coef[0], linefit.coef[1])
0476 
0477         print(labels_s)
0478  
0479         ax = None
0480         if MODE == 2:
0481             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0482             ax = axs[0]
0483             if PLOT.endswith("_HIT"):
0484                 ax.plot(  mxb, _subcount_hit, label=None )
0485                 ax.scatter(  mxb, _subcount_hit, label="hit count vs max bounce (0->31) ")
0486                 ax.set_ylabel("Hit count", fontsize=20 )
0487                 ax.set_xlabel("OPTICKS_MAX_BOUNCE (aka MAX_TRACE)", fontsize=20 )
0488             else:
0489                 ax.scatter(  mxb, launch, label="launch time [us] vs max bounce (0->31) ")
0490                 ax.plot( mxb, linefit(mxb), linestyle="dotted", label=linefit_label )
0491                 ax.text(-0.05,  -0.1, HEADLINE, va='bottom', ha='left', family="monospace", fontsize=12, transform=ax.transAxes)
0492                 ax.set_ylabel("GPU Launch Time [us] ", fontsize=12 )
0493             pass
0494             ax.legend(loc="lower right")
0495             fig.show()
0496         pass  
0497         self.ax = ax
0498 
0499 
0500 
0501 class Ranges_SPAN(object):
0502     """
0503     PLOT=Ranges_SPAN ~/o/sreport.sh 
0504 
0505     TODO: split off QRng upload, probably most of upload_geom from that 
0506 
0507     """
0508     def __init__(self, fold, symbol="fold"):
0509 
0510         NPC = fold.submeta_NumPhotonCollected.a[:,0]
0511         #title = "Ranges_SPAN : Total Process Time Accounting : ~20 evt from 0.1 M to 100M photons"
0512         title = RUN_META.Title(fold)  
0513         print(title)
0514 
0515         print("NPC:%s" % str(NPC))
0516 
0517         t0 = fold.ranges[0,0]   ## currently ranges only setup for cxs_min.sh 
0518         ax = None
0519         if MODE == 2:
0520             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0521             ax = axs[0]
0522             names = ["init", "load_geom", "upload_geom", "simulate", "download", "upload_genstep" ]
0523             COLORS = ["yellow", "magenta", "cyan",  "red", "green", "blue" ]
0524 
0525             for i, name in enumerate(names):
0526                 color = COLORS[i%len(COLORS)]
0527                 ww = np.where( np.char.endswith( fold.ranges_names, name ))[0]  
0528                 if i > 3:
0529                     assert len(ww) == len(NPC)
0530                 pass
0531                 for j, w in enumerate(ww): 
0532                     rg = (fold.ranges[w] - t0)/1e6 
0533                     ax.axvspan(rg[0], rg[1], alpha=0.5, color=color, label=name if j==0 else None )
0534                 pass
0535             pass
0536             ax.legend(loc="center right")
0537             #ax.set_yscale('log')
0538             ax.set_xlim(-5,180)
0539             ax.set_xlabel("cxr_min.sh (CSGOptiXSMTest) Process Run Time[s]", fontsize=20 ); 
0540             fig.show()
0541         pass  
0542         self.ax = ax
0543 
0544 
0545 
0546 
0547 class Ranges_ONE(object):
0548     """
0549     PLOT=Ranges_ONE ~/o/sreport.sh 
0550     """
0551     def __init__(self, fold, symbol="fold"):
0552 
0553         NPC = fold.submeta_NumPhotonCollected.a[:,0]
0554         print("NPC:%s" % str(NPC))
0555         title = RUN_META.Title(fold)
0556         print(title)
0557 
0558         names = ["simulate", "download", "upload_genstep" ]
0559 
0560 
0561         COLORS = ["red", "green", "blue" ]
0562         ax = None
0563         if MODE == 2:
0564             fig, axs = mpplt_plotter(nrows=1, ncols=1, label=title, equal=False)
0565             ax = axs[0]
0566             for i, name in enumerate(names):
0567                 color = COLORS[i%len(COLORS)]
0568                 w = np.where( np.char.endswith( fold.ranges_names, name ))[0]  
0569                 rgs = fold.ranges[w] 
0570                 assert len(rgs) == len(NPC)
0571                 ax.plot( NPC/1e6, rgs[:,2]/1e6, color=color )  
0572                 ax.scatter( NPC/1e6, rgs[:,2]/1e6, label="%s" % name, color=color )  
0573             pass
0574             ax.legend(loc="center right")
0575             ax.set_yscale('log')
0576             ax.set_ylim(5e-4,50)
0577             ax.set_xlim(-5,105)
0578             ax.set_ylabel("Time (seconds)", fontsize=20); 
0579             ax.set_xlabel("Number of \"TORCH\" Photons from CD center (Millions)", fontsize=20 ); 
0580             fig.show()
0581         pass  
0582         self.ax = ax
0583 
0584 
0585 
0586 
0587 class SUB_META(object):
0588     @classmethod
0589     def NumPhotonCollected(cls, fold, esym):
0590         assert esym in ["a", "b"]
0591         p_symbol = "fold.submeta_NumPhotonCollected.%s[:,0]" % esym 
0592         photon = eval(p_symbol)
0593         return photon
0594 
0595 
0596 class RUN_META(object):
0597     @classmethod
0598     def _QSim__Switches(cls, fold):
0599         """
0600         eg: 'CONFIG_Release PRODUCTION WITH_CHILD WITH_CUSTOM4 PLOG_LOCAL '
0601         """
0602         SKIPS = "WITH_CHILD PLOG_LOCAL".split(); 
0603         switches = list(filter(lambda _:not _.startswith("NOT-"), fold.run_meta.QSim__Switches.split(","))) 
0604         switches = list(filter(lambda _:not _ in SKIPS, switches )) 
0605         return switches 
0606 
0607     @classmethod
0608     def QSim__Switches(cls, fold):
0609         """
0610         eg: 'CONFIG_Release PRODUCTION WITH_CHILD WITH_CUSTOM4 PLOG_LOCAL '
0611         """
0612         switches = cls._QSim__Switches(fold) 
0613         return " ".join(switches)  
0614 
0615     @classmethod
0616     def QSim__RNGLabel(cls, fold):
0617         switches = cls._QSim__Switches(fold) 
0618         return "RNG_PHILOX" if "RNG_PHILOX" in switches else "RNG_XORWOW"   
0619 
0620 
0621     @classmethod
0622     def ABCD_Title(cls, *rr):
0623         SCRIPT = None
0624         for i, r in enumerate(rr):
0625             _SCRIPT = getattr(r.run_meta, 'SCRIPT', "cxs_min.sh")
0626             if i == 0:
0627                 SCRIPT = _SCRIPT 
0628             else:
0629                 assert SCRIPT == _SCRIPT 
0630             pass 
0631         pass
0632         topline = "%s ## %s " % ( COMMANDLINE, SCRIPT )
0633 
0634         cvar = ["RUNNING_MODE","EVENT_MODE","MAX_BOUNCE"] 
0635         #cvar += ["MAX_PHOTON"]
0636         #cvar += ["NUM_PHOTON"]
0637 
0638         ctrls = [] 
0639         for var in cvar:
0640             val = None
0641             for i, r in enumerate(rr):
0642                 _val = getattr(r.run_meta, "OPTICKS_%s" % var, "?" )
0643 
0644                 if i == 0:
0645                     val = _val
0646                 else:
0647                     assert val == _val, ( val,  _val ) 
0648                 pass
0649             pass
0650             ctrls.append("%s:%s" % (var,val)) 
0651         pass
0652         ctrl = " ".join(ctrls)
0653 
0654         for i, r in enumerate(rr):
0655             SWITCHES = cls.QSim__Switches(r)
0656             print(SWITCHES)
0657         pass  
0658         title = "\n".join([topline, ctrl])
0659         return title 
0660 
0661     @classmethod
0662     def AB_Title(cls, a, b):
0663         """
0664         :param a: sreport Fold
0665         :param b: sreport Fold
0666         :return str: title 
0667 
0668         In addition to providing the title this also
0669         asserts consistency between the sreport fold
0670         for the below run_meta:
0671 
0672         1. SCRIPT
0673         2. OPTICKS_RUNNING_MODE, OPTICKS_EVENT_MODE, OPTICKS_MAX_BOUNCE, OPTICKS_MAX_PHOTON
0674         3. QSim__Switches
0675         """
0676         a_SCRIPT = getattr(a.run_meta, 'SCRIPT', "cxs_min.sh")  
0677         b_SCRIPT = getattr(b.run_meta, 'SCRIPT', "cxs_min.sh")  
0678         assert a_SCRIPT == b_SCRIPT, (a_SCRIPT, b_SCRIPT)
0679         SCRIPT = a_SCRIPT
0680 
0681 
0682         topline = "%s ## %s " % ( COMMANDLINE, SCRIPT )
0683 
0684         cvar = ["RUNNING_MODE","EVENT_MODE","MAX_BOUNCE","MAX_PHOTON"] 
0685         #cvar += ["NUM_PHOTON"]
0686 
0687         ctrls = [] 
0688         for var in cvar:
0689             a_val = getattr(a.run_meta, "OPTICKS_%s" % var, "?" )
0690             b_val = getattr(a.run_meta, "OPTICKS_%s" % var, "?" )
0691             assert a_val == b_val, (a_val, b_val)
0692             val = a_val
0693             ctrls.append("%s:%s" % (var,val)) 
0694         pass
0695         ctrl = " ".join(ctrls)
0696 
0697 
0698         a_SWITCHES = cls.QSim__Switches(a)
0699         b_SWITCHES = cls.QSim__Switches(b)
0700         assert a_SWITCHES == b_SWITCHES, (a_SWITCHES, b_SWITCHES) ## TODO: layout when not matched
0701         SWITCHES = a_SWITCHES 
0702 
0703         title = "\n".join([topline, ctrl])
0704         return title 
0705 
0706     @classmethod
0707     def GPUMeta(cls, fold, simplify=True):
0708         gpu = fold.run_meta.GPUMeta
0709         if simplify and (gpu.startswith("0:") or gpu.startswith("1:")):
0710             gpu = gpu[2:]
0711         pass
0712         return "%s : %s" % (fold.symbol, gpu) 
0713  
0714 
0715     @classmethod
0716     def Title(cls, fold):
0717         SCRIPT = getattr(fold.run_meta, 'SCRIPT', "cxs_min.sh")  
0718         GPUMeta = fold.run_meta.GPUMeta 
0719         topline = "%s ## %s : %s " % ( COMMANDLINE, SCRIPT, GPUMeta )
0720         SWITCHES = cls.QSim__Switches(fold)
0721 
0722         cvar = ["RUNNING_MODE","EVENT_MODE","MAX_BOUNCE","MAX_PHOTON"] 
0723         #cvar += ["NUM_PHOTON"]
0724 
0725         ctrls = [] 
0726         for var in cvar:
0727             val = getattr(fold.run_meta, "OPTICKS_%s" % var, "?" )
0728             ctrls.append("%s:%s" % (var,val)) 
0729         pass
0730         ctrl = " ".join(ctrls)
0731 
0732         title = "\n".join([topline, SWITCHES, ctrl])
0733         return title 
0734 
0735 
0736 
0737 
0738 
0739 
0740 if __name__ == '__main__':
0741 
0742     print("[sreport.py:PLOT[%s]" % PLOT ) 
0743     print("[sreport.py:fold = Fold.Load" ) 
0744     fold = Fold.Load("$SREPORT_FOLD", symbol="fold")
0745     print("]sreport.py:fold = Fold.Load" ) 
0746 
0747     print("[sreport.py:repr(fold)" ) 
0748     print(repr(fold))
0749     print("]sreport.py:repr(fold)" ) 
0750 
0751 
0752     SWITCHES = RUN_META.QSim__Switches(fold)
0753     print("MODE:%d PICK:%s SWITCHES:%s " % (MODE, PICK, SWITCHES) ) 
0754     print("COMMANDLINE:%s" % COMMANDLINE)
0755 
0756     if PLOT.startswith("Substamp_ONE") and hasattr(fold, "substamp"):
0757         for e in PICK:
0758             esym = e.lower()
0759             f = getattr(fold.substamp, esym, None)
0760             symbol = "fold.substamp.%s" % esym 
0761             pass
0762             if f is None: continue 
0763             if PLOT.startswith("Substamp_ONE_Delta"): Substamp_ONE_Delta(fold, symbol=symbol )
0764             if PLOT.startswith("Substamp_ONE_Etime"): Substamp_ONE_Etime(fold, symbol=symbol, esym=esym )
0765             if PLOT.startswith("Substamp_ONE_maxb_scan"): Substamp_ONE_maxb_scan(fold, symbol=symbol, esym=esym )
0766         pass
0767     pass  
0768     ## Ranges only working for cxs_min.sh : based on SProf.hh run metadata : that needs work for G4CXTest
0769     if PLOT.startswith("Ranges_ONE") and hasattr(fold, "ranges") and hasattr(fold,"submeta_NumPhotonCollected") :
0770         Ranges_ONE(fold, symbol="fold")  ## process activity line plots 
0771     if PLOT.startswith("Ranges_SPAN") and hasattr(fold, "ranges") and hasattr(fold,"submeta_NumPhotonCollected") :
0772         Ranges_SPAN(fold, symbol="fold")  ## colorfull process activity plot 
0773     pass
0774     if PLOT.startswith("Substamp_ALL"): 
0775         if hasattr(fold, "substamp"):
0776             if PLOT.startswith("Substamp_ALL_Etime_vs_Photon"): Substamp_ALL_Etime_vs_Photon(  fold, symbol="fold.substamp" )
0777             if PLOT.startswith("Substamp_ALL_Hit_vs_Photon"): Substamp_ALL_Hit_vs_Photon(      fold, symbol="fold.substamp" )
0778             if PLOT.startswith("Substamp_ALL_RATIO_vs_Photon"): Substamp_ALL_RATIO_vs_Photon(  fold, symbol="fold.substamp" )
0779         else:
0780             print(".sreport.py: fold does not have substamp : CANNOT PLOT [%s]" % PLOT)
0781         pass
0782     pass
0783     if PLOT.startswith("Subprofile_ONE") and hasattr(fold, "subprofile"):
0784         for e in PICK:
0785             f = getattr(fold.subprofile, e.lower(), None)
0786             symbol = "fold.subprofile.%s" % e.lower() 
0787             if f is None: continue
0788             Subprofile_ONE(fold, symbol=symbol)   ## RSS vs time : technical 
0789         pass
0790     pass
0791     if PLOT.startswith("Subprofile_ALL") and hasattr(fold, "subprofile"):
0792         Subprofile_ALL(fold, symbol="fold.subprofile")  ## RSS vs time 
0793     pass
0794     if PLOT.startswith("Runprof_ALL") and hasattr(fold, "runprof"):
0795         Runprof_ALL(fold, symbol="fold.runprof" )  ## RSS vs time : profile plot 
0796     pass
0797     print("]sreport.py:PLOT[%s]" % PLOT ) 
0798 pass
0799 
0800