/** * Create FITS file information for each file selected. Loads headers * and data from the files and creates and fills the output * workspace(s). * * @param paths File names as given in the algorithm input property * * @param outWSName name of the output (group) workspace to create * * @param loadAsRectImg Load files with 1 spectrum per row and 1 bin * per column, so a color fill plot displays the image * * @param binSize size to rebin (1 == no re-bin == default) * * @param noiseThresh threshold for noise filtering * * @throw std::runtime_error when load fails (for example a memory * allocation issue, wrong rebin requested, etc.) */ void LoadFITS::doLoadFiles(const std::vector<std::string> &paths, const std::string &outWSName, bool loadAsRectImg, int binSize, double noiseThresh) { std::vector<FITSInfo> headers; headers.resize(paths.size()); loadHeader(paths[0], headers[0]); // No extension is set -> it's the standard format which we can parse. if (headers[0].numberOfAxis > 0) m_pixelCount += headers[0].axisPixelLengths[0]; // Presumably 2 axis, but futureproofing. for (int i = 1; i < headers[0].numberOfAxis; ++i) { m_pixelCount *= headers[0].axisPixelLengths[i]; } // Check consistency of binSize asap for (int i = 0; i < headers[0].numberOfAxis; ++i) { if (0 != (headers[0].axisPixelLengths[i] % binSize)) { throw std::runtime_error( "Cannot rebin this image in blocks of " + std::to_string(binSize) + " x " + std::to_string(binSize) + " pixels as requested because the size of dimension " + std::to_string(i + 1) + " (" + std::to_string(headers[0].axisPixelLengths[i]) + ") is not a multiple of the bin size."); } } MantidImage imageY(headers[0].axisPixelLengths[1], std::vector<double>(headers[0].axisPixelLengths[0])); MantidImage imageE(headers[0].axisPixelLengths[1], std::vector<double>(headers[0].axisPixelLengths[0])); size_t bytes = (headers[0].bitsPerPixel / 8) * m_pixelCount; std::vector<char> buffer; try { buffer.resize(bytes); } catch (std::exception &) { throw std::runtime_error( "Could not allocate enough memory to run when trying to allocate " + std::to_string(bytes) + " bytes."); } // Create a group for these new workspaces, if the group already exists, add // to it. size_t fileNumberInGroup = 0; WorkspaceGroup_sptr wsGroup; if (!AnalysisDataService::Instance().doesExist(outWSName)) { wsGroup = boost::make_shared<WorkspaceGroup>(); wsGroup->setTitle(outWSName); } else { // Get the name of the latest file in group to start numbering from if (AnalysisDataService::Instance().doesExist(outWSName)) wsGroup = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outWSName); std::string latestName = wsGroup->getNames().back(); // Set next file number fileNumberInGroup = fetchNumber(latestName) + 1; } size_t totalWS = headers.size(); // Create a progress reporting object API::Progress progress(this, 0, 1, totalWS + 1); progress.report(0, "Loading file(s) into workspace(s)"); // Create first workspace (with instrument definition). This is also used as // a template for creating others Workspace2D_sptr imgWS; imgWS = makeWorkspace(headers[0], fileNumberInGroup, buffer, imageY, imageE, imgWS, loadAsRectImg, binSize, noiseThresh); progress.report(1, "First file loaded."); wsGroup->addWorkspace(imgWS); if (isInstrOtherThanIMAT(headers[0])) { // For now we assume IMAT except when specific headers are found by // isInstrOtherThanIMAT() // // TODO: do this conditional on INSTR='IMAT' when we have proper IMAT .fits // files try { IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument"); std::string directoryName = Kernel::ConfigService::Instance().getInstrumentDirectory(); directoryName = directoryName + "/IMAT_Definition.xml"; loadInst->setPropertyValue("Filename", directoryName); loadInst->setProperty<MatrixWorkspace_sptr>( "Workspace", boost::dynamic_pointer_cast<MatrixWorkspace>(imgWS)); loadInst->execute(); } catch (std::exception &ex) { g_log.information("Cannot load the instrument definition. " + std::string(ex.what())); } } // don't feel tempted to parallelize this loop as it is - it uses the same // imageY and imageE buffers for all the workspaces for (int64_t i = 1; i < static_cast<int64_t>(totalWS); ++i) { loadHeader(paths[i], headers[i]); // Check each header is valid/supported: standard (no extension to // FITS), has two axis, and it is consistent with the first header headerSanityCheck(headers[i], headers[0]); imgWS = makeWorkspace(headers[i], fileNumberInGroup, buffer, imageY, imageE, imgWS, loadAsRectImg, binSize, noiseThresh); progress.report("Loaded file " + std::to_string(i + 1) + " of " + std::to_string(totalWS)); wsGroup->addWorkspace(imgWS); } setProperty("OutputWorkspace", wsGroup); }