00001 // @(#)root/hist:$Id: TMultiDimFit.cxx 35406 2010-09-19 17:07:22Z brun $ 00002 // Author: Christian Holm Christensen 07/11/2000 00003 00004 //____________________________________________________________________ 00005 // 00006 // 00007 // Begin_Html 00008 /* 00009 </pre> 00010 <H1><A NAME="SECTION00010000000000000000"> 00011 Multidimensional Fits in ROOT</A> 00012 </H1> 00013 00014 <H1><A NAME="SECTION00020000000000000000"></A> 00015 <A NAME="sec:overview"></A><BR> 00016 Overview 00017 </H1> 00018 00019 <P> 00020 A common problem encountered in different fields of applied science is 00021 to find an expression for one physical quantity in terms of several 00022 others, which are directly measurable. 00023 00024 <P> 00025 An example in high energy physics is the evaluation of the momentum of 00026 a charged particle from the observation of its trajectory in a magnetic 00027 field. The problem is to relate the momentum of the particle to the 00028 observations, which may consists of of positional measurements at 00029 intervals along the particle trajectory. 00030 00031 <P> 00032 The exact functional relationship between the measured quantities 00033 (e.g., the space-points) and the dependent quantity (e.g., the 00034 momentum) is in general not known, but one possible way of solving the 00035 problem, is to find an expression which reliably approximates the 00036 dependence of the momentum on the observations. 00037 00038 <P> 00039 This explicit function of the observations can be obtained by a 00040 <I>least squares</I> fitting procedure applied to a representive 00041 sample of the data, for which the dependent quantity (e.g., momentum) 00042 and the independent observations are known. The function can then be 00043 used to compute the quantity of interest for new observations of the 00044 independent variables. 00045 00046 <P> 00047 This class <TT>TMultiDimFit</TT> implements such a procedure in 00048 ROOT. It is largely based on the CERNLIB MUDIFI package 00049 [<A 00050 HREF="TMultiFimFit.html#mudifi">2</A>]. Though the basic concepts are still sound, and 00051 therefore kept, a few implementation details have changed, and this 00052 class can take advantage of MINUIT [<A 00053 HREF="TMultiFimFit.html#minuit">4</A>] to improve the errors 00054 of the fitting, thanks to the class <TT>TMinuit</TT>. 00055 00056 <P> 00057 In [<A 00058 HREF="TMultiFimFit.html#wind72">5</A>] and [<A 00059 HREF="TMultiFimFit.html#wind81">6</A>] H. Wind demonstrates the utility 00060 of this procedure in the context of tracking, magnetic field 00061 parameterisation, and so on. The outline of the method used in this 00062 class is based on Winds discussion, and I refer these two excellents 00063 text for more information. 00064 00065 <P> 00066 And example of usage is given in 00067 <A NAME="tex2html1" 00068 HREF=" 00069 ./examples/multidimfit.C"><TT>$ROOTSYS/tutorials/fit/multidimfit.C</TT></A>. 00070 00071 <P> 00072 00073 <H1><A NAME="SECTION00030000000000000000"></A> 00074 <A NAME="sec:method"></A><BR> 00075 The Method 00076 </H1> 00077 00078 <P> 00079 Let <IMG 00080 WIDTH="18" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00081 SRC="gif/multidimfit_img7.gif" 00082 ALT="$ D$"> by the dependent quantity of interest, which depends smoothly 00083 on the observable quantities <!-- MATH 00084 $x_1, \ldots, x_N$ 00085 --> 00086 <IMG 00087 WIDTH="80" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00088 SRC="gif/multidimfit_img8.gif" 00089 ALT="$ x_1, \ldots, x_N$">, which we'll denote by 00090 <!-- MATH 00091 $\mathbf{x}$ 00092 --> 00093 <IMG 00094 WIDTH="14" HEIGHT="13" ALIGN="BOTTOM" BORDER="0" 00095 SRC="gif/multidimfit_img9.gif" 00096 ALT="$ \mathbf{x}$">. Given a training sample of <IMG 00097 WIDTH="21" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00098 SRC="gif/multidimfit_img10.gif" 00099 ALT="$ M$"> tuples of the form, 00100 (<A NAME="tex2html2" 00101 HREF=" 00102 ./TMultiDimFit.html#TMultiDimFit:AddRow"><TT>TMultiDimFit::AddRow</TT></A>) 00103 <!-- MATH 00104 \begin{displaymath} 00105 \left(\mathbf{x}_j, D_j, E_j\right)\quad, 00106 \end{displaymath} 00107 --> 00108 <P></P><DIV ALIGN="CENTER"> 00109 <IMG 00110 WIDTH="108" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00111 SRC="gif/multidimfit_img11.gif" 00112 ALT="$\displaystyle \left(\mathbf{x}_j, D_j, E_j\right)\quad, 00113 $"> 00114 </DIV><P></P> 00115 where <!-- MATH 00116 $\mathbf{x}_j = (x_{1,j},\ldots,x_{N,j})$ 00117 --> 00118 <IMG 00119 WIDTH="148" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00120 SRC="gif/multidimfit_img12.gif" 00121 ALT="$ \mathbf{x}_j = (x_{1,j},\ldots,x_{N,j})$"> are <IMG 00122 WIDTH="19" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00123 SRC="gif/multidimfit_img13.gif" 00124 ALT="$ N$"> independent 00125 variables, <IMG 00126 WIDTH="24" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00127 SRC="gif/multidimfit_img14.gif" 00128 ALT="$ D_j$"> is the known, quantity dependent at <!-- MATH 00129 $\mathbf{x}_j$ 00130 --> 00131 <IMG 00132 WIDTH="20" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00133 SRC="gif/multidimfit_img15.gif" 00134 ALT="$ \mathbf{x}_j$">, 00135 and <IMG 00136 WIDTH="23" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00137 SRC="gif/multidimfit_img16.gif" 00138 ALT="$ E_j$"> is the square error in <IMG 00139 WIDTH="24" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00140 SRC="gif/multidimfit_img14.gif" 00141 ALT="$ D_j$">, the class 00142 <A NAME="tex2html3" 00143 HREF="./TMultiDimFit.html"><TT>TMultiDimFit</TT></A> 00144 will 00145 try to find the parameterization 00146 <P></P> 00147 <DIV ALIGN="CENTER"><A NAME="Dp"></A><!-- MATH 00148 \begin{equation} 00149 D_p(\mathbf{x}) = \sum_{l=1}^{L} c_l \prod_{i=1}^{N} p_{li}\left(x_i\right) 00150 = \sum_{l=1}^{L} c_l F_l(\mathbf{x}) 00151 \end{equation} 00152 --> 00153 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00154 <TR VALIGN="MIDDLE"> 00155 <TD NOWRAP ALIGN="CENTER"><IMG 00156 WIDTH="274" HEIGHT="65" ALIGN="MIDDLE" BORDER="0" 00157 SRC="gif/multidimfit_img17.gif" 00158 ALT="$\displaystyle D_p(\mathbf{x}) = \sum_{l=1}^{L} c_l \prod_{i=1}^{N} p_{li}\left(x_i\right) = \sum_{l=1}^{L} c_l F_l(\mathbf{x})$"></TD> 00159 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00160 (1)</TD></TR> 00161 </TABLE></DIV> 00162 <BR CLEAR="ALL"><P></P> 00163 such that 00164 <P></P> 00165 <DIV ALIGN="CENTER"><A NAME="S"></A><!-- MATH 00166 \begin{equation} 00167 S \equiv \sum_{j=1}^{M} \left(D_j - D_p\left(\mathbf{x}_j\right)\right)^2 00168 \end{equation} 00169 --> 00170 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00171 <TR VALIGN="MIDDLE"> 00172 <TD NOWRAP ALIGN="CENTER"><IMG 00173 WIDTH="172" HEIGHT="65" ALIGN="MIDDLE" BORDER="0" 00174 SRC="gif/multidimfit_img18.gif" 00175 ALT="$\displaystyle S \equiv \sum_{j=1}^{M} \left(D_j - D_p\left(\mathbf{x}_j\right)\right)^2$"></TD> 00176 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00177 (2)</TD></TR> 00178 </TABLE></DIV> 00179 <BR CLEAR="ALL"><P></P> 00180 is minimal. Here <!-- MATH 00181 $p_{li}(x_i)$ 00182 --> 00183 <IMG 00184 WIDTH="48" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00185 SRC="gif/multidimfit_img19.gif" 00186 ALT="$ p_{li}(x_i)$"> are monomials, or Chebyshev or Legendre 00187 polynomials, labelled <!-- MATH 00188 $l = 1, \ldots, L$ 00189 --> 00190 <IMG 00191 WIDTH="87" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00192 SRC="gif/multidimfit_img20.gif" 00193 ALT="$ l = 1, \ldots, L$">, in each variable 00194 <IMG 00195 WIDTH="18" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00196 SRC="gif/multidimfit_img21.gif" 00197 ALT="$ x_i$">, <!-- MATH 00198 $i=1, \ldots, N$ 00199 --> 00200 <IMG 00201 WIDTH="91" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00202 SRC="gif/multidimfit_img22.gif" 00203 ALT="$ i=1, \ldots, N$">. 00204 00205 <P> 00206 So what <TT>TMultiDimFit</TT> does, is to determine the number of 00207 terms <IMG 00208 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00209 SRC="gif/multidimfit_img23.gif" 00210 ALT="$ L$">, and then <IMG 00211 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00212 SRC="gif/multidimfit_img23.gif" 00213 ALT="$ L$"> terms (or functions) <IMG 00214 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00215 SRC="gif/multidimfit_img24.gif" 00216 ALT="$ F_l$">, and the <IMG 00217 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00218 SRC="gif/multidimfit_img23.gif" 00219 ALT="$ L$"> 00220 coefficients <IMG 00221 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00222 SRC="gif/multidimfit_img25.gif" 00223 ALT="$ c_l$">, so that <IMG 00224 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00225 SRC="gif/multidimfit_img26.gif" 00226 ALT="$ S$"> is minimal 00227 (<A NAME="tex2html4" 00228 HREF=" 00229 ./TMultiDimFit.html#TMultiDimFit:FindParameterization"><TT>TMultiDimFit::FindParameterization</TT></A>). 00230 00231 <P> 00232 Of course it's more than a little unlikely that <IMG 00233 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00234 SRC="gif/multidimfit_img26.gif" 00235 ALT="$ S$"> will ever become 00236 exact zero as a result of the procedure outlined below. Therefore, the 00237 user is asked to provide a minimum relative error <IMG 00238 WIDTH="11" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00239 SRC="gif/multidimfit_img27.gif" 00240 ALT="$ \epsilon$"> 00241 (<A NAME="tex2html5" 00242 HREF=" 00243 ./TMultiDimFit.html#TMultiDimFit:SetMinRelativeError"><TT>TMultiDimFit::SetMinRelativeError</TT></A>), and <IMG 00244 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00245 SRC="gif/multidimfit_img26.gif" 00246 ALT="$ S$"> 00247 will be considered minimized when 00248 <!-- MATH 00249 \begin{displaymath} 00250 R = \frac{S}{\sum_{j=1}^M D_j^2} < \epsilon 00251 \end{displaymath} 00252 --> 00253 <P></P><DIV ALIGN="CENTER"> 00254 <IMG 00255 WIDTH="132" HEIGHT="51" ALIGN="MIDDLE" BORDER="0" 00256 SRC="gif/multidimfit_img28.gif" 00257 ALT="$\displaystyle R = \frac{S}{\sum_{j=1}^M D_j^2} < \epsilon 00258 $"> 00259 </DIV><P></P> 00260 00261 <P> 00262 Optionally, the user may impose a functional expression by specifying 00263 the powers of each variable in <IMG 00264 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00265 SRC="gif/multidimfit_img23.gif" 00266 ALT="$ L$"> specified functions <!-- MATH 00267 $F_1, \ldots, 00268 F_L$ 00269 --> 00270 <IMG 00271 WIDTH="79" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00272 SRC="gif/multidimfit_img29.gif" 00273 ALT="$ F_1, \ldots, 00274 F_L$"> (<A NAME="tex2html6" 00275 HREF=" 00276 ./TMultiDimFit.html#TMultiDimFit:SetPowers"><TT>TMultiDimFit::SetPowers</TT></A>). In that case, only the 00277 coefficients <IMG 00278 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00279 SRC="gif/multidimfit_img25.gif" 00280 ALT="$ c_l$"> is calculated by the class. 00281 00282 <P> 00283 00284 <H2><A NAME="SECTION00031000000000000000"></A> 00285 <A NAME="sec:selection"></A><BR> 00286 Limiting the Number of Terms 00287 </H2> 00288 00289 <P> 00290 As always when dealing with fits, there's a real chance of 00291 <I>over fitting</I>. As is well-known, it's always possible to fit an 00292 <IMG 00293 WIDTH="46" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00294 SRC="gif/multidimfit_img30.gif" 00295 ALT="$ N-1$"> polynomial in <IMG 00296 WIDTH="13" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00297 SRC="gif/multidimfit_img31.gif" 00298 ALT="$ x$"> to <IMG 00299 WIDTH="19" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00300 SRC="gif/multidimfit_img13.gif" 00301 ALT="$ N$"> points <IMG 00302 WIDTH="41" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00303 SRC="gif/multidimfit_img32.gif" 00304 ALT="$ (x,y)$"> with <!-- MATH 00305 $\chi^2 = 0$ 00306 --> 00307 <IMG 00308 WIDTH="50" HEIGHT="33" ALIGN="MIDDLE" BORDER="0" 00309 SRC="gif/multidimfit_img33.gif" 00310 ALT="$ \chi^2 = 0$">, but 00311 the polynomial is not likely to fit new data at all 00312 [<A 00313 HREF="TMultiFimFit.html#bevington">1</A>]. Therefore, the user is asked to provide an upper 00314 limit, <IMG 00315 WIDTH="41" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00316 SRC="gif/multidimfit_img34.gif" 00317 ALT="$ L_{max}$"> to the number of terms in <IMG 00318 WIDTH="25" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00319 SRC="gif/multidimfit_img35.gif" 00320 ALT="$ D_p$"> 00321 (<A NAME="tex2html7" 00322 HREF=" 00323 ./TMultiDimFit.html#TMultiDimFit:SetMaxTerms"><TT>TMultiDimFit::SetMaxTerms</TT></A>). 00324 00325 <P> 00326 However, since there's an infinite number of <IMG 00327 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00328 SRC="gif/multidimfit_img24.gif" 00329 ALT="$ F_l$"> to choose from, the 00330 user is asked to give the maximum power. <IMG 00331 WIDTH="49" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00332 SRC="gif/multidimfit_img36.gif" 00333 ALT="$ P_{max,i}$">, of each variable 00334 <IMG 00335 WIDTH="18" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00336 SRC="gif/multidimfit_img21.gif" 00337 ALT="$ x_i$"> to be considered in the minimization of <IMG 00338 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00339 SRC="gif/multidimfit_img26.gif" 00340 ALT="$ S$"> 00341 (<A NAME="tex2html8" 00342 HREF=" 00343 ./TMultiDimFit.html#TMultiDimFit:SetMaxPowers"><TT>TMultiDimFit::SetMaxPowers</TT></A>). 00344 00345 <P> 00346 One way of obtaining values for the maximum power in variable <IMG 00347 WIDTH="10" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00348 SRC="gif/multidimfit_img37.gif" 00349 ALT="$ i$">, is 00350 to perform a regular fit to the dependent quantity <IMG 00351 WIDTH="18" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00352 SRC="gif/multidimfit_img7.gif" 00353 ALT="$ D$">, using a 00354 polynomial only in <IMG 00355 WIDTH="18" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00356 SRC="gif/multidimfit_img21.gif" 00357 ALT="$ x_i$">. The maximum power is <IMG 00358 WIDTH="49" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00359 SRC="gif/multidimfit_img36.gif" 00360 ALT="$ P_{max,i}$"> is then the 00361 power that does not significantly improve the one-dimensional 00362 least-square fit over <IMG 00363 WIDTH="18" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00364 SRC="gif/multidimfit_img21.gif" 00365 ALT="$ x_i$"> to <IMG 00366 WIDTH="18" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00367 SRC="gif/multidimfit_img7.gif" 00368 ALT="$ D$"> [<A 00369 HREF="TMultiFimFit.html#wind72">5</A>]. 00370 00371 <P> 00372 There are still a huge amount of possible choices for <IMG 00373 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00374 SRC="gif/multidimfit_img24.gif" 00375 ALT="$ F_l$">; in fact 00376 there are <!-- MATH 00377 $\prod_{i=1}^{N} (P_{max,i} + 1)$ 00378 --> 00379 <IMG 00380 WIDTH="125" HEIGHT="39" ALIGN="MIDDLE" BORDER="0" 00381 SRC="gif/multidimfit_img38.gif" 00382 ALT="$ \prod_{i=1}^{N} (P_{max,i} + 1)$"> possible 00383 choices. Obviously we need to limit this. To this end, the user is 00384 asked to set a <I>power control limit</I>, <IMG 00385 WIDTH="17" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00386 SRC="gif/multidimfit_img39.gif" 00387 ALT="$ Q$"> 00388 (<A NAME="tex2html9" 00389 HREF=" 00390 ./TMultiDimFit.html#TMultiDimFit:SetPowerLimit"><TT>TMultiDimFit::SetPowerLimit</TT></A>), and a function 00391 <IMG 00392 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00393 SRC="gif/multidimfit_img24.gif" 00394 ALT="$ F_l$"> is only accepted if 00395 <!-- MATH 00396 \begin{displaymath} 00397 Q_l = \sum_{i=1}^{N} \frac{P_{li}}{P_{max,i}} < Q 00398 \end{displaymath} 00399 --> 00400 <P></P><DIV ALIGN="CENTER"> 00401 <IMG 00402 WIDTH="151" HEIGHT="65" ALIGN="MIDDLE" BORDER="0" 00403 SRC="gif/multidimfit_img40.gif" 00404 ALT="$\displaystyle Q_l = \sum_{i=1}^{N} \frac{P_{li}}{P_{max,i}} < Q 00405 $"> 00406 </DIV><P></P> 00407 where <IMG 00408 WIDTH="24" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00409 SRC="gif/multidimfit_img41.gif" 00410 ALT="$ P_{li}$"> is the leading power of variable <IMG 00411 WIDTH="18" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00412 SRC="gif/multidimfit_img21.gif" 00413 ALT="$ x_i$"> in function 00414 <IMG 00415 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00416 SRC="gif/multidimfit_img24.gif" 00417 ALT="$ F_l$">. (<A NAME="tex2html10" 00418 HREF=" 00419 00420 ./TMultiDimFit.html#TMultiDimFit:MakeCandidates"><TT>TMultiDimFit::MakeCandidates</TT></A>). So the number of 00421 functions increase with <IMG 00422 WIDTH="17" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00423 SRC="gif/multidimfit_img39.gif" 00424 ALT="$ Q$"> (1, 2 is fine, 5 is way out). 00425 00426 <P> 00427 00428 <H2><A NAME="SECTION00032000000000000000"> 00429 Gram-Schmidt Orthogonalisation</A> 00430 </H2> 00431 00432 <P> 00433 To further reduce the number of functions in the final expression, 00434 only those functions that significantly reduce <IMG 00435 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00436 SRC="gif/multidimfit_img26.gif" 00437 ALT="$ S$"> is chosen. What 00438 `significant' means, is chosen by the user, and will be 00439 discussed below (see <A HREF="TMultiFimFit.html#sec:selectiondetail">2.3</A>). 00440 00441 <P> 00442 The functions <IMG 00443 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00444 SRC="gif/multidimfit_img24.gif" 00445 ALT="$ F_l$"> are generally not orthogonal, which means one will 00446 have to evaluate all possible <IMG 00447 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00448 SRC="gif/multidimfit_img24.gif" 00449 ALT="$ F_l$">'s over all data-points before 00450 finding the most significant [<A 00451 HREF="TMultiFimFit.html#bevington">1</A>]. We can, however, do 00452 better then that. By applying the <I>modified Gram-Schmidt 00453 orthogonalisation</I> algorithm [<A 00454 HREF="TMultiFimFit.html#wind72">5</A>] [<A 00455 HREF="TMultiFimFit.html#golub">3</A>] to the 00456 functions <IMG 00457 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00458 SRC="gif/multidimfit_img24.gif" 00459 ALT="$ F_l$">, we can evaluate the contribution to the reduction of 00460 <IMG 00461 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00462 SRC="gif/multidimfit_img26.gif" 00463 ALT="$ S$"> from each function in turn, and we may delay the actual inversion 00464 of the curvature-matrix 00465 (<A NAME="tex2html11" 00466 HREF=" 00467 ./TMultiDimFit.html#TMultiDimFit:MakeGramSchmidt"><TT>TMultiDimFit::MakeGramSchmidt</TT></A>). 00468 00469 <P> 00470 So we are let to consider an <IMG 00471 WIDTH="52" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00472 SRC="gif/multidimfit_img42.gif" 00473 ALT="$ M\times L$"> matrix <!-- MATH 00474 $\mathsf{F}$ 00475 --> 00476 <IMG 00477 WIDTH="13" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00478 SRC="gif/multidimfit_img43.gif" 00479 ALT="$ \mathsf{F}$">, an 00480 element of which is given by 00481 <P></P> 00482 <DIV ALIGN="CENTER"><A NAME="eq:Felem"></A><!-- MATH 00483 \begin{equation} 00484 f_{jl} = F_j\left(x_{1j} , x_{2j}, \ldots, x_{Nj}\right) 00485 = F_l(\mathbf{x}_j)\, \quad\mbox{with}~j=1,2,\ldots,M, 00486 \end{equation} 00487 --> 00488 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00489 <TR VALIGN="MIDDLE"> 00490 <TD NOWRAP ALIGN="CENTER"><IMG 00491 WIDTH="260" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00492 SRC="gif/multidimfit_img44.gif" 00493 ALT="$\displaystyle f_{jl} = F_j\left(x_{1j} , x_{2j}, \ldots, x_{Nj}\right) = F_l(\mathbf{x}_j) $"> with<IMG 00494 WIDTH="120" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00495 SRC="gif/multidimfit_img45.gif" 00496 ALT="$\displaystyle j=1,2,\ldots,M,$"></TD> 00497 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00498 (3)</TD></TR> 00499 </TABLE></DIV> 00500 <BR CLEAR="ALL"><P></P> 00501 where <IMG 00502 WIDTH="12" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00503 SRC="gif/multidimfit_img46.gif" 00504 ALT="$ j$"> labels the <IMG 00505 WIDTH="21" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00506 SRC="gif/multidimfit_img10.gif" 00507 ALT="$ M$"> rows in the training sample and <IMG 00508 WIDTH="9" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00509 SRC="gif/multidimfit_img47.gif" 00510 ALT="$ l$"> labels 00511 <IMG 00512 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00513 SRC="gif/multidimfit_img23.gif" 00514 ALT="$ L$"> functions of <IMG 00515 WIDTH="19" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00516 SRC="gif/multidimfit_img13.gif" 00517 ALT="$ N$"> variables, and <IMG 00518 WIDTH="53" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00519 SRC="gif/multidimfit_img48.gif" 00520 ALT="$ L \leq M$">. That is, <IMG 00521 WIDTH="23" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00522 SRC="gif/multidimfit_img49.gif" 00523 ALT="$ f_{jl}$"> is 00524 the term (or function) numbered <IMG 00525 WIDTH="9" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00526 SRC="gif/multidimfit_img47.gif" 00527 ALT="$ l$"> evaluated at the data point 00528 <IMG 00529 WIDTH="12" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00530 SRC="gif/multidimfit_img46.gif" 00531 ALT="$ j$">. We have to normalise <!-- MATH 00532 $\mathbf{x}_j$ 00533 --> 00534 <IMG 00535 WIDTH="20" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00536 SRC="gif/multidimfit_img15.gif" 00537 ALT="$ \mathbf{x}_j$"> to <IMG 00538 WIDTH="48" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00539 SRC="gif/multidimfit_img50.gif" 00540 ALT="$ [-1,1]$"> for this to 00541 succeed [<A 00542 HREF="TMultiFimFit.html#wind72">5</A>] 00543 (<A NAME="tex2html12" 00544 HREF=" 00545 ./TMultiDimFit.html#TMultiDimFit:MakeNormalized"><TT>TMultiDimFit::MakeNormalized</TT></A>). We then define a 00546 matrix <!-- MATH 00547 $\mathsf{W}$ 00548 --> 00549 <IMG 00550 WIDTH="19" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00551 SRC="gif/multidimfit_img51.gif" 00552 ALT="$ \mathsf{W}$"> of which the columns <!-- MATH 00553 $\mathbf{w}_j$ 00554 --> 00555 <IMG 00556 WIDTH="24" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00557 SRC="gif/multidimfit_img52.gif" 00558 ALT="$ \mathbf{w}_j$"> are given by 00559 <BR> 00560 <DIV ALIGN="CENTER"><A NAME="eq:wj"></A><!-- MATH 00561 \begin{eqnarray} 00562 \mathbf{w}_1 &=& \mathbf{f}_1 = F_1\left(\mathbf x_1\right)\\ 00563 \mathbf{w}_l &=& \mathbf{f}_l - \sum^{l-1}_{k=1} \frac{\mathbf{f}_l \bullet 00564 \mathbf{w}_k}{\mathbf{w}_k^2}\mathbf{w}_k\,. 00565 \end{eqnarray} 00566 --> 00567 <TABLE CELLPADDING="0" ALIGN="CENTER" WIDTH="100%"> 00568 <TR VALIGN="MIDDLE"><TD NOWRAP ALIGN="RIGHT"><IMG 00569 WIDTH="25" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00570 SRC="gif/multidimfit_img53.gif" 00571 ALT="$\displaystyle \mathbf{w}_1$"></TD> 00572 <TD WIDTH="10" ALIGN="CENTER" NOWRAP><IMG 00573 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00574 SRC="gif/multidimfit_img54.gif" 00575 ALT="$\displaystyle =$"></TD> 00576 <TD ALIGN="LEFT" NOWRAP><IMG 00577 WIDTH="87" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00578 SRC="gif/multidimfit_img55.gif" 00579 ALT="$\displaystyle \mathbf{f}_1 = F_1\left(\mathbf x_1\right)$"></TD> 00580 <TD WIDTH=10 ALIGN="RIGHT"> 00581 (4)</TD></TR> 00582 <TR VALIGN="MIDDLE"><TD NOWRAP ALIGN="RIGHT"><IMG 00583 WIDTH="22" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00584 SRC="gif/multidimfit_img56.gif" 00585 ALT="$\displaystyle \mathbf{w}_l$"></TD> 00586 <TD WIDTH="10" ALIGN="CENTER" NOWRAP><IMG 00587 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00588 SRC="gif/multidimfit_img54.gif" 00589 ALT="$\displaystyle =$"></TD> 00590 <TD ALIGN="LEFT" NOWRAP><IMG 00591 WIDTH="138" HEIGHT="66" ALIGN="MIDDLE" BORDER="0" 00592 SRC="gif/multidimfit_img57.gif" 00593 ALT="$\displaystyle \mathbf{f}_l - \sum^{l-1}_{k=1} \frac{\mathbf{f}_l \bullet 00594 \mathbf{w}_k}{\mathbf{w}_k^2}\mathbf{w}_k .$"></TD> 00595 <TD WIDTH=10 ALIGN="RIGHT"> 00596 (5)</TD></TR> 00597 </TABLE></DIV> 00598 <BR CLEAR="ALL"><P></P> 00599 and <!-- MATH 00600 $\mathbf{w}_{l}$ 00601 --> 00602 <IMG 00603 WIDTH="22" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00604 SRC="gif/multidimfit_img58.gif" 00605 ALT="$ \mathbf{w}_{l}$"> is the component of <!-- MATH 00606 $\mathbf{f}_{l}$ 00607 --> 00608 <IMG 00609 WIDTH="15" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00610 SRC="gif/multidimfit_img59.gif" 00611 ALT="$ \mathbf{f}_{l}$"> orthogonal 00612 to <!-- MATH 00613 $\mathbf{w}_{1}, \ldots, \mathbf{w}_{l-1}$ 00614 --> 00615 <IMG 00616 WIDTH="97" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00617 SRC="gif/multidimfit_img60.gif" 00618 ALT="$ \mathbf{w}_{1}, \ldots, \mathbf{w}_{l-1}$">. Hence we obtain 00619 [<A 00620 HREF="TMultiFimFit.html#golub">3</A>], 00621 <P></P> 00622 <DIV ALIGN="CENTER"><A NAME="eq:worto"></A><!-- MATH 00623 \begin{equation} 00624 \mathbf{w}_k\bullet\mathbf{w}_l = 0\quad\mbox{if}~k \neq l\quad. 00625 \end{equation} 00626 --> 00627 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00628 <TR VALIGN="MIDDLE"> 00629 <TD NOWRAP ALIGN="CENTER"><IMG 00630 WIDTH="87" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00631 SRC="gif/multidimfit_img61.gif" 00632 ALT="$\displaystyle \mathbf{w}_k\bullet\mathbf{w}_l = 0$"> if<IMG 00633 WIDTH="65" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00634 SRC="gif/multidimfit_img62.gif" 00635 ALT="$\displaystyle k \neq l\quad.$"></TD> 00636 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00637 (6)</TD></TR> 00638 </TABLE></DIV> 00639 <BR CLEAR="ALL"><P></P> 00640 00641 <P> 00642 We now take as a new model <!-- MATH 00643 $\mathsf{W}\mathbf{a}$ 00644 --> 00645 <IMG 00646 WIDTH="28" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 00647 SRC="gif/multidimfit_img63.gif" 00648 ALT="$ \mathsf{W}\mathbf{a}$">. We thus want to 00649 minimize 00650 <P></P> 00651 <DIV ALIGN="CENTER"><A NAME="eq:S"></A><!-- MATH 00652 \begin{equation} 00653 S\equiv \left(\mathbf{D} - \mathsf{W}\mathbf{a}\right)^2\quad, 00654 \end{equation} 00655 --> 00656 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00657 <TR VALIGN="MIDDLE"> 00658 <TD NOWRAP ALIGN="CENTER"><IMG 00659 WIDTH="136" HEIGHT="38" ALIGN="MIDDLE" BORDER="0" 00660 SRC="gif/multidimfit_img64.gif" 00661 ALT="$\displaystyle S\equiv \left(\mathbf{D} - \mathsf{W}\mathbf{a}\right)^2\quad,$"></TD> 00662 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00663 (7)</TD></TR> 00664 </TABLE></DIV> 00665 <BR CLEAR="ALL"><P></P> 00666 where <!-- MATH 00667 $\mathbf{D} = \left(D_1,\ldots,D_M\right)$ 00668 --> 00669 <IMG 00670 WIDTH="137" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 00671 SRC="gif/multidimfit_img65.gif" 00672 ALT="$ \mathbf{D} = \left(D_1,\ldots,D_M\right)$"> is a vector of the 00673 dependent quantity in the sample. Differentiation with respect to 00674 <IMG 00675 WIDTH="19" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00676 SRC="gif/multidimfit_img66.gif" 00677 ALT="$ a_j$"> gives, using (<A HREF="TMultiFimFit.html#eq:worto">6</A>), 00678 <P></P> 00679 <DIV ALIGN="CENTER"><A NAME="eq:dS"></A><!-- MATH 00680 \begin{equation} 00681 \mathbf{D}\bullet\mathbf{w}_l - a_l\mathbf{w}_l^2 = 0 00682 \end{equation} 00683 --> 00684 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00685 <TR VALIGN="MIDDLE"> 00686 <TD NOWRAP ALIGN="CENTER"><IMG 00687 WIDTH="134" HEIGHT="35" ALIGN="MIDDLE" BORDER="0" 00688 SRC="gif/multidimfit_img67.gif" 00689 ALT="$\displaystyle \mathbf{D}\bullet\mathbf{w}_l - a_l\mathbf{w}_l^2 = 0$"></TD> 00690 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00691 (8)</TD></TR> 00692 </TABLE></DIV> 00693 <BR CLEAR="ALL"><P></P> 00694 or 00695 <P></P> 00696 <DIV ALIGN="CENTER"><A NAME="eq:dS2"></A><!-- MATH 00697 \begin{equation} 00698 a_l = \frac{\mathbf{D}_l\bullet\mathbf{w}_l}{\mathbf{w}_l^2} 00699 \end{equation} 00700 --> 00701 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00702 <TR VALIGN="MIDDLE"> 00703 <TD NOWRAP ALIGN="CENTER"><IMG 00704 WIDTH="95" HEIGHT="51" ALIGN="MIDDLE" BORDER="0" 00705 SRC="gif/multidimfit_img68.gif" 00706 ALT="$\displaystyle a_l = \frac{\mathbf{D}_l\bullet\mathbf{w}_l}{\mathbf{w}_l^2}$"></TD> 00707 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00708 (9)</TD></TR> 00709 </TABLE></DIV> 00710 <BR CLEAR="ALL"><P></P> 00711 Let <IMG 00712 WIDTH="21" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00713 SRC="gif/multidimfit_img69.gif" 00714 ALT="$ S_j$"> be the sum of squares of residuals when taking <IMG 00715 WIDTH="12" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00716 SRC="gif/multidimfit_img46.gif" 00717 ALT="$ j$"> functions 00718 into account. Then 00719 <P></P> 00720 <DIV ALIGN="CENTER"><A NAME="eq:Sj"></A><!-- MATH 00721 \begin{equation} 00722 S_l = \left[\mathbf{D} - \sum^l_{k=1} a_k\mathbf{w}_k\right]^2 00723 = \mathbf{D}^2 - 2\mathbf{D} \sum^l_{k=1} a_k\mathbf{w}_k 00724 + \sum^l_{k=1} a_k^2\mathbf{w}_k^2 00725 \end{equation} 00726 --> 00727 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00728 <TR VALIGN="MIDDLE"> 00729 <TD NOWRAP ALIGN="CENTER"><IMG 00730 WIDTH="394" HEIGHT="72" ALIGN="MIDDLE" BORDER="0" 00731 SRC="gif/multidimfit_img70.gif" 00732 ALT="$\displaystyle S_l = \left[\mathbf{D} - \sum^l_{k=1} a_k\mathbf{w}_k\right]^2 = ... 00733 ...2 - 2\mathbf{D} \sum^l_{k=1} a_k\mathbf{w}_k + \sum^l_{k=1} a_k^2\mathbf{w}_k^2$"></TD> 00734 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00735 (10)</TD></TR> 00736 </TABLE></DIV> 00737 <BR CLEAR="ALL"><P></P> 00738 Using (<A HREF="TMultiFimFit.html#eq:dS2">9</A>), we see that 00739 <BR> 00740 <DIV ALIGN="CENTER"><A NAME="eq:sj2"></A><!-- MATH 00741 \begin{eqnarray} 00742 S_l &=& \mathbf{D}^2 - 2 \sum^l_{k=1} a_k^2\mathbf{w}_k^2 + 00743 \sum^j_{k=1} a_k^2\mathbf{w}_k^2\nonumber\\ 00744 &=& \mathbf{D}^2 - \sum^l_{k=1} a_k^2\mathbf{w}_k^2\nonumber\\ 00745 &=& \mathbf{D}^2 - \sum^l_{k=1} \frac{\left(\mathbf D\bullet \mathbf 00746 w_k\right)}{\mathbf w_k^2} 00747 \end{eqnarray} 00748 --> 00749 <TABLE CELLPADDING="0" ALIGN="CENTER" WIDTH="100%"> 00750 <TR VALIGN="MIDDLE"><TD NOWRAP ALIGN="RIGHT"><IMG 00751 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00752 SRC="gif/multidimfit_img71.gif" 00753 ALT="$\displaystyle S_l$"></TD> 00754 <TD WIDTH="10" ALIGN="CENTER" NOWRAP><IMG 00755 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00756 SRC="gif/multidimfit_img54.gif" 00757 ALT="$\displaystyle =$"></TD> 00758 <TD ALIGN="LEFT" NOWRAP><IMG 00759 WIDTH="201" HEIGHT="67" ALIGN="MIDDLE" BORDER="0" 00760 SRC="gif/multidimfit_img72.gif" 00761 ALT="$\displaystyle \mathbf{D}^2 - 2 \sum^l_{k=1} a_k^2\mathbf{w}_k^2 + 00762 \sum^j_{k=1} a_k^2\mathbf{w}_k^2$"></TD> 00763 <TD WIDTH=10 ALIGN="RIGHT"> 00764 </TD></TR> 00765 <TR VALIGN="MIDDLE"><TD NOWRAP ALIGN="RIGHT"> </TD> 00766 <TD WIDTH="10" ALIGN="CENTER" NOWRAP><IMG 00767 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00768 SRC="gif/multidimfit_img54.gif" 00769 ALT="$\displaystyle =$"></TD> 00770 <TD ALIGN="LEFT" NOWRAP><IMG 00771 WIDTH="108" HEIGHT="66" ALIGN="MIDDLE" BORDER="0" 00772 SRC="gif/multidimfit_img73.gif" 00773 ALT="$\displaystyle \mathbf{D}^2 - \sum^l_{k=1} a_k^2\mathbf{w}_k^2$"></TD> 00774 <TD WIDTH=10 ALIGN="RIGHT"> 00775 </TD></TR> 00776 <TR VALIGN="MIDDLE"><TD NOWRAP ALIGN="RIGHT"> </TD> 00777 <TD WIDTH="10" ALIGN="CENTER" NOWRAP><IMG 00778 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00779 SRC="gif/multidimfit_img54.gif" 00780 ALT="$\displaystyle =$"></TD> 00781 <TD ALIGN="LEFT" NOWRAP><IMG 00782 WIDTH="137" HEIGHT="66" ALIGN="MIDDLE" BORDER="0" 00783 SRC="gif/multidimfit_img74.gif" 00784 ALT="$\displaystyle \mathbf{D}^2 - \sum^l_{k=1} \frac{\left(\mathbf D\bullet \mathbf 00785 w_k\right)}{\mathbf w_k^2}$"></TD> 00786 <TD WIDTH=10 ALIGN="RIGHT"> 00787 (11)</TD></TR> 00788 </TABLE></DIV> 00789 <BR CLEAR="ALL"><P></P> 00790 00791 <P> 00792 So for each new function <IMG 00793 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00794 SRC="gif/multidimfit_img24.gif" 00795 ALT="$ F_l$"> included in the model, we get a 00796 reduction of the sum of squares of residuals of <!-- MATH 00797 $a_l^2\mathbf{w}_l^2$ 00798 --> 00799 <IMG 00800 WIDTH="40" HEIGHT="33" ALIGN="MIDDLE" BORDER="0" 00801 SRC="gif/multidimfit_img75.gif" 00802 ALT="$ a_l^2\mathbf{w}_l^2$">, 00803 where <!-- MATH 00804 $\mathbf{w}_l$ 00805 --> 00806 <IMG 00807 WIDTH="22" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00808 SRC="gif/multidimfit_img76.gif" 00809 ALT="$ \mathbf{w}_l$"> is given by (<A HREF="TMultiFimFit.html#eq:wj">4</A>) and <IMG 00810 WIDTH="17" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00811 SRC="gif/multidimfit_img77.gif" 00812 ALT="$ a_l$"> by 00813 (<A HREF="TMultiFimFit.html#eq:dS2">9</A>). Thus, using the Gram-Schmidt orthogonalisation, we 00814 can decide if we want to include this function in the final model, 00815 <I>before</I> the matrix inversion. 00816 00817 <P> 00818 00819 <H2><A NAME="SECTION00033000000000000000"></A> 00820 <A NAME="sec:selectiondetail"></A><BR> 00821 Function Selection Based on Residual 00822 </H2> 00823 00824 <P> 00825 Supposing that <IMG 00826 WIDTH="42" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00827 SRC="gif/multidimfit_img78.gif" 00828 ALT="$ L-1$"> steps of the procedure have been performed, the 00829 problem now is to consider the <!-- MATH 00830 $L^{\mbox{th}}$ 00831 --> 00832 <IMG 00833 WIDTH="31" HEIGHT="20" ALIGN="BOTTOM" BORDER="0" 00834 SRC="gif/multidimfit_img79.gif" 00835 ALT="$ L^{\mbox{th}}$"> function. 00836 00837 <P> 00838 The sum of squares of residuals can be written as 00839 <P></P> 00840 <DIV ALIGN="CENTER"><A NAME="eq:sums"></A><!-- MATH 00841 \begin{equation} 00842 S_L = \textbf{D}^T\bullet\textbf{D} - 00843 \sum^L_{l=1}a^2_l\left(\textbf{w}_l^T\bullet\textbf{w}_l\right) 00844 \end{equation} 00845 --> 00846 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00847 <TR VALIGN="MIDDLE"> 00848 <TD NOWRAP ALIGN="CENTER"><IMG 00849 WIDTH="232" HEIGHT="65" ALIGN="MIDDLE" BORDER="0" 00850 SRC="gif/multidimfit_img80.gif" 00851 ALT="$\displaystyle S_L = \textbf{D}^T\bullet\textbf{D} - \sum^L_{l=1}a^2_l\left(\textbf{w}_l^T\bullet\textbf{w}_l\right)$"></TD> 00852 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00853 (12)</TD></TR> 00854 </TABLE></DIV> 00855 <BR CLEAR="ALL"><P></P> 00856 where the relation (<A HREF="TMultiFimFit.html#eq:dS2">9</A>) have been taken into account. The 00857 contribution of the <!-- MATH 00858 $L^{\mbox{th}}$ 00859 --> 00860 <IMG 00861 WIDTH="31" HEIGHT="20" ALIGN="BOTTOM" BORDER="0" 00862 SRC="gif/multidimfit_img79.gif" 00863 ALT="$ L^{\mbox{th}}$"> function to the reduction of S, is 00864 given by 00865 <P></P> 00866 <DIV ALIGN="CENTER"><A NAME="eq:dSN"></A><!-- MATH 00867 \begin{equation} 00868 \Delta S_L = a^2_L\left(\textbf{w}_L^T\bullet\textbf{w}_L\right) 00869 \end{equation} 00870 --> 00871 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 00872 <TR VALIGN="MIDDLE"> 00873 <TD NOWRAP ALIGN="CENTER"><IMG 00874 WIDTH="154" HEIGHT="36" ALIGN="MIDDLE" BORDER="0" 00875 SRC="gif/multidimfit_img81.gif" 00876 ALT="$\displaystyle \Delta S_L = a^2_L\left(\textbf{w}_L^T\bullet\textbf{w}_L\right)$"></TD> 00877 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 00878 (13)</TD></TR> 00879 </TABLE></DIV> 00880 <BR CLEAR="ALL"><P></P> 00881 00882 <P> 00883 Two test are now applied to decide whether this <!-- MATH 00884 $L^{\mbox{th}}$ 00885 --> 00886 <IMG 00887 WIDTH="31" HEIGHT="20" ALIGN="BOTTOM" BORDER="0" 00888 SRC="gif/multidimfit_img79.gif" 00889 ALT="$ L^{\mbox{th}}$"> 00890 function is to be included in the final expression, or not. 00891 00892 <P> 00893 00894 <H3><A NAME="SECTION00033100000000000000"></A> 00895 <A NAME="testone"></A><BR> 00896 Test 1 00897 </H3> 00898 00899 <P> 00900 Denoting by <IMG 00901 WIDTH="43" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00902 SRC="gif/multidimfit_img82.gif" 00903 ALT="$ H_{L-1}$"> the subspace spanned by 00904 <!-- MATH 00905 $\textbf{w}_1,\ldots,\textbf{w}_{L-1}$ 00906 --> 00907 <IMG 00908 WIDTH="102" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00909 SRC="gif/multidimfit_img83.gif" 00910 ALT="$ \textbf{w}_1,\ldots,\textbf{w}_{L-1}$"> the function <!-- MATH 00911 $\textbf{w}_L$ 00912 --> 00913 <IMG 00914 WIDTH="27" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00915 SRC="gif/multidimfit_img5.gif" 00916 ALT="$ \textbf {w}_L$"> is 00917 by construction (see (<A HREF="TMultiFimFit.html#eq:wj">4</A>)) the projection of the function 00918 <IMG 00919 WIDTH="24" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00920 SRC="gif/multidimfit_img84.gif" 00921 ALT="$ F_L$"> onto the direction perpendicular to <IMG 00922 WIDTH="43" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00923 SRC="gif/multidimfit_img82.gif" 00924 ALT="$ H_{L-1}$">. Now, if the 00925 length of <!-- MATH 00926 $\textbf{w}_L$ 00927 --> 00928 <IMG 00929 WIDTH="27" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00930 SRC="gif/multidimfit_img5.gif" 00931 ALT="$ \textbf {w}_L$"> (given by <!-- MATH 00932 $\textbf{w}_L\bullet\textbf{w}_L$ 00933 --> 00934 <IMG 00935 WIDTH="65" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00936 SRC="gif/multidimfit_img85.gif" 00937 ALT="$ \textbf{w}_L\bullet\textbf{w}_L$">) 00938 is very small compared to the length of <!-- MATH 00939 $\textbf{f}_L$ 00940 --> 00941 <IMG 00942 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00943 SRC="gif/multidimfit_img3.gif" 00944 ALT="$ \textbf {f}_L$"> this new 00945 function can not contribute much to the reduction of the sum of 00946 squares of residuals. The test consists then in calculating the angle 00947 <IMG 00948 WIDTH="12" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00949 SRC="gif/multidimfit_img1.gif" 00950 ALT="$ \theta $"> between the two vectors <!-- MATH 00951 $\textbf{w}_L$ 00952 --> 00953 <IMG 00954 WIDTH="27" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00955 SRC="gif/multidimfit_img5.gif" 00956 ALT="$ \textbf {w}_L$"> and <!-- MATH 00957 $\textbf{f}_L$ 00958 --> 00959 <IMG 00960 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00961 SRC="gif/multidimfit_img3.gif" 00962 ALT="$ \textbf {f}_L$"> 00963 (see also figure <A HREF="TMultiFimFit.html#fig:thetaphi">1</A>) and requiring that it's 00964 <I>greater</I> then a threshold value which the user must set 00965 (<A NAME="tex2html14" 00966 HREF=" 00967 ./TMultiDimFit.html#TMultiDimFit:SetMinAngle"><TT>TMultiDimFit::SetMinAngle</TT></A>). 00968 00969 <P> 00970 00971 <P></P> 00972 <DIV ALIGN="CENTER"><A NAME="fig:thetaphi"></A><A NAME="519"></A> 00973 <TABLE> 00974 <CAPTION ALIGN="BOTTOM"><STRONG>Figure 1:</STRONG> 00975 (a) Angle <IMG 00976 WIDTH="12" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 00977 SRC="gif/multidimfit_img1.gif" 00978 ALT="$ \theta $"> between <!-- MATH 00979 $\textbf{w}_l$ 00980 --> 00981 <IMG 00982 WIDTH="22" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00983 SRC="gif/multidimfit_img2.gif" 00984 ALT="$ \textbf {w}_l$"> and 00985 <!-- MATH 00986 $\textbf{f}_L$ 00987 --> 00988 <IMG 00989 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00990 SRC="gif/multidimfit_img3.gif" 00991 ALT="$ \textbf {f}_L$">, (b) angle <IMG 00992 WIDTH="14" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 00993 SRC="gif/multidimfit_img4.gif" 00994 ALT="$ \phi $"> between <!-- MATH 00995 $\textbf{w}_L$ 00996 --> 00997 <IMG 00998 WIDTH="27" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 00999 SRC="gif/multidimfit_img5.gif" 01000 ALT="$ \textbf {w}_L$"> and 01001 <!-- MATH 01002 $\textbf{D}$ 01003 --> 01004 <IMG 01005 WIDTH="18" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01006 SRC="gif/multidimfit_img6.gif" 01007 ALT="$ \textbf {D}$"></CAPTION> 01008 <TR><TD><IMG 01009 WIDTH="466" HEIGHT="172" BORDER="0" 01010 SRC="gif/multidimfit_img86.gif" 01011 ALT="\begin{figure}\begin{center} 01012 \begin{tabular}{p{.4\textwidth}p{.4\textwidth}} 01013 \... 01014 ... \put(80,100){$\mathbf{D}$} 01015 \end{picture} \end{tabular} \end{center}\end{figure}"></TD></TR> 01016 </TABLE> 01017 </DIV><P></P> 01018 01019 <P> 01020 01021 <H3><A NAME="SECTION00033200000000000000"></A> <A NAME="testtwo"></A><BR> 01022 Test 2 01023 </H3> 01024 01025 <P> 01026 Let <!-- MATH 01027 $\textbf{D}$ 01028 --> 01029 <IMG 01030 WIDTH="18" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01031 SRC="gif/multidimfit_img6.gif" 01032 ALT="$ \textbf {D}$"> be the data vector to be fitted. As illustrated in 01033 figure <A HREF="TMultiFimFit.html#fig:thetaphi">1</A>, the <!-- MATH 01034 $L^{\mbox{th}}$ 01035 --> 01036 <IMG 01037 WIDTH="31" HEIGHT="20" ALIGN="BOTTOM" BORDER="0" 01038 SRC="gif/multidimfit_img79.gif" 01039 ALT="$ L^{\mbox{th}}$"> function <!-- MATH 01040 $\textbf{w}_L$ 01041 --> 01042 <IMG 01043 WIDTH="27" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01044 SRC="gif/multidimfit_img5.gif" 01045 ALT="$ \textbf {w}_L$"> 01046 will contribute significantly to the reduction of <IMG 01047 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01048 SRC="gif/multidimfit_img26.gif" 01049 ALT="$ S$">, if the angle 01050 <!-- MATH 01051 $\phi^\prime$ 01052 --> 01053 <IMG 01054 WIDTH="18" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01055 SRC="gif/multidimfit_img87.gif" 01056 ALT="$ \phi^\prime$"> between <!-- MATH 01057 $\textbf{w}_L$ 01058 --> 01059 <IMG 01060 WIDTH="27" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01061 SRC="gif/multidimfit_img5.gif" 01062 ALT="$ \textbf {w}_L$"> and <!-- MATH 01063 $\textbf{D}$ 01064 --> 01065 <IMG 01066 WIDTH="18" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01067 SRC="gif/multidimfit_img6.gif" 01068 ALT="$ \textbf {D}$"> is smaller than 01069 an upper limit <IMG 01070 WIDTH="14" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01071 SRC="gif/multidimfit_img4.gif" 01072 ALT="$ \phi $">, defined by the user 01073 (<A NAME="tex2html15" 01074 HREF=" 01075 ./TMultiDimFit.html#TMultiDimFit:SetMaxAngle"><TT>TMultiDimFit::SetMaxAngle</TT></A>) 01076 01077 <P> 01078 However, the method automatically readjusts the value of this angle 01079 while fitting is in progress, in order to make the selection criteria 01080 less and less difficult to be fulfilled. The result is that the 01081 functions contributing most to the reduction of <IMG 01082 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01083 SRC="gif/multidimfit_img26.gif" 01084 ALT="$ S$"> are chosen first 01085 (<A NAME="tex2html16" 01086 HREF=" 01087 ./TMultiDimFit.html#TMultiDimFit:TestFunction"><TT>TMultiDimFit::TestFunction</TT></A>). 01088 01089 <P> 01090 In case <IMG 01091 WIDTH="14" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01092 SRC="gif/multidimfit_img4.gif" 01093 ALT="$ \phi $"> isn't defined, an alternative method of 01094 performing this second test is used: The <!-- MATH 01095 $L^{\mbox{th}}$ 01096 --> 01097 <IMG 01098 WIDTH="31" HEIGHT="20" ALIGN="BOTTOM" BORDER="0" 01099 SRC="gif/multidimfit_img79.gif" 01100 ALT="$ L^{\mbox{th}}$"> function 01101 <!-- MATH 01102 $\textbf{f}_L$ 01103 --> 01104 <IMG 01105 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01106 SRC="gif/multidimfit_img3.gif" 01107 ALT="$ \textbf {f}_L$"> is accepted if (refer also to equation (<A HREF="TMultiFimFit.html#eq:dSN">13</A>)) 01108 <P></P> 01109 <DIV ALIGN="CENTER"><A NAME="eq:dSN2"></A><!-- MATH 01110 \begin{equation} 01111 \Delta S_L > \frac{S_{L-1}}{L_{max}-L} 01112 \end{equation} 01113 --> 01114 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 01115 <TR VALIGN="MIDDLE"> 01116 <TD NOWRAP ALIGN="CENTER"><IMG 01117 WIDTH="129" HEIGHT="51" ALIGN="MIDDLE" BORDER="0" 01118 SRC="gif/multidimfit_img88.gif" 01119 ALT="$\displaystyle \Delta S_L > \frac{S_{L-1}}{L_{max}-L}$"></TD> 01120 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 01121 (14)</TD></TR> 01122 </TABLE></DIV> 01123 <BR CLEAR="ALL"><P></P> 01124 where <IMG 01125 WIDTH="40" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01126 SRC="gif/multidimfit_img89.gif" 01127 ALT="$ S_{L-1}$"> is the sum of the <IMG 01128 WIDTH="42" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01129 SRC="gif/multidimfit_img78.gif" 01130 ALT="$ L-1$"> first residuals from the 01131 <IMG 01132 WIDTH="42" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01133 SRC="gif/multidimfit_img78.gif" 01134 ALT="$ L-1$"> functions previously accepted; and <IMG 01135 WIDTH="41" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01136 SRC="gif/multidimfit_img34.gif" 01137 ALT="$ L_{max}$"> is the total number 01138 of functions allowed in the final expression of the fit (defined by 01139 user). 01140 01141 <P> 01142 >From this we see, that by restricting <IMG 01143 WIDTH="41" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01144 SRC="gif/multidimfit_img34.gif" 01145 ALT="$ L_{max}$"> -- the number of 01146 terms in the final model -- the fit is more difficult to perform, 01147 since the above selection criteria is more limiting. 01148 01149 <P> 01150 The more coefficients we evaluate, the more the sum of squares of 01151 residuals <IMG 01152 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01153 SRC="gif/multidimfit_img26.gif" 01154 ALT="$ S$"> will be reduced. We can evaluate <IMG 01155 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01156 SRC="gif/multidimfit_img26.gif" 01157 ALT="$ S$"> before inverting 01158 <!-- MATH 01159 $\mathsf{B}$ 01160 --> 01161 <IMG 01162 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01163 SRC="gif/multidimfit_img90.gif" 01164 ALT="$ \mathsf{B}$"> as shown below. 01165 01166 <P> 01167 01168 <H2><A NAME="SECTION00034000000000000000"> 01169 Coefficients and Coefficient Errors</A> 01170 </H2> 01171 01172 <P> 01173 Having found a parameterization, that is the <IMG 01174 WIDTH="19" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01175 SRC="gif/multidimfit_img24.gif" 01176 ALT="$ F_l$">'s and <IMG 01177 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01178 SRC="gif/multidimfit_img23.gif" 01179 ALT="$ L$">, that 01180 minimizes <IMG 01181 WIDTH="15" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01182 SRC="gif/multidimfit_img26.gif" 01183 ALT="$ S$">, we still need to determine the coefficients 01184 <IMG 01185 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01186 SRC="gif/multidimfit_img25.gif" 01187 ALT="$ c_l$">. However, it's a feature of how we choose the significant 01188 functions, that the evaluation of the <IMG 01189 WIDTH="16" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01190 SRC="gif/multidimfit_img25.gif" 01191 ALT="$ c_l$">'s becomes trivial 01192 [<A 01193 HREF="TMultiFimFit.html#wind72">5</A>]. To derive <!-- MATH 01194 $\mathbf{c}$ 01195 --> 01196 <IMG 01197 WIDTH="12" HEIGHT="13" ALIGN="BOTTOM" BORDER="0" 01198 SRC="gif/multidimfit_img91.gif" 01199 ALT="$ \mathbf{c}$">, we first note that 01200 equation (<A HREF="TMultiFimFit.html#eq:wj">4</A>) can be written as 01201 <P></P> 01202 <DIV ALIGN="CENTER"><A NAME="eq:FF"></A><!-- MATH 01203 \begin{equation} 01204 \mathsf{F} = \mathsf{W}\mathsf{B} 01205 \end{equation} 01206 --> 01207 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 01208 <TR VALIGN="MIDDLE"> 01209 <TD NOWRAP ALIGN="CENTER"><IMG 01210 WIDTH="60" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01211 SRC="gif/multidimfit_img92.gif" 01212 ALT="$\displaystyle \mathsf{F} = \mathsf{W}\mathsf{B}$"></TD> 01213 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 01214 (15)</TD></TR> 01215 </TABLE></DIV> 01216 <BR CLEAR="ALL"><P></P> 01217 where 01218 <P></P> 01219 <DIV ALIGN="CENTER"><A NAME="eq:bij"></A><!-- MATH 01220 \begin{equation} 01221 b_{ij} = \left\{\begin{array}{rcl} 01222 \frac{\mathbf{f}_j \bullet \mathbf{w}_i}{\mathbf{w}_i^2} 01223 & \mbox{if} & i < j\\ 01224 1 & \mbox{if} & i = j\\ 01225 0 & \mbox{if} & i > j 01226 \end{array}\right. 01227 \end{equation} 01228 --> 01229 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 01230 <TR VALIGN="MIDDLE"> 01231 <TD NOWRAP ALIGN="CENTER"><IMG 01232 WIDTH="187" HEIGHT="79" ALIGN="MIDDLE" BORDER="0" 01233 SRC="gif/multidimfit_img93.gif" 01234 ALT="$\displaystyle b_{ij} = \left\{\begin{array}{rcl} \frac{\mathbf{f}_j \bullet \ma... 01235 ...f} & i < j\ 1 & \mbox{if} & i = j\ 0 & \mbox{if} & i > j \end{array}\right.$"></TD> 01236 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 01237 (16)</TD></TR> 01238 </TABLE></DIV> 01239 <BR CLEAR="ALL"><P></P> 01240 Consequently, <!-- MATH 01241 $\mathsf{B}$ 01242 --> 01243 <IMG 01244 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01245 SRC="gif/multidimfit_img90.gif" 01246 ALT="$ \mathsf{B}$"> is an upper triangle matrix, which can be 01247 readily inverted. So we now evaluate 01248 <P></P> 01249 <DIV ALIGN="CENTER"><A NAME="eq:FFF"></A><!-- MATH 01250 \begin{equation} 01251 \mathsf{F}\mathsf{B}^{-1} = \mathsf{W} 01252 \end{equation} 01253 --> 01254 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 01255 <TR VALIGN="MIDDLE"> 01256 <TD NOWRAP ALIGN="CENTER"><IMG 01257 WIDTH="77" HEIGHT="35" ALIGN="MIDDLE" BORDER="0" 01258 SRC="gif/multidimfit_img94.gif" 01259 ALT="$\displaystyle \mathsf{F}\mathsf{B}^{-1} = \mathsf{W}$"></TD> 01260 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 01261 (17)</TD></TR> 01262 </TABLE></DIV> 01263 <BR CLEAR="ALL"><P></P> 01264 The model <!-- MATH 01265 $\mathsf{W}\mathbf{a}$ 01266 --> 01267 <IMG 01268 WIDTH="28" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01269 SRC="gif/multidimfit_img63.gif" 01270 ALT="$ \mathsf{W}\mathbf{a}$"> can therefore be written as 01271 <!-- MATH 01272 \begin{displaymath} 01273 (\mathsf{F}\mathsf{B}^{-1})\mathbf{a} = 01274 \mathsf{F}(\mathsf{B}^{-1}\mathbf{a})\,. 01275 \end{displaymath} 01276 --> 01277 <P></P><DIV ALIGN="CENTER"> 01278 <IMG 01279 WIDTH="148" HEIGHT="35" ALIGN="MIDDLE" BORDER="0" 01280 SRC="gif/multidimfit_img95.gif" 01281 ALT="$\displaystyle (\mathsf{F}\mathsf{B}^{-1})\mathbf{a} = 01282 \mathsf{F}(\mathsf{B}^{-1}\mathbf{a}) . 01283 $"> 01284 </DIV><P></P> 01285 The original model <!-- MATH 01286 $\mathsf{F}\mathbf{c}$ 01287 --> 01288 <IMG 01289 WIDTH="21" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01290 SRC="gif/multidimfit_img96.gif" 01291 ALT="$ \mathsf{F}\mathbf{c}$"> is therefore identical with 01292 this if 01293 <P></P> 01294 <DIV ALIGN="CENTER"><A NAME="eq:id:cond"></A><!-- MATH 01295 \begin{equation} 01296 \mathbf{c} = \left(\mathsf{B}^{-1}\mathbf{a}\right) = 01297 \left[\mathbf{a}^T\left(\mathsf{B}^{-1}\right)^T\right]^T\,. 01298 \end{equation} 01299 --> 01300 <TABLE CELLPADDING="0" WIDTH="100%" ALIGN="CENTER"> 01301 <TR VALIGN="MIDDLE"> 01302 <TD NOWRAP ALIGN="CENTER"><IMG 01303 WIDTH="214" HEIGHT="51" ALIGN="MIDDLE" BORDER="0" 01304 SRC="gif/multidimfit_img97.gif" 01305 ALT="$\displaystyle \mathbf{c} = \left(\mathsf{B}^{-1}\mathbf{a}\right) = \left[\mathbf{a}^T\left(\mathsf{B}^{-1}\right)^T\right]^T .$"></TD> 01306 <TD NOWRAP WIDTH="10" ALIGN="RIGHT"> 01307 (18)</TD></TR> 01308 </TABLE></DIV> 01309 <BR CLEAR="ALL"><P></P> 01310 The reason we use <!-- MATH 01311 $\left(\mathsf{B}^{-1}\right)^T$ 01312 --> 01313 <IMG 01314 WIDTH="56" HEIGHT="42" ALIGN="MIDDLE" BORDER="0" 01315 SRC="gif/multidimfit_img98.gif" 01316 ALT="$ \left(\mathsf{B}^{-1}\right)^T$"> rather then 01317 <!-- MATH 01318 $\mathsf{B}^{-1}$ 01319 --> 01320 <IMG 01321 WIDTH="32" HEIGHT="16" ALIGN="BOTTOM" BORDER="0" 01322 SRC="gif/multidimfit_img99.gif" 01323 ALT="$ \mathsf{B}^{-1}$"> is to save storage, since 01324 <!-- MATH 01325 $\left(\mathsf{B}^{-1}\right)^T$ 01326 --> 01327 <IMG 01328 WIDTH="56" HEIGHT="42" ALIGN="MIDDLE" BORDER="0" 01329 SRC="gif/multidimfit_img98.gif" 01330 ALT="$ \left(\mathsf{B}^{-1}\right)^T$"> can be stored in the same matrix as 01331 <!-- MATH 01332 $\mathsf{B}$ 01333 --> 01334 <IMG 01335 WIDTH="15" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01336 SRC="gif/multidimfit_img90.gif" 01337 ALT="$ \mathsf{B}$"> 01338 (<A NAME="tex2html17" 01339 HREF=" 01340 ./TMultiDimFit.html#TMultiDimFit:MakeCoefficients"><TT>TMultiDimFit::MakeCoefficients</TT></A>). The errors in 01341 the coefficients is calculated by inverting the curvature matrix 01342 of the non-orthogonal functions <IMG 01343 WIDTH="23" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01344 SRC="gif/multidimfit_img100.gif" 01345 ALT="$ f_{lj}$"> [<A 01346 HREF="TMultiFimFit.html#bevington">1</A>] 01347 (<A NAME="tex2html18" 01348 HREF=" 01349 01350 ./TMultiDimFit.html#TMultiDimFit:MakeCoefficientErrors"><TT>TMultiDimFit::MakeCoefficientErrors</TT></A>). 01351 01352 <P> 01353 01354 <H2><A NAME="SECTION00035000000000000000"></A> 01355 <A NAME="sec:considerations"></A><BR> 01356 Considerations 01357 </H2> 01358 01359 <P> 01360 It's important to realize that the training sample should be 01361 representive of the problem at hand, in particular along the borders 01362 of the region of interest. This is because the algorithm presented 01363 here, is a <I>interpolation</I>, rahter then a <I>extrapolation</I> 01364 [<A 01365 HREF="TMultiFimFit.html#wind72">5</A>]. 01366 01367 <P> 01368 Also, the independent variables <IMG 01369 WIDTH="18" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01370 SRC="gif/multidimfit_img101.gif" 01371 ALT="$ x_{i}$"> need to be linear 01372 independent, since the procedure will perform poorly if they are not 01373 [<A 01374 HREF="TMultiFimFit.html#wind72">5</A>]. One can find an linear transformation from ones 01375 original variables <IMG 01376 WIDTH="16" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01377 SRC="gif/multidimfit_img102.gif" 01378 ALT="$ \xi_{i}$"> to a set of linear independent variables 01379 <IMG 01380 WIDTH="18" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01381 SRC="gif/multidimfit_img101.gif" 01382 ALT="$ x_{i}$">, using a <I>Principal Components Analysis</I> 01383 <A NAME="tex2html19" 01384 HREF="./TPrincipal.html">(see <TT>TPrincipal</TT>)</A>, and 01385 then use the transformed variable as input to this class [<A 01386 HREF="TMultiFimFit.html#wind72">5</A>] 01387 [<A 01388 HREF="TMultiFimFit.html#wind81">6</A>]. 01389 01390 <P> 01391 H. Wind also outlines a method for parameterising a multidimensional 01392 dependence over a multidimensional set of variables. An example 01393 of the method from [<A 01394 HREF="TMultiFimFit.html#wind72">5</A>], is a follows (please refer to 01395 [<A 01396 HREF="TMultiFimFit.html#wind72">5</A>] for a full discussion): 01397 01398 <P> 01399 01400 <OL> 01401 <LI>Define <!-- MATH 01402 $\mathbf{P} = (P_1, \ldots, P_5)$ 01403 --> 01404 <IMG 01405 WIDTH="123" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01406 SRC="gif/multidimfit_img103.gif" 01407 ALT="$ \mathbf{P} = (P_1, \ldots, P_5)$"> are the 5 dependent 01408 quantities that define a track. 01409 </LI> 01410 <LI>Compute, for <IMG 01411 WIDTH="21" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01412 SRC="gif/multidimfit_img10.gif" 01413 ALT="$ M$"> different values of <!-- MATH 01414 $\mathbf{P}$ 01415 --> 01416 <IMG 01417 WIDTH="17" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01418 SRC="gif/multidimfit_img104.gif" 01419 ALT="$ \mathbf{P}$">, the tracks 01420 through the magnetic field, and determine the corresponding 01421 <!-- MATH 01422 $\mathbf{x} = (x_1, \ldots, x_N)$ 01423 --> 01424 <IMG 01425 WIDTH="123" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01426 SRC="gif/multidimfit_img105.gif" 01427 ALT="$ \mathbf{x} = (x_1, \ldots, x_N)$">. 01428 </LI> 01429 <LI>Use the simulated observations to determine, with a simple 01430 approximation, the values of <!-- MATH 01431 $\mathbf{P}_j$ 01432 --> 01433 <IMG 01434 WIDTH="23" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01435 SRC="gif/multidimfit_img106.gif" 01436 ALT="$ \mathbf{P}_j$">. We call these values 01437 <!-- MATH 01438 $\mathbf{P}^\prime_j, j = 1, \ldots, M$ 01439 --> 01440 <IMG 01441 WIDTH="122" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01442 SRC="gif/multidimfit_img107.gif" 01443 ALT="$ \mathbf{P}^\prime_j, j = 1, \ldots, M$">. 01444 </LI> 01445 <LI>Determine from <!-- MATH 01446 $\mathbf{x}$ 01447 --> 01448 <IMG 01449 WIDTH="14" HEIGHT="13" ALIGN="BOTTOM" BORDER="0" 01450 SRC="gif/multidimfit_img9.gif" 01451 ALT="$ \mathbf{x}$"> a set of at least five relevant 01452 coordinates <!-- MATH 01453 $\mathbf{x}^\prime$ 01454 --> 01455 <IMG 01456 WIDTH="18" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01457 SRC="gif/multidimfit_img108.gif" 01458 ALT="$ \mathbf{x}^\prime$">, using contrains, <I>or 01459 alternative:</I> 01460 </LI> 01461 <LI>Perform a Principal Component Analysis (using 01462 <A NAME="tex2html20" 01463 HREF="./TPrincipal.html"><TT>TPrincipal</TT></A>), and use 01464 01465 to get a linear transformation 01466 <!-- MATH 01467 $\mathbf{x} \rightarrow \mathbf{x}^\prime$ 01468 --> 01469 <IMG 01470 WIDTH="53" HEIGHT="16" ALIGN="BOTTOM" BORDER="0" 01471 SRC="gif/multidimfit_img109.gif" 01472 ALT="$ \mathbf{x} \rightarrow \mathbf{x}^\prime$">, so that 01473 <!-- MATH 01474 $\mathbf{x}^\prime$ 01475 --> 01476 <IMG 01477 WIDTH="18" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01478 SRC="gif/multidimfit_img108.gif" 01479 ALT="$ \mathbf{x}^\prime$"> are constrained and linear independent. 01480 </LI> 01481 <LI>Perform a Principal Component Analysis on 01482 <!-- MATH 01483 $Q_i = P_i / P^\prime_i\, i = 1, \ldots, 5$ 01484 --> 01485 <IMG 01486 WIDTH="210" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01487 SRC="gif/multidimfit_img110.gif" 01488 ALT="$ Q_i = P_i / P^prime_i i = 1, \ldots, 5$">, to get linear 01489 indenpendent (among themselves, but not independent of 01490 <!-- MATH 01491 $\mathbf{x}$ 01492 --> 01493 <IMG 01494 WIDTH="14" HEIGHT="13" ALIGN="BOTTOM" BORDER="0" 01495 SRC="gif/multidimfit_img9.gif" 01496 ALT="$ \mathbf{x}$">) quantities <!-- MATH 01497 $\mathbf{Q}^\prime$ 01498 --> 01499 <IMG 01500 WIDTH="22" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01501 SRC="gif/multidimfit_img111.gif" 01502 ALT="$ \mathbf{Q}^\prime$"> 01503 </LI> 01504 <LI>For each component <!-- MATH 01505 $Q^\prime_i$ 01506 --> 01507 <IMG 01508 WIDTH="22" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01509 SRC="gif/multidimfit_img112.gif" 01510 ALT="$ Q^\prime_i$"> make a mutlidimensional fit, 01511 using <!-- MATH 01512 $\mathbf{x}^\prime$ 01513 --> 01514 <IMG 01515 WIDTH="18" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01516 SRC="gif/multidimfit_img108.gif" 01517 ALT="$ \mathbf{x}^\prime$"> as the variables, thus determing a set of 01518 coefficents <!-- MATH 01519 $\mathbf{c}_i$ 01520 --> 01521 <IMG 01522 WIDTH="17" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01523 SRC="gif/multidimfit_img113.gif" 01524 ALT="$ \mathbf{c}_i$">. 01525 </LI> 01526 </OL> 01527 01528 <P> 01529 To process data, using this parameterisation, do 01530 01531 <OL> 01532 <LI>Test wether the observation <!-- MATH 01533 $\mathbf{x}$ 01534 --> 01535 <IMG 01536 WIDTH="14" HEIGHT="13" ALIGN="BOTTOM" BORDER="0" 01537 SRC="gif/multidimfit_img9.gif" 01538 ALT="$ \mathbf{x}$"> within the domain of 01539 the parameterization, using the result from the Principal Component 01540 Analysis. 01541 </LI> 01542 <LI>Determine <!-- MATH 01543 $\mathbf{P}^\prime$ 01544 --> 01545 <IMG 01546 WIDTH="21" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01547 SRC="gif/multidimfit_img114.gif" 01548 ALT="$ \mathbf{P}^\prime$"> as before. 01549 </LI> 01550 <LI>Detetmine <!-- MATH 01551 $\mathbf{x}^\prime$ 01552 --> 01553 <IMG 01554 WIDTH="18" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01555 SRC="gif/multidimfit_img108.gif" 01556 ALT="$ \mathbf{x}^\prime$"> as before. 01557 </LI> 01558 <LI>Use the result of the fit to determind <!-- MATH 01559 $\mathbf{Q}^\prime$ 01560 --> 01561 <IMG 01562 WIDTH="22" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01563 SRC="gif/multidimfit_img111.gif" 01564 ALT="$ \mathbf{Q}^\prime$">. 01565 </LI> 01566 <LI>Transform back to <!-- MATH 01567 $\mathbf{P}$ 01568 --> 01569 <IMG 01570 WIDTH="17" HEIGHT="14" ALIGN="BOTTOM" BORDER="0" 01571 SRC="gif/multidimfit_img104.gif" 01572 ALT="$ \mathbf{P}$"> from <!-- MATH 01573 $\mathbf{Q}^\prime$ 01574 --> 01575 <IMG 01576 WIDTH="22" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01577 SRC="gif/multidimfit_img111.gif" 01578 ALT="$ \mathbf{Q}^\prime$">, using 01579 the result from the Principal Component Analysis. 01580 </LI> 01581 </OL> 01582 01583 <P> 01584 01585 <H2><A NAME="SECTION00036000000000000000"></A> 01586 <A NAME="sec:testing"></A><BR> 01587 Testing the parameterization 01588 </H2> 01589 01590 <P> 01591 The class also provides functionality for testing the, over the 01592 training sample, found parameterization 01593 (<A NAME="tex2html21" 01594 HREF=" 01595 ./TMultiDimFit.html#TMultiDimFit:Fit"><TT>TMultiDimFit::Fit</TT></A>). This is done by passing 01596 the class a test sample of <IMG 01597 WIDTH="25" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01598 SRC="gif/multidimfit_img115.gif" 01599 ALT="$ M_t$"> tuples of the form <!-- MATH 01600 $(\mathbf{x}_{t,j}, 01601 D_{t,j}, E_{t,j})$ 01602 --> 01603 <IMG 01604 WIDTH="111" HEIGHT="31" ALIGN="MIDDLE" BORDER="0" 01605 SRC="gif/multidimfit_img116.gif" 01606 ALT="$ (\mathbf{x}_{t,j}, 01607 D_{t,j}, E_{t,j})$">, where <!-- MATH 01608 $\mathbf{x}_{t,j}$ 01609 --> 01610 <IMG 01611 WIDTH="29" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01612 SRC="gif/multidimfit_img117.gif" 01613 ALT="$ \mathbf{x}_{t,j}$"> are the independent 01614 variables, <IMG 01615 WIDTH="33" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01616 SRC="gif/multidimfit_img118.gif" 01617 ALT="$ D_{t,j}$"> the known, dependent quantity, and <IMG 01618 WIDTH="31" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01619 SRC="gif/multidimfit_img119.gif" 01620 ALT="$ E_{t,j}$"> is 01621 the square error in <IMG 01622 WIDTH="33" HEIGHT="29" ALIGN="MIDDLE" BORDER="0" 01623 SRC="gif/multidimfit_img118.gif" 01624 ALT="$ D_{t,j}$"> 01625 (<A NAME="tex2html22" 01626 HREF=" 01627 01628 ./TMultiDimFit.html#TMultiDimFit:AddTestRow"><TT>TMultiDimFit::AddTestRow</TT></A>). 01629 01630 <P> 01631 The parameterization is then evaluated at every <!-- MATH 01632 $\mathbf{x}_t$ 01633 --> 01634 <IMG 01635 WIDTH="19" HEIGHT="28" ALIGN="MIDDLE" BORDER="0" 01636 SRC="gif/multidimfit_img120.gif" 01637 ALT="$ \mathbf{x}_t$"> in the 01638 test sample, and 01639 <!-- MATH 01640 \begin{displaymath} 01641 S_t \equiv \sum_{j=1}^{M_t} \left(D_{t,j} - 01642 D_p\left(\mathbf{x}_{t,j}\right)\right)^2 01643 \end{displaymath} 01644 --> 01645 <P></P><DIV ALIGN="CENTER"> 01646 <IMG 01647 WIDTH="194" HEIGHT="66" ALIGN="MIDDLE" BORDER="0" 01648 SRC="gif/multidimfit_img121.gif" 01649 ALT="$\displaystyle S_t \equiv \sum_{j=1}^{M_t} \left(D_{t,j} - 01650 D_p\left(\mathbf{x}_{t,j}\right)\right)^2 01651 $"> 01652 </DIV><P></P> 01653 is evaluated. The relative error over the test sample 01654 <!-- MATH 01655 \begin{displaymath} 01656 R_t = \frac{S_t}{\sum_{j=1}^{M_t} D_{t,j}^2} 01657 \end{displaymath} 01658 --> 01659 <P></P><DIV ALIGN="CENTER"> 01660 <IMG 01661 WIDTH="118" HEIGHT="51" ALIGN="MIDDLE" BORDER="0" 01662 SRC="gif/multidimfit_img122.gif" 01663 ALT="$\displaystyle R_t = \frac{S_t}{\sum_{j=1}^{M_t} D_{t,j}^2} 01664 $"> 01665 </DIV><P></P> 01666 should not be to low or high compared to <IMG 01667 WIDTH="16" HEIGHT="15" ALIGN="BOTTOM" BORDER="0" 01668 SRC="gif/multidimfit_img123.gif" 01669 ALT="$ R$"> from the training 01670 sample. Also, multiple correlation coefficient from both samples should 01671 be fairly close, otherwise one of the samples is not representive of 01672 the problem. A large difference in the reduced <IMG 01673 WIDTH="21" HEIGHT="33" ALIGN="MIDDLE" BORDER="0" 01674 SRC="gif/multidimfit_img124.gif" 01675 ALT="$ \chi^2$"> over the two 01676 samples indicate an over fit, and the maximum number of terms in the 01677 parameterisation should be reduced. 01678 01679 <P> 01680 It's possible to use <A NAME="tex2html23" 01681 HREF="./TMinuit.html"><I>Minuit</I></A> 01682 [<A 01683 HREF="TMultiFimFit.html#minuit">4</A>] to further improve the fit, using the test sample. 01684 01685 <P> 01686 <DIV ALIGN="RIGHT"> 01687 Christian Holm 01688 <BR> November 2000, NBI 01689 01690 </DIV> 01691 01692 <P> 01693 01694 <H2><A NAME="SECTION00040000000000000000"> 01695 Bibliography</A> 01696 </H2><DL COMPACT><DD><P></P><DT><A NAME="bevington">1</A> 01697 <DD> 01698 Philip R. Bevington and D. Keith Robinson. 01699 <BR><EM>Data Reduction and Error Analysis for the Physical Sciences</EM>. 01700 <BR>McGraw-Hill, 2 edition, 1992. 01701 01702 <P></P><DT><A NAME="mudifi">2</A> 01703 <DD> 01704 René Brun et al. 01705 <BR>Mudifi. 01706 <BR>Long writeup DD/75-23, CERN, 1980. 01707 01708 <P></P><DT><A NAME="golub">3</A> 01709 <DD> 01710 Gene H. Golub and Charles F. van Loan. 01711 <BR><EM>Matrix Computations</EM>. 01712 <BR>John Hopkins Univeristy Press, Baltimore, 3 edition, 1996. 01713 01714 <P></P><DT><A NAME="minuit">4</A> 01715 <DD> 01716 F. James. 01717 <BR>Minuit. 01718 <BR>Long writeup D506, CERN, 1998. 01719 01720 <P></P><DT><A NAME="wind72">5</A> 01721 <DD> 01722 H. Wind. 01723 <BR>Function parameterization. 01724 <BR>In <EM>Proceedings of the 1972 CERN Computing and Data Processing 01725 School</EM>, volume 72-21 of <EM>Yellow report</EM>. CERN, 1972. 01726 01727 <P></P><DT><A NAME="wind81">6</A> 01728 <DD> 01729 H. Wind. 01730 <BR>1. principal component analysis, 2. pattern recognition for track 01731 finding, 3. interpolation and functional representation. 01732 <BR>Yellow report EP/81-12, CERN, 1981. 01733 </DL> 01734 <pre> 01735 */ 01736 //End_Html 01737 // 01738 01739 #include "Riostream.h" 01740 #include "TMultiDimFit.h" 01741 #include "TMath.h" 01742 #include "TH1.h" 01743 #include "TH2.h" 01744 #include "TROOT.h" 01745 #include "TBrowser.h" 01746 #include "TDecompChol.h" 01747 01748 #define RADDEG (180. / TMath::Pi()) 01749 #define DEGRAD (TMath::Pi() / 180.) 01750 #define HIST_XORIG 0 01751 #define HIST_DORIG 1 01752 #define HIST_XNORM 2 01753 #define HIST_DSHIF 3 01754 #define HIST_RX 4 01755 #define HIST_RD 5 01756 #define HIST_RTRAI 6 01757 #define HIST_RTEST 7 01758 #define PARAM_MAXSTUDY 1 01759 #define PARAM_SEVERAL 2 01760 #define PARAM_RELERR 3 01761 #define PARAM_MAXTERMS 4 01762 01763 01764 //____________________________________________________________________ 01765 static void mdfHelper(int&, double*, double&, double*, int); 01766 01767 //____________________________________________________________________ 01768 ClassImp(TMultiDimFit); 01769 01770 //____________________________________________________________________ 01771 // Static instance. Used with mdfHelper and TMinuit 01772 TMultiDimFit* TMultiDimFit::fgInstance = 0; 01773 01774 01775 //____________________________________________________________________ 01776 TMultiDimFit::TMultiDimFit() 01777 { 01778 // Empty CTOR. Do not use 01779 fMeanQuantity = 0; 01780 fMaxQuantity = 0; 01781 fMinQuantity = 0; 01782 fSumSqQuantity = 0; 01783 fSumSqAvgQuantity = 0; 01784 01785 fNVariables = 0; 01786 fSampleSize = 0; 01787 fTestSampleSize = 0; 01788 01789 fMinAngle = 1; 01790 fMaxAngle = 0; 01791 fMaxTerms = 0; 01792 fMinRelativeError = 0; 01793 fMaxPowers = 0; 01794 fPowerLimit = 0; 01795 01796 fMaxFunctions = 0; 01797 fFunctionCodes = 0; 01798 fMaxStudy = 0; 01799 fMaxFuncNV = 0; 01800 01801 fMaxPowersFinal = 0; 01802 fPowers = 0; 01803 fPowerIndex = 0; 01804 01805 fMaxResidual = 0; 01806 fMinResidual = 0; 01807 fMaxResidualRow = 0; 01808 fMinResidualRow = 0; 01809 fSumSqResidual = 0; 01810 01811 fNCoefficients = 0; 01812 fRMS = 0; 01813 fChi2 = 0; 01814 fParameterisationCode = 0; 01815 01816 fError = 0; 01817 fTestError = 0; 01818 fPrecision = 0; 01819 fTestPrecision = 0; 01820 fCorrelationCoeff = 0; 01821 fTestCorrelationCoeff = 0; 01822 01823 fHistograms = 0; 01824 fHistogramMask = 0; 01825 fBinVarX = 100; 01826 fBinVarY = 100; 01827 01828 fFitter = 0; 01829 fPolyType = kMonomials; 01830 fShowCorrelation = kFALSE; 01831 fIsUserFunction = kFALSE; 01832 fIsVerbose = kFALSE; 01833 01834 } 01835 01836 01837 //____________________________________________________________________ 01838 TMultiDimFit::TMultiDimFit(Int_t dimension, 01839 EMDFPolyType type, 01840 Option_t *option) 01841 : TNamed("multidimfit","Multi-dimensional fit object"), 01842 fQuantity(dimension), 01843 fSqError(dimension), 01844 fVariables(dimension*100), 01845 fMeanVariables(dimension), 01846 fMaxVariables(dimension), 01847 fMinVariables(dimension) 01848 { 01849 // Constructor 01850 // Second argument is the type of polynomials to use in 01851 // parameterisation, one of: 01852 // TMultiDimFit::kMonomials 01853 // TMultiDimFit::kChebyshev 01854 // TMultiDimFit::kLegendre 01855 // 01856 // Options: 01857 // K Compute (k)correlation matrix 01858 // V Be verbose 01859 // 01860 // Default is no options. 01861 // 01862 01863 fgInstance = this; 01864 01865 fMeanQuantity = 0; 01866 fMaxQuantity = 0; 01867 fMinQuantity = 0; 01868 fSumSqQuantity = 0; 01869 fSumSqAvgQuantity = 0; 01870 01871 fNVariables = dimension; 01872 fSampleSize = 0; 01873 fTestSampleSize = 0; 01874 01875 fMinAngle = 1; 01876 fMaxAngle = 0; 01877 fMaxTerms = 0; 01878 fMinRelativeError = 0.01; 01879 fMaxPowers = new Int_t[dimension]; 01880 fPowerLimit = 1; 01881 01882 fMaxFunctions = 0; 01883 fFunctionCodes = 0; 01884 fMaxStudy = 0; 01885 fMaxFuncNV = 0; 01886 01887 fMaxPowersFinal = new Int_t[dimension]; 01888 fPowers = 0; 01889 fPowerIndex = 0; 01890 01891 fMaxResidual = 0; 01892 fMinResidual = 0; 01893 fMaxResidualRow = 0; 01894 fMinResidualRow = 0; 01895 fSumSqResidual = 0; 01896 01897 fNCoefficients = 0; 01898 fRMS = 0; 01899 fChi2 = 0; 01900 fParameterisationCode = 0; 01901 01902 fError = 0; 01903 fTestError = 0; 01904 fPrecision = 0; 01905 fTestPrecision = 0; 01906 fCorrelationCoeff = 0; 01907 fTestCorrelationCoeff = 0; 01908 01909 fHistograms = 0; 01910 fHistogramMask = 0; 01911 fBinVarX = 100; 01912 fBinVarY = 100; 01913 01914 fFitter = 0; 01915 fPolyType = type; 01916 fShowCorrelation = kFALSE; 01917 fIsUserFunction = kFALSE; 01918 fIsVerbose = kFALSE; 01919 TString opt = option; 01920 opt.ToLower(); 01921 01922 if (opt.Contains("k")) fShowCorrelation = kTRUE; 01923 if (opt.Contains("v")) fIsVerbose = kTRUE; 01924 } 01925 01926 01927 //____________________________________________________________________ 01928 TMultiDimFit::~TMultiDimFit() 01929 { 01930 // Destructor 01931 delete [] fPowers; 01932 delete [] fMaxPowers; 01933 delete [] fMaxPowersFinal; 01934 delete [] fPowerIndex; 01935 delete [] fFunctionCodes; 01936 if (fHistograms) fHistograms->Clear("nodelete"); 01937 delete fHistograms; 01938 } 01939 01940 01941 //____________________________________________________________________ 01942 void TMultiDimFit::AddRow(const Double_t *x, Double_t D, Double_t E) 01943 { 01944 // Add a row consisting of fNVariables independent variables, the 01945 // known, dependent quantity, and optionally, the square error in 01946 // the dependent quantity, to the training sample to be used for the 01947 // parameterization. 01948 // The mean of the variables and quantity is calculated on the fly, 01949 // as outlined in TPrincipal::AddRow. 01950 // This sample should be representive of the problem at hand. 01951 // Please note, that if no error is given Poisson statistics is 01952 // assumed and the square error is set to the value of dependent 01953 // quantity. See also the 01954 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 01955 if (!x) 01956 return; 01957 01958 if (++fSampleSize == 1) { 01959 fMeanQuantity = D; 01960 fMaxQuantity = D; 01961 fMinQuantity = D; 01962 fSumSqQuantity = D * D;// G.Q. erratum on August 15th, 2008 01963 } 01964 else { 01965 fMeanQuantity *= 1 - 1./Double_t(fSampleSize); 01966 fMeanQuantity += D / Double_t(fSampleSize); 01967 fSumSqQuantity += D * D; 01968 01969 if (D >= fMaxQuantity) fMaxQuantity = D; 01970 if (D <= fMinQuantity) fMinQuantity = D; 01971 } 01972 01973 01974 // If the vector isn't big enough to hold the new data, then 01975 // expand the vector by half it's size. 01976 Int_t size = fQuantity.GetNrows(); 01977 if (fSampleSize > size) { 01978 fQuantity.ResizeTo(size + size/2); 01979 fSqError.ResizeTo(size + size/2); 01980 } 01981 01982 // Store the value 01983 fQuantity(fSampleSize-1) = D; 01984 fSqError(fSampleSize-1) = (E == 0 ? D : E); 01985 01986 // Store data point in internal vector 01987 // If the vector isn't big enough to hold the new data, then 01988 // expand the vector by half it's size 01989 size = fVariables.GetNrows(); 01990 if (fSampleSize * fNVariables > size) 01991 fVariables.ResizeTo(size + size/2); 01992 01993 01994 // Increment the data point counter 01995 Int_t i,j; 01996 for (i = 0; i < fNVariables; i++) { 01997 if (fSampleSize == 1) { 01998 fMeanVariables(i) = x[i]; 01999 fMaxVariables(i) = x[i]; 02000 fMinVariables(i) = x[i]; 02001 } 02002 else { 02003 fMeanVariables(i) *= 1 - 1./Double_t(fSampleSize); 02004 fMeanVariables(i) += x[i] / Double_t(fSampleSize); 02005 02006 // Update the maximum value for this component 02007 if (x[i] >= fMaxVariables(i)) fMaxVariables(i) = x[i]; 02008 02009 // Update the minimum value for this component 02010 if (x[i] <= fMinVariables(i)) fMinVariables(i) = x[i]; 02011 02012 } 02013 02014 // Store the data. 02015 j = (fSampleSize-1) * fNVariables + i; 02016 fVariables(j) = x[i]; 02017 } 02018 } 02019 02020 02021 //____________________________________________________________________ 02022 void TMultiDimFit::AddTestRow(const Double_t *x, Double_t D, Double_t E) 02023 { 02024 // Add a row consisting of fNVariables independent variables, the 02025 // known, dependent quantity, and optionally, the square error in 02026 // the dependent quantity, to the test sample to be used for the 02027 // test of the parameterization. 02028 // This sample needn't be representive of the problem at hand. 02029 // Please note, that if no error is given Poisson statistics is 02030 // assumed and the square error is set to the value of dependent 02031 // quantity. See also the 02032 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 02033 if (fTestSampleSize++ == 0) { 02034 fTestQuantity.ResizeTo(fNVariables); 02035 fTestSqError.ResizeTo(fNVariables); 02036 fTestVariables.ResizeTo(fNVariables * 100); 02037 } 02038 02039 // If the vector isn't big enough to hold the new data, then 02040 // expand the vector by half it's size. 02041 Int_t size = fTestQuantity.GetNrows(); 02042 if (fTestSampleSize > size) { 02043 fTestQuantity.ResizeTo(size + size/2); 02044 fTestSqError.ResizeTo(size + size/2); 02045 } 02046 02047 // Store the value 02048 fTestQuantity(fTestSampleSize-1) = D; 02049 fTestSqError(fTestSampleSize-1) = (E == 0 ? D : E); 02050 02051 // Store data point in internal vector 02052 // If the vector isn't big enough to hold the new data, then 02053 // expand the vector by half it's size 02054 size = fTestVariables.GetNrows(); 02055 if (fTestSampleSize * fNVariables > size) 02056 fTestVariables.ResizeTo(size + size/2); 02057 02058 02059 // Increment the data point counter 02060 Int_t i,j; 02061 for (i = 0; i < fNVariables; i++) { 02062 j = fNVariables * (fTestSampleSize - 1) + i; 02063 fTestVariables(j) = x[i]; 02064 02065 if (x[i] > fMaxVariables(i)) 02066 Warning("AddTestRow", "variable %d (row: %d) too large: %f > %f", 02067 i, fTestSampleSize, x[i], fMaxVariables(i)); 02068 if (x[i] < fMinVariables(i)) 02069 Warning("AddTestRow", "variable %d (row: %d) too small: %f < %f", 02070 i, fTestSampleSize, x[i], fMinVariables(i)); 02071 } 02072 } 02073 02074 02075 //____________________________________________________________________ 02076 void TMultiDimFit::Browse(TBrowser* b) 02077 { 02078 // Browse the TMultiDimFit object in the TBrowser. 02079 if (fHistograms) { 02080 TIter next(fHistograms); 02081 TH1* h = 0; 02082 while ((h = (TH1*)next())) 02083 b->Add(h,h->GetName()); 02084 } 02085 if (fVariables.IsValid()) 02086 b->Add(&fVariables, "Variables (Training)"); 02087 if (fQuantity.IsValid()) 02088 b->Add(&fQuantity, "Quantity (Training)"); 02089 if (fSqError.IsValid()) 02090 b->Add(&fSqError, "Error (Training)"); 02091 if (fMeanVariables.IsValid()) 02092 b->Add(&fMeanVariables, "Mean of Variables (Training)"); 02093 if (fMaxVariables.IsValid()) 02094 b->Add(&fMaxVariables, "Mean of Variables (Training)"); 02095 if (fMinVariables.IsValid()) 02096 b->Add(&fMinVariables, "Min of Variables (Training)"); 02097 if (fTestVariables.IsValid()) 02098 b->Add(&fTestVariables, "Variables (Test)"); 02099 if (fTestQuantity.IsValid()) 02100 b->Add(&fTestQuantity, "Quantity (Test)"); 02101 if (fTestSqError.IsValid()) 02102 b->Add(&fTestSqError, "Error (Test)"); 02103 if (fFunctions.IsValid()) 02104 b->Add(&fFunctions, "Functions"); 02105 if(fCoefficients.IsValid()) 02106 b->Add(&fCoefficients,"Coefficients"); 02107 if(fCoefficientsRMS.IsValid()) 02108 b->Add(&fCoefficientsRMS,"Coefficients Errors"); 02109 if (fOrthFunctions.IsValid()) 02110 b->Add(&fOrthFunctions, "Orthogonal Functions"); 02111 if (fOrthFunctionNorms.IsValid()) 02112 b->Add(&fOrthFunctionNorms, "Orthogonal Functions Norms"); 02113 if (fResiduals.IsValid()) 02114 b->Add(&fResiduals, "Residuals"); 02115 if(fOrthCoefficients.IsValid()) 02116 b->Add(&fOrthCoefficients,"Orthogonal Coefficients"); 02117 if (fOrthCurvatureMatrix.IsValid()) 02118 b->Add(&fOrthCurvatureMatrix,"Orthogonal curvature matrix"); 02119 if(fCorrelationMatrix.IsValid()) 02120 b->Add(&fCorrelationMatrix,"Correlation Matrix"); 02121 if (fFitter) 02122 b->Add(fFitter, fFitter->GetName()); 02123 } 02124 02125 02126 //____________________________________________________________________ 02127 void TMultiDimFit::Clear(Option_t *option) 02128 { 02129 // Clear internal structures and variables 02130 Int_t i, j, n = fNVariables, m = fMaxFunctions; 02131 02132 // Training sample, dependent quantity 02133 fQuantity.Zero(); 02134 fSqError.Zero(); 02135 fMeanQuantity = 0; 02136 fMaxQuantity = 0; 02137 fMinQuantity = 0; 02138 fSumSqQuantity = 0; 02139 fSumSqAvgQuantity = 0; 02140 02141 // Training sample, independent variables 02142 fVariables.Zero(); 02143 fNVariables = 0; 02144 fSampleSize = 0; 02145 fMeanVariables.Zero(); 02146 fMaxVariables.Zero(); 02147 fMinVariables.Zero(); 02148 02149 // Test sample 02150 fTestQuantity.Zero(); 02151 fTestSqError.Zero(); 02152 fTestVariables.Zero(); 02153 fTestSampleSize = 0; 02154 02155 // Functions 02156 fFunctions.Zero(); 02157 //for (i = 0; i < fMaxTerms; i++) fPowerIndex[i] = 0; 02158 //for (i = 0; i < fMaxTerms; i++) fFunctionCodes[i] = 0; 02159 fMaxFunctions = 0; 02160 fMaxStudy = 0; 02161 fOrthFunctions.Zero(); 02162 fOrthFunctionNorms.Zero(); 02163 02164 // Control parameters 02165 fMinRelativeError = 0; 02166 fMinAngle = 0; 02167 fMaxAngle = 0; 02168 fMaxTerms = 0; 02169 02170 // Powers 02171 for (i = 0; i < n; i++) { 02172 fMaxPowers[i] = 0; 02173 fMaxPowersFinal[i] = 0; 02174 for (j = 0; j < m; j++) 02175 fPowers[i * n + j] = 0; 02176 } 02177 fPowerLimit = 0; 02178 02179 // Residuals 02180 fMaxResidual = 0; 02181 fMinResidual = 0; 02182 fMaxResidualRow = 0; 02183 fMinResidualRow = 0; 02184 fSumSqResidual = 0; 02185 02186 // Fit 02187 fNCoefficients = 0; 02188 fOrthCoefficients = 0; 02189 fOrthCurvatureMatrix = 0; 02190 fRMS = 0; 02191 fCorrelationMatrix.Zero(); 02192 fError = 0; 02193 fTestError = 0; 02194 fPrecision = 0; 02195 fTestPrecision = 0; 02196 02197 // Coefficients 02198 fCoefficients.Zero(); 02199 fCoefficientsRMS.Zero(); 02200 fResiduals.Zero(); 02201 fHistograms->Clear(option); 02202 02203 // Options 02204 fPolyType = kMonomials; 02205 fShowCorrelation = kFALSE; 02206 fIsUserFunction = kFALSE; 02207 } 02208 02209 02210 //____________________________________________________________________ 02211 Double_t TMultiDimFit::Eval(const Double_t *x, const Double_t* coeff) const 02212 { 02213 // Evaluate parameterization at point x. Optional argument coeff is 02214 // a vector of coefficients for the parameterisation, fNCoefficients 02215 // elements long. 02216 Double_t returnValue = fMeanQuantity; 02217 Double_t term = 0; 02218 Int_t i, j; 02219 02220 for (i = 0; i < fNCoefficients; i++) { 02221 // Evaluate the ith term in the expansion 02222 term = (coeff ? coeff[i] : fCoefficients(i)); 02223 for (j = 0; j < fNVariables; j++) { 02224 // Evaluate the factor (polynomial) in the j-th variable. 02225 Int_t p = fPowers[fPowerIndex[i] * fNVariables + j]; 02226 Double_t y = 1 + 2. / (fMaxVariables(j) - fMinVariables(j)) 02227 * (x[j] - fMaxVariables(j)); 02228 term *= EvalFactor(p,y); 02229 } 02230 // Add this term to the final result 02231 returnValue += term; 02232 } 02233 return returnValue; 02234 } 02235 02236 02237 //____________________________________________________________________ 02238 Double_t TMultiDimFit::EvalError(const Double_t *x, const Double_t* coeff) const 02239 { 02240 // Evaluate parameterization error at point x. Optional argument coeff is 02241 // a vector of coefficients for the parameterisation, fNCoefficients 02242 // elements long. 02243 Double_t returnValue = 0; 02244 Double_t term = 0; 02245 Int_t i, j; 02246 02247 for (i = 0; i < fNCoefficients; i++) { 02248 // cout << "Error coef " << i << " -> " << fCoefficientsRMS(i) << endl; 02249 } 02250 for (i = 0; i < fNCoefficients; i++) { 02251 // Evaluate the ith term in the expansion 02252 term = (coeff ? coeff[i] : fCoefficientsRMS(i)); 02253 for (j = 0; j < fNVariables; j++) { 02254 // Evaluate the factor (polynomial) in the j-th variable. 02255 Int_t p = fPowers[fPowerIndex[i] * fNVariables + j]; 02256 Double_t y = 1 + 2. / (fMaxVariables(j) - fMinVariables(j)) 02257 * (x[j] - fMaxVariables(j)); 02258 term *= EvalFactor(p,y); 02259 // cout << "i,j " << i << ", " << j << " " << p << " " << y << " " << EvalFactor(p,y) << " " << term << endl; 02260 } 02261 // Add this term to the final result 02262 returnValue += term*term; 02263 // cout << " i = " << i << " value = " << returnValue << endl; 02264 } 02265 returnValue = sqrt(returnValue); 02266 return returnValue; 02267 } 02268 02269 02270 //____________________________________________________________________ 02271 Double_t TMultiDimFit::EvalControl(const Int_t *iv) const 02272 { 02273 // PRIVATE METHOD: 02274 // Calculate the control parameter from the passed powers 02275 Double_t s = 0; 02276 Double_t epsilon = 1e-6; // a small number 02277 for (Int_t i = 0; i < fNVariables; i++) { 02278 if (fMaxPowers[i] != 1) 02279 s += (epsilon + iv[i] - 1) / (epsilon + fMaxPowers[i] - 1); 02280 } 02281 return s; 02282 } 02283 02284 //____________________________________________________________________ 02285 Double_t TMultiDimFit::EvalFactor(Int_t p, Double_t x) const 02286 { 02287 // PRIVATE METHOD: 02288 // Evaluate function with power p at variable value x 02289 Int_t i = 0; 02290 Double_t p1 = 1; 02291 Double_t p2 = 0; 02292 Double_t p3 = 0; 02293 Double_t r = 0; 02294 02295 switch(p) { 02296 case 1: 02297 r = 1; 02298 break; 02299 case 2: 02300 r = x; 02301 break; 02302 default: 02303 p2 = x; 02304 for (i = 3; i <= p; i++) { 02305 p3 = p2 * x; 02306 if (fPolyType == kLegendre) 02307 p3 = ((2 * i - 3) * p2 * x - (i - 2) * p1) / (i - 1); 02308 else if (fPolyType == kChebyshev) 02309 p3 = 2 * x * p2 - p1; 02310 p1 = p2; 02311 p2 = p3; 02312 } 02313 r = p3; 02314 } 02315 02316 return r; 02317 } 02318 02319 02320 //____________________________________________________________________ 02321 void TMultiDimFit::FindParameterization(Option_t *) 02322 { 02323 // Find the parameterization 02324 // 02325 // Options: 02326 // None so far 02327 // 02328 // For detailed description of what this entails, please refer to the 02329 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 02330 MakeNormalized(); 02331 MakeCandidates(); 02332 MakeParameterization(); 02333 MakeCoefficients(); 02334 MakeCoefficientErrors(); 02335 MakeCorrelation(); 02336 } 02337 02338 //____________________________________________________________________ 02339 void TMultiDimFit::Fit(Option_t *option) 02340 { 02341 // Try to fit the found parameterisation to the test sample. 02342 // 02343 // Options 02344 // M use Minuit to improve coefficients 02345 // 02346 // Also, refer to 02347 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 02348 Int_t i, j; 02349 Double_t* x = new Double_t[fNVariables]; 02350 Double_t sumSqD = 0; 02351 Double_t sumD = 0; 02352 Double_t sumSqR = 0; 02353 Double_t sumR = 0; 02354 02355 // Calculate the residuals over the test sample 02356 for (i = 0; i < fTestSampleSize; i++) { 02357 for (j = 0; j < fNVariables; j++) 02358 x[j] = fTestVariables(i * fNVariables + j); 02359 Double_t res = fTestQuantity(i) - Eval(x); 02360 sumD += fTestQuantity(i); 02361 sumSqD += fTestQuantity(i) * fTestQuantity(i); 02362 sumR += res; 02363 sumSqR += res * res; 02364 if (TESTBIT(fHistogramMask,HIST_RTEST)) 02365 ((TH1D*)fHistograms->FindObject("res_test"))->Fill(res); 02366 } 02367 Double_t dAvg = sumSqD - (sumD * sumD) / fTestSampleSize; 02368 Double_t rAvg = sumSqR - (sumR * sumR) / fTestSampleSize; 02369 fTestCorrelationCoeff = (dAvg - rAvg) / dAvg; 02370 fTestError = sumSqR; 02371 fTestPrecision = sumSqR / sumSqD; 02372 02373 TString opt(option); 02374 opt.ToLower(); 02375 02376 if (!opt.Contains("m")) 02377 MakeChi2(); 02378 02379 if (fNCoefficients * 50 > fTestSampleSize) 02380 Warning("Fit", "test sample is very small"); 02381 02382 if (!opt.Contains("m")) { 02383 delete [] x; 02384 return; 02385 } 02386 02387 fFitter = TVirtualFitter::Fitter(0,fNCoefficients); 02388 fFitter->SetFCN(mdfHelper); 02389 02390 const Int_t maxArgs = 16; 02391 Int_t args = 1; 02392 Double_t* arglist = new Double_t[maxArgs]; 02393 arglist[0] = -1; 02394 fFitter->ExecuteCommand("SET PRINT",arglist,args); 02395 02396 for (i = 0; i < fNCoefficients; i++) { 02397 Double_t startVal = fCoefficients(i); 02398 Double_t startErr = fCoefficientsRMS(i); 02399 fFitter->SetParameter(i, Form("coeff%02d",i), 02400 startVal, startErr, 0, 0); 02401 } 02402 02403 // arglist[0] = 0; 02404 args = 1; 02405 // fFitter->ExecuteCommand("SET PRINT",arglist,args); 02406 fFitter->ExecuteCommand("MIGRAD",arglist,args); 02407 02408 for (i = 0; i < fNCoefficients; i++) { 02409 Double_t val = 0, err = 0, low = 0, high = 0; 02410 fFitter->GetParameter(i, Form("coeff%02d",i), 02411 val, err, low, high); 02412 fCoefficients(i) = val; 02413 fCoefficientsRMS(i) = err; 02414 } 02415 delete [] x; 02416 } 02417 02418 //____________________________________________________________________ 02419 TMultiDimFit* TMultiDimFit::Instance() 02420 { 02421 // Return the static instance. 02422 return fgInstance; 02423 } 02424 02425 //____________________________________________________________________ 02426 void TMultiDimFit::MakeCandidates() 02427 { 02428 // PRIVATE METHOD: 02429 // Create list of candidate functions for the parameterisation. See 02430 // also 02431 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 02432 Int_t i = 0; 02433 Int_t j = 0; 02434 Int_t k = 0; 02435 02436 // The temporary array to store the powers in. We don't need to 02437 // initialize this array however. 02438 fMaxFuncNV = fNVariables * fMaxFunctions; 02439 Int_t *powers = new Int_t[fMaxFuncNV]; 02440 02441 // store of `control variables' 02442 Double_t* control = new Double_t[fMaxFunctions]; 02443 02444 // We've better initialize the variables 02445 Int_t *iv = new Int_t[fNVariables]; 02446 for (i = 0; i < fNVariables; i++) 02447 iv[i] = 1; 02448 02449 if (!fIsUserFunction) { 02450 02451 // Number of funcs selected 02452 Int_t numberFunctions = 0; 02453 02454 // Absolute max number of functions 02455 Int_t maxNumberFunctions = 1; 02456 for (i = 0; i < fNVariables; i++) 02457 maxNumberFunctions *= fMaxPowers[i]; 02458 02459 while (kTRUE) { 02460 // Get the control value for this function 02461 Double_t s = EvalControl(iv); 02462 02463 if (s <= fPowerLimit) { 02464 02465 // Call over-loadable method Select, as to allow the user to 02466 // interfere with the selection of functions. 02467 if (Select(iv)) { 02468 numberFunctions++; 02469 02470 // If we've reached the user defined limit of how many 02471 // functions we can consider, break out of the loop 02472 if (numberFunctions > fMaxFunctions) 02473 break; 02474 02475 // Store the control value, so we can sort array of powers 02476 // later on 02477 control[numberFunctions-1] = Int_t(1.0e+6*s); 02478 02479 // Store the powers in powers array. 02480 for (i = 0; i < fNVariables; i++) { 02481 j = (numberFunctions - 1) * fNVariables + i; 02482 powers[j] = iv[i]; 02483 } 02484 } // if (Select()) 02485 } // if (s <= fPowerLimit) 02486 02487 for (i = 0; i < fNVariables; i++) 02488 if (iv[i] < fMaxPowers[i]) 02489 break; 02490 02491 // If all variables have reached their maximum power, then we 02492 // break out of the loop 02493 if (i == fNVariables) { 02494 fMaxFunctions = numberFunctions; 02495 break; 02496 } 02497 02498 // Next power in variable i 02499 if (i < fNVariables) iv[i]++; 02500 02501 for (j = 0; j < i; j++) 02502 iv[j] = 1; 02503 } // while (kTRUE) 02504 } 02505 else { 02506 // In case the user gave an explicit function 02507 for (i = 0; i < fMaxFunctions; i++) { 02508 // Copy the powers to working arrays 02509 for (j = 0; j < fNVariables; j++) { 02510 powers[i * fNVariables + j] = fPowers[i * fNVariables + j]; 02511 iv[j] = fPowers[i * fNVariables + j]; 02512 } 02513 02514 control[i] = Int_t(1.0e+6*EvalControl(iv)); 02515 } 02516 } 02517 02518 // Now we need to sort the powers according to least `control 02519 // variable' 02520 Int_t *order = new Int_t[fMaxFunctions]; 02521 for (i = 0; i < fMaxFunctions; i++) 02522 order[i] = i; 02523 fMaxFuncNV = fMaxFunctions * fNVariables; 02524 fPowers = new Int_t[fMaxFuncNV]; 02525 02526 for (i = 0; i < fMaxFunctions; i++) { 02527 Double_t x = control[i]; 02528 Int_t l = order[i]; 02529 k = i; 02530 02531 for (j = i; j < fMaxFunctions; j++) { 02532 if (control[j] <= x) { 02533 x = control[j]; 02534 l = order[j]; 02535 k = j; 02536 } 02537 } 02538 02539 if (k != i) { 02540 control[k] = control[i]; 02541 control[i] = x; 02542 order[k] = order[i]; 02543 order[i] = l; 02544 } 02545 } 02546 02547 for (i = 0; i < fMaxFunctions; i++) 02548 for (j = 0; j < fNVariables; j++) 02549 fPowers[i * fNVariables + j] = powers[order[i] * fNVariables + j]; 02550 02551 delete [] control; 02552 delete [] powers; 02553 delete [] order; 02554 delete [] iv; 02555 } 02556 02557 02558 //____________________________________________________________________ 02559 Double_t TMultiDimFit::MakeChi2(const Double_t* coeff) 02560 { 02561 // Calculate Chi square over either the test sample. The optional 02562 // argument coeff is a vector of coefficients to use in the 02563 // evaluation of the parameterisation. If coeff == 0, then the found 02564 // coefficients is used. 02565 // Used my MINUIT for fit (see TMultDimFit::Fit) 02566 fChi2 = 0; 02567 Int_t i, j; 02568 Double_t* x = new Double_t[fNVariables]; 02569 for (i = 0; i < fTestSampleSize; i++) { 02570 // Get the stored point 02571 for (j = 0; j < fNVariables; j++) 02572 x[j] = fTestVariables(i * fNVariables + j); 02573 02574 // Evaluate function. Scale to shifted values 02575 Double_t f = Eval(x,coeff); 02576 02577 // Calculate contribution to Chic square 02578 fChi2 += 1. / TMath::Max(fTestSqError(i),1e-20) 02579 * (fTestQuantity(i) - f) * (fTestQuantity(i) - f); 02580 } 02581 02582 // Clean up 02583 delete [] x; 02584 02585 return fChi2; 02586 } 02587 02588 02589 //____________________________________________________________________ 02590 void TMultiDimFit::MakeCode(const char* filename, Option_t *option) 02591 { 02592 // Generate the file <filename> with .C appended if argument doesn't 02593 // end in .cxx or .C. The contains the implementation of the 02594 // function: 02595 // 02596 // Double_t <funcname>(Double_t *x) 02597 // 02598 // which does the same as TMultiDimFit::Eval. Please refer to this 02599 // method. 02600 // 02601 // Further, the static variables: 02602 // 02603 // Int_t gNVariables 02604 // Int_t gNCoefficients 02605 // Double_t gDMean 02606 // Double_t gXMean[] 02607 // Double_t gXMin[] 02608 // Double_t gXMax[] 02609 // Double_t gCoefficient[] 02610 // Int_t gPower[] 02611 // 02612 // are initialized. The only ROOT header file needed is Rtypes.h 02613 // 02614 // See TMultiDimFit::MakeRealCode for a list of options 02615 02616 02617 TString outName(filename); 02618 if (!outName.EndsWith(".C") && !outName.EndsWith(".cxx")) 02619 outName += ".C"; 02620 02621 MakeRealCode(outName.Data(),"",option); 02622 } 02623 02624 02625 02626 //____________________________________________________________________ 02627 void TMultiDimFit::MakeCoefficientErrors() 02628 { 02629 // PRIVATE METHOD: 02630 // Compute the errors on the coefficients. For this to be done, the 02631 // curvature matrix of the non-orthogonal functions, is computed. 02632 Int_t i = 0; 02633 Int_t j = 0; 02634 Int_t k = 0; 02635 TVectorD iF(fSampleSize); 02636 TVectorD jF(fSampleSize); 02637 fCoefficientsRMS.ResizeTo(fNCoefficients); 02638 02639 TMatrixDSym curvatureMatrix(fNCoefficients); 02640 02641 // Build the curvature matrix 02642 for (i = 0; i < fNCoefficients; i++) { 02643 iF = TMatrixDRow(fFunctions,i); 02644 for (j = 0; j <= i; j++) { 02645 jF = TMatrixDRow(fFunctions,j); 02646 for (k = 0; k < fSampleSize; k++) 02647 curvatureMatrix(i,j) += 02648 1 / TMath::Max(fSqError(k), 1e-20) * iF(k) * jF(k); 02649 curvatureMatrix(j,i) = curvatureMatrix(i,j); 02650 } 02651 } 02652 02653 // Calculate Chi Square 02654 fChi2 = 0; 02655 for (i = 0; i < fSampleSize; i++) { 02656 Double_t f = 0; 02657 for (j = 0; j < fNCoefficients; j++) 02658 f += fCoefficients(j) * fFunctions(j,i); 02659 fChi2 += 1. / TMath::Max(fSqError(i),1e-20) * (fQuantity(i) - f) 02660 * (fQuantity(i) - f); 02661 } 02662 02663 // Invert the curvature matrix 02664 const TVectorD diag = TMatrixDDiag_const(curvatureMatrix); 02665 curvatureMatrix.NormByDiag(diag); 02666 02667 TDecompChol chol(curvatureMatrix); 02668 if (!chol.Decompose()) 02669 Error("MakeCoefficientErrors", "curvature matrix is singular"); 02670 chol.Invert(curvatureMatrix); 02671 02672 curvatureMatrix.NormByDiag(diag); 02673 02674 for (i = 0; i < fNCoefficients; i++) 02675 fCoefficientsRMS(i) = TMath::Sqrt(curvatureMatrix(i,i)); 02676 } 02677 02678 02679 //____________________________________________________________________ 02680 void TMultiDimFit::MakeCoefficients() 02681 { 02682 // PRIVATE METHOD: 02683 // Invert the model matrix B, and compute final coefficients. For a 02684 // more thorough discussion of what this means, please refer to the 02685 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 02686 // 02687 // First we invert the lower triangle matrix fOrthCurvatureMatrix 02688 // and store the inverted matrix in the upper triangle. 02689 02690 Int_t i = 0, j = 0; 02691 Int_t col = 0, row = 0; 02692 02693 // Invert the B matrix 02694 for (col = 1; col < fNCoefficients; col++) { 02695 for (row = col - 1; row > -1; row--) { 02696 fOrthCurvatureMatrix(row,col) = 0; 02697 for (i = row; i <= col ; i++) 02698 fOrthCurvatureMatrix(row,col) -= 02699 fOrthCurvatureMatrix(i,row) 02700 * fOrthCurvatureMatrix(i,col); 02701 } 02702 } 02703 02704 // Compute the final coefficients 02705 fCoefficients.ResizeTo(fNCoefficients); 02706 02707 for (i = 0; i < fNCoefficients; i++) { 02708 Double_t sum = 0; 02709 for (j = i; j < fNCoefficients; j++) 02710 sum += fOrthCurvatureMatrix(i,j) * fOrthCoefficients(j); 02711 fCoefficients(i) = sum; 02712 } 02713 02714 // Compute the final residuals 02715 fResiduals.ResizeTo(fSampleSize); 02716 for (i = 0; i < fSampleSize; i++) 02717 fResiduals(i) = fQuantity(i); 02718 02719 for (i = 0; i < fNCoefficients; i++) 02720 for (j = 0; j < fSampleSize; j++) 02721 fResiduals(j) -= fCoefficients(i) * fFunctions(i,j); 02722 02723 // Compute the max and minimum, and squared sum of the evaluated 02724 // residuals 02725 fMinResidual = 10e10; 02726 fMaxResidual = -10e10; 02727 Double_t sqRes = 0; 02728 for (i = 0; i < fSampleSize; i++){ 02729 sqRes += fResiduals(i) * fResiduals(i); 02730 if (fResiduals(i) <= fMinResidual) { 02731 fMinResidual = fResiduals(i); 02732 fMinResidualRow = i; 02733 } 02734 if (fResiduals(i) >= fMaxResidual) { 02735 fMaxResidual = fResiduals(i); 02736 fMaxResidualRow = i; 02737 } 02738 } 02739 02740 fCorrelationCoeff = fSumSqResidual / fSumSqAvgQuantity; 02741 fPrecision = TMath::Sqrt(sqRes / fSumSqQuantity); 02742 02743 // If we use histograms, fill some more 02744 if (TESTBIT(fHistogramMask,HIST_RD) || 02745 TESTBIT(fHistogramMask,HIST_RTRAI) || 02746 TESTBIT(fHistogramMask,HIST_RX)) { 02747 for (i = 0; i < fSampleSize; i++) { 02748 if (TESTBIT(fHistogramMask,HIST_RD)) 02749 ((TH2D*)fHistograms->FindObject("res_d"))->Fill(fQuantity(i), 02750 fResiduals(i)); 02751 if (TESTBIT(fHistogramMask,HIST_RTRAI)) 02752 ((TH1D*)fHistograms->FindObject("res_train"))->Fill(fResiduals(i)); 02753 02754 if (TESTBIT(fHistogramMask,HIST_RX)) 02755 for (j = 0; j < fNVariables; j++) 02756 ((TH2D*)fHistograms->FindObject(Form("res_x_%d",j))) 02757 ->Fill(fVariables(i * fNVariables + j),fResiduals(i)); 02758 } 02759 } // If histograms 02760 02761 } 02762 02763 02764 //____________________________________________________________________ 02765 void TMultiDimFit::MakeCorrelation() 02766 { 02767 // PRIVATE METHOD: 02768 // Compute the correlation matrix 02769 if (!fShowCorrelation) 02770 return; 02771 02772 fCorrelationMatrix.ResizeTo(fNVariables,fNVariables+1); 02773 02774 Double_t d2 = 0; 02775 Double_t ddotXi = 0; // G.Q. needs to be reinitialized in the loop over i fNVariables 02776 Double_t xiNorm = 0; // G.Q. needs to be reinitialized in the loop over i fNVariables 02777 Double_t xidotXj = 0; // G.Q. needs to be reinitialized in the loop over j fNVariables 02778 Double_t xjNorm = 0; // G.Q. needs to be reinitialized in the loop over j fNVariables 02779 02780 Int_t i, j, k, l, m; // G.Q. added m variable 02781 for (i = 0; i < fSampleSize; i++) 02782 d2 += fQuantity(i) * fQuantity(i); 02783 02784 for (i = 0; i < fNVariables; i++) { 02785 ddotXi = 0.; // G.Q. reinitialisation 02786 xiNorm = 0.; // G.Q. reinitialisation 02787 for (j = 0; j< fSampleSize; j++) { 02788 // Index of sample j of variable i 02789 k = j * fNVariables + i; 02790 ddotXi += fQuantity(j) * (fVariables(k) - fMeanVariables(i)); 02791 xiNorm += (fVariables(k) - fMeanVariables(i)) 02792 * (fVariables(k) - fMeanVariables(i)); 02793 } 02794 fCorrelationMatrix(i,0) = ddotXi / TMath::Sqrt(d2 * xiNorm); 02795 02796 for (j = 0; j < i; j++) { 02797 xidotXj = 0.; // G.Q. reinitialisation 02798 xjNorm = 0.; // G.Q. reinitialisation 02799 for (k = 0; k < fSampleSize; k++) { 02800 // Index of sample j of variable i 02801 // l = j * fNVariables + k; // G.Q. 02802 l = k * fNVariables + j; // G.Q. 02803 m = k * fNVariables + i; // G.Q. 02804 // G.Q. xidotXj += (fVariables(i) - fMeanVariables(i)) 02805 // G.Q. * (fVariables(l) - fMeanVariables(j)); 02806 xidotXj += (fVariables(m) - fMeanVariables(i)) 02807 * (fVariables(l) - fMeanVariables(j)); // G.Q. modified index for Xi 02808 xjNorm += (fVariables(l) - fMeanVariables(j)) 02809 * (fVariables(l) - fMeanVariables(j)); 02810 } 02811 //fCorrelationMatrix(i+1,j) = xidotXj / TMath::Sqrt(xiNorm * xjNorm); 02812 fCorrelationMatrix(i,j+1) = xidotXj / TMath::Sqrt(xiNorm * xjNorm); 02813 } 02814 } 02815 } 02816 02817 02818 02819 //____________________________________________________________________ 02820 Double_t TMultiDimFit::MakeGramSchmidt(Int_t function) 02821 { 02822 // PRIVATE METHOD: 02823 // Make Gram-Schmidt orthogonalisation. The class description gives 02824 // a thorough account of this algorithm, as well as 02825 // references. Please refer to the 02826 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 02827 02828 02829 // calculate w_i, that is, evaluate the current function at data 02830 // point i 02831 Double_t f2 = 0; 02832 fOrthCoefficients(fNCoefficients) = 0; 02833 fOrthFunctionNorms(fNCoefficients) = 0; 02834 Int_t j = 0; 02835 Int_t k = 0; 02836 02837 for (j = 0; j < fSampleSize; j++) { 02838 fFunctions(fNCoefficients, j) = 1; 02839 fOrthFunctions(fNCoefficients, j) = 0; 02840 // First, however, we need to calculate f_fNCoefficients 02841 for (k = 0; k < fNVariables; k++) { 02842 Int_t p = fPowers[function * fNVariables + k]; 02843 Double_t x = fVariables(j * fNVariables + k); 02844 fFunctions(fNCoefficients, j) *= EvalFactor(p,x); 02845 } 02846 02847 // Calculate f dot f in f2 02848 f2 += fFunctions(fNCoefficients,j) * fFunctions(fNCoefficients,j); 02849 // Assign to w_fNCoefficients f_fNCoefficients 02850 fOrthFunctions(fNCoefficients, j) = fFunctions(fNCoefficients, j); 02851 } 02852 02853 // the first column of w is equal to f 02854 for (j = 0; j < fNCoefficients; j++) { 02855 Double_t fdw = 0; 02856 // Calculate (f_fNCoefficients dot w_j) / w_j^2 02857 for (k = 0; k < fSampleSize; k++) { 02858 fdw += fFunctions(fNCoefficients, k) * fOrthFunctions(j,k) 02859 / fOrthFunctionNorms(j); 02860 } 02861 02862 fOrthCurvatureMatrix(fNCoefficients,j) = fdw; 02863 // and subtract it from the current value of w_ij 02864 for (k = 0; k < fSampleSize; k++) 02865 fOrthFunctions(fNCoefficients,k) -= fdw * fOrthFunctions(j,k); 02866 } 02867 02868 for (j = 0; j < fSampleSize; j++) { 02869 // calculate squared length of w_fNCoefficients 02870 fOrthFunctionNorms(fNCoefficients) += 02871 fOrthFunctions(fNCoefficients,j) 02872 * fOrthFunctions(fNCoefficients,j); 02873 02874 // calculate D dot w_fNCoefficients in A 02875 fOrthCoefficients(fNCoefficients) += fQuantity(j) 02876 * fOrthFunctions(fNCoefficients, j); 02877 } 02878 02879 // First test, but only if didn't user specify 02880 if (!fIsUserFunction) 02881 if (TMath::Sqrt(fOrthFunctionNorms(fNCoefficients) / (f2 + 1e-10)) 02882 < TMath::Sin(fMinAngle*DEGRAD)) 02883 return 0; 02884 02885 // The result found by this code for the first residual is always 02886 // much less then the one found be MUDIFI. That's because it's 02887 // supposed to be. The cause is the improved precision of Double_t 02888 // over DOUBLE PRECISION! 02889 fOrthCurvatureMatrix(fNCoefficients,fNCoefficients) = 1; 02890 Double_t b = fOrthCoefficients(fNCoefficients); 02891 fOrthCoefficients(fNCoefficients) /= fOrthFunctionNorms(fNCoefficients); 02892 02893 // Calculate the residual from including this fNCoefficients. 02894 Double_t dResidur = fOrthCoefficients(fNCoefficients) * b; 02895 02896 return dResidur; 02897 } 02898 02899 02900 //____________________________________________________________________ 02901 void TMultiDimFit::MakeHistograms(Option_t *option) 02902 { 02903 // Make histograms of the result of the analysis. This message 02904 // should be sent after having read all data points, but before 02905 // finding the parameterization 02906 // 02907 // Options: 02908 // A All the below 02909 // X Original independent variables 02910 // D Original dependent variables 02911 // N Normalised independent variables 02912 // S Shifted dependent variables 02913 // R1 Residuals versus normalised independent variables 02914 // R2 Residuals versus dependent variable 02915 // R3 Residuals computed on training sample 02916 // R4 Residuals computed on test sample 02917 // 02918 // For a description of these quantities, refer to 02919 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 02920 TString opt(option); 02921 opt.ToLower(); 02922 02923 if (opt.Length() < 1) 02924 return; 02925 02926 if (!fHistograms) 02927 fHistograms = new TList; 02928 02929 // Counter variable 02930 Int_t i = 0; 02931 02932 // Histogram of original variables 02933 if (opt.Contains("x") || opt.Contains("a")) { 02934 SETBIT(fHistogramMask,HIST_XORIG); 02935 for (i = 0; i < fNVariables; i++) 02936 if (!fHistograms->FindObject(Form("x_%d_orig",i))) 02937 fHistograms->Add(new TH1D(Form("x_%d_orig",i), 02938 Form("Original variable # %d",i), 02939 fBinVarX, fMinVariables(i), 02940 fMaxVariables(i))); 02941 } 02942 02943 // Histogram of original dependent variable 02944 if (opt.Contains("d") || opt.Contains("a")) { 02945 SETBIT(fHistogramMask,HIST_DORIG); 02946 if (!fHistograms->FindObject("d_orig")) 02947 fHistograms->Add(new TH1D("d_orig", "Original Quantity", 02948 fBinVarX, fMinQuantity, fMaxQuantity)); 02949 } 02950 02951 // Histograms of normalized variables 02952 if (opt.Contains("n") || opt.Contains("a")) { 02953 SETBIT(fHistogramMask,HIST_XNORM); 02954 for (i = 0; i < fNVariables; i++) 02955 if (!fHistograms->FindObject(Form("x_%d_norm",i))) 02956 fHistograms->Add(new TH1D(Form("x_%d_norm",i), 02957 Form("Normalized variable # %d",i), 02958 fBinVarX, -1,1)); 02959 } 02960 02961 // Histogram of shifted dependent variable 02962 if (opt.Contains("s") || opt.Contains("a")) { 02963 SETBIT(fHistogramMask,HIST_DSHIF); 02964 if (!fHistograms->FindObject("d_shifted")) 02965 fHistograms->Add(new TH1D("d_shifted", "Shifted Quantity", 02966 fBinVarX, fMinQuantity - fMeanQuantity, 02967 fMaxQuantity - fMeanQuantity)); 02968 } 02969 02970 // Residual from training sample versus independent variables 02971 if (opt.Contains("r1") || opt.Contains("a")) { 02972 SETBIT(fHistogramMask,HIST_RX); 02973 for (i = 0; i < fNVariables; i++) 02974 if (!fHistograms->FindObject(Form("res_x_%d",i))) 02975 fHistograms->Add(new TH2D(Form("res_x_%d",i), 02976 Form("Computed residual versus x_%d", i), 02977 fBinVarX, -1, 1, 02978 fBinVarY, 02979 fMinQuantity - fMeanQuantity, 02980 fMaxQuantity - fMeanQuantity)); 02981 } 02982 02983 // Residual from training sample versus. dependent variable 02984 if (opt.Contains("r2") || opt.Contains("a")) { 02985 SETBIT(fHistogramMask,HIST_RD); 02986 if (!fHistograms->FindObject("res_d")) 02987 fHistograms->Add(new TH2D("res_d", 02988 "Computed residuals vs Quantity", 02989 fBinVarX, 02990 fMinQuantity - fMeanQuantity, 02991 fMaxQuantity - fMeanQuantity, 02992 fBinVarY, 02993 fMinQuantity - fMeanQuantity, 02994 fMaxQuantity - fMeanQuantity)); 02995 } 02996 02997 // Residual from training sample 02998 if (opt.Contains("r3") || opt.Contains("a")) { 02999 SETBIT(fHistogramMask,HIST_RTRAI); 03000 if (!fHistograms->FindObject("res_train")) 03001 fHistograms->Add(new TH1D("res_train", 03002 "Computed residuals over training sample", 03003 fBinVarX, fMinQuantity - fMeanQuantity, 03004 fMaxQuantity - fMeanQuantity)); 03005 03006 } 03007 if (opt.Contains("r4") || opt.Contains("a")) { 03008 SETBIT(fHistogramMask,HIST_RTEST); 03009 if (!fHistograms->FindObject("res_test")) 03010 fHistograms->Add(new TH1D("res_test", 03011 "Distribution of residuals from test", 03012 fBinVarX,fMinQuantity - fMeanQuantity, 03013 fMaxQuantity - fMeanQuantity)); 03014 } 03015 } 03016 03017 03018 //____________________________________________________________________ 03019 void TMultiDimFit::MakeMethod(const Char_t* classname, Option_t* option) 03020 { 03021 // Generate the file <classname>MDF.cxx which contains the 03022 // implementation of the method: 03023 // 03024 // Double_t <classname>::MDF(Double_t *x) 03025 // 03026 // which does the same as TMultiDimFit::Eval. Please refer to this 03027 // method. 03028 // 03029 // Further, the public static members: 03030 // 03031 // Int_t <classname>::fgNVariables 03032 // Int_t <classname>::fgNCoefficients 03033 // Double_t <classname>::fgDMean 03034 // Double_t <classname>::fgXMean[] //[fgNVariables] 03035 // Double_t <classname>::fgXMin[] //[fgNVariables] 03036 // Double_t <classname>::fgXMax[] //[fgNVariables] 03037 // Double_t <classname>::fgCoefficient[] //[fgNCoeffficents] 03038 // Int_t <classname>::fgPower[] //[fgNCoeffficents*fgNVariables] 03039 // 03040 // are initialized, and assumed to exist. The class declaration is 03041 // assumed to be in <classname>.h and assumed to be provided by the 03042 // user. 03043 // 03044 // See TMultiDimFit::MakeRealCode for a list of options 03045 // 03046 // The minimal class definition is: 03047 // 03048 // class <classname> { 03049 // public: 03050 // Int_t <classname>::fgNVariables; // Number of variables 03051 // Int_t <classname>::fgNCoefficients; // Number of terms 03052 // Double_t <classname>::fgDMean; // Mean from training sample 03053 // Double_t <classname>::fgXMean[]; // Mean from training sample 03054 // Double_t <classname>::fgXMin[]; // Min from training sample 03055 // Double_t <classname>::fgXMax[]; // Max from training sample 03056 // Double_t <classname>::fgCoefficient[]; // Coefficients 03057 // Int_t <classname>::fgPower[]; // Function powers 03058 // 03059 // Double_t Eval(Double_t *x); 03060 // }; 03061 // 03062 // Whether the method <classname>::Eval should be static or not, is 03063 // up to the user. 03064 03065 MakeRealCode(Form("%sMDF.cxx", classname), classname, option); 03066 } 03067 03068 03069 03070 //____________________________________________________________________ 03071 void TMultiDimFit::MakeNormalized() 03072 { 03073 // PRIVATE METHOD: 03074 // Normalize data to the interval [-1;1]. This is needed for the 03075 // classes method to work. 03076 03077 Int_t i = 0; 03078 Int_t j = 0; 03079 Int_t k = 0; 03080 03081 for (i = 0; i < fSampleSize; i++) { 03082 if (TESTBIT(fHistogramMask,HIST_DORIG)) 03083 ((TH1D*)fHistograms->FindObject("d_orig"))->Fill(fQuantity(i)); 03084 03085 fQuantity(i) -= fMeanQuantity; 03086 fSumSqAvgQuantity += fQuantity(i) * fQuantity(i); 03087 03088 if (TESTBIT(fHistogramMask,HIST_DSHIF)) 03089 ((TH1D*)fHistograms->FindObject("d_shifted"))->Fill(fQuantity(i)); 03090 03091 for (j = 0; j < fNVariables; j++) { 03092 Double_t range = 1. / (fMaxVariables(j) - fMinVariables(j)); 03093 k = i * fNVariables + j; 03094 03095 // Fill histograms of original independent variables 03096 if (TESTBIT(fHistogramMask,HIST_XORIG)) 03097 ((TH1D*)fHistograms->FindObject(Form("x_%d_orig",j))) 03098 ->Fill(fVariables(k)); 03099 03100 // Normalise independent variables 03101 fVariables(k) = 1 + 2 * range * (fVariables(k) - fMaxVariables(j)); 03102 03103 // Fill histograms of normalised independent variables 03104 if (TESTBIT(fHistogramMask,HIST_XNORM)) 03105 ((TH1D*)fHistograms->FindObject(Form("x_%d_norm",j))) 03106 ->Fill(fVariables(k)); 03107 03108 } 03109 } 03110 // Shift min and max of dependent variable 03111 fMaxQuantity -= fMeanQuantity; 03112 fMinQuantity -= fMeanQuantity; 03113 03114 // Shift mean of independent variables 03115 for (i = 0; i < fNVariables; i++) { 03116 Double_t range = 1. / (fMaxVariables(i) - fMinVariables(i)); 03117 fMeanVariables(i) = 1 + 2 * range * (fMeanVariables(i) 03118 - fMaxVariables(i)); 03119 } 03120 } 03121 03122 03123 //____________________________________________________________________ 03124 void TMultiDimFit::MakeParameterization() 03125 { 03126 // PRIVATE METHOD: 03127 // Find the parameterization over the training sample. A full account 03128 // of the algorithm is given in the 03129 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03130 03131 Int_t i = -1; 03132 Int_t j = 0; 03133 Int_t k = 0; 03134 Int_t maxPass = 3; 03135 Int_t studied = 0; 03136 Double_t squareResidual = fSumSqAvgQuantity; 03137 fNCoefficients = 0; 03138 fSumSqResidual = fSumSqAvgQuantity; 03139 fFunctions.ResizeTo(fMaxTerms,fSampleSize); 03140 fOrthFunctions.ResizeTo(fMaxTerms,fSampleSize); 03141 fOrthFunctionNorms.ResizeTo(fMaxTerms); 03142 fOrthCoefficients.ResizeTo(fMaxTerms); 03143 fOrthCurvatureMatrix.ResizeTo(fMaxTerms,fMaxTerms); 03144 fFunctions = 1; 03145 03146 fFunctionCodes = new Int_t[fMaxFunctions]; 03147 fPowerIndex = new Int_t[fMaxTerms]; 03148 Int_t l; 03149 for (l=0;l<fMaxFunctions;l++) fFunctionCodes[l] = 0; 03150 for (l=0;l<fMaxTerms;l++) fPowerIndex[l] = 0; 03151 03152 if (fMaxAngle != 0) maxPass = 100; 03153 if (fIsUserFunction) maxPass = 1; 03154 03155 // Loop over the number of functions we want to study. 03156 // increment inspection counter 03157 while(kTRUE) { 03158 03159 // Reach user defined limit of studies 03160 if (studied++ >= fMaxStudy) { 03161 fParameterisationCode = PARAM_MAXSTUDY; 03162 break; 03163 } 03164 03165 // Considered all functions several times 03166 if (k >= maxPass) { 03167 fParameterisationCode = PARAM_SEVERAL; 03168 break; 03169 } 03170 03171 // increment function counter 03172 i++; 03173 03174 // If we've reached the end of the functions, restart pass 03175 if (i == fMaxFunctions) { 03176 if (fMaxAngle != 0) 03177 fMaxAngle += (90 - fMaxAngle) / 2; 03178 i = 0; 03179 studied--; 03180 k++; 03181 continue; 03182 } 03183 if (studied == 1) 03184 fFunctionCodes[i] = 0; 03185 else if (fFunctionCodes[i] >= 2) 03186 continue; 03187 03188 // Print a happy message 03189 if (fIsVerbose && studied == 1) 03190 cout << "Coeff SumSqRes Contrib Angle QM Func" 03191 << " Value W^2 Powers" << endl; 03192 03193 // Make the Gram-Schmidt 03194 Double_t dResidur = MakeGramSchmidt(i); 03195 03196 if (dResidur == 0) { 03197 // This function is no good! 03198 // First test is in MakeGramSchmidt 03199 fFunctionCodes[i] = 1; 03200 continue; 03201 } 03202 03203 // If user specified function, assume she/he knows what he's doing 03204 if (!fIsUserFunction) { 03205 // Flag this function as considered 03206 fFunctionCodes[i] = 2; 03207 03208 // Test if this function contributes to the fit 03209 if (!TestFunction(squareResidual, dResidur)) { 03210 fFunctionCodes[i] = 1; 03211 continue; 03212 } 03213 } 03214 03215 // If we get to here, the function currently considered is 03216 // fNCoefficients, so we increment the counter 03217 // Flag this function as OK, and store and the number in the 03218 // index. 03219 fFunctionCodes[i] = 3; 03220 fPowerIndex[fNCoefficients] = i; 03221 fNCoefficients++; 03222 03223 // We add the current contribution to the sum of square of 03224 // residuals; 03225 squareResidual -= dResidur; 03226 03227 03228 // Calculate control parameter from this function 03229 for (j = 0; j < fNVariables; j++) { 03230 if (fNCoefficients == 1 03231 || fMaxPowersFinal[j] <= fPowers[i * fNVariables + j] - 1) 03232 fMaxPowersFinal[j] = fPowers[i * fNVariables + j] - 1; 03233 } 03234 Double_t s = EvalControl(&fPowers[i * fNVariables]); 03235 03236 // Print the statistics about this function 03237 if (fIsVerbose) { 03238 cout << setw(5) << fNCoefficients << " " 03239 << setw(10) << setprecision(4) << squareResidual << " " 03240 << setw(10) << setprecision(4) << dResidur << " " 03241 << setw(7) << setprecision(3) << fMaxAngle << " " 03242 << setw(7) << setprecision(3) << s << " " 03243 << setw(5) << i << " " 03244 << setw(10) << setprecision(4) 03245 << fOrthCoefficients(fNCoefficients-1) << " " 03246 << setw(10) << setprecision(4) 03247 << fOrthFunctionNorms(fNCoefficients-1) << " " 03248 << flush; 03249 for (j = 0; j < fNVariables; j++) 03250 cout << " " << fPowers[i * fNVariables + j] - 1 << flush; 03251 cout << endl; 03252 } 03253 03254 if (fNCoefficients >= fMaxTerms /* && fIsVerbose */) { 03255 fParameterisationCode = PARAM_MAXTERMS; 03256 break; 03257 } 03258 03259 Double_t err = TMath::Sqrt(TMath::Max(1e-20,squareResidual) / 03260 fSumSqAvgQuantity); 03261 if (err < fMinRelativeError) { 03262 fParameterisationCode = PARAM_RELERR; 03263 break; 03264 } 03265 03266 } 03267 03268 fError = TMath::Max(1e-20,squareResidual); 03269 fSumSqResidual -= fError; 03270 fRMS = TMath::Sqrt(fError / fSampleSize); 03271 } 03272 03273 03274 //____________________________________________________________________ 03275 void TMultiDimFit::MakeRealCode(const char *filename, 03276 const char *classname, 03277 Option_t *) 03278 { 03279 // PRIVATE METHOD: 03280 // This is the method that actually generates the code for the 03281 // evaluation the parameterization on some point. 03282 // It's called by TMultiDimFit::MakeCode and TMultiDimFit::MakeMethod. 03283 // 03284 // The options are: NONE so far 03285 Int_t i, j; 03286 03287 Bool_t isMethod = (classname[0] == '\0' ? kFALSE : kTRUE); 03288 const char *prefix = (isMethod ? Form("%s::", classname) : ""); 03289 const char *cv_qual = (isMethod ? "" : "static "); 03290 03291 ofstream outFile(filename,ios::out|ios::trunc); 03292 if (!outFile) { 03293 Error("MakeRealCode","couldn't open output file '%s'",filename); 03294 return; 03295 } 03296 03297 if (fIsVerbose) 03298 cout << "Writing on file \"" << filename << "\" ... " << flush; 03299 // 03300 // Write header of file 03301 // 03302 // Emacs mode line ;-) 03303 outFile << "// -*- mode: c++ -*-" << endl; 03304 // Info about creator 03305 outFile << "// " << endl 03306 << "// File " << filename 03307 << " generated by TMultiDimFit::MakeRealCode" << endl; 03308 // Time stamp 03309 TDatime date; 03310 outFile << "// on " << date.AsString() << endl; 03311 // ROOT version info 03312 outFile << "// ROOT version " << gROOT->GetVersion() 03313 << endl << "//" << endl; 03314 // General information on the code 03315 outFile << "// This file contains the function " << endl 03316 << "//" << endl 03317 << "// double " << prefix << "MDF(double *x); " << endl 03318 << "//" << endl 03319 << "// For evaluating the parameterization obtained" << endl 03320 << "// from TMultiDimFit and the point x" << endl 03321 << "// " << endl 03322 << "// See TMultiDimFit class documentation for more " 03323 << "information " << endl << "// " << endl; 03324 // Header files 03325 if (isMethod) 03326 // If these are methods, we need the class header 03327 outFile << "#include \"" << classname << ".h\"" << endl; 03328 03329 // 03330 // Now for the data 03331 // 03332 outFile << "//" << endl 03333 << "// Static data variables" << endl 03334 << "//" << endl; 03335 outFile << cv_qual << "int " << prefix << "gNVariables = " 03336 << fNVariables << ";" << endl; 03337 outFile << cv_qual << "int " << prefix << "gNCoefficients = " 03338 << fNCoefficients << ";" << endl; 03339 outFile << cv_qual << "double " << prefix << "gDMean = " 03340 << fMeanQuantity << ";" << endl; 03341 03342 // Assignment to mean vector. 03343 outFile << "// Assignment to mean vector." << endl; 03344 outFile << cv_qual << "double " << prefix 03345 << "gXMean[] = {" << endl; 03346 for (i = 0; i < fNVariables; i++) 03347 outFile << (i != 0 ? ", " : " ") << fMeanVariables(i) << flush; 03348 outFile << " };" << endl << endl; 03349 03350 // Assignment to minimum vector. 03351 outFile << "// Assignment to minimum vector." << endl; 03352 outFile << cv_qual << "double " << prefix 03353 << "gXMin[] = {" << endl; 03354 for (i = 0; i < fNVariables; i++) 03355 outFile << (i != 0 ? ", " : " ") << fMinVariables(i) << flush; 03356 outFile << " };" << endl << endl; 03357 03358 // Assignment to maximum vector. 03359 outFile << "// Assignment to maximum vector." << endl; 03360 outFile << cv_qual << "double " << prefix 03361 << "gXMax[] = {" << endl; 03362 for (i = 0; i < fNVariables; i++) 03363 outFile << (i != 0 ? ", " : " ") << fMaxVariables(i) << flush; 03364 outFile << " };" << endl << endl; 03365 03366 // Assignment to coefficients vector. 03367 outFile << "// Assignment to coefficients vector." << endl; 03368 outFile << cv_qual << "double " << prefix 03369 << "gCoefficient[] = {" << flush; 03370 for (i = 0; i < fNCoefficients; i++) 03371 outFile << (i != 0 ? "," : "") << endl 03372 << " " << fCoefficients(i) << flush; 03373 outFile << endl << " };" << endl << endl; 03374 03375 // Assignment to error coefficients vector. 03376 outFile << "// Assignment to error coefficients vector." << endl; 03377 outFile << cv_qual << "double " << prefix 03378 << "gCoefficientRMS[] = {" << flush; 03379 for (i = 0; i < fNCoefficients; i++) 03380 outFile << (i != 0 ? "," : "") << endl 03381 << " " << fCoefficientsRMS(i) << flush; 03382 outFile << endl << " };" << endl << endl; 03383 03384 // Assignment to powers vector. 03385 outFile << "// Assignment to powers vector." << endl 03386 << "// The powers are stored row-wise, that is" << endl 03387 << "// p_ij = " << prefix 03388 << "gPower[i * NVariables + j];" << endl; 03389 outFile << cv_qual << "int " << prefix 03390 << "gPower[] = {" << flush; 03391 for (i = 0; i < fNCoefficients; i++) { 03392 for (j = 0; j < fNVariables; j++) { 03393 if (j != 0) outFile << flush << " "; 03394 else outFile << endl << " "; 03395 outFile << fPowers[fPowerIndex[i] * fNVariables + j] 03396 << (i == fNCoefficients - 1 && j == fNVariables - 1 ? "" : ",") 03397 << flush; 03398 } 03399 } 03400 outFile << endl << "};" << endl << endl; 03401 03402 03403 // 03404 // Finally we reach the function itself 03405 // 03406 outFile << "// " << endl 03407 << "// The " 03408 << (isMethod ? "method " : "function ") 03409 << " double " << prefix 03410 << "MDF(double *x)" 03411 << endl << "// " << endl; 03412 outFile << "double " << prefix 03413 << "MDF(double *x) {" << endl 03414 << " double returnValue = " << prefix << "gDMean;" << endl 03415 << " int i = 0, j = 0, k = 0;" << endl 03416 << " for (i = 0; i < " << prefix << "gNCoefficients ; i++) {" 03417 << endl 03418 << " // Evaluate the ith term in the expansion" << endl 03419 << " double term = " << prefix << "gCoefficient[i];" 03420 << endl 03421 << " for (j = 0; j < " << prefix << "gNVariables; j++) {" 03422 << endl 03423 << " // Evaluate the polynomial in the jth variable." << endl 03424 << " int power = "<< prefix << "gPower[" 03425 << prefix << "gNVariables * i + j]; " << endl 03426 << " double p1 = 1, p2 = 0, p3 = 0, r = 0;" << endl 03427 << " double v = 1 + 2. / (" 03428 << prefix << "gXMax[j] - " << prefix 03429 << "gXMin[j]) * (x[j] - " << prefix << "gXMax[j]);" << endl 03430 << " // what is the power to use!" << endl 03431 << " switch(power) {" << endl 03432 << " case 1: r = 1; break; " << endl 03433 << " case 2: r = v; break; " << endl 03434 << " default: " << endl 03435 << " p2 = v; " << endl 03436 << " for (k = 3; k <= power; k++) { " << endl 03437 << " p3 = p2 * v;" << endl; 03438 if (fPolyType == kLegendre) 03439 outFile << " p3 = ((2 * i - 3) * p2 * v - (i - 2) * p1)" 03440 << " / (i - 1);" << endl; 03441 if (fPolyType == kChebyshev) 03442 outFile << " p3 = 2 * v * p2 - p1; " << endl; 03443 outFile << " p1 = p2; p2 = p3; " << endl << " }" << endl 03444 << " r = p3;" << endl << " }" << endl 03445 << " // multiply this term by the poly in the jth var" << endl 03446 << " term *= r; " << endl << " }" << endl 03447 << " // Add this term to the final result" << endl 03448 << " returnValue += term;" << endl << " }" << endl 03449 << " return returnValue;" << endl << "}" << endl << endl; 03450 03451 // EOF 03452 outFile << "// EOF for " << filename << endl; 03453 03454 // Close the file 03455 outFile.close(); 03456 03457 if (fIsVerbose) 03458 cout << "done" << endl; 03459 } 03460 03461 03462 //____________________________________________________________________ 03463 void TMultiDimFit::Print(Option_t *option) const 03464 { 03465 // Print statistics etc. 03466 // Options are 03467 // P Parameters 03468 // S Statistics 03469 // C Coefficients 03470 // R Result of parameterisation 03471 // F Result of fit 03472 // K Correlation Matrix 03473 // M Pretty print formula 03474 // 03475 Int_t i = 0; 03476 Int_t j = 0; 03477 03478 TString opt(option); 03479 opt.ToLower(); 03480 03481 if (opt.Contains("p")) { 03482 // Print basic parameters for this object 03483 cout << "User parameters:" << endl 03484 << "----------------" << endl 03485 << " Variables: " << fNVariables << endl 03486 << " Data points: " << fSampleSize << endl 03487 << " Max Terms: " << fMaxTerms << endl 03488 << " Power Limit Parameter: " << fPowerLimit << endl 03489 << " Max functions: " << fMaxFunctions << endl 03490 << " Max functions to study: " << fMaxStudy << endl 03491 << " Max angle (optional): " << fMaxAngle << endl 03492 << " Min angle: " << fMinAngle << endl 03493 << " Relative Error accepted: " << fMinRelativeError << endl 03494 << " Maximum Powers: " << flush; 03495 for (i = 0; i < fNVariables; i++) 03496 cout << " " << fMaxPowers[i] - 1 << flush; 03497 cout << endl << endl 03498 << " Parameterisation will be done using " << flush; 03499 if (fPolyType == kChebyshev) 03500 cout << "Chebyshev polynomials" << endl; 03501 else if (fPolyType == kLegendre) 03502 cout << "Legendre polynomials" << endl; 03503 else 03504 cout << "Monomials" << endl; 03505 cout << endl; 03506 } 03507 03508 if (opt.Contains("s")) { 03509 // Print statistics for read data 03510 cout << "Sample statistics:" << endl 03511 << "------------------" << endl 03512 << " D" << flush; 03513 for (i = 0; i < fNVariables; i++) 03514 cout << " " << setw(10) << i+1 << flush; 03515 cout << endl << " Max: " << setw(10) << setprecision(7) 03516 << fMaxQuantity << flush; 03517 for (i = 0; i < fNVariables; i++) 03518 cout << " " << setw(10) << setprecision(4) 03519 << fMaxVariables(i) << flush; 03520 cout << endl << " Min: " << setw(10) << setprecision(7) 03521 << fMinQuantity << flush; 03522 for (i = 0; i < fNVariables; i++) 03523 cout << " " << setw(10) << setprecision(4) 03524 << fMinVariables(i) << flush; 03525 cout << endl << " Mean: " << setw(10) << setprecision(7) 03526 << fMeanQuantity << flush; 03527 for (i = 0; i < fNVariables; i++) 03528 cout << " " << setw(10) << setprecision(4) 03529 << fMeanVariables(i) << flush; 03530 cout << endl << " Function Sum Squares: " << fSumSqQuantity 03531 << endl << endl; 03532 } 03533 03534 if (opt.Contains("r")) { 03535 cout << "Results of Parameterisation:" << endl 03536 << "----------------------------" << endl 03537 << " Total reduction of square residuals " 03538 << fSumSqResidual << endl 03539 << " Relative precision obtained: " 03540 << fPrecision << endl 03541 << " Error obtained: " 03542 << fError << endl 03543 << " Multiple correlation coefficient: " 03544 << fCorrelationCoeff << endl 03545 << " Reduced Chi square over sample: " 03546 << fChi2 / (fSampleSize - fNCoefficients) << endl 03547 << " Maximum residual value: " 03548 << fMaxResidual << endl 03549 << " Minimum residual value: " 03550 << fMinResidual << endl 03551 << " Estimated root mean square: " 03552 << fRMS << endl 03553 << " Maximum powers used: " << flush; 03554 for (j = 0; j < fNVariables; j++) 03555 cout << fMaxPowersFinal[j] << " " << flush; 03556 cout << endl 03557 << " Function codes of candidate functions." << endl 03558 << " 1: considered," 03559 << " 2: too little contribution," 03560 << " 3: accepted." << flush; 03561 for (i = 0; i < fMaxFunctions; i++) { 03562 if (i % 60 == 0) 03563 cout << endl << " " << flush; 03564 else if (i % 10 == 0) 03565 cout << " " << flush; 03566 cout << fFunctionCodes[i]; 03567 } 03568 cout << endl << " Loop over candidates stopped because " << flush; 03569 switch(fParameterisationCode){ 03570 case PARAM_MAXSTUDY: 03571 cout << "max allowed studies reached" << endl; break; 03572 case PARAM_SEVERAL: 03573 cout << "all candidates considered several times" << endl; break; 03574 case PARAM_RELERR: 03575 cout << "wanted relative error obtained" << endl; break; 03576 case PARAM_MAXTERMS: 03577 cout << "max number of terms reached" << endl; break; 03578 default: 03579 cout << "some unknown reason" << endl; 03580 break; 03581 } 03582 cout << endl; 03583 } 03584 03585 if (opt.Contains("f")) { 03586 cout << "Results of Fit:" << endl 03587 << "---------------" << endl 03588 << " Test sample size: " 03589 << fTestSampleSize << endl 03590 << " Multiple correlation coefficient: " 03591 << fTestCorrelationCoeff << endl 03592 << " Relative precision obtained: " 03593 << fTestPrecision << endl 03594 << " Error obtained: " 03595 << fTestError << endl 03596 << " Reduced Chi square over sample: " 03597 << fChi2 / (fSampleSize - fNCoefficients) << endl 03598 << endl; 03599 if (fFitter) { 03600 fFitter->PrintResults(1,1); 03601 cout << endl; 03602 } 03603 } 03604 03605 if (opt.Contains("c")){ 03606 cout << "Coefficients:" << endl 03607 << "-------------" << endl 03608 << " # Value Error Powers" << endl 03609 << " ---------------------------------------" << endl; 03610 for (i = 0; i < fNCoefficients; i++) { 03611 cout << " " << setw(3) << i << " " 03612 << setw(12) << fCoefficients(i) << " " 03613 << setw(12) << fCoefficientsRMS(i) << " " << flush; 03614 for (j = 0; j < fNVariables; j++) 03615 cout << " " << setw(3) 03616 << fPowers[fPowerIndex[i] * fNVariables + j] - 1 << flush; 03617 cout << endl; 03618 } 03619 cout << endl; 03620 } 03621 if (opt.Contains("k") && fCorrelationMatrix.IsValid()) { 03622 cout << "Correlation Matrix:" << endl 03623 << "-------------------"; 03624 fCorrelationMatrix.Print(); 03625 } 03626 03627 if (opt.Contains("m")) { 03628 cout << "Parameterization:" << endl 03629 << "-----------------" << endl 03630 << " Normalised variables: " << endl; 03631 for (i = 0; i < fNVariables; i++) 03632 cout << "\ty_" << i << "\t= 1 + 2 * (x_" << i << " - " 03633 << fMaxVariables(i) << ") / (" 03634 << fMaxVariables(i) << " - " << fMinVariables(i) << ")" 03635 << endl; 03636 cout << endl 03637 << " f("; 03638 for (i = 0; i < fNVariables; i++) { 03639 cout << "y_" << i; 03640 if (i != fNVariables-1) cout << ", "; 03641 } 03642 cout << ") = "; 03643 for (i = 0; i < fNCoefficients; i++) { 03644 if (i != 0) 03645 cout << endl << "\t" << (fCoefficients(i) < 0 ? "- " : "+ ") 03646 << TMath::Abs(fCoefficients(i)); 03647 else 03648 cout << fCoefficients(i); 03649 for (j = 0; j < fNVariables; j++) { 03650 Int_t p = fPowers[fPowerIndex[i] * fNVariables + j]; 03651 switch (p) { 03652 case 1: break; 03653 case 2: cout << " * y_" << j; break; 03654 default: 03655 switch(fPolyType) { 03656 case kLegendre: cout << " * L_" << p-1 << "(y_" << j << ")"; break; 03657 case kChebyshev: cout << " * C_" << p-1 << "(y_" << j << ")"; break; 03658 default: cout << " * y_" << j << "^" << p-1; break; 03659 } 03660 } 03661 03662 } 03663 } 03664 cout << endl; 03665 } 03666 } 03667 03668 03669 //____________________________________________________________________ 03670 Bool_t TMultiDimFit::Select(const Int_t *) 03671 { 03672 // Selection method. User can override this method for specialized 03673 // selection of acceptable functions in fit. Default is to select 03674 // all. This message is sent during the build-up of the function 03675 // candidates table once for each set of powers in 03676 // variables. Notice, that the argument array contains the powers 03677 // PLUS ONE. For example, to De select the function 03678 // f = x1^2 * x2^4 * x3^5, 03679 // this method should return kFALSE if given the argument 03680 // { 3, 4, 6 } 03681 return kTRUE; 03682 } 03683 03684 //____________________________________________________________________ 03685 void TMultiDimFit::SetMaxAngle(Double_t ang) 03686 { 03687 // Set the max angle (in degrees) between the initial data vector to 03688 // be fitted, and the new candidate function to be included in the 03689 // fit. By default it is 0, which automatically chooses another 03690 // selection criteria. See also 03691 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03692 if (ang >= 90 || ang < 0) { 03693 Warning("SetMaxAngle", "angle must be in [0,90)"); 03694 return; 03695 } 03696 03697 fMaxAngle = ang; 03698 } 03699 03700 //____________________________________________________________________ 03701 void TMultiDimFit::SetMinAngle(Double_t ang) 03702 { 03703 // Set the min angle (in degrees) between a new candidate function 03704 // and the subspace spanned by the previously accepted 03705 // functions. See also 03706 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03707 if (ang > 90 || ang <= 0) { 03708 Warning("SetMinAngle", "angle must be in [0,90)"); 03709 return; 03710 } 03711 03712 fMinAngle = ang; 03713 03714 } 03715 03716 03717 //____________________________________________________________________ 03718 void TMultiDimFit::SetPowers(const Int_t* powers, Int_t terms) 03719 { 03720 // Define a user function. The input array must be of the form 03721 // (p11, ..., p1N, ... ,pL1, ..., pLN) 03722 // Where N is the dimension of the data sample, L is the number of 03723 // terms (given in terms) and the first number, labels the term, the 03724 // second the variable. More information is given in the 03725 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03726 fIsUserFunction = kTRUE; 03727 fMaxFunctions = terms; 03728 fMaxTerms = terms; 03729 fMaxStudy = terms; 03730 fMaxFuncNV = fMaxFunctions * fNVariables; 03731 fPowers = new Int_t[fMaxFuncNV]; 03732 Int_t i, j; 03733 for (i = 0; i < fMaxFunctions; i++) 03734 for(j = 0; j < fNVariables; j++) 03735 fPowers[i * fNVariables + j] = powers[i * fNVariables + j] + 1; 03736 } 03737 03738 //____________________________________________________________________ 03739 void TMultiDimFit::SetPowerLimit(Double_t limit) 03740 { 03741 // Set the user parameter for the function selection. The bigger the 03742 // limit, the more functions are used. The meaning of this variable 03743 // is defined in the 03744 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03745 fPowerLimit = limit; 03746 } 03747 03748 //____________________________________________________________________ 03749 void TMultiDimFit::SetMaxPowers(const Int_t* powers) 03750 { 03751 // Set the maximum power to be considered in the fit for each 03752 // variable. See also 03753 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03754 if (!powers) 03755 return; 03756 03757 for (Int_t i = 0; i < fNVariables; i++) 03758 fMaxPowers[i] = powers[i]+1; 03759 } 03760 03761 //____________________________________________________________________ 03762 void TMultiDimFit::SetMinRelativeError(Double_t error) 03763 { 03764 // Set the acceptable relative error for when sum of square 03765 // residuals is considered minimized. For a full account, refer to 03766 // the 03767 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03768 fMinRelativeError = error; 03769 } 03770 03771 03772 //____________________________________________________________________ 03773 Bool_t TMultiDimFit::TestFunction(Double_t squareResidual, 03774 Double_t dResidur) 03775 { 03776 // PRIVATE METHOD: 03777 // Test whether the currently considered function contributes to the 03778 // fit. See also 03779 // Begin_Html<a href="#TMultiDimFit:description">class description</a>End_Html 03780 03781 if (fNCoefficients != 0) { 03782 // Now for the second test: 03783 if (fMaxAngle == 0) { 03784 // If the user hasn't supplied a max angle do the test as, 03785 if (dResidur < 03786 squareResidual / (fMaxTerms - fNCoefficients + 1 + 1E-10)) { 03787 return kFALSE; 03788 } 03789 } 03790 else { 03791 // If the user has provided a max angle, test if the calculated 03792 // angle is less then the max angle. 03793 if (TMath::Sqrt(dResidur/fSumSqAvgQuantity) < 03794 TMath::Cos(fMaxAngle*DEGRAD)) { 03795 return kFALSE; 03796 } 03797 } 03798 } 03799 // If we get here, the function is OK 03800 return kTRUE; 03801 } 03802 03803 03804 //____________________________________________________________________ 03805 void mdfHelper(int& /*npar*/, double* /*divs*/, double& chi2, 03806 double* coeffs, int /*flag*/) 03807 { 03808 // Helper function for doing the minimisation of Chi2 using Minuit 03809 03810 // Get pointer to current TMultiDimFit object. 03811 TMultiDimFit* mdf = TMultiDimFit::Instance(); 03812 chi2 = mdf->MakeChi2(coeffs); 03813 }