TMultiDimFit.cxx

Go to the documentation of this file.
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} &lt; \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}} &lt; 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&nbsp;<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) $">&nbsp; &nbsp;with<IMG
00494  WIDTH="120" HEIGHT="29" ALIGN="MIDDLE" BORDER="0"
00495  SRC="gif/multidimfit_img45.gif"
00496  ALT="$\displaystyle &nbsp;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$">&nbsp; &nbsp;if<IMG
00633  WIDTH="65" HEIGHT="29" ALIGN="MIDDLE" BORDER="0"
00634  SRC="gif/multidimfit_img62.gif"
00635  ALT="$\displaystyle &nbsp;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&nbsp;(<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 &nbsp;</TD></TR>
00765 <TR VALIGN="MIDDLE"><TD NOWRAP ALIGN="RIGHT">&nbsp;</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 &nbsp;</TD></TR>
00776 <TR VALIGN="MIDDLE"><TD NOWRAP ALIGN="RIGHT">&nbsp;</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&nbsp;<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&nbsp;<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&nbsp;(<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 &gt; \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&nbsp;(<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} &amp; i &lt; j\  1 &amp; \mbox{if} &amp; i = j\  0 &amp; \mbox{if} &amp; i &gt; 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&nbsp;R. Bevington and D.&nbsp;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&#233; Brun et&nbsp;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&nbsp;H. Golub and Charles&nbsp;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.&nbsp;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.&nbsp;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.&nbsp;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 }

Generated on Tue Jul 5 14:24:21 2011 for ROOT_528-00b_version by  doxygen 1.5.1