File indexing completed on 2026-04-09 07:48:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 """
0022
0023 ::
0024
0025 export OPTICKS_ANA_DEFAULTS=cat=tboolean-box,det=tboolean-box,src=torch,tag=1,pfx=tboolean-box
0026 main.py
0027
0028 unset OPTICKS_ANA_DEFAULTS
0029 export LV=box
0030 main.py
0031
0032
0033
0034 """
0035 from __future__ import print_function
0036 import numpy as np
0037
0038 import os, sys, re, logging, argparse, platform
0039 from opticks.ana.num import slice_, _slice
0040 from opticks.ana.log import init_logging
0041 from opticks.ana.env import opticks_environment
0042 from opticks.ana.OpticksQuery import OpticksQuery
0043 from opticks.ana.nload import tagdir_
0044
0045 log = logging.getLogger(__name__)
0046
0047
0048 def isIPython():
0049 try:
0050 __IPYTHON__
0051 except NameError:
0052 return False
0053 else:
0054 return True
0055
0056 class OK(argparse.Namespace):
0057 pass
0058
0059 ipython = isIPython()
0060 brief = property(lambda self:"pfx %s tag %s src %s det %s c2max %s ipython %s " % (self.pfx, self.utag,self.src,self.det, self.c2max, self.ipython))
0061
0062 def _get_ctx(self):
0063 return dict(tag=self.tag, utag=self.utag, src=self.src, det=self.det)
0064 ctx = property(_get_ctx)
0065
0066 def _get_tagdir(self):
0067 return tagdir_(self.det, self.src, self.tag, pfx=self.pfx )
0068 tagdir = property(_get_tagdir)
0069
0070 def _get_ntagdir(self):
0071 itag = int(self.tag)
0072 return tagdir_(self.det, self.src, str(-itag), pfx=self.pfx )
0073 ntagdir = property(_get_ntagdir)
0074
0075
0076
0077 def _get_catdir(self):
0078 return tagdir_(self.det, self.src, None, pfx=self.pfx )
0079 catdir = property(_get_catdir)
0080
0081 def _get_username(self):
0082 """
0083 Same approach as SSys::username
0084 """
0085 k = "USERNAME" if platform.system() == "Windows" else "USER"
0086 return os.environ[k]
0087 username = property(_get_username)
0088
0089 def _get_tmpdefault(self):
0090 return os.path.join("/tmp", self.username, "opticks")
0091 tmpdefault = property(_get_tmpdefault)
0092
0093 def resolve(self, arg):
0094 """
0095 :return: path with $TMP tokens replaced with a TMP envvar OR the default of /tmp/USERNAME/opticks
0096 """
0097 token = "$TMP"
0098 tmpd = os.environ.get(token[1:], self.tmpdefault )
0099 if arg.find(token) > -1:
0100 path = arg.replace(token,tmpd)
0101 else:
0102 path = os.path.expandvars(arg)
0103 pass
0104 assert path.find("$") == -1, "failed to resolve tokens in arg %s path %s " % (arg, path )
0105
0106 return path
0107
0108
0109 def opticks_args(**kwa):
0110 """
0111 The envvar OPTICKS_ANA_DEFAULTS provides a convenient way to
0112 communicate where the events of interest are, eg::
0113
0114 OPTICKS_ANA_DEFAULTS=det=g4live,cat=g4live,src=torch,tag=1,pfx=OKTest
0115
0116 The pfx setting default from here can be separately overridden using
0117 the TEST envvar, for example::
0118
0119 TEST=OpticksRunTest ipython -i ~/opticks/ana/profile_.py
0120
0121 """
0122 oad_key = "OPTICKS_ANA_DEFAULTS"
0123 oad = os.environ.get(oad_key,"det=g4live,cat=g4live,src=torch,tag=1,pfx=.")
0124 defaults = dict(map(lambda ekv:ekv.split("="), oad.split(",")))
0125 lv = os.environ.get("LV", None)
0126
0127 if lv is not None:
0128 lv_is_int = re.compile("\d+").match(lv) is not None
0129 lvn = lv if not lv_is_int else "proxy-%d" % int(lv)
0130 defaults["pfx"] = "tboolean-%s" % lvn
0131 defaults["cat"] = defaults["pfx"]
0132 log.info("override pfx, cat defaults as LV=%s envvar defined, %s " % (lv, defaults["pfx"]))
0133 pass
0134
0135 test = os.environ.get("TEST", None)
0136 if test is not None:
0137 defaults["pfx"] = test
0138 pass
0139
0140 log.info("envvar %s -> defaults %s " % (oad_key, repr(defaults)))
0141
0142 det = kwa.get("det", defaults["det"])
0143 cat = kwa.get("cat", defaults["cat"])
0144 src = kwa.get("src", defaults["src"])
0145 tag = kwa.get("tag", defaults["tag"])
0146 pfx = kwa.get("pfx", defaults["pfx"])
0147
0148
0149
0150
0151 llv = kwa.get("loglevel", "info")
0152 llv2 = kwa.get("log-level", "info")
0153 mrc = kwa.get("mrc", 101)
0154 doc = kwa.get("doc", None)
0155 tagoffset = kwa.get("tagoffset", 0)
0156 multievent = kwa.get("multievent", 1)
0157 stag = kwa.get("stag", None)
0158 ptag = kwa.get("ptag", None)
0159 show = kwa.get("show", False)
0160 plot = kwa.get("plot", True)
0161 compare = kwa.get("compare", True)
0162 terse = kwa.get("terse", False)
0163 mat = kwa.get("mat", "GdDopedLS")
0164
0165 msli = kwa.get("msli", "0:1M")
0166 sli = kwa.get("sli", "::")
0167 sel = kwa.get("sel", "0:5:1")
0168 qwn = kwa.get("qwn", "XYZT,ABCW")
0169
0170 c2max = kwa.get("c2max", "1.5,2.0,2.5")
0171 rdvmax = kwa.get("rdvmax", "0.01,0.10,1.0")
0172
0173 pdvmax = kwa.get("pdvmax", "0.10,0.25,0.50")
0174
0175
0176 pfxseqhis = kwa.get("pfxseqhis", "")
0177 pfxseqmat = kwa.get("pfxseqmat", "")
0178 dbgseqhis = kwa.get("dbgseqhis", "0")
0179 dbgseqmat = kwa.get("dbgseqmat", "0")
0180 dbgmskhis = kwa.get("dbgmskhis", "0")
0181 dbgmskmat = kwa.get("dbgmskmat", "0")
0182
0183 mask = kwa.get("mask", None)
0184
0185 smry = kwa.get("smry", False)
0186 dbgzero = kwa.get("dbgzero", False)
0187 lmx = kwa.get("lmx", 20)
0188 cmx = kwa.get("cmx", 0)
0189
0190
0191 prohis = kwa.get("prohis", False)
0192 promat = kwa.get("promat", False)
0193 rehist = kwa.get("rehist", False)
0194 chi2sel = kwa.get("chi2sel", False)
0195 chi2selcut = kwa.get("chi2selcut", 1.1)
0196 statcut = kwa.get("statcut", 1000)
0197 nointerpol = kwa.get("nointerpol", False)
0198
0199
0200 default_dpi = 100.
0201 pixwh=np.array([1280.,720.])
0202 figwh=pixwh/default_dpi
0203 old_figwh=np.array([18, 10.2])
0204 sfigwh = ",".join(list(map(str, figwh)))
0205 figsize = kwa.get("figsize", sfigwh )
0206
0207
0208 size = kwa.get("size", "1920,1080,1" )
0209 position = kwa.get("position", "100,100" )
0210 yes = kwa.get("yes", False )
0211 gltfsave = kwa.get("gltfsave", False )
0212 lvnlist = kwa.get("lvnlist", "" )
0213
0214 addpath = kwa.get("addpath", "$LOCAL_BASE/env/dyb/NuWa-trunk/dybgaudi/Detector/XmlDetDesc/DDDB/dayabay.xml" )
0215 apmtddpath = kwa.get("apmtddpath", "$LOCAL_BASE/env/dyb/NuWa-trunk/dybgaudi/Detector/XmlDetDesc/DDDB/PMT/hemi-pmt.xml" )
0216 apmtpathtmpl = kwa.get("apmtpathtmpl", "$OPTICKS_INSTALL_PREFIX/opticksdata/export/DayaBay/GPmt/%(apmtidx)s/GPmt.npy" )
0217 apmtidx = kwa.get("apmtidx", 2 )
0218
0219 csgname = kwa.get("csgname", "tboolean-dummy")
0220 csgpath = kwa.get("csgpath", None)
0221
0222
0223 container = kwa.get("container","Rock//perfectAbsorbSurface/Vacuum")
0224 testobject = kwa.get("testobject","Vacuum///GlassSchottF2" )
0225
0226 autocontainer = kwa.get("autocontainer","Rock//perfectAbsorbSurface/Vacuum")
0227 autoobject = kwa.get("autoobject","Vacuum/perfectSpecularSurface//GlassSchottF2" )
0228 autoemitconfig = kwa.get("autoemitconfig","photons:600000,wavelength:380,time:0.2,posdelta:0.1,sheetmask:0x3f,umin:0.25,umax:0.75,vmin:0.25,vmax:0.75" )
0229 autoseqmap = kwa.get("autoseqmap","TO:0,SR:1,SA:0" )
0230
0231
0232 gsel = kwa.get("gsel", "/dd/Geometry/PMT/lvPmtHemi0x" )
0233 gidx = kwa.get("gidx", 0 )
0234 gmaxnode = kwa.get("gmaxnode", 0 )
0235 gmaxdepth = kwa.get("gmaxdepth", 0 )
0236
0237
0238 cfordering = kwa.get("cfordering", "sum" )
0239 dumpenv = kwa.get("dumpenv", False)
0240
0241 parser = argparse.ArgumentParser(doc)
0242
0243 parser.add_argument( "--tag", default=tag, help="tag identifiying a simulation within a specific source and detector geometry, negated tag for Geant4 equivalent. Default %(default)s" )
0244 parser.add_argument( "--det", default=det, help="detector geometry: eg g4live, PmtInBox, dayabay. Default %(default)s. " )
0245 parser.add_argument( "--cat", default=cat, help="category that overrides det. Will replace det, to match C++. Default %(default)s. " )
0246 parser.add_argument( "--src", default=src, help="photon source: torch, natural, scintillation OR cerenkov. Default %(default)s " )
0247 parser.add_argument( "--pfx", default=pfx, help="either \"source\" for 1st executable or the name of the executable for subsequent eg \"OKG4Test\". Default %(default)s " )
0248
0249 parser.add_argument( "--noshow", dest="show", default=show, action="store_false", help="switch off dumping commandline " )
0250 parser.add_argument( "--noplot", dest="plot", default=plot, action="store_false", help="switch off plotting" )
0251 parser.add_argument( "-C,--nocompare", dest="compare", default=compare, action="store_false", help="switch off comparison for early stage debugging" )
0252 parser.add_argument( "--show", default=show, action="store_true", help="dump invoking commandline " )
0253 parser.add_argument( "--loglevel", default=llv, help=" set logging level : DEBUG/INFO/WARNING/ERROR/CRITICAL. Default %(default)s." )
0254 parser.add_argument( "--log-level", default=llv2, help=" mirror ipython level option to avoid complications with splitting options. Default %(default)s." )
0255
0256 parser.add_argument( "--profile", default=None, help="Unused option allowing argparser to cope with remnant ipython profile option" )
0257 parser.add_argument( "-i", dest="interactive", action="store_true", default=False, help="Unused option allowing argparser to cope with remnant ipython -i option" )
0258
0259 parser.add_argument( "--tagoffset", default=tagoffset, type=int, help="tagoffset : unsigned offset from tag, identifies event in multivent running. Default %(default)s " )
0260 parser.add_argument( "--multievent", default=multievent, type=int, help="multievent : unsigned number of events to handle. Default %(default)s " )
0261 parser.add_argument( "--stag", default=stag, help="S-Polarization tag : identifying a simulation within a specific source and detector geometry, negated tag for Geant4 equivalent" )
0262 parser.add_argument( "--ptag", default=ptag, help="P-Polarization tag : identifying a simulation within a specific source and detector geometry, negated tag for Geant4 equivalent" )
0263 parser.add_argument( "--mrc", default=mrc, type=int, help="script return code resulting from missing event files. Default %(default)s " )
0264 parser.add_argument( "--mat", default=mat, help="material name, used for optical property dumping/plotting. Default %(default)s" )
0265 parser.add_argument( "--sli", default=sli, help="slice specification delimited by colon. Default %(default)s" )
0266 parser.add_argument( "--msli", default=msli, help="photon np.load mmap_mode slice specification delimited by colon. Default %(default)s" )
0267 parser.add_argument( "--sel", default=sel, help="selection slice specification delimited by colon. Default %(default)s" )
0268 parser.add_argument( "--qwn", default=qwn, help="Quantity by single char, pages delimited by comma eg XYZT,ABCR. Default %(default)s" )
0269
0270 parser.add_argument( "--c2max", default=c2max, help="Admissable total chi2 deviation in comparisons. Comma delimited triplet of floats for warn/error/fatal levels. Default %(default)s" )
0271 parser.add_argument( "--rdvmax", default=rdvmax, help="For compressed record data : admissable total absolute deviation in DvTab comparisons. Comma delimited triplet of floats for warn/error/fatal levels. Default %(default)s" )
0272 parser.add_argument( "--pdvmax", default=pdvmax, help="For uncompressed final photon data : admissable total absolute deviation in DvTab comparisons. Comma delimited triplet of floats for warn/error/fatal levels. Default %(default)s" )
0273
0274 parser.add_argument( "--pfxseqhis", default=pfxseqhis, help="Seqhis hexstring prefix for spawned selection. Default %(default)s" )
0275 parser.add_argument( "--pfxseqmat", default=pfxseqmat, help="Seqmat hexstring prefix for spawned selection. Default %(default)s" )
0276 parser.add_argument( "--dbgseqhis", default=dbgseqhis, help="Seqhis hexstring prefix for dumping. Default %(default)s" )
0277 parser.add_argument( "--dbgseqmat", default=dbgseqmat, help="Seqmat hexstring prefix for dumping. Default %(default)s" )
0278 parser.add_argument( "--dbgmskhis", default=dbgmskhis, help="History mask hexstring for selection/dumping. Default %(default)s" )
0279 parser.add_argument( "--dbgmskmat", default=dbgmskmat, help="Material mask hexstring for selection/dumping. Default %(default)s" )
0280
0281 parser.add_argument( "--mask", default=mask, help="For analysis of masked events. Default %(default)s" )
0282
0283
0284 parser.add_argument( "--figsize", default=figsize, help="Comma delimited figure width,height in inches. Default %(default)s" )
0285 parser.add_argument( "--size", default=size, help="Comma delimited figure width,height in inches. Default %(default)s" )
0286 parser.add_argument( "--position", default=position, help="Comma delimited window position. Default %(default)s" )
0287 parser.add_argument( "--dbgzero", default=dbgzero, action="store_true", help="Dump sequence lines with zero counts. Default %(default)s" )
0288 parser.add_argument( "--terse", action="store_true", help="less verbose, useful together with --multievent ")
0289 parser.add_argument( "--smry", default=smry, action="store_true", help="smry option gives less detailed seqmat and seqhis tables, including the hex strings, useful for dbgseqhis")
0290 parser.add_argument( "--pybnd", action="store_true", help="Avoid error from op binary selection flag. ")
0291 parser.add_argument( "--gdml2gltf", action="store_true", help="Avoid error from op binary selection flag. ")
0292 parser.add_argument( "--prohis", default=prohis, action="store_true", help="Present progressively masked seqhis frequency tables for step by step checking. Default %(default)s ")
0293 parser.add_argument( "--promat", default=promat, action="store_true", help="Present progressively masked seqmat frequency tables for step by step checking. Default %(default)s ")
0294 parser.add_argument( "--rehist", default=rehist, action="store_true", help="Recreate hists rather than loading persisted ones. Default %(default)s ")
0295 parser.add_argument( "--chi2sel", default=chi2sel, action="store_true", help="Select histograms by their chi2 sum exceeding a cut, see cfh.py. Default %(default)s ")
0296 parser.add_argument( "--chi2selcut", default=chi2selcut, type=float, help="chi2 per degree of freedom cut used to select histograms when using --chi2sel option, see cfh-vi. Default %(default)s ")
0297 parser.add_argument( "--statcut", default=statcut, type=int, help="Statistics cut used with --chi2sel option, see cfh-vi Default %(default)s ")
0298 parser.add_argument( "--nointerpol", dest="interpol", default=not nointerpol, action="store_false", help="See cfg4/tests/CInterpolationTest.py. Default %(default)s ")
0299 parser.add_argument( "--lmx", default=lmx, type=int, help="Maximum number of lines to present in sequence frequency tables. Default %(default)s " )
0300 parser.add_argument( "--cmx", default=cmx, type=float, help="When greater than zero used as minimum line chi2 to present in sequence frequency tables. Default %(default)s " )
0301 parser.add_argument( "--apmtpathtmpl", default=apmtpathtmpl, help="Template Path to analytic PMT serialization, see pmt- and ana/pmt/analytic.py. %(default)s ")
0302 parser.add_argument( "--apmtidx", default=apmtidx, type=int, help="PmtPath index used to fill in the template, see pmt- and ana/pmt/analytic.py. %(default)s ")
0303 parser.add_argument( "--apmtddpath", default=apmtddpath, help="Path to detdesc xml file with description of DayaBay PMT, which references other files. %(default)s ")
0304 parser.add_argument( "--addpath", default=addpath, help="Path to detdesc xml file for topdown testing. %(default)s ")
0305 parser.add_argument( "--yes", action="store_true", help="Confirm any YES dialogs. %(default)s ")
0306 parser.add_argument( "--csgpath", default=csgpath, help="Directory of the NCSG input serialization. %(default)s ")
0307 parser.add_argument( "--csgname", default=csgname, help="Name of the Directory of the NCSG input serialization. %(default)s ")
0308
0309 parser.add_argument( "--container", default=container, help="Boundary specification for container. %(default)s ")
0310 parser.add_argument( "--testobject", default=testobject, help="Boundary specification for testobject. %(default)s ")
0311
0312 parser.add_argument( "--autocontainer", default=autocontainer, help="Boundary specification for test container used with --testauto. %(default)s ")
0313 parser.add_argument( "--autoobject", default=autoobject, help="Boundary specification for test object used with --testauto. %(default)s ")
0314 parser.add_argument( "--autoemitconfig", default=autoemitconfig, help="Emit config from test container used with --testauto. %(default)s ")
0315 parser.add_argument( "--autoseqmap", default=autoseqmap, help="Seqmap for NCSGIntersect testing with --testauto geometry. %(default)s ")
0316
0317 parser.add_argument( "--cfordering", default=cfordering, help="Sort ordering of cf tables, one of max/self/other. %(default)s ")
0318
0319 parser.add_argument( "--gsel", default=gsel, help="GDML node selection, either tree node index integer or LV name prefix, see tboolean-gdml . %(default)s ")
0320 parser.add_argument( "--gmaxdepth", default=gmaxdepth, type=int, help="GDML node depth limit, 0 for no limit, see tboolean-gdml. %(default)s ")
0321 parser.add_argument( "--gmaxnode", default=gmaxnode, type=int, help="GDML node limit including target node, 0 for no limit, see tboolean-gdml. %(default)s ")
0322 parser.add_argument( "--gidx", default=gidx, type=int, help="GDML index to pick target node from within gsel lvn selection, see tboolean-gdml. %(default)s ")
0323 parser.add_argument( "--gltfsave", default=gltfsave, action="store_true", help="Save GDML parsed scene as glTF, see analytic/sc.py. %(default)s ")
0324 parser.add_argument( "--lvnlist", default=lvnlist, help="Path to file containing list of lv names. %(default)s ")
0325 parser.add_argument( "--j1707", action="store_true", help="Bash level option passthru. %(default)s ")
0326 parser.add_argument( "--ip", action="store_true", help="Bash level option passthru. %(default)s ")
0327 parser.add_argument( "--pdb", action="store_true", help="ipython level option passthru. %(default)s ")
0328 parser.add_argument( "--extras", action="store_true", help="Bash level option passthru. %(default)s ")
0329 parser.add_argument( "--dumpenv", default=dumpenv, action="store_true", help="Dump enviroment. %(default)s ")
0330 parser.add_argument( "--disco", action="store_true", help="Disable container, investigate suspected inefficient raytrace of objects inside spacious containers. %(default)s ")
0331
0332 parser.add_argument('nargs', nargs='*', help='nargs : non-option args')
0333
0334
0335 ok = OK()
0336 args = parser.parse_args(namespace=ok)
0337
0338 cflog = True
0339 init_logging(level=args.loglevel,cflog=cflog)
0340
0341
0342 if args.multievent > 1 and args.tagoffset > 0:
0343 log.fatal("use either --multievent n or --tagoffset o to pick one from multi, USING BOTH --multievent and --tagoffset NOT SUPPORTED ")
0344 sys.exit(1)
0345
0346
0347 ok.allowed_cfordering = "max self other sum sum_code code".split()
0348 assert args.cfordering in ok.allowed_cfordering
0349
0350
0351 args.det = args.cat
0352
0353
0354
0355
0356
0357 args.c2max = list(map(float, args.c2max.split(",")))
0358 args.rdvmax = list(map(float, args.rdvmax.split(",")))
0359 args.pdvmax = list(map(float, args.pdvmax.split(",")))
0360
0361 if args.multievent > 1:
0362 args.utags = map(lambda offset:int(args.tag) + offset, range(args.multievent))
0363 args.utag = args.utags[0]
0364 else:
0365 try:
0366 tag = int(args.tag)
0367 except ValueError:
0368 tag = list(map(int,args.tag.split(",")))
0369 pass
0370
0371 if type(tag) is int:
0372 args.utag = tag + args.tagoffset
0373 args.utags = [args.utag]
0374 else:
0375 args.utag = None
0376 args.utags = tag
0377 pass
0378 pass
0379
0380 args.qwns = args.qwn.replace(",","")
0381 os.environ.update(OPTICKS_MAIN_QWNS=args.qwns)
0382
0383
0384 args.dbgseqhis = int(str(args.dbgseqhis),16)
0385 args.dbgseqmat = int(str(args.dbgseqmat),16)
0386 args.dbgmskhis = int(str(args.dbgmskhis),16)
0387 args.dbgmskmat = int(str(args.dbgmskmat),16)
0388 args.figsize = list(map(float, args.figsize.split(",")))
0389
0390
0391 args.msli = slice_(args.msli)
0392 args.sli = slice_(args.sli)
0393 args.sel = slice_(args.sel)
0394
0395 args.apmtpath = args.apmtpathtmpl % dict(apmtidx=str(args.apmtidx))
0396 log.debug("args.apmtpathtmpl %s args.apmtidx %d -> args.apmtpath %s " % ( args.apmtpathtmpl, args.apmtidx, args.apmtpath ) )
0397
0398
0399 log.debug("args.dbgseqhis [%x] " % args.dbgseqhis)
0400 log.debug("args.smry : %s " % args.smry )
0401
0402 if args.show:
0403 sys.stderr.write("args: " + " ".join(sys.argv) + "\n")
0404 pass
0405 ok.query = OpticksQuery(os.environ.get("OPTICKS_QUERY",""))
0406 return ok
0407
0408
0409 def opticks_main(**kwa):
0410 ok = opticks_args(**kwa)
0411 opticks_environment(ok)
0412 np.set_printoptions(suppress=True, precision=4, linewidth=200)
0413 return ok
0414
0415
0416 if __name__ == '__main__':
0417 ok = opticks_main(doc=__doc__)
0418 log.info(ok)
0419 log.info(ok.brief)
0420
0421
0422
0423
0424