#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);
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.
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:
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.
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
Deriving a class from CFitDictionary::CObserver
Creating an instance of that class that lives for as long as you want the observation to continue.
Using addObserver
to add that object
to the ordered list of observers.
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.