Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #!/usr/bin/env python
0002 
0003 import os, sys, logging, codecs, numpy as np
0004 from opticks.sysrap.OpticksCSG import CSG_ as CSG 
0005 from complete_binary_tree import layout_tree
0006 
0007 
0008 log = logging.getLogger(__name__)
0009 
0010 class BB(object):
0011     """
0012 
0013                 +--------+       
0014                 |        | 
0015       z1  +--------+     | 
0016           |     |  |     |
0017           |     +--|-----+   y1  
0018           |        |
0019       z0  +--------+     y0
0020          x0        x1
0021     """
0022     def __init__(self, bb=[-0.,-0.,-0.,0.,0.,0.]):
0023         self.x0 = bb[0]
0024         self.y0 = bb[1]
0025         self.z0 = bb[2]
0026         self.x1 = bb[3]
0027         self.y1 = bb[4]
0028         self.z1 = bb[5]
0029         self.data = bb 
0030 
0031     def __repr__(self):
0032         fmt = "%10.3f "
0033         fmt = fmt * 6 
0034         return fmt % tuple(self.data)
0035 
0036     def include(self, other):
0037         if other.x0 < self.x0: self.x0 = other.x0
0038         if other.y0 < self.y0: self.y0 = other.y0
0039         if other.z0 < self.z0: self.z0 = other.z0
0040 
0041         if other.x1 > self.x1: self.x1 = other.x1
0042         if other.y1 > self.y1: self.y1 = other.y1
0043         if other.z1 > self.z1: self.z1 = other.z1
0044 
0045 
0046 
0047 class Tran(object):
0048     def __init__(self, idx, tr, it):
0049         self.idx = idx
0050         self.tr = tr 
0051         self.it = it 
0052     def __repr__(self):
0053         return "\n".join([str(self.idx), repr(self.tr)])
0054 
0055 class Node(object):
0056     """
0057 
0058                                     1
0059                       10                          11
0060                 100       101               110         111
0061              1000 1001 1100 1101        1100 1101     1110 1111
0062 
0063 
0064     """
0065     def __init__(self, item, fd):
0066         self.fd = fd 
0067         self.tc = item[3,2].view(np.int32)
0068         self.tyd = CSG.desc(self.tc)
0069         self.ty = self.tyd[:2]
0070         self.idx = item[1,3].view(np.int32)
0071         self.depth = len("{0:b}".format(self.idx+1)) - 1   # complete binary trees are very special  
0072         self.tref = item[3,3].view(np.int32) & 0x7fffffff 
0073         self.tidx = self.tref - 1
0074         self.cm = bool(item[3,3].view(np.uint32) & 0x80000000 >> 31) 
0075         self.bb = BB(item[2:4].ravel()[:6])
0076         self.pa = item[0:2].ravel()[:6]
0077         self.tr = self.fd.tran[self.tidx] if self.tref > 0 else None
0078         self.it = self.fd.itra[self.tidx] if self.tref > 0 else None
0079         self.tran = Tran(self.tidx, self.tr, self.it) if self.tidx > -1 else None
0080         self.scm = "!" if self.cm else ":"
0081         self.label = "%s%s%s" % (1+self.idx,self.scm, self.ty) 
0082 
0083     def __repr__(self):
0084         return "Node %2d%s%2s tidx:%5d cm:%1d bb %30s pa %30s " % (1+self.idx,self.scm,self.ty, self.tidx, self.cm, str(self.bb), str(self.pa))   
0085     def __str__(self):
0086         return self.label
0087 
0088 
0089 class Prim(object):
0090     def __init__(self, item, fd):
0091         self.fd = fd 
0092         self.numNode = item[0,0].view(np.int32)
0093         self.nodeOffset = item[0,1].view(np.int32)
0094         self.bb = BB(item[2:4].ravel()[:6])
0095 
0096         self.midx = item[1,1].view(np.uint32)
0097         self.ridx = item[1,2].view(np.uint32)
0098         self.pidx = item[1,3].view(np.uint32)
0099         self.mname = self.fd.getName(self.midx)
0100 
0101         levelorder = list(map(lambda item:Node(item, fd), self.fd.node[self.nodeOffset:self.nodeOffset+self.numNode]))
0102         self.node = levelorder
0103 
0104     def __repr__(self):
0105         return "Prim %3d %5d %30s : %s" % (self.numNode, self.nodeOffset, str(self.bb), self.mname)   
0106 
0107     def __str__(self):
0108         return "\n".join([repr(self)]+list(map(repr, self.node))+list(map(lambda n:repr(n.tran), self.node)))
0109 
0110     def __getitem__(self, nodeIdx):
0111         return self.node[nodeIdx]
0112 
0113 class Solid(object):
0114     @classmethod
0115     def DecodeLabel(cls, item):
0116         return item.tobytes()[:16].split(b'\0')[0].decode("utf-8")     # TODO: test full 8 char label  
0117 
0118     def __init__(self, item, fd):
0119         self.item = item  
0120         self.fd = fd 
0121         self.label = self.DecodeLabel(item)
0122         self.numPrim = item[1,0].view(np.int32)
0123         self.primOffset = item[1,1].view(np.int32)
0124         self.prim = list(map(lambda item:Prim(item, fd), self.fd.prim[self.primOffset:self.primOffset+self.numPrim]))
0125         self.ce = item[2].view(np.float32)
0126 
0127     def __repr__(self):
0128         return "Solid %10s : %4d %5d  ce %35s  "  % (self.label, self.numPrim, self.primOffset, str(self.ce))
0129 
0130     def __str__(self):
0131         return "\n".join([repr(self)]+list(map(repr, self.prim)))
0132 
0133     def __getitem__(self, primIdx):
0134         return self.prim[primIdx]
0135 
0136 
0137 class Foundry(object):
0138     BASE = "$TMP/CSG_GGeo/CSGFoundry"
0139     NAMES = "solid prim node tran itra inst".split()
0140     def __init__(self, base=None):
0141         if base is None: base = self.BASE  
0142         base = os.path.expandvars(base) 
0143         for n in self.NAMES+["plan"]:
0144             path = os.path.join(base, "%s.npy" % n)
0145             if not os.path.exists(path): continue
0146             setattr( self, n, np.load(path))
0147         pass   
0148         self.name = np.loadtxt(os.path.join(base, "name.txt"), dtype=np.object)
0149         self.label = list(map(Solid.DecodeLabel, self.solid))
0150         self.solids = list(map(lambda item:Solid(item,self), self.solid))
0151 
0152     def __repr__(self):
0153         return "\n".join(["Foundry"] + list(map(lambda n:"%10s : %s " % (n,repr(getattr(self, n).shape)), self.NAMES))) 
0154 
0155     def __str__(self):
0156         return "\n".join(["Foundry"]+ list(map(repr, self.solids)))
0157 
0158     def getName(self, midx):
0159         return self.name[midx]
0160 
0161     def index(self, solid_label):
0162         return self.label.index(solid_label) 
0163 
0164     def gt(self):
0165         return self.node.view(np.int32)[:,3,3] & 0x7fffffff  
0166     def cm(self):
0167         return (self.node.view(np.int32)[:,3,3] & 0x80000000) >> 31     # complemented node
0168 
0169 
0170     def midx(self):
0171         return self.prim.view(np.uint32)[:,1,1]  
0172     def ridx(self):
0173         return self.prim.view(np.uint32)[:,1,2]  
0174     def pidx(self):
0175         return self.prim.view(np.uint32)[:,1,3]  
0176 
0177 
0178 
0179 
0180     def __getitem__(self, arg):
0181         """
0182         Access solids nodes prims via string specification::
0183 
0184              fd["d1"]        # solid with label "d1"
0185              fd["d1/0"]      # 1st prim
0186              fd["d1/0/0"]    # 1st node of 1st prim
0187 
0188         """
0189         ret = None
0190         elem = arg.split("/")
0191 
0192         solid_label = elem[0] if len(elem) > 0 else None
0193         primIdx = int(elem[1]) if len(elem) > 1 else None
0194         nodeIdx = int(elem[2]) if len(elem) > 2 else None
0195 
0196         solidIdx = self.index(solid_label) if not solid_label is None else None
0197 
0198         so = None
0199         pr = None
0200         nd = None
0201 
0202         if not solidIdx is None:
0203             so = self.solids[solidIdx]
0204         pass  
0205         if not so is None and not primIdx is None:
0206             pr = so[primIdx]
0207         pass
0208         if not pr is None and not nodeIdx is None:
0209             nd = pr[nodeIdx]
0210         pass
0211 
0212         if not nd is None:
0213             return nd
0214         elif not pr is None:
0215             return pr
0216         elif not so is None:
0217             return so
0218         else:
0219             return None
0220         pass
0221         return None
0222 
0223 
0224 
0225 if __name__ == '__main__':
0226     logging.basicConfig(level=logging.INFO)
0227     fd = Foundry("$TMP/CSG_GGeo/CSGFoundry")
0228     print(repr(fd))
0229     #print(str(fd))
0230     args = sys.argv[1:] if len(sys.argv) > 1 else "r8/0".split()
0231 
0232     p = None
0233     n = None
0234     s = None
0235 
0236     for arg in args: 
0237         obj = fd[arg] 
0238         print(arg)
0239         print(obj)
0240 
0241         if type(obj) is Prim:
0242             p = obj
0243         elif type(obj) is Node:
0244             n = obj
0245         elif type(obj) is Solid:
0246             s = obj
0247         else:
0248             pass
0249         pass
0250     pass
0251 
0252     if not p is None: 
0253         #print("\n".join(map(repr,p.node))) 
0254         t = layout_tree(p.node)
0255         print("layout_tree")
0256         print(t)
0257     pass
0258        
0259