Example #1
0
size_t MaskPeaksWorkspace::getWkspIndex(const detid2index_map &pixel_to_wi,
                                        Geometry::IComponent_const_sptr comp,
                                        const int x, const int y) {
  Geometry::RectangularDetector_const_sptr det =
      boost::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp);
  if (det) {
    if (x >= det->xpixels() || x < 0 || y >= det->ypixels() || y < 0)
      return EMPTY_INT();
    if ((x >= det->xpixels()) ||
        (x < 0) // this check is unnecessary as callers are doing it too
        || (y >= det->ypixels()) ||
        (y < 0)) // but just to make debugging easier
    {
      std::stringstream msg;
      msg << "Failed to find workspace index for x=" << x << " y=" << y
          << "(max x=" << det->xpixels() << ", max y=" << det->ypixels() << ")";
      throw std::runtime_error(msg.str());
    }

    int pixelID = det->getAtXY(x, y)->getID();

    // Find the corresponding workspace index, if any
    auto wiEntry = pixel_to_wi.find(pixelID);
    if (wiEntry == pixel_to_wi.end()) {
      std::stringstream msg;
      msg << "Failed to find workspace index for x=" << x << " y=" << y;
      throw std::runtime_error(msg.str());
    }
    return wiEntry->second;
  } else {
    std::vector<Geometry::IComponent_const_sptr> children;
    boost::shared_ptr<const Geometry::ICompAssembly> asmb =
        boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(comp);
    asmb->getChildren(children, false);
    boost::shared_ptr<const Geometry::ICompAssembly> asmb2 =
        boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(children[0]);
    std::vector<Geometry::IComponent_const_sptr> grandchildren;
    asmb2->getChildren(grandchildren, false);
    int NROWS = static_cast<int>(grandchildren.size());
    int NCOLS = static_cast<int>(children.size());
    // Wish pixels and tubes start at 1 not 0
    if (x - 1 >= NCOLS || x - 1 < 0 || y - 1 >= NROWS || y - 1 < 0)
      return EMPTY_INT();
    std::string bankName = comp->getName();
    detid2index_map::const_iterator it =
        pixel_to_wi.find(findPixelID(bankName, x, y));
    if (it == pixel_to_wi.end())
      return EMPTY_INT();
    return (it->second);
  }
}
/** Utility function to write out the
 * data or errors to a field in the group.
 *
 * @param det :: rectangular detector being written
 * @param x_pixel_slab :: size of a slab to write, in number of X pixels.
 *ignored if doBoth
 * @param field_name :: "data" field name
 * @param errors_field_name :: "errors" field name.
 * @param doErrors :: set true if you are writing the errors field this time.
 *field_name should be the "errors" field name
 * @param doBoth :: do both data and errors at once, no slabbing.
 * @param is_definition ::
 * @param bank :: name of the bank being written.
 * @return error code
 */
int SaveToSNSHistogramNexus::WriteOutDataOrErrors(
    Geometry::RectangularDetector_const_sptr det, int x_pixel_slab,
    const char *field_name, const char *errors_field_name, bool doErrors,
    bool doBoth, int is_definition, std::string bank) {
  int dataRank, dataDimensions[NX_MAXRANK];
  int slabDimensions[NX_MAXRANK], slabStartIndices[NX_MAXRANK];

  dataRank = 3;

  // Dimension 0 = the X pixels
  dataDimensions[0] = det->xpixels();
  // Dimension 1 = the Y pixels
  dataDimensions[1] = det->ypixels();
  // Dimension 2 = time of flight bins
  dataDimensions[2] = static_cast<int>(inputWorkspace->blocksize());

  // ---- Determine slab size -----
  // Number of pixels to collect in X before slabbing
  slabDimensions[0] = x_pixel_slab;
  slabDimensions[1] = dataDimensions[1];
  slabDimensions[2] = dataDimensions[2];

  if (doBoth)
    slabDimensions[0] = dataDimensions[0];

  std::cout << "RectangularDetector " << det->getName()
            << " being copied. Dimensions : " << dataDimensions[0] << ", "
            << dataDimensions[1] << ", " << dataDimensions[2] << ".\n";

  // ----- Open the data field -----------------------
  if (m_compress) {
    if (NXcompmakedata(outId, field_name, NX_FLOAT32, dataRank, dataDimensions,
                       NX_COMP_LZW, slabDimensions) != NX_OK)
      return NX_ERROR;
  } else {
    if (NXmakedata(outId, field_name, NX_FLOAT32, dataRank, dataDimensions) !=
        NX_OK)
      return NX_ERROR;
  }
  if (NXopendata(outId, field_name) != NX_OK)
    return NX_ERROR;
  if (WriteAttributes(is_definition) != NX_OK)
    return NX_ERROR;
  if (!doErrors) {
    // Add an attribute called "errors" with value = the name of the data_errors
    // field.
    NXname attrName = "errors";
    std::string attrBuffer = errors_field_name;
    if (NXputattr(outId, attrName, attrBuffer.c_str(),
                  static_cast<int>(attrBuffer.size()), NX_CHAR) != NX_OK)
      return NX_ERROR;
  }

  // ---- Errors field -----
  if (doBoth) {
    if (NXclosedata(outId) != NX_OK)
      return NX_ERROR;

    if (m_compress) {
      if (NXcompmakedata(outId, errors_field_name, NX_FLOAT32, dataRank,
                         dataDimensions, NX_COMP_LZW, slabDimensions) != NX_OK)
        return NX_ERROR;
    } else {
      if (NXmakedata(outId, errors_field_name, NX_FLOAT32, dataRank,
                     dataDimensions) != NX_OK)
        return NX_ERROR;
    }
    if (NXopendata(outId, errors_field_name) != NX_OK)
      return NX_ERROR;

    //      NXlink * link = new NXlink;
    //      link->linkType = 1; /* SDS data link */
    //      NXgetdataID(outId, link);
    //      std::string targetPath = "/entry/" + bank + "/" + errors_field_name;
    //      strcpy(link->targetPath, targetPath.c_str());
    //      if (NXmakelink(outId,link) != NX_OK)
    //        g_log.debug() << "Error while making link to " << targetPath <<
    //        '\n';

    if (WriteAttributes(is_definition) != NX_OK)
      return NX_ERROR;
    if (NXclosedata(outId) != NX_OK)
      return NX_ERROR;
  }

  double fillTime = 0;
  double saveTime = 0;

  // Make a buffer of floats will all the counts in that bank.
  auto data =
      new float[slabDimensions[0] * slabDimensions[1] * slabDimensions[2]];

  // Only allocate an array for errors if it is needed
  float *errors = nullptr;
  if (doBoth)
    errors =
        new float[slabDimensions[0] * slabDimensions[1] * slabDimensions[2]];

  for (int x = 0; x < det->xpixels(); x++) {
    // Which slab are we in?
    int slabnum = x / x_pixel_slab;

    // X index into the slabbed output array
    int slabx = x % x_pixel_slab;

    Timer tim1;
    int ypixels = static_cast<int>(det->ypixels());

    PARALLEL_FOR1(inputWorkspace)
    for (int y = 0; y < ypixels; y++) {
      PARALLEL_START_INTERUPT_REGION
      // Get the workspace index for the detector ID at this spot
      size_t wi = 0;
      try {
        wi = map.find(det->getAtXY(x, y)->getID())->second;
      } catch (...) {
        std::cout << "Error finding " << bank << " x " << x << " y " << y
                  << "\n";
      }

      // Offset into array.
      size_t index = size_t(slabx) * size_t(dataDimensions[1]) *
                         size_t(dataDimensions[2]) +
                     size_t(y) * size_t(dataDimensions[2]);

      const MantidVec &Y = inputWorkspace->readY(wi);
      const MantidVec &E = inputWorkspace->readE(wi);

      for (size_t i = 0; i < Y.size(); ++i) {
        if (doErrors) {
          data[i + index] = static_cast<float>(E[i]);
        } else {
          data[i + index] = static_cast<float>(Y[i]);
          if (doBoth) {
            errors[i + index] = static_cast<float>(E[i]);
          }
        }
      }

      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

    fillTime += tim1.elapsed();

    // Is this the last pixel in the slab?
    if (!doBoth && (x % x_pixel_slab == x_pixel_slab - 1)) {
      Timer tim2;
      // std::cout << "starting slab " << x << "\n";
      // This is where the slab is in the greater data array.
      slabStartIndices[0] = slabnum * x_pixel_slab;
      slabStartIndices[1] = 0;
      slabStartIndices[2] = 0;
      if (NXputslab(outId, data, slabStartIndices, slabDimensions) != NX_OK)
        return NX_ERROR;
      saveTime += tim2.elapsed();

      std::ostringstream mess;
      mess << det->getName() << ", " << field_name << " slab " << slabnum
           << " of " << det->xpixels() / x_pixel_slab;
      this->prog->reportIncrement(x_pixel_slab * det->ypixels(), mess.str());
    }

  } // X loop

  if (doBoth) {
    bool returnerror = false;

    Timer tim2;
    if (NXopendata(outId, field_name) != NX_OK)
      returnerror = true;
    else if (NXputdata(outId, data) != NX_OK)
      returnerror = true;
    else if (NXclosedata(outId) != NX_OK)
      returnerror = true;
    else {
      this->prog->reportIncrement(det->xpixels() * det->ypixels() * 1,
                                  det->getName() + " data");

      if (NXopendata(outId, errors_field_name) != NX_OK)
        returnerror = true;
      else if (NXputdata(outId, errors) != NX_OK)
        returnerror = true;
      else if (NXclosedata(outId) != NX_OK)
        returnerror = true;
      else {
        this->prog->reportIncrement(det->xpixels() * det->ypixels() * 1,
                                    det->getName() + " errors");
        saveTime += tim2.elapsed();
      }
    }

    if (returnerror) {
      delete[] data;
      delete[] errors;

      return NX_ERROR;
    }

  } else {
    if (NXclosedata(outId) != NX_OK) {
      delete[] data;
      return NX_ERROR;
    }
  }

  std::cout << "Filling out " << det->getName() << " took " << fillTime
            << " sec.\n";
  std::cout << "Saving      " << det->getName() << " took " << saveTime
            << " sec.\n";

  delete[] data;
  if (doBoth)
    delete[] errors;

  return NX_OK;
}