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"
11#include "MantidDataObjects/DllConfig.h"
15#include "MantidKernel/Logger.h"
17#include "MantidNexus/NexusFile.h"
18
19#include <cmath>
20
21using namespace Mantid::API;
22using namespace Mantid::Kernel;
23using namespace Mantid::Geometry;
24
25namespace Mantid::DataObjects {
28
30
31//---------------------------------------------------------------------------------------------
34PeaksWorkspace::PeaksWorkspace() : IPeaksWorkspace(), m_peaks(), m_columns(), m_columnNames(), m_coordSystem(None) {
35 initColumns();
36 // PeaksWorkspace does not use the grouping mechanism of ExperimentInfo.
37 setNumberOfDetectorGroups(0);
38}
39
40//---------------------------------------------------------------------------------------------
45// PeaksWorkspace::PeaksWorkspace(const PeaksWorkspace &other) = default;
47 : IPeaksWorkspace(other), m_peaks(other.m_peaks), m_columns(), m_columnNames(), m_coordSystem(other.m_coordSystem) {
49 // PeaksWorkspace does not use the grouping mechanism of ExperimentInfo.
51}
52
55class PeakComparator {
56public:
58 std::vector<ColumnAndDirection> &criteria;
59
64 explicit PeakComparator(std::vector<ColumnAndDirection> &criteria) : criteria(criteria) {}
65
67 inline bool operator()(const Peak &a, const Peak &b) {
68 for (const auto &name : criteria) {
69 const auto &col = name.first;
70 const bool ascending = name.second;
71 bool lessThan = false;
72 if (col == "BankName") {
73 // If this criterion is equal, move on to the next one
74 const std::string valA = a.getBankName();
75 const std::string valB = b.getBankName();
76 // Move on to lesser criterion if equal
77 if (valA == valB)
78 continue;
79 lessThan = (valA < valB);
80 } else {
81 // General double comparison
82 const double valA = a.getValueByColName(col);
83 const double valB = b.getValueByColName(col);
84 // Move on to lesser criterion if equal
85 if (valA == valB)
86 continue;
87 lessThan = (valA < valB);
88 }
89 // Flip the sign of comparison if descending.
90 if (ascending)
91 return lessThan;
92 else
93 return !lessThan;
94 }
95 // If you reach here, all criteria were ==; so not <, so return false
96 return false;
97 }
98};
99
100//---------------------------------------------------------------------------------------------
108void PeaksWorkspace::sort(std::vector<ColumnAndDirection> &criteria) {
109 PeakComparator comparator(criteria);
110 std::stable_sort(m_peaks.begin(), m_peaks.end(), comparator);
111}
112
113//---------------------------------------------------------------------------------------------
116int PeaksWorkspace::getNumberPeaks() const { return int(m_peaks.size()); }
117
118//---------------------------------------------------------------------------------------------
121std::string PeaksWorkspace::getConvention() const { return m_convention; }
122
123//---------------------------------------------------------------------------------------------
127void PeaksWorkspace::removePeak(const int peakNum) {
128 if (peakNum >= static_cast<int>(m_peaks.size()) || peakNum < 0) {
129 throw std::invalid_argument("PeaksWorkspace::removePeak(): peakNum is out of range.");
130 }
131 m_peaks.erase(m_peaks.begin() + peakNum);
132}
133
137void PeaksWorkspace::removePeaks(std::vector<int> badPeaks) {
138 if (badPeaks.empty())
139 return;
140 // if index of peak is in badPeaks remove
141 int ip = -1;
142 auto it = std::remove_if(m_peaks.begin(), m_peaks.end(), [&ip, badPeaks](const Peak &pk) {
143 UNUSED_ARG(pk);
144 ip++;
145 return std::any_of(badPeaks.cbegin(), badPeaks.cend(), [ip](int badPeak) { return badPeak == ip; });
146 });
147 m_peaks.erase(it, m_peaks.end());
148}
149
150//---------------------------------------------------------------------------------------------
155 if (dynamic_cast<const Peak *>(&ipeak)) {
156 m_peaks.emplace_back(static_cast<const Peak &>(ipeak));
157 } else {
158 m_peaks.emplace_back(Peak(ipeak));
159 }
160}
161
162//---------------------------------------------------------------------------------------------
168 auto peak = createPeak(position, frame);
169 addPeak(*peak);
170}
171
172//---------------------------------------------------------------------------------------------
176void PeaksWorkspace::addPeak(Peak &&peak) { m_peaks.emplace_back(peak); }
177
178//---------------------------------------------------------------------------------------------
183Peak &PeaksWorkspace::getPeak(size_t const peakNum) {
184 if (peakNum >= m_peaks.size()) {
185 throw std::invalid_argument("PeaksWorkspace::getPeak(): peakNum is out of range.");
186 }
187 return m_peaks[peakNum];
188}
189
190//---------------------------------------------------------------------------------------------
195const Peak &PeaksWorkspace::getPeak(size_t const peakNum) const {
196 if (peakNum >= m_peaks.size()) {
197 throw std::invalid_argument("PeaksWorkspace::getPeak(): peakNum is out of range.");
198 }
199 return m_peaks[peakNum];
200}
201
202//---------------------------------------------------------------------------------------------
209std::unique_ptr<Geometry::IPeak> PeaksWorkspace::createPeak(const Kernel::V3D &QLabFrame,
210 std::optional<double> detectorDistance) const {
211 // create a peak using the qLab frame
212 std::unique_ptr<IPeak> peak = std::make_unique<Peak>(this->getInstrument(), QLabFrame, detectorDistance);
213 // Set the goniometer
214 peak->setGoniometerMatrix(this->run().getGoniometer().getR());
215 // Take the run number from this
216 peak->setRunNumber(this->getRunNumber());
217
218 return peak;
219}
220
221//---------------------------------------------------------------------------------------------
228std::unique_ptr<Geometry::IPeak> PeaksWorkspace::createPeak(const Kernel::V3D &position,
229 const Kernel::SpecialCoordinateSystem &frame) const {
230 if (frame == Mantid::Kernel::HKL) {
231 return createPeakHKL(position);
232 } else if (frame == Mantid::Kernel::QLab) {
233 return createPeak(position);
234 } else {
236 }
237}
238
239//---------------------------------------------------------------------------------------------
246std::unique_ptr<IPeak> PeaksWorkspace::createPeakQSample(const V3D &position) const {
247 // Create a peak from QSampleFrame
248
249 Geometry::Goniometer goniometer;
250
252 // See if we can get a wavelength/energy
253 // Then assume constant wavelength
254 double wavelength(0);
255 if (props->hasProperty("wavelength")) {
256 wavelength = props->getLogAsSingleValue("wavelength");
257 } else if (props->hasProperty("energy")) {
258 wavelength = Kernel::UnitConversion::run("Energy", "Wavelength", props->getPropertyValueAsType<double>("energy"), 0,
260 } else if (getInstrument()->hasParameter("wavelength")) {
261 wavelength = getInstrument()->getNumberParameter("wavelength").at(0);
262 }
263
264 if (wavelength > 0) {
265 goniometer.calcFromQSampleAndWavelength(position, wavelength);
266 g_log.information() << "Found goniometer rotation to be " << goniometer.getEulerAngles()[0]
267 << " degrees for Q sample = " << position << "\n";
268 } else {
269 goniometer = run().getGoniometer();
270 }
271 // create a peak using the qLab frame
272 std::unique_ptr<IPeak> peak = std::make_unique<Peak>(getInstrument(), position, goniometer.getR());
273 // Take the run number from this
274 peak->setRunNumber(getRunNumber());
275 return peak;
276}
277
293std::vector<std::pair<std::string, std::string>> PeaksWorkspace::peakInfo(const Kernel::V3D &qFrame,
294 bool labCoords) const {
295 std::vector<std::pair<std::string, std::string>> Result;
296 std::ostringstream oss;
297 oss << std::setw(12) << std::fixed << std::setprecision(3) << (qFrame.norm());
298 std::pair<std::string, std::string> QMag("|Q|", oss.str());
299 Result.emplace_back(QMag);
300
301 oss.str("");
302 oss.clear();
303 oss << std::setw(12) << std::fixed << std::setprecision(3) << (2.0 * M_PI / qFrame.norm());
304
305 std::pair<std::string, std::string> dspc("d-spacing", oss.str());
306 oss.str("");
307 oss.clear();
308 Result.emplace_back(dspc);
309
310 int seqNum = -1;
311 bool hasOneRunNumber = true;
312 int runNum = -1;
313 try {
314 int NPeaks = getNumberPeaks();
315 double minDist = 10000000;
316 for (int i = 0; i < NPeaks; i++) {
317 Peak pk = getPeak(i);
318 V3D Q = pk.getQLabFrame();
319 if (!labCoords)
320 Q = pk.getQSampleFrame();
321 double D = qFrame.distance(Q);
322 if (D < minDist) {
323 minDist = D;
324 seqNum = i;
325 }
326
327 int run = pk.getRunNumber();
328 if (runNum < 0)
329 runNum = run;
330 else if (runNum != run)
331 hasOneRunNumber = false;
332 }
333 } catch (...) {
334 seqNum = -1; // peak could have been removed
335 }
336 V3D Qlab = qFrame;
337 V3D Qsamp;
338 Kernel::Matrix<double> Gon(3, 3, true);
339
340 if (seqNum >= 0)
341 Gon = getPeak(seqNum).getGoniometerMatrix();
342 if (labCoords) {
343
344 Kernel::Matrix<double> InvGon(Gon);
345 InvGon.Invert();
346 Qsamp = InvGon * Qlab;
347
348 } else {
349 Qsamp = qFrame;
350 Qlab = Gon * Qsamp;
351 }
352
353 if (labCoords || seqNum >= 0)
354
355 {
356 std::pair<std::string, std::string> QlabStr("Qlab", boost::lexical_cast<std::string>(Qlab));
357 Result.emplace_back(QlabStr);
358 }
359
360 if (!labCoords || seqNum >= 0) {
361
362 std::pair<std::string, std::string> QsampStr("QSample", boost::lexical_cast<std::string>(Qsamp));
363 Result.emplace_back(QsampStr);
364 }
365
366 try {
367 IPeak_uptr iPeak = createPeak(Qlab);
368 Peak_uptr peak(static_cast<DataObjects::Peak *>(iPeak.release()));
369
370 if (sample().hasOrientedLattice()) {
371
372 peak->setGoniometerMatrix(Gon);
374
375 const Kernel::Matrix<double> &UB0 = lat.getUB();
377 UB.Invert();
378 V3D hkl = UB * Qsamp / 2 / M_PI;
379
380 std::pair<std::string, std::string> HKL("HKL", boost::lexical_cast<std::string>(hkl));
381 Result.emplace_back(HKL);
382 }
383
384 if (hasOneRunNumber) {
385 std::pair<std::string, std::string> runn("RunNumber", " " + std::to_string(runNum));
386 Result.emplace_back(runn);
387 }
388
389 //------- Now get phi, chi and omega ----------------
390 Geometry::Goniometer GonG(Gon);
391 std::vector<double> OmegaChiPhi = GonG.getEulerAngles("YZY");
392 Kernel::V3D PhiChiOmega(OmegaChiPhi[2], OmegaChiPhi[1], OmegaChiPhi[0]);
393
394 std::pair<std::string, std::string> GRead("Goniometer Angles", boost::lexical_cast<std::string>(PhiChiOmega));
395 Result.emplace_back(GRead);
396
397 std::pair<std::string, std::string> SeqNum("Seq Num,1st=1", " " + std::to_string(seqNum + 1));
398 Result.emplace_back(SeqNum);
399
400 oss << std::setw(12) << std::fixed << std::setprecision(3) << (peak->getWavelength());
401 std::pair<std::string, std::string> wl("Wavelength", oss.str());
402 Result.emplace_back(wl);
403 oss.str("");
404 oss.clear();
405
406 if (peak->findDetector()) {
407 std::pair<std::string, std::string> detpos("Position(x,y,z)",
408 boost::lexical_cast<std::string>(peak->getDetPos()));
409 Result.emplace_back(detpos);
410
411 oss << std::setw(15) << std::fixed << std::setprecision(3) << (peak->getTOF());
412 std::pair<std::string, std::string> tof("TOF", oss.str());
413 Result.emplace_back(tof);
414 oss.str("");
415 oss.clear();
416
417 oss << std::setw(12) << std::fixed << std::setprecision(3) << (peak->getFinalEnergy());
418 std::pair<std::string, std::string> Energy("Energy", oss.str());
419 Result.emplace_back(Energy);
420 oss.str("");
421 oss.clear();
422
423 std::pair<std::string, std::string> row("Row", " " + std::to_string(peak->getRow()));
424 Result.emplace_back(row);
425
426 std::pair<std::string, std::string> col("Col", " " + std::to_string(peak->getCol()));
427 Result.emplace_back(col);
428
429 std::pair<std::string, std::string> bank("Bank", " " + peak->getBankName());
430 Result.emplace_back(bank);
431
432 oss << std::setw(12) << std::fixed << std::setprecision(3) << (peak->getScattering());
433 std::pair<std::string, std::string> scat("Scattering Angle", oss.str());
434 Result.emplace_back(scat);
435 }
436
437 } catch (...) // Impossible position
438 {
439 }
440 return Result;
441}
442
450std::unique_ptr<IPeak> PeaksWorkspace::createPeakHKL(const V3D &HKL) const {
451 /*
452 The following allows us to add peaks where we have a single UB to work from.
453 */
454 const auto &lattice = this->sample().getOrientedLattice();
455 const auto &goniometer = this->run().getGoniometer();
456
457 // Calculate qLab from q HKL. As per Busing and Levy 1967, q_lab_frame = 2pi *
458 // Goniometer * UB * HKL
459 const V3D qLabFrame = goniometer.getR() * lattice.getUB() * HKL * 2 * M_PI;
460
461 // create a peak using the qLab frame
462 // This should calculate the detector positions too
463 std::unique_ptr<IPeak> peak = std::make_unique<Peak>(this->getInstrument(), qLabFrame);
464 // We need to set HKL separately to keep things consistent.
465 peak->setHKL(HKL[0], HKL[1], HKL[2]);
466 peak->setIntHKL(peak->getHKL());
467 // Set the goniometer
468 peak->setGoniometerMatrix(goniometer.getR());
469 // Take the run number from this
470 peak->setRunNumber(this->getRunNumber());
471
472 return peak;
473}
474
480std::unique_ptr<IPeak> PeaksWorkspace::createPeak() const { return std::make_unique<Peak>(); }
481
497int PeaksWorkspace::peakInfoNumber(const Kernel::V3D &qFrame, bool labCoords) const {
498 std::vector<std::pair<std::string, std::string>> Result;
499 std::ostringstream oss;
500 oss << std::setw(12) << std::fixed << std::setprecision(3) << (qFrame.norm());
501 std::pair<std::string, std::string> QMag("|Q|", oss.str());
502 Result.emplace_back(QMag);
503
504 oss.str("");
505 oss.clear();
506 oss << std::setw(12) << std::fixed << std::setprecision(3) << (2.0 * M_PI / qFrame.norm());
507
508 std::pair<std::string, std::string> dspc("d-spacing", oss.str());
509 oss.str("");
510 oss.clear();
511 Result.emplace_back(dspc);
512
513 int seqNum = -1;
514 double minDist = 10000000;
515
516 for (int i = 0; i < getNumberPeaks(); i++) {
517 Peak pk = getPeak(i);
518 V3D Q = pk.getQLabFrame();
519 if (!labCoords)
520 Q = pk.getQSampleFrame();
521 double D = qFrame.distance(Q);
522 if (D < minDist) {
523 minDist = D;
524 seqNum = i + 1;
525 }
526 }
527 return seqNum;
528}
529
530//---------------------------------------------------------------------------------------------
532std::vector<Peak> &PeaksWorkspace::getPeaks() { return m_peaks; }
533
535const std::vector<Peak> &PeaksWorkspace::getPeaks() const { return m_peaks; }
536
541 bool ret = false;
542 const std::string peaksIntegrated = "PeaksIntegrated";
543 if (this->run().hasProperty(peaksIntegrated)) {
544 const auto value = boost::lexical_cast<int>(this->run().getProperty(peaksIntegrated)->value());
545 ret = (value != 0);
546 }
547 return ret;
548}
549
550//---------------------------------------------------------------------------------------------
552size_t PeaksWorkspace::getMemorySize() const { return getNumberPeaks() * sizeof(Peak); }
553
554//---------------------------------------------------------------------------------------------
563 auto table = API::WorkspaceFactory::Instance().createTable("TableWorkspace");
564 table->addColumn("int", "Index");
565 table->addColumn("int", "DetectorID");
566
567 const auto npeaks(static_cast<int>(this->rowCount()));
568 int nrows(0);
569 for (int i = 0; i < npeaks; ++i) {
570 const Peak &peak = this->m_peaks[i];
571 auto detIDs = peak.getContributingDetIDs();
572 auto itEnd = detIDs.end();
573 for (auto it = detIDs.begin(); it != itEnd; ++it) {
574 table->appendRow();
575 table->cell<int>(nrows, 0) = i;
576 table->cell<int>(nrows, 1) = *it;
577 ++nrows;
578 }
579 }
580
581 return table;
582}
583
584//---------------------------------------------------------------------------------------------
587 // Note: The column types are controlled in PeakColumn.cpp
588 addPeakColumn("RunNumber");
589 addPeakColumn("DetID");
590 addPeakColumn("h");
591 addPeakColumn("k");
592 addPeakColumn("l");
593 addPeakColumn("Wavelength");
594 addPeakColumn("Energy");
595 addPeakColumn("TOF");
596 addPeakColumn("DSpacing");
597 addPeakColumn("Intens");
598 addPeakColumn("SigInt");
599 addPeakColumn("Intens/SigInt");
600 addPeakColumn("BinCount");
601 addPeakColumn("BankName");
602 addPeakColumn("Row");
603 addPeakColumn("Col");
604 addPeakColumn("QLab");
605 addPeakColumn("QSample");
606 addPeakColumn("PeakNumber");
607 addPeakColumn("TBar");
608 addPeakColumn("IntHKL");
609 addPeakColumn("IntMNP");
610}
611
612//---------------------------------------------------------------------------------------------
617void PeaksWorkspace::addPeakColumn(const std::string &name) {
618 // Create the PeakColumn.
619 m_columns.emplace_back(std::make_shared<DataObjects::PeakColumn<Peak>>(this->m_peaks, name));
620 // Cache the names
621 m_columnNames.emplace_back(name);
622}
623
624//---------------------------------------------------------------------------------------------
626size_t PeaksWorkspace::getColumnIndex(const std::string &name) const {
627 const auto it = std::find(m_columnNames.cbegin(), m_columnNames.cend(), name);
628 if (it != m_columnNames.cend())
629 return std::distance(m_columnNames.cbegin(), it);
630 throw std::invalid_argument("Column named " + name + " was not found in the PeaksWorkspace.");
631}
632
633//---------------------------------------------------------------------------------------------
635std::shared_ptr<Mantid::API::Column> PeaksWorkspace::getColumn(size_t index) {
636 if (index >= m_columns.size())
637 throw std::invalid_argument("PeaksWorkspace::getColumn() called with invalid index.");
638 return m_columns[index];
639}
640
641//---------------------------------------------------------------------------------------------
643std::shared_ptr<const Mantid::API::Column> PeaksWorkspace::getColumn(size_t index) const {
644 if (index >= m_columns.size())
645 throw std::invalid_argument("PeaksWorkspace::getColumn() called with invalid index.");
646 return m_columns[index];
647}
648
649void PeaksWorkspace::saveNexus(Nexus::File *file) const {
650
651 // Number of Peaks
652 const size_t np(m_peaks.size());
653
654 // Column vectors for peaks table
655 std::vector<int> detectorID(np);
656 std::vector<double> H(np);
657 std::vector<double> K(np);
658 std::vector<double> L(np);
659 std::vector<double> intensity(np);
660 std::vector<double> sigmaIntensity(np);
661 std::vector<double> binCount(np);
662 std::vector<double> initialEnergy(np);
663 std::vector<double> finalEnergy(np);
664 std::vector<double> waveLength(np);
665 std::vector<double> scattering(np);
666 std::vector<double> dSpacing(np);
667 std::vector<double> TOF(np);
668 std::vector<int> runNumber(np);
669 std::vector<int> peakNumber(np);
670 std::vector<double> tbar(np);
671 std::vector<double> intHKL(3 * np);
672 std::vector<double> intMNP(3 * np);
673 std::vector<double> goniometerMatrix(9 * np);
674 std::vector<std::string> shapes(np);
675 std::vector<double> monitorCount(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 {
698 V3D hkl = p.getIntHKL();
699 intHKL[3 * i + 0] = hkl[0];
700 intHKL[3 * i + 1] = hkl[1];
701 intHKL[3 * i + 2] = hkl[2];
702 V3D mnp = p.getIntMNP();
703 intMNP[3 * i + 0] = mnp[0];
704 intMNP[3 * i + 1] = mnp[1];
705 intMNP[3 * i + 2] = mnp[2];
707 goniometerMatrix[9 * i + 0] = gm[0][0];
708 goniometerMatrix[9 * i + 1] = gm[1][0];
709 goniometerMatrix[9 * i + 2] = gm[2][0];
710 goniometerMatrix[9 * i + 3] = gm[0][1];
711 goniometerMatrix[9 * i + 4] = gm[1][1];
712 goniometerMatrix[9 * i + 5] = gm[2][1];
713 goniometerMatrix[9 * i + 6] = gm[0][2];
714 goniometerMatrix[9 * i + 7] = gm[1][2];
715 goniometerMatrix[9 * i + 8] = gm[2][2];
716 }
717 const std::string shapeJSON = p.getPeakShape().toJSON();
718 shapes[i] = shapeJSON;
719 if (shapeJSON.size() > maxShapeJSONLength) {
720 maxShapeJSONLength = shapeJSON.size();
721 }
722 monitorCount[i] = p.getMonitorCount();
723 }
724
725 // Start Peaks Workspace in Nexus File
726 const std::string specifyInteger = "An integer";
727 const std::string specifyDouble = "A double";
728 const std::string specifyString = "A string";
729 file->makeGroup("peaks_workspace", "NXentry",
730 true); // For when peaksWorkspace can be loaded
731
732 // Coordinate system
733 file->writeData("coordinate_system", static_cast<uint32_t>(m_coordSystem));
734
735 // Write out the Qconvention
736 // ki-kf for Inelastic convention; kf-ki for Crystallography convention
737 std::string m_QConvention = this->getConvention();
738 file->putAttr("QConvention", m_QConvention);
739
740 // Detectors column
741 file->writeData("column_1", detectorID);
742 file->openData("column_1");
743 file->putAttr("name", "Detector ID");
744 file->putAttr("interpret_as", specifyInteger);
745 file->putAttr("units", "Not known");
746 file->closeData();
747
748 // H column
749 file->writeData("column_2", H);
750 file->openData("column_2");
751 file->putAttr("name", "H");
752 file->putAttr("interpret_as", specifyDouble);
753 file->putAttr("units", "Not known"); // Units may need changing when known
754 file->closeData();
755
756 // K column
757 file->writeData("column_3", K);
758 file->openData("column_3");
759 file->putAttr("name", "K");
760 file->putAttr("interpret_as", specifyDouble);
761 file->putAttr("units", "Not known"); // Units may need changing when known
762 file->closeData();
763
764 // L column
765 file->writeData("column_4", L);
766 file->openData("column_4");
767 file->putAttr("name", "L");
768 file->putAttr("interpret_as", specifyDouble);
769 file->putAttr("units", "Not known"); // Units may need changing when known
770 file->closeData();
771
772 // Intensity column
773 file->writeData("column_5", intensity);
774 file->openData("column_5");
775 file->putAttr("name", "Intensity");
776 file->putAttr("interpret_as", specifyDouble);
777 file->putAttr("units", "Not known"); // Units may need changing when known
778 file->closeData();
779
780 // Sigma Intensity column
781 file->writeData("column_6", sigmaIntensity);
782 file->openData("column_6");
783 file->putAttr("name", "Sigma Intensity");
784 file->putAttr("interpret_as", specifyDouble);
785 file->putAttr("units", "Not known"); // Units may need changing when known
786 file->closeData();
787
788 // Bin Count column
789 file->writeData("column_7", binCount);
790 file->openData("column_7");
791 file->putAttr("name", "Bin Count");
792 file->putAttr("interpret_as", specifyDouble);
793 file->putAttr("units", "Not known"); // Units may need changing when known
794 file->closeData();
795
796 // Initial Energy column
797 file->writeData("column_8", initialEnergy);
798 file->openData("column_8");
799 file->putAttr("name", "Initial Energy");
800 file->putAttr("interpret_as", specifyDouble);
801 file->putAttr("units", "Not known"); // Units may need changing when known
802 file->closeData();
803
804 // Final Energy column
805 file->writeData("column_9", finalEnergy);
806 file->openData("column_9");
807 file->putAttr("name", "Final Energy");
808 file->putAttr("interpret_as", specifyDouble);
809 file->putAttr("units", "Not known"); // Units may need changing when known
810 file->closeData();
811
812 // Wave Length Column
813 file->writeData("column_10", waveLength);
814 file->openData("column_10");
815 file->putAttr("name", "Wave Length");
816 file->putAttr("interpret_as", specifyDouble);
817 file->putAttr("units", "Not known"); // Units may need changing when known
818 file->closeData();
819
820 // Scattering Column
821 file->writeData("column_11", scattering);
822 file->openData("column_11");
823 file->putAttr("name", "Scattering");
824 file->putAttr("interpret_as", specifyDouble);
825 file->putAttr("units", "Not known"); // Units may need changing when known
826 file->closeData();
827
828 // D Spacing Column
829 file->writeData("column_12", dSpacing);
830 file->openData("column_12");
831 file->putAttr("name", "D Spacing");
832 file->putAttr("interpret_as", specifyDouble);
833 file->putAttr("units", "Not known"); // Units may need changing when known
834 file->closeData();
835
836 // TOF Column
837 file->writeData("column_13", TOF);
838 file->openData("column_13");
839 file->putAttr("name", "TOF");
840 file->putAttr("interpret_as", specifyDouble);
841 file->putAttr("units", "Not known"); // Units may need changing when known
842 file->closeData();
843
844 // Run Number column
845 file->writeData("column_14", runNumber);
846 file->openData("column_14");
847 file->putAttr("name", "Run Number");
848 file->putAttr("interpret_as", specifyInteger);
849 file->putAttr("units", "Not known"); // Units may need changing when known
850 file->closeData();
851
852 // Peak Number column
853 file->writeData("column_17", peakNumber);
854 file->openData("column_17");
855 file->putAttr("name", "Peak Number");
856 file->putAttr("interpret_as", specifyInteger);
857 file->putAttr("units", "Not known"); // Units may need changing when known
858 file->closeData();
859
860 // TBar column
861 file->writeData("column_18", tbar);
862 file->openData("column_18");
863 file->putAttr("name", "TBar");
864 file->putAttr("interpret_as", specifyDouble);
865 file->putAttr("units", "Not known"); // Units may need changing when known
866 file->closeData();
867
868 const Nexus::DimVector qlab_dims{m_peaks.size(), 3};
869
870 // Integer HKL column
871 file->writeData("column_19", intHKL, qlab_dims);
872 file->openData("column_19");
873 file->putAttr("name", "IntHKL");
874 file->putAttr("interpret_as", "A vector of 3 doubles");
875 file->putAttr("units", "r.l.u.");
876 file->closeData();
877
878 // Integer HKL column
879 file->writeData("column_20", intMNP, qlab_dims);
880 file->openData("column_20");
881 file->putAttr("name", "IntMNP");
882 file->putAttr("interpret_as", "A vector of 3 doubles");
883 file->putAttr("units", "r.l.u.");
884 file->closeData();
885
886 // Monitor Count column
887 file->writeData("column_21", monitorCount);
888 file->openData("column_21");
889 file->putAttr("name", "Monitor Count");
890 file->putAttr("interpret_as", specifyDouble);
891 file->putAttr("units", "Not known");
892 file->closeData();
893
894 // Goniometer Matrix Column
895 const Nexus::DimVector array_dims{m_peaks.size(), 9};
896 file->writeData("column_15", goniometerMatrix, array_dims);
897 file->openData("column_15");
898 file->putAttr("name", "Goniometer Matrix");
899 file->putAttr("interpret_as", "A matrix of 3x3 doubles");
900 file->putAttr("units", "Not known"); // Units may need changing when known
901 file->closeData();
902
903 // Shape
904 Nexus::DimVector dims;
905 dims.emplace_back(np);
906 dims.emplace_back(static_cast<int>(maxShapeJSONLength));
907 const std::string name = "column_16";
908 file->makeData(name, NXnumtype::CHAR, dims, false);
909 file->openData(name);
910
911 auto toNexus = new char[maxShapeJSONLength * np];
912 for (size_t ii = 0; ii < np; ii++) {
913 std::string rowStr = shapes[ii];
914 for (size_t ic = 0; ic < rowStr.size(); ic++)
915 toNexus[ii * maxShapeJSONLength + ic] = rowStr[ic];
916 for (size_t ic = rowStr.size(); ic < static_cast<size_t>(maxShapeJSONLength); ic++)
917 toNexus[ii * maxShapeJSONLength + ic] = ' ';
918 }
919
920 file->putData(toNexus);
921
922 delete[] toNexus;
923 file->putAttr("units", "Not known"); // Units may need changing when known
924 file->putAttr("name", "Shape");
925 file->putAttr("interpret_as", specifyString);
926 file->closeData();
927
928 // QLab & QSample are calculated and do not need to be saved
929
930 file->closeGroup(); // end of peaks workpace
931}
932
938 m_coordSystem = coordinateSystem;
939}
940
945
946// prevent shared pointer from deleting this
947struct NullDeleter {
948 template <typename T> void operator()(T * /*unused*/) {}
949};
952
959
960ITableWorkspace *PeaksWorkspace::doCloneColumns(const std::vector<std::string> & /*colNames*/) const {
961 throw Kernel::Exception::NotImplementedError("PeaksWorkspace cannot clone columns.");
962}
963} // namespace Mantid::DataObjects
964
966
967namespace Mantid::Kernel {
968
969template <>
970MANTID_DATAOBJECTS_DLL Mantid::DataObjects::PeaksWorkspace_sptr
971IPropertyManager::getValue<Mantid::DataObjects::PeaksWorkspace_sptr>(const std::string &name) const {
972 if (const auto *prop =
973 dynamic_cast<PropertyWithValue<Mantid::DataObjects::PeaksWorkspace_sptr> *>(getPointerToProperty(name))) {
974 return *prop;
975 } else {
976 std::string message =
977 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<PeaksWorkspace>.";
978 throw std::runtime_error(message);
979 }
980}
981
982template <>
984IPropertyManager::getValue<Mantid::DataObjects::PeaksWorkspace_const_sptr>(const std::string &name) const {
985 if (const auto *prop =
986 dynamic_cast<PropertyWithValue<Mantid::DataObjects::PeaksWorkspace_sptr> *>(getPointerToProperty(name))) {
987 return prop->operator()();
988 } else {
989 std::string message =
990 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<PeaksWorkspace>.";
991 throw std::runtime_error(message);
992 }
993}
994
995} // namespace Mantid::Kernel
996
std::string name
Definition Run.cpp:60
double intensity
double value
The value of the point.
Definition FitMW.cpp:51
double position
Definition GetAllEi.cpp:154
std::map< DeltaEMode::Type, std::string > index
#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:43
const Geometry::Goniometer & getGoniometer() const
Return reference to the first const Goniometer object for this run.
Definition Run.cpp:525
const Geometry::OrientedLattice & getOrientedLattice() const
Get a reference to the sample's OrientedLattice.
Definition Sample.cpp:198
Mantid::Kernel::V3D getIntMNP() const override
Return the int MNP vector.
Definition BasePeak.cpp:116
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:348
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:298
double getMonitorCount() const override
Return the monitor count stored in this peak.
Definition BasePeak.cpp:86
Mantid::Kernel::V3D getIntHKL() const override
Return the int HKL vector.
Definition BasePeak.cpp:113
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:450
const std::set< int > & getContributingDetIDs() const
Return the set of detector IDs that contribute to this peak.
Definition Peak.cpp:310
double getInitialEnergy() const override
Get the initial (incident) neutron energy in meV.
Definition Peak.cpp:729
Mantid::Kernel::V3D getQLabFrame() const override
Return the Q change (of the lattice, k_i - k_f) for this peak.
Definition Peak.cpp:475
int getDetectorID() const override
Get the ID of the detector at the center of the peak
Definition Peak.cpp:289
double getFinalEnergy() const override
Get the final neutron energy in meV.
Definition Peak.cpp:726
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
Definition Peak.cpp:382
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:397
Mantid::Kernel::V3D getQSampleFrame() const override
Return the Q change (of the lattice, k_i - k_f) for this peak.
Definition Peak.cpp:506
const std::string & getBankName() const
Find the name of the bank that is the parent of the detector.
Definition Peak.cpp:371
double getScattering() const override
Calculate the scattering angle of the peak
Definition Peak.cpp:415
double getValueByColName(std::string colName) const override
Helper function for displaying/sorting peaks.
Definition Peak.cpp:627
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
void saveNexus(Nexus::File *file) const override
std::vector< Peak > m_peaks
Vector of Peak contained within.
ITableWorkspace * doCloneColumns(const std::vector< std::string > &colNames) const override
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.
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.
Peak & getPeak(size_t const peakNum) override
Return a reference to the Peak.
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.
const Kernel::DblMatrix & getR() const
Return global rotation matrix.
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.
HKL : HKL MDFrame.
Definition HKL.h:20
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:51
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
Numerical Matrix class.
Definition Matrix.h:41
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:35
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition V3D.h:294
double norm() const noexcept
Definition V3D.h:270
static unsigned short constexpr CHAR
std::shared_ptr< const LogManager > LogManager_const_sptr
shared pointer to the logManager base class (const version)
Definition LogManager.h:228
std::shared_ptr< LogManager > LogManager_sptr
shared pointer to the logManager base class
Definition LogManager.h:226
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:176
std::unique_ptr< IPeak > IPeak_uptr
Definition IPeak.h:108
SpecialCoordinateSystem
Special coordinate systems for Q3D.
std::vector< dimsize_t > DimVector
Helper class which provides the Collimation Length for SANS instruments.
std::string to_string(const wide_integer< Bits, Signed > &n)