Anaphe Home Page Reference Documentation

Main Page     Namespaces     Classes     Source Code    

Translator.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //
00004 // (c) CERN, Geneva
00005 //
00006 
00007 
00008 
00009 
00010 //
00011 // Implemented as two DataXML::DataObjects to hold the trees.
00012 //
00013 // Writing:
00014 // Tree created at first write, then extra histos are added as children
00015 // until flush() dumps the whole tree to the stream and then deletes it.
00016 //
00017 // Reading:
00018 // The WHOLE tree is read in from the stream as soon as setInputStream(s) 
00019 // is called. Then there are three "iterators" which point to the next
00020 // histo of a given dimensionality. Calling read(hp) fills it into hp (the 
00021 // HistoParametersXD object) and increments it. If it points to children.end()
00022 // then it returns false and does nothing.
00023 //
00024 // The only thing to know is that DataXML makes a tree. The root is the <aida>
00025 // element, and then the children are the histograms (plus a <histoType> element,
00026 // whose usefulness is unclear). Each histo has children (the axes, data etc) and
00027 // so on.
00028 //
00029 // MS 20/12/01
00030 //
00031 
00032 
00033 
00034 
00035 #include <algorithm>
00036 #include "Interfaces/IAxis.h"
00037 #include "Translator.h"
00038 
00039 
00040 
00041 
00042 namespace Anaphe {
00043 
00044 
00045 
00046 
00048 //                              //
00049 // static members of Translator //
00050 //                              //
00052 
00053 const int              Translator::constant_UNDERFLOW          = -1;
00054 const int              Translator::constant_OVERFLOW           = -2;
00055 const int              Translator::RUBBISH            = -999;
00056 const int              Translator::SCI_PRECISION      = 8;
00057 const double           Translator::ROUNDOFF_TOLERANCE = 1.0E-9;
00058 const AIDA_STD::string Translator::XML_VERSION        = "1.0";
00059 const AIDA_STD::string Translator::ENCODING_TYPE      = "ISO-8859-1";
00060 
00061 
00062 
00063 
00065 //                                 //
00066 // De/Constructor(s) of Translator //
00067 //                                 //
00069 
00070 Translator::Translator(void)
00071   : silent      (false),
00072     iXmlStream  (0),
00073     iRootElement(0),
00074     iHisto1DIt  (0),
00075     iHisto2DIt  (0),
00076     iHisto3DIt  (0),
00077     oStream     (0),
00078     oRootElement(0)
00079 {
00080   // nop
00081 }
00082 
00083 
00084 
00085 
00086 Translator::Translator(const Translator& rhs)
00087   : silent      (rhs.silent),
00088     iXmlStream  (0),
00089     iRootElement(0),
00090     iHisto1DIt  (0),
00091     iHisto2DIt  (0),
00092     iHisto3DIt  (0),
00093     oStream     (0),
00094     oRootElement(0)
00095 {
00096   // nop
00097 }
00098 
00099 
00100 
00101 
00102 Translator::~Translator(void)
00103 {
00104   flush();
00105   removeOTree();
00106   removeITree();
00107 }
00108 
00109 
00110 
00111 
00112 const Translator& Translator::operator=(const Translator& rhs)
00113 {
00114   // flush() is not called! assignment loses the contents of the
00115   // writing tree. At the moment the one from the rhs is not copied!
00116   removeOTree();
00117   removeITree();
00118   silent = rhs.silent;
00119   return *this;
00120 }
00121 
00122 
00123 
00124 
00126 //                              //
00127 // public methods of Translator //
00128 //                              //
00130 
00131 void Translator::noWarnings(const bool& b)
00132 {
00133   silent = b;
00134 }
00135 
00136 
00137 
00138 
00139 bool Translator::setInputStream(AIDA_STD::istream& s)
00140 {
00141   removeITree();
00142   return createNewITree(s);
00143 }
00144 
00145 
00146 
00147 
00148 bool Translator::setOutputStream(AIDA_STD::ostream& s)
00149 {
00150   oStream = &s;
00151   return true; //ND check stream state?
00152 }
00153 
00154 
00155 
00156 
00157 bool Translator::read(HistoParameters1D& hp)
00158 {
00159   if (!iRootElement) return false;
00160   while (iHisto1DIt != iRootElement->children().end()) {
00161     if (dimensionality(iHisto1DIt) == 1) readHistoElement(iHisto1DIt, hp);
00162     ++iHisto1DIt;
00163     if (goodParameters(hp)) return true;
00164   }
00165   return false;
00166 }
00167 
00168 
00169 
00170 
00171 bool Translator::read(HistoParameters2D& hp)
00172 {
00173   if (!iRootElement) return false;
00174   while (iHisto2DIt != iRootElement->children().end()) {
00175     if (dimensionality(iHisto2DIt) == 2) readHistoElement(iHisto2DIt, hp);
00176     ++iHisto2DIt;
00177     if (goodParameters(hp)) return true;
00178   }
00179   return false;
00180 }
00181 
00182 
00183 
00184 
00185 bool Translator::read(HistoParameters3D& hp)
00186 {
00187   if (!iRootElement) return false;
00188   while (iHisto3DIt != iRootElement->children().end()) {
00189     if (dimensionality(iHisto3DIt) == 3) readHistoElement(iHisto3DIt, hp);
00190     ++iHisto3DIt;
00191     if (goodParameters(hp)) return true;
00192   }
00193   return false; 
00194 }
00195 
00196 
00197 
00198 
00199 bool Translator::write(const IHistogram1D& h)
00200 {
00201   return genericWrite(h);
00202 }
00203 
00204 
00205 
00206 
00207 bool Translator::write(const IHistogram2D& h)
00208 {
00209   return genericWrite(h);
00210 }
00211 
00212 
00213 
00214 
00215 bool Translator::write(const IHistogram3D& h)
00216 {
00217   return genericWrite(h);
00218 }
00219 
00220 
00221 
00222 
00223 void Translator::flush(void)
00224 {
00225   if (!oStream || !oRootElement) return;
00226   writeHeader(*oStream);
00227   DataXML::OutputXMLStream oxml(*oStream);
00228   oxml.write(*oRootElement);
00229   writeFooter(*oStream);
00230   removeOTree();
00231 }
00232 
00233 
00234 
00235 
00237 //                               //
00238 // private methods of Translator //
00239 //                               //
00241 
00242 template<class HistoType>
00243 bool Translator::genericWrite(const HistoType& h)
00244 {
00245   // append a new histo to the writing tree
00246   // (create a new tree first, if necessary)
00247   if (!oStream) { noOutputStreamError();  return false; }
00248   else {
00249     if (!oRootElement) createNewOTree();
00250     if (!oRootElement) return false;
00251     else return appendHisto(h,oRootElement);
00252   }
00253 }
00254 
00255 
00256 
00257 
00258 template<class HistoType>
00259 bool Translator::appendHisto(const HistoType& h, const ElementIterator& parent)
00260 {
00261   DataXML::DataObject histoElement;
00262   bool allOK = writeHistoElement(h, &histoElement);
00263   if (!allOK) return false;
00264   else {
00265     parent->appendChild(histoElement);
00266     return true;
00267   }
00268 }
00269 
00270 
00271 
00272 
00273 template<class FP>
00274 AIDA_STD::string Translator::toString(const FP& number) const
00275 {
00276   // generic method for floating point types
00277   AIDA_STD::ostrstream buf;
00278   buf.setf(AIDA_STD::ios::scientific);
00279   buf.precision(SCI_PRECISION);
00280   buf << number << AIDA_STD::ends;
00281   AIDA_STD::string ret = buf.str();
00282   buf.freeze(false);
00283   return ret;
00284 }
00285 
00286 
00287 
00288 
00289 AIDA_STD::string Translator::toString(const int& number) const
00290 {
00291   // specialisation for integers
00292   AIDA_STD::ostrstream buf;
00293   buf << number << AIDA_STD::ends;
00294   AIDA_STD::string ret = buf.str();
00295   buf.freeze(false);
00296   return ret;
00297 }
00298 
00299 
00300 
00301 
00302 void Translator::removeITree(void)
00303 {
00304   if (iXmlStream) { delete iXmlStream; iXmlStream = 0; }
00305   iRootElement = 0;
00306   resetIterators();
00307 }
00308 
00309 
00310 
00311 
00312 void Translator::removeOTree(void)
00313 {
00314   if (oRootElement) { delete oRootElement; oRootElement = 0; }
00315 }
00316 
00317 
00318 
00319 
00320 bool Translator::createNewITree(AIDA_STD::istream& s)
00321 {
00322   removeITree();
00323   iXmlStream = new DataXML::InputXMLStream;
00324   if (!iXmlStream) return false;
00325   iRootElement = &(iXmlStream->read(s));
00326   if (!iXmlStream->success()) { 
00327     removeITree(); 
00328     badInputStreamError(); 
00329     return false; 
00330   }
00331   else if (iRootElement->name() != "aida") {
00332     removeITree();
00333     wrongDocTypeError(); 
00334     return false; 
00335   }
00336   else {
00337     resetIterators();
00338     return true;
00339   }
00340 }
00341 
00342 
00343 
00344 
00345 bool Translator::createNewOTree(void)
00346 {
00347   removeOTree();
00348   oRootElement = new DataXML::DataObject;
00349   if (!oRootElement) return false;
00350   oRootElement->setName("aida");
00351   appendHistoTypeElement(oRootElement);
00352   return true;
00353 }
00354 
00355 
00356 
00357 
00358 void Translator::appendHistoTypeElement(const ElementIterator& parent)
00359 {
00360   // add the <histoType> element to the writing tree
00361   if (!parent) return;
00362   DataXML::DataObject hto;
00363   hto.setName("histoType");
00364   hto.setAttribute("package", "Anaphe");
00365   parent->appendChild(hto);
00366 }
00367 
00368 
00369 
00370 
00371 bool Translator::writeHistoElement(const IHistogram1D& h, const ElementIterator& histoElement)
00372 {
00373   if (!histoElement) return false;
00374   histoElement->setName("histogram1d");
00375   setTitle(h, histoElement);
00376   if (!setAxes (h, histoElement)) return false;
00377   if (!setStats(h, histoElement)) return false;
00378   if (!setData (h, histoElement)) return false;
00379   return true;
00380 }
00381 
00382 
00383 
00384 
00385 bool Translator::writeHistoElement(const IHistogram2D& h, const ElementIterator& histoElement)
00386 {
00387   if (!histoElement) return false;
00388   histoElement->setName("histogram2d");
00389   setTitle(h, histoElement);
00390   if (!setAxes (h, histoElement)) return false;
00391   if (!setStats(h, histoElement)) return false;
00392   if (!setData (h, histoElement)) return false;
00393   return true;
00394 }
00395 
00396 
00397 
00398 
00399 bool Translator::writeHistoElement(const IHistogram3D& h, const ElementIterator& histoElement)
00400 {
00401   if (!histoElement) return false;
00402   histoElement->setName("histogram3d");
00403   setTitle(h, histoElement);
00404   if (!setAxes (h, histoElement)) return false;
00405   if (!setStats(h, histoElement)) return false;
00406   if (!setData (h, histoElement)) return false;
00407   return true;
00408 }
00409 
00410 
00411 
00412 
00413 void Translator::setTitle(const IHistogram& h, const ElementIterator& histoElement)
00414 {
00415   histoElement->setAttribute("title", h.title());
00416 }
00417 
00418 
00419 
00420 
00421 bool Translator::setAxes(const IHistogram1D& h, const ElementIterator& histoElement)
00422 {
00423   const IAxis* xaxis = h.xAxis();
00424   if (!xaxis) return false;
00425   appendAxis (histoElement, "x", *xaxis);
00426   return true;
00427 }
00428 
00429 
00430 
00431 
00432 bool Translator::setAxes(const IHistogram2D& h, const ElementIterator& histoElement)
00433 {
00434   const IAxis* xaxis = h.xAxis();
00435   const IAxis* yaxis = h.yAxis();
00436   if (!xaxis || !yaxis) return false;
00437   appendAxis (histoElement, "x", *xaxis);
00438   appendAxis (histoElement, "y", *yaxis);
00439   return true;
00440 }
00441 
00442 
00443 
00444 
00445 bool Translator::setAxes(const IHistogram3D& h, const ElementIterator& histoElement)
00446 {
00447   const IAxis* xaxis = h.xAxis();
00448   const IAxis* yaxis = h.yAxis();
00449   const IAxis* zaxis = h.zAxis();
00450   if (!xaxis || !yaxis || !zaxis) return false;
00451   appendAxis (histoElement, "x", *xaxis);
00452   appendAxis (histoElement, "y", *yaxis);
00453   appendAxis (histoElement, "z", *zaxis);
00454   return true;
00455 }
00456 
00457 
00458 
00459 
00460 bool Translator::appendAxis(const ElementIterator& histoElement, 
00461                             const AIDA_STD::string& axisName,
00462                             const IAxis& axis)
00463 {
00464   // add axis child to a histogram
00465   DataXML::DataObject axisElement;
00466   axisElement.setName("axis");
00467   axisElement.setAttribute("direction", axisName);
00468   axisElement.setAttribute("min",          toString(axis.lowerEdge()));
00469   axisElement.setAttribute("max",          toString(axis.upperEdge()));
00470   axisElement.setAttribute("numberOfBins", toString(axis.bins()));
00471   if (variableBins(axis)) {
00472     DataXML::DataObject borderElement;
00473     borderElement.setName("binBorder");
00474     const int nEdges = axis.bins() - 1;
00475     for (int i = 0; i < nEdges; ++i) {
00476       borderElement.setAttribute("value", toString(axis.binUpperEdge(i)));
00477       axisElement.appendChild(borderElement);
00478     }
00479   }
00480   histoElement->appendChild(axisElement);
00481   return true;
00482 }
00483 
00484 
00485 
00486 
00487 bool Translator::variableBins(const IAxis& axis) const
00488 {
00489   // Try to figure out if the histogram has variable width bins.
00490   // It's not in the interfaces so we need to figure it out ourselves...
00491   const int nBins  = axis.bins();
00492   if (nBins < 2) return false;
00493   const int nEdges = nBins - 1;
00494   const double low = axis.lowerEdge(), high = axis.upperEdge();
00495   const double binWidth = (high-low)/static_cast<double>(nBins);
00496   for (int i = 0; i < nEdges; ++i) {
00497     if (significantlyDifferent(axis.binUpperEdge(i),
00498                                low+(binWidth*(i+1)) 
00499                                )) return true;
00500   }
00501   return false;
00502 }
00503 
00504 
00505 
00506 
00507 bool Translator::setStats(const IHistogram1D& h, const ElementIterator& histoElement)
00508 {
00509   // append statistics child to a histo
00510   DataXML::DataObject allStats;
00511   allStats.setName("statistics");
00512   allStats.setAttribute("entries", toString(h.entries()));
00513   appendStat(&allStats, "x", h.mean(), h.rms());
00514   histoElement->appendChild(allStats);
00515   return true;
00516 }
00517 
00518 
00519 
00520 
00521 bool Translator::setStats(const IHistogram2D& h, const ElementIterator& histoElement)
00522 {
00523   // append statistics child to a histo
00524   DataXML::DataObject allStats;
00525   allStats.setName("statistics");
00526   allStats.setAttribute("entries", toString(h.entries()));
00527   appendStat(&allStats, "x", h.meanX(), h.rmsX());
00528   appendStat(&allStats, "y", h.meanY(), h.rmsY());
00529   histoElement->appendChild(allStats);
00530   return true;
00531 }
00532 
00533 
00534 
00535 
00536 bool Translator::setStats(const IHistogram3D& h, const ElementIterator& histoElement)
00537 {
00538   // append statistics child to a histo
00539   DataXML::DataObject allStats;
00540   allStats.setName("statistics");
00541   allStats.setAttribute("entries", toString(h.entries()));
00542   appendStat(&allStats, "x", h.meanX(), h.rmsX());
00543   appendStat(&allStats, "y", h.meanY(), h.rmsY());
00544   appendStat(&allStats, "z", h.meanZ(), h.rmsZ());
00545   histoElement->appendChild(allStats);
00546   return true;
00547 }
00548 
00549 
00550 
00551 
00552 bool Translator::appendStat(const ElementIterator& statisticsElement, 
00553                             const AIDA_STD::string& axisName,
00554                             const double& mean, const double& rms)
00555 {
00556   // add a statistic child to the statistics element (there is one per axis)
00557   DataXML::DataObject statElement;
00558   statElement.setName("statistic");
00559   statElement.setAttribute("direction", axisName);
00560   statElement.setAttribute("mean",toString(mean));
00561   statElement.setAttribute("rms", toString(rms));
00562   statisticsElement->appendChild(statElement);
00563   return true;
00564 }
00565 
00566 
00567 
00568 
00569 bool Translator::setData(const IHistogram1D& h, const ElementIterator& histoElement)
00570 {
00571   // make a data element, append all the points as children, then
00572   // append it to the histo
00573   DataXML::DataObject dataElement;
00574   dataElement.setName("data1d");
00575   const int dim = 1;
00576   const int nbx = h.xAxis()->bins();
00577   for (int i = -2; i < nbx; ++i) {
00578     int hi = binConversion(i,true);
00579     int ti = binConversion(i,false);
00580     int    entries = h.binEntries(hi);
00581     double height  = h.binHeight (hi);
00582     double error   = h.binError  (hi);
00583     appendDataPoint(dim, &dataElement, ti, 0, 0, entries, height, error);
00584   }
00585   histoElement->appendChild(dataElement);
00586   return true;
00587 }
00588 
00589 
00590 
00591 
00592 bool Translator::setData(const IHistogram2D& h, const ElementIterator& histoElement)
00593 {
00594   // make a data element, append all the points as children, then
00595   // append it to the histo
00596   DataXML::DataObject dataElement;
00597   dataElement.setName("data2d");
00598   const int dim = 2;
00599   const int nbx = h.xAxis()->bins();
00600   const int nby = h.yAxis()->bins();
00601   for (int i = -2; i < nbx; ++i) {
00602     int hi = binConversion(i,true);
00603     int ti = binConversion(i,false);
00604     for (int j = -2; j < nby; ++j) {
00605       int hj = binConversion(j,true);
00606       int tj = binConversion(j,false);
00607       int    entries = h.binEntries(hi, hj);
00608       double height  = h.binHeight (hi, hj);
00609       double error   = h.binError  (hi, hj);
00610       appendDataPoint(dim, &dataElement, ti, tj, 0, entries, height, error);
00611     }
00612   }
00613   histoElement->appendChild(dataElement);
00614   return true;
00615 }
00616 
00617 
00618 
00619 
00620 bool Translator::setData(const IHistogram3D& h, const ElementIterator& histoElement)
00621 {
00622   // make a data element, append all the points as children, then
00623   // append it to the histo
00624   DataXML::DataObject dataElement;
00625   dataElement.setName("data3d");
00626   const int dim = 3;
00627   const int nbx = h.xAxis()->bins();
00628   const int nby = h.yAxis()->bins();
00629   const int nbz = h.zAxis()->bins();
00630   for (int i = -2; i < nbx; ++i) {
00631     int hi = binConversion(i,true);
00632     int ti = binConversion(i,false);
00633     for (int j = -2; j < nby; ++j) {
00634       int hj = binConversion(j,true);
00635       int tj = binConversion(j,false);
00636       for (int k = -2; k < nbz; ++k) {
00637         int hk = binConversion(k,true);
00638         int tk = binConversion(k,false);
00639         int    entries = h.binEntries(hi, hj, hk);
00640         double height  = h.binHeight (hi, hj, hk);
00641         double error   = h.binError  (hi, hj, hk);
00642         appendDataPoint(dim, &dataElement, ti, tj, tk, entries, height, error);
00643       }
00644     }
00645   }
00646   histoElement->appendChild(dataElement);
00647   return true;
00648 }
00649 
00650 
00651 
00652 
00653 int Translator::binConversion(const int& i, const bool& histoMetric) const
00654 {
00655   // converts an integer from -2 to nb-1 to the relevant symbolic constants
00656   // if histoMetric is true then it returns whatever IHistogram uses as its
00657   // uflow/oflow constants, if false then whatever we use in this class.
00658   if      (i == -2) return (histoMetric ? IHistogram::UNDERFLOW_BIN : constant_UNDERFLOW);
00659   else if (i == -1) return (histoMetric ? IHistogram::OVERFLOW_BIN  : constant_OVERFLOW);
00660   else              return i;
00661 }
00662 
00663 
00664 
00665 
00666 void Translator::appendDataPoint(const int& dim, const ElementIterator& parent,
00667                                  const int& xbin, const int& ybin, const int& zbin,
00668                                  const int& entries, const double& height, 
00669                                  const double& error)
00670 {
00671   // append a data point to a <dataXD> element
00672   DataXML::DataObject binElement;
00673   binElement.setName(AIDA_STD::string("bin")+toString(dim)+AIDA_STD::string("d"));
00674   if (dim >= 1) addBinNumberAttribute(&binElement, "binNumX", xbin);
00675   if (dim >= 2) addBinNumberAttribute(&binElement, "binNumY", ybin);
00676   if (dim >= 3) addBinNumberAttribute(&binElement, "binNumZ", zbin);
00677   binElement.setAttribute("height",  toString(height) );
00678   binElement.setAttribute("error",   toString(error)  );
00679   binElement.setAttribute("entries", toString(entries));
00680   parent->appendChild(binElement);  
00681 }
00682 
00683 
00684 
00685 
00686 void Translator::addBinNumberAttribute(const ElementIterator& el, 
00687                                        const AIDA_STD::string& attName,
00688                                        const int& bn)
00689 {
00690   AIDA_STD::string id;
00691   if      (bn == constant_UNDERFLOW) id = "UNDERFLOW";
00692   else if (bn == constant_OVERFLOW)  id = "OVERFLOW";
00693   else                      id = toString(bn);
00694   el->setAttribute(attName, id);
00695 }
00696 
00697 
00698 
00699 
00700 void Translator::resetIterators(void)
00701 {
00702   if (iRootElement) 
00703     iHisto1DIt = iHisto2DIt = iHisto3DIt = iRootElement->children().begin();
00704   else             
00705     iHisto1DIt = iHisto2DIt = iHisto3DIt = 0;
00706 }
00707 
00708 
00709 
00710 
00711 bool Translator::readHistoElement(const ElementCIterator& histoElement, 
00712                                   HistoParameters1D& hp)
00713 {
00714   if (dimensionality(histoElement) == 1) {
00715     getTitle             (histoElement, hp);
00716     getXAxis             (histoElement, hp);
00717     getStatistics        (histoElement, hp);
00718     getData              (histoElement, hp);
00719     return goodParameters(hp);
00720   }
00721   else return false;
00722 }
00723 
00724 
00725 
00726 
00727 bool Translator::readHistoElement(const ElementCIterator& histoElement, 
00728                                   HistoParameters2D& hp)
00729 {
00730   if (dimensionality(histoElement) == 2) {
00731     getTitle             (histoElement, hp);
00732     getXAndYAxes         (histoElement, hp);
00733     getStatistics        (histoElement, hp);
00734     getData              (histoElement, hp);
00735     return goodParameters(hp);
00736   }
00737   else return false;
00738 }
00739 
00740 
00741 
00742 
00743 bool Translator::readHistoElement(const ElementCIterator& histoElement, 
00744                                   HistoParameters3D& hp)
00745 {
00746   if (dimensionality(histoElement) == 3) {
00747     getTitle             (histoElement, hp);
00748     getXYAndZAxes        (histoElement, hp);
00749     getStatistics        (histoElement, hp);
00750     getData              (histoElement, hp);
00751     return goodParameters(hp);
00752   }
00753   else return false;
00754 }
00755 
00756 
00757 
00758 
00759 void Translator::writeHeader(AIDA_STD::ostream& stream) const
00760 {
00761   stream << "<?xml"
00762          << " "
00763          << "version=\""  << XML_VERSION   << "\""
00764          << " "
00765          << "encoding=\"" << ENCODING_TYPE << "\""
00766          << "?>"
00767          << AIDA_STD::endl;
00768   stream << "<!"
00769          << "DOCTYPE"
00770          << " " << "aida" << " "
00771          << "SYSTEM"
00772          << " " << "\"aida.dtd\"" << " "
00773          << ">"
00774          << AIDA_STD::endl;
00775 }
00776 
00777 
00778 
00779 
00780 void Translator::writeFooter(AIDA_STD::ostream& stream) const
00781 {
00782   // stream << "</xml>" << AIDA_STD::endl; // probably unnecessary...
00783 }
00784 
00785 
00786 
00787 
00788 int Translator::dimensionality(const ElementCIterator& histoElement) const
00789 {
00790   if      (histoElement->name() == "histogram1d") return 1;
00791   else if (histoElement->name() == "histogram2d") return 2;
00792   else if (histoElement->name() == "histogram3d") return 3;
00793   else return 0;
00794 }
00795 
00796 
00797 
00798 
00799 void Translator::getTitle(const ElementCIterator& histoElement, 
00800                           HistoParameters& hp) const
00801 {
00802   hp.setTitle(histoElement->getAttributeValue("title"));
00803 }
00804 
00805 
00806 
00807 
00808 void Translator::getXAxis(const ElementCIterator& histoElement, 
00809                           HistoParameters1D& hp) const
00810 {
00811   int   nbx   = 0;
00812   double lowx  = 0.0, highx = 0.0;
00813   HistoParameters::VecDouble vecx;
00814   getAxis(histoElement, "x", nbx, lowx, highx, vecx);
00815   hp.setLowX  (lowx);
00816   hp.setHighX (highx);
00817   hp.setNbX   (nbx);
00818   hp.setEdgesX(vecx);
00819 }
00820 
00821 
00822 
00823 
00824 void Translator::getXAndYAxes(const ElementCIterator& histoElement, 
00825                               HistoParameters2D& hp) const
00826 {
00827   int   nbx = 0, nby = 0;
00828   double lowx = 0.0, lowy = 0.0, highx = 0.0, highy = 0.0;
00829   HistoParameters::VecDouble vecx, vecy;
00830   getAxis(histoElement, "x", nbx, lowx, highx, vecx);
00831   getAxis(histoElement, "y", nby, lowy, highy, vecy);
00832   hp.setNbX   (nbx);   hp.setNbY   (nby);
00833   hp.setLowX  (lowx);  hp.setLowY  (lowy);
00834   hp.setHighX (highx); hp.setHighY (highy);
00835   hp.setEdgesX(vecx);  hp.setEdgesY(vecy);
00836 }
00837 
00838 
00839 
00840 
00841 void Translator::getXYAndZAxes(const ElementCIterator& histoElement, 
00842                                HistoParameters3D& hp) const
00843 {
00844   int   nbx = 0, nby = 0, nbz = 0;
00845   double lowx = 0.0, lowy = 0.0, lowz = 0.0, highx = 0.0, highy = 0.0, highz = 0.0;
00846   HistoParameters::VecDouble vecx, vecy, vecz;
00847   getAxis(histoElement, "x", nbx, lowx, highx, vecx);
00848   getAxis(histoElement, "y", nby, lowy, highy, vecy);
00849   getAxis(histoElement, "z", nbz, lowz, highz, vecz);
00850   hp.setNbX   (nbx);   hp.setNbY   (nby);   hp.setNbZ   (nbz);
00851   hp.setLowX  (lowx);  hp.setLowY  (lowy);  hp.setLowZ  (lowz);
00852   hp.setHighX (highx); hp.setHighY (highy); hp.setHighZ (highz);
00853   hp.setEdgesX(vecx);  hp.setEdgesY(vecy);  hp.setEdgesZ(vecz);
00854 }
00855 
00856 
00857 
00858 
00859 void Translator::getAxis(const ElementCIterator& histoElement, 
00860                          const AIDA_STD::string& axisName,
00861                          int& nBins, double& low, double& high,
00862                          HistoParameters::VecDouble& vec) const
00863 {
00864   // extract the parameters of the histogram axis, including bin edges if necessary
00865   for (ElementCIterator i = histoElement->children().begin(); 
00866        i != histoElement->children().end(); ++i) {
00867     if (i->name() == "axis" && i->getAttributeValue("direction") == axisName) {
00868       // get common parameters
00869       DataXML::to_value(i->getAttributeValue("min"),          low);
00870       DataXML::to_value(i->getAttributeValue("max"),          high);
00871       DataXML::to_value(i->getAttributeValue("numberOfBins"), nBins);
00872       // and then get variable bin edges (if available)
00873       getBinEdges(i, vec, low, high);
00874       if (vec.empty()) return;
00875       else {
00876         // DTD does not (cannot) enforce the order of the edges, or consistency
00877         // of the number of bins and the number of edges, so we have to do it 
00878         // by hand.
00879         if (nBins != static_cast<int>(vec.size())-1) { vec.clear(); return; }
00880         else AIDA_STD::sort(vec.begin(), vec.end());
00881       }
00882     }
00883   }
00884 }
00885 
00886 
00887 
00888 
00889 void Translator::getBinEdges(const ElementCIterator& elm, 
00890                              HistoParameters::VecDouble& vec, 
00891                              const double& low, const double& high) const
00892 {
00893   // get the bin edges from the <binBorder> elements
00894   vec.clear();
00895   vec.push_back(low);
00896   for (ElementCIterator i = elm->children().begin(); 
00897        i != elm->children().end(); ++i) {
00898     if (i->name() == "binBorder") {
00899       double edge = 0.0;
00900       if (DataXML::to_value(i->getAttributeValue("value"), edge)) 
00901         vec.push_back(edge);
00902     }
00903   }
00904   // check it's the right size (use fixed bins if not)
00905   if (static_cast<int>(vec.size()) > 1) vec.push_back(high);
00906   else vec.clear();  
00907 }
00908 
00909 
00910 
00911 
00912 void Translator::getStatistics(const ElementCIterator& histoElement,
00913                                HistoParameters1D& hp) const
00914 {
00915   int nev = 0;
00916   double meanx = 0.0, rmsx = 0.0, skewx = 0.0;
00917   getNumberOfEntries(histoElement, nev);
00918   getStatistic(histoElement, "x", meanx, rmsx, skewx);
00919   hp.setNev(nev);
00920   hp.setEbe(static_cast<double>(nev)); // no EBE in DTD (yet)
00921   hp.setMeanX(meanx);
00922   hp.setRMSX(rmsx);
00923 }
00924 
00925 
00926 
00927 
00928 void Translator::getStatistics(const ElementCIterator& histoElement, 
00929                                HistoParameters2D& hp) const
00930 {
00931   int nev = 0;
00932   double meanx = 0.0, rmsx = 0.0, skewx = 0.0;
00933   double meany = 0.0, rmsy = 0.0, skewy = 0.0;
00934   getNumberOfEntries(histoElement, nev);
00935   getStatistic(histoElement, "x", meanx, rmsx, skewx);
00936   getStatistic(histoElement, "y", meany, rmsy, skewy);
00937   hp.setNev(nev);
00938   hp.setEbe(static_cast<double>(nev)); // no EBE in DTD (yet)
00939   hp.setMeanX(meanx); hp.setMeanY(meany);
00940   hp.setRMSX(rmsx);   hp.setRMSY(rmsy);
00941 }
00942 
00943 
00944 
00945 
00946 void Translator::getStatistics(const ElementCIterator& histoElement, 
00947                                HistoParameters3D& hp) const
00948 {
00949   int nev = 0;
00950   double meanx = 0.0, rmsx = 0.0, skewx = 0.0;
00951   double meany = 0.0, rmsy = 0.0, skewy = 0.0;
00952   double meanz = 0.0, rmsz = 0.0, skewz = 0.0;
00953   getNumberOfEntries(histoElement, nev);
00954   getStatistic(histoElement, "x", meanx, rmsx, skewx);
00955   getStatistic(histoElement, "y", meany, rmsy, skewy);
00956   getStatistic(histoElement, "z", meanz, rmsz, skewz);
00957   hp.setNev(nev);
00958   hp.setEbe(static_cast<double>(nev)); // no EBE in DTD (yet)
00959   hp.setMeanX(meanx); hp.setMeanY(meany); hp.setMeanZ(meanz);
00960   hp.setRMSX(rmsx);   hp.setRMSY(rmsy);   hp.setRMSZ(rmsz);
00961 }
00962 
00963 
00964 
00965 
00966 void Translator::getNumberOfEntries(const ElementCIterator& histoElement,
00967                                     int& nev) const
00968 {
00969   ElementCIterator statisticsElement = histoElement->getChild("statistics");
00970   if (statisticsElement == histoElement->children().end()) {
00971     missingElementError("statistics");
00972     return;
00973   }
00974   else DataXML::to_value(statisticsElement->getAttributeValue("entries"), nev);
00975 }
00976 
00977 
00978 
00979 
00980 void Translator::getStatistic(const ElementCIterator& histoElement, 
00981                               const AIDA_STD::string& axisName,
00982                               double& mean, double& rms, double& skew) const
00983 {
00984   ElementCIterator statisticsElement = histoElement->getChild("statistics");
00985   if (statisticsElement == histoElement->children().end()) {
00986     missingElementError("statistics");
00987     return;
00988   }
00989   for (ElementCIterator i = statisticsElement->children().begin();
00990        i != statisticsElement->children().end(); ++i) {
00991     if (i->name() == "statistic" && i->getAttributeValue("direction") == axisName) {
00992       DataXML::to_value(i->getAttributeValue("mean"),     mean);
00993       DataXML::to_value(i->getAttributeValue("rms"),      rms);
00994       DataXML::to_value(i->getAttributeValue("skewness"), skew);
00995       return;
00996     }
00997   }
00998   missingElementError("statistic ("+axisName+" axis)");
00999 }
01000 
01001 
01002 
01003 
01004 void Translator::getData(const ElementCIterator& histoElement, 
01005                          HistoParameters1D& p) const
01006 {
01007   const AIDA_STD::string dataName = "data1d";
01008   const AIDA_STD::string binName  = "bin1d";
01009   const ElementCIterator dataElement = getChild(histoElement, dataName);
01010   if (!dataElement) return;
01011   const int nBinsX = p.nbX(), vecSizeX = nBinsX+2;
01012   if (nBinsX < 1) return;
01013   HistoParameters::VecData binMatrix;
01014   resizeMatrix(binMatrix, vecSizeX);
01015   for (ElementCIterator elm = dataElement->children().begin(); 
01016        elm != dataElement->children().end(); ++elm) {
01017     if (elm->name() == binName) {
01018       int bnx  = xBinNumber(elm);
01019       // check they make sense!
01020       if (!consistentBin(bnx,p)) { nonsenseBinError(); return; }
01021       // shift by one, and put the uflow/oflow in the right places.
01022       convertBinNumber(bnx, nBinsX);
01023       fillBin(elm, binMatrix[bnx]);
01024     }
01025   }
01026   p.setValues(binMatrix);
01027 }
01028 
01029 
01030 
01031 
01032 void Translator::getData(const ElementCIterator& histoElement, 
01033                          HistoParameters2D& p) const
01034 {
01035   const AIDA_STD::string dataName = "data2d";
01036   const AIDA_STD::string binName  = "bin2d";
01037   const ElementCIterator dataElement = getChild(histoElement, dataName);
01038   if (!dataElement) return;
01039   const int nBinsX = p.nbX(), vecSizeX = nBinsX+2;
01040   const int nBinsY = p.nbY(), vecSizeY = nBinsY+2;
01041   if (nBinsX < 1 || nBinsY < 1) return;
01042   HistoParameters::VecVecData binMatrix;
01043   resizeMatrix(binMatrix, vecSizeX, vecSizeY);
01044   for (ElementCIterator elm = dataElement->children().begin(); 
01045        elm != dataElement->children().end(); ++elm) {
01046     if (elm->name() == binName) {
01047       int bnx  = xBinNumber(elm);
01048       int bny  = yBinNumber(elm);
01049       // check they make sense!
01050       if (!consistentBin(bnx,bny,p)) { nonsenseBinError(); return; }
01051       // shift by one, and put the uflow/oflow in the right places.
01052       convertBinNumber(bnx, nBinsX);
01053       convertBinNumber(bny, nBinsY);
01054       fillBin(elm, binMatrix[bnx][bny]);
01055     }
01056   }
01057   p.setValues(binMatrix);
01058 }
01059 
01060 
01061 
01062 
01063 void Translator::getData(const ElementCIterator& histoElement, 
01064                          HistoParameters3D& p) const
01065 {
01066   const AIDA_STD::string dataName = "data3d";
01067   const AIDA_STD::string binName  = "bin3d";
01068   const ElementCIterator dataElement = getChild(histoElement, dataName);
01069   if (!dataElement) return;
01070   const int nBinsX = p.nbX(), vecSizeX = nBinsX+2;
01071   const int nBinsY = p.nbY(), vecSizeY = nBinsY+2;
01072   const int nBinsZ = p.nbZ(), vecSizeZ = nBinsZ+2;
01073   if (nBinsX < 1 || nBinsY < 1 || nBinsZ < 1) return;
01074   HistoParameters::VecVecVecData binMatrix;
01075   resizeMatrix(binMatrix, vecSizeX, vecSizeY, vecSizeZ);
01076   for (ElementCIterator elm = dataElement->children().begin(); 
01077        elm != dataElement->children().end(); ++elm) {
01078     if (elm->name() == binName) {
01079       int bnx  = xBinNumber(elm);
01080       int bny  = yBinNumber(elm);
01081       int bnz  = zBinNumber(elm);
01082       // check they make sense!
01083       if (!consistentBin(bnx,bny,bnz,p)) { nonsenseBinError(); return; }
01084       // shift by one, and put the uflow/oflow in the right places.
01085       convertBinNumber(bnx, nBinsX);
01086       convertBinNumber(bny, nBinsY);
01087       convertBinNumber(bnz, nBinsZ);
01088       fillBin(elm, binMatrix[bnx][bny][bnz]);
01089     }
01090   }
01091   p.setValues(binMatrix);
01092 }
01093 
01094 
01095 
01096 
01097 void Translator::fillBin(const ElementCIterator& elm, HistoParameters::BinInfo& bin) const
01098 {
01099   bin.height  = binHeight(elm);
01100   bin.error   = binError(elm);
01101   bin.error2  = binError2(elm);
01102   bin.entries = binEntries(elm);
01103 }
01104 
01105 
01106 
01107 
01108 Translator::ElementCIterator Translator::getChild(const ElementCIterator& parent, 
01109                                                   const AIDA_STD::string& childName) const
01110 {
01111   ElementCIterator child = parent->getChild(childName);
01112   if (child == parent->children().end() || child == 0) {
01113     missingElementError(childName);
01114     return 0;
01115   }
01116   else return child;
01117 }
01118 
01119 
01120 
01121 
01122 void Translator::convertBinNumber(int& i, const int& nbins) const
01123 {
01124   // convert from bin number in range [-2, nb-1] to one in range [0, nb+1]
01125   // (i.e. make underflow and overflow the first and last bins, respectively)
01126   if      (i == constant_UNDERFLOW) i = 0;
01127   else if (i == constant_OVERFLOW)  i = nbins+1;
01128   else ++i;  
01129 }
01130 
01131 
01132 
01133 
01134 int Translator::binNumber(const ElementCIterator& it) const
01135 {
01136   const AIDA_STD::string sbn = it->getAttributeValue("binNum");
01137   return binNumber(sbn);
01138 }
01139 
01140 
01141 
01142 
01143 int Translator::xBinNumber(const ElementCIterator& it) const
01144 {
01145   AIDA_STD::string sbn = it->getAttributeValue("binNumX");
01146   if (sbn == "") sbn = it->getAttributeValue("binNum");
01147   return binNumber(sbn);
01148 }
01149 
01150 
01151 
01152 
01153 int Translator::yBinNumber(const ElementCIterator& it) const
01154 {
01155   const AIDA_STD::string sbn = it->getAttributeValue("binNumY");
01156   return binNumber(sbn);
01157 }
01158 
01159 
01160 
01161 
01162 int Translator::zBinNumber(const ElementCIterator& it) const
01163 {
01164   const AIDA_STD::string sbn = it->getAttributeValue("binNumZ");
01165   return binNumber(sbn);
01166 }
01167 
01168 
01169 
01170 
01171 int Translator::binNumber(const AIDA_STD::string& sbn) const
01172 {
01173   if (sbn == "UNDERFLOW" || sbn == "") return constant_UNDERFLOW;
01174   else if (sbn == "OVERFLOW") return constant_OVERFLOW;
01175   else return stringToInt(sbn);
01176 }
01177 
01178 
01179 
01180 
01181 double Translator::binHeight(const ElementCIterator& binElement) const
01182 {
01183   double val = 0.0;
01184   return ((DataXML::to_value(binElement->getAttributeValue("height"),val)) ? val : 0.0);
01185 }
01186 
01187 
01188 
01189 
01190 double Translator::binError(const ElementCIterator& binElement) const
01191 {
01192   double val = 0.0;
01193   return ((DataXML::to_value(binElement->getAttributeValue("error"),val)) ? val : 0.0);
01194 }
01195 
01196 
01197 
01198 
01199 double Translator::binError2(const ElementCIterator& binElement) const
01200 {
01201   double val = 0.0;
01202   return ((DataXML::to_value(binElement->getAttributeValue("error2"),val)) ? val : 0.0);
01203 }
01204 
01205 
01206 
01207 
01208 int Translator::binEntries(const ElementCIterator& binElement) const
01209 {
01210   int val;
01211   return ((DataXML::to_value(binElement->getAttributeValue("entries"),val)) ? val : 0);
01212 }
01213 
01214 
01215 
01216 
01217 bool Translator::consistentBin(const int& binNumberX, 
01218                                const HistoParameters1D& hp) const
01219 {
01220   // minimal consistency check for a bin index
01221   const int minBinX = 0;
01222   const int maxBinX = hp.nbX()-1;
01223   bool xok =   binNumberX == constant_UNDERFLOW 
01224             || binNumberX == constant_OVERFLOW 
01225             || (binNumberX >= minBinX && binNumberX <= maxBinX);
01226   return (xok);
01227 }
01228 
01229 
01230 
01231 
01232 bool Translator::consistentBin(const int& binNumberX, 
01233                                const int& binNumberY, 
01234                                const HistoParameters2D& hp) const
01235 {
01236   // minimal consistency check for bin indices
01237   const int minBinX = 0, minBinY = 0;
01238   const int maxBinX = hp.nbX()-1, maxBinY = hp.nbY()-1;
01239   bool xok =   binNumberX == constant_UNDERFLOW 
01240             || binNumberX == constant_OVERFLOW 
01241             || (binNumberX >= minBinX && binNumberX <= maxBinX);
01242   bool yok =   binNumberY == constant_UNDERFLOW 
01243             || binNumberY == constant_OVERFLOW 
01244             || (binNumberY >= minBinY && binNumberY <= maxBinY);
01245   return (xok && yok);
01246 }
01247 
01248 
01249 
01250 
01251 bool Translator::consistentBin(const int& binNumberX, 
01252                                const int& binNumberY,  
01253                                const int& binNumberZ, 
01254                                const HistoParameters3D& hp) const
01255 {
01256   // minimal consistency check for bin indices
01257   const int minBinX = 0, minBinY = 0, minBinZ = 0;
01258   const int maxBinX = hp.nbX()-1, maxBinY = hp.nbY()-1, maxBinZ = hp.nbZ()-1;
01259   bool xok =   binNumberX == constant_UNDERFLOW 
01260             || binNumberX == constant_OVERFLOW 
01261             || (binNumberX >= minBinX && binNumberX <= maxBinX);
01262   bool yok =   binNumberY == constant_UNDERFLOW 
01263             || binNumberY == constant_OVERFLOW 
01264             || (binNumberY >= minBinY && binNumberY <= maxBinY);
01265   bool zok =   binNumberZ == constant_UNDERFLOW 
01266             || binNumberZ == constant_OVERFLOW 
01267             || (binNumberZ >= minBinZ && binNumberZ <= maxBinZ);
01268   return (xok && yok && zok);
01269 }
01270 
01271 
01272 
01273 
01274 int Translator::stringToInt(const AIDA_STD::string& c) const
01275 {
01276   int ans = 0;
01277   if (c.length() < 1) return false;
01278   AIDA_STD::string s = c;
01279   for (unsigned int i = 0; i < s.length(); ++i) {
01280     if (s[i] == '0') s.erase(0,1);
01281     else break;
01282   }
01283   if (s.length() < 1) return false;
01284   for (unsigned int i = 0; i < s.length(); ++i) {
01285     if (!isdigit(s[i])) return false;
01286   }
01287   ans = atoi(s.c_str());
01288   return (ans > 0) ? ans : RUBBISH;
01289 }
01290 
01291 
01292 
01293 
01294 bool Translator::goodParameters(const HistoParameters1D& p) const
01295 {
01296   // minimal check on consistency of parameters
01297   int nb    = p.nbX();
01298   int sov   = p.edgesX().size();
01299   bool goodFixed = nb > 0 && sov == 0 && p.lowX() < p.highX();
01300   bool goodVar   = nb > 0 && nb == sov-1 && 
01301                    p.edgesX()[0] == p.lowX() && p.edgesX()[sov-1] == p.highX();
01302   return (goodFixed || goodVar);
01303 }
01304 
01305 
01306 
01307 
01308 bool Translator::goodParameters(const HistoParameters2D& p) const
01309 {
01310   // minimal check on consistency of parameters
01311   bool goodX = p.nbX() > 0 && p.lowX() < p.highX();
01312   bool goodY = p.nbY() > 0 && p.lowY() < p.highY();
01313   return (goodX && goodY);
01314 }
01315 
01316 
01317 
01318 
01319 bool Translator::goodParameters(const HistoParameters3D& p) const
01320 {
01321   // minimal check on consistency of parameters
01322   bool goodX = p.nbX() > 0 && p.lowX() < p.highX();
01323   bool goodY = p.nbY() > 0 && p.lowY() < p.highY();
01324   bool goodZ = p.nbZ() > 0 && p.lowZ() < p.highZ();
01325   return (goodX && goodY && goodZ);
01326 }
01327 
01328 
01329 
01330 
01331 void Translator::resizeMatrix(HistoParameters::VecData& vec,
01332                               const int& xdim) const
01333 {
01334   vec.clear();
01335   vec.resize(xdim);
01336 }
01337 
01338 
01339 
01340 
01341 void Translator::resizeMatrix(HistoParameters::VecVecData& vec,
01342                               const int& xdim, const int& ydim) const
01343 {
01344   vec.clear();
01345   vec.resize(xdim);
01346   for (int i = 0; i < xdim; ++i) {
01347     vec[i].resize(ydim);
01348   }
01349 }
01350 
01351 
01352 
01353 
01354 void Translator::resizeMatrix(HistoParameters::VecVecVecData& vec,
01355                               const int& xdim, const int& ydim, const int& zdim) const
01356 {
01357   vec.clear();
01358   vec.resize(xdim);
01359   for (int i = 0; i < xdim; ++i) {
01360     vec[i].resize(ydim);
01361     for (int j = 0; j < ydim; ++j) {
01362       (vec[i])[j].resize(zdim);
01363     }
01364   }
01365 }
01366 
01367 
01368 
01369 
01370 void Translator::badInputStreamError(void) const
01371 {
01372   errorMessage("malformed or unreadable XML input stream!");
01373 }
01374 
01375 
01376 
01377 
01378 void Translator::wrongDocTypeError(void) const
01379 {
01380   errorMessage("input stream is not AIDA standard XML");
01381 }
01382 
01383 
01384 
01385 
01386 void Translator::missingElementError(const AIDA_STD::string& elementName) const
01387 {
01388   errorMessage("no \"" + elementName + "\" element found in input");
01389 }
01390 
01391 
01392 
01393 
01394 void Translator::nonsenseBinError(void) const
01395 {
01396   errorMessage("bin index inconsistent with histo parameters");
01397 }
01398 
01399 
01400 
01401 
01402 void Translator::badNBError(void) const
01403 {
01404   errorMessage("incorrect number of bins found in data element");
01405 }
01406 
01407 
01408 
01409 
01410 void Translator::noOutputStreamError(void) const
01411 {
01412   errorMessage("output stream has not been set!");
01413 }
01414 
01415 
01416 
01417 
01418 void Translator::errorMessage(const AIDA_STD::string& msg) const
01419 {
01420   if (!silent) AIDA_STD::cerr << "AidaXML::Translator ERROR: " << msg <<  AIDA_STD::endl;
01421 }
01422 
01423 
01424 
01425 
01426 bool Translator::significantlyDifferent(const double& a, const double& b) const
01427 {
01428   // checks for difference between two numbers which is too large to have come from
01429   // roundoff error in FP calculations. Very stupid and simple method!
01430   const double minus      = -1.0;
01431   const double zero       =  0.0;
01432   const double absa       = (a >= zero ? a : minus*a);
01433   const double absb       = (b >= zero ? b : minus*b);
01434   const double magnitude  = (absa > absb ? absa : absb);
01435   const double difference = (absa > absb ? absa - absb : absb - absa);
01436   const double delta      =  difference * magnitude;
01437   return (delta > ROUNDOFF_TOLERANCE);
01438 }
01439 
01440 
01441 
01442 
01443 } // end of namespace Anaphe


Anaphe documentation generated by Doxygen (www.doxygen.org)