Skip to content
Snippets Groups Projects
MDBox.h 12.8 KiB
Newer Older
#ifndef MDBOX_H_
#define MDBOX_H_

#include "MantidKernel/ThreadScheduler.h"
#include "MantidKernel/MultiThreaded.h"
#include "MantidGeometry/MDGeometry/MDDimensionExtents.h"
#include "MantidGeometry/MDGeometry/MDTypes.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidDataObjects/MDBoxBase.h"
#include "MantidDataObjects/MDDimensionStats.h"
#include "MantidDataObjects/MDLeanEvent.h"
namespace Mantid {
#ifndef __INTEL_COMPILER // As of July 13, the packing has no effect for the
                         // Intel compiler and produces a warning
#pragma pack(push, 4)    // Ensure the structure is no larger than it needs to

//===============================================================================================
/** Templated class for a multi-dimensional event "box".
 *
 * A box is a container of MDLeanEvent's within a certain range of values
 * within the nd dimensions. This range defines a n-dimensional "box"
 * or rectangular prism.
 *
 * This class is a simple list of points with no more internal structure.
 *
 * @tparam nd :: the number of dimensions that each MDLeanEvent will be
 *tracking.
 *                  an int > 0.
 *
 * @author Janik Zikovsky, SNS
 * @date Dec 7, 2010
 *
 * */

TMDE_CLASS
class DLLExport MDBox : public MDBoxBase<MDE, nd> {
public:
  MDBox(Mantid::API::BoxController_sptr &splitter, const uint32_t depth = 0,
        const size_t nBoxEvents = UNDEF_SIZET,
        const size_t boxID = UNDEF_SIZET);
  MDBox(Mantid::API::BoxController *const splitter, const uint32_t depth = 0,
        const size_t nBoxEvents = UNDEF_SIZET,
        const size_t boxID = UNDEF_SIZET);

  MDBox(Mantid::API::BoxController_sptr &splitter, const uint32_t depth,
        const std::vector<Mantid::Geometry::MDDimensionExtents<coord_t>> &
            extentsVector,
        const size_t nBoxEvents = UNDEF_SIZET,
        const size_t boxID = UNDEF_SIZET);
  MDBox(Mantid::API::BoxController *const splitter, const uint32_t depth,
        const std::vector<Mantid::Geometry::MDDimensionExtents<coord_t>> &
            extentsVector,
        const size_t nBoxEvents = UNDEF_SIZET,
        const size_t boxID = UNDEF_SIZET);

  MDBox(const MDBox<MDE, nd> &other, Mantid::API::BoxController *const otherBC);


  // ----------------------------- ISaveable Methods
  // ------------------------------------------------------
  Kernel::ISaveable *getISaveable() override;
  Kernel::ISaveable *getISaveable() const override;
Hahn, Steven's avatar
Hahn, Steven committed
  void setFileBacked(const uint64_t /*fileLocation*/, const size_t /*fileSize*/,
                     const bool /*markSaved*/) override;
  void setFileBacked() override;
  void clearFileBacked(bool loadDiskBackedData) override;
  //-----------------------------------------------------------------------------------------------
  void saveAt(API::IBoxControllerIO *const /* */,
              uint64_t /*position*/) const override;
Hahn, Steven's avatar
Hahn, Steven committed
  void loadAndAddFrom(API::IBoxControllerIO *const /* */, uint64_t /*position*/,
                      size_t /* Size */) override;
  void reserveMemoryForLoad(uint64_t /* Size */) override;
  /**drop events data from memory but keep averages (and file-backed info) */
  void clearDataFromMemory() override;
  void clear() override;
  uint64_t getNPoints() const override;
  size_t getDataInMemorySize() const override { return data.size(); }
  uint64_t getTotalDataSize() const override { return getNPoints(); }
  size_t getNumDims() const override;
  size_t getNumMDBoxes() const override;

  /// Get the # of children MDBoxBase'es (non-recursive)
  size_t getNumChildren() const override { return 0; }
  // to avoid casting (which need also the number of dimensions) method say if
  // Node is a box. if not, it is gridbox
  bool isBox() const override { return true; }

  /// Return the indexth child MDBoxBase.
  API::IMDNode *getChild(size_t /*index*/) override {
    throw std::runtime_error("MDBox does not have children.");
  }

  /// Sets the children from a vector of children
  void setChildren(const std::vector<API::IMDNode *> & /*boxes*/,
Hahn, Steven's avatar
Hahn, Steven committed
                   const size_t /*indexStart*/,
                   const size_t /*indexEnd*/) override {
    throw std::runtime_error("MDBox cannot have children.");
  }

  /// @return true if events were added to the box (using addEvent()) while the
  /// rest of the event list is cached to disk
  bool isDataAdded() const;

  /**Get vector of events to change. Beware, that calling this funtion for
    file-based workspace sets both dataChanged and dataBusy flags
    first forces disk buffer to write the object contents to HDD when disk
    buffer is full and the second one prevents DB
    from clearing object from memory untill the events are released. One HAS TO
    call releaseEvents when finished using data on file-based WS    */
  std::vector<MDE> &getEvents();
  /**Get vector of constant events to use. Beware, that calling this funtion for
     file-based workspace sets dataBusy flag
     This flag prevents DB from clearing object from memory untill the events
     are released.
     One HAS TO call releaseEvents when finished using data on file-based WS to
     allow DB clearing them  */
  const std::vector<MDE> &getConstEvents() const;
  // the same as getConstEvents above,
  const std::vector<MDE> &getEvents() const;
  void releaseEvents();

  std::vector<MDE> *getEventsCopy() override;
  void getEventsData(std::vector<coord_t> &coordTable,
                     size_t &nColumns) const override;
  void setEventsData(const std::vector<coord_t> &coordTable) override;
  size_t addEvent(const MDE &Evnt) override;
  size_t addEventUnsafe(const MDE &Evnt) override;

  // add range of events
  size_t addEvents(const std::vector<MDE> &events) override;
  // unhide MDBoxBase methods
  size_t addEventsUnsafe(const std::vector<MDE> &events) override;

  /*--------------->  EVENTS from event data
   * <-------------------------------------------------------------*/
  void buildAndAddEvent(const signal_t Signal, const signal_t errorSq,
Hahn, Steven's avatar
Hahn, Steven committed
                        const std::vector<coord_t> &point, uint16_t runIndex,
                        uint32_t detectorId) override;
  void buildAndAddEventUnsafe(const signal_t Signal, const signal_t errorSq,
                              const std::vector<coord_t> &point,
                              uint16_t runIndex, uint32_t detectorId) override;
  size_t buildAndAddEvents(const std::vector<signal_t> &sigErrSq,
Hahn, Steven's avatar
Hahn, Steven committed
                           const std::vector<coord_t> &Coord,
                           const std::vector<uint16_t> &runIndex,
                           const std::vector<uint32_t> &detectorId) override;
  //---------------------------------------------------------------------------------------------------------------------------------
  void centerpointBin(MDBin<MDE, nd> &bin, bool *fullyContained) const override;
  void
  generalBin(MDBin<MDE, nd> &bin,
             Mantid::Geometry::MDImplicitFunction &function) const override;
  void splitAllIfNeeded(Mantid::Kernel::ThreadScheduler * /*ts*/ = nullptr)
Hahn, Steven's avatar
Hahn, Steven committed
      override { /* Do nothing with a box default. */
  //---------------------------------------------------------------------------------------------------------------------------------
  /** Recalculate signal and various averages dependent on signal and the signal
   * coordinates */
  void refreshCache(Kernel::ThreadScheduler * /*ts*/ = nullptr) override;
  void calculateCentroid(coord_t *centroid) const override;
  void calculateCentroid(coord_t *centroid, const int runindex) const override;
  coord_t *getCentroid() const override;
  void calculateDimensionStats(MDDimensionStats *stats) const;
  void integrateSphere(Mantid::API::CoordTransform &radiusTransform,
                       const coord_t radiusSquared, signal_t &signal,
                       signal_t &errorSquared,
                       const coord_t innerRadiusSquared = 0.0) const override;
  void centroidSphere(Mantid::API::CoordTransform &radiusTransform,
                      const coord_t radiusSquared, coord_t *centroid,
                      signal_t &signal) const override;
  void integrateCylinder(Mantid::API::CoordTransform &radiusTransform,
                         const coord_t radius, const coord_t length,
                         signal_t &signal, signal_t &errorSquared,
                         std::vector<signal_t> &signal_fit) const override;
  //------------------------------------------------------------------------------------------------------------------------------------
  void getBoxes(std::vector<MDBoxBase<MDE, nd> *> &boxes, size_t /*maxDepth*/,
                bool /*leafOnly*/);
  void getBoxes(std::vector<API::IMDNode *> &boxes, size_t /*maxDepth*/,
                bool /*leafOnly*/) override;

  void getBoxes(std::vector<MDBoxBase<MDE, nd> *> &boxes, size_t maxDepth,
                bool leafOnly, Mantid::Geometry::MDImplicitFunction *function);
  void getBoxes(std::vector<API::IMDNode *> &boxes, size_t maxDepth,
Hahn, Steven's avatar
Hahn, Steven committed
                bool leafOnly,
                Mantid::Geometry::MDImplicitFunction *function) override;
  //------------------------------------------------------------------------------------------------------------------------------------
  void transformDimensions(std::vector<double> &scaling,
                           std::vector<double> &offset) override;
  //------------------------------------------------------------------------------------------------------------------------------------
  /* Getter to determine if masking is applied.
  @return true if masking is applied.   */
  bool getIsMasked() const override { return m_bIsMasked; }
  /// Setter for masking the box
  void mask() override;
  /// Setter for unmasking the box
  void unmask() override;

protected:
  // the pointer to the class, responsible for saving/restoring this class to
  // the hdd
  mutable Kernel::ISaveable *m_Saveable;
  /** Vector of MDEvent's, in no particular order. */
  mutable std::vector<MDE> data;

  /// Flag indicating that masking has been applied.
  bool m_bIsMasked;

private:
  /// private default copy constructor as the only correct constructor is the
  /// one with the boxController;
  MDBox(const MDBox &);
  /// common part of mdBox constructor
  struct MyComparator {
    const std::vector<double> &value_vector;

    MyComparator(const std::vector<double> &val_vec) : value_vector(val_vec) {}

Lynch, Vickie's avatar
Lynch, Vickie committed
    bool operator()(size_t i1, size_t i2) {
      return value_vector[i1] < value_vector[i2];
    }
  };

public:
  /// Typedef for a shared pointer to a MDBox
  typedef boost::shared_ptr<MDBox<MDE, nd>> sptr;

  /// Typedef for a vector of the conatined events
  typedef std::vector<MDE> vec_t;
};
#ifndef __INTEL_COMPILER
#pragma pack(pop) // Return to default packing size
//------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Internal TMP class to simplify adding events to the box for events and lean
 * events using single interface*/
template <typename MDE, size_t nd> struct IF {
public:
  // create generic events from array of events data and add them to the grid
  // box
  static inline void
  EXEC(std::vector<MDE> &data, const std::vector<signal_t> &sigErrSq,
       const std::vector<coord_t> &Coord, const std::vector<uint16_t> &runIndex,
       const std::vector<uint32_t> &detectorId, size_t nEvents) {
    for (size_t i = 0; i < nEvents; i++) {
      data.emplace_back(sigErrSq[2 * i], sigErrSq[2 * i + 1], runIndex[i],
                        detectorId[i], &Coord[i * nd]);
    }
  }
  // create single generic event from event's data
  static inline MDE BUILD_EVENT(const signal_t Signal, const signal_t Error,
                                const coord_t *Coord, const uint16_t runIndex,
                                const uint32_t detectorId) {
    return MDE(Signal, Error, runIndex, detectorId, Coord);
  }
};
/* Specialize for the case of LeanEvent */
template <size_t nd> struct IF<MDLeanEvent<nd>, nd> {
public:
  // create lean events from array of events data and add them to the box
  static inline void EXEC(std::vector<MDLeanEvent<nd>> &data,
                          const std::vector<signal_t> &sigErrSq,
                          const std::vector<coord_t> &Coord,
                          const std::vector<uint16_t> & /*runIndex*/,
                          const std::vector<uint32_t> & /*detectorId*/,
                          size_t nEvents) {
    for (size_t i = 0; i < nEvents; i++) {
      data.emplace_back(sigErrSq[2 * i], sigErrSq[2 * i + 1], &Coord[i * nd]);
    }
  }
  // create single lean event from event's data
  static inline MDLeanEvent<nd>
  BUILD_EVENT(const signal_t Signal, const signal_t Error, const coord_t *Coord,
              const uint16_t /*runIndex*/, const uint32_t /*detectorId*/) {
    return MDLeanEvent<nd>(Signal, Error, Coord);
  }
};

} // namespace Mantid