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