Mantid
Loading...
Searching...
No Matches
PeaksWorkspace.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 "MantidAPI/Run.h"
9#include "MantidAPI/Sample.h"
14#include "MantidKernel/Logger.h"
16
17// clang-format off
18#include <nexus/NeXusFile.hpp>
19#include <nexus/NeXusException.hpp>
20// clang-format on
21
22#include <cmath>
23
24using namespace Mantid::API;
25using namespace Mantid::Kernel;
26using namespace Mantid::Geometry;
27
28namespace Mantid::DataObjects {
31
33
34//---------------------------------------------------------------------------------------------
39PeaksWorkspace::PeaksWorkspace() : IPeaksWorkspace(), m_peaks(), m_columns(), m_columnNames(), m_coordSystem(None) {
40 initColumns();
41 // PeaksWorkspace does not use the grouping mechanism of ExperimentInfo.
42 setNumberOfDetectorGroups(0);
43}
44
45//---------------------------------------------------------------------------------------------
50// PeaksWorkspace::PeaksWorkspace(const PeaksWorkspace &other) = default;
52 : IPeaksWorkspace(other), m_peaks(other.m_peaks), m_columns(), m_columnNames(), m_coordSystem(other.m_coordSystem) {
54 // PeaksWorkspace does not use the grouping mechanism of ExperimentInfo.
56}
57
60class PeakComparator {
61public:
63 std::vector<ColumnAndDirection> &criteria;
64
69 explicit PeakComparator(std::vector<ColumnAndDirection> &criteria) : criteria(criteria) {}
70
72 inline bool operator()(const Peak &a, const Peak &b) {
73 for (const auto &name : criteria) {
74 const auto &col = name.first;
75 const bool ascending = name.second;
76 bool lessThan = false;
77 if (col == "BankName") {
78 // If this criterion is equal, move on to the next one
79 const std::string valA = a.getBankName();
80 const std::string valB = b.getBankName();
81 // Move on to lesser criterion if equal
82 if (valA == valB)
83 continue;
84 lessThan = (valA < valB);
85 } else {
86 // General double comparison
87 const double valA = a.getValueByColName(col);
88 const double valB = b.getValueByColName(col);
89 // Move on to lesser criterion if equal
90 if (valA == valB)
91 continue;
92 lessThan = (valA < valB);
93 }
94 // Flip the sign of comparison if descending.
95 if (ascending)
96 return lessThan;
97 else
98 return !lessThan;
99 }
100 // If you reach here, all criteria were ==; so not <, so return false
101 return false;
102 }
103};
104
105//---------------------------------------------------------------------------------------------
113void PeaksWorkspace::sort(std::vector<ColumnAndDirection> &criteria) {
114 PeakComparator comparator(criteria);
115 std::stable_sort(m_peaks.begin(), m_peaks.end(), comparator);
116}
117
118//---------------------------------------------------------------------------------------------
121int PeaksWorkspace::getNumberPeaks() const { return int(m_peaks.size()); }
122
123//---------------------------------------------------------------------------------------------
126std::string PeaksWorkspace::getConvention() const { return m_convention; }
127
128//---------------------------------------------------------------------------------------------
132void PeaksWorkspace::removePeak(const int peakNum) {
133 if (peakNum >= static_cast<int>(m_peaks.size()) || peakNum < 0) {
134 throw std::invalid_argument("PeaksWorkspace::removePeak(): peakNum is out of range.");
135 }
136 m_peaks.erase(m_peaks.begin() + peakNum);
137}
138
142void PeaksWorkspace::removePeaks(std::vector<int> badPeaks) {
143 if (badPeaks.empty())
144 return;
145 // if index of peak is in badPeaks remove
146 int ip = -1;
147 auto it = std::remove_if(m_peaks.begin(), m_peaks.end(), [&ip, badPeaks](Peak &pk) {
148 (void)pk;
149 ip++;
150 return std::any_of(badPeaks.cbegin(), badPeaks.cend(), [ip](int badPeak) { return badPeak == ip; });
151 });
152 m_peaks.erase(it, m_peaks.end());
153}
154
155//---------------------------------------------------------------------------------------------
160 if (dynamic_cast<const Peak *>(&ipeak)) {
161 m_peaks.emplace_back((const Peak &)ipeak);
162 } else {
163 m_peaks.emplace_back(Peak(ipeak));
164 }
165}
166
167//---------------------------------------------------------------------------------------------
173 auto peak = createPeak(position, frame);
174 addPeak(*peak);
175}
176
177//---------------------------------------------------------------------------------------------
181void PeaksWorkspace::addPeak(Peak &&peak) { m_peaks.emplace_back(peak); }
182
183//---------------------------------------------------------------------------------------------
188Peak &PeaksWorkspace::getPeak(const int peakNum) {
189 if (peakNum >= static_cast<int>(m_peaks.size()) || peakNum < 0) {
190 throw std::invalid_argument("PeaksWorkspace::getPeak(): peakNum is out of range.");
191 }
192 return m_peaks[peakNum];
193}
194
195//---------------------------------------------------------------------------------------------
200const Peak &PeaksWorkspace::getPeak(const int peakNum) const {
201 if (peakNum >= static_cast<int>(m_peaks.size()) || peakNum < 0) {
202 throw std::invalid_argument("PeaksWorkspace::getPeak(): peakNum is out of range.");
203 }
204 return m_peaks[peakNum];
205}
206
207//---------------------------------------------------------------------------------------------
214std::unique_ptr<Geometry::IPeak> PeaksWorkspace::createPeak(const Kernel::V3D &QLabFrame,
215 boost::optional<double> detectorDistance) const {
216 // create a peak using the qLab frame
217 std::unique_ptr<IPeak> peak = std::make_unique<Peak>(this->getInstrument(), QLabFrame, detectorDistance);
218 // Set the goniometer
219 peak->setGoniometerMatrix(this->run().getGoniometer().getR());
220 // Take the run number from this
221 peak->setRunNumber(this->getRunNumber());
222
223 return peak;
224}
225
226//---------------------------------------------------------------------------------------------
233std::unique_ptr<Geometry::IPeak> PeaksWorkspace::createPeak(const Kernel::V3D &position,
234 const Kernel::SpecialCoordinateSystem &frame) const {
235 if (frame == Mantid::Kernel::HKL) {
236 return createPeakHKL(position);
237 } else if (frame == Mantid::Kernel::QLab) {
238 return createPeak(position);
239 } else {
241 }
242}
243
244//---------------------------------------------------------------------------------------------
251std::unique_ptr<IPeak> PeaksWorkspace::createPeakQSample(const V3D &position) const {
252 // Create a peak from QSampleFrame
253
254 Geometry::Goniometer goniometer;
255
257 // See if we can get a wavelength/energy
258 // Then assume constant wavelenth
259 double wavelength(0);
260 if (props->hasProperty("wavelength")) {
261 wavelength = props->getPropertyValueAsType<double>("wavelength");
262 } else if (props->hasProperty("energy")) {
263 wavelength = Kernel::UnitConversion::run("Energy", "Wavelength", props->getPropertyValueAsType<double>("energy"), 0,
265 } else if (getInstrument()->hasParameter("wavelength")) {
266 wavelength = getInstrument()->getNumberParameter("wavelength").at(0);
267 }
268
269 if (wavelength > 0) {
270 goniometer.calcFromQSampleAndWavelength(position, wavelength);
271 g_log.information() << "Found goniometer rotation to be " << goniometer.getEulerAngles()[0]
272 << " degrees for Q sample = " << position << "\n";
273 } else {
274 goniometer = run().getGoniometer();
275 }
276 // create a peak using the qLab frame
277 std::unique_ptr<IPeak> peak = std::make_unique<Peak>(getInstrument(), position, goniometer.getR());
278 // Take the run number from this
279 peak->setRunNumber(getRunNumber());
280 return peak;
281}
282
298std::vector<std::pair<std::string, std::string>> PeaksWorkspace::peakInfo(const Kernel::V3D &qFrame,
299 bool labCoords) const {
300 std::vector<std::pair<std::string, std::string>> Result;
301 std::ostringstream oss;
302 oss << std::setw(12) << std::fixed << std::setprecision(3) << (qFrame.norm());
303 std::pair<std::string, std::string> QMag("|Q|", oss.str());
304 Result.emplace_back(QMag);
305
306 oss.str("");
307 oss.clear();
308 oss << std::setw(12) << std::fixed << std::setprecision(3) << (2.0 * M_PI / qFrame.norm());
309
310 std::pair<std::string, std::string> dspc("d-spacing", oss.str());
311 oss.str("");
312 oss.clear();
313 Result.emplace_back(dspc);
314
315 int seqNum = -1;
316 bool hasOneRunNumber = true;
317 int runNum = -1;
318 int NPeaks = getNumberPeaks();
319 try {
320 double minDist = 10000000;
321 for (int i = 0; i < NPeaks; i++) {
322 Peak pk = getPeak(i);
323 V3D Q = pk.getQLabFrame();
324 if (!labCoords)
325 Q = pk.getQSampleFrame();
326 double D = qFrame.distance(Q);
327 if (D < minDist) {
328 minDist = D;
329 seqNum = i;
330 }
331
332 int run = pk.getRunNumber();
333 if (runNum < 0)
334 runNum = run;
335 else if (runNum != run)
336 hasOneRunNumber = false;
337 }
338 } catch (...) {
339 seqNum = -1; // peak could have been removed
340 }
341 V3D Qlab = qFrame;
342 V3D Qsamp;
343 Kernel::Matrix<double> Gon(3, 3, true);
344
345 if (seqNum >= 0)
346 Gon = getPeak(seqNum).getGoniometerMatrix();
347 if (labCoords) {
348
349 Kernel::Matrix<double> InvGon(Gon);
350 InvGon.Invert();
351 Qsamp = InvGon * Qlab;
352
353 } else {
354 Qsamp = qFrame;
355 Qlab = Gon * Qsamp;
356 }
357
358 if (labCoords || seqNum >= 0)
359
360 {
361 std::pair<std::string, std::string> QlabStr("Qlab", boost::lexical_cast<std::string>(Qlab));
362 Result.emplace_back(QlabStr);
363 }
364
365 if (!labCoords || seqNum >= 0) {
366
367 std::pair<std::string, std::string> QsampStr("QSample", boost::lexical_cast<std::string>(Qsamp));
368 Result.emplace_back(QsampStr);
369 }
370
371 try {
372 IPeak_uptr iPeak = createPeak(Qlab);
373 Peak_uptr peak(static_cast<DataObjects::Peak *>(iPeak.release()));
374
375 if (sample().hasOrientedLattice()) {
376
377 peak->setGoniometerMatrix(Gon);
379
380 const Kernel::Matrix<double> &UB0 = lat.getUB();
382 UB.Invert();
383 V3D hkl = UB * Qsamp / 2 / M_PI;
384
385 std::pair<std::string, std::string> HKL("HKL", boost::lexical_cast<std::string>(hkl));
386 Result.emplace_back(HKL);
387 }
388
389 if (hasOneRunNumber) {
390 std::pair<std::string, std::string> runn("RunNumber", " " + std::to_string(runNum));
391 Result.emplace_back(runn);
392 }
393
394 //------- Now get phi, chi and omega ----------------
395 Geometry::Goniometer GonG(Gon);
396 std::vector<double> OmegaChiPhi = GonG.getEulerAngles("YZY");
397 Kernel::V3D PhiChiOmega(OmegaChiPhi[2], OmegaChiPhi[1], OmegaChiPhi[0]);
398
399 std::pair<std::string, std::string> GRead("Goniometer Angles", boost::lexical_cast<std::string>(PhiChiOmega));
400 Result.emplace_back(GRead);
401
402 std::pair<std::string, std::string> SeqNum("Seq Num,1st=1", " " + std::to_string(seqNum + 1));
403 Result.emplace_back(SeqNum);
404
405 oss << std::setw(12) << std::fixed << std::setprecision(3) << (peak->getWavelength());
406 std::pair<std::string, std::string> wl("Wavelength", oss.str());
407 Result.emplace_back(wl);
408 oss.str("");
409 oss.clear();
410
411 if (peak->findDetector()) {
412 std::pair<std::string, std::string> detpos("Position(x,y,z)",
413 boost::lexical_cast<std::string>(peak->getDetPos()));
414 Result.emplace_back(detpos);
415
416 oss << std::setw(15) << std::fixed << std::setprecision(3) << (peak->getTOF());
417 std::pair<std::string, std::string> tof("TOF", oss.str());
418 Result.emplace_back(tof);
419 oss.str("");
420 oss.clear();
421
422 oss << std::setw(12) << std::fixed << std::setprecision(3) << (peak->getFinalEnergy());
423 std::pair<std::string, std::string> Energy("Energy", oss.str());
424 Result.emplace_back(Energy);
425 oss.str("");
426 oss.clear();
427
428 std::pair<std::string, std::string> row("Row", " " + std::to_string(peak->getRow()));
429 Result.emplace_back(row);
430
431 std::pair<std::string, std::string> col("Col", " " + std::to_string(peak->getCol()));
432 Result.emplace_back(col);
433
434 std::pair<std::string, std::string> bank("Bank", " " + peak->getBankName());
435 Result.emplace_back(bank);
436
437 oss << std::setw(12) << std::fixed << std::setprecision(3) << (peak->getScattering());
438 std::pair<std::string, std::string> scat("Scattering Angle", oss.str());
439 Result.emplace_back(scat);
440 }
441
442 } catch (...) // Impossible position
443 {
444 }
445 return Result;
446}
447
455std::unique_ptr<IPeak> PeaksWorkspace::createPeakHKL(const V3D &HKL) const {
456 /*
457 The following allows us to add peaks where we have a single UB to work from.
458 */
459 const auto &lattice = this->sample().getOrientedLattice();
460 const auto &goniometer = this->run().getGoniometer();
461
462 // Calculate qLab from q HKL. As per Busing and Levy 1967, q_lab_frame = 2pi *
463 // Goniometer * UB * HKL
464 const V3D qLabFrame = goniometer.getR() * lattice.getUB() * HKL * 2 * M_PI;
465
466 // create a peak using the qLab frame
467 // This should calculate the detector positions too
468 std::unique_ptr<IPeak> peak = std::make_unique<Peak>(this->getInstrument(), qLabFrame);
469 // We need to set HKL separately to keep things consistent.
470 peak->setHKL(HKL[0], HKL[1], HKL[2]);
471 peak->setIntHKL(peak->getHKL());
472 // Set the goniometer
473 peak->setGoniometerMatrix(goniometer.getR());
474 // Take the run number from this
475 peak->setRunNumber(this->getRunNumber());
476
477 return peak;
478}
479
485std::unique_ptr<IPeak> PeaksWorkspace::createPeak() const { return std::make_unique<Peak>(); }
486
502int PeaksWorkspace::peakInfoNumber(const Kernel::V3D &qFrame, bool labCoords) const {
503 std::vector<std::pair<std::string, std::string>> Result;
504 std::ostringstream oss;
505 oss << std::setw(12) << std::fixed << std::setprecision(3) << (qFrame.norm());
506 std::pair<std::string, std::string> QMag("|Q|", oss.str());
507 Result.emplace_back(QMag);
508
509 oss.str("");
510 oss.clear();
511 oss << std::setw(12) << std::fixed << std::setprecision(3) << (2.0 * M_PI / qFrame.norm());
512
513 std::pair<std::string, std::string> dspc("d-spacing", oss.str());
514 oss.str("");
515 oss.clear();
516 Result.emplace_back(dspc);
517
518 int seqNum = -1;
519 double minDist = 10000000;
520
521 for (int i = 0; i < getNumberPeaks(); i++) {
522 Peak pk = getPeak(i);
523 V3D Q = pk.getQLabFrame();
524 if (!labCoords)
525 Q = pk.getQSampleFrame();
526 double D = qFrame.distance(Q);
527 if (D < minDist) {
528 minDist = D;
529 seqNum = i + 1;
530 }
531 }
532 return seqNum;
533}
534
535//---------------------------------------------------------------------------------------------
537std::vector<Peak> &PeaksWorkspace::getPeaks() { return m_peaks; }
538
540const std::vector<Peak> &PeaksWorkspace::getPeaks() const { return m_peaks; }
541
546 bool ret = false;
547 const std::string peaksIntegrated = "PeaksIntegrated";
548 if (this->run().hasProperty(peaksIntegrated)) {
549 const auto value = boost::lexical_cast<int>(this->run().getProperty(peaksIntegrated)->value());
550 ret = (value != 0);
551 }
552 return ret;
553}
554
555//---------------------------------------------------------------------------------------------
557size_t PeaksWorkspace::getMemorySize() const { return getNumberPeaks() * sizeof(Peak); }
558
559//---------------------------------------------------------------------------------------------
568 auto table = API::WorkspaceFactory::Instance().createTable("TableWorkspace");
569 table->addColumn("int", "Index");
570 table->addColumn("int", "DetectorID");
571
572 const auto npeaks(static_cast<int>(this->rowCount()));
573 int nrows(0);
574 for (int i = 0; i < npeaks; ++i) {
575 const Peak &peak = this->m_peaks[i];
576 auto detIDs = peak.getContributingDetIDs();
577 auto itEnd = detIDs.end();
578 for (auto it = detIDs.begin(); it != itEnd; ++it) {
579 table->appendRow();
580 table->cell<int>(nrows, 0) = i;
581 table->cell<int>(nrows, 1) = *it;
582 ++nrows;
583 }
584 }
585
586 return table;
587}
588
589//---------------------------------------------------------------------------------------------
592 // Note: The column types are controlled in PeakColumn.cpp
593 addPeakColumn("RunNumber");
594 addPeakColumn("DetID");
595 addPeakColumn("h");
596 addPeakColumn("k");
597 addPeakColumn("l");
598 addPeakColumn("Wavelength");
599 addPeakColumn("Energy");
600 addPeakColumn("TOF");
601 addPeakColumn("DSpacing");
602 addPeakColumn("Intens");
603 addPeakColumn("SigInt");
604 addPeakColumn("Intens/SigInt");
605 addPeakColumn("BinCount");
606 addPeakColumn("BankName");
607 addPeakColumn("Row");
608 addPeakColumn("Col");
609 addPeakColumn("QLab");
610 addPeakColumn("QSample");
611 addPeakColumn("PeakNumber");
612 addPeakColumn("TBar");
613}
614
615//---------------------------------------------------------------------------------------------
620void PeaksWorkspace::addPeakColumn(const std::string &name) {
621 // Create the PeakColumn.
622 m_columns.emplace_back(std::make_shared<DataObjects::PeakColumn<Peak>>(this->m_peaks, name));
623 // Cache the names
624 m_columnNames.emplace_back(name);
625}
626
627//---------------------------------------------------------------------------------------------
629size_t PeaksWorkspace::getColumnIndex(const std::string &name) const {
630 for (size_t i = 0; i < m_columns.size(); i++)
631 if (m_columns[i]->name() == name)
632 return i;
633 throw std::invalid_argument("Column named " + name + " was not found in the PeaksWorkspace.");
634}
635
636//---------------------------------------------------------------------------------------------
638std::shared_ptr<Mantid::API::Column> PeaksWorkspace::getColumn(size_t index) {
639 if (index >= m_columns.size())
640 throw std::invalid_argument("PeaksWorkspace::getColumn() called with invalid index.");
641 return m_columns[index];
642}
643
644//---------------------------------------------------------------------------------------------
646std::shared_ptr<const Mantid::API::Column> PeaksWorkspace::getColumn(size_t index) const {
647 if (index >= m_columns.size())
648 throw std::invalid_argument("PeaksWorkspace::getColumn() called with invalid index.");
649 return m_columns[index];
650}
651
652void PeaksWorkspace::saveNexus(::NeXus::File *file) const {
653
654 // Number of Peaks
655 const size_t np(m_peaks.size());
656
657 // Column vectors for peaks table
658 std::vector<int> detectorID(np);
659 std::vector<double> H(np);
660 std::vector<double> K(np);
661 std::vector<double> L(np);
662 std::vector<double> intensity(np);
663 std::vector<double> sigmaIntensity(np);
664 std::vector<double> binCount(np);
665 std::vector<double> initialEnergy(np);
666 std::vector<double> finalEnergy(np);
667 std::vector<double> waveLength(np);
668 std::vector<double> scattering(np);
669 std::vector<double> dSpacing(np);
670 std::vector<double> TOF(np);
671 std::vector<int> runNumber(np);
672 std::vector<int> peakNumber(np);
673 std::vector<double> tbar(np);
674 std::vector<double> goniometerMatrix(9 * np);
675 std::vector<std::string> shapes(np);
676
677 // Populate column vectors from Peak Workspace
678 size_t maxShapeJSONLength = 0;
679 for (size_t i = 0; i < np; i++) {
680 Peak p = m_peaks[i];
681 detectorID[i] = p.getDetectorID();
682 H[i] = p.getH();
683 K[i] = p.getK();
684 L[i] = p.getL();
685 intensity[i] = p.getIntensity();
686 sigmaIntensity[i] = p.getSigmaIntensity();
687 binCount[i] = p.getBinCount();
688 initialEnergy[i] = p.getInitialEnergy();
689 finalEnergy[i] = p.getFinalEnergy();
690 waveLength[i] = p.getWavelength();
691 scattering[i] = p.getScattering();
692 dSpacing[i] = p.getDSpacing();
693 TOF[i] = p.getTOF();
694 runNumber[i] = p.getRunNumber();
695 peakNumber[i] = p.getPeakNumber();
697 {
699 goniometerMatrix[9 * i] = gm[0][0];
700 goniometerMatrix[9 * i + 1] = gm[1][0];
701 goniometerMatrix[9 * i + 2] = gm[2][0];
702 goniometerMatrix[9 * i + 3] = gm[0][1];
703 goniometerMatrix[9 * i + 4] = gm[1][1];
704 goniometerMatrix[9 * i + 5] = gm[2][1];
705 goniometerMatrix[9 * i + 6] = gm[0][2];
706 goniometerMatrix[9 * i + 7] = gm[1][2];
707 goniometerMatrix[9 * i + 8] = gm[2][2];
708 }
709 const std::string shapeJSON = p.getPeakShape().toJSON();
710 shapes[i] = shapeJSON;
711 if (shapeJSON.size() > maxShapeJSONLength) {
712 maxShapeJSONLength = shapeJSON.size();
713 }
714 }
715
716 // Start Peaks Workspace in Nexus File
717 const std::string specifyInteger = "An integer";
718 const std::string specifyDouble = "A double";
719 const std::string specifyString = "A string";
720 file->makeGroup("peaks_workspace", "NXentry",
721 true); // For when peaksWorkspace can be loaded
722
723 // Coordinate system
724 file->writeData("coordinate_system", static_cast<uint32_t>(m_coordSystem));
725
726 // Write out the Qconvention
727 // ki-kf for Inelastic convention; kf-ki for Crystallography convention
728 std::string m_QConvention = this->getConvention();
729 file->putAttr("QConvention", m_QConvention);
730
731 // Detectors column
732 file->writeData("column_1", detectorID);
733 file->openData("column_1");
734 file->putAttr("name", "Detector ID");
735 file->putAttr("interpret_as", specifyInteger);
736 file->putAttr("units", "Not known");
737 file->closeData();
738
739 // H column
740 file->writeData("column_2", H);
741 file->openData("column_2");
742 file->putAttr("name", "H");
743 file->putAttr("interpret_as", specifyDouble);
744 file->putAttr("units", "Not known"); // Units may need changing when known
745 file->closeData();
746
747 // K column
748 file->writeData("column_3", K);
749 file->openData("column_3");
750 file->putAttr("name", "K");
751 file->putAttr("interpret_as", specifyDouble);
752 file->putAttr("units", "Not known"); // Units may need changing when known
753 file->closeData();
754
755 // L column
756 file->writeData("column_4", L);
757 file->openData("column_4");
758 file->putAttr("name", "L");
759 file->putAttr("interpret_as", specifyDouble);
760 file->putAttr("units", "Not known"); // Units may need changing when known
761 file->closeData();
762
763 // Intensity column
764 file->writeData("column_5", intensity);
765 file->openData("column_5");
766 file->putAttr("name", "Intensity");
767 file->putAttr("interpret_as", specifyDouble);
768 file->putAttr("units", "Not known"); // Units may need changing when known
769 file->closeData();
770
771 // Sigma Intensity column
772 file->writeData("column_6", sigmaIntensity);
773 file->openData("column_6");
774 file->putAttr("name", "Sigma Intensity");
775 file->putAttr("interpret_as", specifyDouble);
776 file->putAttr("units", "Not known"); // Units may need changing when known
777 file->closeData();
778
779 // Bin Count column
780 file->writeData("column_7", binCount);
781 file->openData("column_7");
782 file->putAttr("name", "Bin Count");
783 file->putAttr("interpret_as", specifyDouble);
784 file->putAttr("units", "Not known"); // Units may need changing when known
785 file->closeData();
786
787 // Initial Energy column
788 file->writeData("column_8", initialEnergy);
789 file->openData("column_8");
790 file->putAttr("name", "Initial Energy");
791 file->putAttr("interpret_as", specifyDouble);
792 file->putAttr("units", "Not known"); // Units may need changing when known
793 file->closeData();
794
795 // Final Energy column
796 file->writeData("column_9", finalEnergy);
797 file->openData("column_9");
798 file->putAttr("name", "Final Energy");
799 file->putAttr("interpret_as", specifyDouble);
800 file->putAttr("units", "Not known"); // Units may need changing when known
801 file->closeData();
802
803 // Wave Length Column
804 file->writeData("column_10", waveLength);
805 file->openData("column_10");
806 file->putAttr("name", "Wave Length");
807 file->putAttr("interpret_as", specifyDouble);
808 file->putAttr("units", "Not known"); // Units may need changing when known
809 file->closeData();
810
811 // Scattering Column
812 file->writeData("column_11", scattering);
813 file->openData("column_11");
814 file->putAttr("name", "Scattering");
815 file->putAttr("interpret_as", specifyDouble);
816 file->putAttr("units", "Not known"); // Units may need changing when known
817 file->closeData();
818
819 // D Spacing Column
820 file->writeData("column_12", dSpacing);
821 file->openData("column_12");
822 file->putAttr("name", "D Spacing");
823 file->putAttr("interpret_as", specifyDouble);
824 file->putAttr("units", "Not known"); // Units may need changing when known
825 file->closeData();
826
827 // TOF Column
828 file->writeData("column_13", TOF);
829 file->openData("column_13");
830 file->putAttr("name", "TOF");
831 file->putAttr("interpret_as", specifyDouble);
832 file->putAttr("units", "Not known"); // Units may need changing when known
833 file->closeData();
834
835 // Run Number column
836 file->writeData("column_14", runNumber);
837 file->openData("column_14");
838 file->putAttr("name", "Run Number");
839 file->putAttr("interpret_as", specifyInteger);
840 file->putAttr("units", "Not known"); // Units may need changing when known
841 file->closeData();
842
843 // Peak Number column
844 file->writeData("column_17", peakNumber);
845 file->openData("column_17");
846 file->putAttr("name", "Peak Number");
847 file->putAttr("interpret_as", specifyInteger);
848 file->putAttr("units", "Not known"); // Units may need changing when known
849 file->closeData();
850
851 // TBar column
852 file->writeData("column_18", tbar);
853 file->openData("column_18");
854 file->putAttr("name", "TBar");
855 file->putAttr("interpret_as", specifyDouble);
856 file->putAttr("units", "Not known"); // Units may need changing when known
857 file->closeData();
858
859 // Goniometer Matrix Column
860 std::vector<int> array_dims;
861 array_dims.emplace_back(static_cast<int>(m_peaks.size()));
862 array_dims.emplace_back(9);
863 file->writeData("column_15", goniometerMatrix, array_dims);
864 file->openData("column_15");
865 file->putAttr("name", "Goniometer Matrix");
866 file->putAttr("interpret_as", "A matrix of 3x3 doubles");
867 file->putAttr("units", "Not known"); // Units may need changing when known
868 file->closeData();
869
870 // Shape
871 std::vector<int64_t> dims;
872 dims.emplace_back(np);
873 dims.emplace_back(static_cast<int>(maxShapeJSONLength));
874 const std::string name = "column_16";
875 file->makeData(name, NeXus::CHAR, dims, false);
876 file->openData(name);
877
878 auto toNexus = new char[maxShapeJSONLength * np];
879 for (size_t ii = 0; ii < np; ii++) {
880 std::string rowStr = shapes[ii];
881 for (size_t ic = 0; ic < rowStr.size(); ic++)
882 toNexus[ii * maxShapeJSONLength + ic] = rowStr[ic];
883 for (size_t ic = rowStr.size(); ic < static_cast<size_t>(maxShapeJSONLength); ic++)
884 toNexus[ii * maxShapeJSONLength + ic] = ' ';
885 }
886
887 file->putData((void *)(toNexus));
888
889 delete[] toNexus;
890 file->putAttr("units", "Not known"); // Units may need changing when known
891 file->putAttr("name", "Shape");
892 file->putAttr("interpret_as", specifyString);
893 file->closeData();
894
895 // QLab & QSample are calculated and do not need to be saved
896
897 file->closeGroup(); // end of peaks workpace
898}
899
905 m_coordSystem = coordinateSystem;
906}
907
912
913// prevent shared pointer from deleting this
914struct NullDeleter {
915 template <typename T> void operator()(T * /*unused*/) {}
916};
919
925}
926
927ITableWorkspace *PeaksWorkspace::doCloneColumns(const std::vector<std::string> & /*colNames*/) const {
928 throw Kernel::Exception::NotImplementedError("PeaksWorkspace cannot clone columns.");
929}
930} // namespace Mantid::DataObjects
931
933
934namespace Mantid::Kernel {
935
936template <>
938IPropertyManager::getValue<Mantid::DataObjects::PeaksWorkspace_sptr>(const std::string &name) const {
939 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::PeaksWorkspace_sptr> *>(getPointerToProperty(name));
940 if (prop) {
941 return *prop;
942 } else {
943 std::string message =
944 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<PeaksWorkspace>.";
945 throw std::runtime_error(message);
946 }
947}
948
949template <>
951IPropertyManager::getValue<Mantid::DataObjects::PeaksWorkspace_const_sptr>(const std::string &name) const {
952 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::PeaksWorkspace_sptr> *>(getPointerToProperty(name));
953 if (prop) {
954 return prop->operator()();
955 } else {
956 std::string message =
957 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<PeaksWorkspace>.";
958 throw std::runtime_error(message);
959 }
960}
961
962} // namespace Mantid::Kernel
963
double value
The value of the point.
Definition: FitMW.cpp:51
double position
Definition: GetAllEi.cpp:154
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
Definition: System.h:53
#define DECLARE_WORKSPACE(classname)
Run & mutableRun()
Writable version of the run object.
const Run & run() const
Run details object access.
Geometry::Instrument_const_sptr getInstrument() const
Returns the parameterized instrument.
const Sample & sample() const
Sample accessors.
int getRunNumber() const
Utility method to get the run number.
void setNumberOfDetectorGroups(const size_t count) const
Sets the number of detector groups.
Interface to the class Mantid::DataObjects::PeaksWorkspace.
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
This class contains the information about the log entries.
Definition: LogManager.h:44
const Geometry::Goniometer & getGoniometer() const
Return reference to the first const Goniometer object for this run.
Definition: Run.cpp:324
const Geometry::OrientedLattice & getOrientedLattice() const
Get a reference to the sample's OrientedLattice.
Definition: Sample.cpp:154
double getL() const override
Get the L index of the peak.
Definition: BasePeak.cpp:100
double getIntensity() const override
Return the integrated peak intensity.
Definition: BasePeak.cpp:185
double getAbsorptionWeightedPathLength() const override
Gets the absorption weighted path length.
Definition: BasePeak.cpp:340
double getSigmaIntensity() const override
Return the error on the integrated peak intensity.
Definition: BasePeak.cpp:188
double getK() const override
Get the K index of the peak.
Definition: BasePeak.cpp:97
int getPeakNumber() const override
Returns the unique peak number Returns -1 if it could not find it.
Definition: BasePeak.cpp:234
int getRunNumber() const override
Return the run number this peak was measured at.
Definition: BasePeak.cpp:78
double getH() const override
Get the H index of the peak.
Definition: BasePeak.cpp:94
double getBinCount() const override
Return the # of counts in the bin at its peak.
Definition: BasePeak.cpp:182
Mantid::Kernel::Matrix< double > getGoniometerMatrix() const override
Get the goniometer rotation matrix at which this peak was measured.
Definition: BasePeak.cpp:210
const Mantid::Geometry::PeakShape & getPeakShape() const override
Get the peak shape.
Definition: BasePeak.cpp:290
PeakColumn : a Column sub-class used to display peak information as a TableWorkspace.
Definition: PeakColumn.h:28
Comparator class for sorting peaks by one or more criteria.
bool operator()(const Peak &a, const Peak &b)
Compare two peaks using the stored criteria.
PeakComparator(std::vector< ColumnAndDirection > &criteria)
Constructor for the comparator for sorting peaks.
LeanElasticPeaksWorkspace::ColumnAndDirection ColumnAndDirection
std::vector< ColumnAndDirection > & criteria
Structure describing a single-crystal peak.
Definition: Peak.h:34
double getDSpacing() const override
Calculate the d-spacing of the peak, in 1/Angstroms
Definition: Peak.cpp:416
std::string getBankName() const
Find the name of the bank that is the parent of the detector.
Definition: Peak.cpp:353
const std::set< int > & getContributingDetIDs() const
Return the set of detector IDs that contribute to this peak.
Definition: Peak.cpp:292
double getInitialEnergy() const override
Get the initial (incident) neutron energy in meV.
Definition: Peak.cpp:695
Mantid::Kernel::V3D getQLabFrame() const override
Return the Q change (of the lattice, k_i - k_f) for this peak.
Definition: Peak.cpp:441
double getFinalEnergy() const override
Get the final neutron energy in meV.
Definition: Peak.cpp:692
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
Definition: Peak.cpp:364
double getTOF() const override
Calculate the time of flight (in microseconds) of the neutrons for this peak, using the geometry of t...
Definition: Peak.cpp:379
Mantid::Kernel::V3D getQSampleFrame() const override
Return the Q change (of the lattice, k_i - k_f) for this peak.
Definition: Peak.cpp:472
int getDetectorID() const
Get the ID of the detector at the center of the peak
Definition: Peak.cpp:271
double getScattering() const override
Calculate the scattering angle of the peak
Definition: Peak.cpp:397
double getValueByColName(std::string colName) const override
Helper function for displaying/sorting peaks.
Definition: Peak.cpp:593
The class PeaksWorkspace stores information about a set of SCD peaks.
Kernel::SpecialCoordinateSystem getSpecialCoordinateSystem() const override
Get the special coordinate system.
API::ITableWorkspace_sptr createDetectorTable() const override
Creates a new TableWorkspace giving the IDs of the detectors that contribute to the peaks within the ...
std::vector< std::shared_ptr< Mantid::DataObjects::PeakColumn< Peak > > > m_columns
Column shared pointers.
IPeak_uptr createPeak() const override
Create a Peak using default values.
std::pair< std::string, bool > ColumnAndDirection
std::vector< Peak > m_peaks
Vector of Peak contained within.
ITableWorkspace * doCloneColumns(const std::vector< std::string > &colNames) const override
Peak & getPeak(int peakNum) override
Return a reference to the Peak.
void removePeaks(std::vector< int > badPeaks) override
Removes multiple peaks.
void removePeak(int peakNum) override
Removes the indicated peak.
std::vector< std::string > m_columnNames
Column names.
std::vector< Peak > & getPeaks()
Return a reference to the Peaks vector.
void initColumns()
Initialize the table structure.
std::shared_ptr< Mantid::API::Column > getColumn(const std::string &name) override
Gets the shared pointer to a column by name.
virtual size_t getColumnIndex(const std::string &name) const
IPeak_uptr createPeakHKL(const Kernel::V3D &HKL) const override
Create a Peak from a HKL value provided by the client.
void addPeakColumn(const std::string &name)
Adds a new PeakColumn of the given type.
IPeak_uptr createPeakQSample(const Kernel::V3D &position) const override
Creates an instance of a Peak BUT DOES NOT ADD IT TO THE WORKSPACE.
void saveNexus(::NeXus::File *file) const override
std::vector< std::pair< std::string, std::string > > peakInfo(const Kernel::V3D &qFrame, bool labCoords) const override
Returns selected information for a "peak" at QLabFrame.
std::string getConvention() const override
bool hasIntegratedPeaks() const override
Getter for the integration status.
void sort(std::vector< ColumnAndDirection > &criteria) override
Sort the peaks by one or more criteria.
API::LogManager_sptr logs() override
Get access to shared pointer containing workspace porperties.
int peakInfoNumber(const Kernel::V3D &qFrame, bool labCoords) const override
Returns selected information for a "peak" at QLabFrame.
API::LogManager_const_sptr getLogs() const override
Get constant access to shared pointer containing workspace porperties; Copies logs into new LogManage...
size_t getMemorySize() const override
Return the memory used in bytes.
Kernel::SpecialCoordinateSystem m_coordSystem
Coordinates.
void addPeak(const Geometry::IPeak &peak) override
Add a peak to the list.
void setCoordinateSystem(const Kernel::SpecialCoordinateSystem coordinateSystem) override
Set the special coordinate system.
size_t rowCount() const override
Number of rows in the workspace.
Class to represent a particular goniometer setting, which is described by the rotation matrix.
Definition: Goniometer.h:55
std::vector< double > getEulerAngles(const std::string &convention="YZX")
Return Euler angles acording to a convention.
Definition: Goniometer.cpp:282
const Kernel::DblMatrix & getR() const
Return global rotation matrix.
Definition: Goniometer.cpp:80
void calcFromQSampleAndWavelength(const Mantid::Kernel::V3D &Q, double wavelength, bool flip_x=false, bool inner=false)
Calculate goniometer for rotation around y-asix for constant wavelength from Q Sample.
Definition: Goniometer.cpp:197
HKL : HKL MDFrame.
Definition: HKL.h:21
Structure describing a single-crystal peak.
Definition: IPeak.h:26
Class to implement UB matrix.
const Kernel::DblMatrix & getUB() const
Get the UB matrix.
virtual std::string toJSON() const =0
Serialize.
Marks code as not implemented yet.
Definition: Exception.h:138
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Numerical Matrix class.
Definition: Matrix.h:42
T Invert()
LU inversion routine.
Definition: Matrix.cpp:924
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
static double run(const std::string &src, const std::string &dest, const double srcValue, const double l1, const double l2, const double theta, const DeltaEMode::Type emode, const double efixed)
Convert a single value between the given units (as strings)
Class for 3D vectors.
Definition: V3D.h:34
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition: V3D.h:287
double norm() const noexcept
Definition: V3D.h:263
std::shared_ptr< const LogManager > LogManager_const_sptr
shared pointer to the logManager base class (const version)
Definition: LogManager.h:210
std::shared_ptr< LogManager > LogManager_sptr
shared pointer to the logManager base class
Definition: LogManager.h:208
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< const PeaksWorkspace > PeaksWorkspace_const_sptr
Typedef for a shared pointer to a const peaks workspace.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::unique_ptr< Peak > Peak_uptr
Definition: Peak.h:170
std::unique_ptr< IPeak > IPeak_uptr
Definition: IPeak.h:103
SpecialCoordinateSystem
Special coordinate systems for Q3D.
Helper class which provides the Collimation Length for SANS instruments.
std::string to_string(const wide_integer< Bits, Signed > &n)