source: trunk/Mars/mjoptim/MJOptimize.cc@ 11945

Last change on this file since 11945 was 9017, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 22.2 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 9/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MJOptimize
28//
29// Class for otimizing the parameters of the supercuts
30//
31// Minimization Control
32// ====================
33//
34// To choose the minimization algorithm use:
35// void SetOptimizer(Optimizer_t o);
36//
37// Allowed options are:
38// enum Optimizer_t
39// {
40// kMigrad, // Minimize by the method of Migrad
41// kSimplex, // Minimize by the method of Simplex
42// kMinimize, // Migrad + Simplex (if Migrad fails)
43// kMinos, // Minos error determination
44// kImprove, // Local minimum search
45// kSeek, // Minimize by the method of Monte Carlo
46// kNone // Skip optimization
47// };
48//
49// For more details on the methods see TMinuit.
50//
51//
52// You can change the behaviour of the minimization using
53//
54// void SetNumMaxCalls(UInt_t num=0);
55// void SetTolerance(Float_t tol=0);
56//
57// While NumMaxCalls is the first, Tolerance the second arguement.
58// For more details start root and type
59//
60// gMinuit->mnhelp("command")
61//
62// while command can be
63// * MIGRAD
64// * SIMPLEX
65// * MINIMIZE
66// * MINOS
67// * IMPROVE
68// * SEEK
69//
70// The default (num==0 and tol==0) should always give you the
71// corresponding defaults used in Minuit.
72//
73//
74// FIXME: Implement changing cut in hadronness...
75// FIXME: Show MHSignificance on MStatusDisplay during filling...
76// FIXME: Choose step-size percentage as static data membewr
77// FIXME: Choose minimization method
78//
79/////////////////////////////////////////////////////////////////////////////
80#include "MJOptimize.h"
81
82#include <TMinuit.h>
83#include <TVirtualFitter.h>
84
85#include <TStopwatch.h>
86
87#include <TCanvas.h>
88
89#include <TGraph.h>
90#include <TMultiGraph.h>
91
92#include "MHMatrix.h"
93
94// environment
95#include "MLog.h"
96#include "MLogManip.h"
97
98#include "MDirIter.h"
99#include "MStatusDisplay.h"
100
101// eventloop
102#include "MParList.h"
103#include "MTaskList.h"
104#include "MEvtLoop.h"
105
106// parameters
107#include "MParameters.h"
108
109// tasks
110#include "MReadTree.h"
111#include "MMatrixLoop.h"
112#include "MFillH.h"
113#include "MParameterCalc.h"
114#include "MContinue.h"
115
116// filters
117#include "MFDataPhrase.h"
118#include "MFilterList.h"
119
120using namespace std;
121
122//------------------------------------------------------------------------
123//
124// fcn calculates the function to be minimized (using TMinuit::Migrad)
125//
126void MJOptimize::fcn(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
127{
128 MJOptimize *optim = (MJOptimize*)gMinuit->GetObjectFit();
129
130 // WORKAROUND --- FOR WHAT?
131 if (gMinuit->fEpsi<1e-2)
132 {
133 *optim->fLog << warn << "WARNING - For unknown reasons: fEspi<1e-100... resetting to 0.01." << endl;
134 gMinuit->fEpsi = 0.01;
135 }
136
137 TMinuit *minuit = gMinuit;
138 f = optim->Fcn(TArrayD(TMath::Min(gMinuit->fMaxpar, optim->fParameters.GetSize()), par), minuit);
139 gMinuit = minuit;
140
141}
142
143Double_t MJOptimize::Fcn(const TArrayD &par, TMinuit *minuit)
144{
145 if (fEvtLoop->GetDisplay()!=fDisplay)
146 return 0;
147 /*
148 switch(iflag)
149 {
150 case 1: // first call
151 case 2: // calc derivative
152 break;
153 case 3:
154 // last call
155 MStatusDisplay *d = new MStatusDisplay;
156 fEvtLoop->SetDisplay(d);
157 break;
158 }
159 */
160 MParList *plist = fEvtLoop->GetParList();
161
162 MParameterD *eval = (MParameterD*)plist->FindObject(fNameMinimizationValue, "MParameterD");
163 MParContainer *pars = (MParContainer*)plist->FindObject("MParameters", "MParContainer");
164
165 MRead *read = (MRead*)plist->FindObject("MTaskList")->FindObject("MRead");
166 if (read)
167 read->Rewind();
168
169 if (fDebug>=0)
170 {
171 *fLog << inf << "New Set: ";
172 for (Int_t i=0; i<fParameters.GetSize(); i++)
173 *fLog << par[i] << " ";
174 *fLog << endl;
175 }
176
177 pars->SetVariables(par);
178 eval->SetVal(0);
179
180 const Bool_t isnull = gLog.IsNullOutput();
181 if (fDebug<3)
182 gLog.SetNullOutput(kTRUE);
183
184 TStopwatch clock;
185 clock.Start();
186 fEvtLoop->Eventloop(fNumEvents, MEvtLoop::kNoStatistics);
187 clock.Stop();
188
189 if (fDebug<3)
190 gLog.SetNullOutput(isnull);
191
192 const Double_t f = eval->GetVal();
193
194 if (fDebug>=0)
195 *fLog << inf << "Result F=" << f << endl;
196
197 if (fDebug>=1 && minuit)
198 {
199 Double_t fmin, fedm, errdef;
200 Int_t n1, n2, istat;
201 minuit->mnstat(fmin, fedm, errdef, n1, n2, istat);
202 *fLog << inf << underline << "Minimization Status so far:" << endl;
203 *fLog << " Calls: " << minuit->fNfcn << " (max=" << gMinuit->fMaxIterations << ")" << endl;
204 *fLog << " Parameters: fixed=" << gMinuit->fNpfix << ", free=" << gMinuit->fNpar << endl;
205 *fLog << " Func min: " << fmin << " (Epsi=" << gMinuit->fEpsi << ", Apsi=" << gMinuit->fApsi << ")" << endl;
206 *fLog << " Found edm: " << fedm << endl;
207 *fLog << " ErrDef: " << errdef << endl;
208 *fLog << " Status: ";
209
210 switch (istat)
211 {
212 case 0: *fLog << "n/a" << endl; break;
213 case 1: *fLog << "approximation only, not accurate" << endl; break;
214 case 2: *fLog << "full matrix, but forced positive-definite" << endl; break;
215 case 3: *fLog << "full accurate covariance matrix" << endl; break;
216 default: *fLog << "undefined" << endl; break;
217 }
218 }
219
220 if (fDebug>=1)
221 {
222 clock.Print();
223 fEvtLoop->GetTaskList()->PrintStatistics();
224 }
225
226 return f;
227}
228
229MJOptimize::MJOptimize() : /*fDebug(-1),*/ fNumEvents(0), fType(kSimplex), fNumMaxCalls(0), fTolerance(0), fTestTrain(0), fNameMinimizationValue("MinimizationValue")
230{
231 fRules.SetOwner();
232 fFilter.SetOwner();
233
234 fNamesOn.SetOwner();
235 fNamesOff.SetOwner();
236}
237
238//------------------------------------------------------------------------
239//
240// Add sequences from list to reader
241//
242Bool_t MJOptimize::AddSequences(MRead &read, TList &list) const
243{
244 MDirIter files;
245
246 TIter Next(&list);
247 MSequence *seq=0;
248 while ((seq=(MSequence*)Next()))
249 {
250 if (!seq->IsValid())
251 return kFALSE;
252 if (seq->GetRuns(files, MSequence::kRootDat)<=0)
253 return kFALSE;
254 }
255
256 return read.AddFiles(files)>0;
257}
258
259//------------------------------------------------------------------------
260//
261// Add on-sequences:
262// - fname: sequence file name (with path)
263// - dir: directory were image files are stored
264//
265void MJOptimize::AddSequenceOn(const char *fname, const char *dir)
266{
267 fNamesOn.Add(new MSequence(fname, dir));
268}
269
270//------------------------------------------------------------------------
271//
272// Add off-sequences:
273// - fname: sequence file name (with path)
274// - dir: directory were image files are stored
275//
276void MJOptimize::AddSequenceOff(const char *fname, const char *dir)
277{
278 fNamesOff.Add(new MSequence(fname, dir));
279}
280
281//------------------------------------------------------------------------
282//
283// Empty list of on- and off-sequences
284//
285void MJOptimize::ResetSequences()
286{
287 fNamesOn.Delete();
288 fNamesOff.Delete();
289}
290
291
292//------------------------------------------------------------------------
293//
294// Add a filter which can be applied in the optimization (for deatils
295// see correspodning Run function) You can use the indices you got by
296// AddParameter, eg
297//
298// AddFilter("M[0] < 3.2");
299//
300// if used in optimization you can do
301//
302// AddFilter("M[0] < [0]");
303//
304// for more details, see SetParameter and FixParameter
305//
306void MJOptimize::AddFilter(const char *rule)
307{
308 fFilter.Add(new MFDataPhrase(rule));
309}
310
311//------------------------------------------------------------------------
312//
313// Set the fParameters Array accoring to par.
314//
315void MJOptimize::SetParameters(const TArrayD &par)
316{
317 fParameters = par;
318}
319
320//------------------------------------------------------------------------
321//
322// Set the number of events processed by the eventloop. (Be carfull,
323// if you are doing on-off analysis and you only process the first
324// 1000 events which are on-events only the optimization may not work)
325//
326void MJOptimize::SetNumEvents(UInt_t n)
327{
328 fNumEvents=n;
329}
330
331//------------------------------------------------------------------------
332//
333// Set a debug level, which tells the optimization how much information
334// is displayed about and in the running eventloop.
335//
336void MJOptimize::SetDebug(UInt_t n)
337{
338 fDebug=n;
339}
340
341//------------------------------------------------------------------------
342//
343// Set a optimization algorithm to be used. For more information see
344// TMinuit.
345//
346// Available Algorithms are:
347// kMigrad, // Minimize by the method of Migrad
348// kSimplex, // Minimize by the method of Simplex
349// kSeek // Minimize by the method of Monte Carlo
350//
351void MJOptimize::SetOptimizer(Optimizer_t o)
352{
353 fType = o;
354}
355
356//------------------------------------------------------------------------
357//
358// If a status didplay is set, search for tab "Optimizer".
359// If not found, create it.
360// In the tab search for TMultiGraph "Parameters".
361// If not found create it.
362// If empty create TGraphs.
363// Check number of graphs vs. number of parameters.
364// return TList with graphs.
365//
366TList *MJOptimize::GetPlots() const
367{
368 if (!fDisplay)
369 return NULL;
370
371 TCanvas *c=fDisplay->GetCanvas("Optimizer");
372 if (!c)
373 c = &fDisplay->AddTab("Optimizer");
374
375 TMultiGraph *mg = dynamic_cast<TMultiGraph*>(c->FindObject("Parameters"));
376 if (!mg)
377 mg = new TMultiGraph("Parameters", "Parameters of optimization");
378
379 TList *l = mg->GetListOfGraphs();
380 if (!l)
381 {
382 const Int_t n = fParameters.GetSize();
383 for (int i=0; i<n+1; i++)
384 {
385 TGraph *g = new TGraph;
386 if (i==n)
387 g->SetLineColor(kBlue);
388 mg->Add(g, "");
389 AddPoint(mg->GetListOfGraphs(), i, i==n?1:fParameters[i]);
390 }
391 mg->SetBit(kCanDelete);
392 mg->Draw("al*");
393
394 l = mg->GetListOfGraphs();
395 }
396
397 return l->GetSize() == fParameters.GetSize()+1 ? l : NULL;
398}
399
400//------------------------------------------------------------------------
401//
402// Add a point with y=val as last point in idx-th Tgraph of list l.
403//
404void MJOptimize::AddPoint(TList *l, Int_t idx, Float_t val) const
405{
406 if (!l)
407 return;
408
409 TGraph *gr = (TGraph*)l->At(idx);
410 gr->SetPoint(gr->GetN(), gr->GetN(), val);
411}
412
413Int_t MJOptimize::Minuit(TMinuit &minuit, const char *cmd) const
414{
415 Int_t er;
416 Double_t tmp[2] = { fNumMaxCalls, fTolerance };
417 minuit.mnexcm(cmd, tmp, 2, er);
418
419 switch (er)
420 {
421 case 0:
422 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm excuted normally." << endl;
423 break;
424 case 1:
425 *fLog << warn << GetDescriptor() << " TMinuit::mnexcm command is blank... ignored." << endl;
426 break;
427 case 2:
428 *fLog << warn << GetDescriptor() << " TMinuit::mnexcm command-line syntax error... ignored." << endl;
429 break;
430 case 3:
431 *fLog << warn << GetDescriptor() << " TMinuit::mnexcm unknown command... ignored." << endl;
432 break;
433 case 4:
434 *fLog << warn << GetDescriptor() << " TMinuit::mnexcm - Abnormal termination (eg Migrad not converged)" << endl;
435 break;
436 /*
437 case 5:
438 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - Parameters requested." << endl;
439 break;
440 case 6:
441 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - SET INPUT returned." << endl;
442 break;
443 case 7:
444 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - SET TITLE returned." << endl;
445 break;
446 case 8:
447 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - SET COVAR returned." << endl;
448 break;
449 case 9:
450 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - reserved." << endl;
451 break;
452 case 10:
453 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - END returned." << endl;
454 break;
455 case 11:
456 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - EXIT or STOP returned." << endl;
457 break;
458 case 12:
459 *fLog << inf << GetDescriptor() << " TMinuit::mnexcm - RETURN returned." << endl;
460 break;*/
461 }
462
463 return er;
464}
465
466Bool_t MJOptimize::Optimize(MEvtLoop &evtloop)
467{
468 if (fParameters.GetSize()==0)
469 {
470 *fLog << err << GetDescriptor() << "::Optimize: ERROR - Sorry, no parameters defined." << endl;
471 return kFALSE;
472 }
473
474 if (fType==kNone)
475 return kTRUE;
476
477 gMinuit = new TMinuit(fParameters.GetSize());
478
479 gMinuit->SetFCN(fcn);
480 gMinuit->SetObjectFit(this);
481 gMinuit->SetPrintLevel(-1); // Don't print when DefineParameter
482
483 //
484 // Set starting values and step sizes for parameters
485 //
486 for (Int_t i=0; i<fParameters.GetSize(); i++)
487 {
488 TString name = "par[";
489 name += i;
490 name += "]";
491 Double_t vinit = fParameters[i];
492 Double_t step = fStep[i];
493
494 Double_t limlo = fLimLo[i];
495 Double_t limup = fLimUp[i];
496
497 Bool_t rc = gMinuit->DefineParameter(i, name, vinit, step, limlo, limup);
498 if (rc)
499 {
500 *fLog << err << dbginf << "Error in defining parameter #" << i << endl;
501 return kFALSE;
502 }
503
504 if (step==0)
505 gMinuit->FixParameter(i);
506 }
507
508 gMinuit->SetPrintLevel(1); // Switch on pritning again
509 gMinuit->mnprin(1,0); // Print all parameters
510
511 fEvtLoop = &evtloop;
512
513 TList *g=GetPlots();
514
515 // Now ready for minimization step:
516 TStopwatch clock;
517 clock.Start();
518 switch (fType)
519 {
520 case kSimplex:
521 Simplex(*gMinuit);
522 break;
523 case kMigrad:
524 Migrad(*gMinuit);
525 break;
526 case kMinimize:
527 Minimize(*gMinuit);
528 break;
529 case kMinos:
530 Minos(*gMinuit);
531 break;
532 case kImprove:
533 Improve(*gMinuit);
534 break;
535 case kSeek:
536 Seek(*gMinuit);
537 break;
538 case kNone: // Should never happen
539 return kFALSE;
540 }
541 clock.Stop();
542 clock.Print();
543
544 if (evtloop.GetDisplay()!=fDisplay)
545 {
546 *fLog << inf << "Optimization aborted by user." << endl;
547 fDisplay = 0;
548 return kFALSE;
549 }
550
551 *fLog << inf << "Resulting Chisq: " << gMinuit->fAmin << endl;
552
553 //
554 // Update values of fA, fB:
555 //
556 for (Int_t i=0; i<fParameters.GetSize(); i++)
557 {
558 Double_t x1, x2;
559 gMinuit->GetParameter(i,x1,x2);
560 fParameters[i] = x1;
561 cout << i << ": " << fParameters[i] << endl;
562
563 AddPoint(g, i, x1);
564 }
565 AddPoint(g, fParameters.GetSize(), gMinuit->fAmin);
566
567 delete gMinuit;
568
569 return kTRUE;
570}
571
572//------------------------------------------------------------------------
573//
574// Optimize allows to use the optimizing by an eventloop based on
575// some requirements.
576//
577// 1) The tasklist to be executed must have the name MTaskList and
578// be an entry in the parameterlist.
579//
580// 2) The reading task (MReadMarsFile, MMatrixLoop) must have the name
581// "MRead". If it derives from MRead Rewind() must be implemented,
582// otherwise it must start reading from scratch each time its
583// PreProcess is called.
584//
585// 3) The parameters to be optimized must be accessed through (currently)
586// a single parameter container (MParContainer) called MParameters.
587// The parameters are set through SetVariables.
588//
589// 4) The result of a single function call for minimization (eg. chisquare)
590// must be available after the eventloop in a container of type
591// MParameterD with the name "MinimizationResult".
592//
593// 5) The parameters to start with must have been set using
594// MJOptimize::SetParameter or MJOptimize::SetParameters and
595// MJOptimize::FixParameter
596//
597// The behaviour of the optimization can be changed using:
598// void SetNumEvents(UInt_t n);
599// void SetDebug(UInt_t n);
600// void SetOptimizer(Optimizer_t o);
601//
602// After optimization the resulting parameters are set and another eventloop
603// with a MStatusDisplay is set is called. The resulting parameters can be
604// accessed using: GetParameters()
605//
606// To be fixed:
607// - MStatusDisplay should show status while optimization is running
608// - write result into MStatusDisplay
609// - save result
610//
611Bool_t MJOptimize::Optimize(MParList &parlist)
612{
613 // Checks to make sure, that fcn doesn't crash
614 if (!parlist.FindCreateObj("MParameterD", fNameMinimizationValue))
615 return kFALSE;
616
617 if (!parlist.FindObject("MParameters", "MParContainer"))
618 {
619 *fLog << err << "MParameters [MParContainer] not found... abort." << endl;
620 return kFALSE;
621 }
622
623 MTaskList *tlist = (MTaskList*)parlist.FindObject("MTaskList");
624 if (!tlist)
625 {
626 *fLog << err << "MTaskList not found... abort." << endl;
627 return kFALSE;
628 }
629 tlist->SetAccelerator(MTask::kAccDontReset|MTask::kAccDontTime);
630
631 MMatrixLoop *loop = dynamic_cast<MMatrixLoop*>(parlist.FindTask("MRead"));
632
633 TString txt("Starting ");
634 switch (fType)
635 {
636 case kMigrad: txt += "Migrad"; break;
637 case kMinimize: txt += "Minimize"; break;
638 case kMinos: txt += "Minos"; break;
639 case kImprove: txt += "Improve"; break;
640 case kSimplex: txt += "Simplex"; break;
641 case kSeek: txt += "Seek"; break;
642 case kNone: txt += "no"; break;
643 }
644 txt += " optimization";
645
646 fLog->Separator(txt);
647
648 // Setup eventloop
649 MEvtLoop evtloop(fTitle);
650 evtloop.SetParList(&parlist);
651 evtloop.SetDisplay(fDisplay); // set display for evtloop and all childs
652 parlist.SetDisplay(0); // reset display for all contents of parlist and tasklist
653 evtloop.SetPrivateDisplay(); // prevent display from being cascaded again in PreProcess
654
655 *fLog << inf << "Number of Parameters: " << fParameters.GetSize() << endl;
656
657 // In case the reader is the matrix loop and testrain is enabled
658 // switch on even mode...
659 if (loop && TMath::Abs(fTestTrain)>0)
660 loop->SetOperationMode(fTestTrain>0?MMatrixLoop::kEven:MMatrixLoop::kOdd);
661
662 if (!Optimize(evtloop))
663 return kFALSE;
664
665 gMinuit = 0;
666
667 // Test with training data
668 fEvtLoop->SetDisplay(fDisplay);
669 if (!Fcn(fParameters))
670 return kFALSE;
671
672 // In case the reader is the matrix loop and testrain is enabled
673 // switch on odd mode...
674 if (!loop || fTestTrain==0)
675 return kTRUE;
676
677 // Test with test-data
678 loop->SetOperationMode(fTestTrain<0?MMatrixLoop::kEven:MMatrixLoop::kOdd);
679
680 // Done already in Fcn
681 // list.SetVariables(fParameters);
682 return Fcn(fParameters);
683}
684
685void MJOptimize::AddRulesToMatrix(MHMatrix &m) const
686{
687 TIter Next1(&fRules);
688 TObject *o1=0;
689 while ((o1=Next1()))
690 m.AddColumn(o1->GetName());
691}
692
693//------------------------------------------------------------------------
694//
695// Fill matrix m by using read. Use rules as a filter if userules.
696//
697Bool_t MJOptimize::FillMatrix(MReadTree &read, MParList &parlist, Bool_t userules)
698{
699 MHMatrix *m = (MHMatrix*)parlist.FindObject("M", "MHMatrix");
700 if (!m)
701 {
702 *fLog << err << "MJOptimize::FillMatrix - ERROR: M [MHMatrix] not found in parlist... abort." << endl;
703 return kFALSE;
704 }
705
706 m->Print("cols");
707
708 // MGeomCamMagic cam;
709 // parlist.AddToList(&cam);
710
711 // Setup filter and apply filter to filling of matrix
712 MFilterList list;
713 if (!list.AddToList(fPreCuts))
714 *fLog << err << "ERROR - Calling MFilterList::AddToList for fPreCuts failed!" << endl;
715 if (userules)
716 SetupFilters(list);
717 list.SetName("PreCuts"); // reset Name set by SetupFilters
718 list.SetInverted(kTRUE); // reset inversion set by SetupFilters
719
720 MContinue cont(&list);
721
722 // Setup filling of matrix
723 MFillH fillh(m);
724
725 // Setup tasklist
726 MTaskList tlist;
727 parlist.Replace(&tlist);
728
729 // Create task list
730 tlist.AddToList(&read); // read data
731 tlist.AddToList(fPreTasks); // execute pre-filter tasks
732 tlist.AddToList(&cont); // execute filters
733 tlist.AddToList(fPostTasks); // execute post-filter tasks
734 tlist.AddToList(&fillh); // Fill matrix
735
736 tlist.SetAccelerator(MTask::kAccDontReset|MTask::kAccDontTime);
737
738 MEvtLoop fillloop(fTitle);
739 fillloop.SetParList(&parlist);
740 fillloop.SetDisplay(fDisplay);
741 if (!fillloop.Eventloop(fNumEvents))
742 {
743 *fLog << err << "Filling matrix failed..." << endl;
744 return kFALSE;
745 }
746
747 *fLog << inf << "Read events from file '" << read.GetFileName() << "'" << endl;
748
749 if (fillloop.GetDisplay()!=fDisplay)
750 {
751 fDisplay = 0;
752 *fLog << inf << "Optimization aborted by user." << endl;
753 return kFALSE;
754 }
755
756 m->Print("size");
757
758 return kTRUE;
759}
760
761//------------------------------------------------------------------------
762//
763// Adds all filters to MFilterList
764//
765void MJOptimize::SetupFilters(MFilterList &list, MFilter *filter) const
766{
767 list.SetName("MParameters");
768 list.SetInverted();
769
770 if (filter)
771 {
772 if (fFilter.GetSize()>0)
773 {
774 *fLog << inf;
775 *fLog << "INFORMATION - You are using an external filter and internal filters." << endl;
776 *fLog << " Please make sure that all parameters '[i]' are starting" << endl;
777 *fLog << " behind the number of parameters of the external filter." << endl;
778 }
779 list.AddToList(filter);
780 }
781
782 if (!list.AddToList(fFilter))
783 *fLog << err << "ERROR - Calling MFilterList::AddToList fFilter failed!" << endl;
784
785 *fLog << inf << "Filter: ";
786 list.Print();
787 *fLog << endl;
788}
Note: See TracBrowser for help on using the repository browser.