Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:56:42

0001 // -*- C++ -*-
0002 //
0003 // Package:     MuonAlignment
0004 // Class  :     MuonAlignmentOutputXML
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:
0010 //         Created:  Fri Mar 14 18:02:33 CDT 2008
0011 // $Id: MuonAlignmentOutputXML.cc,v 1.9 2011/06/07 19:38:24 khotilov Exp $
0012 //
0013 
0014 // system include files
0015 #include "FWCore/Framework/interface/ESHandle.h"
0016 #include "FWCore/Framework/interface/ESTransientHandle.h"
0017 
0018 // user include files
0019 #include "Alignment/MuonAlignment/interface/MuonAlignmentOutputXML.h"
0020 #include "Alignment/CommonAlignment/interface/AlignableObjectId.h"
0021 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
0022 #include "DataFormats/MuonDetId/interface/DTSuperLayerId.h"
0023 #include "DataFormats/MuonDetId/interface/DTLayerId.h"
0024 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
0025 #include "Geometry/DTGeometry/interface/DTGeometry.h"
0026 #include "Geometry/CSCGeometry/interface/CSCGeometry.h"
0027 #include "Alignment/CommonAlignment/interface/SurveyDet.h"
0028 #include "CondFormats/Alignment/interface/AlignmentErrorsExtended.h"
0029 #include "Geometry/Records/interface/MuonGeometryRecord.h"
0030 
0031 //
0032 // constants, enums and typedefs
0033 //
0034 
0035 //
0036 // static data member definitions
0037 //
0038 
0039 //
0040 // constructors and destructor
0041 //
0042 MuonAlignmentOutputXML::MuonAlignmentOutputXML(const edm::ParameterSet &iConfig,
0043                                                const DTGeometry *dtGeometry,
0044                                                const CSCGeometry *cscGeometry,
0045                                                const GEMGeometry *gemGeometry)
0046     : m_fileName(iConfig.getParameter<std::string>("fileName")),
0047       m_survey(iConfig.getParameter<bool>("survey")),
0048       m_rawIds(iConfig.getParameter<bool>("rawIds")),
0049       m_eulerAngles(iConfig.getParameter<bool>("eulerAngles")),
0050       m_precision(iConfig.getParameter<int>("precision")),
0051       m_suppressDTBarrel(iConfig.getUntrackedParameter<bool>("suppressDTBarrel", false)),
0052       m_suppressDTWheels(iConfig.getUntrackedParameter<bool>("suppressDTWheels", false)),
0053       m_suppressDTStations(iConfig.getUntrackedParameter<bool>("suppressDTStations", false)),
0054       m_suppressDTChambers(iConfig.getUntrackedParameter<bool>("suppressDTChambers", false)),
0055       m_suppressDTSuperLayers(iConfig.getUntrackedParameter<bool>("suppressDTSuperLayers", false)),
0056       m_suppressDTLayers(iConfig.getUntrackedParameter<bool>("suppressDTLayers", false)),
0057       m_suppressCSCEndcaps(iConfig.getUntrackedParameter<bool>("suppressCSCEndcaps", false)),
0058       m_suppressCSCStations(iConfig.getUntrackedParameter<bool>("suppressCSCStations", false)),
0059       m_suppressCSCRings(iConfig.getUntrackedParameter<bool>("suppressCSCRings", false)),
0060       m_suppressCSCChambers(iConfig.getUntrackedParameter<bool>("suppressCSCChambers", false)),
0061       m_suppressCSCLayers(iConfig.getUntrackedParameter<bool>("suppressCSCLayers", false)),
0062       m_suppressGEMEndcaps(iConfig.getUntrackedParameter<bool>("suppressGEMEndcaps", false)),
0063       m_suppressGEMStations(iConfig.getUntrackedParameter<bool>("suppressGEMStations", false)),
0064       m_suppressGEMRings(iConfig.getUntrackedParameter<bool>("suppressGEMRings", false)),
0065       m_suppressGEMSuperChambers(iConfig.getUntrackedParameter<bool>("suppressGEMSuperChambers", false)),
0066       m_suppressGEMChambers(iConfig.getUntrackedParameter<bool>("suppressGEMChambers", false)),
0067       m_suppressGEMEtaPartitions(iConfig.getUntrackedParameter<bool>("suppressGEMEtaPartitions", false)),
0068       dtGeometry_(dtGeometry),
0069       cscGeometry_(cscGeometry),
0070       gemGeometry_(gemGeometry) {
0071   std::string str_relativeto = iConfig.getParameter<std::string>("relativeto");
0072 
0073   if (str_relativeto == std::string("none")) {
0074     m_relativeto = 0;
0075   } else if (str_relativeto == std::string("ideal")) {
0076     m_relativeto = 1;
0077   } else if (str_relativeto == std::string("container")) {
0078     m_relativeto = 2;
0079   } else {
0080     throw cms::Exception("BadConfig") << "relativeto must be \"none\", \"ideal\", or \"container\"" << std::endl;
0081   }
0082 }
0083 
0084 // MuonAlignmentOutputXML::MuonAlignmentOutputXML(const MuonAlignmentOutputXML& rhs)
0085 // {
0086 //    // do actual copying here;
0087 // }
0088 
0089 MuonAlignmentOutputXML::~MuonAlignmentOutputXML() {}
0090 
0091 //
0092 // assignment operators
0093 //
0094 // const MuonAlignmentOutputXML& MuonAlignmentOutputXML::operator=(const MuonAlignmentOutputXML& rhs)
0095 // {
0096 //   //An exception safe implementation is
0097 //   MuonAlignmentOutputXML temp(rhs);
0098 //   swap(rhs);
0099 //
0100 //   return *this;
0101 // }
0102 
0103 //
0104 // member functions
0105 //
0106 
0107 void MuonAlignmentOutputXML::write(AlignableMuon *alignableMuon) const {
0108   std::ofstream outputFile(m_fileName.c_str());
0109   outputFile << std::setprecision(m_precision) << std::fixed;
0110 
0111   outputFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
0112   outputFile << "<?xml-stylesheet type=\"text/xml\" href=\"MuonAlignment.xsl\"?>" << std::endl;
0113   outputFile << "<MuonAlignment>" << std::endl << std::endl;
0114 
0115   std::map<align::ID, CLHEP::HepSymMatrix> errors;
0116   AlignmentErrorsExtended *dtErrors = alignableMuon->dtAlignmentErrorsExtended();
0117   AlignmentErrorsExtended *cscErrors = alignableMuon->cscAlignmentErrorsExtended();
0118   AlignmentErrorsExtended *gemErrors = alignableMuon->gemAlignmentErrorsExtended();
0119   for (std::vector<AlignTransformErrorExtended>::const_iterator dtError = dtErrors->m_alignError.begin();
0120        dtError != dtErrors->m_alignError.end();
0121        ++dtError) {
0122     errors[dtError->rawId()] = dtError->matrix();
0123   }
0124   for (std::vector<AlignTransformErrorExtended>::const_iterator cscError = cscErrors->m_alignError.begin();
0125        cscError != cscErrors->m_alignError.end();
0126        ++cscError) {
0127     errors[cscError->rawId()] = cscError->matrix();
0128   }
0129   for (std::vector<AlignTransformErrorExtended>::const_iterator gemError = gemErrors->m_alignError.begin();
0130        gemError != gemErrors->m_alignError.end();
0131        ++gemError) {
0132     errors[gemError->rawId()] = gemError->matrix();
0133   }
0134 
0135   align::Alignables barrels = alignableMuon->DTBarrel();
0136   align::Alignables endcaps = alignableMuon->CSCEndcaps();
0137   align::Alignables endcaps_GEM = alignableMuon->GEMEndcaps();
0138 
0139   if (m_relativeto == 1) {
0140     AlignableMuon ideal_alignableMuon(dtGeometry_, cscGeometry_, gemGeometry_);
0141 
0142     align::Alignables ideal_barrels = ideal_alignableMuon.DTBarrel();
0143     align::Alignables ideal_endcaps = ideal_alignableMuon.CSCEndcaps();
0144     align::Alignables ideal_endcaps_GEM = ideal_alignableMuon.GEMEndcaps();
0145 
0146     writeComponents(barrels, ideal_barrels, errors, outputFile, doDT, alignableMuon->objectIdProvider());
0147     writeComponents(endcaps, ideal_endcaps, errors, outputFile, doCSC, alignableMuon->objectIdProvider());
0148     writeComponents(endcaps_GEM, ideal_endcaps_GEM, errors, outputFile, doGEM, alignableMuon->objectIdProvider());
0149   } else {
0150     align::Alignables empty1, empty2, empty3;
0151 
0152     writeComponents(barrels, empty1, errors, outputFile, doDT, alignableMuon->objectIdProvider());
0153     writeComponents(endcaps, empty2, errors, outputFile, doCSC, alignableMuon->objectIdProvider());
0154     writeComponents(endcaps_GEM, empty3, errors, outputFile, doGEM, alignableMuon->objectIdProvider());
0155   }
0156 
0157   outputFile << "</MuonAlignment>" << std::endl;
0158 }
0159 
0160 void MuonAlignmentOutputXML::writeComponents(align::Alignables &alignables,
0161                                              align::Alignables &ideals,
0162                                              std::map<align::ID, CLHEP::HepSymMatrix> &errors,
0163                                              std::ofstream &outputFile,
0164                                              const int doDet,
0165                                              const AlignableObjectId &objectIdProvider) const {
0166   align::Alignables::const_iterator ideal = ideals.begin();
0167   for (align::Alignables::const_iterator alignable = alignables.begin(); alignable != alignables.end(); ++alignable) {
0168     if (m_survey && (*alignable)->survey() == nullptr) {
0169       throw cms::Exception("Alignment") << "SurveyDets must all be defined when writing to XML" << std::endl;
0170     }
0171 
0172     align::StructureType alignableObjectId = (*alignable)->alignableObjectId();
0173 
0174     if ((alignableObjectId == align::AlignableDTBarrel && !m_suppressDTBarrel) ||
0175         (alignableObjectId == align::AlignableDTWheel && !m_suppressDTWheels) ||
0176         (alignableObjectId == align::AlignableDTStation && !m_suppressDTStations) ||
0177         (alignableObjectId == align::AlignableDTChamber && !m_suppressDTChambers) ||
0178         (doDet == doDT && alignableObjectId == align::AlignableDTSuperLayer && !m_suppressDTSuperLayers) ||
0179         (doDet == doDT && alignableObjectId == align::AlignableDetUnit && !m_suppressDTLayers) ||
0180         (alignableObjectId == align::AlignableCSCEndcap && !m_suppressCSCEndcaps) ||
0181         (alignableObjectId == align::AlignableCSCStation && !m_suppressCSCStations) ||
0182         (alignableObjectId == align::AlignableCSCRing && !m_suppressCSCRings) ||
0183         (alignableObjectId == align::AlignableCSCChamber && !m_suppressCSCChambers) ||
0184         (alignableObjectId == align::AlignableGEMEndcap && !m_suppressGEMEndcaps) ||
0185         (alignableObjectId == align::AlignableGEMStation && !m_suppressGEMStations) ||
0186         (alignableObjectId == align::AlignableGEMRing && !m_suppressGEMRings) ||
0187         (alignableObjectId == align::AlignableGEMSuperChamber && !m_suppressGEMSuperChambers) ||
0188         (alignableObjectId == align::AlignableGEMChamber && !m_suppressGEMChambers) ||
0189         (alignableObjectId == align::AlignableGEMEtaPartition && !m_suppressGEMEtaPartitions) ||
0190         (doDet != doDT && doDet != doGEM && doDet == doCSC && alignableObjectId == align::AlignableDetUnit &&
0191          !m_suppressCSCLayers) ||
0192         (doDet != doDT && doDet != doCSC && doDet == doGEM && alignableObjectId == align::AlignableDetUnit &&
0193          !m_suppressGEMEtaPartitions)) {
0194       unsigned int rawId = (*alignable)->geomDetId().rawId();
0195       outputFile << "<operation>" << std::endl;
0196 
0197       if (doDet == doDT) {
0198         if (m_rawIds && rawId != 0) {
0199           std::string typeName = objectIdProvider.idToString(alignableObjectId);
0200           if (alignableObjectId == align::AlignableDTSuperLayer)
0201             typeName = std::string("DTSuperLayer");
0202           if (alignableObjectId == align::AlignableDetUnit)
0203             typeName = std::string("DTLayer");
0204           outputFile << "  <" << typeName << " rawId=\"" << rawId << "\" />" << std::endl;
0205         } else {
0206           if (alignableObjectId == align::AlignableDetUnit) {
0207             DTLayerId id(rawId);
0208             outputFile << "  <DTLayer wheel=\"" << id.wheel() << "\" station=\"" << id.station() << "\" sector=\""
0209                        << id.sector() << "\" superlayer=\"" << id.superlayer() << "\" layer=\"" << id.layer() << "\" />"
0210                        << std::endl;
0211           } else if (alignableObjectId == align::AlignableDTSuperLayer) {
0212             DTSuperLayerId id(rawId);
0213             outputFile << "  <DTSuperLayer wheel=\"" << id.wheel() << "\" station=\"" << id.station() << "\" sector=\""
0214                        << id.sector() << "\" superlayer=\"" << id.superlayer() << "\" />" << std::endl;
0215           } else if (alignableObjectId == align::AlignableDTChamber) {
0216             DTChamberId id(rawId);
0217             outputFile << "  <DTChamber wheel=\"" << id.wheel() << "\" station=\"" << id.station() << "\" sector=\""
0218                        << id.sector() << "\" />" << std::endl;
0219           } else {
0220             DTChamberId id((*alignable)->id());
0221             if (alignableObjectId == align::AlignableDTStation) {
0222               outputFile << "  <DTStation wheel=\"" << id.wheel() << "\" station=\"" << id.station() << "\" />"
0223                          << std::endl;
0224             } else if (alignableObjectId == align::AlignableDTWheel) {
0225               outputFile << "  <DTWheel wheel=\"" << id.wheel() << "\" />" << std::endl;
0226             } else if (alignableObjectId == align::AlignableDTBarrel) {
0227               outputFile << "  <DTBarrel />" << std::endl;
0228             } else
0229               throw cms::Exception("Alignment") << "Unknown DT Alignable StructureType" << std::endl;
0230           }
0231 
0232         }  // end if not rawId
0233       }    // end if DT
0234 
0235       if (doDet == doCSC) {  // CSC
0236         if (m_rawIds && rawId != 0) {
0237           std::string typeName = objectIdProvider.idToString(alignableObjectId);
0238           if (alignableObjectId == align::AlignableDetUnit)
0239             typeName = std::string("CSCLayer");
0240           outputFile << "  <" << typeName << " rawId=\"" << rawId << "\" />" << std::endl;
0241         } else {
0242           if (alignableObjectId == align::AlignableDetUnit) {
0243             CSCDetId id(rawId);
0244             outputFile << "  <CSCLayer endcap=\"" << id.endcap() << "\" station=\"" << id.station() << "\" ring=\""
0245                        << id.ring() << "\" chamber=\"" << id.chamber() << "\" layer=\"" << id.layer() << "\" />"
0246                        << std::endl;
0247           } else if (alignableObjectId == align::AlignableCSCChamber) {
0248             CSCDetId id(rawId);
0249             outputFile << "  <CSCChamber endcap=\"" << id.endcap() << "\" station=\"" << id.station() << "\" ring=\""
0250                        << id.ring() << "\" chamber=\"" << id.chamber() << "\" />" << std::endl;
0251           } else {
0252             CSCDetId id((*alignable)->id());
0253             if (alignableObjectId == align::AlignableCSCRing) {
0254               outputFile << "  <CSCRing endcap=\"" << id.endcap() << "\" station=\"" << id.station() << "\" ring=\""
0255                          << id.ring() << "\" />" << std::endl;
0256             } else if (alignableObjectId == align::AlignableCSCStation) {
0257               outputFile << "  <CSCStation endcap=\"" << id.endcap() << "\" station=\"" << id.station() << "\" />"
0258                          << std::endl;
0259             } else if (alignableObjectId == align::AlignableCSCEndcap) {
0260               outputFile << "  <CSCEndcap endcap=\"" << id.endcap() << "\" />" << std::endl;
0261             } else
0262               throw cms::Exception("Alignment") << "Unknown CSC Alignable StructureType" << std::endl;
0263           }
0264 
0265         }  // end if not rawId
0266       }    // end if CSC
0267 
0268       if (doDet == doGEM) {  // GEM
0269         if (m_rawIds && rawId != 0) {
0270           std::string typeName = objectIdProvider.idToString(alignableObjectId);
0271           if (alignableObjectId == align::AlignableDetUnit)
0272             typeName = std::string("GEMChambers");
0273           outputFile << "  <" << typeName << " rawId=\"" << rawId << "\" />" << std::endl;
0274         } else {
0275           if (alignableObjectId == align::AlignableDetUnit) {
0276             GEMDetId id(rawId);
0277             outputFile << "  <GEMSuperChambers endcap=\"" << id.region() << "\" station=\"" << id.station()
0278                        << "\" ring=\"" << id.ring() << "\" superchamber=\"" << id.chamber() << "\" layer=\""
0279                        << id.layer() << "\" />" << std::endl;
0280           } else if (alignableObjectId == align::AlignableGEMSuperChamber) {
0281             GEMDetId id(rawId);
0282             outputFile << "  <GEMSuperChamber endcap=\"" << id.region() << "\" station=\"" << id.station()
0283                        << "\" ring=\"" << id.ring() << "\" chamber=\"" << id.chamber() << "\" />" << std::endl;
0284           } else {
0285             GEMDetId id((*alignable)->id());
0286             if (alignableObjectId == align::AlignableGEMRing) {
0287               outputFile << "  <GEMRing endcap=\"" << id.region() << "\" station=\"" << id.station() << "\" ring=\""
0288                          << id.ring() << "\" />" << std::endl;
0289             } else if (alignableObjectId == align::AlignableGEMStation) {
0290               outputFile << "  <GEMStation endcap=\"" << id.region() << "\" station=\"" << id.station() << "\" />"
0291                          << std::endl;
0292             } else if (alignableObjectId == align::AlignableGEMEndcap) {
0293               outputFile << "  <GEMEndcap endcap=\"" << id.region() << "\" />" << std::endl;
0294             } else
0295               throw cms::Exception("Alignment") << "Unknown GEM Alignable StructureType" << std::endl;
0296           }
0297 
0298         }  // end if not rawId
0299       }    // end if GEM
0300 
0301       align::PositionType pos = (*alignable)->globalPosition();
0302       align::RotationType rot = (*alignable)->globalRotation();
0303 
0304       if (m_survey) {
0305         pos = (*alignable)->survey()->position();
0306         rot = (*alignable)->survey()->rotation();
0307       }
0308 
0309       std::string str_relativeto;
0310       if (m_relativeto == 0) {
0311         str_relativeto = std::string("none");
0312       }
0313 
0314       else if (m_relativeto == 1) {
0315         if (ideal == ideals.end() || (*ideal)->alignableObjectId() != alignableObjectId ||
0316             (*ideal)->id() != (*alignable)->id()) {
0317           throw cms::Exception("Alignment") << "AlignableMuon and ideal_AlignableMuon are out of sync!" << std::endl;
0318         }
0319 
0320         align::PositionType idealPosition = (*ideal)->globalPosition();
0321         align::RotationType idealRotation = (*ideal)->globalRotation();
0322 
0323         pos = align::PositionType(idealRotation * (pos.basicVector() - idealPosition.basicVector()));
0324         rot = rot * idealRotation.transposed();
0325 
0326         str_relativeto = std::string("ideal");
0327 
0328         bool csc_debug = false;
0329         if (csc_debug && doDet == doCSC) {
0330           CSCDetId id(rawId);
0331           if (id.endcap() == 1 && id.station() == 1 && id.ring() == 1 && id.chamber() == 33) {
0332             std::cout << " investigating " << id << std::endl
0333                       << (*alignable)->globalRotation() << std::endl
0334                       << std::endl
0335                       << idealRotation.transposed() << std::endl
0336                       << std::endl
0337                       << rot << std::endl
0338                       << std::endl;
0339             double phix = atan2(rot.yz(), rot.zz());
0340             double phiy = asin(-rot.xz());
0341             double phiz = atan2(rot.xy(), rot.xx());
0342 
0343             std::cout << "phix=\"" << phix << "\" phiy=\"" << phiy << "\" phiz=\"" << phiz << std::endl;
0344 
0345             align::EulerAngles eulerAngles = align::toAngles((*alignable)->globalRotation());
0346             std::cout << "alpha=\"" << eulerAngles(1) << "\" beta=\"" << eulerAngles(2) << "\" gamma=\""
0347                       << eulerAngles(3) << std::endl;
0348             eulerAngles = align::toAngles(idealRotation);
0349             std::cout << "alpha=\"" << eulerAngles(1) << "\" beta=\"" << eulerAngles(2) << "\" gamma=\""
0350                       << eulerAngles(3) << std::endl;
0351             eulerAngles = align::toAngles(rot);
0352             std::cout << "alpha=\"" << eulerAngles(1) << "\" beta=\"" << eulerAngles(2) << "\" gamma=\""
0353                       << eulerAngles(3) << std::endl;
0354           }
0355         }
0356       }
0357 
0358       else if (m_relativeto == 2 && (*alignable)->mother() != nullptr) {
0359         align::PositionType globalPosition = (*alignable)->mother()->globalPosition();
0360         align::RotationType globalRotation = (*alignable)->mother()->globalRotation();
0361 
0362         pos = align::PositionType(globalRotation * (pos.basicVector() - globalPosition.basicVector()));
0363         rot = rot * globalRotation.transposed();
0364 
0365         str_relativeto = std::string("container");
0366       }
0367 
0368       else
0369         assert(false);  // can't happen: see constructor
0370 
0371       outputFile << "  <setposition relativeto=\"" << str_relativeto << "\" "
0372                  << "x=\"" << pos.x() << "\" y=\"" << pos.y() << "\" z=\"" << pos.z() << "\" ";
0373 
0374       if (m_eulerAngles) {
0375         align::EulerAngles eulerAngles = align::toAngles(rot);
0376         outputFile << "alpha=\"" << eulerAngles(1) << "\" beta=\"" << eulerAngles(2) << "\" gamma=\"" << eulerAngles(3)
0377                    << "\" />" << std::endl;
0378       }
0379 
0380       else {
0381         // the angle convention originally used in alignment, also known as "non-standard Euler angles with a Z-Y-X convention"
0382         //         // this also gets the sign convention right
0383         double phix = atan2(rot.yz(), rot.zz());
0384         double phiy = asin(-rot.xz());
0385         double phiz = atan2(rot.xy(), rot.xx());
0386 
0387         outputFile << "phix=\"" << phix << "\" phiy=\"" << phiy << "\" phiz=\"" << phiz << "\" />" << std::endl;
0388       }
0389 
0390       if (m_survey) {
0391         align::ErrorMatrix err = (*alignable)->survey()->errors();
0392 
0393         outputFile << "  <setsurveyerr"
0394                    << " xx=\"" << err(0, 0) << "\" xy=\"" << err(0, 1) << "\" xz=\"" << err(0, 2) << "\" xa=\""
0395                    << err(0, 3) << "\" xb=\"" << err(0, 4) << "\" xc=\"" << err(0, 5) << "\" yy=\"" << err(1, 1)
0396                    << "\" yz=\"" << err(1, 2) << "\" ya=\"" << err(1, 3) << "\" yb=\"" << err(1, 4) << "\" yc=\""
0397                    << err(1, 5) << "\" zz=\"" << err(2, 2) << "\" za=\"" << err(2, 3) << "\" zb=\"" << err(2, 4)
0398                    << "\" zc=\"" << err(2, 5) << "\" aa=\"" << err(3, 3) << "\" ab=\"" << err(3, 4) << "\" ac=\""
0399                    << err(3, 5) << "\" bb=\"" << err(4, 4) << "\" bc=\"" << err(4, 5) << "\" cc=\"" << err(5, 5)
0400                    << "\" />" << std::endl;
0401       }
0402 
0403       else if (rawId != 0) {
0404         CLHEP::HepSymMatrix err = errors[(*alignable)->id()];
0405 
0406         outputFile << "  <setape xx=\"" << err(1, 1) << "\" xy=\"" << err(1, 2) << "\" xz=\"" << err(1, 3) << "\" xa=\""
0407                    << err(1, 4) << "\" xb=\"" << err(1, 5) << "\" xc=\"" << err(1, 6) << "\" yy=\"" << err(2, 2)
0408                    << "\" yz=\"" << err(2, 3) << "\" ya=\"" << err(2, 4) << "\" yb=\"" << err(2, 5) << "\" yc=\""
0409                    << err(2, 6) << "\" zz=\"" << err(3, 3) << "\" za=\"" << err(3, 4) << "\" zb=\"" << err(3, 5)
0410                    << "\" zc=\"" << err(3, 6) << "\" aa=\"" << err(4, 4) << "\" ab=\"" << err(4, 5) << "\" ac=\""
0411                    << err(4, 6) << "\" bb=\"" << err(5, 5) << "\" bc=\"" << err(5, 6) << "\" cc=\"" << err(6, 6)
0412                    << "\" />" << std::endl;
0413       }
0414 
0415       outputFile << "</operation>" << std::endl << std::endl;
0416 
0417     }  // end if not suppressed
0418 
0419     // write superstructures before substructures: this is important because <setape> overwrites all substructures' APEs
0420     if (ideal != ideals.end()) {
0421       align::Alignables components = (*alignable)->components();
0422       align::Alignables ideal_components = (*ideal)->components();
0423       writeComponents(components, ideal_components, errors, outputFile, doDet, objectIdProvider);
0424       ++ideal;  // important for synchronization in the "for" loop!
0425     } else {
0426       align::Alignables components = (*alignable)->components();
0427       align::Alignables dummy;
0428       writeComponents(components, dummy, errors, outputFile, doDet, objectIdProvider);
0429     }
0430   }  // end loop over alignables
0431 }
0432 
0433 //
0434 // const member functions
0435 //
0436 
0437 //
0438 // static member functions
0439 //