forked from DeepLearnPhysics/Supera
-
Notifications
You must be signed in to change notification settings - Fork 1
/
check_supera_3d.py
171 lines (159 loc) · 7.13 KB
/
check_supera_3d.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import numpy as np
from larcv import larcv
def xyz_from_tensor3d(vs,meta):
"""
Given a larcv::VoxelSet (vs) and larcv::Voxel3DMeta, constructs 3D index array of shape (N,3)
"""
x = np.zeros(shape=(vs.size()),dtype=np.int32)
y = np.zeros(shape=(vs.size()),dtype=np.int32)
z = np.zeros(shape=(vs.size()),dtype=np.int32)
v = np.zeros(shape=(vs.size()),dtype=np.float32)
larcv.as_flat_arrays(vs,meta,x,y,z,v)
return np.stack([x,y,z],axis=1)
def same_tensor3d(t0,t1,meta0=None,meta1=None,explicit=False):
"""
Given two set of "tensors", compare to see if they are "identical"
INPUT:
- t0 ... either EventSparse3DTensor (then meta0 should be None) or VoxelSet (then meta0 needed)
- t1 ... either EventSparse3DTensor (then meta1 should be None) or VoxelSet (then meta1 needed)
- meta0 ... Voxel3DMeta, if t0 is VoxelSet which does not carry meta info
- meta1 ... Voxel3DMeta, if t1 is VoxelSet which does not carry meta info
- explicit ... if True, ALL elements are compared. If false, only start/end+randomly chosen elements compared
"""
if not t0.size() == t1.size(): return False
if t0.size() == 0: return True
if meta0 is None: meta0 = t0.meta()
if meta1 is None: meta1 = t1.meta()
if explicit:
a0 = xyz_from_tensor3d(t0,meta0)
a1 = xyz_from_tensor3d(t1,meta1)
return (a0 == a1).astype(np.int32).sum() == np.prod(a0.shape)
else:
# only check if voxel ID agrees at the start, end, and random min(10,t0.size()) elements
elements = [0,1] + list(np.random.randint(0,t0.size()-1,size=(min(10,t0.size()))))
elements = np.unique(elements).astype(np.int32)
v0 = t0.as_vector()
v1 = t1.as_vector()
for e in elements:
if not v0[int(e)].id() == v1[int(e)].id(): return False
return True
def subset_tensor3d(t0,t1,meta0=None,meta1=None):
"""
Given two set of "tensors", compare to see if one (t1) is a subset of the other (t0).
INPUT:
- t0 ... either EventSparse3DTensor (then meta0 should be None) or VoxelSet (then meta0 needed)
- t1 ... either EventSparse3DTensor (then meta1 should be None) or VoxelSet (then meta1 needed)
- meta0 ... Voxel3DMeta, if t0 is VoxelSet which does not carry meta info
- meta1 ... Voxel3DMeta, if t1 is VoxelSet which does not carry meta info
"""
if not t0.size() >= t1.size(): return False
if t0.size() == 0: return True
if t1.size() == 0: return True
if meta0 is None: meta0 = t0.meta()
if meta1 is None: meta1 = t1.meta()
a0 = xyz_from_tensor3d(t0,meta0)
a1 = xyz_from_tensor3d(t1,meta1)
subset_not = np.array([not pt in a0 for pt in a1]).astype(np.int32).sum()
return (subset_not == 0)
def same_cluster3d(c0,c1,explicit=False):
"""
Given two larcv::EventCluserVoxel3D, compare if they are identical in voxel count and locations
for each cluster element.
"""
if not c0.size() == c1.size(): return False
if c0.size() == 0: return True
for i in range(c0.size()):
if not same_tensor3d(c0.as_vector()[i],c1.as_vector()[i],c0.meta(),c1.meta(),explicit):
return False
return True
def subset_cluster3d(c0,c1):
"""
Given two larcv::EventCluserVoxel3D, compare if one (c1) is a subset of the other (c0).
Here, by "subset", it means individual clusters. So the length of c0 and c1 must match.
"""
if not c0.size() == c1.size(): return False
if c0.size() == 0: return True
for i in range(c0.size()):
if not subset_tensor3d(c0.as_vector()[i],c1.as_vector()[i],c0.meta(),c1.meta()):
return False
return True
class data_blob:
"""
Utility class to handle arbitrary many larcv data products
"""
def __init__(self,names):
from ROOT import TChain
self._names = names
self._chains = {}
for name in self._names: self._chains[name] = TChain('%s_tree' % name)
def add_file(self,f):
for name,ch in self._chains.items(): ch.AddFile(f)
def get_entry(self,e):
for name,ch in self._chains.items(): ch.GetEntry(e)
def get_data(self,name):
return getattr(self._chains[name],"%s_branch" % name)
def get_entries(self):
entry = self._chains[self._names[0]].GetEntries()
for name,ch in self._chains.items():
if not ch.GetEntries() == entry:
print('Chain',name,'has different entry',ch.GetEntries(),'!=',entry)
raise ValueError
return entry
def check_supera():
import sys
names = ['sparse3d_reco',
'sparse3d_pcluster',
'sparse3d_pcluster_semantics',
'sparse3d_pcluster_semantics_ghost',
'cluster3d_pcluster',
'cluster3d_pcluster_highE',
'cluster3d_pcluster_lowE',
'particle_pcluster',
'particle_corrected']
blob = data_blob(names)
fs = [v for v in sys.argv if v.endswith('.root')]
for f in fs: blob.add_file(f)
entries = blob.get_entries()
for entry in range(entries):
sys.stdout.write('%d/%d\r' % (entry,entries))
sys.stdout.flush()
blob.get_entry(entry)
error=False
# sparse3d_reco and sparse3d_semantics_reco
s1, s2 = 'sparse3d_reco', 'sparse3d_pcluster_semantics_ghost'
if not same_tensor3d(blob.get_data(s1),blob.get_data(s2)):
print('\nNot same tensor3d',s1,'(%d)' % blob.get_data(s1).size(),s2,'(%d)' % blob.get_data(s2).size())
error=True
# sparse3d_pcluster and sparse3d_pcluster_semantics
s1, s2 = 'sparse3d_pcluster', 'sparse3d_pcluster_semantics'
if not same_tensor3d(blob.get_data(s1),blob.get_data(s2)):
print('\nNot same tensor3d',s1,'(%d)' % blob.get_data(s1).size(),s2,'(%d)' % blob.get_data(s2).size())
error=True
# cluster3d_pcluster and cluster3d_pcluster_highE
c1, c2 = 'cluster3d_pcluster', 'cluster3d_pcluster_highE'
if not subset_cluster3d(blob.get_data(c1),blob.get_data(c2)):
print('\nNot a subset cluster3d',c1,c2);
error=True
# cluster3d_pcluster and cluster3d_pcluster_lowE
c1, c2 = 'cluster3d_pcluster', 'cluster3d_pcluster_lowE'
if not subset_cluster3d(blob.get_data(c1),blob.get_data(c2)):
print('\nNot a subset cluster3d',c1,c2);
error=True
# cluster3d_pcluster_reco and cluster3d_pcluster_highE_reco
c1, c2 = 'cluster3d_pcluster', 'cluster3d_pcluster_highE'
if not subset_cluster3d(blob.get_data(c1),blob.get_data(c2)):
print('\nNot a subset cluster3d',c1,c2);
error=True
# make sure the size is same
p='particle_pcluster'
part_count = blob.get_data(p).as_vector().size()
for n in names:
if not n.startswith('cluster3d_'): continue
if not blob.get_data(n).as_vector().size() == part_count:
print('\nParticle count mismatch',p,n)
error=True
if error:
d = blob.get_data(p)
print('Bad entry',entry,'run',d.run(),'subrun',d.subrun(),'event',d.event())
if __name__ == '__main__':
check_supera()