go-hep.org/x/hep@v0.38.1/slha/slha.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 slha implements encoding and decoding of SUSY Les Houches Accords (SLHA) data format. 6 package slha // import "go-hep.org/x/hep/slha" 7 8 import ( 9 "fmt" 10 "reflect" 11 "strconv" 12 "strings" 13 ) 14 15 // SLHA holds informations about a SUSY Les Houches Accords file. 16 type SLHA struct { 17 Blocks Blocks 18 Particles Particles 19 } 20 21 // Value represents a value (string,int,float64) + comment in a SLHA line. 22 type Value struct { 23 v reflect.Value 24 c string // comment attached to value 25 } 26 27 // Int returns the value as an int64. 28 // Int panics if the underlying value isn't an int64. 29 func (v *Value) Int() int64 { 30 return v.v.Int() 31 } 32 33 // Float returns the value as a float64. 34 // Float panics if the underlying value isn't a float64. 35 func (v *Value) Float() float64 { 36 return v.v.Float() 37 } 38 39 // Interface returns the value as an empty interface. 40 func (v *Value) Interface() any { 41 return v.v.Interface() 42 } 43 44 // Kind returns the kind of the value (reflect.String, reflect.Float64, reflect.Int) 45 func (v *Value) Kind() reflect.Kind { 46 return v.v.Kind() 47 } 48 49 // Comment returns the comment string attached to this value 50 func (v *Value) Comment() string { 51 return v.c 52 } 53 54 // Block represents a block in a SLHA file. 55 type Block struct { 56 Name string 57 Comment string 58 Q float64 59 Data DataArray 60 } 61 62 // Get returns the Value at index args. 63 // Note that args are 1-based indices. 64 func (b *Block) Get(args ...int) (Value, error) { 65 var err error 66 var val Value 67 68 idx := NewIndex(args...) 69 val, ok := b.Data.Get(idx) 70 if !ok { 71 return val, fmt.Errorf("slha: no index (%s) in block %q", strings.Join(strindex(args...), ", "), b.Name) 72 } 73 return val, err 74 } 75 76 // Set sets the Value at index args with v. 77 // Set creates a new empty Value if none exists at args. 78 // Note that args are 1-based indices. 79 func (b *Block) Set(v any, args ...int) error { 80 var err error 81 val, _ := b.Get(args...) 82 val.v = reflect.ValueOf(v) 83 idx := NewIndex(args...) 84 pos := b.Data.pos(idx) 85 if pos < 0 { 86 pos = len(b.Data) 87 b.Data = append(b.Data, DataItem{ 88 Index: idx, 89 }) 90 } 91 b.Data[pos].Value = val 92 return err 93 } 94 95 // DataArray is an ordered list of DataItems. 96 type DataArray []DataItem 97 98 // DataItem is a pair of (Index,Value). 99 // Index is a n-dim index (1-based indices) 100 type DataItem struct { 101 Index Index 102 Value Value 103 } 104 105 // Get returns the value at the n-dim index idx. 106 func (d DataArray) Get(idx Index) (Value, bool) { 107 var val Value 108 for _, v := range d { 109 if v.Index == idx { 110 return v.Value, true 111 } 112 } 113 return val, false 114 } 115 116 func (d DataArray) pos(idx Index) int { 117 for i, v := range d { 118 if v.Index == idx { 119 return i 120 } 121 } 122 return -1 123 } 124 125 // Index is an n-dimensional index. 126 // Note that the indices are 1-based. 127 type Index struct { 128 rank int 129 coords string 130 } 131 132 // NewIndex creates a new n-dim index from args. 133 // Note that args are 1-based indices. 134 func NewIndex(args ...int) Index { 135 sargs := strindex(args...) 136 return Index{ 137 rank: len(args), 138 coords: strings.Join(sargs, "#"), 139 } 140 } 141 142 // Index returns the n-dim indices. 143 // Note that the indices are 1-based. 144 func (idx Index) Index() []int { 145 sargs := strings.Split(idx.coords, "#") 146 args := make([]int, len(sargs)) 147 for i, v := range sargs { 148 if v == "" { 149 continue 150 } 151 var err error 152 args[i], err = strconv.Atoi(v) 153 if err != nil { 154 panic(fmt.Errorf("slha.index: %v", err)) 155 } 156 } 157 return args 158 } 159 160 func strindex(args ...int) []string { 161 sargs := make([]string, len(args)) 162 for i, v := range args { 163 sargs[i] = strconv.Itoa(v) 164 } 165 return sargs 166 } 167 168 // Blocks is a list of Blocks. 169 type Blocks []Block 170 171 // Keys returns the names of the contained blocks. 172 func (b Blocks) Keys() []string { 173 keys := make([]string, len(b)) 174 for i := range b { 175 keys[i] = b[i].Name 176 } 177 return keys 178 } 179 180 // Get returns the block named name or nil. 181 func (b Blocks) Get(name string) *Block { 182 for i := range b { 183 blk := &b[i] 184 if blk.Name == name { 185 return blk 186 } 187 } 188 return nil 189 } 190 191 // Decay is a decay line in an SLHA file. 192 type Decay struct { 193 Br float64 // Branching Ratio 194 IDs []int // list of PDG IDs to which the decay occur 195 Comment string // comment attached to this decay line - if any 196 } 197 198 // Decays is a list of decays in a Decay block. 199 type Decays []Decay 200 201 // Particle is the representation of a single, specific particle, decay block from a SLHA file. 202 type Particle struct { 203 PdgID int // PDG-ID code 204 Width float64 // total width of that particle 205 Mass float64 // mass of that particle 206 Comment string 207 Decays Decays 208 } 209 210 // Particles is a block of particle's decays in an SLHA file. 211 type Particles []Particle 212 213 func (p Particles) Len() int { return len(p) } 214 func (p Particles) Less(i, j int) bool { return p[i].PdgID < p[j].PdgID } 215 func (p Particles) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 216 217 // Get returns the Particle with matching pdgid or nil. 218 func (p Particles) Get(pdgid int) *Particle { 219 for i := range p { 220 part := &p[i] 221 if part.PdgID == pdgid { 222 return part 223 } 224 } 225 return nil 226 }