void MinusMD::doMinus(typename MDEventWorkspace<MDE, nd>::sptr ws) { typename MDEventWorkspace<MDE, nd>::sptr ws1 = ws; typename MDEventWorkspace<MDE, nd>::sptr ws2 = boost::dynamic_pointer_cast<MDEventWorkspace<MDE, nd> >(m_operand_event); if (!ws1 || !ws2) throw std::runtime_error("Incompatible workspace types passed to MinusMD."); MDBoxBase<MDE,nd> * box1 = ws1->getBox(); MDBoxBase<MDE,nd> * box2 = ws2->getBox(); Progress prog(this, 0.0, 0.4, box2->getBoxController()->getTotalNumMDBoxes()); // How many events you started with size_t initial_numEvents = ws1->getNPoints(); // Make a leaf-only iterator through all boxes with events in the RHS workspace MDBoxIterator<MDE,nd> it2(box2, 1000, true); do { MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(it2.getBox()); if (box) { // Copy the events from WS2 and add them into WS1 const std::vector<MDE> & events = box->getConstEvents(); // Perform a copy while flipping the signal std::vector<MDE> eventsCopy; eventsCopy.reserve(events.size()); for (auto it = events.begin(); it != events.end(); it++) { MDE eventCopy(*it); eventCopy.setSignal( -eventCopy.getSignal()); eventsCopy.push_back(eventCopy); } // Add events, with bounds checking box1->addEvents(eventsCopy); box->releaseEvents(); } prog.report("Adding Events"); } while (it2.next()); this->progress(0.41, "Splitting Boxes"); Progress * prog2 = new Progress(this, 0.4, 0.9, 100); ThreadScheduler * ts = new ThreadSchedulerFIFO(); ThreadPool tp(ts, 0, prog2); ws1->splitAllIfNeeded(ts); prog2->resetNumSteps( ts->size(), 0.4, 0.6); tp.joinAll(); this->progress(0.95, "Refreshing cache"); ws1->refreshCache(); // Set a marker that the file-back-end needs updating if the # of events changed. if (ws1->getNPoints() != initial_numEvents) ws1->setFileNeedsUpdating(true); }
void MultiplyMD::execEventScalar(typename MDEventWorkspace<MDE, nd>::sptr ws) { // Get the scalar multiplying float scalar = float(m_rhs_scalar->dataY(0)[0]); float scalarError = float(m_rhs_scalar->dataE(0)[0]); float scalarRelativeErrorSquared = (scalarError * scalarError) / (scalar * scalar); // Get all the MDBoxes contained MDBoxBase<MDE,nd> * parentBox = ws->getBox(); std::vector<API::IMDNode *> boxes; parentBox->getBoxes(boxes, 1000, true); bool fileBackedTarget(false); Kernel::DiskBuffer *dbuff(NULL); if(ws->isFileBacked()) { fileBackedTarget = true; dbuff = ws->getBoxController()->getFileIO(); } for (size_t i=0; i<boxes.size(); i++) { MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(boxes[i]); if (box) { typename std::vector<MDE> & events = box->getEvents(); size_t ic(events.size()); typename std::vector<MDE>::iterator it = events.begin(); typename std::vector<MDE>::iterator it_end = events.end(); for (; it != it_end; it++) { // Multiply weight by a scalar, propagating error float oldSignal = it->getSignal(); float signal = oldSignal * scalar; float errorSquared = signal * signal * (it->getErrorSquared() / (oldSignal * oldSignal) + scalarRelativeErrorSquared); it->setSignal(signal); it->setErrorSquared(errorSquared); } box->releaseEvents(); if(fileBackedTarget && ic>0) { Kernel::ISaveable *const pSaver(box->getISaveable()); dbuff->toWrite(pSaver); } } } // Recalculate the totals ws->refreshCache(); // Mark file-backed workspace as dirty ws->setFileNeedsUpdating(true); }
void SaveMD::doSaveEvents(typename MDEventWorkspace<MDE, nd>::sptr ws) { std::string filename = getPropertyValue("Filename"); bool update = getProperty("UpdateFileBackEnd"); bool MakeFileBacked = getProperty("MakeFileBacked"); bool wsIsFileBacked = ws->isFileBacked(); if (update && MakeFileBacked) throw std::invalid_argument( "Please choose either UpdateFileBackEnd or MakeFileBacked, not both."); if (MakeFileBacked && wsIsFileBacked) throw std::invalid_argument( "You picked MakeFileBacked but the workspace is already file-backed!"); BoxController_sptr bc = ws->getBoxController(); if (!wsIsFileBacked) { // Erase the file if it exists Poco::File oldFile(filename); if (oldFile.exists()) oldFile.remove(); } auto prog = new Progress(this, 0.0, 0.05, 1); if (update) // workspace has its own file and ignores any changes to the // algorithm parameters { if (!ws->isFileBacked()) throw std::runtime_error(" attempt to update non-file backed workspace"); filename = bc->getFileIO()->getFileName(); } //----------------------------------------------------------------------------------------------------- // create or open WS group and put there additional information about WS and // its dimensions int nDims = static_cast<int>(nd); bool data_exist; auto file = file_holder_type(MDBoxFlatTree::createOrOpenMDWSgroup( filename, nDims, MDE::getTypeName(), false, data_exist)); // Save each NEW ExperimentInfo to a spot in the file MDBoxFlatTree::saveExperimentInfos(file.get(), ws); if (!update || !data_exist) { MDBoxFlatTree::saveWSGenericInfo(file.get(), ws); } file->closeGroup(); file->close(); MDBoxFlatTree BoxFlatStruct; //----------------------------------------------------------------------------------------------------- if (update) // the workspace is already file backed; { // remove all boxes from the DiskBuffer. DB will calculate boxes positions // on HDD. bc->getFileIO()->flushCache(); // flatten the box structure; this will remember boxes file positions in the // box structure BoxFlatStruct.initFlatStructure(ws, filename); } else // not file backed; { // the boxes file positions are unknown and we need to calculate it. BoxFlatStruct.initFlatStructure(ws, filename); // create saver class auto Saver = boost::shared_ptr<API::IBoxControllerIO>( new DataObjects::BoxControllerNeXusIO(bc.get())); Saver->setDataType(sizeof(coord_t), MDE::getTypeName()); if (MakeFileBacked) { // store saver with box controller bc->setFileBacked(Saver, filename); // get access to boxes array std::vector<API::IMDNode *> &boxes = BoxFlatStruct.getBoxes(); // calculate the position of the boxes on file, indicating to make them // saveable and that the boxes were not saved. BoxFlatStruct.setBoxesFilePositions(true); prog->resetNumSteps(boxes.size(), 0.06, 0.90); for (auto &boxe : boxes) { auto saveableTag = boxe->getISaveable(); if (saveableTag) // only boxes can be saveable { // do not spend time on empty boxes if (boxe->getDataInMemorySize() == 0) continue; // save boxes directly using the boxes file postion, precalculated in // boxFlatStructure. saveableTag->save(); // remove boxes data from memory. This will actually correctly set the // tag indicatin that data were not loaded. saveableTag->clearDataFromMemory(); // put boxes into write buffer wich will save them when necessary // Saver->toWrite(saveTag); prog->report("Saving Box"); } } // remove everything from diskBuffer; (not sure if it really necessary // but just in case , should not make any harm) Saver->flushCache(); // drop NeXus on HDD (not sure if it really necessary but just in case ) Saver->flushData(); } else // just save data, and finish with it { Saver->openFile(filename, "w"); BoxFlatStruct.setBoxesFilePositions(false); std::vector<API::IMDNode *> &boxes = BoxFlatStruct.getBoxes(); std::vector<uint64_t> &eventIndex = BoxFlatStruct.getEventIndex(); prog->resetNumSteps(boxes.size(), 0.06, 0.90); for (size_t i = 0; i < boxes.size(); i++) { if (eventIndex[2 * i + 1] == 0) continue; boxes[i]->saveAt(Saver.get(), eventIndex[2 * i]); prog->report("Saving Box"); } Saver->closeFile(); } } // -------------- Save Box Structure ------------------------------------- // OK, we've filled these big arrays of data representing flat box structrre. // Save them. progress(0.91, "Writing Box Data"); prog->resetNumSteps(8, 0.92, 1.00); // Save box structure; BoxFlatStruct.saveBoxStructure(filename); delete prog; ws->setFileNeedsUpdating(false); }
void PlusMD::doPlus(typename MDEventWorkspace<MDE, nd>::sptr ws) { typename MDEventWorkspace<MDE, nd>::sptr ws1 = ws; typename MDEventWorkspace<MDE, nd>::sptr ws2 = boost::dynamic_pointer_cast<MDEventWorkspace<MDE, nd> >(m_operand_event); if (!ws1 || !ws2) throw std::runtime_error("Incompatible workspace types passed to PlusMD."); MDBoxBase<MDE,nd> * box1 = ws1->getBox(); MDBoxBase<MDE,nd> * box2 = ws2->getBox(); Progress prog(this, 0.0, 0.4, box2->getBoxController()->getTotalNumMDBoxes()); // How many events you started with size_t initial_numEvents = ws1->getNPoints(); // Make a leaf-only iterator through all boxes with events in the RHS workspace MDBoxIterator<MDE,nd> it2(box2, 1000, true); do { MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(it2.getBox()); if (box) { // Copy the events from WS2 and add them into WS1 const std::vector<MDE> & events = box->getConstEvents(); // Add events, with bounds checking box1->addEvents(events); box->releaseEvents(); } prog.report("Adding Events"); } while (it2.next()); this->progress(0.41, "Splitting Boxes"); Progress * prog2 = new Progress(this, 0.4, 0.9, 100); ThreadScheduler * ts = new ThreadSchedulerFIFO(); ThreadPool tp(ts, 0, prog2); ws1->splitAllIfNeeded(ts); prog2->resetNumSteps( ts->size(), 0.4, 0.6); tp.joinAll(); // // Now we need to save all the data that was not saved before. // if (ws1->isFileBacked()) // { // // Flush anything else in the to-write buffer // BoxController_sptr bc = ws1->getBoxController(); // // prog.resetNumSteps(bc->getTotalNumMDBoxes(), 0.6, 1.0); // MDBoxIterator<MDE,nd> it1(box1, 1000, true); // while (true) // { // MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(it1.getBox()); // if (box) // { // // Something was maybe added to this box // if (box->getEventVectorSize() > 0) // { // // By getting the events, this will merge the newly added and the cached events. // box->getEvents(); // // The MRU to-write cache will optimize writes by reducing seek times // box->releaseEvents(); // } // } // prog.report("Saving"); // if (!it1.next()) break; // } // //bc->getDiskBuffer().flushCache(); // // Flush the data writes to disk. // box1->flushData(); // } this->progress(0.95, "Refreshing cache"); ws1->refreshCache(); // Set a marker that the file-back-end needs updating if the # of events changed. if (ws1->getNPoints() != initial_numEvents) ws1->setFileNeedsUpdating(true); }