go-hep.org/x/hep@v0.38.1/heppdt/parser.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 heppdt
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"fmt"
    11  	"io"
    12  	"strconv"
    13  )
    14  
    15  // parse fills a Table from the content of r
    16  func parse(r io.Reader, table *Table) error {
    17  	var err error
    18  	s := bufio.NewScanner(r)
    19  	lineno := 0
    20  	for s.Scan() {
    21  		lineno++
    22  		err = s.Err()
    23  		if err != nil {
    24  			break
    25  		}
    26  		bline := s.Bytes()
    27  		bline = bytes.Trim(bline, " \t\r\n")
    28  		if len(bline) <= 0 {
    29  			continue
    30  		}
    31  		if bline[0] == '#' {
    32  			continue
    33  		}
    34  		if len(bline) >= 2 && string(bline[:2]) == "//" {
    35  			continue
    36  		}
    37  		toks := bytes.Split(bline, []byte(" "))
    38  		tokens := make([]string, 0, len(toks))
    39  		for _, tok := range toks {
    40  			//fmt.Printf("--> [%s] => ", string(tok))
    41  			tok = bytes.Trim(tok, " \t\r\n")
    42  			//fmt.Printf("[%s]\n", string(tok))
    43  			if len(tok) > 0 {
    44  				tokens = append(tokens, string(tok))
    45  			}
    46  		}
    47  		if len(tokens) != 6 {
    48  			stoks := ""
    49  			for i, tok := range tokens {
    50  				stoks += fmt.Sprintf("%q", tok)
    51  				if i != len(tokens)-1 {
    52  					stoks += ", "
    53  				}
    54  			}
    55  			//fmt.Printf("** error: line %d (%d): %v\n", lineno, len(tokens), stoks)
    56  			return fmt.Errorf("heppdt: malformed line:%d: %v", lineno, string(bline))
    57  		}
    58  		var id int64
    59  		id, err = strconv.ParseInt(tokens[0], 10, 64)
    60  		if err != nil {
    61  			return fmt.Errorf("heppdt: line:%d: %w", lineno, err)
    62  		}
    63  		pid := PID(id)
    64  
    65  		name := string(tokens[1])
    66  
    67  		var icharge int64
    68  		icharge, err = strconv.ParseInt(tokens[2], 10, 64)
    69  		if err != nil {
    70  			return fmt.Errorf("heppdt: line:%d: %w", lineno, err)
    71  		}
    72  		var charge float64
    73  		// allow for Q-balls
    74  		if pid.IsQBall() {
    75  			// 10x the charge
    76  			charge = float64(icharge) * 0.01
    77  		} else {
    78  			// 3x the charge
    79  			const onethird = 1. / 3.0
    80  			charge = float64(icharge) * onethird
    81  		}
    82  		var mass float64
    83  		mass, err = strconv.ParseFloat(tokens[3], 64)
    84  		if err != nil {
    85  			return fmt.Errorf("heppdt: line:%d: %w", lineno, err)
    86  		}
    87  
    88  		var totwidth float64
    89  		totwidth, err = strconv.ParseFloat(tokens[4], 64)
    90  		if err != nil {
    91  			return fmt.Errorf("heppdt: line:%d: %w", lineno, err)
    92  		}
    93  
    94  		var lifetime float64
    95  		lifetime, err = strconv.ParseFloat(tokens[5], 64)
    96  		if err != nil {
    97  			return fmt.Errorf("heppdt: line:%d: %w", lineno, err)
    98  		}
    99  
   100  		res := Resonance{
   101  			Mass: Measurement{
   102  				Value: mass,
   103  				Sigma: 0,
   104  			},
   105  		}
   106  
   107  		// either width or lifetime is defined. not both.
   108  		switch {
   109  		case totwidth > 0.:
   110  			res.Width = Measurement{
   111  				Value: totwidth,
   112  				Sigma: 0,
   113  			}
   114  		case totwidth == -1.:
   115  			res.Width = Measurement{
   116  				Value: -1.,
   117  				Sigma: 0.,
   118  			}
   119  		case lifetime > 0.:
   120  			res.Width = Measurement{
   121  				Value: calcWidthFromLifetime(lifetime),
   122  				Sigma: 0.,
   123  			}
   124  		default:
   125  			res.Width = Measurement{}
   126  		}
   127  
   128  		part := Particle{
   129  			ID:        pid,
   130  			Name:      name,
   131  			PDG:       int(id),
   132  			Mass:      mass,
   133  			Charge:    charge,
   134  			Resonance: res,
   135  		}
   136  		table.pdt[pid] = &part
   137  		table.pid[name] = pid
   138  		//fmt.Printf(">>> %d: [%s]\n", lineno, tokens)
   139  	}
   140  	if err == io.EOF {
   141  		err = nil
   142  	}
   143  
   144  	return err
   145  }