CTL  0.6.1
Computed Tomography Library
abstractsource.h
Go to the documentation of this file.
1 #ifndef CTL_ABSTRACTSOURCE_H
2 #define CTL_ABSTRACTSOURCE_H
3 #include "mat/matrix_types.h"
4 #include "models/intervaldataseries.h"
5 #include "models/abstractxrayspectrummodel.h"
6 #include "systemcomponent.h"
7 #include <QJsonArray>
8 #include <QSizeF>
9 
10 /*
11  * NOTE: This is header only.
12  */
13 
14 namespace CTL {
15 
16 class GenericSource;
17 
66 typedef Range<float> EnergyRange;
67 
69 {
72 
73 public:
74  static const uint DEFAULT_SPECTRUM_RESOLUTION_HINT = 10;
75 
76  // abstract interface
77  public:virtual EnergyRange nominalEnergyRange() const = 0;
78  protected:virtual double nominalPhotonFlux() const = 0;
79 
80 public:
81  // virtual methods
82  virtual IntervalDataSeries spectrum(uint nbSamples) const;
83  virtual uint spectrumDiscretizationHint() const;
84  virtual void setSpectrumModel(AbstractXraySpectrumModel* model);
85  QString info() const override;
86  void fromVariant(const QVariant& variant) override; // de-serialization
87  QVariant toVariant() const override; // serialization
88 
89  // getter methods
90  EnergyRange energyRange() const;
91  float meanEnergy() const;
92  double photonFlux() const;
93  double fluxModifier() const;
94  const QSizeF& focalSpotSize() const;
95  const Vector3x1& focalSpotPosition() const;
97 
98  // setter methods
99  void setFluxModifier(double modifier);
100  void setFocalSpotSize(const QSizeF& size);
101  void setFocalSpotSize(double width, double height); // convenience alternative
102  void setFocalSpotPosition(const Vector3x1& position);
103  void setFocalSpotPosition(double x, double y, double z); // convenience alternative
104  void setEnergyRangeRestriction(const EnergyRange& window);
105 
106  // other methods
107  IntervalDataSeries spectrum(EnergyRange range, uint nbSamples) const;
108  bool hasSpectrumModel() const;
109  void setSpectrumModel(std::unique_ptr<AbstractXraySpectrumModel> model);
110 
111  // converter
112  std::unique_ptr<GenericSource> toGeneric() const;
113 
114  ~AbstractSource() override = default;
115 
116 protected:
117  AbstractSource() = default;
118  AbstractSource(const QString& name);
119  AbstractSource(const QSizeF& focalSpotSize, const QString& name);
120  AbstractSource(const QSizeF& focalSpotSize,
122  const QString& name);
123  AbstractSource(const QSizeF& focalSpotSize,
125  AbstractXraySpectrumModel* spectumModel,
126  const QString& name);
127 
128  AbstractSource(const AbstractSource&) = default;
129  AbstractSource(AbstractSource&&) = default;
130  AbstractSource& operator=(const AbstractSource&) = default;
131  AbstractSource& operator=(AbstractSource&&) = default;
132 
133  QSizeF _focalSpotSize = QSizeF(0.0, 0.0);
135  double _fluxModifier = 1.0;
136 
139  bool _hasRestrictedEnergyWindow = false;
140 };
141 
163 inline AbstractSource::AbstractSource(const QString& name)
164  : SystemComponent(name)
165 {
166 }
167 
173 inline AbstractSource::AbstractSource(const QSizeF& focalSpotSize, const QString& name)
174  : SystemComponent(name)
175  , _focalSpotSize(focalSpotSize)
176 {
177 }
178 
183 inline AbstractSource::AbstractSource(const QSizeF& focalSpotSize,
184  const Vector3x1& focalSpotPosition,
185  const QString& name)
186  : SystemComponent(name)
187  , _focalSpotSize(focalSpotSize)
188  , _focalSpotPosition(focalSpotPosition)
189 {
190 }
191 
197 inline AbstractSource::AbstractSource(const QSizeF& focalSpotSize,
198  const Vector3x1& focalSpotPosition,
199  AbstractXraySpectrumModel* spectumModel,
200  const QString& name)
201  : SystemComponent(name)
202  , _focalSpotSize(focalSpotSize)
203  , _focalSpotPosition(focalSpotPosition)
204  , _spectrumModel(spectumModel)
205 {
206 }
207 
208 
273 {
274  if(!hasSpectrumModel())
275  throw std::runtime_error("No spectrum model set.");
276 
277  const auto eRange = energyRange();
279  eRange.start(), eRange.end(), nbSamples);
280 
281  // normalization not well-defined on spectra with an integral of zero -> skip
282  /* Notes:
283  * This happens when energy range restiction is outside nominal energy range. The bin value of
284  * that spectrum sample will be zero, which guarantees that if it is used somewhere, it is clear
285  * that no radiation is emitted (because energy range restriction outside operation range of the
286  * source).
287  */
288  if(!qFuzzyIsNull(spec.integral()))
289  spec.normalizeByIntegral();
290 
291  return spec;
292 }
293 
294 
295 inline IntervalDataSeries AbstractSource::spectrum(EnergyRange range, uint nbSamples) const
296 {
297  if(!hasSpectrumModel())
298  throw std::runtime_error("No spectrum model set.");
299 
301  range.start(), range.end(), nbSamples);
302  const auto eRange = energyRange();
303  spec.clampToRange({ eRange.start(), eRange.end() });
304 
305  // normalization not well-defined on spectra with an integral of zero -> skip
306  if(!qFuzzyIsNull(spec.integral()))
307  spec.normalizeByIntegral();
308 
309  return spec;
310 }
311 
318 {
319  return DEFAULT_SPECTRUM_RESOLUTION_HINT;
320 }
321 
328 inline const QSizeF& AbstractSource::focalSpotSize() const { return _focalSpotSize; }
329 
336 
341 {
342  return _spectrumModel.get();
343 }
344 
351 inline void AbstractSource::setFocalSpotSize(const QSizeF& size) { _focalSpotSize = size; }
352 
358 inline void AbstractSource::setFocalSpotSize(double width, double height)
359 {
360  _focalSpotSize = QSizeF(width, height);
361 }
362 
369 {
370  _focalSpotPosition = position;
371 }
372 
378 inline void AbstractSource::setFocalSpotPosition(double x, double y, double z)
379 {
380  _focalSpotPosition = Vector3x1({ x, y, z });
381 }
382 
383 inline void AbstractSource::setEnergyRangeRestriction(const EnergyRange& window)
384 {
385  _restrictedEnergyWindow = window;
386  _hasRestrictedEnergyWindow = true;
387 }
388 
394 inline bool AbstractSource::hasSpectrumModel() const { return static_cast<bool>(_spectrumModel); }
395 
402 inline QString AbstractSource::info() const
403 {
404  QString ret(SystemComponent::info());
405 
406  ret += typeInfoString(typeid(this))
407  + "\tEnergy range: [" + QString::number(energyRange().start()) + "," +
408  QString::number(energyRange().end()) + "] keV\n"
409  + "\tNominal photon flux: " + QString::number(nominalPhotonFlux())
410  + "photons / cm^2 @ 1m\n"
411  + "\tFlux modifier: "
412  + QString::number(_fluxModifier) + "\n";
413  + "\tFocal spot size: " + QString::number(_focalSpotSize.width()) + " mm x "
414  + QString::number(_focalSpotSize.height())
415  + " mm\n"
416  "\tFocal spot position: "
417  + QString::number(_focalSpotPosition(0, 0)) + " mm, "
418  + QString::number(_focalSpotPosition(1, 0)) + " mm, "
419  + QString::number(_focalSpotPosition(2, 0)) + " mm\n";
420 
421  ret += (this->type() == AbstractSource::Type) ? QLatin1String("}\n") : QLatin1String("");
422 
423  return ret;
424 }
425 
432 {
433  _spectrumModel.reset(model);
434 }
435 
439 inline void AbstractSource::setSpectrumModel(std::unique_ptr<AbstractXraySpectrumModel> model)
440 {
441  _spectrumModel = std::move(model);
442 }
443 
444 // Use SerializationInterface::fromVariant() documentation.
445 inline void AbstractSource::fromVariant(const QVariant& variant)
446 {
448 
449  QVariantMap varMap = variant.toMap();
450  auto fsPos = varMap.value(QStringLiteral("focal spot position"), QVariantList{0.0, 0.0, 0.0}).toList();
451  Vector3x1 fsPosVec({ fsPos.at(0).toDouble(), fsPos.at(1).toDouble(), fsPos.at(2).toDouble() });
452 
453  auto fsSize = varMap.value(QStringLiteral("focal spot size")).toMap();
454  QSizeF fsQSize;
455  fsQSize.setWidth(fsSize.value(QStringLiteral("width")).toDouble());
456  fsQSize.setHeight(fsSize.value(QStringLiteral("height")).toDouble());
457 
458  QVariant specMod = varMap.value(QStringLiteral("spectrum model"));
459 
460  _focalSpotSize = fsQSize;
461  _focalSpotPosition = fsPosVec;
462  _spectrumModel.reset(static_cast<AbstractXraySpectrumModel*>(
463  SerializationHelper::parseDataModel(specMod)));
464 }
465 
466 // Use SerializationInterface::toVariant() documentation.
467 inline QVariant AbstractSource::toVariant() const
468 {
469  QVariantMap ret = SystemComponent::toVariant().toMap();
470 
471  QVariantList fsPos;
472  fsPos.append(_focalSpotPosition.get<0>());
473  fsPos.append(_focalSpotPosition.get<1>());
474  fsPos.append(_focalSpotPosition.get<2>());
475 
476  QVariantMap fsSize;
477  fsSize.insert(QStringLiteral("width"), _focalSpotSize.width());
478  fsSize.insert(QStringLiteral("height"), _focalSpotSize.height());
479 
480  QVariant specMod = _spectrumModel ? _spectrumModel->toVariant() : QVariant();
481 
482  ret.insert(QStringLiteral("focal spot position"), fsPos);
483  ret.insert(QStringLiteral("focal spot size"), fsSize);
484  ret.insert(QStringLiteral("spectrum model"), specMod);
485 
486  return ret;
487 }
488 
490 {
491  const auto clamp = [] (float val, float low, float high)
492  {
493  return (val<low) ? low : ((val>high) ? high : val);
494  };
495 
496  const auto nomRange = nominalEnergyRange();
497  if(!_hasRestrictedEnergyWindow)
498  return nomRange;
499 
500  return { clamp(_restrictedEnergyWindow.start(), nomRange.start(), nomRange.end()),
501  clamp(_restrictedEnergyWindow.end(), nomRange.start(), nomRange.end()), };
502 }
503 
509 inline float AbstractSource::meanEnergy() const
510 {
512 }
513 
523 inline double AbstractSource::photonFlux() const { return _fluxModifier * nominalPhotonFlux(); }
524 
531 inline double AbstractSource::fluxModifier() const { return _fluxModifier; }
532 
544 inline void AbstractSource::setFluxModifier(double modifier) { _fluxModifier = modifier; }
545 
546 } // namespace CTL
547 
549 
559 
561 #endif // CTL_ABSTRACTSOURCE_H
void setFocalSpotPosition(const Vector3x1 &position)
Definition: abstractsource.h:368
#define DECLARE_ELEMENTAL_TYPE
Definition: systemcomponent.h:148
QString info() const override
Definition: abstractsource.h:402
double photonFlux() const
Definition: abstractsource.h:523
QVariant toVariant() const override
Definition: abstractsource.h:467
double & get() noexcept
Definition: matrix.tpp:164
const Vector3x1 & focalSpotPosition() const
Definition: abstractsource.h:335
static QString typeInfoString(const std::type_info &type)
Definition: systemcomponent.cpp:52
virtual double nominalPhotonFlux() const =0
void setFocalSpotSize(const QSizeF &size)
Definition: abstractsource.h:351
const QSizeF & focalSpotSize() const
Definition: abstractsource.h:328
virtual uint spectrumDiscretizationHint() const
Definition: abstractsource.h:317
virtual QString info() const
Definition: systemcomponent.cpp:29
virtual IntervalDataSeries spectrum(uint nbSamples) const
Returns the (relative) emitted radiation spectrum sampled with nbSamples bins covering the energy ran...
Definition: abstractsource.h:272
static IntervalDataSeries sampledFromModel(const AbstractIntegrableDataModel &dataModel, float from, float to, uint nbSamples, ValueType samples=BinIntegral)
Return a series of nbSamples values sampled from dataModel within the specified interval [ from,...
Definition: intervaldataseries.cpp:110
T & end()
Returns a (modifiable) reference to the end point of this range.
Definition: range.h:157
const QString & name() const
Definition: systemcomponent.cpp:42
const AbstractXraySpectrumModel * spectrumModel() const
Definition: abstractsource.h:340
QVariant toVariant() const override
Definition: systemcomponent.cpp:64
The AbstractXraySpectrumModel class is the abstract base class for data models representing X-ray spe...
Definition: abstractxrayspectrummodel.h:27
double _fluxModifier
Global (multiplicative) modifier for the photon flux.
Definition: abstractsource.h:135
The IntervalDataSeries class is a container for a series of values sampled in equidistant steps (i....
Definition: intervaldataseries.h:65
T & start()
Returns a (modifiable) reference to the start point of this range.
Definition: range.h:151
bool hasSpectrumModel() const
Definition: abstractsource.h:394
Base class for all system components.
Definition: systemcomponent.h:53
float centroid() const
Returns the centroid of the series.
Definition: intervaldataseries.cpp:335
DataModelPtr< AbstractXraySpectrumModel > _spectrumModel
Data model for the emitted radiation spectrum.
Definition: abstractsource.h:137
void setFluxModifier(double modifier)
Definition: abstractsource.h:544
EnergyRange _restrictedEnergyWindow
Windowed energy range.
Definition: abstractsource.h:138
void fromVariant(const QVariant &variant) override
Definition: abstractsource.h:445
#define CTL_TYPE_ID(newIndex)
Definition: serializationinterface.h:189
Vector3x1 _focalSpotPosition
Position of the focal spot (relative to source center).
Definition: abstractsource.h:134
unsigned int uint
Qt style alias for unsigned int.
Definition: modulelayout.h:6
QSizeF _focalSpotSize
Size of the focal spot (in mm).
Definition: abstractsource.h:133
float meanEnergy() const
Definition: abstractsource.h:509
void fromVariant(const QVariant &variant) override
Definition: systemcomponent.cpp:58
EnergyRange energyRange() const
Definition: abstractsource.h:489
Extends std::unique_ptr<T> with copy operations using the clone method of type T.
Definition: copyableuniqueptr.h:14
int type() const override
Definition: abstractsource.h:70
virtual void setSpectrumModel(AbstractXraySpectrumModel *model)
Definition: abstractsource.h:431
Base class for source components.
Definition: abstractsource.h:68
Definition: genericsource.h:11
void normalizeByIntegral()
Normalizes the values in the series such that the integral will be one afterwards.
Definition: intervaldataseries.cpp:232
double fluxModifier() const
Definition: abstractsource.h:531