Fitting across array

Hi all

I have a function which generates the elements of an array, but to fit using the TF1.fit() routine, requires it to return just a single element - to my understanding.
This increases the runtime by a factor of ~400 (the number of bins over which the function has to be re-run).

Is there a way to return the whole element and to use it to fit to data using the fit routine, or do I need to construct my own TMinuit or TMinuitMinimiser object?

I do not understand your problem and the factor 400.
Could you post the shortest possible RUNNING script showing your problem?
(and a data file if there is one)

REne

The problem is that the code needs to compute every element of a 400-element array simultaneously (because the elements of the array are inter-related) - but to my understanding, to fit it using a TF1->fit requires the function to only return a double, rather than a whole array.
This means that to calculate the TF1 over its range means that a self-same array is calculated once for every array of the element which is returned.

In retrospect, I could rewrite the program flow so as not to recalculate the entire matrix at every call of the TF1

This is the main function, the remaining several hundred lines of code are within the array-generating function instEmiss which calculates the instantaneous flux from a source
The function instEmiss which is in the TF1 spect creates this 400 element array

void Mrk501fit()
{
  TCanvas* c1[3];
  TF1* spect;
  spect = new TF1("spect",instEmiss,pow(10,7), pow(10,25),8 );

  TGraphErrors* datagraph[3];
  
  ifstream fin;
  double nu, nuFnu;
  int count;
  int limit;
 
  for( int i= 0; i < 3; i++)
    {
      c1[i] = new TCanvas("C1","Observed Spectrum",1200,800);
      count = 0;
      if(i==0)
      { 
        fin.open("2005high.dat");
        limit = 14;
      }
      if(i==1)
      {
        fin.open("2005low.dat");
        limit = 10;
      }
      if(i==2)
      {
        limit = 16;
        fin.open("2008a.dat");
      }

      datagraph[i] = new TGraphErrors(limit); 
      while(count < limit)
	{
          fin >> nu >> nuFnu;
          nu = pow(10, nu);
          nuFnu = pow(10, nuFnu);
          datagraph[i]->SetPoint(count,nu,nuFnu);
          datagraph[i]->SetPointError(count,0,nuFnu*0.50 ); //set an arbitrary error of 50%
          count++;
	} 
      fin.close();

      gPad->SetLogx(1);
      gPad->SetLogy(1);
     
      datagraph[i]->GetXaxis()->SetRangeUser(1E10,1E29);
      datagraph[i]->GetYaxis()->SetRangeUser(1E-13,1E-8);
      datagraph[i]->Draw("A*");

      c1[i]->Modified();
      c1[i]->Update();

      // redshift - fixed
      spect->FixParameter(0, 0.033663);
   
      // break in spectrum      
      spect->SetParameter(1, 6);
      spect->SetParLimits(1, 1, 9 );

      // slope 1
      spect->SetParameter(2, 0.3);
      spect->SetParLimits(2, 0, 1 );

      //slope 2
      spect->SetParameter(3, 0.5);
      spect->SetParLimits(3, 0, 1 );

      //magnetic field, microGauss
      spect->SetParameter(4, 5.5 );
      spect->SetParLimits(4, 4, 8 );

      // number density /cm^3
      spect->SetParameter(5, 6);
      spect->SetParLimits(5, 1, 10 );

      // region radius, /cm
      spect->SetParameter(6, 15);
      spect->SetParLimits(6, 10, 20 );
 
      //doppler
      spect->SetParameter(7, 1.5);
      spect->SetParLimits(7, 0, 2 );      

      spect->SetParNames("z","break","n1","n2","B (uG)","K (cm^-3)","R (cm)","doppler ");

      datagraph[i]->Fit("spect");

      spect->Draw("sameC");
      c1[i]->Modified();
      c1[i]->Update();

    }
}

Hi,

you can create the TF1 caching the 400 array elements and compute then only once when the parameters are changed. For creating a TF1 using an external object (see D or E in root.cern.ch/root/htmldoc/TF1.html#F4).

Otherwise you need to implement yourself the chi2 fitting function and pass to Minuit (or the Minimizer interface) for minimizing it.
See root.cern.ch/drupal/content/nume … nimization

Best Regards

Lorenzo