IFunction.h 26.5 KB
Newer Older
1
2
3
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2009 ISIS Rutherford Appleton Laboratory UKRI,
4
5
//   NScD Oak Ridge National Laboratory, European Spallation Source,
//   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6
// SPDX - License - Identifier: GPL - 3.0 +
7
#pragma once
8
9
10
11
12
13

//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/FunctionDomain.h"
14
#include "MantidAPI/FunctionValues.h"
15
#include "MantidAPI/IConstraint.h"
Roman Tolchenov's avatar
Roman Tolchenov committed
16
#include "MantidAPI/Jacobian.h"
17
#include "MantidAPI/ParameterTie.h"
18
#include "MantidKernel/Matrix.h"
19
20
#include "MantidKernel/Unit.h"

21
#ifndef Q_MOC_RUN
22
#include <boost/variant.hpp>
23
#include <memory>
24
25
#endif

26
#include <string>
David Fairbrother's avatar
David Fairbrother committed
27
28
#include <utility>

29
30
31
#include <vector>

#ifdef _WIN32
32
#pragma warning(disable : 4250)
33
34
#endif

35
36
namespace Mantid {
namespace Kernel {
37
38
39
//----------------------------------------------------------------------
// Forward declaration
//----------------------------------------------------------------------
40
class ProgressBase;
LamarMoore's avatar
LamarMoore committed
41
} // namespace Kernel
42
namespace API {
43
class Workspace;
44
class MatrixWorkspace;
45
class FunctionHandler;
46

47
48
49
50
/** This is an interface to a fitting function - a semi-abstarct class.
    Functions derived from IFunction can be used with the Fit algorithm.
    IFunction defines the structure of a fitting funtion.

51
52
53
54
55
56
    A function has a number of named parameters (not arguments), type double, on
   which it depends.
    Parameters must be declared either in the constructor or in the init()
   method
    of a derived class with method declareParameter(...). Method nParams()
   returns
57
    the number of parameters. A parameter can be accessed either by its name
58
59
    or the index. For example in case of Gaussian the parameters can be
   "Height",
60
61
    "PeakCentre" and "Sigma".

62
63
64
65
66
67
    The main method of IFunction is called function(const
   FunctionDomain&,FunctionValues&).
    It takes a set of function arguments via interface FunctionDomain,
   calculates the values, and
    returns them via the FunctionValues. The derived classes must implement this
   method.
68
69

    Implement functionDeriv method for the function to be used with
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    fitting algorithms using derivatives. functionDeriv calculates patrial
   derivatives of the
    function with respect to the fitting parameters. The default implementation
   uses numeric differentiation.

    To fit a function to a set of data its parameters must be adjusted so that
   the difference
    between the data and the corresponding function values were minimized. This
   is the aim
    of the Fit algorithm. But Fit does not work with the declared parameters
   directly.
    Instead it uses other - active - parameters. In simple case the active
   parameters are the
    same as the declared ones. But they can be overidden if the declared
   parameters make fit unstable.
    There are as many active parameters as there are the declared ones. A
   one-to-one transformation
    must exist between the active and the declared parameters. Overide
   activeParameter and
    setActiveParameter methods to implement this transformation. An example is
   Gaussian where
    "Sigma" makes the fit unstable. So in the fit it is replaced with variable
   Weight = 1 / Sigma
93
    which is more efficient.
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    The active parameters can be accessed by their index. The implementations of
   the access method
    for both active and declared parameters must ensure that any changes to one
   of them
    immediately reflected on the other so that the two sets are consistent at
   any moment.

    IFunction declares method nameOfActive(int i) which returns the name of the
   declared parameter
    corresponding to the i-th active parameter. I am not completely sure in the
   usefulness of it.

    The declared parameters can be made fixed in a fit with method fix(). If a
   parameter is fixed a fit
    shouldn't change its value unless it is also tied to values of other
   parameters. Implementations of
111
    active parameters must ensure this behaviour.
112

113
114
115
116
117
118
    When a declared parameter is made fixed one of the active parameters must
   become inactive. isActive(i)
    method must return false for it. In case of declared == active the fixed
   parameter becomes inactive.
    Classes overriding active parameters must ensure that number of inactive
   parameters == number of
119
    fixed declared ones at any moment.
120

121
122
123
124
    IFunction provides methods for tying and untying parameters. Only the
   declared parameters can be
    tied. isFixed() method returns true for a tied parameter. The value of a
   tied parameter is defined
125
126
    by its tie and can change in a fit.

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    Method addConstraint adds constraints on possible values of a declared
   parameter. A constrained parameter
    is not fixed and can vary within its constraint. Constraints and ties are
   used only in fitting.

    Any non-fitting parameters can be implemented as attributes (class
   IFunction::Attribute).
    An attribute can have one of three types: std::string, int, or double. The
   type is set at construction
    and cannot be changed later. To read or write the attributes there are two
   ways. If the type
    is known the type specific accessors can be used, e.g. asString(), asInt().
   Otherwise the
    IFunction::AttributeVisitor can be used. It provides alternative virtual
   methods to access
    attributes of each type. When creating a function from a string (using
   FunctionFactory::creaeInitialized(...))
    the attributes must be set first, before any fitting parameter, as the
   number and names of the parameters
146
147
148
149
150
151
    can depend on the attributes.

    @author Roman Tolchenov, Tessella Support Services plc
    @date 16/10/2009
    @date 22/12/2010
*/
152
class MANTID_API_DLL IFunction {
153
154
155
156
157
public:
  /**
   * Atribute visitor class. It provides a separate access method
   * for each attribute type. When applied to a particular attribue
   * the appropriate method will be used. The child classes must
158
   * implement the virtual AttributeVisitor::apply methods. See
159
160
   * implementation of Attribute::value() method for an example.
   */
161
162
  template <typename T = void>
  class DLLExport AttributeVisitor : public boost::static_visitor<T> {
163
164
  public:
    /// Virtual destructor
165
    virtual ~AttributeVisitor() = default;
166
    /// implements static_visitor's operator() for std::string
167
    T operator()(std::string &str) const { return apply(str); }
168
    /// implements static_visitor's operator() for double
169
    T operator()(double &d) const { return apply(d); }
170
    /// implements static_visitor's operator() for int
171
    T operator()(int &i) const { return apply(i); }
172
    /// implements static_visitor's operator() for bool
173
    T operator()(bool &b) const { return apply(b); }
174
    /// implements static_visitor's operator() for vector
175
176
    T operator()(std::vector<double> &v) const { return apply(v); }

177
178
  protected:
    /// Implement this mathod to access attribute as string
179
    virtual T apply(std::string &) const = 0;
180
    /// Implement this mathod to access attribute as double
181
    virtual T apply(double &) const = 0;
182
    /// Implement this mathod to access attribute as int
183
    virtual T apply(int &) const = 0;
184
    /// Implement this mathod to access attribute as bool
185
    virtual T apply(bool &) const = 0;
186
    /// Implement this mathod to access attribute as vector
187
    virtual T apply(std::vector<double> &) const = 0;
188
189
190
  };

  /**
191
   * Const version of AttributeVisitor.
192
   */
193
194
  template <typename T = void>
  class DLLExport ConstAttributeVisitor : public boost::static_visitor<T> {
195
196
  public:
    /// Virtual destructor
197
    virtual ~ConstAttributeVisitor() = default;
198
    /// implements static_visitor's operator() for std::string
199
    T operator()(std::string &str) const { return apply(str); }
200
    /// implements static_visitor's operator() for double
201
    T operator()(double &d) const { return apply(d); }
202
    /// implements static_visitor's operator() for int
203
    T operator()(int &i) const { return apply(i); }
204
    /// implements static_visitor's operator() for bool
205
    T operator()(bool &b) const { return apply(b); }
206
    /// implements static_visitor's operator() for vector
207
208
    T operator()(std::vector<double> &v) const { return apply(v); }

209
210
  protected:
    /// Implement this mathod to access attribute as string
211
    virtual T apply(const std::string &str) const = 0;
212
    /// Implement this mathod to access attribute as double
213
    virtual T apply(const double &d) const = 0;
214
    /// Implement this mathod to access attribute as int
215
    virtual T apply(const int &i) const = 0;
216
    /// Implement this mathod to access attribute as bool
217
    virtual T apply(const bool &i) const = 0;
218
    /// Implement this mathod to access attribute as vector
219
    virtual T apply(const std::vector<double> &) const = 0;
220
221
222
223
224
  };

  /// Attribute is a non-fitting parameter.
  /// It can be one of the types: std::string, int, or double
  /// Examples: file name, polinomial order
225
  class MANTID_API_DLL Attribute {
226
  public:
227
    /// Create empty string attribute
228
    explicit Attribute() : m_data(std::string()), m_quoteValue(false) {}
229
    /// Create string attribute
230
231
    explicit Attribute(const std::string &str, bool quoteValue = false)
        : m_data(str), m_quoteValue(quoteValue) {}
232
    /// Create int attribute
233
    explicit Attribute(const int &i) : m_data(i), m_quoteValue(false) {}
234
    /// Create double attribute
235
    explicit Attribute(const double &d) : m_data(d), m_quoteValue(false) {}
236
    /// Create bool attribute
237
    explicit Attribute(const bool &b) : m_data(b), m_quoteValue(false) {}
238
    /// Create string attribute
239
240
    explicit Attribute(const char *c)
        : m_data(std::string(c)), m_quoteValue(false) {}
241
    /// Create vector attribute
242
243
    explicit Attribute(const std::vector<double> &v)
        : m_data(v), m_quoteValue(false) {}
244

245
246
247
248
    /// Apply an attribute visitor
    template <typename T> T apply(AttributeVisitor<T> &v) {
      return boost::apply_visitor(v, m_data);
    }
249
    /// Apply a const attribute visitor
250
251
252
    template <typename T> T apply(ConstAttributeVisitor<T> &v) const {
      return boost::apply_visitor(v, m_data);
    }
253

254
    /// Returns type of the attribute
255
    std::string type() const;
256
    /// Returns the attribute value as a string
257
258
259
260
261
262
    std::string value() const;
    /// Returns string value if attribute is a string, throws exception
    /// otherwise
    std::string asString() const;
    /// Returns a string value that is guarenteed to be quoted for use in places
    /// where the string is used as the displayed value.
263
264
265
266
    std::string asQuotedString() const;
    /// Returns a string value that is guarenteed to be unquoted.
    std::string asUnquotedString() const;
    /// Returns int value if attribute is a int, throws exception otherwise
267
268
269
270
    int asInt() const;
    /// Returns double value if attribute is a double, throws exception
    /// otherwise
    double asDouble() const;
271
    /// Returns bool value if attribute is a bool, throws exception otherwise
272
    bool asBool() const;
273
    /// Returns bool value if attribute is a vector, throws exception otherwise
274
    std::vector<double> asVector() const;
275
276
    /// Check if a string attribute is empty
    bool isEmpty() const;
277

278
    /// Sets new value if attribute is a string
279
    void setString(const std::string &str);
280
    /// Sets new value if attribute is a double
281
    void setDouble(const double &);
282
    /// Sets new value if attribute is a int
283
    void setInt(const int &);
284
    /// Sets new value if attribute is a bool
285
    void setBool(const bool &);
286
    /// Sets new value if attribute is a vector
287
    void setVector(const std::vector<double> &);
288
289
290
291
292
    template <typename T>
    // Set value
    void setValue(const T &v) {
      m_data = v;
    }
293
    /// Set value from a string.
294
295
    void fromString(const std::string &str);

296
297
  private:
    /// The data holder as boost variant
298
299
    mutable boost::variant<std::string, int, double, bool, std::vector<double>>
        m_data;
300
    /// Flag indicating if the string value should be returned quoted
301
    bool m_quoteValue = false;
302
303
304
305
306
  };

  //---------------------------------------------------------//

  /// Constructor
Roman Tolchenov's avatar
Roman Tolchenov committed
307
  IFunction() : m_isParallel(false), m_handler(nullptr), m_chiSquared(0.0) {}
308
309
  /// Virtual destructor
  virtual ~IFunction();
310
311
312
313
  /// No copying
  IFunction(const IFunction &) = delete;
  /// No copying
  IFunction &operator=(const IFunction &) = delete;
314
315

  /// Returns the function's name
316
  virtual std::string name() const = 0;
317
  /// Writes itself into a string
318
  std::string asString() const;
319
  /// Virtual copy constructor
320
  virtual std::shared_ptr<IFunction> clone() const;
321
  /// Set the workspace.
322
  /// @param ws :: Shared pointer to a workspace
323
  virtual void setWorkspace(std::shared_ptr<const Workspace> ws) {
324
325
    UNUSED_ARG(ws);
  }
326
  /// Set matrix workspace
327
  virtual void
328
  setMatrixWorkspace(std::shared_ptr<const API::MatrixWorkspace> workspace,
329
                     size_t wi, double startX, double endX);
330
  /// Iinialize the function
331
332
333
  virtual void initialize() { this->init(); }
  /// Returns an estimate of the number of progress reports a single evaluation
  /// of the function will have. For backwards compatibility default=1
334
335
336
  virtual int64_t estimateNoProgressCalls() const { return 1; }

  /// Attach a progress reporter
337
  void setProgressReporter(std::shared_ptr<Kernel::ProgressBase> reporter);
338
  /// Reports progress with an optional message
339
340
341
  void reportProgress(const std::string &msg = "") const;
  /// Returns true if a progress reporter is set & evalaution has been requested
  /// to stop
342
  bool cancellationRequestReceived() const;
343
344

  /// The categories the Fit function belong to.
345
  /// Categories must be listed as a semi colon separated list.
346
  /// For example: "General, Muon\\Custom" which adds
347
  /// a function to the category "General" and the sub-category
348
349
  /// "Muon\\Custom"
  virtual const std::string category() const { return "General"; }
350
351
  /// Function to return all of the categories that contain this algorithm
  virtual const std::vector<std::string> categories() const;
352
353
354
  /// Function to return the sperator token for the category string. A default
  /// implementation ';' is provided
  virtual const std::string categorySeparator() const { return ";"; }
355

356
357
  /// Evaluates the function for all arguments in the domain.
  /// @param domain :: Provides arguments for the function.
358
359
360
361
  /// @param values :: A buffer to store the function values. It must be large
  /// enogh to store domain.size() values.
  virtual void function(const FunctionDomain &domain,
                        FunctionValues &values) const = 0;
362
  /// Derivatives of function with respect to active parameters.
363
  virtual void functionDeriv(const FunctionDomain &domain, Jacobian &jacobian);
364

365
366
  /* @name Callbacks to perform work at various points other than in the
   * function */
367
368
369
370
371
  /// Called at the start of each iteration
  virtual void iterationStarting() {}
  /// Called at the end of an iteration
  virtual void iterationFinished() {}

372
373
  /** @name Function parameters */
  //@{
374
  /// Set i-th parameter
375
376
  virtual void setParameter(size_t, const double &value,
                            bool explicitlySet = true) = 0;
377
  /// Set i-th parameter description
378
379
  virtual void setParameterDescription(size_t,
                                       const std::string &description) = 0;
380
  /// Get i-th parameter
381
  virtual double getParameter(size_t i) const = 0;
382
  /// Set parameter by name.
383
384
  virtual void setParameter(const std::string &name, const double &value,
                            bool explicitlySet = true) = 0;
385
  /// Set description of parameter by name.
386
387
  virtual void setParameterDescription(const std::string &name,
                                       const std::string &description) = 0;
388
  /// Get parameter by name.
389
  virtual double getParameter(const std::string &name) const = 0;
390
391
  /// Check if function has a parameter with this name.
  virtual bool hasParameter(const std::string &name) const = 0;
392
  /// Total number of parameters
393
  virtual size_t nParams() const = 0;
394
  /// Returns the index of parameter name
395
  virtual size_t parameterIndex(const std::string &name) const = 0;
396
  /// Returns the name of parameter i
397
  virtual std::string parameterName(size_t i) const = 0;
398
  /// Returns the description of parameter i
399
  virtual std::string parameterDescription(size_t i) const = 0;
400
  /// Checks if a parameter has been set explicitly
401
  virtual bool isExplicitlySet(size_t i) const = 0;
402
403
404
405
  /// Get the fitting error for a parameter
  virtual double getError(size_t i) const = 0;
  /// Set the fitting error for a parameter
  virtual void setError(size_t i, double err) = 0;
406

407
  /// Check if a parameter i is fixed
408
  bool isFixed(size_t i) const;
409
410
411
  /// Check if a parameter i is fixed by default (not by user).
  bool isFixedByDefault(size_t i) const;
  /// Removes a parameter i from the list of active
412
  void fix(size_t i, bool isDefault = false);
413
  /// Restores a declared parameter i to the active status
414
  void unfix(size_t i);
415
  /// Fix a parameter
416
  void fixParameter(const std::string &name, bool isDefault = false);
417
418
419
  /// Free a parameter
  void unfixParameter(const std::string &name);
  /// Fix all parameters
420
  void fixAll(bool isDefault = false);
421
422
  /// Free all parameters
  void unfixAll();
423
424
425
426
  /// Free all parameters fixed by default
  void unfixAllDefault();
  /// Fix all active parameters
  void fixAllActive(bool isDefault = false);
427

428
429
430
  /// Return parameter index from a parameter reference. Usefull for constraints
  /// and ties in composite functions
  virtual size_t getParameterIndex(const ParameterReference &ref) const = 0;
431
  /// Return a vector with all parameter names
432
  std::vector<std::string> getParameterNames() const;
433
434
435
436
  //@}

  /** @name Active parameters */
  //@{
437
438
439
440
441
  /// Value of i-th active parameter. Override this method to make fitted
  /// parameters different from the declared
  virtual double activeParameter(size_t i) const;
  /// Set new value of i-th active parameter. Override this method to make
  /// fitted parameters different from the declared
442
443
  virtual void setActiveParameter(size_t i, double value);
  /// Returns the name of active parameter i
444
  virtual std::string nameOfActive(size_t i) const;
445
  /// Returns the name of active parameter i
446
  virtual std::string descriptionOfActive(size_t i) const;
447
  /// Check if an active parameter i is actually active
448
  bool isActive(size_t i) const;
449
450
  //@}

451
452
  /** @name Ties */
  //@{
453
  /// Tie a parameter to other parameters (or a constant)
454
  virtual void tie(const std::string &parName, const std::string &expr,
Roman Tolchenov's avatar
Roman Tolchenov committed
455
                   bool isDefault = false);
456
  /// Add several ties
457
  virtual void addTies(const std::string &ties, bool isDefault = false);
458
  /// Apply the ties
459
  virtual void applyTies();
460
  /// Removes the tie off a parameter
461
  virtual void removeTie(const std::string &parName);
462
  /// Remove all ties
463
  virtual void clearTies();
464
  /// Removes i-th parameter's tie
465
  virtual bool removeTie(size_t i);
466
  /// Get the tie of i-th parameter
467
  virtual ParameterTie *getTie(size_t i) const;
468
  /// Put all ties in order in which they will be applied correctly.
469
  void sortTies();
470
  /// Write a parameter tie to a string
471
  std::string writeTies() const;
472
  //@}
473

474
475
  /** @name Constraints */
  //@{
476
  /// Add a list of conatraints from a string
477
  virtual void addConstraints(const std::string &str, bool isDefault = false);
478
  /// Add a constraint to function
479
  virtual void addConstraint(std::unique_ptr<IConstraint> ic);
480
  /// Get constraint of i-th parameter
481
  virtual IConstraint *getConstraint(size_t i) const;
482
  /// Remove a constraint
483
  virtual void removeConstraint(const std::string &parName);
484
485
  virtual void setConstraintPenaltyFactor(const std::string &parName,
                                          const double &c);
486
  /// Write a parameter constraint to a string
487
  std::string writeConstraints() const;
488
489
  /// Remove all constraints.
  virtual void clearConstraints();
490
  //@}
491

492
493
  /** @name Attributes */
  //@{
494
  /// Returns the number of attributes associated with the function
495
  virtual size_t nAttributes() const;
496
  /// Returns a list of attribute names
497
  virtual std::vector<std::string> getAttributeNames() const;
498
499
  /// Get name of ith attribute
  virtual std::string attributeName(size_t index) const;
500
  /// Return a value of attribute attName
501
  virtual Attribute getAttribute(const std::string &name) const;
502
  /// Set a value to attribute attName
503
  virtual void setAttribute(const std::string &name, const Attribute &);
504
  /// Check if attribute attName exists
505
  virtual bool hasAttribute(const std::string &name) const;
506
  /// Set an attribute value
507
508
  template <typename T>
  void setAttributeValue(const std::string &attName, const T &value) {
509
510
511
512
513
    // Since we can't know T and we would rather not create a universal setter
    // copy and replace in-place
    auto attr = getAttribute(attName);
    attr.setValue(value);
    setAttribute(attName, attr);
514
515
516
  }
  void setAttributeValue(const std::string &attName, const char *value);
  void setAttributeValue(const std::string &attName, const std::string &value);
517
518
  //@}

Roman Tolchenov's avatar
Roman Tolchenov committed
519
  /// Returns the pointer to i-th child function
520
  virtual std::shared_ptr<IFunction> getFunction(size_t i) const;
Roman Tolchenov's avatar
Roman Tolchenov committed
521
522
  /// Number of child functions
  virtual std::size_t nFunctions() const { return 0; }
523
  /// Set up the function for a fit.
524
  virtual void setUpForFit();
525
526
  /// Get number of values for a given domain.
  virtual size_t getValuesSize(const FunctionDomain &domain) const;
527
528
529
  /// Get number of domains required by this function
  virtual size_t getNumberDomains() const;
  /// Split this function (if needed) into a list of independent functions.
530
  virtual std::vector<std::shared_ptr<IFunction>>
531
  createEquivalentFunctions() const;
532
  /// Calculate numerical derivatives
533
  void calNumericalDeriv(const FunctionDomain &domain, Jacobian &jacobian);
534
  /// Set the covariance matrix
David Fairbrother's avatar
David Fairbrother committed
535
  void
536
  setCovarianceMatrix(const std::shared_ptr<Kernel::Matrix<double>> &covar);
537
  /// Get the covariance matrix
538
  std::shared_ptr<const Kernel::Matrix<double>> getCovarianceMatrix() const {
539
540
    return m_covar;
  }
541
  /// Set the chi^2
542
  void setChiSquared(double chi2) { m_chiSquared = chi2; }
543
  /// Get the chi^2
544
  double getChiSquared() const { return m_chiSquared; }
545

546
  /// Set the parallel hint
547
  void setParallel(bool on) { m_isParallel = on; }
548
  /// Get the parallel hint
549
  bool isParallel() const { return m_isParallel; }
550

551
  /// Set a function handler
552
  void setHandler(std::unique_ptr<FunctionHandler> handler);
553
  /// Return the handler
Sam Jenkins's avatar
Sam Jenkins committed
554
  FunctionHandler *getHandler() const { return m_handler.get(); }
555

556
557
558
  /// Describe parameter status in relation to fitting:
  /// Active: Fit varies such parameter directly.
  /// Fixed:  Value doesn't change during fit.
559
560
  /// FixedByDefault:  Fixed by default, don't show in ties of
  ///         the output string.
561
  /// Tied:   Value depends on values of other parameters.
562
  enum ParameterStatus { Active, Fixed, FixedByDefault, Tied };
563
564
565
566
567
568
  /// Change status of parameter
  virtual void setParameterStatus(size_t i, ParameterStatus status) = 0;
  /// Get status of parameter
  virtual ParameterStatus getParameterStatus(size_t i) const = 0;

protected:
569
  /// Function initialization. Declare function parameters in this method.
570
  virtual void init();
571
  /// Declare a new parameter
572
573
  virtual void declareParameter(const std::string &name, double initValue = 0,
                                const std::string &description = "") = 0;
574

575
  /// Convert a value from one unit (inUnit) to unit defined in workspace (ws)
576
  double convertValue(double value, Kernel::Unit_sptr &outUnit,
577
                      const std::shared_ptr<const MatrixWorkspace> &ws,
578
579
580
                      size_t wsIndex) const;

  void convertValue(std::vector<double> &values, Kernel::Unit_sptr &outUnit,
581
                    const std::shared_ptr<const MatrixWorkspace> &ws,
582
                    size_t wsIndex) const;
583

584
585
586
587
588
589
  /// Override to declare function attributes
  virtual void declareAttributes() {}
  /// Override to declare function parameters
  virtual void declareParameters() {}

  /// Declare a single attribute
590
  virtual void declareAttribute(const std::string &name,
Stephen's avatar
Stephen committed
591
                                const API::IFunction::Attribute &defaultValue);
592
  /// Store an attribute's value
593
594
  void storeAttributeValue(const std::string &name,
                           const API::IFunction::Attribute &value);
595
596
597
  /// A read-only ("mutable") attribute can be stored in a const method
  void storeReadOnlyAttribute(const std::string &name,
                              const API::IFunction::Attribute &value) const;
598
599
  /// Add a new tie. Derived classes must provide storage for ties
  virtual void addTie(std::unique_ptr<ParameterTie> tie);
600
601
  bool hasOrderedTies() const;
  void applyOrderedTies();
602
603
604
  /// Writes itself into a string
  virtual std::string
  writeToString(const std::string &parentLocalAttributesStr = "") const;
605

606
607
  friend class ParameterTie;
  friend class CompositeFunction;
608
  friend class FunctionParameterDecorator;
609
  friend class FunctionGenerator;
610

611
612
  /// Flag to hint that the function is being used in parallel computations
  bool m_isParallel;
613

614
  /// Pointer to a function handler
615
  std::unique_ptr<FunctionHandler> m_handler;
616

617
  /// Pointer to the progress handler
618
  std::shared_ptr<Kernel::ProgressBase> m_progReporter;
619

620
621
622
private:
  /// The declared attributes
  std::map<std::string, API::IFunction::Attribute> m_attrs;
623
  /// The covariance matrix of the fitting parameters
624
  std::shared_ptr<Kernel::Matrix<double>> m_covar;
625
626
  /// The chi-squared of the last fit
  double m_chiSquared;
627
  /// Holds parameter ties
628
629
630
  std::vector<std::unique_ptr<ParameterTie>> m_ties;
  /// Holds the constraints added to function
  std::vector<std::unique_ptr<IConstraint>> m_constraints;
631
  /// Ties ordered in order of correct application
Roman Tolchenov's avatar
Roman Tolchenov committed
632
  std::vector<ParameterTie *> m_orderedTies;
633
634
};

635
/// shared pointer to the function base class
636
using IFunction_sptr = std::shared_ptr<IFunction>;
637
/// shared pointer to the function base class (const version)
638
using IFunction_const_sptr = std::shared_ptr<const IFunction>;
639

640
641
642
643
644
645
646
/**
 * Classes inherited from FunctionHandler will handle the function.
 * The intended purpose is to help with displaying nested composite
 * functions in a tree view. This way a display handler shows only
 * single function and there is no need to duplicate the function tree
 * structure.
 */
647
class FunctionHandler {
648
649
public:
  /// Constructor
David Fairbrother's avatar
David Fairbrother committed
650
  FunctionHandler(IFunction_sptr fun) : m_fun(std::move(fun)) {}
651
  /// Virtual destructor
652
  virtual ~FunctionHandler() = default;
653
654
655
  /// abstract init method. It is called after setting handler to the function
  virtual void init() = 0;
  /// Return the handled function
656
657
  IFunction_sptr function() const { return m_fun; }

658
protected:
659
  IFunction_sptr m_fun; ///< pointer to the handled function
660
661
};

662
663
} // namespace API
} // namespace Mantid