Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:48:48

0001 #!/usr/bin/env python
0002 """
0003 GNodeLib.py
0004 =============
0005 
0006 ::
0007 
0008    ipython -i -- GNodeLib.py --ulv --detail
0009 
0010 
0011 * see also ggeo.py which provides "triplet" indexing  (repeat_idx, instance_index, prim_index) 
0012 
0013 Geocache nodelib to load is controlled by OPTICKS_KEYDIR envvar. Set that in ~/.opticks_config with::
0014 
0015     export OPTICKS_KEY=OKX4Test.X4PhysicalVolume.World0xc15cfc00x40f7000_PV.50a18baaf29b18fae8c1642927003ee3  ## example key  
0016 
0017 ipython -i GNodeLib.py::
0018 
0019      nlib.pv 
0020      nlib.lv
0021      nlib.tr
0022      nlib.id
0023      nlib.ce
0024      nlib.bb
0025 
0026 
0027 Info for a node identified by flat index::
0028 
0029     epsilon:~ blyth$ GNodeLib.py 3154
0030     TR
0031     array([[      0.543,      -0.84 ,       0.   ,       0.   ],
0032            [      0.84 ,       0.543,       0.   ,       0.   ],
0033            [      0.   ,       0.   ,       1.   ,       0.   ],
0034            [ -18079.453, -799699.44 ,   -7100.   ,       1.   ]], dtype=float32)
0035 
0036     BB
0037     array([[ -20576.252, -802196.25 ,   -9600.   ,       1.   ],
0038            [ -15582.654, -797202.6  ,   -4600.   ,       1.   ]], dtype=float32)
0039 
0040     ID
0041     array([3154,   94,   18,    0], dtype=uint32)
0042 
0043     CE
0044     array([ -18079.453, -799699.44 ,   -7100.   ,    2500.   ], dtype=float32)
0045 
0046     PV
0047     '/dd/Geometry/AD/lvADE#pvSST0xc128d900x3ef9100'
0048 
0049     LV
0050     '/dd/Geometry/AD/lvSST0xc234cd00x3f0b5e0'
0051 
0052 
0053 
0054 Can also identify nodes using LV names or PV names and control 
0055 output with slice specification::
0056 
0057     GNodeLib.py --lv HamamatsuR12860_PMT_20inch_body_log --sli 0:2
0058 
0059 Dump a list of unique LV names with::
0060 
0061     GNodeLib.py --ulv 
0062 
0063 
0064 
0065 """
0066 import os, json, numpy as np, argparse, logging
0067 log = logging.getLogger(__name__)
0068 
0069 from opticks.ana.key import key_
0070 
0071 class Txt(list):
0072     def __init__(self, *args, **kwa):
0073         list.__init__(self, *args, **kwa)
0074     def __repr__(self):
0075         return "Txt:%d" % len(self)
0076 
0077 txt_load = lambda _:Txt(map(str.strip, open(_).readlines()))
0078 
0079 
0080 
0081 class Node(object):
0082     def __init__(self, nlib, idx):
0083         self.nlib = nlib
0084         self.idx = idx
0085     def __repr__(self):
0086         return "### Node idx:%d " % self.idx
0087     def __str__(self):
0088         return "\n".join([repr(self),""]+list(map(lambda k:"%2s\n%r\n" % (k, getattr(self.nlib,k.lower())[idx]), self.nlib.k2name.keys())))
0089 
0090 
0091 class GNodeLib(object):
0092     KEY = key_(os.environ["OPTICKS_KEY"])
0093     KEYDIR = KEY.keydir
0094     RELDIR = "GNodeLib" 
0095     k2name = {
0096       "TR":"all_volume_transforms.npy",
0097       "BB":"all_volume_bbox.npy",
0098       "ID":"all_volume_identity.npy",
0099       "NI":"all_volume_nodeinfo.npy",
0100       "CE":"all_volume_center_extent.npy",
0101       "PV":"all_volume_PVNames.txt",
0102       "LV":"all_volume_LVNames.txt",
0103     }
0104 
0105     @classmethod   
0106     def Path(cls, k): 
0107         keydir = cls.KEYDIR
0108         reldir = cls.RELDIR
0109         name = cls.k2name[k]
0110         return os.path.expandvars("{keydir}/{reldir}/{name}".format(**locals()))
0111 
0112     @classmethod   
0113     def Load(cls, k): 
0114         path = cls.Path(k)
0115         return np.load(path) if path[-4:] == ".npy" else np.loadtxt(path, dtype="|S100" )
0116 
0117     def pvfind(self, pvname_start, encoding='utf-8'):
0118         """
0119         :param pvname_start: string start of PV name
0120         :return indices: array of matching indices in pv name array (all nodes) 
0121         """
0122         return np.flatnonzero(np.char.startswith(self.pv, pvname_start.encode(encoding)))  
0123 
0124     def lvfind(self, lvname_start, encoding='utf-8'):
0125         """
0126         :param lvname_start: string start of LV name
0127         :return indices: array of matching indices in lv name array (all nodes: so will be many repeats)  
0128         """
0129         return np.flatnonzero(np.char.startswith(self.lv, lvname_start.encode(encoding)))  
0130 
0131     def __init__(self):
0132         for k in self.k2name.keys(): 
0133             setattr( self, k.lower(), self.Load(k) )
0134         pass
0135         self.lvidx = (( self.id[:,2] >> 16) & 0xffff )    
0136         self.bnidx = (( self.id[:,2] >>  0) & 0xffff ) 
0137 
0138     def __str__(self):
0139         return "\n".join(map(lambda k:"%2s\n%r\n" % (k, getattr(self,k.lower())), self.k2name.keys()))
0140 
0141     def __getitem__(self, idx):
0142         return Node(self, idx)
0143 
0144 
0145 def slice_(sli):
0146     elem = []
0147     for s in sli.split(":"):
0148         try:
0149             elem.append(int(s))
0150         except ValueError:
0151             elem.append(None)
0152         pass
0153     return slice(*elem)
0154 
0155 
0156 def parse_args(doc, **kwa):
0157     np.set_printoptions(suppress=True, precision=3, linewidth=200)
0158     parser = argparse.ArgumentParser(doc)
0159     parser.add_argument(     "idx",  type=int, nargs="*", help="Node index to dump.")
0160     parser.add_argument(     "--level", default="info", help="logging level" ) 
0161     parser.add_argument(     "--pv", default=None, help="PV name to search for" ) 
0162     parser.add_argument(     "--lv", default=None, help="LV name to search for" ) 
0163     parser.add_argument(     "--ulv", default=False, action="store_true", help="Dump unique LV names" ) 
0164     parser.add_argument(     "--sli", default="0:10:1", help="Array slice to control output, 0:None for all" )
0165     parser.add_argument(     "--ce", default=False, action="store_true", help="Dump just center_extent" ) 
0166     parser.add_argument(     "--detail", default=False, action="store_true", help="Dump extra details" )
0167     parser.add_argument(     "-d","--dump", action="store_true", help="Dump lib repr" ) 
0168     args = parser.parse_args()
0169     fmt = '[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s'
0170     logging.basicConfig(level=getattr(logging,args.level.upper()), format=fmt)
0171     args.slice = slice_(args.sli)
0172     return args  
0173 
0174 if __name__ == '__main__':
0175     args = parse_args(__doc__)
0176     print(repr(GNodeLib.KEY))
0177     nlib = GNodeLib()
0178     if args.dump: 
0179         print(nlib)
0180     pass
0181     for idx in args.idx:
0182         nd = nlib[idx]
0183         print(nd)
0184     pass
0185 
0186     idxs = []
0187     if args.pv:
0188         idxs = nlib.pvfind(args.pv)
0189         print("args.pv:%s matched %d nodes " % (args.pv, len(idxs))) 
0190     elif args.lv:
0191         idxs = nlib.lvfind(args.lv)
0192         print("args.lv:%s matched %d nodes " % (args.lv, len(idxs))) 
0193     elif args.ulv:
0194         ulv, ulv_count = np.unique(nlib.lv, return_counts=True) 
0195         print("args.ulv found %d unique LV names" % (len(ulv))) 
0196         print("\n".join(list(map(lambda _:_.decode('utf-8'),ulv[args.slice]))))
0197         print("unique lv in descending count order, with names of first few corresponding pv ")
0198         for i in sorted(range(len(ulv)),key=lambda i:ulv_count[i], reverse=True):
0199             detail = "" 
0200             if args.detail:
0201                 w = np.where( nlib.lv == ulv[i] )              
0202                 pv = nlib.pv[w][:3]
0203                 detail = " ".join(list(map(lambda _:_.decode("utf-8"), pv )))     
0204             pass
0205             print("%10d : %50s : %s " % (ulv_count[i], ulv[i].decode("utf-8"), detail ))
0206         pass
0207     pass
0208 
0209     print("slice %s " % args.sli)
0210 
0211     print(idxs[args.slice])
0212     for idx in idxs[args.slice]:
0213         if args.ce:
0214             print(nlib.ce[idx])
0215         else:
0216             nd = nlib[idx]
0217             print(nd)
0218         pass
0219     pass 
0220 
0221