Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TFitParametersDialog.cxx
Go to the documentation of this file.
1 // @(#)root/fitpanel:$Id$
2 // Author: Ilka Antcheva, Lorenzo Moneta 03/10/06
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TFitParametersDialog //
15 // //
16 // Create a dialog for fit function parameter settings. //
17 // //
18 //////////////////////////////////////////////////////////////////////////
19 
20 #include "TFitParametersDialog.h"
21 #include "TF1.h"
22 #include "TGButton.h"
23 #include "TGFrame.h"
24 #include "TGLabel.h"
25 #include "TGLayout.h"
26 #include "TGTextEntry.h"
27 #include "TGMsgBox.h"
28 #include "TGNumberEntry.h"
29 #include "TGTripleSlider.h"
30 #include "TVirtualPad.h"
31 #include "TMath.h"
32 
33 #include <limits>
34 
35 
36 enum EParametersDialogWid {
37  kNAME,
38  kFIX = 10,
39  kBND = 20,
40  kVAL = 30,
41  kMIN = 40,
42  kMAX = 50,
43  kSLD = 60,
44  kSTP = 70,
45  kERR = 80,
46  kUPDATE = 8888,
47  kRESET,
48  kAPPLY,
49  kOK,
50  kCANCEL
51 };
52 
53 ClassImp(TFitParametersDialog);
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 
57 TFitParametersDialog::TFitParametersDialog(const TGWindow *p,
58  const TGWindow *main,
59  TF1 *func,
60  TVirtualPad *pad,
61  Int_t *ret_code) :
62  TGTransientFrame(p, main, 10, 10, kVerticalFrame),
63  fFunc (func),
64  fFpad (pad),
65  fHasChanges (kFALSE),
66  fImmediateDraw (kTRUE),
67  fRetCode (ret_code)
68 
69 {
70  // Create a dialog for fit function parameters' settings.
71 
72  SetCleanup(kDeepCleanup);
73 
74  fFunc->GetRange(fRangexmin, fRangexmax);
75  fNP = fFunc->GetNpar();
76  fPmin = new Double_t[fNP];
77  fPmax = new Double_t[fNP];
78  fPval = new Double_t[fNP];
79  fPerr = new Double_t[fNP];
80  fPstp = new Double_t[fNP];
81 
82  for (Int_t i = 0; i < fNP; i++) {
83  fFunc->GetParLimits(i, fPmin[i], fPmax[i]);
84  fPval[i] = fFunc->GetParameter(i);
85  fPerr[i] = fFunc->GetParError(i);
86  if (fPerr[i] > 1E-16)
87  fPstp[i] = TMath::Power(10, TMath::Floor(TMath::Log10(fPerr[i])));
88  else {
89  if (TMath::Abs(fPval[i]) > 1.)
90  // if error is zero use as step approx 10% of current value
91  fPstp[i] = TMath::Power(10, TMath::Floor(TMath::Log10(fPval[i])) - 1);
92  else
93  fPstp[i] = 0.1;
94  }
95  }
96  fParNam = new TGTextEntry*[fNP];
97  fParFix = new TGCheckButton*[fNP];
98  fParBnd = new TGCheckButton*[fNP];
99  fParVal = new TGNumberEntry*[fNP];
100  fParMin = new TGNumberEntryField*[fNP];
101  fParMax = new TGNumberEntryField*[fNP];
102  fParSld = new TGTripleHSlider*[fNP];
103  fParStp = new TGNumberEntry*[fNP];
104  fParErr = new TGNumberEntryField*[fNP];
105 
106  memset(fParNam, 0, sizeof(TGTextEntry*)*fNP);
107  memset(fParFix, 0, sizeof(TGCheckButton*)*fNP);
108  memset(fParBnd, 0, sizeof(TGCheckButton*)*fNP);
109  memset(fParVal, 0, sizeof(TGNumberEntry*)*fNP);
110  memset(fParMin, 0, sizeof(TGNumberEntryField*)*fNP);
111  memset(fParMax, 0, sizeof(TGNumberEntryField*)*fNP);
112  memset(fParSld, 0, sizeof(TGTripleHSlider*)*fNP);
113  memset(fParStp, 0, sizeof(TGNumberEntry*)*fNP);
114  memset(fParErr, 0, sizeof(TGNumberEntryField*)*fNP);
115 
116  TGCompositeFrame *f1 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
117  AddFrame(f1, new TGLayoutHints(kLHintsTop, 1, 1, 1, 1));
118 
119  // column 'Name'
120  fContNam = new TGCompositeFrame(f1, 80, 20, kVerticalFrame | kFixedWidth);
121  fContNam->AddFrame(new TGLabel(fContNam,"Name"),
122  new TGLayoutHints(kLHintsTop, 5, 0, 0, 0));
123  for (Int_t i = 0; i < fNP; i++ ) {
124  fParNam[i] = new TGTextEntry(fContNam, new TGTextBuffer(80), kNAME+i);
125  fParNam[i]->SetText(Form("%s", fFunc->GetParName(i)));
126  fParNam[i]->SetEnabled(kFALSE);
127  fContNam->AddFrame(fParNam[i],
128  new TGLayoutHints(kLHintsExpandX, 2, 2, 7, 5));
129  }
130  f1->AddFrame(fContNam, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
131 
132  // column 'Fix'
133  fContFix = new TGCompositeFrame(f1, 20, 20, kVerticalFrame | kFixedWidth);
134  fContFix->AddFrame(new TGLabel(fContFix,"Fix"),
135  new TGLayoutHints(kLHintsTop, 2, 0, 0, 0));
136  for (Int_t i = 0; i < fNP; i++ ) {
137  fParFix[i] = new TGCheckButton(fContFix, "", kFIX*fNP+i);
138  fParFix[i]->SetToolTipText(Form("Set %s to fixed", fFunc->GetParName(i)));
139  fContFix->AddFrame(fParFix[i], new TGLayoutHints(kLHintsLeft | kLHintsCenterY,
140  5, 5, 10, 7));
141  if ((fPmin[i] == fPmax[i]) && (fPmin[i] || fPmax[i]))
142  fParFix[i]->SetState(kButtonDown);
143  else
144  fParFix[i]->SetState(kButtonUp);
145  fParFix[i]->Connect("Toggled(Bool_t)", "TFitParametersDialog", this, "DoParFix(Bool_t)");
146  }
147  f1->AddFrame(fContFix, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
148 
149  // column 'Bound'
150  fContBnd = new TGCompositeFrame(f1, 40, 20, kVerticalFrame | kFixedWidth);
151  fContBnd->AddFrame(new TGLabel(fContBnd,"Bound"),
152  new TGLayoutHints(kLHintsTop, 2, 0, 0, 0));
153  for (Int_t i = 0; i < fNP; i++ ) {
154  fParBnd[i] = new TGCheckButton(fContBnd, "", kBND*fNP+i);
155  fParBnd[i]->SetToolTipText(Form("Set bound to %s", fFunc->GetParName(i)));
156  fContBnd->AddFrame(fParBnd[i], new TGLayoutHints(kLHintsLeft | kLHintsCenterY,
157  15, 5, 10, 7));
158  fParBnd[i]->Connect("Toggled(Bool_t)", "TFitParametersDialog", this, "DoParBound(Bool_t)");
159  if ( ((fPmin[i] != fPmax[i]) && (fPmin[i] || fPmax[i])) || (fParMin[i] < fParMax[i]) )
160  fParBnd[i]->SetState(kButtonDown, kFALSE);
161  else
162  fParBnd[i]->SetState(kButtonUp, kFALSE);
163  }
164  f1->AddFrame(fContBnd, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
165 
166  // column 'Value'
167  fContVal = new TGCompositeFrame(f1, 100, 20, kVerticalFrame | kFixedWidth);
168  fContVal->AddFrame(new TGLabel(fContVal,"Value"),
169  new TGLayoutHints(kLHintsTop, 5, 0, 0, 0));
170  for (Int_t i = 0; i < fNP; i++ ) {
171  fParVal[i] = new TGNumberEntry(fContVal, 1.2E-12, 15, kVAL*fNP+i,
172  TGNumberFormat::kNESReal);
173  fParVal[i]->SetNumber(fPval[i]);
174  fParVal[i]->SetFormat(TGNumberFormat::kNESReal, TGNumberFormat::kNEAAnyNumber); //tbs
175  fContVal->AddFrame(fParVal[i], new TGLayoutHints(kLHintsExpandX, 2, 2, 7, 5));
176  (fParVal[i]->GetNumberEntry())->SetToolTipText(Form("%s", fFunc->GetParName(i)));
177  (fParVal[i]->GetNumberEntry())->Connect("ReturnPressed()", "TFitParametersDialog",
178  this, "DoParValue()");
179  fParVal[i]->Connect("ValueSet(Long_t)", "TFitParametersDialog", this, "DoParValue()");
180  (fParVal[i]->GetNumberEntry())->Connect("TabPressed()", "TFitParametersDialog", this, "HandleTab()");
181  (fParVal[i]->GetNumberEntry())->Connect("ShiftTabPressed()", "TFitParametersDialog", this, "HandleShiftTab()");
182  fTextEntries.Add(fParVal[i]->GetNumberEntry());
183  }
184  f1->AddFrame(fContVal, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
185 
186  // column 'Min'
187  fContMin = new TGCompositeFrame(f1, 100, 20, kVerticalFrame | kFixedWidth);
188  fContMin->AddFrame(new TGLabel(fContMin,"Min"),
189  new TGLayoutHints(kLHintsTop, 5, 0, 0, 0));
190  for (Int_t i = 0; i < fNP; i++ ) {
191  fParMin[i] = new TGNumberEntryField(fContMin, kMIN*fNP+i, 0.0,
192  TGNumberFormat::kNESReal,
193  TGNumberFormat::kNEAAnyNumber);
194  ((TGTextEntry*)fParMin[i])->SetToolTipText(Form("Lower limit of %s",
195  fFunc->GetParName(i)));
196  fContMin->AddFrame(fParMin[i], new TGLayoutHints(kLHintsExpandX, 2, 2, 7, 5));
197  fParMin[i]->SetNumber(fPmin[i]);
198  fParMin[i]->Connect("ReturnPressed()", "TFitParametersDialog", this,
199  "DoParMinLimit()");
200  fParMin[i]->Connect("TabPressed()", "TFitParametersDialog", this, "HandleTab()");
201  fParMin[i]->Connect("ShiftTabPressed()", "TFitParametersDialog", this, "HandleShiftTab()");
202  fTextEntries.Add(fParMin[i]);
203  }
204  f1->AddFrame(fContMin, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
205 
206  // column 'Set Range'
207  fContSld = new TGCompositeFrame(f1, 120, 20, kVerticalFrame | kFixedWidth);
208  fContSld->AddFrame(new TGLabel(fContSld,"Set Range"),
209  new TGLayoutHints(kLHintsTop, 5, 0, 0, 0));
210  for (Int_t i = 0; i < fNP; i++ ) {
211  fParSld[i] = new TGTripleHSlider(fContSld, 100, kDoubleScaleBoth, kSLD*fNP+i,
212  kHorizontalFrame, GetDefaultFrameBackground(),
213  kFALSE, kFALSE, kFALSE, kFALSE);
214  fContSld->AddFrame(fParSld[i], new TGLayoutHints(kLHintsExpandX, 2, 2, 5, 5));
215  fParSld[i]->SetConstrained(kTRUE);
216  }
217  f1->AddFrame(fContSld, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
218 
219  // column 'Max'
220  fContMax = new TGCompositeFrame(f1, 100, 20, kVerticalFrame | kFixedWidth);
221  fContMax->AddFrame(new TGLabel(fContMax,"Max"),
222  new TGLayoutHints(kLHintsTop, 5, 0, 0, 0));
223  for (Int_t i = 0; i < fNP; i++ ) {
224  fParMax[i] = new TGNumberEntryField(fContMax, kMAX*fNP+i, 0.0,
225  TGNumberFormat::kNESReal,
226  TGNumberFormat::kNEAAnyNumber);
227  ((TGTextEntry*)fParMax[i])->SetToolTipText(Form("Upper limit of %s",
228  fFunc->GetParName(i)));
229  fContMax->AddFrame(fParMax[i], new TGLayoutHints(kLHintsExpandX, 2, 2, 7, 5));
230  fParMax[i]->SetNumber(fPmax[i]);
231  fParMax[i]->Connect("ReturnPressed()", "TFitParametersDialog", this, "DoParMaxLimit()");
232  fParMax[i]->Connect("TabPressed()", "TFitParametersDialog", this, "HandleTab()");
233  fParMax[i]->Connect("ShiftTabPressed()", "TFitParametersDialog", this, "HandleShiftTab()");
234  fTextEntries.Add(fParMax[i]);
235  }
236  f1->AddFrame(fContMax, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
237 
238  // column 'Step'
239  fContStp = new TGCompositeFrame(f1, 100, 20, kVerticalFrame | kFixedWidth);
240  fContStp->AddFrame(new TGLabel(fContStp,"Step"),
241  new TGLayoutHints(kLHintsTop, 5, 0, 0, 0));
242  for (Int_t i = 0; i < fNP; i++ ) {
243  fParStp[i] = new TGNumberEntry(fContStp, 1.2E-12, 15, kSTP*fNP+i,
244  TGNumberFormat::kNESReal);
245  fParStp[i]->SetNumber(fPstp[i]);
246  fParStp[i]->SetFormat(TGNumberFormat::kNESReal, TGNumberFormat::kNEAAnyNumber); //tbs
247  fContStp->AddFrame(fParStp[i], new TGLayoutHints(kLHintsExpandX, 2, 2, 7, 5));
248  (fParStp[i]->GetNumberEntry())->SetToolTipText(Form("%s", fFunc->GetParName(i)));
249  (fParStp[i]->GetNumberEntry())->Connect("ReturnPressed()", "TFitParametersDialog",
250  this, "DoParStep()");
251  fParStp[i]->Connect("ValueSet(Long_t)", "TFitParametersDialog", this, "DoParStep()");
252  (fParStp[i]->GetNumberEntry())->Connect("TabPressed()", "TFitParametersDialog", this, "HandleTab()");
253  (fParStp[i]->GetNumberEntry())->Connect("ShiftTabPressed()", "TFitParametersDialog", this, "HandleShiftTab()");
254  fTextEntries.Add(fParStp[i]->GetNumberEntry());
255  }
256  f1->AddFrame(fContStp, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
257 
258  // column 'Error'
259  fContErr = new TGCompositeFrame(f1, 80, 20, kVerticalFrame | kFixedWidth);
260  fContErr->AddFrame(new TGLabel(fContErr,"Errors"),
261  new TGLayoutHints(kLHintsTop, 5, 0, 0, 0));
262  for (Int_t i = 0; i < fNP; i++ ) {
263  fParErr[i] = new TGNumberEntryField(fContErr, kERR*fNP+i, 0.0,
264  TGNumberFormat::kNESReal,
265  TGNumberFormat::kNEAAnyNumber);
266  ((TGTextEntry*)fParErr[i])->SetToolTipText(Form("Error of %s",
267  fFunc->GetParName(i)));
268  fContErr->AddFrame(fParErr[i], new TGLayoutHints(kLHintsExpandX, 2, 2, 7, 5));
269  fParErr[i]->SetEnabled(kFALSE);
270  if (fPerr[i])
271  fParErr[i]->SetNumber(fPerr[i]);
272  else
273  ((TGTextEntry *)fParErr[i])->SetText("-");
274  }
275  f1->AddFrame(fContErr, new TGLayoutHints(kLHintsLeft, 1, 1, 2, 2));
276 
277  TGCompositeFrame *f2 = new TGCompositeFrame(this, 270, 20, kHorizontalFrame);
278  AddFrame(f2, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX));
279 
280  fUpdate = new TGCheckButton(f2, "&Immediate preview", kUPDATE);
281  fUpdate->SetToolTipText("Immediate function redrawing");
282  fUpdate->SetState(kButtonDown);
283  f2->AddFrame(fUpdate, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 5, 5, 5, 5));
284  fUpdate->Connect("Toggled(Bool_t)", "TFitParametersDialog", this, "HandleButtons(Bool_t)");
285 
286  TGCompositeFrame *f3 = new TGCompositeFrame(f2, 270, 20, kHorizontalFrame | kFixedWidth);
287  f2->AddFrame(f3, new TGLayoutHints(kLHintsRight));
288 
289  fReset = new TGTextButton(f3, "&Reset", kRESET);
290  f3->AddFrame(fReset, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX,2,2,5,5));
291  fReset->SetToolTipText("Reset the parameter settings");
292  fReset->SetState(kButtonDisabled);
293  fReset->Connect("Clicked()", "TFitParametersDialog", this, "DoReset()");
294 
295  fApply = new TGTextButton(f3, "&Apply", kAPPLY);
296  f3->AddFrame(fApply, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX,2,2,5,5));
297  fApply->SetState(kButtonDisabled);
298  fApply->Connect("Clicked()", "TFitParametersDialog", this, "DoApply()");
299  fApply->SetToolTipText("Apply parameter settings and redraw the function");
300 
301  fOK = new TGTextButton(f3, "&OK", kOK);
302  f3->AddFrame(fOK, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX,2,2,5,5));
303  fOK->SetToolTipText("Apply parameter settings, redraw function and close this dialog");
304  fOK->Connect("Clicked()", "TFitParametersDialog", this, "DoOK()");
305 
306  fCancel = new TGTextButton(f3, "&Cancel", kCANCEL);
307  f3->AddFrame(fCancel, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX,2,2,5,5));
308  fCancel->SetToolTipText("Close this dialog with no parameter changes");
309  fCancel->Connect("Clicked()", "TFitParametersDialog", this, "DoCancel()");
310  *fRetCode = kFPDNoChange; // default setting
311 
312  MapSubwindows();
313  Resize(GetDefaultSize());
314  MapWindow();
315  CenterOnParent(kFALSE, kBottomLeft);
316  SetWindowName(Form("Set Parameters of %s", fFunc->GetTitle()));
317 
318  for (Int_t i = 0; i < fNP; i++ ) {
319  if (fParFix[i]->GetState() == kButtonDown) {
320  fParVal[i]->SetState(kFALSE);
321  fParMin[i]->SetEnabled(kFALSE);
322  fParMax[i]->SetEnabled(kFALSE);
323  fParSld[i]->UnmapWindow();
324  } else {
325  if (fPmin[i]*fPmax[i] == 0 && fPmin[i] >= fPmax[i]) { //init
326  // round again the values on the percent level
327  Double_t u = TMath::Power(10, TMath::Floor(TMath::Log10(TMath::Abs(fPval[i])) )-2 );
328  Double_t roundVal = int(fPval[i]/ u) * u;
329  // set min at +/- 100 step size
330  fParMin[i]->SetNumber( roundVal - 100* fPstp[i]);
331  fParMax[i]->SetNumber( roundVal + 100* fPstp[i]);
332  // if (!fPval[i]) {
333  // fParMin[i]->SetNumber(-10);
334  // fParMax[i]->SetNumber(10);
335  // } else {
336  // fParMin[i]->SetNumber(-3*TMath::Abs(fPval[i]));
337  // fParMax[i]->SetNumber(3*TMath::Abs(fPval[i]));
338  // }
339  }
340  fParSld[i]->SetRange(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
341  fParSld[i]->SetPosition(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
342  fParSld[i]->SetPointerPosition(fParVal[i]->GetNumber());
343  fParSld[i]->Connect("PointerPositionChanged()", "TFitParametersDialog",
344  this, "DoSlider()");
345  fParSld[i]->Connect("PositionChanged()", "TFitParametersDialog",
346  this, "DoSlider()");
347  }
348  }
349 
350  gClient->WaitFor(this);
351 }
352 
353 ////////////////////////////////////////////////////////////////////////////////
354 /// Destructor.
355 
356 TFitParametersDialog::~TFitParametersDialog()
357 {
358  DisconnectSlots();
359  fTextEntries.Clear();
360  Cleanup();
361  delete [] fPval;
362  delete [] fPmin;
363  delete [] fPmax;
364  delete [] fPerr;
365  delete [] fPstp;
366 
367  delete [] fParNam;
368  delete [] fParFix;
369  delete [] fParBnd;
370  delete [] fParVal;
371  delete [] fParMin;
372  delete [] fParMax;
373  delete [] fParSld;
374  delete [] fParStp;
375  delete [] fParErr;
376 }
377 
378 ////////////////////////////////////////////////////////////////////////////////
379 /// Close parameters' dialog.
380 
381 void TFitParametersDialog::CloseWindow()
382 {
383  if (fHasChanges) {
384  Int_t ret;
385  const char *txt;
386  txt = "Do you want to apply last parameters' setting?";
387  new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
388  "Parameters Have Been Changed", txt, kMBIconExclamation,
389  kMBYes | kMBNo | kMBCancel, &ret);
390  if (ret == kMBYes) {
391  SetParameters();
392  *fRetCode = kFPDChange;
393  }
394  else if (ret == kMBNo)
395  DoReset();
396  else return;
397  }
398 
399  DisconnectSlots();
400  DeleteWindow();
401 }
402 
403 ////////////////////////////////////////////////////////////////////////////////
404 /// Slot related to the Cancel button.
405 
406 void TFitParametersDialog::DoCancel()
407 {
408  if (fHasChanges)
409  DoReset();
410  // for (Int_t i = 0; i < fNP; i++ ) {
411  // if (fParBnd[i]->GetState() == kButtonDown)
412  // *fRetCode = kFPDBounded;
413  // }
414  CloseWindow();
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// Slot related to the Bound check button.
419 
420 void TFitParametersDialog::DoParBound(Bool_t on)
421 {
422  TGButton *bt = (TGButton *) gTQSender;
423  Int_t id = bt->WidgetId();
424  fHasChanges = kTRUE;
425 
426  for (Int_t i = 0; i < fNP; i++ ) {
427  if (id == kBND*fNP+i) {
428  if (on) {
429  if (fParMin[i]->GetNumber() >= fParMax[i]->GetNumber()) {
430  Int_t ret;
431  const char *txt;
432  txt = "'Min' value cannot be bigger or equal to 'Max' - set the limits first!";
433  new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
434  "Parameter Limits", txt, kMBIconExclamation,kMBOk,&ret);
435 
436  fParBnd[i]->SetState(kButtonUp, kFALSE);
437  return;
438  }
439  if ((fParVal[i]->GetNumber() < fParMin[i]->GetNumber()) ||
440  (fParVal[i]->GetNumber() > fParMax[i]->GetNumber())) {
441  Double_t v = (fParMax[i]->GetNumber()+fParMin[i]->GetNumber())/2.;
442  fParVal[i]->SetNumber(v);
443  fFunc->SetParameter(i, v);
444  fClient->NeedRedraw(fParVal[i]);
445  }
446  fParVal[i]->SetLimits(TGNumberFormat::kNELLimitMinMax,
447  fParMin[i]->GetNumber(),
448  fParMax[i]->GetNumber());
449  fClient->NeedRedraw(fParVal[i]);
450  fFunc->SetParLimits(i, fParMin[i]->GetNumber(),
451  fParMax[i]->GetNumber());
452  } else {
453  fParVal[i]->SetLimits(TGNumberFormat::kNELNoLimits);
454  fFunc->ReleaseParameter(i);
455  fFunc->GetParLimits(i, fPmin[i], fPmax[i]);
456  fPval[i] = fFunc->GetParameter(i);
457  if (fPmin[i]*fPmax[i] == 0 && fPmin[i] >= fPmax[i]) { //init
458  if (!fPval[i]) {
459  fParMin[i]->SetNumber(-10);
460  fParMax[i]->SetNumber(10);
461  } else {
462  fParMin[i]->SetNumber(-10*TMath::Abs(fPval[i]));
463  fParMax[i]->SetNumber(10*TMath::Abs(fPval[i]));
464  }
465  }
466  fParSld[i]->SetRange(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
467  fParSld[i]->SetPosition(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
468  fParSld[i]->SetPointerPosition(fPval[i]);
469  }
470  }
471  }
472  if (fUpdate->GetState() == kButtonDown)
473  DrawFunction();
474  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges)
475  fApply->SetState(kButtonUp);
476 }
477 
478 ////////////////////////////////////////////////////////////////////////////////
479 /// Slot related to parameter step setting.
480 
481 void TFitParametersDialog::DoParStep()
482 {
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// Slot related to the Fix check button.
487 
488 void TFitParametersDialog::DoParFix(Bool_t on)
489 {
490  fReset->SetState(kButtonUp);
491 
492  TGButton *bt = (TGButton *) gTQSender;
493  Int_t id = bt->WidgetId();
494  fHasChanges = kTRUE;
495 
496  for (Int_t i = 0; i < fNP; i++ ) {
497  if (id == kFIX*fNP+i) {
498  if (on) {
499  // no bound available
500  fParBnd[i]->Disconnect("Toggled(Bool_t)");
501  fParBnd[i]->SetEnabled(kFALSE);
502  fParBnd[i]->SetToolTipText(Form("DISABLED - %s is fixed", fFunc->GetParName(i)));
503  if (fParVal[i]->GetNumber() != 0) {
504  fParMin[i]->SetNumber(fParVal[i]->GetNumber());
505  fParMin[i]->SetEnabled(kFALSE);
506  fParMax[i]->SetNumber(fParVal[i]->GetNumber());
507  fParMax[i]->SetEnabled(kFALSE);
508  } else {
509  fParMin[i]->SetNumber(1.);
510  fParMin[i]->SetEnabled(kFALSE);
511  fParMax[i]->SetNumber(1.);
512  fParMax[i]->SetEnabled(kFALSE);
513  }
514  fParVal[i]->SetState(kFALSE);
515  fParStp[i]->SetState(kFALSE);
516  fParSld[i]->Disconnect("PointerPositionChanged()");
517  fParSld[i]->Disconnect("PositionChanged()");
518  fParSld[i]->UnmapWindow();
519  fFunc->FixParameter(i, fParVal[i]->GetNumber());
520  } else if (!fParMin[i]->IsEnabled()) {
521  if (fPmin[i] != fPmax[i]) {
522  if (fPmin[i])
523  fParMin[i]->SetNumber(fPmin[i]);
524  else if (fPerr[i])
525  fParMin[i]->SetNumber(fPval[i]-3*fPerr[i]);
526  else if (fPval[i])
527  fParMin[i]->SetNumber(fPval[i]-0.1*fPval[i]);
528  else
529  fParMin[i]->SetNumber(1.0);
530  if (fPmax[i])
531  fParMax[i]->SetNumber(fPmax[i]);
532  else if (fPerr[i])
533  fParMax[i]->SetNumber(fPval[i]+3*fPerr[i]);
534  else if (fPval[i])
535  fParMax[i]->SetNumber(fPval[i]+0.1*fPval[i]);
536  else
537  fParMax[i]->SetNumber(1.0);
538  } else if (fPval[i]) {
539  fParMin[i]->SetNumber(fPval[i]-0.1*fPval[i]);
540  fParMax[i]->SetNumber(fPval[i]+0.1*fPval[i]);
541  } else {
542  fParMin[i]->SetNumber(1.0);
543  fParMax[i]->SetNumber(1.0);
544  }
545  if (fParMax[i]->GetNumber() < fParMin[i]->GetNumber()){
546  Double_t temp;
547  temp = fParMax[i]->GetNumber();
548  fParMax[i]->SetNumber(fParMin[i]->GetNumber());
549  fParMin[i]->SetNumber(temp);
550  }
551  fParBnd[i]->SetEnabled(kTRUE);
552  fParBnd[i]->Connect("Toggled(Bool_t)", "TFitParametersDialog",
553  this, "DoParBound(Bool_t)");
554  fParBnd[i]->SetState(kButtonUp);
555  fParMax[i]->SetEnabled(kTRUE);
556  fParMin[i]->SetEnabled(kTRUE);
557  fParSld[i]->MapWindow();
558  fParVal[i]->SetState(kTRUE);
559  fParStp[i]->SetState(kTRUE);
560  fParSld[i]->SetRange(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
561  fParSld[i]->SetPosition(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
562  fParSld[i]->SetPointerPosition(fPval[i]);
563  fParSld[i]->Connect("PointerPositionChanged()", "TFitParametersDialog",
564  this, "DoSlider()");
565  fParSld[i]->Connect("PositionChanged()", "TFitParametersDialog",
566  this, "DoSlider()");
567  fFunc->SetParLimits(i, fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
568  }
569  }
570  }
571  if (fUpdate->GetState() == kButtonDown)
572  DrawFunction();
573  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges)
574  fApply->SetState(kButtonUp);
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 /// Set the parameter values inside the function
579 
580 void TFitParametersDialog::SetParameters()
581 {
582  fFunc->SetRange(fRangexmin, fRangexmax);
583  for (Int_t i = 0; i < fNP; i++ ) {
584  // first make sure the current value is up to date
585  fParVal[i]->GetNumberEntry()->ReturnPressed();
586  if (fParFix[i]->GetState() == kButtonDown) {
587  fFunc->SetParameter(i, fParVal[i]->GetNumber());
588  fFunc->FixParameter(i, fParVal[i]->GetNumber());
589  *fRetCode = kFPDBounded;
590  } else {
591  if (fParBnd[i]->GetState() == kButtonDown) {
592  fFunc->SetParameter(i, fParVal[i]->GetNumber());
593  fFunc->SetParLimits(i, fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
594  *fRetCode = kFPDBounded;
595  } else {
596  fFunc->ReleaseParameter(i);
597  }
598  }
599  }
600 }
601 
602 ////////////////////////////////////////////////////////////////////////////////
603 /// Slot related to the OK button.
604 
605 void TFitParametersDialog::DoOK()
606 {
607  if (fHasChanges)
608  DrawFunction();
609 
610  SetParameters();
611 
612  // we want here to confirm the parameters settings so
613  // it is like having changed them
614  *fRetCode = kFPDChange;
615 
616 
617  CloseWindow();
618 }
619 
620 ////////////////////////////////////////////////////////////////////////////////
621 /// Slot related to the Preview button.
622 
623 void TFitParametersDialog::DoApply()
624 {
625  DrawFunction();
626  fApply->SetState(kButtonDisabled);
627  if (fReset->GetState() == kButtonDisabled)
628  fReset->SetState(kButtonUp);
629 }
630 
631 ////////////////////////////////////////////////////////////////////////////////
632 /// Slot related to the Reset button.
633 
634 void TFitParametersDialog::DoReset()
635 {
636  fHasChanges = kTRUE;
637  Int_t k = fNP;
638  for (Int_t i = 0; i < fNP; i++) {
639  if (fParVal[i]->GetNumber() == fPval[i])
640  k--;
641  else
642  break;
643  }
644 
645  if (!k) {
646  if (fReset->GetState() == kButtonUp)
647  fReset->SetState(kButtonDisabled);
648  fHasChanges = kFALSE;
649  return;
650  }
651  for (Int_t i = 0; i < fNP; i++) {
652  fFunc->SetParameter(i, fPval[i]);
653  fFunc->SetParLimits(i, fPmin[i], fPmax[i]);
654  fFunc->SetParError(i, fPerr[i]);
655 
656  if (fPmin[i])
657  fParMin[i]->SetNumber(fPmin[i]);
658  else if (fPerr[i])
659  fParMin[i]->SetNumber(fPval[i]-3*fPerr[i]);
660  else if (fPval[i])
661  fParMin[i]->SetNumber(-3*TMath::Abs(fPval[i]));
662  else
663  fParMin[i]->SetNumber(1.0);
664 
665  if (fPmax[i])
666  fParMax[i]->SetNumber(fPmax[i]);
667  else if (fPerr[i])
668  fParMax[i]->SetNumber(fPval[i]+3*fPerr[i]);
669  else if (fPval[i])
670  fParMax[i]->SetNumber(3*TMath::Abs(fPval[i]));
671  else
672  fParMax[i]->SetNumber(1.0);
673  if (fParMax[i]->GetNumber() < fParMin[i]->GetNumber()){
674  Double_t temp;
675  temp = fParMax[i]->GetNumber();
676  fParMax[i]->SetNumber(fParMin[i]->GetNumber());
677  fParMin[i]->SetNumber(temp);
678  }
679  if (fParMin[i]->GetNumber() == fParMax[i]->GetNumber()) {
680  fParVal[i]->SetState(kFALSE);
681  fParMin[i]->SetEnabled(kFALSE);
682  fParMax[i]->SetEnabled(kFALSE);
683  fParStp[i]->SetState(kFALSE);
684  fParSld[i]->Disconnect("PointerPositionChanged()");
685  fParSld[i]->Disconnect("PositionChanged()");
686  fParSld[i]->UnmapWindow();
687  fParBnd[i]->Disconnect("Toggled(Bool_t)");
688  fParBnd[i]->SetEnabled(kFALSE);
689  fFunc->FixParameter(i, fParVal[i]->GetNumber());
690  fParFix[i]->SetState(kButtonDown);
691  } else {
692  fParFix[i]->SetState(kButtonUp);
693  if (!fParMax[i]->IsEnabled()) {
694  fParMax[i]->SetEnabled(kTRUE);
695  fParMin[i]->SetEnabled(kTRUE);
696  fParVal[i]->SetState(kTRUE);
697  fParStp[i]->SetState(kTRUE);
698  fParSld[i]->SetRange(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
699  fParSld[i]->SetPosition(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
700  fParSld[i]->SetPointerPosition(fPval[i]);
701  fParSld[i]->MapWindow();
702  fParSld[i]->Connect("PointerPositionChanged()", "TFitParametersDialog",
703  this, "DoSlider()");
704  fParSld[i]->Connect("PositionChanged()", "TFitParametersDialog",
705  this, "DoSlider()");
706  fParBnd[i]->SetEnabled(kTRUE);
707  fParBnd[i]->Connect("Toggled(Bool_t)", "TFitParametersDialog",
708  this, "DoParBound(Bool_t)");
709  }
710  }
711  fParVal[i]->SetNumber(fPval[i]);
712 
713  fParSld[i]->SetRange(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
714  fParSld[i]->SetPosition(fParMin[i]->GetNumber(), fParMax[i]->GetNumber());
715  fParSld[i]->SetPointerPosition(fPval[i]);
716  }
717 
718  if (fUpdate->GetState() == kButtonDown)
719  DrawFunction();
720  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges)
721  fApply->SetState(kButtonUp);
722  fHasChanges = kFALSE;
723  *fRetCode = kFPDNoChange;
724  fReset->SetState(kButtonDisabled);
725 }
726 
727 ////////////////////////////////////////////////////////////////////////////////
728 /// Slot related to the parameters' value settings.
729 
730 void TFitParametersDialog::DoSlider()
731 {
732  TGTripleHSlider *sl = (TGTripleHSlider *) gTQSender;
733  Int_t id = sl->WidgetId();
734 
735  fHasChanges = kTRUE;
736  for (Int_t i = 0; i < fNP; i++ ) {
737  if (id == kSLD*fNP+i) {
738  fFunc->SetParameter(i,fParSld[i]->GetPointerPosition());
739  fFunc->SetParLimits(i,fParSld[i]->GetMinPosition(),
740  fParSld[i]->GetMaxPosition());
741  fParMin[i]->SetNumber(fParSld[i]->GetMinPosition());
742  fParMax[i]->SetNumber(fParSld[i]->GetMaxPosition());
743  fParVal[i]->SetNumber(fParSld[i]->GetPointerPosition());
744  }
745  }
746  if (fUpdate->GetState() == kButtonDown)
747  DrawFunction();
748  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges)
749  fApply->SetState(kButtonUp);
750  if (fReset->GetState() == kButtonDisabled)
751  fReset->SetState(kButtonUp);
752 }
753 
754 ////////////////////////////////////////////////////////////////////////////////
755 /// Slot related to the parameter value settings.
756 
757 void TFitParametersDialog::DoParValue()
758 {
759  TGNumberEntry *ne = (TGNumberEntry *) gTQSender;
760  Int_t id = ne->WidgetId();
761 
762  for (Int_t i = 0; i < fNP; i++ ) {
763  if (id == kVAL*fNP+i) {
764  if (fParVal[i]->GetNumber() < fParMin[i]->GetNumber()) {
765  Double_t extraIncrement = (fParMax[i]->GetNumber() - fParMin[i]->GetNumber()) / 4;
766  fParMin[i]->SetNumber(fParVal[i]->GetNumber() - extraIncrement );
767  fClient->NeedRedraw(fParMin[i]);
768  fParSld[i]->SetRange(fParMin[i]->GetNumber(),
769  fParMax[i]->GetNumber());
770  fParSld[i]->SetPosition(fParMin[i]->GetNumber(),
771  fParMax[i]->GetNumber());
772  }
773  if (fParVal[i]->GetNumber() > fParMax[i]->GetNumber()) {
774  Double_t extraIncrement = (fParMax[i]->GetNumber() - fParMin[i]->GetNumber()) / 4;
775  fParMax[i]->SetNumber(fParVal[i]->GetNumber() + extraIncrement );
776  fClient->NeedRedraw(fParMax[i]);
777  fParSld[i]->SetRange(fParMin[i]->GetNumber(),
778  fParMax[i]->GetNumber());
779  fParSld[i]->SetPosition(fParMin[i]->GetNumber(),
780  fParMax[i]->GetNumber());
781  }
782  fParSld[i]->SetPointerPosition(fParVal[i]->GetNumber());
783  fClient->NeedRedraw(fParSld[i]);
784  fFunc->SetParameter(i,fParSld[i]->GetPointerPosition());
785  if (fParBnd[i]->GetState() == kButtonDown)
786  fFunc->SetParLimits(i,fParSld[i]->GetMinPosition(),
787  fParSld[i]->GetMaxPosition());
788  else
789  fFunc->ReleaseParameter(i);
790  }
791  }
792  fHasChanges = kTRUE;
793  if (fUpdate->GetState() == kButtonDown)
794  DrawFunction();
795  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges)
796  fApply->SetState(kButtonUp);
797  if (fReset->GetState() == kButtonDisabled)
798  fReset->SetState(kButtonUp);
799 }
800 
801 ////////////////////////////////////////////////////////////////////////////////
802 /// Slot related to the minumum parameter limit settings.
803 
804 void TFitParametersDialog::DoParMinLimit()
805 {
806  TGNumberEntryField *ne = (TGNumberEntryField *) gTQSender;
807  Int_t id = ne->WidgetId();
808 
809  for (Int_t i = 0; i < fNP; i++ ) {
810  if (id == kMIN*fNP+i) {
811  if ((fParMin[i]->GetNumber() >= fParMax[i]->GetNumber()) &&
812  (fParBnd[i]->GetState() == kButtonDown)) {
813  Int_t ret;
814  const char *txt;
815  txt = "'Min' cannot be bigger then 'Max' if this parameter is bounded.";
816  new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
817  "Parameter Limits", txt, kMBIconExclamation, kMBOk, &ret);
818  fParMin[i]->SetNumber(fParVal[i]->GetNumber()-fParStp[i]->GetNumber());
819  return;
820  }
821  if (fParBnd[i]->GetState() == kButtonDown) {
822  Double_t val = (fParMax[i]->GetNumber()+fParMin[i]->GetNumber())/2.;
823  fParVal[i]->SetNumber(val);
824  fParVal[i]->SetLimitValues(fParMin[i]->GetNumber(),
825  fParMax[i]->GetNumber());
826  }
827  fParSld[i]->SetRange(fParMin[i]->GetNumber(),
828  fParMax[i]->GetNumber());
829  fParSld[i]->SetPosition(fParMin[i]->GetNumber(),
830  fParMax[i]->GetNumber());
831  fParSld[i]->SetPointerPosition(fParVal[i]->GetNumber());
832  fClient->NeedRedraw(fParSld[i]);
833  }
834  }
835  fHasChanges = kTRUE;
836  if (fUpdate->GetState() == kButtonDown)
837  DrawFunction();
838  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges)
839  fApply->SetState(kButtonUp);
840  if (fReset->GetState() == kButtonDisabled)
841  fReset->SetState(kButtonUp);
842 }
843 
844 ////////////////////////////////////////////////////////////////////////////////
845 /// Slot related to the maximum parameter limit settings.
846 
847 void TFitParametersDialog::DoParMaxLimit()
848 {
849  TGNumberEntryField *ne = (TGNumberEntryField *) gTQSender;
850  Int_t id = ne->WidgetId();
851 
852  for (Int_t i = 0; i < fNP; i++ ) {
853  if (id == kMAX*fNP+i) {
854  if ((fParMin[i]->GetNumber() >= fParMax[i]->GetNumber()) &&
855  (fParBnd[i]->GetState() == kButtonDown)) {
856  Int_t ret;
857  const char *txt;
858  txt = "'Min' cannot be bigger then 'Max' if this parameter is bounded.";
859  new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
860  "Parameter Limits", txt, kMBIconExclamation, kMBOk, &ret);
861  fParMax[i]->SetNumber(fParVal[i]->GetNumber()+fParStp[i]->GetNumber());
862  return;
863  }
864  if (fParBnd[i]->GetState() == kButtonDown) {
865  Double_t val = (fParMax[i]->GetNumber()+(fParMin[i]->GetNumber()))/2.;
866  fParVal[i]->SetNumber(val);
867  fParVal[i]->SetLimitValues(fParMin[i]->GetNumber(),
868  fParMax[i]->GetNumber());
869  }
870  fParSld[i]->SetRange(fParMin[i]->GetNumber(),
871  fParMax[i]->GetNumber());
872  fParSld[i]->SetPosition(fParMin[i]->GetNumber(),
873  fParMax[i]->GetNumber());
874  fParSld[i]->SetPointerPosition(fParVal[i]->GetNumber());
875  fClient->NeedRedraw(fParSld[i]);
876  }
877  }
878  fHasChanges = kTRUE;
879  if (fUpdate->GetState() == kButtonDown)
880  DrawFunction();
881  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges)
882  fApply->SetState(kButtonUp);
883  if (fReset->GetState() == kButtonDisabled)
884  fReset->SetState(kButtonUp);
885 }
886 
887 ////////////////////////////////////////////////////////////////////////////////
888 /// Redraw function graphics.
889 
890 void TFitParametersDialog::DrawFunction()
891 {
892  if ( !fFpad ) return;
893  TVirtualPad *save = 0;
894  save = gPad;
895  gPad = fFpad;
896  gPad->cd();
897 
898  Style_t st = fFunc->GetLineStyle();
899  fFunc->SetLineStyle(2);
900 
901  TString opt = fFunc->GetDrawOption();
902  opt.ToUpper();
903  if (!opt.Contains("SAME"))
904  opt += "SAME";
905  //fFunc->SetRange(fRXmin, fRXmax);
906  fFunc->Draw(opt);
907  gPad->Modified();
908  gPad->Update();
909  fHasChanges = kFALSE;
910 
911  fFunc->SetLineStyle(st);
912  if (save) gPad = save;
913  *fRetCode = kFPDBounded;
914 }
915 
916 ////////////////////////////////////////////////////////////////////////////////
917 /// Handle the button dependent states in this dialog.
918 
919 void TFitParametersDialog::HandleButtons(Bool_t update)
920 {
921  if (update && fHasChanges)
922  DrawFunction();
923  else if ((fApply->GetState() == kButtonDisabled) && fHasChanges) {
924  fApply->SetState(kButtonUp);
925  }
926 }
927 
928 ////////////////////////////////////////////////////////////////////////////////
929 /// Disconnect signals from slot methods.
930 
931 void TFitParametersDialog::DisconnectSlots()
932 {
933  for (Int_t i = 0; i < fNP; i++ ) {
934  fParFix[i]->Disconnect("Toggled(Bool_t)");
935  fParBnd[i]->Disconnect("Toggled(Bool_t)");
936  fParVal[i]->Disconnect("ValueSet(Long_t)");
937  fParMin[i]->Disconnect("ReturnPressed()");
938  fParMax[i]->Disconnect("ReturnPressed()");
939  fParSld[i]->Disconnect("PointerPositionChanged()");
940  fParSld[i]->Disconnect("PositionChanged()");
941  fParStp[i]->Disconnect("ValueSet(Long_t)");
942  fParVal[i]->Disconnect("TabPressed(Long_t)");
943  fParVal[i]->Disconnect("ShiftTabPressed(Long_t)");
944  fParMin[i]->Disconnect("TabPressed(Long_t)");
945  fParMin[i]->Disconnect("ShiftTabPressed(Long_t)");
946  fParMax[i]->Disconnect("TabPressed(Long_t)");
947  fParMax[i]->Disconnect("ShiftTabPressed(Long_t)");
948  fParStp[i]->Disconnect("TabPressed(Long_t)");
949  fParStp[i]->Disconnect("ShiftTabPressed(Long_t)");
950  }
951  fUpdate->Disconnect("Toggled(Bool_t)");
952  fReset->Disconnect("Clicked()");
953  fApply->Disconnect("Clicked()");
954  fOK->Disconnect("Clicked()");
955  fCancel->Disconnect("Clicked()");
956 }
957 
958 ////////////////////////////////////////////////////////////////////////////////
959 /// Handle Shift+Tab key event (set focus to the previous number entry field)
960 
961 void TFitParametersDialog::HandleShiftTab()
962 {
963  TGNumberEntryField *next, *sender = (TGNumberEntryField *)gTQSender;
964  next = (TGNumberEntryField *)fTextEntries.Before((TObject *)sender);
965  if (next == 0)
966  next = (TGNumberEntryField *)fTextEntries.Last();
967  if (next) {
968  next->SetFocus();
969  next->Home();
970  }
971 }
972 
973 ////////////////////////////////////////////////////////////////////////////////
974 /// Handle Tab key event (set focus to the next number entry field)
975 
976 void TFitParametersDialog::HandleTab()
977 {
978  TGNumberEntryField *next, *sender = (TGNumberEntryField *)gTQSender;
979  next = (TGNumberEntryField *)fTextEntries.After((TObject *)sender);
980  if (next == 0)
981  next = (TGNumberEntryField *)fTextEntries.First();
982  if (next) {
983  next->SetFocus();
984  next->Home();
985  }
986 }
987 
988 
989