GPLIB++
C1DMTObjective.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <algorithm>
3 #include <functional>
4 #include <numeric>
5 #include <cassert>
6 #include <boost/numeric/ublas/io.hpp>
7 #include <boost/function.hpp>
8 #include <boost/bind.hpp>
9 #include "miscfunc.h"
10 #include "C1DMTObjective.h"
11 #include "Adaptors.h"
12 #include "FatalException.h"
13 
14 namespace ublas = boost::numeric::ublas;
15 using namespace std;
16 
17 namespace gplib
18  {
19  C1DMTObjective::C1DMTObjective(const MTStation &LocalMTData) :
20  // we always need a reference to the data to fit and an object to calculate synthetic data
21  MTData(LocalMTData)
22  {
23  // if nothing will be set in SetFitParameters
24  // we use the xy phase by default
25  DataFunctions.push_back(&MTTensor::GetPhixy);
26  ErrorFunctions.push_back(&MTTensor::GetdPhixy);
27  ErrorLevels.push_back(0.01);
28  FitparametersSet = false; //but we want to know whether the fit parameters have been set to issue a warning
29  }
30 
32  {
33  }
34 
36  PlottableObjective(Old), DataFunctions(Old.DataFunctions),
37  ErrorFunctions(Old.ErrorFunctions), ErrorLevels(Old.ErrorLevels),
38  FitparametersSet(Old.FitparametersSet), MTData(Old.MTData)
39  {
40  }
41 
43  {
44  if (this == &source)
45  return *this;
47  DataFunctions.resize(source.DataFunctions.size());
48  ErrorFunctions.resize(source.ErrorFunctions.size());
49  ErrorLevels.resize(source.ErrorLevels.size());
50  copy(source.DataFunctions.begin(), source.DataFunctions.end(),
51  DataFunctions.begin());
52  copy(source.ErrorFunctions.begin(), source.ErrorFunctions.end(),
53  ErrorFunctions.begin());
54  copy(source.ErrorLevels.begin(), source.ErrorLevels.end(),
55  ErrorLevels.begin());
56  MTData = source.MTData;
57  FitparametersSet = source.FitparametersSet;
58  return *this;
59  }
60 
61  /*! Instead of seperate access functions, we force the user to set all of them if he doesn't want defaults
62  *
63  * This functions takes three parameters
64  * @param TheDataV A vector containing pointers to functions that return the data to fit as a double when given a *MTTensor
65  * @param TheErrorV A similar vector of pointers to functions that return the corresponding error
66  * @param TheErrLevel The relative errorlevel that corresponds to the data function
67  *
68  * All three vectors have to be of the same size and have at least one entry to work
69  */
71  const datafuncvector_t TheErrorV, const std::vector<double> TheErrLevel)
72  {
73  //we have to make sure all vectors have the same size
74  if (TheDataV.size() != TheErrorV.size() || TheDataV.size()
75  != TheErrLevel.size())
76  throw FatalException(
77  "Vectors of fit parameters have incompatible size !");
78  if (TheDataV.empty())
79  throw FatalException("Cannot work with empty vectors !");
80  //we resize and copy, so we overwrite anything that was in the vector before
81  DataFunctions.resize(TheDataV.size());
82  ErrorFunctions.resize(TheErrorV.size());
83  ErrorLevels.resize(TheErrLevel.size());
84  copy(TheDataV.begin(), TheDataV.end(), DataFunctions.begin());
85  copy(TheErrorV.begin(), TheErrorV.end(), ErrorFunctions.begin());
86  copy(TheErrLevel.begin(), TheErrLevel.end(), ErrorLevels.begin());
87  FitparametersSet = true; //signal that the parameters have been selected by the user
88  }
89 
90  /*! Add a new type of MT data to the vector of quantities to fit. The first call overrides
91  * the default xy phase that is set by the constructor.
92  * @param TheDataFunc The data to fit. A reference to function that takes a MTTensor* const and returns a double. e.g. &MTTensor::GetPhixy to fit xy phase
93  * @param TheErrorFunc The error associated with the data. Also a reference to function that takes a MTTensor* const and returns a double. e.g. &MTTensor::GetdPhixy
94  * @param TheErrLevel The relative error floor for this type of data
95  */
97  const datafunc_t TheErrorFunc, const double TheErrLevel)
98  {
99  if (!FitparametersSet) // if we didn't set anything before
100  {
101  DataFunctions.clear();
102  ErrorFunctions.clear();
103  ErrorLevels.clear();
104  DataFunctions.push_back(TheDataFunc); //we overwrite the defaults
105  ErrorFunctions.push_back(TheErrorFunc);
106  ErrorLevels.push_back(TheErrLevel);
107  FitparametersSet = true;
108  }
109  else //if we have set something before
110  {
111  DataFunctions.push_back(TheDataFunc); // we append the new values
112  ErrorFunctions.push_back(TheErrorFunc);
113  ErrorLevels.push_back(TheErrLevel);
114  }
115  }
116 
117  /*! Calculate synthetics from the model given by member and compare with Data given
118  * the fitparameters
119  */
121  {
122 
123  double returnvalue = 0; // init misfit value
124 
125  if (!FitparametersSet)
126  {
127  FitparametersSet = true; // we only issue this warning once
128  cerr
129  << "Warning errorlevel and Fitparameters not set, using hardcoded default ! "
130  << endl;
131  cerr << "You should change your program !" << endl;
132  }
133  //if we didn't set the frequencies before
134  if (GetMTSynth().GetFrequencies().empty())
135  {
136  //make sure the modelled frequencies match the data frequencies
138  }
139  //calculate the synthetic data for the model
140  CalcSynthData(member);
141 
142  //the number of data we fit, depends on which aspects of the tensor we fit
143  unsigned int datacount = 0;
144  double currdata = 0.0;
145  typedef vector<MTTensor>::const_iterator tensorit_t; // local convenience typedef
146  typedef datafuncvector_t::iterator funcit_t;
147  //we have to step through all types of data to fit
148  //we achieve this vectors of function that return the necessary quantities and their errors
149  //for each tensor element we call those two functions
150  funcit_t dfuncit = DataFunctions.begin();
151  funcit_t efuncit = ErrorFunctions.begin();
152  //we can have a different error floor for every type of data
153  std::vector<double>::const_iterator elevelit = ErrorLevels.begin();
154  const unsigned int ndata = DataFunctions.size()
155  * MTData.GetMTData().size();
156  SetMisfit().resize(ndata); //make sure Misfit in base class can hold enough elements
157  SetSynthData().resize(ndata); // and same for data
158 
159  //for all types of parameters to calculate misfit for
160  //step through the frequencies and add up the misfit
161  for (/* init done above*/; dfuncit != DataFunctions.end(); ++dfuncit, ++efuncit, ++elevelit)
162  {
163  for (tensorit_t datait = MTData.GetMTData().begin(), synthit =
164  GetMTSynth().GetMTData().begin(); datait
165  < MTData.GetMTData().end(); ++datait, ++synthit) // go through the frequencies
166  {
167  //calculate the current parameter using the function pointer in the vector DataFunctions
168  //the function calls through iterators with elements that are referenced by iterators
169  //are cryptic so we store them in temporary variables with better names
170  currdata = (*dfuncit)(&*datait);
171  const double currpredicted = (*dfuncit)(&*synthit);
172  const double currerror = (*efuncit)(&*datait);
173  const double errorlevel = *elevelit;
174  returnvalue += CalcMisfit(currdata, currpredicted, currerror,
175  errorlevel, datacount);
176  ++datacount;
177  }
178  }
179  SetRMS(std::pow(returnvalue / datacount, 1.0 / GetFitExponent()));
180  }
181 
182  //! All calculation has been done in SafeParallel we only return the stored result
184  {
185  return GetRMS();
186  }
187  }
void AppendFitParameters(const datafunc_t TheDataFunc, const datafunc_t TheErrorFunc, const double TheErrLevel)
boost::function< double(const MTTensor *const )> datafunc_t
A function that returns a real valued quantity calculated from an MT impedance tensor.
ublas::vector< double > ttranscribed
Definition: gentypes.h:21
This only adds a few plotting functions to GeneralObjective to define a common interface.
double GetPhixy() const
Definition: MTTensor.h:207
C1DMTObjective(const MTStation &LocalMTData)
We need data to fit for any objective function, so we want it as constructor parameter, but no implicit conversion.
int GetFitExponent()
Get the Fit exponent.
double CalcMisfit(const double measured, const double predicted, const double measerror, const double errorlevel, const int index)
The class MTStation is used to store the transfer functions and related information for a MT-site...
Definition: MTStation.h:17
CMTStation MTData
Definition: cadijoint.cpp:15
double GetRMS()
Get the current RMS.
C1DMTObjective & operator=(const C1DMTObjective &source)
tdata & SetSynthData()
Only derived classes can write access the Synthetic data.
tmisfit & SetMisfit()
Only derived classes can write access the Misfit.
std::vector< datafunc_t > datafuncvector_t
A vector of MT data functions. This is used to store the types of data to fit.
PlottableObjective & operator=(const PlottableObjective &source)
void SetFitParameters(const datafuncvector_t TheDataV, const datafuncvector_t TheErrorV, const std::vector< double > TheErrLevel)
function to set the parameters that determine the type of fit
const std::vector< MTTensor > & GetMTData() const
Get the full vector of Tensor elements read only.
Definition: MTStation.h:119
virtual MTStation & GetMTSynth()=0
double GetdPhixy() const
Definition: MTTensor.h:258
virtual double PostParallel(const ttranscribed &member)
All calculation has been done in SafeParallel we only return the stored result.
virtual void SafeParallel(const ttranscribed &member)
Calc misfit for a model given by member.
trealdata GetFrequencies() const
return the available frequencies in a single vector
Definition: MTStation.cpp:136
C1DMTObjective is the base class for MT misfit calculations from 1D models, it provides common functi...
void SetRMS(const double x)
void SetFrequencies(const trealdata &freqs)
Set the frequencies of the tensor elements, invalidates the previously stored impedance data...
Definition: MTStation.cpp:144
The basic exception class for all errors that arise in gplib.