File indexing completed on 2026-04-09 07:48:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 """
0022 ABSmry
0023 ========
0024
0025 Canonical instance ab.smry collects summary info
0026 from bi-simulation event comparisons.
0027
0028 """
0029 from __future__ import print_function
0030 import os, sys, logging, numpy as np
0031 from collections import OrderedDict as odict
0032 from opticks.ana.base import json_save_, json_load_, findfile
0033 from opticks.ana.num import Num
0034 from opticks.ana.level import Level
0035
0036 log = logging.getLogger(__name__)
0037
0038
0039 class ABSmryTab(object):
0040 def __init__(self, base="$TMP"):
0041 base = os.path.expandvars(base)
0042 LV=os.environ.get("LV", None)
0043 log.debug("base %s LV %s " % (base, LV))
0044 relp = findfile(base, ABSmry.NAME )
0045 self.base = base
0046 s = odict()
0047 for rp in relp:
0048 path = os.path.join(base, rp)
0049 smry = ABSmry.Load(os.path.dirname(path))
0050
0051 if LV is not None and smry.key != LV: continue
0052
0053 try:
0054 fkey = float(smry.key)
0055 except ValueError:
0056 fkey = 1000.0+len(s)
0057 pass
0058 log.debug("rp:%s smry.key:%s fkey:%s" % (rp, smry.key, fkey))
0059
0060 while fkey in s:
0061 fkey += 0.001
0062 pass
0063 s[fkey] = smry
0064 pass
0065 self.s = s
0066 def __repr__(self):
0067 return "\n".join(["ABSmryTab", ABSmry.Labels()]+map(lambda kv:repr(kv[1]), sorted(self.s.items(), key=lambda kv:float(kv[0])) ))
0068
0069
0070
0071 class ABSmry(odict):
0072 """
0073
0074 After adding keys can usually update the summary just via redoing analysis
0075 with scan-tp
0076
0077
0078 """
0079 NAME = "ABSmry.json"
0080 DVS = "rpost_dv rpol_dv ox_dv".split()
0081 DVSQ = "maxdvmax RC level ndvp".split()
0082
0083
0084 @classmethod
0085 def Path(cls, dir_):
0086 return os.path.join(dir_, cls.NAME)
0087
0088 @classmethod
0089 def Pfx(cls, dir_):
0090 e = dir_.split("/")
0091 return e[e.index("evt")-1]
0092
0093
0094 KEYS = r"""
0095 ab.a.tagdir
0096 ab.a.metadata.lv
0097 ab.a.metadata.solid
0098 ab.dsli
0099 ab.RC
0100 ab.level
0101 ab.cfm.numPhotons
0102 ab.mal.fmaligned
0103 ab.mal.nmal
0104 ab.pro.ap.tim
0105 ab.pro.bp.tim
0106 ab.pro.boa
0107 """
0108
0109 @classmethod
0110 def Make(cls, ab):
0111 s = cls()
0112 s.dir_ = ab.a.tagdir
0113 log.debug("s.dir_ %s " % s.dir_)
0114 for q in list(filter(None, list(map(str.strip,cls.KEYS.split("\n"))))):
0115 v = eval(q)
0116 log.debug("eval(%s) -> %s %r " % (q, v, type(v)) )
0117 if type(v) is np.float32:
0118 v = float(v)
0119 pass
0120 s[q] = v
0121 pass
0122 for dv in cls.DVS:
0123 for q in cls.DVSQ:
0124 key = "ab.%s.%s" % (dv, q)
0125 log.debug(key)
0126 val = eval(key)
0127 log.debug(val)
0128 s[key] = val
0129 pass
0130 pass
0131 s.init()
0132 return s
0133
0134 @classmethod
0135 def Load(cls, dir_):
0136 log.debug("dir_ %s " % dir_ )
0137 d = json_load_(cls.Path(dir_))
0138 s = cls()
0139 for k, v in d.items():
0140 s[k] = v
0141 pass
0142 s.init()
0143 return s
0144
0145 pfx = property(lambda self:self.Pfx(self.tdir))
0146 tdir = property(lambda self:self["ab.a.tagdir"])
0147 key = property(lambda self:self["ab.a.metadata.lv"])
0148 dsli = property(lambda self:self.get("ab.dsli","."))
0149 RC = property(lambda self:self["ab.RC"])
0150 level = property(lambda self:self["ab.level"])
0151 fmal = property(lambda self:self["ab.mal.fmaligned"])
0152 nmal = property(lambda self:self.get("ab.mal.nmal",-1))
0153 npho = property(lambda self:self.get("ab.cfm.numPhotons",-1))
0154 solid = property(lambda self:self["ab.a.metadata.solid"])
0155
0156 ati = property(lambda self:self.get("ab.pro.ap.tim",-1))
0157 bti = property(lambda self:self.get("ab.pro.bp.tim",-1))
0158 boa = property(lambda self:self.get("ab.pro.boa",-1))
0159
0160
0161 def __init__(self):
0162 odict.__init__(self)
0163
0164 def init(self):
0165 self.lev = None if self.level is None else Level.FromLevel(self.level)
0166
0167 def save(self, dir_=None):
0168 if dir_ is None:
0169 dir_ = self.dir_
0170 pass
0171 path = self.Path(dir_)
0172 log.debug("saving to %s " % path)
0173 log.debug("self %s " % self)
0174 json_save_(path, self )
0175
0176
0177 HEAD2 = False
0178
0179
0180 @classmethod
0181 def Labels(cls):
0182 """
0183 level uses ansi codes in table, so has 9 invisible characters that take no screen space
0184 """
0185 head = " %5s %10s %4s %7s %4s %4s %10s %5s " % ("pfx", "dsli", "LV", "level", "RC", "npho", "fmal(%)", "nmal" )
0186 head2 = " %7s %7s %7s " % ( "ati", "bti", "boa" ) if cls.HEAD2 else None
0187 space = " "
0188 body = cls.label_dv()
0189 tail = "solid"
0190 return " ".join(filter(None,[head,head2,space,body,space, tail]))
0191
0192 def __repr__(self):
0193 head = " %5s %10s %4s %16s 0x%.2x %4s %10.3f %5d " % ( self.pfx[-5:], self.dsli, self.key, self.lev.fn_(self.lev.nam) , self.RC, Num.String(self.npho), self.fmal*100.0, self.nmal )
0194 head2 = " %7.4f %7.1f %7.1f " % (self.ati, self.bti, self.boa ) if self.HEAD2 else None
0195 space = " "
0196 body = self.desc_dv()
0197 tail = "%s" % self.solid
0198 return " ".join(filter(None,[head,head2,space,body,space,tail]))
0199
0200
0201 @classmethod
0202 def dvk(cls, n, k ):
0203 return "ab.%s.%s" % (n,k)
0204 def dvlev(self, dvn):
0205 levk = self.dvk(dvn, "level")
0206 levn = self[levk]
0207 return Level.FromName(levn)
0208 def desc_dv_(self, dvn):
0209 lev = self.dvlev(dvn)
0210
0211 mxk = self.dvk(dvn, "maxdvmax")
0212 mxv = self[mxk]
0213 mxs = "%10.4f" % mxv
0214
0215 ndk = self.dvk(dvn, "ndvp")
0216 ndv = self.get(ndk, -1)
0217
0218 return " %16s %15s %5s " % ( lev.fn_(lev.nam), lev.fn_(mxs), ndv )
0219
0220 @classmethod
0221 def label_dv_(cls, dvn):
0222 mxk = cls.dvk(dvn, "maxdvmax")
0223
0224
0225 return " %22s " % ( mxk[3:-5] )
0226 @classmethod
0227 def label_dv(cls):
0228 return " ".join([cls.label_dv_(dvn) for dvn in cls.DVS])
0229
0230 def desc_dv(self):
0231 return " ".join([self.desc_dv_(dvn) for dvn in self.DVS])
0232
0233
0234
0235
0236 def test_MakeLoad(ok):
0237 ab = AB(ok)
0238 ab.dump()
0239
0240 dir_ = "/tmp"
0241 s = ABSmry.Make(ab)
0242 s.save(dir_)
0243
0244 s2 = ABSmry.Load(dir_)
0245
0246
0247
0248 if __name__ == '__main__':
0249 from opticks.ana.main import opticks_main
0250
0251 from opticks.ana.ab import AB
0252 ok = opticks_main()
0253
0254
0255
0256 st = ABSmryTab()
0257 print(st)
0258
0259
0260
0261
0262