CompositeFunction.cpp 22.9 KB
Newer Older
1
2
3
4
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/Exception.h"
5
6
#include "MantidAPI/CompositeFunction.h"
#include "MantidAPI/ParameterTie.h"
7
#include "MantidAPI/IConstraint.h"
8

9
#include <boost/lexical_cast.hpp>
10
11
12
#include <boost/shared_array.hpp>
#include <sstream>
#include <iostream>
13
#include <algorithm>
14
15
16
17
18
19

namespace Mantid
{
namespace API
{

20
//DECLARE_FUNCTION(CompositeFunction)
21

22
23
/// Copy contructor
CompositeFunction::CompositeFunction(const CompositeFunction& f)
24
:m_nActive(f.m_nParams),m_nParams(f.m_nParams),m_iConstraintFunction(0)
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
  m_functions.assign(f.m_functions.begin(),f.m_functions.end());
  m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
  m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
}

///Assignment operator
CompositeFunction& CompositeFunction::operator=(const CompositeFunction& f)
{
  m_nActive = f.m_nActive;
  m_nParams = f.m_nParams;
  m_functions.assign(f.m_functions.begin(),f.m_functions.end());
  m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
  m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
39
  m_iConstraintFunction = f.m_iConstraintFunction;
40
41
42
43
44
45
  return *this;
}

///Destructor
CompositeFunction::~CompositeFunction()
{
46
  for(int i=0;i<nFunctions();i++)
47
48
49
50
51
52
53
54
55
    if (m_functions[i]) delete m_functions[i];
}


/// Function initialization. Declare function parameters in this method.
void CompositeFunction::init()
{
}

56
57
58
59
60
61
62
63
64
65
66
/** 
 * Writes itself into a string. Functions derived from CompositeFunction must
 * override this method with something like this:
 *   std::string NewFunction::asString()const
 *   {
 *      ostr << "composite=" << this->name() << ';';
 *      // write NewFunction's own attributes and parameters
 *      ostr << CompositeFunction::asString();
 *      // write NewFunction's own ties and constraints
 *      // ostr << ";constraints=(" << ... <<")";
 *   }
67
 * @return the string representation of the composite function
68
 */
69
70
71
std::string CompositeFunction::asString()const
{
  std::ostringstream ostr;
72
  for(int i=0;i<nFunctions();i++)
73
  {
74
    IFitFunction* fun = getFunction(i);
75
76
    bool isComp = dynamic_cast<CompositeFunction*>(fun) != 0;
    if (isComp) ostr << '(';
77
    ostr << fun->asString();
78
    if (isComp) ostr << ')';
79
80
81
82
83
84
    if (i < nFunctions() - 1)
    {
      ostr << ';';
    }
  }
  std::string ties;
85
  for(int i=0;i<nParams();i++)
86
87
88
89
  {
    const ParameterTie* tie = getTie(i);
    if (tie)
    {
90
      IFitFunction* fun = getFunction(functionIndex(i));
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
      std::string tmp = tie->asString(fun);
      if (tmp.empty())
      {
        tmp = tie->asString(this);
        if (!tmp.empty())
        {
          if (!ties.empty())
          {
            ties += ",";
          }
          ties += tmp;
        }
      }
    }
  }
  if (!ties.empty())
  {
    ostr << ";ties=(" << ties << ")";
109
110
111
112
  }
  return ostr.str();
}

113
/** Sets a new value to the i-th parameter.
114
115
116
 *  @param i :: The parameter index
 *  @param value :: The new value
 *  @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
117
 */
118
void CompositeFunction::setParameter(int i, const double& value, bool explicitlySet)
119
{
120
  int iFun = functionIndex(i);
121
  m_functions[ iFun ]->setParameter(i - m_paramOffsets[iFun],value,explicitlySet);
122
123
}

124
/** Get the i-th parameter.
125
 *  @param i :: The parameter index
126
 *  @return value of the requested parameter
127
 */
128
double CompositeFunction::getParameter(int i)const
129
{
130
  int iFun = functionIndex(i);
131
  return m_functions[ iFun ]->getParameter(i - m_paramOffsets[iFun]);
132
133
}

134
135
/**
 * Sets a new value to a parameter by name.
136
137
138
 * @param name :: The name of the parameter.
 * @param value :: The new value
 * @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
139
140
 */
void CompositeFunction::setParameter(const std::string& name, const double& value, bool explicitlySet)
141
{
142
  std::string pname;
143
  int index;
144
  parseName(name,index,pname);
145
146
147
148
149
150
  if (index < 0)
    throw std::invalid_argument("CompositeFunction::getParameter: parameter name must contain function index");
  else
  {   
    getFunction(index)->setParameter(pname,value,explicitlySet);
  }
151
152
}

153
154
/**
 * Parameters by name.
155
 * @param name :: The name of the parameter.
156
 * @return value of the requested named parameter
157
 */
158
159
double CompositeFunction::getParameter(const std::string& name)const
{
160
  std::string pname;
161
  int index;
162
  parseName(name,index,pname);
163
164
165
166
167
168
  if (index < 0)
    throw std::invalid_argument("CompositeFunction::getParameter: parameter name must contain function index");
  else
  {   
    return getFunction(index)->getParameter(pname);
  }
169
170
171
}

/// Total number of parameters
172
int CompositeFunction::nParams()const
173
174
175
176
{
  return m_nParams;
}

177
/**
178
 * 
179
 * @param name :: The name of a parameter
180
 * @return index of the requested named parameter
181
 */
182
int CompositeFunction::parameterIndex(const std::string& name)const
183
{
184
  std::string pname;
185
  int index;
186
  parseName(name,index,pname);
187
188
189
  if (index < 0)
    throw std::invalid_argument("CompositeFunction::getParameter: parameter name must contain function index");

190
  return getFunction(index)->parameterIndex(pname) + m_paramOffsets[index];
191
192
}

Nick Draper's avatar
re #100    
Nick Draper committed
193
/// Returns the name of parameter
194
/// @param i :: The index
Nick Draper's avatar
re #100    
Nick Draper committed
195
/// @return The name of the parameter
196
std::string CompositeFunction::parameterName(int i)const
197
{
198
  int iFun = functionIndex(i);
199
200
201
  std::ostringstream ostr;
  ostr << 'f' << iFun << '.' << m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
  return ostr.str();
202
203
204
}

/// Number of active (in terms of fitting) parameters
205
int CompositeFunction::nActive()const
206
207
208
209
210
{
  return m_nActive;
}

/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
211
double CompositeFunction::activeParameter(int i)const
212
{
213
  int iFun = functionIndexActive(i);
214
215
216
217
218
219
  return m_functions[ iFun ]->activeParameter(i - m_activeOffsets[iFun]);
}

/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
void CompositeFunction::setActiveParameter(int i, double value)
{
220
  int iFun = functionIndexActive(i);
221
  m_functions[ iFun ]->setActiveParameter(i - m_activeOffsets[iFun],value);
222
223
224
225
226
227
228
229
230
}

/// Update parameters after a fitting iteration
void CompositeFunction::updateActive(const double* in)
{
  for(int iFun = 0; iFun < int(m_functions.size()); iFun++)
  {
    m_functions[ iFun ]->updateActive(in + m_activeOffsets[ iFun ]);
  }
231
  applyTies();
232
233
234
}

/// Returns "global" index of active parameter i
235
int CompositeFunction::indexOfActive(int i)const
236
{
237
  int iFun = functionIndexActive(i);
238
239
240
241
  return m_paramOffsets[ iFun ] + m_functions[ iFun ]->indexOfActive(i - m_activeOffsets[iFun]);
}

/// Returns the name of active parameter i
242
std::string CompositeFunction::nameOfActive(int i)const
243
{
244
  int iFun = functionIndexActive(i);
245
246
247
  std::ostringstream ostr;
  ostr << 'f' << iFun << '.' << m_functions[ iFun ]->nameOfActive(i - m_activeOffsets[iFun]);
  return ostr.str();
248
249
}

250
/**
251
 * query to see in the function is active
252
 * @param i :: The index of a declared parameter
253
 * @return true if parameter i is active
254
 */
255
bool CompositeFunction::isActive(int i)const
256
257
258
259
260
261
{
  int iFun = functionIndex(i);
  return m_functions[ iFun ]->isActive(i - m_paramOffsets[iFun]);
}

/**
262
 * @param i :: A declared parameter index to be removed from active
263
 */
264
void CompositeFunction::removeActive(int i)
265
{
266
  if (!isActive(i)) return;
267
268
  int iFun = functionIndex(i);
  int ia = m_activeOffsets[iFun] + m_functions[iFun]->activeIndex(i - m_paramOffsets[iFun]);
269
  m_IFitFunctionActive.erase(m_IFitFunctionActive.begin()+ia);
270
271
  m_functions[ iFun ]->removeActive(i - m_paramOffsets[iFun]);

272
  m_nActive--;
273
  for(int j=iFun+1;j<nFunctions();j++)
274
275
276
    m_activeOffsets[j] -= 1;
}

277
/** Makes a parameter active again. It doesn't change the parameter's tie.
278
 * @param i :: A declared parameter index to be restored to active
279
 */
280
void CompositeFunction::restoreActive(int i)
281
{
282
283
  int iFun = functionIndex(i);
  int ia = m_activeOffsets[iFun] + m_functions[iFun]->activeIndex(i - m_paramOffsets[iFun]);
284

285
  std::vector<int>::iterator itFun = 
286
    std::find_if(m_IFitFunctionActive.begin(),m_IFitFunctionActive.end(),std::bind2nd(std::greater<int>(),i));
287

288
  m_IFitFunctionActive.insert(itFun,1,ia);
289
290
291
  m_functions[ iFun ]->restoreActive(i - m_paramOffsets[iFun]);

  m_nActive++;
292
  for(int j=iFun+1;j<nFunctions();j++)
293
294
295
    m_activeOffsets[j] += 1;
}

296
/**
297
 * @param i :: The index of a declared parameter
298
299
300
 * @return The index of declared parameter i in the list of active parameters or -1
 *         if the parameter is tied.
 */
301
int CompositeFunction::activeIndex(int i)const
302
{
303
304
  int iFun = functionIndex(i);
  int j = m_functions[iFun]->activeIndex(i - m_paramOffsets[iFun]);
305
306
307
308
309
310
311

  if (j == -1) 
  {
    return -1;
  }

  return m_activeOffsets[iFun] + j;
312
313
}

314
315
316
317
318
319
320
321
/** Makes sure that the function is consistent. 
 */
void CompositeFunction::checkFunction()
{
  m_nParams = 0;
  m_nActive = 0;
  m_paramOffsets.clear();
  m_activeOffsets.clear();
322
323
  m_IFitFunction.clear();
  m_IFitFunctionActive.clear();
324

325
  std::vector<IFitFunction*> functions(m_functions.begin(),m_functions.end());
326
327
  m_functions.clear();

328
  for(std::vector<IFitFunction*>::size_type i=0;i<functions.size();i++)
329
  {
330
    IFitFunction* f = functions[i];
331
332
    CompositeFunction* cf = dynamic_cast<CompositeFunction*>(f);
    if (cf) cf->checkFunction();
333
334
335
336
    addFunction(f);
  }
}

337
/** Add a function
338
 * @param f :: A pointer to the added function
339
 * @return The function index
340
 */
341
int CompositeFunction::addFunction(IFitFunction* f)
342
{
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
343
344
  m_IFitFunction.insert(m_IFitFunction.end(),f->nParams(), static_cast<int>(m_functions.size()));
  m_IFitFunctionActive.insert(m_IFitFunctionActive.end(),f->nActive(),static_cast<int>(m_functions.size()));
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  m_functions.push_back(f);
  //?f->init();
  if (m_paramOffsets.size() == 0)
  {
    m_paramOffsets.push_back(0);
    m_activeOffsets.push_back(0);
    m_nParams = f->nParams();
    m_nActive = f->nActive();
  }
  else
  {
    m_paramOffsets.push_back(m_nParams);
    m_activeOffsets.push_back(m_nActive);
    m_nParams += f->nParams();
    m_nActive += f->nActive();
  }
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
361
  return static_cast<int>(m_functions.size())-1;
362
363
}

364
/** Remove a function
365
366
 * @param i :: The index of the function to remove
 * @param del :: The deletion flag. If true the function will be deleted otherwise - simply detached
367
 */
368
void CompositeFunction::removeFunction(int i, bool del)
369
370
371
372
{
  if ( i >= nFunctions() )
    throw std::out_of_range("Function index out of range.");

373
  IFitFunction* fun = getFunction(i);
374

375
376
  int dna = fun->nActive();
  int dnp = fun->nParams();
377

378
  for(int j=0;j<nParams();)
379
380
  {
    ParameterTie* tie = getTie(j);
381
    if (tie && tie->findParametersOf(fun))
382
383
384
385
386
387
388
389
390
391
    {
      removeTie(j);
    }
    else
    {
      j++;
    }
  }

  // Shift down the function indeces for parameters
392
  for(std::vector<int>::iterator it=m_IFitFunction.begin();it!=m_IFitFunction.end();)
393
  {
394

395
396
    if (*it == i)
    {
397
      it = m_IFitFunction.erase(it);
398
    }
399
    else
400
    {
401
402
403
404
405
      if (*it > i)
      {
        *it -= 1;
      }
      it++;
406
407
408
409
    }
  }

  // Shift down the function indeces for active parameters
410
  for(std::vector<int>::iterator it=m_IFitFunctionActive.begin();it!=m_IFitFunctionActive.end();)
411
412
413
  {
    if (*it == i)
    {
414
      it = m_IFitFunctionActive.erase(it);
415
    }
416
    else
417
    {
418
419
420
421
422
      if (*it > i)
      {
        *it -= 1;
      }
      it++;
423
424
425
426
427
    }
  }

  m_nActive -= dna;
  // Shift the active offsets down by the number of i-th function's active params
428
  for(int j=i+1;j<nFunctions();j++)
429
430
431
432
433
434
435
  {
    m_activeOffsets[j] -= dna;
  }
  m_activeOffsets.erase(m_activeOffsets.begin()+i);

  m_nParams -= dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
436
  for(int j=i+1;j<nFunctions();j++)
437
438
439
440
441
442
  {
    m_paramOffsets[j] -= dnp;
  }
  m_paramOffsets.erase(m_paramOffsets.begin()+i);

  m_functions.erase(m_functions.begin()+i);
443
444
445
446
  if (del)
  {
    delete fun;
  }
447
448
}

449
/** Replace a function with a new one. The old function is deleted.
450
 *  The new function must have already its workspace set.
451
 * @param f_old :: The pointer to the function to replace. If it's not
452
 *  a member of this composite function nothing happens
453
 * @param f_new :: A pointer to the new function
454
 */
455
void CompositeFunction::replaceFunction(const IFitFunction* f_old,IFitFunction* f_new)
456
{
457
  std::vector<IFitFunction*>::const_iterator it = 
458
459
    std::find(m_functions.begin(),m_functions.end(),f_old);
  if (it == m_functions.end()) return;
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
460
461
  std::vector<IFitFunction*>::difference_type iFun = it - m_functions.begin();
  replaceFunction(static_cast<int>(iFun),f_new);
462
463
}

464
/** Replace a function with a new one. The old function is deleted.
465
466
 * @param i :: The index of the function to replace
 * @param f :: A pointer to the new function
467
 */
468
void CompositeFunction::replaceFunction(int i,IFitFunction* f)
469
470
471
472
{
  if ( i >= nFunctions() )
    throw std::out_of_range("Function index out of range.");

473
  IFitFunction* fun = getFunction(i);
474
475
  int na_old = fun->nActive();
  int np_old = fun->nParams();
476

477
478
  int na_new = f->nActive();
  int np_new = f->nParams();
479
480
481

  // Modify function indeces: The new function may have different number of parameters
  {
482
    std::vector<int>::iterator itFun = std::find(m_IFitFunction.begin(),m_IFitFunction.end(),i);
483
    if(itFun != m_IFitFunction.end()) // functions must have at least 1 parameter
484
    {
485
486
      if (np_old > np_new)
      {
487
        m_IFitFunction.erase(itFun,itFun + np_old - np_new);
488
489
490
      }
      else if (np_old < np_new) 
      {
491
        m_IFitFunction.insert(itFun,np_new - np_old,i);
492
      }
493
    }
494
495
    else if (np_new > 0) // it could happen if the old function is an empty CompositeFunction
    {
496
497
      itFun = std::find_if(m_IFitFunction.begin(),m_IFitFunction.end(),std::bind2nd(std::greater<int>(),i));
      m_IFitFunction.insert(itFun,np_new,i);
498
    }
499
500
501
502
  }

  // Modify function indeces: The new function may have different number of active parameters
  {
503
    std::vector<int>::iterator itFun = std::find(m_IFitFunctionActive.begin(),m_IFitFunctionActive.end(),i);
504
    if (itFun != m_IFitFunctionActive.end())
505
506
507
    {
      if (na_old > na_new)
      {
508
        m_IFitFunctionActive.erase(itFun,itFun + na_old - na_new);
509
510
511
      }
      else if (na_old < na_new) 
      {
512
        m_IFitFunctionActive.insert(itFun,na_new - na_old,i);
513
514
515
516
      }
    }
    else if (na_new > 0)
    {
517
518
      itFun = std::find_if(m_IFitFunctionActive.begin(),m_IFitFunctionActive.end(),std::bind2nd(std::greater<int>(),i));
      m_IFitFunctionActive.insert(itFun,na_new,i);
519
520
521
    }
  }

522
  int dna = na_new - na_old;
523
524
  m_nActive += dna;
  // Recalc the active offsets 
525
  for(int j=i+1;j<nFunctions();j++)
526
527
528
529
  {
    m_activeOffsets[j] += dna;
  }

530
  int dnp = np_new - np_old;
531
532
  m_nParams += dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
533
  for(int j=i+1;j<nFunctions();j++)
534
535
536
537
538
539
540
541
  {
    m_paramOffsets[j] += dnp;
  }

  m_functions[i] = f;
  delete fun;
}

542
/**
543
 * @param i :: The index of the function
544
 * @return function at the requested index
545
 */
546
IFitFunction* CompositeFunction::getFunction(int i)const
547
{
548
  if ( i >= nFunctions()  || i < 0)
549
  {
550
    throw std::out_of_range("Function index out of range.");
551
  }
552
553
554
  return m_functions[i];
}

555
556
/**
 * Get the index of the function to which parameter i belongs
557
 * @param i :: The parameter index
558
 * @return function index of the requested parameter
559
 */
560
int CompositeFunction::functionIndex(int i)const
561
{
562
  if (i >= nParams() || i < 0)
563
  {
564
    throw std::out_of_range("Function parameter index out of range.");
565
  }
566
  return m_IFitFunction[i];
567
568
569
570
}

/**
 * Get the index of the function to which parameter i belongs
571
 * @param i :: The active parameter index
572
 * @return active function index of the requested parameter
573
 */
574
int CompositeFunction::functionIndexActive(int i)const
575
{
576
  if (i >= nParams() || i < 0)
577
    throw std::out_of_range("Function parameter index out of range.");
578
  return m_IFitFunctionActive[i];
579
580
581
}

/**
582
583
584
* @param varName :: The variable name which may contain function index ( [f<index.>]name )
* @param index :: Receives function index or -1 
* @param name :: Receives the parameter name
585
*/
586
void CompositeFunction::parseName(const std::string& varName,int& index, std::string& name)
587
{
588
589
590
591
  size_t i = varName.find('.');
  if (i == std::string::npos)
  {
    name = varName;
592
593
    index = -1;
    return;
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  }
  else
  {
    if (varName[0] != 'f')
      throw std::invalid_argument("External function parameter name must start with 'f'");

    std::string sindex = varName.substr(1,i-1);
    index = boost::lexical_cast<int>(sindex);

    if (i == varName.size() - 1)
      throw std::invalid_argument("Name cannot be empty");

    name = varName.substr(i+1);
  }
608
609
}

610
/** Returns the index of parameter i as it declared in its function
611
 * @param i :: The parameter index
612
613
 * @return The local index of the parameter
 */
614
int CompositeFunction::parameterLocalIndex(int i)const
615
616
617
618
619
{
  int iFun = functionIndex(i);
  return i - m_paramOffsets[iFun];
}

620
/** Returns the name of parameter i as it declared in its function
621
 * @param i :: The parameter index
622
623
 * @return The pure parameter name (without the function identifier f#.)
 */
624
std::string CompositeFunction::parameterLocalName(int i)const
625
626
627
628
629
{
  int iFun = functionIndex(i);
  return m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
}

Janik Zikovsky's avatar
Janik Zikovsky committed
630
631
632
633
634
635
// /** Initialize the function providing it the workspace
// * @param workspace :: The shared pointer to a workspace to which the function will be fitted
// * @param spec :: The number of a spectrum for fitting
// * @param xMin :: The minimum bin index of spectrum spec that will be used in fitting
// * @param xMax :: The maximum bin index of spectrum spec that will be used in fitting
// */
636
637
638
639
640
641
642
643
//void CompositeFunction::setMatrixWorkspace(boost::shared_ptr<const API::MatrixWorkspace> workspace,int spec,int xMin,int xMax)
//{
//  IFitFunction::setMatrixWorkspace(workspace,spec,xMin,xMax);
//  for(int i=0;i<nFunctions();i++)
//  {
//    getFunction(i)->setMatrixWorkspace(workspace,spec,xMin,xMax);
//  }
//}
644

645
/**
646
 * Apply the ties.
647
648
649
 */
void CompositeFunction::applyTies()
{
650
  for(int i=0;i<nFunctions();i++)
651
652
653
654
655
656
657
658
659
660
  {
    getFunction(i)->applyTies();
  }
}

/**
 * Clear the ties. 
 */
void CompositeFunction::clearTies()
{
661
  for(int i=0;i<nFunctions();i++)
662
663
664
665
666
667
  {
    getFunction(i)->clearTies();
  }
}

/** Removes i-th parameter's tie if it is tied or does nothing.
668
 * @param i :: The index of the tied parameter.
669
670
 * @return True if successfull
 */
671
bool CompositeFunction::removeTie(int i)
672
{
673
  int iFun = functionIndex(i);
674
675
676
677
678
679
680
681
682
  bool res = m_functions[ iFun ]->removeTie(i - m_paramOffsets[iFun]);
  if (res)
  {
    m_nActive++;
  }
  return res;
}

/** Get the tie of i-th parameter
683
 * @param i :: The parameter index
684
 * @return A pointer to the tie.
685
 */
686
ParameterTie* CompositeFunction::getTie(int i)const
687
688
689
690
691
692
693
{
  int iFun = functionIndex(i);
  return m_functions[ iFun ]->getTie(i - m_paramOffsets[iFun]);
}

/**
 * Attaches a tie to this function. The attached tie is owned by the function.
694
 * @param tie :: A pointer to a new tie
695
696
697
 */
void CompositeFunction::addTie(ParameterTie* tie)
{
698
  int i = getParameterIndex(*tie);
699
700
701
702
703
704
705
706
707
708
  if (i < 0)
  {
    throw std::logic_error("Trying to use a tie on a parameter not belonging to this function");
  }
  int iFun = functionIndex(i);
  m_functions[iFun]->addTie(tie);
}

/**
 * Declare a new parameter. To used in the implementation'c constructor.
709
710
 * @param name :: The parameter name.
 * @param initValue :: The initial value for the parameter
711
 */
712
void CompositeFunction::declareParameter(const std::string& name, double initValue, const std::string& description)
713
{
714
715
  (void) name; //Avoid compiler warning
  (void) initValue; //Avoid compiler warning
716
  (void) description; //Avoid compiler warning
717
718
719
720
  throw Kernel::Exception::NotImplementedError("CompositeFunction cannot not have its own parameters.");
}

/** Add a constraint
721
 *  @param ic :: Pointer to a constraint.
722
723
724
 */
void CompositeFunction::addConstraint(IConstraint* ic)
{
725
726
727
  int i = getParameterIndex(*ic);
  int iFun = functionIndex(i);
  getFunction(iFun)->addConstraint(ic);
728
729
}

730
731
void CompositeFunction::setParametersToSatisfyConstraints()
{
732
  for(int i=0;i<nFunctions();i++)
733
734
735
736
737
  {
    getFunction(i)->setParametersToSatisfyConstraints();
  }
}

Nick Draper's avatar
re #100    
Nick Draper committed
738
/// Get constraint
739
/// @param i :: the index
Nick Draper's avatar
re #100    
Nick Draper committed
740
/// @return A pointer to the constraint
741
IConstraint* CompositeFunction::getConstraint(int i)const
742
{
743
  int iFun = functionIndex(i);
744
  return m_functions[ iFun ]->getConstraint(i - m_paramOffsets[iFun]);
745
746
}

747
/** Remove a constraint
748
 * @param parName :: The name of a parameter which constarint to remove.
749
750
751
752
753
754
755
756
 */
void CompositeFunction::removeConstraint(const std::string& parName)
{
  int iPar = parameterIndex(parName);
  int iFun = functionIndex(iPar);
  getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
}

757
/** Checks if a constraint has been explicitly set
758
 *  @param i :: The parameter index
759
 *  @return true if the function is explicitly set
760
 */
761
bool CompositeFunction::isExplicitlySet(int i)const
762
{
763
  int iFun = functionIndex(i);
764
765
766
  return m_functions[ iFun ]->isExplicitlySet(i - m_paramOffsets[iFun]);
}

767
768
/**
 * Returns the index of parameter if the ref points to one of the member function or -1
769
 * @param ref :: A reference to a parameter
770
771
 * @return Parameter index or -1
 */
772
int CompositeFunction::getParameterIndex(const ParameterReference& ref)const
773
{
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
774
  if (ref.getFunction() == this && static_cast<int>(ref.getIndex()) < nParams())
775
  {
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
776
    return static_cast<int>(ref.getIndex());
777
  }
778
  for(int iFun=0;iFun<nFunctions();iFun++)
779
  {
780
    int iLocalIndex = getFunction(iFun)->getParameterIndex(ref);
781
782
783
784
785
    if (iLocalIndex >= 0)
    {
      return m_paramOffsets[iFun] + iLocalIndex;
    }
  }
786
787
788
  return -1;
}

789
/**
790
 * @param ref :: The reference
791
792
 * @return A function containing parameter pointed to by ref
 */
793
IFitFunction* CompositeFunction::getContainingFunction(const ParameterReference& ref)const
794
{
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
795
  if (ref.getFunction() == this && static_cast<int>(ref.getIndex()) < nParams())
796
797
798
  {
    return ref.getFunction();
  }
799
  for(int iFun=0;iFun<nFunctions();iFun++)
800
  {
801
    IFitFunction* fun = static_cast<IFitFunction*>(getFunction(iFun)->getContainingFunction(ref));
802
803
804
805
806
807
808
    if (fun)
    {
      return getFunction(iFun);
    }
  }
  return NULL;
}
809

810
/**
811
 * @param fun :: The searched function
812
813
 * @return A function containing the argument function fun
 */
814
IFitFunction* CompositeFunction::getContainingFunction(const IFitFunction* fun)
815
816
817
818
819
{
  if (fun == this)
  {
    return this;
  }
820
  for(int iFun=0;iFun<nFunctions();iFun++)
821
  {
822
    IFitFunction* f = static_cast<IFitFunction*>(getFunction(iFun)->getContainingFunction(fun));
823
824
825
826
827
828
829
830
    if (f)
    {
      return getFunction(iFun);
    }
  }
  return NULL;
}

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
//void CompositeFunction::setWorkspace(boost::shared_ptr<Workspace> ws,const std::string& slicing)
//{
//  IFitFunction::setWorkspace(ws,slicing);
//  for(int iFun=0;iFun<nFunctions();iFun++)
//  {
//    getFunction(iFun)->setUpNewStuff(m_xValues,m_weights);
//  }
//}

//void CompositeFunction::setUpNewStuff(boost::shared_array<double> xs,boost::shared_array<double> weights)
//{
//  IFitFunction::setUpNewStuff(xs,weights);
//  for(int iFun=0;iFun<nFunctions();iFun++)
//  {
//    getFunction(iFun)->setUpNewStuff(xs,weights);
//  }
//}
848

849
850
} // namespace API
} // namespace Mantid