Scalar AdaptiveSparseGrid<Scalar,UserVector>::refine_grid( typename std::multimap<Scalar,std::vector<int> > & indexSet, UserVector & integralValue, AdaptiveSparseGridInterface<Scalar,UserVector> & problem_data) { int dimension = problem_data.getDimension(); std::vector<EIntrepidBurkardt> rule1D; problem_data.getRule(rule1D); std::vector<EIntrepidGrowth> growth1D; problem_data.getGrowth(growth1D); // Copy Multimap into a Set for ease of use typename std::multimap<Scalar,std::vector<int> >::iterator it; std::set<std::vector<int> > oldSet; std::set<std::vector<int> >::iterator it1(oldSet.begin()); for (it=indexSet.begin(); it!=indexSet.end(); it++) { oldSet.insert(it1,it->second); it1++; } indexSet.clear(); // Find Possible Active Points int flag = 1; std::vector<int> index(dimension,0); typename std::multimap<Scalar,std::vector<int> > activeSet; for (it1=oldSet.begin(); it1!=oldSet.end(); it1++) { index = *it1; for (int i=0; i<dimension; i++) { index[i]++; flag = (int)(!oldSet.count(index)); index[i]--; if (flag) { activeSet.insert(std::pair<Scalar,std::vector<int> >(1.0,index)); oldSet.erase(it1); break; } } } // Compute local and global error indicators for active set typename std::multimap<Scalar,std::vector<int> >::iterator it2; Scalar eta = 0.0; Scalar G = 0.0; Teuchos::RCP<UserVector> s = integralValue.Create(); for (it2=activeSet.begin(); it2!=activeSet.end(); it2++) { // Build Differential Quarature Rule index = it2->second; CubatureTensorSorted<Scalar> diffRule(0,dimension); build_diffRule(diffRule,index,problem_data); // Apply Rule to function problem_data.eval_cubature(*s,diffRule); // Update local error indicator and index set G = problem_data.error_indicator(*s); activeSet.erase(it2); activeSet.insert(it2,std::pair<Scalar,std::vector<int> >(G,index)); eta += G; } // Refine Sparse Grid eta = refine_grid(activeSet,oldSet,integralValue,eta, dimension,rule1D,growth1D); // Insert New Active and Old Index sets into indexSet indexSet.insert(activeSet.begin(),activeSet.end()); for (it1=oldSet.begin(); it1!=oldSet.end(); it1++) { index = *it1; indexSet.insert(std::pair<Scalar,std::vector<int> >(-1.0,index)); } return eta; }
Scalar AdaptiveSparseGrid<Scalar,UserVector>::refine_grid( typename std::multimap<Scalar,std::vector<int> > & activeIndex, std::set<std::vector<int> > & oldIndex, UserVector & integralValue, CubatureTensorSorted<Scalar> & cubRule, Scalar globalErrorIndicator, AdaptiveSparseGridInterface<Scalar,UserVector> & problem_data) { TEUCHOS_TEST_FOR_EXCEPTION((activeIndex.empty()),std::out_of_range, ">>> ERROR (AdaptiveSparseGrid): Active Index set is empty."); int dimension = problem_data.getDimension(); std::vector<EIntrepidBurkardt> rule1D; problem_data.getRule(rule1D); std::vector<EIntrepidGrowth> growth1D; problem_data.getGrowth(growth1D); // Initialize Flags bool maxLevelFlag = true; bool isAdmissibleFlag = true; // Initialize Cubature Rule Teuchos::RCP<UserVector> s = integralValue.Create(); // Initialize iterator at end of inOldIndex std::set<std::vector<int> >::iterator it1(oldIndex.end()); // Initialize iterator at end of inActiveIndex typename std::multimap<Scalar,std::vector<int> >::iterator it; // Obtain Global Error Indicator as sum of key values of inActiveIndex Scalar eta = globalErrorIndicator; // Select Index to refine it = activeIndex.end(); it--; // Decrement to position of final value Scalar G = it->first; // Largest Error Indicator is at End eta -= G; // Update global error indicator std::vector<int> index = it->second; // Get Corresponding index activeIndex.erase(it); // Erase Index from active index set // Insert Index into old index set oldIndex.insert(it1,index); it1 = oldIndex.end(); // Refinement process for (int k=0; k<dimension; k++) { index[k]++; // index + ek // Check Max Level maxLevelFlag = problem_data.max_level(index); if (maxLevelFlag) { // Check Admissibility isAdmissibleFlag = isAdmissible(index,k,oldIndex,problem_data); if (isAdmissibleFlag) { // If admissible // Build Differential Quarature Rule CubatureTensorSorted<Scalar> diffRule(0,dimension); build_diffRule(diffRule,index,problem_data); // Apply Rule to function problem_data.eval_cubature(*s,diffRule); // Update integral value integralValue.Update(*s); // Update local error indicator and index set G = problem_data.error_indicator(*s); if (activeIndex.end()!=activeIndex.begin()) activeIndex.insert(activeIndex.end()--, std::pair<Scalar,std::vector<int> >(G,index)); else activeIndex.insert(std::pair<Scalar,std::vector<int> >(G,index)); // Update global error indicators eta += G; // Update adapted quadrature rule nodes and weights cubRule.update(1.0,diffRule,1.0); } } else { // Max Level Exceeded //std::cout << "Maximum Level Exceeded" << std::endl; } index[k]--; } return eta; }
void FindPeaksMD::findPeaks(typename MDEventWorkspace<MDE, nd>::sptr ws) { if (nd < 3) throw std::invalid_argument("Workspace must have at least 3 dimensions."); progress(0.01, "Refreshing Centroids"); // TODO: This might be slow, progress report? // Make sure all centroids are fresh ws->getBox()->refreshCentroid(); typedef IMDBox<MDE,nd>* boxPtr; if (ws->getNumExperimentInfo() == 0) throw std::runtime_error("No instrument was found in the MDEventWorkspace. Cannot find peaks."); // TODO: Do we need to pick a different instrument info? ExperimentInfo_sptr ei = ws->getExperimentInfo(0); // Instrument associated with workspace Geometry::Instrument_const_sptr inst = ei->getInstrument(); // Find the run number int runNumber = ei->getRunNumber(); // Check that the workspace dimensions are in Q-sample-frame or Q-lab-frame. eDimensionType dimType; std::string dim0 = ws->getDimension(0)->getName(); if (dim0 == "H") { dimType = HKL; throw std::runtime_error("Cannot find peaks in a workspace that is already in HKL space."); } else if (dim0 == "Q_lab_x") { dimType = QLAB; } else if (dim0 == "Q_sample_x") dimType = QSAMPLE; else throw std::runtime_error("Unexpected dimensions: need either Q_lab_x or Q_sample_x."); // Find the goniometer rotation matrix Mantid::Kernel::Matrix<double> goniometer(3,3, true); // Default IDENTITY matrix try { goniometer = ei->mutableRun().getGoniometerMatrix(); } catch (std::exception & e) { g_log.warning() << "Error finding goniometer matrix. It will not be set in the peaks found." << std::endl; g_log.warning() << e.what() << std::endl; } /// Arbitrary scaling factor for density to make more manageable numbers, especially for older file formats. signal_t densityScalingFactor = 1e-6; // Calculate a threshold below which a box is too diffuse to be considered a peak. signal_t thresholdDensity = 0.0; thresholdDensity = ws->getBox()->getSignalNormalized() * DensityThresholdFactor * densityScalingFactor; g_log.notice() << "Threshold signal density: " << thresholdDensity << std::endl; // We will fill this vector with pointers to all the boxes (up to a given depth) typename std::vector<boxPtr> boxes; // Get all the MDboxes progress(0.10, "Getting Boxes"); ws->getBox()->getBoxes(boxes, 1000, true); // TODO: Here keep only the boxes > e.g. 3 * mean. typedef std::pair<double, boxPtr> dens_box; // Map that will sort the boxes by increasing density. The key = density; value = box *. typename std::multimap<double, boxPtr> sortedBoxes; progress(0.20, "Sorting Boxes by Density"); typename std::vector<boxPtr>::iterator it1; typename std::vector<boxPtr>::iterator it1_end = boxes.end(); for (it1 = boxes.begin(); it1 != it1_end; it1++) { boxPtr box = *it1; double density = box->getSignalNormalized() * densityScalingFactor; // Skip any boxes with too small a signal density. if (density > thresholdDensity) sortedBoxes.insert(dens_box(density,box)); } // List of chosen possible peak boxes. std::vector<boxPtr> peakBoxes; prog = new Progress(this, 0.30, 0.95, MaxPeaks); int64_t numBoxesFound = 0; // Now we go (backwards) through the map // e.g. from highest density down to lowest density. typename std::multimap<double, boxPtr>::reverse_iterator it2; typename std::multimap<double, boxPtr>::reverse_iterator it2_end = sortedBoxes.rend(); for (it2 = sortedBoxes.rbegin(); it2 != it2_end; it2++) { signal_t density = it2->first; boxPtr box = it2->second; #ifndef MDBOX_TRACK_CENTROID coord_t boxCenter[nd]; box->calculateCentroid(boxCenter); #else const coord_t * boxCenter = box->getCentroid(); #endif // Compare to all boxes already picked. bool badBox = false; for (typename std::vector<boxPtr>::iterator it3=peakBoxes.begin(); it3 != peakBoxes.end(); it3++) { #ifndef MDBOX_TRACK_CENTROID coord_t otherCenter[nd]; (*it3)->calculateCentroid(otherCenter); #else const coord_t * otherCenter = (*it3)->getCentroid(); #endif // Distance between this box and a box we already put in. coord_t distSquared = 0.0; for (size_t d=0; d<nd; d++) { coord_t dist = otherCenter[d] - boxCenter[d]; distSquared += (dist * dist); } // Reject this box if it is too close to another previously found box. if (distSquared < peakRadiusSquared) { badBox = true; break; } } // The box was not rejected for another reason. if (!badBox) { if (numBoxesFound++ >= MaxPeaks) { g_log.notice() << "Number of peaks found exceeded the limit of " << MaxPeaks << ". Stopping peak finding." << std::endl; break; } peakBoxes.push_back(box); g_log.information() << "Found box at "; for (size_t d=0; d<nd; d++) g_log.information() << (d>0?",":"") << boxCenter[d]; g_log.information() << "; Density = " << density << std::endl; // Report progres for each box found. prog->report("Finding Peaks"); } } prog->resetNumSteps(numBoxesFound, 0.95, 1.0); // Copy the instrument, sample, run to the peaks workspace. peakWS->copyExperimentInfoFrom(ei.get()); // --- Convert the "boxes" to peaks ---- for (typename std::vector<boxPtr>::iterator it3=peakBoxes.begin(); it3 != peakBoxes.end(); it3++) { // The center of the box = Q in the lab frame boxPtr box = *it3; #ifndef MDBOX_TRACK_CENTROID coord_t boxCenter[nd]; box->calculateCentroid(boxCenter); #else const coord_t * boxCenter = box->getCentroid(); #endif V3D Q(boxCenter[0], boxCenter[1], boxCenter[2]); // Create a peak and add it // Empty starting peak. Peak p; try { if (dimType == QLAB) { // Build using the Q-lab-frame constructor p = Peak(inst, Q); // Save gonio matrix for later p.setGoniometerMatrix(goniometer); } else if (dimType == QSAMPLE) { // Build using the Q-sample-frame constructor p = Peak(inst, Q, goniometer); } } catch (std::exception &e) { g_log.notice() << "Error creating peak at " << Q << " because of '" << e.what() << "'. Peak will be skipped." << std::endl; continue; } try { // Look for a detector p.findDetector(); } catch (...) { /* Ignore errors in ray-tracer TODO: Handle for WISH data later */ } // The "bin count" used will be the box density. p.setBinCount( box->getSignalNormalized() * densityScalingFactor); // Save the run number found before. p.setRunNumber(runNumber); peakWS->addPeak(p); // Report progres for each box found. prog->report("Adding Peaks"); } // for each box found }