go-hep.org/x/hep@v0.38.1/lcio/cluster.go (about) 1 // Copyright ©2017 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package lcio 6 7 import ( 8 "fmt" 9 "strings" 10 11 "go-hep.org/x/hep/sio" 12 ) 13 14 // ClusterContainer is a collection of clusters. 15 type ClusterContainer struct { 16 Flags Flags 17 Params Params 18 Clusters []Cluster 19 } 20 21 type Cluster struct { 22 // Type of cluster: 23 // - bits 31-16: ECAL, HCAL, COMBINED, LAT, LCAL 24 // - bits 15-00: NEUTRAL, CHARGED, UNDEFINED 25 Type int32 26 Energy float32 // energy of the cluster 27 EnergyErr float32 // energy error of the cluster 28 Pos [3]float32 // center of cluster (x,y,z) 29 PosErr [6]float32 // covariance matrix of position 30 Theta float32 // intrinsic direction: theta at position 31 Phi float32 // intrinsic direction: phi at position 32 DirErr [3]float32 // covariance matrix of direct 33 Shape []float32 // shape parameters, defined in collection parameter 'ShapeParameterNames' 34 PIDs []ParticleID 35 Clusters []*Cluster // clusters combined into this cluster 36 Hits []*CalorimeterHit // hits that made this cluster 37 Weights []float32 // energy fraction of the hit that contributed to this cluster 38 SubDetEnes []float32 // energy observed in a particular subdetector 39 } 40 41 func (clus ClusterContainer) String() string { 42 o := new(strings.Builder) 43 fmt.Fprintf(o, "%[1]s print out of Cluster collection %[1]s\n\n", strings.Repeat("-", 15)) 44 fmt.Fprintf(o, " flag: 0x%x\n%v", clus.Flags, clus.Params) 45 fmt.Fprintf(o, " LCIO::CLBIT_HITS : %v\n", clus.Flags.Test(BitsClHits)) 46 47 o.WriteString("\n") 48 49 const ( 50 head = " [ id ] |type| energy |energyerr | position ( x,y,z) | itheta | iphi \n" 51 tail = "------------|----|----------|----------|----------------------------------|----------|----------\n" 52 ) 53 o.WriteString(head) 54 o.WriteString(tail) 55 for i := range clus.Clusters { 56 clu := &clus.Clusters[i] 57 fmt.Fprintf(o, 58 "[%09d] |%4d|%+.3e|%+.3e|%+.3e, %+.3e, %+.3e|%+.3e|%+.3e\n", 59 ID(clu), 60 clu.Type, clu.Energy, clu.EnergyErr, 61 clu.Pos[0], clu.Pos[1], clu.Pos[2], 62 clu.Theta, 63 clu.Phi, 64 ) 65 fmt.Fprintf(o, 66 " errors (6 pos)/(3 dir): (%+.3e, %+.3e, %+.3e, %+.3e, %+.3e, %+.3e)/(%+.3e, %+.3e, %+.3e)\n", 67 clu.PosErr[0], clu.PosErr[1], clu.PosErr[2], clu.PosErr[3], clu.PosErr[4], clu.PosErr[5], 68 clu.DirErr[0], clu.DirErr[1], clu.DirErr[2], 69 ) 70 o.WriteString(" clusters(e): ") 71 for ii, cc := range clu.Clusters { 72 var e float32 73 if cc != nil { 74 e = cc.Energy 75 } 76 if ii > 0 { 77 o.WriteString(", ") 78 } 79 fmt.Fprintf(o, "%+.3e", e) 80 } 81 o.WriteString("\n") 82 o.WriteString(" subdetector energies : ") 83 for ii, ee := range clu.SubDetEnes { 84 if ii > 0 { 85 fmt.Fprintf(o, ", ") 86 } 87 fmt.Fprintf(o, "%+.3e", ee) 88 } 89 fmt.Fprintf(o, "\n") 90 } 91 o.WriteString(tail) 92 93 return o.String() 94 } 95 96 func (*ClusterContainer) VersionSio() uint32 { 97 return Version 98 } 99 100 func (clus *ClusterContainer) MarshalSio(w sio.Writer) error { 101 enc := sio.NewEncoder(w) 102 enc.Encode(&clus.Flags) 103 enc.Encode(&clus.Params) 104 enc.Encode(int32(len(clus.Clusters))) 105 for i := range clus.Clusters { 106 clu := &clus.Clusters[i] 107 enc.Encode(&clu.Type) 108 enc.Encode(&clu.Energy) 109 enc.Encode(&clu.EnergyErr) 110 enc.Encode(&clu.Pos) 111 enc.Encode(&clu.PosErr) 112 enc.Encode(&clu.Theta) 113 enc.Encode(&clu.Phi) 114 enc.Encode(&clu.DirErr) 115 enc.Encode(&clu.Shape) 116 enc.Encode(int32(len(clu.PIDs))) 117 for i := range clu.PIDs { 118 pid := &clu.PIDs[i] 119 enc.Encode(&pid.Likelihood) 120 enc.Encode(&pid.Type) 121 enc.Encode(&pid.PDG) 122 enc.Encode(&pid.AlgType) 123 enc.Encode(&pid.Params) 124 } 125 126 enc.Encode(int32(len(clu.Clusters))) 127 for i := range clu.Clusters { 128 enc.Pointer(&clu.Clusters[i]) 129 } 130 131 if clus.Flags.Test(BitsClHits) { 132 enc.Encode(int32(len(clu.Hits))) 133 for i := range clu.Hits { 134 enc.Pointer(&clu.Hits[i]) 135 enc.Encode(&clu.Weights[i]) 136 } 137 } 138 enc.Encode(&clu.SubDetEnes) 139 140 enc.Tag(clu) 141 142 } 143 return enc.Err() 144 } 145 146 func (clus *ClusterContainer) UnmarshalSio(r sio.Reader) error { 147 const NShapeOld = 6 148 149 dec := sio.NewDecoder(r) 150 dec.Decode(&clus.Flags) 151 dec.Decode(&clus.Params) 152 var n int32 153 dec.Decode(&n) 154 clus.Clusters = make([]Cluster, int(n)) 155 for i := range clus.Clusters { 156 clu := &clus.Clusters[i] 157 dec.Decode(&clu.Type) 158 dec.Decode(&clu.Energy) 159 if r.VersionSio() > 1051 { 160 dec.Decode(&clu.EnergyErr) 161 } 162 dec.Decode(&clu.Pos) 163 dec.Decode(&clu.PosErr) 164 dec.Decode(&clu.Theta) 165 dec.Decode(&clu.Phi) 166 dec.Decode(&clu.DirErr) 167 168 var n int32 = NShapeOld 169 if r.VersionSio() > 1002 { 170 dec.Decode(&n) 171 } 172 clu.Shape = make([]float32, int(n)) 173 for i := range clu.Shape { 174 dec.Decode(&clu.Shape[i]) 175 } 176 177 if r.VersionSio() > 1002 { 178 var n int32 179 dec.Decode(&n) 180 clu.PIDs = make([]ParticleID, int(n)) 181 for i := range clu.PIDs { 182 pid := &clu.PIDs[i] 183 dec.Decode(&pid.Likelihood) 184 dec.Decode(&pid.Type) 185 dec.Decode(&pid.PDG) 186 dec.Decode(&pid.AlgType) 187 dec.Decode(&pid.Params) 188 } 189 } else { 190 var ptype [3]float32 191 dec.Decode(&ptype) 192 } 193 194 dec.Decode(&n) 195 clu.Clusters = make([]*Cluster, int(n)) 196 for i := range clu.Clusters { 197 dec.Pointer(&clu.Clusters[i]) 198 } 199 200 if clus.Flags.Test(BitsClHits) { 201 dec.Decode(&n) 202 clu.Hits = make([]*CalorimeterHit, int(n)) 203 clu.Weights = make([]float32, int(n)) 204 205 for i := range clu.Hits { 206 dec.Pointer(&clu.Hits[i]) 207 dec.Decode(&clu.Weights[i]) 208 } 209 } 210 dec.Decode(&clu.SubDetEnes) 211 212 dec.Tag(clu) 213 } 214 return dec.Err() 215 } 216 217 var ( 218 _ sio.Versioner = (*ClusterContainer)(nil) 219 _ sio.Codec = (*ClusterContainer)(nil) 220 )