go-hep.org/x/hep@v0.38.1/fads/cmd/fads-rivet-mc-generic/mcalg.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 main
     6  
     7  import (
     8  	"math"
     9  	"reflect"
    10  
    11  	"go-hep.org/x/hep/fads"
    12  	"go-hep.org/x/hep/fmom"
    13  	"go-hep.org/x/hep/fwk"
    14  	"go-hep.org/x/hep/hbook"
    15  	"go-hep.org/x/hep/hepmc"
    16  	"go-hep.org/x/hep/heppdt"
    17  )
    18  
    19  // McGeneric is a simple task mimicking Rivet's MC_GENERIC analysis looking at various distributions of final state particles
    20  type McGeneric struct {
    21  	fwk.TaskBase
    22  
    23  	mcevt  string  // original HepMC event
    24  	etamax float64 // maximum absolute eta acceptance
    25  	ptmin  float64 // minimum pt acceptance in GeV
    26  
    27  	hsvc    fwk.HistSvc // handle to the histogram service
    28  	hstream string      // histogram output stream
    29  
    30  	hmult fwk.H1D
    31  	hpt   fwk.H1D
    32  	hene  fwk.H1D
    33  	heta  fwk.H1D
    34  	hrap  fwk.H1D
    35  	hphi  fwk.H1D
    36  
    37  	hEtaPlus  fwk.H1D
    38  	hEtaMinus fwk.H1D
    39  	hRapPlus  fwk.H1D
    40  	hRapMinus fwk.H1D
    41  
    42  	hetaSumEt fwk.P1D
    43  
    44  	hetaPMRatio   fwk.S2D
    45  	hrapPMRatio   fwk.S2D
    46  	hetaChPMRatio fwk.S2D
    47  	hrapChPMRatio fwk.S2D
    48  
    49  	hmultCh fwk.H1D
    50  	hptCh   fwk.H1D
    51  	heneCh  fwk.H1D
    52  	hetaCh  fwk.H1D
    53  	hrapCh  fwk.H1D
    54  	hphiCh  fwk.H1D
    55  
    56  	hEtaPlusCh  fwk.H1D
    57  	hEtaMinusCh fwk.H1D
    58  	hRapPlusCh  fwk.H1D
    59  	hRapMinusCh fwk.H1D
    60  }
    61  
    62  func (tsk *McGeneric) Configure(ctx fwk.Context) error {
    63  	err := tsk.DeclInPort(tsk.mcevt, reflect.TypeOf(hepmc.Event{}))
    64  	if err != nil {
    65  		return err
    66  	}
    67  	return nil
    68  }
    69  
    70  func (tsk *McGeneric) StartTask(ctx fwk.Context) error {
    71  	svc, err := ctx.Svc("histsvc")
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	tsk.hsvc = svc.(fwk.HistSvc)
    77  
    78  	tsk.hetaSumEt, err = tsk.hsvc.BookP1D(tsk.hstream+"/EtaSumEt", 25, 0, 5)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	bookH1D := func(name string, nbins int, xmin, xmax float64) fwk.H1D {
    84  		h, e := tsk.hsvc.BookH1D(tsk.hstream+"/"+name, nbins, xmin, xmax)
    85  		if e != nil && err == nil {
    86  			err = e
    87  		}
    88  		return h
    89  	}
    90  
    91  	tsk.hmult = bookH1D("Mult", 100, -0.5, 199.5)
    92  	tsk.hpt = bookH1D("Pt", 300, 0, 30)
    93  	tsk.hene = bookH1D("E", 100, 0, 200)
    94  	tsk.heta = bookH1D("Eta", 50, -5, 5)
    95  	tsk.hrap = bookH1D("Rapidity", 50, -5, 5)
    96  	tsk.hphi = bookH1D("Phi", 50, 0, 2*math.Pi)
    97  
    98  	tsk.hmultCh = bookH1D("MultCh ", 100, -0.5, 199.5)
    99  	tsk.hptCh = bookH1D("PtCh ", 300, 0, 30)
   100  	tsk.heneCh = bookH1D("ECh ", 100, 0, 200)
   101  	tsk.hetaCh = bookH1D("EtaCh ", 50, -5, 5)
   102  	tsk.hrapCh = bookH1D("RapidityCh ", 50, -5, 5)
   103  	tsk.hphiCh = bookH1D("PhiCh ", 50, 0, 2*math.Pi)
   104  
   105  	// temp H1D
   106  	bookH1D = func(name string, nbins int, xmin, xmax float64) fwk.H1D {
   107  		h, e := tsk.hsvc.BookH1D("/"+name, nbins, xmin, xmax)
   108  		if e != nil && err == nil {
   109  			err = e
   110  		}
   111  		return h
   112  	}
   113  
   114  	tsk.hEtaPlus = bookH1D("EtaPlus", 25, 0, 5)
   115  	tsk.hEtaMinus = bookH1D("EtaMinus", 25, 0, 5)
   116  	tsk.hRapPlus = bookH1D("RapPlus", 25, 0, 5)
   117  	tsk.hRapMinus = bookH1D("RapMinus", 25, 0, 5)
   118  
   119  	tsk.hEtaPlusCh = bookH1D("EtaPlusCh", 25, 0, 5)
   120  	tsk.hEtaMinusCh = bookH1D("EtaMinusCh", 25, 0, 5)
   121  	tsk.hRapPlusCh = bookH1D("RapPlusCh", 25, 0, 5)
   122  	tsk.hRapMinusCh = bookH1D("RapMinusCh", 25, 0, 5)
   123  
   124  	bookS2D := func(name string) fwk.S2D {
   125  		s, e := tsk.hsvc.BookS2D(tsk.hstream + "/" + name)
   126  		if e != nil && err == nil {
   127  			err = e
   128  		}
   129  		return s
   130  	}
   131  
   132  	tsk.hetaPMRatio = bookS2D("EtaPMRatio")
   133  	tsk.hrapPMRatio = bookS2D("RapidityPMRatio")
   134  	tsk.hetaChPMRatio = bookS2D("EtaChPMRatio")
   135  	tsk.hrapChPMRatio = bookS2D("RapidityChPMRatio")
   136  
   137  	return nil
   138  }
   139  
   140  func (tsk *McGeneric) StopTask(ctx fwk.Context) error {
   141  	for _, h := range []*hbook.H1D{
   142  		tsk.hmult.Hist, tsk.heta.Hist, tsk.hrap.Hist, tsk.hpt.Hist, tsk.hene.Hist, tsk.hphi.Hist,
   143  		tsk.hmultCh.Hist, tsk.hetaCh.Hist, tsk.hrapCh.Hist, tsk.hptCh.Hist, tsk.heneCh.Hist, tsk.hphiCh.Hist,
   144  	} {
   145  		f := 1 / h.Integral()
   146  		h.Scale(f)
   147  		h.Annotation()["ScaledBy"] = f
   148  	}
   149  
   150  	for _, v := range []struct {
   151  		num *hbook.H1D
   152  		den *hbook.H1D
   153  		res *hbook.S2D
   154  	}{
   155  		{tsk.hEtaPlus.Hist, tsk.hEtaMinus.Hist, tsk.hetaPMRatio.Scatter},
   156  		{tsk.hRapPlus.Hist, tsk.hRapMinus.Hist, tsk.hrapPMRatio.Scatter},
   157  		{tsk.hEtaPlusCh.Hist, tsk.hEtaMinusCh.Hist, tsk.hetaChPMRatio.Scatter},
   158  		{tsk.hRapPlusCh.Hist, tsk.hRapMinusCh.Hist, tsk.hrapChPMRatio.Scatter},
   159  	} {
   160  		res, err := hbook.DivideH1D(v.num, v.den)
   161  		if err != nil {
   162  			return err
   163  		}
   164  		v.res.Fill(res.Points()...)
   165  	}
   166  	return nil
   167  }
   168  
   169  func (tsk *McGeneric) Process(ctx fwk.Context) error {
   170  	var (
   171  		store = ctx.Store()
   172  		msg   = ctx.Msg()
   173  	)
   174  
   175  	v, err := store.Get(tsk.mcevt)
   176  	if err != nil {
   177  		return err
   178  	}
   179  	evt := v.(hepmc.Event)
   180  	weight := 1.0
   181  	if len(evt.Weights.Slice) >= 1 {
   182  		weight = evt.Weights.Slice[0]
   183  	}
   184  
   185  	msg.Debugf(
   186  		"event number: %d, #parts=%d #vtx=%d weight=%v\n",
   187  		evt.EventNumber,
   188  		len(evt.Particles), len(evt.Vertices), weight,
   189  	)
   190  
   191  	nfsparts := 0
   192  	ncfsparts := 0
   193  	for _, p := range evt.Particles {
   194  		pdg := heppdt.ParticleByID(heppdt.PID(p.PdgID))
   195  		if pdg == nil {
   196  			continue
   197  		}
   198  
   199  		mc := fads.Candidate{
   200  			Pid:        int32(p.PdgID),
   201  			Status:     int32(p.Status),
   202  			M2:         1,
   203  			D2:         1,
   204  			CandCharge: int32(pdg.Charge),
   205  			CandMass:   pdg.Mass,
   206  			Mom:        fmom.PxPyPzE(p.Momentum),
   207  		}
   208  		if vtx := p.ProdVertex; vtx != nil {
   209  			mc.M1 = 1
   210  			mc.Pos = fmom.PxPyPzE(vtx.Position)
   211  		}
   212  		// pdgcode := p.PdgID
   213  		// if pdgcode < 0 {
   214  		// 	pdgcode = -pdgcode
   215  		// }
   216  
   217  		if p.Status != 1 {
   218  			continue
   219  		}
   220  
   221  		eta := mc.Mom.Eta()
   222  		abseta := math.Abs(eta)
   223  		if abseta >= tsk.etamax {
   224  			continue
   225  		}
   226  
   227  		if mc.Mom.Pt() <= tsk.ptmin {
   228  			continue
   229  		}
   230  
   231  		width := pdg.Resonance.Width.Value
   232  		if width > 1e-10 {
   233  			continue
   234  		}
   235  		rap := mc.Mom.Rapidity()
   236  		absrap := math.Abs(rap)
   237  
   238  		pt := mc.Mom.Pt()
   239  		ene := mc.Mom.E()
   240  		// hep/fmom.P4 returns phi in [-pi,pi) range.
   241  		// convert to [0,2pi) to match Rivet convention.
   242  		phi := angle0to2Pi(mc.Mom.Phi())
   243  
   244  		tsk.hsvc.FillP1D(tsk.hetaSumEt.ID, abseta, mc.Mom.Et(), weight)
   245  		nfsparts++
   246  		tsk.hsvc.FillH1D(tsk.heta.ID, eta, weight)
   247  		tsk.hsvc.FillH1D(tsk.hrap.ID, rap, weight)
   248  		tsk.hsvc.FillH1D(tsk.hpt.ID, pt, weight)
   249  		tsk.hsvc.FillH1D(tsk.hene.ID, ene, weight)
   250  		tsk.hsvc.FillH1D(tsk.hphi.ID, phi, weight)
   251  
   252  		switch eta > 0 {
   253  		case true:
   254  			tsk.hsvc.FillH1D(tsk.hEtaPlus.ID, abseta, weight)
   255  		case false:
   256  			tsk.hsvc.FillH1D(tsk.hEtaMinus.ID, abseta, weight)
   257  		}
   258  
   259  		switch rap > 0 {
   260  		case true:
   261  			tsk.hsvc.FillH1D(tsk.hRapPlus.ID, absrap, weight)
   262  		case false:
   263  			tsk.hsvc.FillH1D(tsk.hRapMinus.ID, absrap, weight)
   264  		}
   265  
   266  		if mc.CandCharge == 0 {
   267  			continue
   268  		}
   269  
   270  		ncfsparts++
   271  		tsk.hsvc.FillH1D(tsk.hetaCh.ID, eta, weight)
   272  		tsk.hsvc.FillH1D(tsk.hrapCh.ID, rap, weight)
   273  		tsk.hsvc.FillH1D(tsk.hptCh.ID, pt, weight)
   274  		tsk.hsvc.FillH1D(tsk.heneCh.ID, ene, weight)
   275  		tsk.hsvc.FillH1D(tsk.hphiCh.ID, phi, weight)
   276  
   277  		switch eta > 0 {
   278  		case true:
   279  			tsk.hsvc.FillH1D(tsk.hEtaPlusCh.ID, abseta, weight)
   280  		case false:
   281  			tsk.hsvc.FillH1D(tsk.hEtaMinusCh.ID, abseta, weight)
   282  		}
   283  
   284  		switch rap > 0 {
   285  		case true:
   286  			tsk.hsvc.FillH1D(tsk.hRapPlusCh.ID, absrap, weight)
   287  		case false:
   288  			tsk.hsvc.FillH1D(tsk.hRapMinusCh.ID, absrap, weight)
   289  		}
   290  
   291  	}
   292  
   293  	msg.Debugf("total multiplicity = %d\n", nfsparts)
   294  	tsk.hsvc.FillH1D(tsk.hmult.ID, float64(nfsparts), weight)
   295  
   296  	tsk.hsvc.FillH1D(tsk.hmultCh.ID, float64(ncfsparts), weight)
   297  	msg.Debugf("total charged multiplicity = %d\n", ncfsparts)
   298  	return nil
   299  }
   300  
   301  func newMcGeneric(typ, name string, mgr fwk.App) (fwk.Component, error) {
   302  	tsk := &McGeneric{
   303  		TaskBase: fwk.NewTask(typ, name, mgr),
   304  		mcevt:    "/fads/McEvent",
   305  		etamax:   5,
   306  		ptmin:    0.5, // GeV
   307  		hstream:  "/MC_GENERIC",
   308  	}
   309  
   310  	err := tsk.DeclProp("Input", &tsk.mcevt)
   311  	if err != nil {
   312  		return nil, err
   313  	}
   314  
   315  	err = tsk.DeclProp("EtaMax", &tsk.etamax)
   316  	if err != nil {
   317  		return nil, err
   318  	}
   319  
   320  	err = tsk.DeclProp("PtMin", &tsk.ptmin)
   321  	if err != nil {
   322  		return nil, err
   323  	}
   324  
   325  	err = tsk.DeclProp("Stream", &tsk.hstream)
   326  	if err != nil {
   327  		return nil, err
   328  	}
   329  
   330  	return tsk, nil
   331  }
   332  
   333  func init() {
   334  	fwk.Register(reflect.TypeOf(McGeneric{}), newMcGeneric)
   335  }
   336  
   337  const twoPi = 2 * math.Pi
   338  
   339  func angle0to2Pi(v float64) float64 {
   340  	v = math.Mod(v, twoPi)
   341  	if v == 0 {
   342  		return 0
   343  	}
   344  	if v < 0 {
   345  		v += twoPi
   346  	}
   347  	if v == twoPi {
   348  		v = 0
   349  	}
   350  	return v
   351  }