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; }