Skip to main content

Come analyze HEASARC, IRSA, and MAST data in the cloud! The Fornax Initiative is now welcoming all interested beta users.

Xspec Home Page

Writing new mixing models

Mixing models are fundamentally different from the other kinds of models since they apply a transformation to a set of modeled fluxes (as enumerated by the spectra in the fit), rather than modify the flux designed to fit a single spectrum. The need to store temporary results, as well as the requirements of the model calculation, lead to many workspace arrays: further, the transformations applied are often fixed during a fit, or can be split to avoid redundant calculations into parts that are fixed and parts that change during iteration in order. XSPEC's internal organization (data structures) can be mapped straightforwardly to the requirements of these models so to implement them efficiently and handle memory allocation, we recommend that mixing models be written in C++ or C. At present only a C++ implementation is available.

Mixing models are listed in a mixmodel.dat file in the src/manager directory. This is similar to the standard model.dat file except that the class required to run the model is preceded by U_. If a template function is used to run multiple models (e.g. U_Psf) then the template value is added (e.g. U_psf<XMM>). Finally, if other header classes are required to build the models then their names should be included in parentheses. For instance the clmass model requires Potential.h and Potential.cxx so this is indicated by U_MIClusterMassModel(Potential).

The mixing model class requires a constructor taking a single argument:

 ModelClassName (const string& name);
and three public methods
 void initialize (const std::vector<Real>& params, const
                  IntegerVector& specNums, const std::string& modelName);
 void perform (const EnergyPointer& energy, const std::vector<Real>& params,
               GroupFluxContainer& flux, GroupFluxContainer& fluxVariance);
 void initializeForFit (const std::vector<Real>& params, bool paramsAreFrozen);
where initialize is run the first time the model is called, initializeForFit at the start of any fit command, and perform for each model calculation.

The MixUtility class from which all these mixing model classes inherit contains a number of members and methods which can make writing mixing models easier. If the following arrays are set then the doMix method does all the hard work and just needs to be called from perform.

 // sets of spectrum numbers to be mixed together. each set is in the order
 // of the mixing matrix
 std::vector<IntegerVector> m_specNumsMixSets;
 // mixing factors NxNxNe. note that the outer vector is the spectrum number
 // of the output and the inner vector is the spectrum number of the input
 std::vector<std::vector<RealArray> > m_mixingFactors;
 // energies if the mixing factors are energy-dependent. this must be the same
 // size as the RealArray in m_mixingFactors
 RealArray m_mixingEnergies;

The useful MixUtility methods are:

  // do all the hard work to mix the models
  void doMix(const EnergyPointer& energy, GroupFluxContainer& flux);

  // return the total number of data groups
  size_t numberOfDataGroups() const;
  // return the total number of spectra
  size_t numberOfSpectra() const;
  // return true if there is valid data, false if not
  bool isAnyData() const;

  // return the datagroup number (1-based) for the spectrum (1-based)
  size_t dataGroupNumber(const size_t spectrumNumber) const;

  // return a map of all the xflt names and values for the spectrum
  std::map<string, Real> allXfltValues(const size_t
                                       spectrumNumber) const;
  // return the value for the input xflt name and spectrum
  Real xfltValue(const size_t spectrumNumber,
                 const string xfltName) const;
  // return the value for the input xflt number and spectrum
  Real xfltValue(const size_t spectrumNumber,
                 const int xfltNumber) const;
  // return true if the intput xflt name exists in the spectrum
  bool isInXflt(const size_t spectrumNumber, const string xfltName) const;
  // return true if the intput xflt number exists in the spectrum
  bool isInXflt(const size_t spectrumNumber, const int xfltNumber) const;

  // return the name of the spectrum (1-based)
  string dataName(const size_t spectrumNumber) const;
  // return the complete pathname of the spectrum (1-based)
  string fullPathName(const size_t spectrumNumber) const;

  // return the source number (1-based) for this model
  size_t sourceNumber() const;
  // return the data group map for this source number
  const std::map<size_t, size_t>& sourceToDataGroups(
                     const size_t sourceNumber) const;
  // return true if the spectrum is active for the source number
  bool isSpectrumActive(const size_t spectrumNumber,
                        const size_t sourceNumber) const;

  // return the response name for the spectrum and source number
  string rmfName(const size_t spectrumNumber,
                 const size_t sourceNumber) const;

  // return the EnergyPointer object for this model
  EnergyPointer allEnergies();

Users considering adding new mixing model types should contact the developers of XSPEC at xspechelp@athena.gsfc.nasa.gov.