Mantid
Loading...
Searching...
No Matches
Instrument.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8#include "MantidBeamline/ComponentInfo.h"
9#include "MantidBeamline/DetectorInfo.h"
21#include "MantidKernel/Logger.h"
23#include "MantidKernel/Unit.h"
24#include "MantidNexus/NexusFile.h"
25
26#include <algorithm>
27#include <memory>
28#include <queue>
29#include <utility>
30
31using namespace Mantid::Kernel;
34
35namespace Mantid::Geometry {
36
37namespace {
38Kernel::Logger g_log("Instrument");
39
40void raiseDuplicateDetectorError(const size_t detectorId) {
41 std::stringstream sstream;
42 sstream << "Instrument Definition corrupt. Detector with ID " << detectorId << " already exists.";
43 throw Exception::InstrumentDefinitionError(sstream.str());
44}
45} // namespace
46
49 : CompAssembly(), m_detectorCache(), m_sourceCache(nullptr), m_sampleCache(nullptr), m_defaultView("3D"),
50 m_defaultViewAxis("Z+"), m_referenceFrame(new ReferenceFrame) {}
51
53Instrument::Instrument(const std::string &name)
54 : CompAssembly(name), m_detectorCache(), m_sourceCache(nullptr), m_sampleCache(nullptr), m_defaultView("3D"),
55 m_defaultViewAxis("Z+"), m_referenceFrame(new ReferenceFrame) {}
56
61Instrument::Instrument(const std::shared_ptr<const Instrument> &instr, const std::shared_ptr<ParameterMap> &map)
62 : CompAssembly(instr.get(), map.get()), m_sourceCache(instr->m_sourceCache), m_sampleCache(instr->m_sampleCache),
63 m_defaultView(instr->m_defaultView), m_defaultViewAxis(instr->m_defaultViewAxis), m_instr(instr),
64 m_map_nonconst(map), m_ValidFrom(instr->m_ValidFrom), m_ValidTo(instr->m_ValidTo),
65 m_referenceFrame(new ReferenceFrame) {
66 // Note that we do not copy m_detectorInfo and m_componentInfo into the parametrized instrument since the ParameterMap
67 // will make a copy, if applicable.
68}
69
75 : CompAssembly(instr), m_sourceCache(nullptr), m_sampleCache(nullptr), /* Should only be temporarily null */
76 m_logfileCache(instr.m_logfileCache), m_logfileUnit(instr.m_logfileUnit), m_defaultView(instr.m_defaultView),
77 m_defaultViewAxis(instr.m_defaultViewAxis), m_instr(), m_map_nonconst(), /* Should not be parameterized */
78 m_ValidFrom(instr.m_ValidFrom), m_ValidTo(instr.m_ValidTo), m_referenceFrame(instr.m_referenceFrame) {
79 // Note that we do not copy m_detectorInfo and m_componentInfo into the new instrument since they are only non-NULL
80 // for the base instrument, which should usually not be copied.
81
82 // Now we need to fill the detector, source and sample caches with pointers into the new instrument
83 std::vector<IComponent_const_sptr> children;
84 getChildren(children, true);
85 std::vector<IComponent_const_sptr>::const_iterator it;
86 for (it = children.begin(); it != children.end(); ++it) {
87 // First check if the current component is a detector and add to cache if it is
88 if (const IDetector *det = dynamic_cast<const Detector *>(it->get())) {
89 if (instr.isMonitor(det->getID()))
90 markAsMonitor(det);
91 else
92 markAsDetector(det);
93 continue;
94 }
95 // Now check whether the current component is the source or sample.
96 // As the majority of components will be detectors, we will rarely get to here
97 if (const auto *obj = dynamic_cast<const Component *>(it->get())) {
98 const std::string objName = obj->getName();
99 // This relies on the source and sample having a unique name. I think the way our instrument definition files work
100 // ensures this is the case.
101 if (objName == instr.m_sourceCache->getName()) {
103 continue;
104 }
105 if (objName == instr.m_sampleCache->getName()) {
107 continue;
108 }
109 }
110 }
111}
112
120Instrument::Instrument(const Instrument &instr, bool copyCache)
121 : CompAssembly(), m_sourceCache(nullptr), m_sampleCache(nullptr), /* Should only be temporarily null */
122 m_logfileCache(instr.m_logfileCache), m_logfileUnit(instr.m_logfileUnit), m_defaultView(instr.m_defaultView),
123 m_defaultViewAxis(instr.m_defaultViewAxis), m_instr(), m_map_nonconst(), /* Should not be parameterized */
124 m_ValidFrom(instr.m_ValidFrom), m_ValidTo(instr.m_ValidTo), m_referenceFrame(instr.m_referenceFrame) {
125 UNUSED_ARG(copyCache);
126 setName(instr.getName() + "_clone");
127 // add in the sample and the source
128 auto sampleComp = instr.getSample();
129 auto sourceComp = instr.getSource();
130 if (!sampleComp || !sourceComp) {
131 throw std::runtime_error("Cannot copy instrument: source instrument must have valid sample and source components");
132 }
133 auto sample = sampleComp->clone();
134 auto source = sourceComp->clone();
135 add(sample);
136 add(source);
137 markAsSource(source);
138 markAsSamplePos(sample);
139 // also add in the monitors
140 std::vector<IComponent_const_sptr> children;
141 instr.getChildren(children, true);
142 for (auto const &child : children) {
143 if (IDetector const *det = dynamic_cast<Detector const *>(child.get())) {
144 if (instr.isMonitor(det->getID())) {
145 auto dclone = dynamic_cast<IDetector *>(det->clone());
146 add(dclone);
147 markAsMonitor(dclone);
148 }
149 }
150 }
151}
152
154Instrument *Instrument::clone() const { return new Instrument(*this); }
155
158 if (m_map)
159 return m_instr;
160 else
161 throw std::runtime_error("Instrument::baseInstrument() called for a "
162 "non-parametrized instrument.");
163}
164
171 if (m_map)
172 return m_map_nonconst;
173 else
174 throw std::runtime_error("Instrument::getParameterMap() called for a "
175 "non-parametrized instrument.");
176}
177
185 if (m_map) {
186 if (m_instr->getPhysicalInstrument()) {
187 // A physical instrument should use the same parameter map as the 'main'
188 // instrument. This constructor automatically sets the instrument as the
189 // owning instrument in the ParameterMap. We need to undo this immediately
190 // since the ParameterMap must always be owned by the neutronic
191 // instrument.
192 return std::make_shared<Instrument>(m_instr->getPhysicalInstrument(), m_map_nonconst);
193 } else {
194 return Instrument_const_sptr();
195 }
196 } else {
198 }
199}
200
206void Instrument::setPhysicalInstrument(std::unique_ptr<Instrument> physInst) {
207 if (!m_map) {
208 physInst->m_isPhysicalInstrument = true;
209 m_physicalInstrument = std::move(physInst);
210 } else
211 throw std::runtime_error("Instrument::setPhysicalInstrument() called on a "
212 "parametrized instrument.");
213}
214
215//------------------------------------------------------------------------------------------
219 out_map.clear();
220 auto it = out_map.end();
221 if (m_map) {
222 // Get the base instrument detectors
223 const auto &in_dets = m_instr->m_detectorCache;
224 // And turn them into parametrized versions
225 for (const auto &in_det : in_dets) {
226 it = out_map.emplace_hint(it, in_det.id(), ParComponentFactory::createDetector(in_det.detector().get(), m_map));
227 }
228 } else {
229 // You can just return the detector cache directly.
230 for (const auto &in_det : m_detectorCache) {
231 it = out_map.emplace_hint(it, in_det.id(), in_det.detector());
232 }
233 }
234}
235
236//------------------------------------------------------------------------------------------
238std::vector<detid_t> Instrument::getDetectorIDs(bool skipMonitors) const {
239 const auto &in_dets = m_map ? m_instr->m_detectorCache : m_detectorCache;
240 std::vector<detid_t> out;
241 out.reserve(in_dets.size());
242 for (const auto &in_det : in_dets) {
243 if (!skipMonitors || !in_det.isMonitor()) {
244 out.emplace_back(in_det.id());
245 }
246 }
247 return out;
248}
249
253std::vector<detid_t> Instrument::getMonitorIDs() const {
254 // Monitors cannot be parametrized. So just return the base.
255 if (m_map)
256 return m_instr->getMonitorIDs();
257
258 std::vector<detid_t> mons;
259 for (const auto &item : m_detectorCache)
260 if (item.isMonitor())
261 mons.emplace_back(item.id());
262 return mons;
263}
264
266std::size_t Instrument::getNumberDetectors(bool skipMonitors) const {
267 const auto &in_dets = m_map ? m_instr->m_detectorCache : m_detectorCache;
268
269 std::size_t numDetIDs = in_dets.size();
270
271 if (skipMonitors) // this slow, but gets the right answer
272 {
273 std::size_t monitors(0);
274 monitors = std::count_if(in_dets.cbegin(), in_dets.cend(), [](const auto &in_det) { return in_det.isMonitor(); });
275 return (numDetIDs - monitors);
276 } else {
277 return numDetIDs;
278 }
279}
280
288 const auto &in_dets = m_map ? m_instr->m_detectorCache : m_detectorCache;
289 // ensure there are detectors
290 if (in_dets.empty())
291 throw std::runtime_error("No detectors on this instrument. Can't find min/max ids");
292 // ensure the cache is finalized
293 if (!in_dets.isFinalized())
294 throw std::runtime_error("Instrument definition is not finalized. Can't find min/max ids");
295 min = in_dets.minID();
296 max = in_dets.maxID();
297}
298
308void Instrument::getDetectorsInBank(std::vector<IDetector_const_sptr> &dets, const IComponent &comp) const {
309 const auto bank = dynamic_cast<const ICompAssembly *>(&comp);
310 if (bank) {
311 // Get a vector of children (recursively)
312 std::vector<std::shared_ptr<const IComponent>> children;
313 bank->getChildren(children, true);
314 std::vector<std::shared_ptr<const IComponent>>::iterator it;
315 for (it = children.begin(); it != children.end(); ++it) {
316 IDetector_const_sptr det = std::dynamic_pointer_cast<const IDetector>(*it);
317 if (det) {
318 dets.emplace_back(det);
319 }
320 }
321 }
322}
323
334void Instrument::getDetectorsInBank(std::vector<IDetector_const_sptr> &dets, const std::string &bankName) const {
335 std::shared_ptr<const IComponent> comp = this->getComponentByName(bankName);
336 if (!comp) {
337 throw Kernel::Exception::NotFoundError("Instrument: Could not find component", bankName);
338 }
339 getDetectorsInBank(dets, *comp);
340}
341
342std::set<detid_t> Instrument::getDetectorIDsInBank(const std::string &bankName) const {
343 std::set<detid_t> detIDs;
344 std::vector<IDetector_const_sptr> detectors;
345 getDetectorsInBank(detectors, bankName);
346
347 for (const auto &det : detectors) {
348 detIDs.emplace(det->getID());
349 }
350 return detIDs;
351}
352
356bool Instrument::hasSource() const { return m_sourceCache; }
357
361bool Instrument::hasSample() const { return m_sampleCache; }
362
367 if (!m_sourceCache) {
368 g_log.warning("In Instrument::getSource(). No source has been set.");
370 } else if (m_map) {
371 auto sourceCache = static_cast<const Instrument *>(m_base)->m_sourceCache;
372 if (dynamic_cast<const ObjComponent *>(sourceCache))
373 return IComponent_const_sptr(new ObjComponent(sourceCache, m_map));
374 else if (dynamic_cast<const CompAssembly *>(sourceCache))
375 return IComponent_const_sptr(new CompAssembly(sourceCache, m_map));
376 else if (dynamic_cast<const Component *>(sourceCache))
377 return IComponent_const_sptr(new Component(sourceCache, m_map));
378 else {
379 g_log.error("In Instrument::getSource(). Source is not a recognised "
380 "component type.");
381 g_log.error("Try to assume it is a Component.");
382 return IComponent_const_sptr(new ObjComponent(sourceCache, m_map));
383 }
384 } else {
386 }
387}
388
393 if (!m_sampleCache) {
394 g_log.warning("In Instrument::getSamplePos(). No SamplePos has been set.");
396 } else if (m_map) {
397 auto sampleCache = static_cast<const Instrument *>(m_base)->m_sampleCache;
398 if (dynamic_cast<const ObjComponent *>(sampleCache))
399 return IComponent_const_sptr(new ObjComponent(sampleCache, m_map));
400 else if (dynamic_cast<const CompAssembly *>(sampleCache))
401 return IComponent_const_sptr(new CompAssembly(sampleCache, m_map));
402 else if (dynamic_cast<const Component *>(sampleCache))
403 return IComponent_const_sptr(new Component(sampleCache, m_map));
404 else {
405 g_log.error("In Instrument::getSamplePos(). SamplePos is not a "
406 "recognised component type.");
407 g_log.error("Try to assume it is a Component.");
408 return IComponent_const_sptr(new ObjComponent(sampleCache, m_map));
409 }
410 } else {
412 }
413}
414
420
421//------------------------------------------------------------------------------------------
426std::shared_ptr<const IComponent> Instrument::getComponentByID(const IComponent *id) const {
427 const auto *base = static_cast<const IComponent *>(id);
428 if (m_map)
429 return ParComponentFactory::create(std::shared_ptr<const IComponent>(base, NoDeleting()), m_map);
430 else
431 return std::shared_ptr<const IComponent>(base, NoDeleting());
432}
433
442std::vector<std::shared_ptr<const IComponent>> Instrument::getAllComponentsWithName(const std::string &cname) const {
443 std::shared_ptr<const IComponent> node = std::shared_ptr<const IComponent>(this, NoDeleting());
444 std::vector<std::shared_ptr<const IComponent>> retVec;
445 // Check the instrument name first
446 if (this->getName() == cname) {
447 retVec.emplace_back(node);
448 }
449 // Same algorithm as used in getComponentByName() but searching the full tree
450 std::deque<std::shared_ptr<const IComponent>> nodeQueue;
451 // Need to be able to enter the while loop
452 nodeQueue.emplace_back(node);
453 while (!nodeQueue.empty()) {
454 node = nodeQueue.front();
455 nodeQueue.pop_front();
456 int nchildren(0);
457 std::shared_ptr<const ICompAssembly> asmb = std::dynamic_pointer_cast<const ICompAssembly>(node);
458 if (asmb) {
459 nchildren = asmb->nelements();
460 }
461 for (int i = 0; i < nchildren; ++i) {
462 std::shared_ptr<const IComponent> comp = (*asmb)[i];
463 if (comp->getName() == cname) {
464 retVec.emplace_back(comp);
465 } else {
466 nodeQueue.emplace_back(comp);
467 }
468 }
469 } // while-end
470
471 // If we have reached here then the search failed
472 return retVec;
473}
474
483Instrument::DetectorCache::iterator Instrument::DetectorCache::lower_bound(detid_t id) {
484 if (!isFinalized()) {
485 throw std::runtime_error("lower_bound() called on non-finalized DetectorCache");
486 }
487 return std::lower_bound(begin(), end(), id,
488 [](DetectorCacheEntry const &entry, detid_t id) { return entry.id() < id; });
489}
490
500Instrument::DetectorCache::const_iterator Instrument::DetectorCache::lower_bound(detid_t id) const {
501 if (!isFinalized()) {
502 throw std::runtime_error("lower_bound() called on non-finalized DetectorCache");
503 }
504 return std::lower_bound(cbegin(), cend(), id,
505 [](DetectorCacheEntry const &entry, detid_t id) { return entry.id() < id; });
506}
507
515Instrument::DetectorCache::iterator Instrument::DetectorCache::find(detid_t id) {
516 if (!isFinalized()) {
517 throw std::runtime_error("find() called on non-finalized DetectorCache");
518 }
519 auto it = lower_bound(id);
520 if (it != end() && it->id() == id) {
521 return it;
522 } else {
523 return end();
524 }
525}
526
534Instrument::DetectorCache::const_iterator Instrument::DetectorCache::find(detid_t id) const {
535 if (!isFinalized()) {
536 throw std::runtime_error("find() called on non-finalized DetectorCache");
537 }
538 auto const it = lower_bound(id);
539 if (it != cend() && it->id() == id) {
540 return it;
541 } else {
542 return cend();
543 }
544}
545
555 // ensure instrument is finalized
556 if (!isFinalized())
557 throw std::runtime_error("Instrument definition is not finalized. Can't search for detector ID " +
558 std::to_string(detector_id));
559
560 const auto &in_dets = m_map ? m_instr->m_detectorCache : m_detectorCache;
561 const auto it = in_dets.find(detector_id);
562 if (it == in_dets.end()) {
563 std::stringstream readInt;
564 readInt << detector_id;
565 throw Kernel::Exception::NotFoundError("Instrument: Detector with ID " + readInt.str() + " not found.", "");
566 }
567 IDetector_const_sptr baseDet = it->detector();
568
569 if (!m_map)
570 return baseDet;
571
572 auto det = ParComponentFactory::createDetector(baseDet.get(), m_map);
573 return det;
574}
575
581const IDetector *Instrument::getBaseDetector(const detid_t &detector_id) const {
582 // ensure instrument is finalized
583 if (!m_map)
584 throw std::runtime_error("Instrument::getBaseDetector() called on a non-parametrized instrument.");
585 if (!isFinalized())
586 throw std::runtime_error("Instrument definition is not finalized. Can't find base detector ID " +
587 std::to_string(detector_id));
588
589 auto it = m_instr->m_detectorCache.find(detector_id);
590 if (it == m_instr->m_detectorCache.end()) {
591 return nullptr;
592 }
593 return it->detector().get();
594}
595
596bool Instrument::isMonitor(const detid_t &detector_id) const {
597 // ensure instrument is finalized
598 if (!isFinalized())
599 throw std::runtime_error("Instrument definition is not finalized. Can't search for monitor ID " +
600 std::to_string(detector_id));
601
602 const auto &in_dets = m_map ? m_instr->m_detectorCache : m_detectorCache;
603 const auto it = in_dets.find(detector_id);
604 if (it == in_dets.end())
605 return false;
606 return it->isMonitor();
607}
608
609bool Instrument::isMonitor(const std::set<detid_t> &detector_ids) const {
610 if (detector_ids.empty())
611 return false;
612
613 return std::any_of(detector_ids.cbegin(), detector_ids.cend(),
614 [this](const auto detector_id) { return isMonitor(detector_id); });
615}
616
623IDetector_const_sptr Instrument::getDetectorG(const std::set<detid_t> &det_ids) const {
624 const size_t ndets(det_ids.size());
625 if (ndets == 1) {
626 return this->getDetector(*det_ids.begin());
627 } else {
628 std::shared_ptr<DetectorGroup> det_group = std::make_shared<DetectorGroup>();
629 for (const auto detID : det_ids) {
630 det_group->addDetector(this->getDetector(detID));
631 }
632 return det_group;
633 }
634}
635
640std::vector<IDetector_const_sptr> Instrument::getDetectors(const std::vector<detid_t> &det_ids) const {
641 std::vector<IDetector_const_sptr> dets_ptr;
642 dets_ptr.reserve(det_ids.size());
643 std::vector<detid_t>::const_iterator it;
644 for (it = det_ids.begin(); it != det_ids.end(); ++it) {
645 dets_ptr.emplace_back(this->getDetector(*it));
646 }
647 return dets_ptr;
648}
649
654std::vector<IDetector_const_sptr> Instrument::getDetectors(const std::set<detid_t> &det_ids) const {
655 std::vector<IDetector_const_sptr> dets_ptr;
656 dets_ptr.reserve(det_ids.size());
657 std::set<detid_t>::const_iterator it;
658 for (it = det_ids.begin(); it != det_ids.end(); ++it) {
659 dets_ptr.emplace_back(this->getDetector(*it));
660 }
661 return dets_ptr;
662}
663
675 if (m_map)
676 throw std::runtime_error("Instrument::markAsSamplePos() called on a "
677 "parametrized Instrument object.");
678
679 auto objComp = dynamic_cast<const IObjComponent *>(comp);
680 if (objComp) {
681 throw std::runtime_error("Instrument::markAsSamplePos() called on an IObjComponent "
682 "object that supports shape definition. Sample is prevented from "
683 "being this type because the shape must only be stored in "
684 "ExperimentInfo::m_sample.");
685 }
686
687 if (!m_sampleCache) {
688 if (comp->getName().empty()) {
689 throw Exception::InstrumentDefinitionError("The sample component is required to have a name.");
690 }
691 m_sampleCache = comp;
692 } else {
693 g_log.warning("Have already added samplePos component to the _sampleCache.");
694 }
695}
696
708 if (m_map)
709 throw std::runtime_error("Instrument::markAsSource() called on a "
710 "parametrized Instrument object.");
711
712 if (!m_sourceCache) {
713 if (comp->getName().empty()) {
714 throw Exception::InstrumentDefinitionError("The source component is required to have a name.");
715 }
716 m_sourceCache = comp;
717 } else {
718 g_log.warning("Have already added source component to the _sourceCache.");
719 }
720}
721
731 if (m_map)
732 throw std::runtime_error("Instrument::markAsDetector() called on a "
733 "parametrized Instrument object.");
734 // ensure instrument is finalized
735 if (!isFinalized())
736 throw std::runtime_error("Instrument definition is not finalized. Add detector with markAsDetectorIncomplete, "
737 "then call markAsDetectorFinalized when finished.");
738
739 // Duplicate detector ids are forbidden
740 auto it = m_detectorCache.lower_bound(det->getID());
741 if ((it != m_detectorCache.end()) && (it->id() == det->getID())) {
742 raiseDuplicateDetectorError(det->getID());
743 }
744 // Create a (non-deleting) shared pointer to it
746 m_detectorCache.emplace(it, det->getID(), det_sptr, false);
747}
748
752 if (m_map)
753 throw std::runtime_error("Instrument::markAsDetector() called on a "
754 "parametrized Instrument object.");
755
757 // Create a (non-deleting) shared pointer to it
759 m_detectorCache.emplace_back(det->getID(), det_sptr, false);
760}
761
765 // We're already finalized! We can't finalize any further!
766 if (isFinalized())
767 return;
768
769 // Detectors (even when different objects) are NOT allowed to have duplicate
770 // ids. This method establishes the presence of duplicates.
771 std::sort(m_detectorCache.begin(), m_detectorCache.end(),
772 [](DetectorCacheEntry const &a, DetectorCacheEntry const &b) -> bool { return a.id() < b.id(); });
773
774 auto resultIt = std::adjacent_find(
775 m_detectorCache.begin(), m_detectorCache.end(),
776 [](DetectorCacheEntry const &a, DetectorCacheEntry const &b) -> bool { return a.id() == b.id(); });
777 if (resultIt != m_detectorCache.end()) {
778 raiseDuplicateDetectorError(resultIt->id());
779 } else {
781 }
782}
783
793 if (m_map)
794 throw std::runtime_error("Instrument::markAsMonitor() called on a "
795 "parametrized Instrument object.");
796 if (!isFinalized()) {
797 throw std::runtime_error("Instrument definition is not finalized. Add monitor with markAsMonitorIncomplete, then "
798 "call markAsDetectorFinalized when finished.");
799 }
800
801 // attempt to add monitor to instrument detector cache
802 markAsDetector(det);
803
804 // mark detector as a monitor
805 auto it = m_detectorCache.find(det->getID());
806 it->setIsMonitor(true);
807}
808
816 if (m_map)
817 throw std::runtime_error("Instrument::markAsMonitorIncomplete() called on a "
818 "parametrized Instrument object.");
819
821 // Create a (non-deleting) shared pointer to it
823 m_detectorCache.emplace_back(det->getID(), det_sptr, true);
824}
825
832 if (m_map)
833 throw std::runtime_error("Instrument::removeDetector() called on a "
834 "parameterized Instrument object.");
835 if (!isFinalized())
836 throw std::runtime_error("Instrument definition is not finalized. Can't remove detector with ID " +
837 std::to_string(det->getID()));
838
839 const detid_t id = det->getID();
840 // Remove the detector from the detector cache
841 const auto it = m_detectorCache.find(id);
842 // NOTE this operation is O(N) for the vector cache
843 m_detectorCache.erase(it);
844
845 // Remove it from the parent assembly (and thus the instrument).
846 // Evilness required here unfortunately.
847 auto *parentAssembly = dynamic_cast<CompAssembly *>(const_cast<IComponent *>(det->getBareParent()));
848 if (parentAssembly) // Should always be true, but check just in case
849 {
850 parentAssembly->remove(det);
851 }
852}
853
862 if (m_map)
863 throw std::runtime_error("Instrument::removeDetectorIncomplete() called on a "
864 "parameterized Instrument object.");
866 if (m_detectorCache.m_toRemove.empty()) {
868 }
869 m_detectorCache.m_toRemove.insert(det);
870}
871
877 if (m_map)
878 throw std::runtime_error("Instrument::removeDetectorFinalize() called on a "
879 "parameterized Instrument object.");
880
881 if (isFinalized()) {
883 return;
884 }
885
886 // Remove from the cache all the ones to be removed
887 auto newEnd = std::remove_if(m_detectorCache.begin(), m_detectorCache.end(), [this](const auto &entry) {
888 return m_detectorCache.m_toRemove.contains(entry.detector().get());
889 });
890 m_detectorCache.erase(newEnd, m_detectorCache.end());
891
892 // clear the removal set and finalize the cache
895}
896
902void Instrument::getBoundingBox(BoundingBox &assemblyBox) const {
903 if (m_map) {
904
905 if (m_map->hasComponentInfo(this->baseInstrument().get())) {
906 assemblyBox = m_map->componentInfo().boundingBox(index(), &assemblyBox);
907 return;
908 }
909
910 // Loop over the children and define a box large enough for all of them
911 ComponentID sourceID = getSource()->getComponentID();
912 assemblyBox = BoundingBox(); // this makes the instrument BB always axis aligned
913 int nchildren = nelements();
914 for (int i = 0; i < nchildren; ++i) {
915 IComponent_sptr comp = this->getChild(i);
916 if (comp && comp->getComponentID() != sourceID) {
917 BoundingBox compBox;
918 comp->getBoundingBox(compBox);
919 assemblyBox.grow(compBox);
920 }
921 }
922 } else {
923
924 if (!m_cachedBoundingBox) {
926 ComponentID sourceID = getSource()->getComponentID();
927 // Loop over the children and define a box large enough for all of them
928 for (const auto component : m_children) {
929 BoundingBox compBox;
930 if (component && component->getComponentID() != sourceID) {
931 component->getBoundingBox(compBox);
932 m_cachedBoundingBox->grow(compBox);
933 }
934 }
935 }
936 // Use cached box
937 assemblyBox = *m_cachedBoundingBox;
938 }
939}
940
941std::shared_ptr<const std::vector<IObjComponent_const_sptr>> Instrument::getPlottable() const {
942 if (m_map) {
943 // Get the 'base' plottable components
944 std::shared_ptr<const std::vector<IObjComponent_const_sptr>> objs = m_instr->getPlottable();
945
946 // Get a reference to the underlying vector, casting away the constness so that we
947 // can modify it to get our result rather than creating another long vector
948 auto &res = const_cast<std::vector<IObjComponent_const_sptr> &>(*objs);
949 const std::vector<IObjComponent_const_sptr>::size_type total = res.size();
950 for (std::vector<IObjComponent_const_sptr>::size_type i = 0; i < total; ++i) {
951 res[i] = std::dynamic_pointer_cast<const Detector>(ParComponentFactory::create(objs->at(i), m_map));
952 }
953 return objs;
954
955 } else {
956 // Base instrument
957 auto res = std::make_shared<std::vector<IObjComponent_const_sptr>>();
958 res->reserve(m_detectorCache.size() + 10);
959 appendPlottable(*this, *res);
960 return res;
961 }
962}
963
964void Instrument::appendPlottable(const CompAssembly &ca, std::vector<IObjComponent_const_sptr> &lst) const {
965 for (int i = 0; i < ca.nelements(); i++) {
966 IComponent *c = ca[i].get();
967 const auto *a = dynamic_cast<CompAssembly *>(c);
968 if (a)
969 appendPlottable(*a, lst);
970 else {
971 auto *d = dynamic_cast<Detector *>(c);
972 auto *o = dynamic_cast<ObjComponent *>(c);
973 if (d)
974 lst.emplace_back(IObjComponent_const_sptr(d, NoDeleting()));
975 else if (o)
976 lst.emplace_back(IObjComponent_const_sptr(o, NoDeleting()));
977 else
978 g_log.error() << "Unknown comp type\n";
979 }
980 }
981}
982
983//------------------------------------------------------------------------------------------------
992void Instrument::getInstrumentParameters(double &l1, Kernel::V3D &beamline, double &beamline_norm,
993 Kernel::V3D &samplePos) const {
994 // Get some positions
995 const IComponent_const_sptr sourceObj = this->getSource();
996 if (sourceObj == nullptr) {
997 throw Exception::InstrumentDefinitionError("Failed to get source component from instrument");
998 }
999 const Kernel::V3D sourcePos = sourceObj->getPos();
1000 samplePos = this->getSample()->getPos();
1001 beamline = samplePos - sourcePos;
1002 beamline_norm = 2.0 * beamline.norm();
1003
1004 // Get the distance between the source and the sample (assume in metres)
1005 IComponent_const_sptr sample = this->getSample();
1006 try {
1007 l1 = this->getSource()->getDistance(*sample);
1008 } catch (Exception::NotFoundError &) {
1009 throw Exception::InstrumentDefinitionError("Unable to calculate source-sample distance ", this->getName());
1010 }
1011}
1012
1013//--------------------------------------------------------------------------------------------
1016void Instrument::setFilename(const std::string &filename) {
1017 if (m_map)
1018 m_instr->m_filename = filename;
1019 else
1020 m_filename = filename;
1021}
1022
1025const std::string &Instrument::getFilename() const {
1026 if (m_map)
1027 return m_instr->getFilename();
1028 else
1029 return m_filename;
1030}
1031
1033void Instrument::setXmlText(const std::string &XmlText) {
1034 if (m_map)
1035 m_instr->m_xmlText = XmlText;
1036 else
1037 m_xmlText = XmlText;
1038}
1039
1041const std::string &Instrument::getXmlText() const {
1042 if (m_map)
1043 return m_instr->getXmlText();
1044 else
1045 return m_xmlText;
1046}
1047
1048//--------------------------------------------------------------------------------------------
1057void Instrument::saveNexus(Nexus::File *file, const std::string &group) const {
1058 file->makeGroup(group, "NXinstrument", true);
1059 file->putAttr("version", 1);
1060
1061 file->writeData("name", getName());
1062
1063 // XML contents of instrument, as a NX note
1064 file->makeGroup("instrument_xml", "NXnote", true);
1065 const std::string &xmlText = getXmlText();
1066 if (xmlText.empty())
1067 g_log.warning() << "Saving Instrument with no XML data. If this was "
1068 "instrument data you may not be able to load this data "
1069 "back into Mantid, for fitted/analysed data this "
1070 "warning can be ignored.\n";
1071 file->writeData("data", xmlText);
1072 file->writeData("type", "text/xml"); // mimetype
1073 file->writeData("description", "XML contents of the instrument IDF file.");
1074 file->closeGroup();
1075
1076 // Now the parameter map, as a NXnote via its saveNexus method
1077 if (isParametrized()) {
1078 // Map with data extracted from DetectorInfo -> legacy compatible files.
1079 const auto &params = makeLegacyParameterMap();
1080 params->saveNexus(file, "instrument_parameter_map");
1081 }
1082
1083 // Add physical detector data
1084 auto detectorIDs = getDetectorIDs(true);
1085 if (!detectorIDs.empty()) {
1086 // Add detectors group
1087 file->makeGroup("physical_detectors", "NXdetector", true);
1088 file->writeData("number_of_detectors", uint64_t(detectorIDs.size()));
1089 saveDetectorSetInfoToNexus(file, detectorIDs);
1090 file->closeGroup(); // detectors
1091 }
1092
1093 // Add monitor data
1094 auto monitorIDs = getMonitorIDs();
1095 if (!monitorIDs.empty()) {
1096 // Add Monitors group
1097 file->makeGroup("physical_monitors", "NXmonitor", true);
1098 file->writeData("number_of_monitors", uint64_t(monitorIDs.size()));
1099 saveDetectorSetInfoToNexus(file, monitorIDs);
1100 file->closeGroup(); // monitors
1101 }
1102
1103 file->closeGroup();
1104}
1105
1106/* A private helper function so save information about a set of detectors to
1107 * Nexus
1108 * @param file :: open Nexus file ready to recieve the info about the set of
1109 * detectors
1110 * a group must be open that has only one call of this function.
1111 * @param detIDs :: the dectector IDs of the detectors belonging to the set
1112 */
1113void Instrument::saveDetectorSetInfoToNexus(Nexus::File *file, const std::vector<detid_t> &detIDs) const {
1114
1115 size_t nDets = detIDs.size();
1116 if (nDets == 0)
1117 return;
1118 auto detectors = getDetectors(detIDs);
1119
1121 Kernel::V3D sample_pos;
1122 if (sample)
1123 sample_pos = sample->getPos();
1124
1125 std::vector<double> a_angles(nDets);
1126 std::vector<double> p_angles(nDets);
1127 std::vector<double> distances(nDets);
1128
1129 for (size_t i = 0; i < nDets; i++) {
1130 if (sample) {
1131 Kernel::V3D pos = detectors[i]->getPos() - sample_pos;
1132 pos.getSpherical(distances[i], p_angles[i], a_angles[i]);
1133 } else {
1134 a_angles[i] = detectors[i]->getPhi() * 180.0 / M_PI;
1135 }
1136 }
1137 file->writeData("detector_number", detIDs);
1138 file->writeData("azimuthal_angle", a_angles);
1139 file->openData("azimuthal_angle");
1140 file->putAttr("units", "degree");
1141 file->closeData();
1142 if (sample) {
1143 file->writeData("polar_angle", p_angles);
1144 file->openData("polar_angle");
1145 file->putAttr("units", "degree");
1146 file->closeData();
1147 file->writeData("distance", distances);
1148 file->openData("distance");
1149 file->putAttr("units", "metre");
1150 file->closeData();
1151 }
1152}
1153
1154//--------------------------------------------------------------------------------------------
1159void Instrument::loadNexus(Nexus::File *file, const std::string &group) {
1160 file->openGroup(group, "NXinstrument");
1161 file->closeGroup();
1162}
1163
1168void Instrument::setReferenceFrame(std::shared_ptr<ReferenceFrame> frame) { m_referenceFrame = std::move(frame); }
1169
1174std::shared_ptr<const ReferenceFrame> Instrument::getReferenceFrame() const {
1175 if (m_map) {
1176 return m_instr->getReferenceFrame();
1177 } else {
1178 return m_referenceFrame;
1179 }
1180}
1181
1190void Instrument::setDefaultView(const std::string &type) {
1191 std::string typeUC(type);
1192 std::transform(typeUC.begin(), typeUC.end(), typeUC.begin(), toupper);
1193 if (typeUC == "3D" || typeUC == "CYLINDRICAL_X" || typeUC == "CYLINDRICAL_Y" || typeUC == "CYLINDRICAL_Z" ||
1194 typeUC == "SPHERICAL_X" || typeUC == "SPHERICAL_Y" || typeUC == "SPHERICAL_Z") {
1195 m_defaultView = typeUC;
1196 } else {
1197 m_defaultView = "3D";
1198 g_log.warning() << type << " is not allowed as an instrument view type. Default to \"3D\"" << '\n';
1199 }
1200}
1201
1206void Instrument::setValidFromDate(const Types::Core::DateAndTime &val) {
1207 Types::Core::DateAndTime earliestAllowedDate("1900-01-31 23:59:01");
1208 if (val < earliestAllowedDate) {
1210 "The valid-from <instrument> tag date must be from 1900-01-31 23:59:01 "
1211 "or later",
1212 m_filename);
1213 }
1214 m_ValidFrom = val;
1215}
1216
1218 std::queue<IComponent_const_sptr> compQueue; // Search queue
1220
1221 bool foundRect = false;
1222 bool foundNonRect = false;
1223
1225
1226 while (!compQueue.empty() && !(foundRect && foundNonRect)) {
1227 comp = compQueue.front();
1228 compQueue.pop();
1229
1230 if (!validateComponentProperties(comp))
1231 continue;
1232
1233 if (dynamic_cast<const RectangularDetector *>(comp.get())) {
1234 foundRect = true;
1235 } // If component isn't a ComponentAssembly, we know it is a non-rectangular detector. Otherwise check its children
1236 else if (!addAssemblyChildrenToQueue(compQueue, comp)) {
1237 foundNonRect = true;
1238 }
1239 }
1240
1241 // Found both
1242 if (foundRect && foundNonRect)
1244 // Found only rectangular
1245 else if (foundRect)
1247 // Found only non-rectangular
1248 else
1250}
1251
1253 // Skip source, if has one
1254 if (m_sourceCache && m_sourceCache->getComponentID() == component->getComponentID())
1255 return false;
1256
1257 // Skip sample, if has one
1258 if (m_sampleCache && m_sampleCache->getComponentID() == component->getComponentID())
1259 return false;
1260
1261 // Skip monitors
1262 IDetector_const_sptr detector = std::dynamic_pointer_cast<const IDetector>(component);
1263 if (detector && isMonitor(detector->getID()))
1264 return false;
1265
1266 // skip choppers, slits and supermirrors - HACK!
1267 const auto &name = component->getName();
1268 if (name == "chopper-position" || name.substr(0, 4) == "slit" || name == "supermirror") {
1269 return false;
1270 }
1271
1272 return true;
1273}
1274
1275void Instrument::addInstrumentChildrenToQueue(std::queue<IComponent_const_sptr> &queue) const {
1276 // Add all the direct children of the instrument
1277 for (int i = 0; i < nelements(); i++)
1278 queue.push(getChild(i));
1279}
1280
1283bool Instrument::addAssemblyChildrenToQueue(std::queue<IComponent_const_sptr> &queue,
1284 IComponent_const_sptr component) const {
1285 if (auto const assembly = std::dynamic_pointer_cast<const ICompAssembly>(component)) {
1286 for (int i = 0; i < assembly->nelements(); i++)
1287 queue.push(assembly->getChild(i));
1288 return true;
1289 }
1290 return false;
1291}
1292
1294bool Instrument::isMonitorViaIndex(const size_t index) const {
1295 const auto &in_dets = m_map ? m_instr->m_detectorCache : m_detectorCache;
1296 if (!in_dets.isFinalized())
1297 throw std::runtime_error("Instrument::isMonitorViaIndex: detector cache is not finalized");
1298 if (index >= in_dets.size())
1299 throw std::out_of_range("Instrument::isMonitorViaIndex: index out of range");
1300 return in_dets[index].isMonitor();
1301}
1302
1303bool Instrument::isEmptyInstrument() const { return this->nelements() == 0; }
1304
1306size_t Instrument::detectorIndex(const detid_t detID) const {
1307 if (!isFinalized())
1308 throw std::runtime_error("Instrument definition is not finalized. Can't get detector index for ID " +
1309 std::to_string(detID));
1310
1311 const auto &in_dets = m_map ? m_instr->m_detectorCache : m_detectorCache;
1312 const auto it = in_dets.find(detID);
1313 return std::distance(in_dets.cbegin(), it);
1314}
1315
1318std::shared_ptr<ParameterMap> Instrument::makeLegacyParameterMap() const {
1319 if (!isFinalized())
1320 throw std::runtime_error("Instrument definition is not finalized. Can't create legacy ParameterMap.");
1321
1322 auto pmap = std::make_shared<ParameterMap>(*getParameterMap());
1323 // Instrument is only needed for DetectorInfo access so it is not needed. This
1324 // also clears DetectorInfo and ComponentInfo (information will be stored
1325 // directly in pmap so we do not need them).
1326 pmap->setInstrument(nullptr);
1327
1328 const auto &baseInstr = m_map ? *m_instr : *this;
1329
1330 if (!getParameterMap()->hasComponentInfo(&baseInstr))
1331 return pmap;
1332
1333 // Tolerance 1e-9 m with rotation center at a distance of L = 1000 m as in
1334 // Beamline::DetectorInfo::isEquivalent.
1335 constexpr double d_max = 1e-9;
1336 constexpr double L = 1000.0;
1337 constexpr double safety_factor = 2.0;
1338 const double imag_norm_max = sin(d_max / (2.0 * L * safety_factor));
1339
1340 auto transformation = Eigen::Affine3d::Identity();
1341 int64_t oldParentIndex = -1;
1342
1343 const auto &componentInfo = getParameterMap()->componentInfo();
1344 const auto &detectorInfo = getParameterMap()->detectorInfo();
1345 for (size_t i = 0; i < componentInfo.size(); ++i) {
1346
1347 const int64_t parentIndex = componentInfo.parent(i);
1348 const bool makeTransform = parentIndex != oldParentIndex;
1349 bool isDetFixedInBank = false;
1350
1351 if (makeTransform) {
1352 oldParentIndex = parentIndex;
1353 const auto parentPos = toVector3d(componentInfo.position(parentIndex));
1354 const auto invParentRot = toQuaterniond(componentInfo.rotation(parentIndex)).conjugate();
1355
1356 transformation = invParentRot;
1357 transformation.translate(-parentPos);
1358 }
1359
1360 if (componentInfo.isDetector(i)) {
1361 isDetFixedInBank = ComponentInfoBankHelpers::isDetectorFixedInBank(componentInfo, i);
1362 if (detectorInfo.isMasked(i)) {
1363 auto const &baseDet = baseInstr.m_detectorCache[i].detector();
1364 pmap->forceUnsafeSetMasked(baseDet.get(), true);
1365 }
1366
1367 if (makeTransform) {
1368 // Special case: scaling for GridDetectorPixel.
1369 if (isDetFixedInBank) {
1370
1371 size_t panelIndex = componentInfo.parent(parentIndex);
1372 const auto panelID = componentInfo.componentID(panelIndex);
1373
1374 Eigen::Vector3d scale(1, 1, 1);
1375 if (auto scalex = pmap->get(panelID, "scalex"))
1376 scale[0] = 1.0 / scalex->value<double>();
1377 if (auto scaley = pmap->get(panelID, "scaley"))
1378 scale[1] = 1.0 / scaley->value<double>();
1379 transformation.prescale(scale);
1380 }
1381 }
1382 }
1383
1384 const auto componentId = componentInfo.componentID(i);
1385 const IComponent *baseComponent = componentId->getBaseComponent();
1386 // Generic sca scale factors
1387 const auto newScaleFactor = Kernel::toVector3d(componentInfo.scaleFactor(i));
1388 if ((newScaleFactor - toVector3d(baseComponent->getScaleFactor())).norm() >= 1e-9) {
1389 pmap->addV3D(componentId, ParameterMap::scale(), componentInfo.scaleFactor(i));
1390 }
1391
1392 // Undo parent transformation to obtain relative position/rotation.
1393 Eigen::Vector3d relPos = transformation * toVector3d(componentInfo.position(i));
1394 Eigen::Quaterniond relRot = toQuaterniond(componentInfo.relativeRotation(i));
1395
1396 // Tolerance 1e-9 m as in Beamline::DetectorInfo::isEquivalent.
1397 if ((relPos - toVector3d(baseComponent->getRelativePos())).norm() >= 1e-9) {
1398 if (isDetFixedInBank) {
1399 throw std::runtime_error(
1400 "Cannot create legacy ParameterMap: Position parameters for GridDetectorPixel are not supported");
1401 }
1402 pmap->addV3D(componentId, ParameterMap::pos(), Kernel::toV3D(relPos));
1403 }
1404 if ((relRot * toQuaterniond(baseComponent->getRelativeRot()).conjugate()).vec().norm() >= imag_norm_max) {
1405 pmap->addQuat(componentId, ParameterMap::rot(), Kernel::toQuat(relRot));
1406 }
1407 }
1408
1409 return pmap;
1410}
1411
1419 if (isParametrized())
1420 throw std::logic_error(
1421 "Instrument::parseTreeAndCacheBeamline must be called with the base instrument, not a parametrized instrument");
1423}
1424
1430std::pair<std::unique_ptr<ComponentInfo>, std::unique_ptr<DetectorInfo>>
1432 // If we have source and it has Beamline objects just copy them
1433 if (source && source->hasComponentInfo(this)) {
1434 return makeWrappers(pmap, source->componentInfo(), source->detectorInfo());
1435 }
1436 // If pmap is empty and base instrument has Beamline objects just copy them
1437 if (pmap.empty() && m_componentInfo) {
1439 }
1440 // pmap not empty and/or no cached Beamline objects found
1441 return InstrumentVisitor::makeWrappers(*this, &pmap);
1442}
1443
1448std::pair<std::unique_ptr<ComponentInfo>, std::unique_ptr<DetectorInfo>>
1452
1454std::pair<std::unique_ptr<ComponentInfo>, std::unique_ptr<DetectorInfo>>
1456 const DetectorInfo &detectorInfo) const {
1457 auto compInfo = componentInfo.cloneWithoutDetectorInfo();
1458 auto detInfo = std::make_unique<DetectorInfo>(detectorInfo);
1459 compInfo->m_componentInfo->setDetectorInfo(detInfo->m_detectorInfo.get());
1460 const auto parInstrument = ParComponentFactory::createInstrument(
1461 std::shared_ptr<const Instrument>(this, NoDeleting()), std::shared_ptr<ParameterMap>(&pmap, NoDeleting()));
1462 detInfo->m_instrument = parInstrument;
1463 return {std::move(compInfo), std::move(detInfo)};
1464}
1465
1466namespace Conversion {
1467
1476double tofToDSpacingFactor(const double l1, const double l2, const double twoTheta, const double offset) {
1477 return Kernel::Units::tofToDSpacingFactor(l1, l2, twoTheta, offset);
1478}
1479
1480double calculateDIFCCorrection(const double l1, const double l2, const double twoTheta, const double offset,
1481 const double binWidth) {
1482 return Kernel::Units::calculateDIFCCorrection(l1, l2, twoTheta, offset, binWidth);
1483}
1484
1485} // namespace Conversion
1486} // namespace Mantid::Geometry
std::string name
Definition Run.cpp:60
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:44
double obj
the value of the quadratic function
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
void grow(const BoundingBox &other)
Grow the bounding box so that it also encompasses the given box.
Class for Assembly of geometric components.
std::vector< IComponent * > m_children
the group of child components
void getChildren(std::vector< IComponent_const_sptr > &outVector, bool recursive) const override
Returns a vector of all children contained.
BoundingBox * m_cachedBoundingBox
A cached bounding box.
int add(IComponent *) override
Add a component to the assembly.
std::shared_ptr< const IComponent > getComponentByName(const std::string &cname, int nlevels=0) const override
Returns a pointer to the first component of assembly encountered with the given name.
int remove(IComponent *)
Remove a component from the assembly.
Kernel::V3D getPos() const override
Gets the absolute position of the Parametrized CompAssembly This attempts to read the cached position...
CompAssembly()
Empty constructor.
int nelements() const override
Return the number of elements in the assembly.
ComponentInfo : Provides a component centric view on to the instrument.
BoundingBox boundingBox(const size_t componentIndex, const BoundingBox *reference=nullptr, const bool excludeMonitors=false) const
Compute the bounding box for the component with componentIndex taking into account all sub components...
std::unique_ptr< ComponentInfo > cloneWithoutDetectorInfo() const
Clone current instance but not the DetectorInfo non-owned parts.
Component is a wrapper for a Component which can modify some of its parameters, e....
Definition Component.h:42
const ParameterMap * m_map
A pointer to const ParameterMap containing the parameters.
Definition Component.h:316
size_t index() const
Helper for legacy access mode. Returns the index of the component.
void setName(const std::string &) override
Set the IComponent name.
const IComponent * base() const
Returns the address of the base component.
Definition Component.h:289
bool isParametrized() const override
Return true if the Component is, in fact, parametrized (that is - it has a valid parameter map)
Definition Component.cpp:75
std::string getName() const override
Get the IComponent name.
const Component * m_base
The base component - this is the unmodified component (without the parameters).
Definition Component.h:314
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
This class represents a detector - i.e.
Definition Detector.h:30
Class for Assembly of geometric components.
virtual void getChildren(std::vector< IComponent_const_sptr > &outVector, bool recursive) const =0
Get all children.
base class for Geometric IComponent
Definition IComponent.h:53
virtual IComponent const * getBaseComponent() const =0
Returns const pointer to base component if this component is parametrized.
virtual Kernel::V3D getScaleFactor() const
Gets the scaling factor of the object for the Object Component.
Definition IComponent.h:124
virtual ComponentID getComponentID() const =0
Returns the ComponentID - a unique identifier of the component.
virtual Kernel::Quat getRelativeRot() const =0
Get the relative Orientation.
virtual Kernel::V3D getRelativePos() const =0
Get the position relative to the parent IComponent (absolute if no parent)
virtual const IComponent * getBareParent() const =0
Returns the bare pointer to the IComponent parent.
virtual std::string getName() const =0
Get the IComponent name.
Interface class for detector objects.
Definition IDetector.h:43
virtual detid_t getID() const =0
Get the detector ID.
Object Component class, this class brings together the physical attributes of the component to the po...
std::pair< std::unique_ptr< ComponentInfo >, std::unique_ptr< DetectorInfo > > makeWrappers() const
Base Instrument Class.
Definition Instrument.h:49
ContainsState containsRectDetectors() const
Check whether instrument contains rectangular detectors.
std::string m_filename
Path to the original IDF .xml file that was loaded for this instrument.
Definition Instrument.h:364
std::vector< std::shared_ptr< const IComponent > > getAllComponentsWithName(const std::string &cname) const
Returns pointers to all components encountered with the given name.
void markAsSamplePos(const IComponent *)
mark a Component which has already been added to the Instrument (as a child comp.) to be 'the' sample...
std::size_t getNumberDetectors(bool skipMonitors=false) const
IComponent_const_sptr getSource() const
Gets a pointer to the source.
void removeDetectorIncomplete(IDetector const *)
Efficiently remove multiple detectors.
std::string m_xmlText
Contents of the IDF .xml file that was loaded for this instrument.
Definition Instrument.h:367
std::shared_ptr< const IComponent > getComponentByID(const IComponent *id) const
Returns a shared pointer to a component.
bool validateComponentProperties(IComponent_const_sptr component) const
const IComponent * m_sampleCache
Purpose to hold copy of samplePos component.
Definition Instrument.h:327
void getInstrumentParameters(double &l1, Kernel::V3D &beamline, double &beamline_norm, Kernel::V3D &samplePos) const
Get several instrument parameters used in tof to D-space conversion.
std::pair< std::unique_ptr< ComponentInfo >, std::unique_ptr< DetectorInfo > > makeWrappers(ParameterMap &pmap, const ComponentInfo &componentInfo, const DetectorInfo &detectorInfo) const
Sets up links between m_detectorInfo, m_componentInfo, and m_instrument.
void markAsMonitorIncomplete(IDetector const *)
Mark a Component which has already been added to the Instrument class as a monitor and add it to the ...
const IDetector * getBaseDetector(const detid_t &detector_id) const
Gets a pointer to the base (non-parametrized) detector from its ID returns null if the detector has n...
std::shared_ptr< const Instrument > baseInstrument() const
Pointer to the 'real' instrument, for parametrized instruments.
Instrument()
Default constructor.
ContainsState
To determine whether the instrument contains elements of some type.
Definition Instrument.h:203
void parseTreeAndCacheBeamline()
Parse the instrument tree and create ComponentInfo and DetectorInfo.
std::shared_ptr< const Instrument > getPhysicalInstrument() const
INDIRECT GEOMETRY INSTRUMENTS ONLY: Returns the physical instrument, if one has been specified as dis...
std::shared_ptr< const Instrument > m_instr
Pointer to the "real" instrument, for parametrized Instrument.
Definition Instrument.h:353
std::set< detid_t > getDetectorIDsInBank(const std::string &bankName) const
void markAsDetector(const IDetector *)
mark a Component which has already been added to the Instrument (as a child comp.) to be a Detector c...
std::pair< std::unique_ptr< ComponentInfo >, std::unique_ptr< DetectorInfo > > makeBeamlineNew(ParameterMap &pmap) const
Return ComponentInfo and DetectorInfo for instrument given by pmap.
std::string m_defaultView
Stores the default type of the instrument view: 3D or one of the "unwrapped".
Definition Instrument.h:347
std::pair< std::unique_ptr< ComponentInfo >, std::unique_ptr< DetectorInfo > > makeBeamline(ParameterMap &pmap, const ParameterMap *source=nullptr) const
Return ComponentInfo and DetectorInfo for instrument given by pmap.
std::shared_ptr< const DetectorInfo > m_detectorInfo
Pointer to the DetectorInfo object. May be NULL.
Definition Instrument.h:377
std::vector< detid_t > getMonitorIDs() const
Returns a list containing the detector ids of monitors.
std::vector< IDetector_const_sptr > getDetectors(const std::vector< detid_t > &det_ids) const
Returns a list of Detectors for the given detectors ids.
std::shared_ptr< ParameterMap > makeLegacyParameterMap() const
Returns a legacy ParameterMap, containing information that is now stored in DetectorInfo (masking,...
size_t detectorIndex(const detid_t detID) const
Returns the index for a detector ID. Used for accessing DetectorInfo.
void setValidFromDate(const Types::Core::DateAndTime &val)
Set the date from which the instrument definition begins to be valid.
void setXmlText(const std::string &XmlText)
Set the Contents of the IDF .xml file that was loaded for this instrument.
Instrument * clone() const override
Virtual copy constructor.
bool isMonitor(const detid_t &detector_id) const
const std::string & getFilename() const
bool isMonitorViaIndex(const size_t index) const
Temporary helper for refactoring. Argument is index, not ID!
void setPhysicalInstrument(std::unique_ptr< Instrument >)
INDIRECT GEOMETRY INSTRUMENTS ONLY: Sets the physical instrument.
std::shared_ptr< ParameterMap > getParameterMap() const
Pointer to the NOT const ParameterMap holding the parameters of the modified instrument components.
void markAsMonitor(IDetector const *)
mark a Component which has already been added to the Instrument (as a child comp.) to be a monitor an...
std::shared_ptr< IComponent > getChild(const int i) const override
Get a pointer to the ith component within the assembly. Easier to use than.
bool hasSample() const
Checks to see if the Instrument has a sample.
Kernel::V3D getBeamDirection() const
Gets the beam direction (i.e.
const IComponent * m_sourceCache
Purpose to hold copy of source component.
Definition Instrument.h:323
void saveNexus(Nexus::File *file, const std::string &group) const
Save the instrument to an open NeXus file.
void appendPlottable(const CompAssembly &ca, std::vector< IObjComponent_const_sptr > &lst) const
Add a plottable component.
std::string type() const override
String description of the type of component.
Definition Instrument.h:52
void markAsDetectorIncomplete(const IDetector *)
As markAsDetector but without the required sorting.
const std::string & getXmlText() const
std::vector< detid_t > getDetectorIDs(bool skipMonitors=false) const
Returns a list containing the detector ids of all detectors, optionally skipping monitors.
void getBoundingBox(BoundingBox &assemblyBox) const override
Get the bounding box for this component and store it in the given argument.
std::shared_ptr< const ComponentInfo > m_componentInfo
Pointer to the ComponentInfo object. May be NULL.
Definition Instrument.h:380
std::shared_ptr< const Instrument > m_physicalInstrument
Pointer to the physical instrument, where this differs from the 'neutronic' one (indirect geometry)
Definition Instrument.h:371
Mantid::Geometry::Instrument::DetectorCache m_detectorCache
std::shared_ptr< const std::vector< IObjComponent_const_sptr > > getPlottable() const
Get pointers to plottable components.
void saveDetectorSetInfoToNexus(Nexus::File *file, const std::vector< detid_t > &detIDs) const
Save information about a set of detectors to Nexus.
IDetector_const_sptr getDetectorG(const std::set< detid_t > &det_ids) const
Returns a pointer to the geometrical object for the given set of IDs.
void getDetectorsInBank(std::vector< IDetector_const_sptr > &dets, const IComponent &comp) const
Fill a vector with all the detectors contained (at any depth) in a named component.
void markAsSource(const IComponent *)
mark a Component which has already been added to the Instrument (as a child comp.) to be 'the' source...
bool hasSource() const
Checks to see if the Instrument has a source.
void setReferenceFrame(std::shared_ptr< ReferenceFrame > frame)
Set reference Frame.
void getMinMaxDetectorIDs(detid_t &min, detid_t &max) const
Get the minimum and maximum (inclusive) detector IDs.
std::shared_ptr< ParameterMap > m_map_nonconst
Non-const pointer to the parameter map.
Definition Instrument.h:356
void setDefaultView(const std::string &type)
Set the default type of the instrument view.
void removeDetectorFinalize()
Remove all detectors that have been marked for removal with removeDetectorIncomplete() from the detec...
std::shared_ptr< const ReferenceFrame > getReferenceFrame() const
Get refernce Frame.
void markAsDetectorFinalize()
Sorts the detector cache.
bool addAssemblyChildrenToQueue(std::queue< IComponent_const_sptr > &queue, IComponent_const_sptr component) const
If component is a ComponentAssembly, we add its children to the queue to check if they're Rectangular...
std::shared_ptr< ReferenceFrame > m_referenceFrame
Pointer to the reference frame object.
Definition Instrument.h:374
IDetector_const_sptr getDetector(const detid_t &detector_id) const
Gets a pointer to the detector from its ID Note that for getting the detector associated with a spect...
Types::Core::DateAndTime m_ValidFrom
the date from which the instrument definition begins to be valid.
Definition Instrument.h:359
void setFilename(const std::string &filename)
Set the path to the original IDF .xml file that was loaded for this instrument.
IComponent_const_sptr getSample() const
Gets a pointer to the Sample Position.
void addInstrumentChildrenToQueue(std::queue< IComponent_const_sptr > &queue) const
void loadNexus(Nexus::File *file, const std::string &group)
Load the object from an open NeXus file.
void removeDetector(IDetector *)
Remove a detector from the instrument.
Object Component class, this class brings together the physical attributes of the component to the po...
static std::shared_ptr< IComponent > create(const std::shared_ptr< const IComponent > &base, const ParameterMap *map)
Create a parameterized component from the given base component and ParameterMap.
static std::shared_ptr< Instrument > createInstrument(const std::shared_ptr< const Instrument > &base, const std::shared_ptr< ParameterMap > &map)
Create a parameterized instrument from the given base and ParameterMap.
static std::shared_ptr< IDetector > createDetector(const IDetector *base, const ParameterMap *map)
Create a parameterized detector from the given base component and ParameterMap and return a shared_pt...
const Geometry::DetectorInfo & detectorInfo() const
Only for use by ExperimentInfo. Returns a reference to the DetectorInfo.
static const std::string & scale()
static const std::string & rot()
static const std::string & pos()
Return string to be used in the map.
bool hasComponentInfo(const Instrument *instrument) const
Only for use by ExperimentInfo.
const Geometry::ComponentInfo & componentInfo() const
Only for use by ExperimentInfo. Returns a reference to the ComponentInfo.
RectangularDetector is a type of CompAssembly, an assembly of components.
ReferenceFrame : Holds reference frame information from the geometry description file.
Exception for errors associated with the instrument definition.
Definition Exception.h:220
Exception for when an item is not found in a collection.
Definition Exception.h:145
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
Class for 3D vectors.
Definition V3D.h:34
double norm() const noexcept
Definition V3D.h:269
void getSpherical(double &R, double &theta, double &phi) const noexcept
Return the vector's position in spherical coordinates.
Definition V3D.cpp:116
This functor is used as the deleter object of a shared_ptr to effectively erase ownership Raw pointer...
Definition IComponent.h:173
MANTID_GEOMETRY_DLL bool isDetectorFixedInBank(const ComponentInfo &compInfo, const size_t detIndex)
Tests whether or not the detector is within a fixed bank.
MANTID_GEOMETRY_DLL double calculateDIFCCorrection(const double l1, const double l2, const double twoTheta, const double offset, const double binWidth)
MANTID_GEOMETRY_DLL double tofToDSpacingFactor(const double l1, const double l2, const double twoTheta, const double offset)
Calculate and return conversion factor from tof to d-spacing.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:167
std::shared_ptr< IComponent > IComponent_sptr
Typedef of a shared pointer to a IComponent.
Definition IComponent.h:165
Mantid::Kernel::Logger g_log("Goniometer")
std::shared_ptr< const IObjComponent > IObjComponent_const_sptr
Shared pointer to IObjComponent (const version)
std::shared_ptr< ParameterMap > ParameterMap_sptr
ParameterMap shared pointer typedef.
std::shared_ptr< const Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
Definition IDetector.h:102
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
Kernel::Quat toQuat(const Eigen::Quaterniond &quat)
Converts Eigen::Quaterniond to Kernel::Quat.
Eigen::Vector3d toVector3d(const Kernel::V3D &vec)
Converts Kernel::V3D to Eigen::Vector3d.
Kernel::V3D toV3D(const Eigen::Vector3d &vec)
This header provides conversion helpers between vector and rotation types in MantidKernel and equival...
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition V3D.h:352
Eigen::Quaterniond toQuaterniond(const Kernel::Quat &quat)
Converts Kernel::Quat to Eigen::Quaterniond.
int32_t detid_t
Typedef for a detector ID.
std::map< detid_t, Geometry::IDetector_const_sptr > detid2det_map
Typedef of a map from detector ID to detector shared pointer.
Definition Instrument.h:28
Generate a tableworkspace to store the calibration results.
adjust instrument component position and orientation
: detector size scale at y-direction
std::string to_string(const wide_integer< Bits, Signed > &n)
Tuple which holds detector-IDs and pointers to detector components, and monitor flags.
Definition Instrument.h:273
DetectorCache::iterator lower_bound(detid_t id)
Perform a lower bound search on the detector cache, for the element with the given ID.
std::unordered_set< IDetector const * > m_toRemove
Definition Instrument.h:310
DetectorCache::iterator find(detid_t id)
Find the element in the detector cache with the given ID.
void setFinalized(bool const flag=true)
Definition Instrument.h:291