CFitDictionary

Name

CFitDictionary -- Fitting subsystem dictionary.

Synopsis


#include <CFitDictionary.h>

class CFitDictionary {

public:
  typedef std::map<std::string, CSpectrumFit*> FitMap;
  typedef FitMap::iterator      iterator;

  class CObserver {
  public:
    virtual void Add(CSpectrumFit& fit) =0;
    virtual void Delete(CSpectrumFit& fit) = 0;
    virtual void Update(CSpectrumFit& fit) = 0;

  };

public:
  static CFitDictionary& getInstance();
  void add(CSpectrumFit& fit);
  void addOrReplace(CSpectrumFit& fit);
  void Delete(std::string name);

  iterator begin();
  iterator end();
  size_t   size();
  iterator find(std::string name);
  void     erase(iterator here);
  void     erase(iterator first, iterator last);

  void updateFits(std::string name=std::string("*")); 

  void addObserver(CObserver& obs);
  void removeObserver(CObserver& obs);

        

DESCRIPTION

The CFitDictionary defines a singleton class. The provides a dictionary of fits derived from CSpectrumFit and is the dictionary SpecTcl uses to store its fits. In addition to supporting addition and removal operations, the iterator, oberver and search operations are supported. It is also possible to request the dictionary update fits that match some pattern.

Note that the SpecTcl CHistogrammer class establishes an observer so that it can ensure that Xamine can display any fits that have been defined on displayed spectra. Note that the Spectra displayer does not yet support the display of fit lines.

METHODS

static CFitDictionary& getInstance();

Gets a pointer to the singleton instance of the fit dictionary. This singleton uses lazy creation in that the first invocation of getInstance is what actually creates the fit dictionary singleton instance.

void add(CSpectrumFit& fit);

Adds a new fit to the dictionary. The fit must live for the life of its existence in the dictionary as it's not cloned. The name of the fit is taken from the fit itself.

If a fit by this name already exists, an exception is thrown. If the fit is successfully added, all observers are informed of this via their Add method.

void addOrReplace(CSpectrumFit& fit);

Adds the fit fit to the fit dictionary. The name assigned to the fit comes from the fit itself. If the fit already exists, the previous fit is replaced in the dictionary wih fit.

This is treated as an addition and therefore the observers are notified via their Add methods.

void Delete(std::string name);

Removes the fit named name from the dictinoary It's still up to the clients of the dictionary to manage the storage for this fit. If fits are dynamically allocated, removal/deletion should take the form of using find to get a pointer to the fit, deleting the fit from the dictionary (either with erase or Delete), and then using delete to delete the actual fit object.

If there is no fit named name in the dictionary,

iterator begin(); , iterator end(); , size_t size();

These methods implement an interation interface for the fits. The iterators return pointer like objects to objects of the type: std::pair<std:;string, CSpectrumFit>

begin returns an interator that points to the first item in the fit dictionary container. Incrementing this object steps sequentially through the container until the object is equal to the value returned by end. At that point the iteration over the container is complete.

size returns the number of objects in the container.

iterator find(std::string name);

Returns an iterator to the item in the gate dictionary container that has a name; name. If there is no matching item in the gate dictionary container, an iterator that is equal to the one returned by end is returned. See begin above for a description of the iterator object.

void erase(iterator here);

Given an iterator into the gate container dictionary, removes that entry from the dictionary. Note that the gate is not deleted. If the gate was dynamically created the client must delete it. Suppose we want to delete the gate named deleteme and free its storage. This can be done as follows:


CFitDictionary* pDict = CFitDictionary::getInstance();
CFitDictionary::iterator p = pDict->find("deleteme");
if (p != pDict->end()) {
    CSpectrumFit* pFit = p->second;
    pDict->erase(p);
    delete pFit;
} else {
   // Action to take when the fit does not exist.
}
                        

void updateFits(std::string name = std::string("*"));

Updates the fits that have names matching the glob pattern name. Note that this defaults to * which matches all fits.

void addObserver(CObserver& obs);

Adds an observer to the dictionary. The observer object methods will be invoked as a result of specific actions performed by the dictionary. See Nested Types and Classes for a description of observers and their methods.

void removeObserver(CObserver& obs);

Removes the observer obs from the dictionary. Once done, obs will no longer receive method calls from the dictionary. Removing the observer does not destroy it. That is the responsibility of the dictionary client software.

Nested Types and Classes

CFitDictionary defines two types and a an abstract base class. The types are used to support dictionary iterastion and the class to support the observer pattern.

CSpectrumDictionary::FitMap is the type of the container used to store the fit dictionary. While this is currently an std::map, the only thing you should assume is that this object is an associative container of CSpectrumFit* with keys that are std::string objects. The keys are the name of the fit.

CSpectrumDictionary::iterator is an interator into the fit container. As with all iterators for STL associative containers it is a pointer-like object. Dereferencing a ::CSpectrumDictionary::iterator provides a reference to a std::pair<std::string, CSpectrumFit*>. This is also consistent with STL iterators into associative containers.

Incrementing an instance of CSpectrumDictionary::iterator produces a pointer-like object that points to the "next" item in the dictionary. The special iterator value returned by end can be thought of as pointing just off the end of the container. begin can be thought of pointing at the first item in the container.

Therefore typical dictionary iteration follows the pattern below:


CFitDictionary* pDict = CFitDictionary::getInstance();
for (auto p = pDict->begin(); p != pDict->end(); p++) {
    std::string fitname = p->first;
    CSpectrumfit* pFit  = p->second;
    
    doSomethingWithTheFitAndOrName(fitname, pFit);
}
            

Note that this sort of iteration is also perfectly compatible with standard library generic algorithms like std::for_each.

The CFitDictionary supports the observer pattern. The observer pattern (see https://en.wikipedia.org/wiki/Observer_pattern) provides a mechanism that allows other objects to be informed when important state changes occur in CFitDictionary. Observers are objects in an ordered list that are derived from the abstract base class CFitDictionary::CObserver. This abstract base class provides a set of method definitions that define the set of events that will be observed.

The definition of the class is shown below (note this is defined within the definition of CFitDictionary):


class CObserver {
public:
  virtual void Add(CSpectrumFit& fit) =0;
  virtual void Delete(CSpectrumFit& fit) = 0;
  virtual void Update(CSpectrumFit& fit) = 0;

};            
                
            

You can observe the CFitDictionary by

  1. Deriving a class from CFitDictionary::CObserver

  2. Creating an instance of that class that lives for as long as you want the observation to continue.

  3. Using addObserver to add that object to the ordered list of observers.

  4. If the observer is ever no longer needed, use removeObserver to remove it after which, if appropriate you should ensure the observer's destruction.

The methods you must implement in your observer are:

virtual =0 void Add(CSpectrumFit& fit);

This method is invoked when a fit as been successfully added to the dictionary. fit is a referenceto the fit just added. Note that since fit is a NamedObject; getName can be used to get the fit's name if needed.

virtual = 0 void Delete(CSpectrumFit& fit);

This method is called when fit is about to be erased from the fit dictionary. When called, the fit is still in the dictionary. Once all observers are run, the fit is erased from the dictionary.

virtual = 0 void Update(CSpectrumFit& fit);

This method is invoked when fit has been updated. By update we mean that fit has been recomputed in light of the current spectrum data. The observer is invoked after the update.