001 #include "TrackingHL/Utility/CotNegLogT0Fitter.hh"
002 #include "TMinuit.h"
003 #include <iostream>
004 #include <cassert>
005 #include <cerrno>
006 #include <limits>
007 #include <iomanip>
008
009
010 const double CotNegLogT0Fitter::TZERO_LIMIT = 10.0;
011
012
013 CotNegLogT0Fitter::CotNegLogT0Fitter() {
014 _input = 0;
015 _internal = 0;
016 }
017
018 CotNegLogT0Fitter::~CotNegLogT0Fitter(){
019 }
020
021
022 CotT0Fitter::FitStatus
023 CotNegLogT0Fitter::calculateT0 (double & tzero, double & etzero,
024 CotT0Fitter::t0Input* input,
025 CotT0Fitter::t0Internal* internal)
026 {
027 if (input->trk_t0.size()==0)
028 {
029 if ( internal )
030 {
031 internal->ntrk = 0;
032 internal->ndof = 0;
033 internal->chi2 = -999;
034 internal->ncall = 0;
035 }
036 return UNDEFINED;
037 }
038
039
040
041
042
043
044
045 double t0seed;
046 double minLLF = std::numeric_limits<double>::max();
047 for(int mi = 0; mi < input->trk_t0.size(); mi++) {
048 for (int m=PION; m<NPID; m++) {
049 if (m==PION) {
050 tzero = input->trk_t0[mi] ;
051 } else if (m==KAON) {
052 tzero = input->trk_kt0[mi] ;
053 } else if (m==PROTON) {
054 tzero = input->trk_pt0[mi] ;
055 }
056 double llf = getLikelihood( tzero, input );
057 if ( llf < minLLF ) {
058 minLLF = llf;
059 t0seed = tzero;
060 }
061 }
062 }
063
064 tzero = t0seed;
065
066
067 if ( internal )
068 {
069 internal->ncall = 0;
070 }
071 _input = input;
072 _internal = internal;
073
074 int status = do_pid_likelihood_fit(tzero,etzero);
075
076 FitStatus fitStatus;
077 if ( status == 0 )
078 {
079
080
081
082
083
084 if ( fabs( tzero - TZERO_LIMIT ) < 0.2
085 ||
086 fabs( tzero + TZERO_LIMIT ) < 0.2 )
087 {
088 fitStatus = CotT0Fitter::FIT_AT_LIMIT;
089 }
090 else
091 {
092 fitStatus = CotT0Fitter::OK;
093 }
094 }
095 else
096 {
097 fitStatus = CotT0Fitter::FIT_ERROR;
098 }
099
100
101
102
103 if ( internal )
104 {
105 getLikelihood( tzero, input, internal );
106 }
107
108 return fitStatus;
109 }
110
111 int CotNegLogT0Fitter::do_pid_likelihood_fit(double & tzero, double & etzero)
112 {
113 static TMinuit minuit(1);
114 double arglis[10];
115 int ierr = 0;
116 instance = this;
117
118 minuit.SetFCN ( CotNegLogT0Fitter::pid_likelihood_fcn );
119 minuit.SetPrintLevel(-1);
120
121 arglis[0] = 1;
122 minuit.mnexcm("SET SETNOWARNINGS",arglis,1,ierr);
123 minuit.mncler();
124 minuit.mnparm(0, "t0_mean", tzero, 0.01, -TZERO_LIMIT, TZERO_LIMIT, ierr);
125 arglis[0] = 1000;
126 minuit.mnexcm ("MIGRAD",arglis,1, ierr);
127
128 minuit.GetParameter(0, tzero, etzero );
129 return ierr;
130 }
131
132 double CotNegLogT0Fitter::getLikelihood(double t0, CotT0Fitter::t0Input* input,
133 CotT0Fitter::t0Internal * internal)
134 {
135 _input = input;
136 _internal = internal;
137
138 double par[2];
139 par[0] = t0;
140 double llf;
141 if ( internal )
142 {
143 count_input( input, internal );
144 llf = pid_likelihood( par );
145 internal->chi2 = llf;
146 }
147 else
148 {
149 llf = pid_likelihood( par );
150 }
151
152 return llf;
153 }
154
155 double CotNegLogT0Fitter::pid_likelihood(double * par)
156 {
157 static const double norm = 2.5066283;
158 static const double minLog = log( std::numeric_limits<double>::min() );
159 double diff, sig, sigtail;
160 double outer, inner, prod;
161
162
163
164
165 outer = 0;
166
167 for (int mi = 0; mi < _input->trk_t0.size(); mi++) {
168 inner = 0;
169
170 for (int m=PION; m<NPID; m++)
171 {
172 prod = _input->trk_pidProb[mi][m];
173 if (m==PION) {
174 diff = _input->trk_t0[mi] - par[0];
175 sig = _input->trk_et0[mi];
176 } else if (m==KAON) {
177 diff = _input->trk_kt0[mi] - par[0];
178 sig = _input->trk_ekt0[mi];
179 } else if (m==PROTON) {
180 diff = _input->trk_pt0[mi] - par[0];
181 sig = _input->trk_ept0[mi];
182 }
183
184 if (sig!=0)
185 prod *= exp(-diff*diff/(2*sig*sig))/(norm*sig)
186
187 ;
188 inner += prod;
189 }
190
191
192 if (inner>0.) {
193 double logInner = log( inner );
194
195
196
197
198
199 outer += ( logInner < minLog ? minLog : logInner );
200
201
202
203
204
205
206
207
208
209 } else {
210
211
212
213 outer += minLog;
214
215
216
217
218
219
220
221 }
222 }
223
224 return -2*outer;
225 }
226
227
228 CotNegLogT0Fitter* CotNegLogT0Fitter::instance = 0;
229
230 void CotNegLogT0Fitter::pid_likelihood_fcn
231 (int &npar, double *gin, double &f, double *par, int iflag){
232 assert( instance );
233 f = instance->pid_likelihood(par);
234 if ( instance->_internal ) ++instance->_internal->ncall;
235 }
236
237
238
239
240
241 void CotNegLogT0Fitter::count_input( CotT0Fitter::t0Input * input,
242 CotT0Fitter::t0Internal * internal )
243 {
244 int ntrk = 0;
245 for ( int it = 0, itEnd = input->trk_t0.size() ; it < itEnd ; ++it )
246 {
247
248 {
249 ++ntrk;
250 }
251 }
252
253 internal->ntrk = ntrk;
254 internal->ndof = ntrk - 1;
255 }
Send problems or questions to cdfcode@fnal.gov