/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void Fit::exec() { // this is to make it work with AlgorithmProxy if (!m_domainCreator) { setFunction(); addWorkspaces(); } std::string ties = getPropertyValue("Ties"); if (!ties.empty()) { m_function->addTies(ties); } std::string contstraints = getPropertyValue("Constraints"); if (!contstraints.empty()) { m_function->addConstraints(contstraints); } // prepare the function for a fit m_function->setUpForFit(); API::FunctionDomain_sptr domain; API::FunctionValues_sptr values; // TODO: should values be part of domain? m_domainCreator->ignoreInvalidData(getProperty("IgnoreInvalidData")); m_domainCreator->createDomain(domain,values); // do something with the function which may depend on workspace m_domainCreator->initFunction(m_function); // get the minimizer std::string minimizerName = getPropertyValue("Minimizer"); API::IFuncMinimizer_sptr minimizer = API::FuncMinimizerFactory::Instance().createMinimizer(minimizerName); // Try to retrieve optional properties const int maxIterations = getProperty("MaxIterations"); // get the cost function which must be a CostFuncFitting boost::shared_ptr<CostFuncFitting> costFunc = boost::dynamic_pointer_cast<CostFuncFitting>( API::CostFunctionFactory::Instance().create(getPropertyValue("CostFunction")) ); costFunc->setFittingFunction(m_function,domain,values); minimizer->initialize(costFunc); const int64_t nsteps = maxIterations*m_function->estimateNoProgressCalls(); API::Progress prog(this,0.0,1.0,nsteps); m_function->setProgressReporter(&prog); // do the fitting until success or iteration limit is reached size_t iter = 0; bool success = false; std::string errorString; g_log.debug("Starting minimizer iteration\n"); while (static_cast<int>(iter) < maxIterations) { iter++; g_log.debug() << "Starting iteration " << iter << "\n"; m_function->iterationStarting(); if ( !minimizer->iterate() ) { errorString = minimizer->getError(); g_log.debug() << "Iteration stopped. Minimizer status string=" << errorString << "\n"; success = errorString.empty() || errorString == "success"; if (success) { errorString = "success"; } break; } prog.report(); m_function->iterationFinished(); if(g_log.is(Kernel::Logger::Priority::PRIO_INFORMATION)) { g_log.debug() << "Iteration " << iter << ", cost function = " << minimizer->costFunctionVal() << "\n"; } } g_log.debug() << "Number of minimizer iterations=" << iter << "\n"; if (static_cast<int>(iter) >= maxIterations) { if ( !errorString.empty() ) { errorString += '\n'; } errorString += "Failed to converge after " + boost::lexical_cast<std::string>(maxIterations) + " iterations."; } // return the status flag setPropertyValue("OutputStatus",errorString); // degrees of freedom size_t dof = domain->size() - costFunc->nParams(); if (dof == 0) dof = 1; double rawcostfuncval = minimizer->costFunctionVal(); double finalCostFuncVal = rawcostfuncval / double(dof); setProperty("OutputChi2overDoF",finalCostFuncVal); // fit ended, creating output // get the workspace API::Workspace_const_sptr ws = getProperty("InputWorkspace"); bool doCreateOutput = getProperty("CreateOutput"); std::string baseName = getPropertyValue("Output"); if ( !baseName.empty() ) { doCreateOutput = true; } bool doCalcErrors = getProperty("CalcErrors"); if ( doCreateOutput ) { doCalcErrors = true; } if ( costFunc->nParams() == 0 ) { doCalcErrors = false; } GSLMatrix covar; if ( doCalcErrors ) { // Calculate the covariance matrix and the errors. costFunc->calCovarianceMatrix(covar); costFunc->calFittingErrors( covar, rawcostfuncval ); } if (doCreateOutput) { if (baseName.empty()) { baseName = ws->name(); if (baseName.empty()) { baseName = "Output"; } } baseName += "_"; declareProperty( new API::WorkspaceProperty<API::ITableWorkspace>("OutputNormalisedCovarianceMatrix","",Kernel::Direction::Output), "The name of the TableWorkspace in which to store the final covariance matrix" ); setPropertyValue("OutputNormalisedCovarianceMatrix",baseName+"NormalisedCovarianceMatrix"); Mantid::API::ITableWorkspace_sptr covariance = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); covariance->addColumn("str","Name"); // set plot type to Label = 6 covariance->getColumn(covariance->columnCount()-1)->setPlotType(6); //std::vector<std::string> paramThatAreFitted; // used for populating 1st "name" column for(size_t i=0; i < m_function->nParams(); i++) { if (m_function->isActive(i)) { covariance->addColumn("double",m_function->parameterName(i)); //paramThatAreFitted.push_back(m_function->parameterName(i)); } } size_t np = m_function->nParams(); size_t ia = 0; for(size_t i = 0; i < np; i++) { if (m_function->isFixed(i)) continue; Mantid::API::TableRow row = covariance->appendRow(); row << m_function->parameterName(i); size_t ja = 0; for(size_t j = 0; j < np; j++) { if (m_function->isFixed(j)) continue; if (j == i) row << 100.0; else { row << 100.0*covar.get(ia,ja)/sqrt(covar.get(ia,ia)*covar.get(ja,ja)); } ++ja; } ++ia; } setProperty("OutputNormalisedCovarianceMatrix",covariance); // create output parameter table workspace to store final fit parameters // including error estimates if derivative of fitting function defined declareProperty( new API::WorkspaceProperty<API::ITableWorkspace>("OutputParameters","",Kernel::Direction::Output), "The name of the TableWorkspace in which to store the final fit parameters" ); setPropertyValue("OutputParameters",baseName+"Parameters"); Mantid::API::ITableWorkspace_sptr result = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); result->addColumn("str","Name"); // set plot type to Label = 6 result->getColumn(result->columnCount()-1)->setPlotType(6); result->addColumn("double","Value"); result->addColumn("double","Error"); // yErr = 5 result->getColumn(result->columnCount()-1)->setPlotType(5); for(size_t i=0;i<m_function->nParams();i++) { Mantid::API::TableRow row = result->appendRow(); row << m_function->parameterName(i) << m_function->getParameter(i) << m_function->getError(i); } // Add chi-squared value at the end of parameter table Mantid::API::TableRow row = result->appendRow(); #if 1 std::string costfuncname = getPropertyValue("CostFunction"); if (costfuncname == "Rwp") row << "Cost function value" << rawcostfuncval; else row << "Cost function value" << finalCostFuncVal; setProperty("OutputParameters",result); #else row << "Cost function value" << finalCostFuncVal; Mantid::API::TableRow row2 = result->appendRow(); std::string name(getPropertyValue("CostFunction")); name += " value"; row2 << name << rawcostfuncval; #endif setProperty("OutputParameters",result); bool outputParametersOnly = getProperty("OutputParametersOnly"); if ( !outputParametersOnly ) { const bool unrollComposites = getProperty("OutputCompositeMembers"); bool convolveMembers = existsProperty("ConvolveMembers"); if ( convolveMembers ) { convolveMembers = getProperty("ConvolveMembers"); } m_domainCreator->separateCompositeMembersInOutput(unrollComposites,convolveMembers); m_domainCreator->createOutputWorkspace(baseName,m_function,domain,values); } } }
// Test move method void testMoveMethod01() { // Test with a variety of object types in the From ResponseData // Build the class CIMClass CIMclass1 = buildClass(); // Build a CIM Instance. NOTE: key is defaulted in class CIMInstance CIMInst1 = CIMclass1.buildInstance(true, true, CIMPropertyList()); // Clone the instance and change key CIMInstance CIMInst2 = CIMInst1.clone(); setPropertyValue(CIMInst2, "id", 2); CIMInstance CIMInst3 = CIMInst1.clone(); setPropertyValue(CIMInst3, "id", 3); CIMInstance CIMInst4 = CIMInst1.clone(); setPropertyValue(CIMInst4, "id", 4); // build CIMInstance array Array<CIMInstance> CIMInstArray; CIMInstArray.append(CIMInst1); CIMInstArray.append(CIMInst2); CIMInstArray.append(CIMInst3); CIMInstArray.append(CIMInst3); { // Create from CIMReponseData object CIMResponseData crdFrom = CIMResponseData( CIMResponseData::RESP_INSTANCES); // Append an array of CIMInstances crdFrom.appendInstances(CIMInstArray); VCOUT << crdFrom.size() << endl; PEGASUS_TEST_ASSERT(crdFrom.size() == 4); // Move the objects < what is in from crd CIMResponseData crdTo = CIMResponseData( CIMResponseData::RESP_INSTANCES); PEGASUS_TEST_ASSERT(testMoveObjects(crdTo, crdFrom, 2)); PEGASUS_TEST_ASSERT(crdFrom.size() == 2); PEGASUS_TEST_ASSERT(crdTo.size() == 2); // request move of more that exists. Moves all CIMResponseData crdTo1 = CIMResponseData( CIMResponseData::RESP_INSTANCES); PEGASUS_TEST_ASSERT(testMoveObjects(crdTo1, crdFrom, 8)); PEGASUS_TEST_ASSERT(crdFrom.size() == 0); PEGASUS_TEST_ASSERT(crdTo1.size() == 2); } // move exactly all and then none { // Create from CIMReponseData object CIMResponseData crdFrom = CIMResponseData( CIMResponseData::RESP_INSTANCES); // Append an array of CIMInstances crdFrom.appendInstances(CIMInstArray); VCOUT << crdFrom.size() << endl; PEGASUS_TEST_ASSERT(crdFrom.size() == 4); // Move the objects < what is in from crd CIMResponseData crdTo = CIMResponseData( CIMResponseData::RESP_INSTANCES); PEGASUS_TEST_ASSERT(testMoveObjects(crdTo, crdFrom, 4)); PEGASUS_TEST_ASSERT(crdFrom.size() == 0); PEGASUS_TEST_ASSERT(crdTo.size() == 4); // request move of more that exists. Moves all r CIMResponseData crdTo1 = CIMResponseData( CIMResponseData::RESP_INSTANCES); PEGASUS_TEST_ASSERT(testMoveObjects(crdTo1, crdFrom, 8)); PEGASUS_TEST_ASSERT(crdFrom.size() == 0); VCOUT << "Error: bad size() = " << crdTo1.size() << endl; PEGASUS_TEST_ASSERT(crdTo1.size() == 0); } // request move more than total { // Create from CIMReponseData object CIMResponseData crdFrom = CIMResponseData( CIMResponseData::RESP_INSTANCES); // Append an array of CIMInstances crdFrom.appendInstances(CIMInstArray); VCOUT << crdFrom.size() << endl; PEGASUS_TEST_ASSERT(crdFrom.size() == 4); // Move the objects < what is in from crd CIMResponseData crdTo = CIMResponseData( CIMResponseData::RESP_INSTANCES); PEGASUS_TEST_ASSERT(testMoveObjects(crdTo, crdFrom, 9)); PEGASUS_TEST_ASSERT(crdFrom.size() == 0); PEGASUS_TEST_ASSERT(crdTo.size() == 4); } }
void EQSANSLoad::exec() { // Verify the validity of the inputs //TODO: this should be done by the new data management algorithm used for // live data reduction (when it's implemented...) const std::string fileName = getPropertyValue("Filename"); EventWorkspace_sptr inputEventWS = getProperty("InputWorkspace"); if (fileName.size()==0 && !inputEventWS) { g_log.error() << "EQSANSLoad input error: Either a valid file path or an input workspace must be provided" << std::endl; throw std::runtime_error("EQSANSLoad input error: Either a valid file path or an input workspace must be provided"); } else if (fileName.size()>0 && inputEventWS) { g_log.error() << "EQSANSLoad input error: Either a valid file path or an input workspace must be provided, but not both" << std::endl; throw std::runtime_error("EQSANSLoad input error: Either a valid file path or an input workspace must be provided, but not both"); } // Read in default TOF cuts const bool skipTOFCorrection = getProperty("SkipTOFCorrection"); m_low_TOF_cut = getProperty("LowTOFCut"); m_high_TOF_cut = getProperty("HighTOFCut"); // Read in default beam center m_center_x = getProperty("BeamCenterX"); m_center_y = getProperty("BeamCenterY"); const bool noBeamCenter = getProperty("NoBeamCenter"); // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } if (!reductionManager->existsProperty("LoadAlgorithm")) { AlgorithmProperty *loadProp = new AlgorithmProperty("LoadAlgorithm"); setPropertyValue("InputWorkspace", ""); setProperty("NoBeamCenter", false); loadProp->setValue(toString()); reductionManager->declareProperty(loadProp); } if (!reductionManager->existsProperty("InstrumentName")) { reductionManager->declareProperty(new PropertyWithValue<std::string>("InstrumentName", "EQSANS") ); } // Output log m_output_message = ""; // Check whether we need to load the data if (!inputEventWS) { const bool loadMonitors = getProperty("LoadMonitors"); IAlgorithm_sptr loadAlg = createChildAlgorithm("LoadEventNexus", 0, 0.2); loadAlg->setProperty("LoadMonitors", loadMonitors); loadAlg->setProperty("MonitorsAsEvents", false); loadAlg->setProperty("Filename", fileName); if (skipTOFCorrection) { if (m_low_TOF_cut>0.0) loadAlg->setProperty("FilterByTofMin", m_low_TOF_cut); if (m_high_TOF_cut>0.0) loadAlg->setProperty("FilterByTofMax", m_high_TOF_cut); } loadAlg->execute(); IEventWorkspace_sptr dataWS_asWks = loadAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks); // Get monitor workspace as necessary std::string mon_wsname = getPropertyValue("OutputWorkspace")+"_monitors"; if (loadMonitors && loadAlg->existsProperty("MonitorWorkspace")) { MatrixWorkspace_sptr monWS = loadAlg->getProperty("MonitorWorkspace"); declareProperty(new WorkspaceProperty<>("MonitorWorkspace", mon_wsname, Direction::Output), "Monitors from the Event NeXus file"); setProperty("MonitorWorkspace", monWS); } } else { MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); EventWorkspace_sptr outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (inputEventWS != outputEventWS) { IAlgorithm_sptr copyAlg = createChildAlgorithm("CloneWorkspace", 0, 0.2); copyAlg->setProperty("InputWorkspace", inputEventWS); copyAlg->executeAsChildAlg(); Workspace_sptr dataWS_asWks = copyAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks); } else { dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(inputEventWS); } } // Get the sample-detector distance double sdd = 0.0; const double sample_det_dist = getProperty("SampleDetectorDistance"); if (!isEmpty(sample_det_dist)) { sdd = sample_det_dist; } else { if (!dataWS->run().hasProperty("detectorZ")) { g_log.error() << "Could not determine Z position: the SampleDetectorDistance property was not set " "and the run logs do not contain the detectorZ property" << std::endl; throw std::invalid_argument("Could not determine Z position: stopping execution"); } Mantid::Kernel::Property* prop = dataWS->run().getProperty("detectorZ"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); sdd = dp->getStatistics().mean; // Modify SDD according to offset if given const double sample_det_offset = getProperty("SampleDetectorDistanceOffset"); if (!isEmpty(sample_det_offset)) { sdd += sample_det_offset; } } dataWS->mutableRun().addProperty("sample_detector_distance", sdd, "mm", true); // Move the detector to its correct position IAlgorithm_sptr mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.2, 0.4); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "detector1"); mvAlg->setProperty("Z", sdd/1000.0); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsChildAlg(); g_log.information() << "Moving detector to " << sdd/1000.0 << " meters" << std::endl; m_output_message += " Detector position: " + Poco::NumberFormatter::format(sdd/1000.0, 3) + " m\n"; // Get the run number so we can find the proper config file int run_number = 0; std::string config_file = ""; if (dataWS->run().hasProperty("run_number")) { Mantid::Kernel::Property* prop = dataWS->run().getProperty("run_number"); Mantid::Kernel::PropertyWithValue<std::string>* dp = dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string>* >(prop); const std::string run_str = *dp; Poco::NumberParser::tryParse(run_str, run_number); // Find a proper config file config_file = findConfigFile(run_number); } else { g_log.error() << "Could not find run number for workspace " << getPropertyValue("OutputWorkspace") << std::endl; m_output_message += " Could not find run number for data file\n"; } // Process the config file bool use_config = getProperty("UseConfig"); if (use_config && config_file.size()>0) { // Special case to force reading the beam center from the config file // We're adding this to be compatible with the original EQSANS load // written in python if (m_center_x==0.0 && m_center_y==0.0) { setProperty("UseConfigBeam", true); } readConfigFile(config_file); } else if (use_config) { use_config = false; g_log.error() << "Cound not find config file for workspace " << getPropertyValue("OutputWorkspace") << std::endl; m_output_message += " Could not find configuration file for run " + Poco::NumberFormatter::format(run_number) + "\n"; } // If we use the config file, move the moderator position if (use_config) { if (m_moderator_position > -13.0) g_log.error() << "Moderator position seems close to the sample, please check" << std::endl; g_log.information() << "Moving moderator to " << m_moderator_position << std::endl; m_output_message += " Moderator position: " + Poco::NumberFormatter::format(m_moderator_position, 3) + " m\n"; mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.4, 0.45); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "moderator"); mvAlg->setProperty("Z", m_moderator_position); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsChildAlg(); } // Get source aperture radius getSourceSlitSize(); // Move the beam center to its proper position if (!noBeamCenter) { if (isEmpty(m_center_x) || isEmpty(m_center_y)) { if (reductionManager->existsProperty("LatestBeamCenterX") && reductionManager->existsProperty("LatestBeamCenterY")) { m_center_x = reductionManager->getProperty("LatestBeamCenterX"); m_center_y = reductionManager->getProperty("LatestBeamCenterY"); } } moveToBeamCenter(); // Add beam center to reduction properties, as the last beam center position that was used. // This will give us our default position next time. if (!reductionManager->existsProperty("LatestBeamCenterX")) reductionManager->declareProperty(new PropertyWithValue<double>("LatestBeamCenterX", m_center_x) ); else reductionManager->setProperty("LatestBeamCenterX", m_center_x); if (!reductionManager->existsProperty("LatestBeamCenterY")) reductionManager->declareProperty(new PropertyWithValue<double>("LatestBeamCenterY", m_center_y) ); else reductionManager->setProperty("LatestBeamCenterY", m_center_y); } // Modify TOF const bool correct_for_flight_path = getProperty("CorrectForFlightPath"); double wl_min = 0.0; double wl_max = 0.0; double wl_combined_max = 0.0; if (skipTOFCorrection) { m_output_message += " Skipping EQSANS TOF correction: assuming a single frame\n"; dataWS->mutableRun().addProperty("is_frame_skipping", 0, true); if (correct_for_flight_path) { g_log.error() << "CorrectForFlightPath and SkipTOFCorrection can't be set to true at the same time" << std::endl; m_output_message += " Skipped flight path correction: see error log\n"; } } else { m_output_message += " Flight path correction "; if (!correct_for_flight_path) m_output_message += "NOT "; m_output_message += "applied\n"; DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS); IAlgorithm_sptr tofAlg = createChildAlgorithm("EQSANSTofStructure", 0.5, 0.7); tofAlg->setProperty<EventWorkspace_sptr>("InputWorkspace", dataWS_evt); tofAlg->setProperty("LowTOFCut", m_low_TOF_cut); tofAlg->setProperty("HighTOFCut", m_high_TOF_cut); tofAlg->setProperty("FlightPathCorrection", correct_for_flight_path); tofAlg->executeAsChildAlg(); wl_min = tofAlg->getProperty("WavelengthMin"); wl_max = tofAlg->getProperty("WavelengthMax"); if (wl_min != wl_min || wl_max != wl_max) { g_log.error() << "Bad wavelength range" << std::endl; g_log.error() << m_output_message << std::endl; } const bool frame_skipping = tofAlg->getProperty("FrameSkipping"); dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true); dataWS->mutableRun().addProperty("is_frame_skipping", int(frame_skipping), true); wl_combined_max = wl_max; m_output_message += " Wavelength range: " + Poco::NumberFormatter::format(wl_min, 1) + " - " + Poco::NumberFormatter::format(wl_max, 1); if (frame_skipping) { const double wl_min2 = tofAlg->getProperty("WavelengthMinFrame2"); const double wl_max2 = tofAlg->getProperty("WavelengthMaxFrame2"); wl_combined_max = wl_max2; dataWS->mutableRun().addProperty("wavelength_min_frame2", wl_min2, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max_frame2", wl_max2, "Angstrom", true); m_output_message += " and " + Poco::NumberFormatter::format(wl_min2, 1) + " - " + Poco::NumberFormatter::format(wl_max2, 1) + " Angstrom\n"; } else m_output_message += " Angstrom\n"; } // Convert to wavelength const double ssd = fabs(dataWS->getInstrument()->getSource()->getPos().Z())*1000.0; const double conversion_factor = 3.9560346 / (sdd+ssd); m_output_message += " TOF to wavelength conversion factor: " + Poco::NumberFormatter::format(conversion_factor) + "\n"; if (skipTOFCorrection) { DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS); if (dataWS_evt->getNumberEvents()==0) throw std::invalid_argument("No event to process: check your TOF cuts"); wl_min = dataWS_evt->getTofMin()*conversion_factor; wl_max = dataWS_evt->getTofMax()*conversion_factor; wl_combined_max = wl_max; g_log.information() << "Wavelength range: " << wl_min << " to " << wl_max << std::endl; dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true); } IAlgorithm_sptr scAlg = createChildAlgorithm("ScaleX", 0.7, 0.71); scAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); scAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); scAlg->setProperty("Factor", conversion_factor); scAlg->executeAsChildAlg(); dataWS->getAxis(0)->setUnit("Wavelength"); // Rebin so all the wavelength bins are aligned const bool preserveEvents = getProperty("PreserveEvents"); const double wl_step = getProperty("WavelengthStep"); std::string params = Poco::NumberFormatter::format(wl_min, 2) + "," + Poco::NumberFormatter::format(wl_step, 2) + "," + Poco::NumberFormatter::format(wl_combined_max, 2); IAlgorithm_sptr rebinAlg = createChildAlgorithm("Rebin", 0.71, 0.72); rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); if (preserveEvents) rebinAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); rebinAlg->setPropertyValue("Params", params); rebinAlg->setProperty("PreserveEvents", preserveEvents); rebinAlg->executeAsChildAlg(); if (!preserveEvents) dataWS = rebinAlg->getProperty("OutputWorkspace"); dataWS->mutableRun().addProperty("event_ws", getPropertyValue("OutputWorkspace"), true); setProperty<MatrixWorkspace_sptr>("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS)); //m_output_message = "Loaded " + fileName + '\n' + m_output_message; setPropertyValue("OutputMessage", m_output_message); }
void DataBus::AbstractClient::processSetClientPropertyValueRequestPacket(const Packet &packet) { // Check if registered if (m_registered == false) { // Error, can't send a response if not registered return; } // Check destination if (packet.getDestination() != m_clientId) { // Error, invalid destination return; } // Get Property ID and Value quint8 propertyId; Value propertyValue; if (SetClientPropertyValueRequestPacket::parse(packet, &propertyId, &propertyValue) == false) { // Error, failed to parse packet return; } // Set Property Value quint8 returnStatus = RETURN_STATUS_SUCCESS; if (setPropertyValue(propertyId, propertyValue) == false) { // Error, failed to get property value returnStatus = RETURN_STATUS_INVALID_PROPERTY_ID; } // Create response Packet responsePacket; if (SetClientPropertyValueResponsePacket::create(m_clientId, packet.getSource(), packet.getPacketId(), propertyId, returnStatus, &responsePacket) == false) { // Error, failed to create packet return; } // Send Response if (sendPacket(responsePacket) == false) { // Error, failed to create packet return; } // Success return; }
void FontFace::setPropertyFromString(const String& s, CSSPropertyID propertyID, ExceptionState& es) { RefPtr<CSSValue> value = parseCSSValue(s, propertyID); if (!value || !setPropertyValue(value, propertyID)) es.throwDOMException(SyntaxError); }
bool FontFace::setPropertyFromStyle(const StylePropertySet* properties, CSSPropertyID propertyID) { return setPropertyValue(properties->getPropertyCSSValue(propertyID), propertyID); }
void EQSANSLoad::exec() { // Read in default TOF cuts m_low_TOF_cut = getProperty("LowTOFCut"); m_high_TOF_cut = getProperty("HighTOFCut"); // Read in default beam center m_center_x = getProperty("BeamCenterX"); m_center_y = getProperty("BeamCenterY"); TableWorkspace_sptr reductionTable = getProperty("ReductionTableWorkspace"); ReductionTableHandler reductionHandler(reductionTable); if (!reductionTable) { const std::string reductionTableName = getPropertyValue("ReductionTableWorkspace"); if (reductionTableName.size()>0) setProperty("ReductionTableWorkspace", reductionHandler.getTable()); } if (reductionHandler.findStringEntry("LoadAlgorithm").size()==0) reductionHandler.addEntry("LoadAlgorithm", toString()); const std::string fileName = getPropertyValue("Filename"); // Output log m_output_message = ""; IAlgorithm_sptr loadAlg = createSubAlgorithm("LoadEventNexus", 0, 0.2); loadAlg->setProperty("Filename", fileName); loadAlg->executeAsSubAlg(); IEventWorkspace_sptr dataWS_tmp = loadAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_tmp); // Get the sample-detector distance double sdd = 0.0; const double sample_det_dist = getProperty("SampleDetectorDistance"); if (!isEmpty(sample_det_dist)) { sdd = sample_det_dist; } else { Mantid::Kernel::Property* prop = dataWS->run().getProperty("detectorZ"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); sdd = dp->getStatistics().mean; // Modify SDD according to offset if given const double sample_det_offset = getProperty("SampleDetectorDistanceOffset"); if (!isEmpty(sample_det_offset)) { sdd += sample_det_offset; } } dataWS->mutableRun().addProperty("sample_detector_distance", sdd, "mm", true); // Move the detector to its correct position IAlgorithm_sptr mvAlg = createSubAlgorithm("MoveInstrumentComponent", 0.2, 0.4); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "detector1"); mvAlg->setProperty("Z", sdd/1000.0); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsSubAlg(); g_log.information() << "Moving detector to " << sdd/1000.0 << std::endl; m_output_message += " Detector position: " + Poco::NumberFormatter::format(sdd/1000.0, 3) + " m\n"; // Get the run number so we can find the proper config file int run_number = 0; std::string config_file = ""; if (dataWS->run().hasProperty("run_number")) { Mantid::Kernel::Property* prop = dataWS->run().getProperty("run_number"); Mantid::Kernel::PropertyWithValue<std::string>* dp = dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string>* >(prop); const std::string run_str = *dp; Poco::NumberParser::tryParse(run_str, run_number); // Find a proper config file config_file = findConfigFile(run_number); } else { g_log.error() << "Could not find run number for workspace " << getPropertyValue("OutputWorkspace") << std::endl; m_output_message += " Could not find run number for data file\n"; } // Process the config file bool use_config = getProperty("UseConfig"); if (use_config && config_file.size()>0) { readConfigFile(config_file); } else if (use_config) { use_config = false; g_log.error() << "Cound not find config file for workspace " << getPropertyValue("OutputWorkspace") << std::endl; m_output_message += " Could not find configuration file for run " + Poco::NumberFormatter::format(run_number) + "\n"; } // If we use the config file, move the moderator position if (use_config) { if (m_moderator_position > -13.0) g_log.error() << "Moderator position seems close to the sample, please check" << std::endl; g_log.information() << "Moving moderator to " << m_moderator_position << std::endl; m_output_message += " Moderator position: " + Poco::NumberFormatter::format(m_moderator_position, 3) + " m\n"; mvAlg = createSubAlgorithm("MoveInstrumentComponent", 0.4, 0.45); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "moderator"); mvAlg->setProperty("Z", m_moderator_position); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsSubAlg(); } // Get source aperture radius getSourceSlitSize(); // Move the beam center to its proper position moveToBeamCenter(); // Modify TOF bool correct_for_flight_path = getProperty("CorrectForFlightPath"); m_output_message += " Flight path correction "; if (!correct_for_flight_path) m_output_message += "NOT "; m_output_message += "applied\n"; DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS_tmp); IAlgorithm_sptr tofAlg = createSubAlgorithm("EQSANSTofStructure", 0.5, 0.7); tofAlg->setProperty<EventWorkspace_sptr>("InputWorkspace", dataWS_evt); tofAlg->setProperty("LowTOFCut", m_low_TOF_cut); tofAlg->setProperty("HighTOFCut", m_high_TOF_cut); tofAlg->setProperty("FlightPathCorrection", correct_for_flight_path); tofAlg->executeAsSubAlg(); const double wl_min = tofAlg->getProperty("WavelengthMin"); const double wl_max = tofAlg->getProperty("WavelengthMax"); const bool frame_skipping = tofAlg->getProperty("FrameSkipping"); dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true); dataWS->mutableRun().addProperty("is_frame_skipping", int(frame_skipping), true); double wl_combined_max = wl_max; m_output_message += " Wavelength range: " + Poco::NumberFormatter::format(wl_min, 1) + " - " + Poco::NumberFormatter::format(wl_max, 1); if (frame_skipping) { const double wl_min2 = tofAlg->getProperty("WavelengthMinFrame2"); const double wl_max2 = tofAlg->getProperty("WavelengthMaxFrame2"); wl_combined_max = wl_max2; dataWS->mutableRun().addProperty("wavelength_min_frame2", wl_min2, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max_frame2", wl_max2, "Angstrom", true); m_output_message += " and " + Poco::NumberFormatter::format(wl_min2, 1) + " - " + Poco::NumberFormatter::format(wl_max2, 1) + " Angstrom\n"; } else m_output_message += " Angstrom\n"; // Convert to wavelength const double ssd = fabs(dataWS->getInstrument()->getSource()->getPos().Z())*1000.0; const double conversion_factor = 3.9560346 / (sdd+ssd); m_output_message += " TOF to wavelength conversion factor: " + Poco::NumberFormatter::format(conversion_factor) + "\n"; IAlgorithm_sptr scAlg = createSubAlgorithm("ScaleX", 0.7, 0.71); scAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); scAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); scAlg->setProperty("Factor", conversion_factor); scAlg->executeAsSubAlg(); dataWS->getAxis(0)->setUnit("Wavelength"); // Rebin so all the wavelength bins are aligned const bool preserveEvents = getProperty("PreserveEvents"); std::string params = Poco::NumberFormatter::format(wl_min, 2) + ",0.1," + Poco::NumberFormatter::format(wl_combined_max, 2); IAlgorithm_sptr rebinAlg = createSubAlgorithm("Rebin", 0.71, 0.72); rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); if (preserveEvents) rebinAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); rebinAlg->setPropertyValue("Params", params); rebinAlg->setProperty("PreserveEvents", preserveEvents); rebinAlg->executeAsSubAlg(); if (!preserveEvents) dataWS = rebinAlg->getProperty("OutputWorkspace"); dataWS->mutableRun().addProperty("event_ws", getPropertyValue("OutputWorkspace"), true); setProperty<MatrixWorkspace_sptr>("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS)); setPropertyValue("OutputMessage", m_output_message); }
//---------------------------------------------------------------------------------------------- /// Examine the chi squared as a function of fitting parameters and estimate /// errors for each parameter. void CalculateChiSquared::estimateErrors() { // Number of fiting parameters auto nParams = m_function->nParams(); // Create an output table for displaying slices of the chi squared and // the probabilitydensity function auto pdfTable = API::WorkspaceFactory::Instance().createTable(); std::string baseName = getProperty("Output"); if (baseName.empty()) { baseName = "CalculateChiSquared"; } declareProperty(new API::WorkspaceProperty<API::ITableWorkspace>( "PDFs", "", Kernel::Direction::Output), "The name of the TableWorkspace in which to store the " "pdfs of fit parameters"); setPropertyValue("PDFs", baseName + "_pdf"); setProperty("PDFs", pdfTable); // Create an output table for displaying the parameter errors. auto errorsTable = API::WorkspaceFactory::Instance().createTable(); auto nameColumn = errorsTable->addColumn("str", "Parameter"); auto valueColumn = errorsTable->addColumn("double", "Value"); auto minValueColumn = errorsTable->addColumn("double", "Value at Min"); auto leftErrColumn = errorsTable->addColumn("double", "Left Error"); auto rightErrColumn = errorsTable->addColumn("double", "Right Error"); auto quadraticErrColumn = errorsTable->addColumn("double", "Quadratic Error"); auto chiMinColumn = errorsTable->addColumn("double", "Chi2 Min"); errorsTable->setRowCount(nParams); declareProperty(new API::WorkspaceProperty<API::ITableWorkspace>( "Errors", "", Kernel::Direction::Output), "The name of the TableWorkspace in which to store the " "values and errors of fit parameters"); setPropertyValue("Errors", baseName + "_errors"); setProperty("Errors", errorsTable); // Calculate initial values double chiSquared = 0.0; double chiSquaredWeighted = 0.0; double dof = 0; API::FunctionDomain_sptr domain; API::FunctionValues_sptr values; m_domainCreator->createDomain(domain, values); calcChiSquared(*m_function, nParams, *domain, *values, chiSquared, chiSquaredWeighted, dof); // Value of chi squared for current parameters in m_function double chi0 = chiSquared; // Fit data variance double sigma2 = chiSquared / dof; bool useWeighted = getProperty("Weighted"); if (useWeighted) { chi0 = chiSquaredWeighted; sigma2 = 0.0; } if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "chi0=" << chi0 << std::endl; g_log.debug() << "sigma2=" << sigma2 << std::endl; g_log.debug() << "dof=" << dof << std::endl; } // Parameter bounds that define a volume in the parameter // space within which the chi squared is being examined. GSLVector lBounds(nParams); GSLVector rBounds(nParams); // Number of points in lines for plotting size_t n = 100; pdfTable->setRowCount(n); const double fac = 1e-4; // Loop over each parameter for (size_t ip = 0; ip < nParams; ++ip) { // Add columns for the parameter to the pdf table. auto parName = m_function->parameterName(ip); nameColumn->read(ip, parName); // Parameter values auto col1 = pdfTable->addColumn("double", parName); col1->setPlotType(1); // Chi squared values auto col2 = pdfTable->addColumn("double", parName + "_chi2"); col2->setPlotType(2); // PDF values auto col3 = pdfTable->addColumn("double", parName + "_pdf"); col3->setPlotType(2); double par0 = m_function->getParameter(ip); double shift = fabs(par0 * fac); if (shift == 0.0) { shift = fac; } // Make a slice along this parameter GSLVector dir(nParams); dir.zero(); dir[ip] = 1.0; ChiSlice slice(*m_function, dir, *domain, *values, chi0, sigma2); // Find the bounds withn which the PDF is significantly above zero. // The bounds are defined relative to par0: // par0 + lBound is the lowest value of the parameter (lBound <= 0) // par0 + rBound is the highest value of the parameter (rBound >= 0) double lBound = slice.findBound(-shift); double rBound = slice.findBound(shift); lBounds[ip] = lBound; rBounds[ip] = rBound; // Approximate the slice with a polynomial. // P is a vector of values of the polynomial at special points. // A is a vector of Chebyshev expansion coefficients. // The polynomial is defined on interval [lBound, rBound] // The value of the polynomial at 0 == chi squared at par0 std::vector<double> P, A; bool ok = true; auto base = slice.makeApprox(lBound, rBound, P, A, ok); if (!ok) { g_log.warning() << "Approximation failed for parameter " << ip << std::endl; } if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "Parameter " << ip << std::endl; g_log.debug() << "Slice approximated by polynomial of order " << base->size() - 1; g_log.debug() << " between " << lBound << " and " << rBound << std::endl; } // Write n slice points into the output table. double dp = (rBound - lBound) / static_cast<double>(n); for (size_t i = 0; i < n; ++i) { double par = lBound + dp * static_cast<double>(i); double chi = base->eval(par, P); col1->fromDouble(i, par0 + par); col2->fromDouble(i, chi); } // Check if par0 is a minimum point of the chi squared std::vector<double> AD; // Calculate the derivative polynomial. // AD are the Chebyshev expansion of the derivative. base->derivative(A, AD); // Find the roots of the derivative polynomial std::vector<double> minima = base->roots(AD); if (minima.empty()) { minima.push_back(par0); } if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "Minima: "; } // If only 1 extremum is found assume (without checking) that it's a // minimum. // If there are more than 1, find the one with the smallest chi^2. double chiMin = std::numeric_limits<double>::max(); double parMin = par0; for (size_t i = 0; i < minima.size(); ++i) { double value = base->eval(minima[i], P); if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << minima[i] << " (" << value << ") "; } if (value < chiMin) { chiMin = value; parMin = minima[i]; } } if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << std::endl; g_log.debug() << "Smallest minimum at " << parMin << " is " << chiMin << std::endl; } // Points of intersections with line chi^2 = 1/2 give an estimate of // the standard deviation of this parameter if it's uncorrelated with the // others. A[0] -= 0.5; // Now A are the coefficients of the original polynomial // shifted down by 1/2. std::vector<double> roots = base->roots(A); std::sort(roots.begin(), roots.end()); if (roots.empty()) { // Something went wrong; use the whole interval. roots.resize(2); roots[0] = lBound; roots[1] = rBound; } else if (roots.size() == 1) { // Only one root found; use a bound for the other root. if (roots.front() < 0) { roots.push_back(rBound); } else { roots.insert(roots.begin(), lBound); } } else if (roots.size() > 2) { // More than 2 roots; use the smallest and the biggest auto smallest = roots.front(); auto biggest = roots.back(); roots.resize(2); roots[0] = smallest; roots[1] = biggest; } if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "Roots: "; for (size_t i = 0; i < roots.size(); ++i) { g_log.debug() << roots[i] << ' '; } g_log.debug() << std::endl; } // Output parameter info to the table. valueColumn->fromDouble(ip, par0); minValueColumn->fromDouble(ip, par0 + parMin); leftErrColumn->fromDouble(ip, roots[0] - parMin); rightErrColumn->fromDouble(ip, roots[1] - parMin); chiMinColumn->fromDouble(ip, chiMin); // Output the PDF for (size_t i = 0; i < n; ++i) { double chi = col2->toDouble(i); col3->fromDouble(i, exp(-chi + chiMin)); } // make sure function parameters don't change. m_function->setParameter(ip, par0); } // Improve estimates for standard deviations. // If parameters are correlated the found deviations // most likely underestimate the true values. unfixParameters(); GSLJacobian J(m_function, values->size()); m_function->functionDeriv(*domain, J); refixParameters(); // Calculate the hessian at the current point. GSLMatrix H; if (useWeighted) { H.resize(nParams, nParams); for (size_t i = 0; i < nParams; ++i) { for (size_t j = i; j < nParams; ++j) { double h = 0.0; for (size_t k = 0; k < values->size(); ++k) { double w = values->getFitWeight(k); h += J.get(k, i) * J.get(k, j) * w * w; } H.set(i, j, h); if (i != j) { H.set(j, i, h); } } } } else { H = Tr(J.matrix()) * J.matrix(); } // Square roots of the diagonals of the covariance matrix give // the standard deviations in the quadratic approximation of the chi^2. GSLMatrix V(H); if (!useWeighted) { V *= 1. / sigma2; } V.invert(); // In a non-quadratic asymmetric case the following procedure can give a // better result: // Find the direction in which the chi^2 changes slowest and the positive and // negative deviations in that direction. The change in a parameter at those // points can be a better estimate for the standard deviation. GSLVector v(nParams); GSLMatrix Q(nParams, nParams); // One of the eigenvectors of the hessian is the direction of the slowest // change. H.eigenSystem(v, Q); // Loop over the eigenvectors for (size_t i = 0; i < nParams; ++i) { auto dir = Q.copyColumn(i); if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "Direction " << i << std::endl; g_log.debug() << dir << std::endl; } // Make a slice in that direction ChiSlice slice(*m_function, dir, *domain, *values, chi0, sigma2); double rBound0 = dir.dot(rBounds); double lBound0 = dir.dot(lBounds); if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "lBound " << lBound0 << std::endl; g_log.debug() << "rBound " << rBound0 << std::endl; } double lBound = slice.findBound(lBound0); double rBound = slice.findBound(rBound0); std::vector<double> P, A; // Use a polynomial approximation bool ok = true; auto base = slice.makeApprox(lBound, rBound, P, A, ok); if (!ok) { g_log.warning() << "Approximation failed in direction " << i << std::endl; } // Find the deviation points where the chi^2 = 1/2 A[0] -= 0.5; std::vector<double> roots = base->roots(A); std::sort(roots.begin(), roots.end()); // Sort out the roots auto nRoots = roots.size(); if (nRoots == 0) { roots.resize(2, 0.0); } else if (nRoots == 1) { if (roots.front() > 0.0) { roots.insert(roots.begin(), 0.0); } else { roots.push_back(0.0); } } else if (nRoots > 2) { roots[1] = roots.back(); roots.resize(2); } if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "Roots " << roots[0] << " (" << slice(roots[0]) << ") " << roots[1] << " (" << slice(roots[1]) << ") " << std::endl; } // Loop over the parameters and see if there deviations along // this direction is greater than any previous value. for (size_t ip = 0; ip < nParams; ++ip) { auto lError = roots.front() * dir[ip]; auto rError = roots.back() * dir[ip]; if (lError > rError) { std::swap(lError, rError); } if (lError < leftErrColumn->toDouble(ip)) { if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << " left for " << ip << ' ' << lError << ' ' << leftErrColumn->toDouble(ip) << std::endl; } leftErrColumn->fromDouble(ip, lError); } if (rError > rightErrColumn->toDouble(ip)) { if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) { g_log.debug() << " right for " << ip << ' ' << rError << ' ' << rightErrColumn->toDouble(ip) << std::endl; } rightErrColumn->fromDouble(ip, rError); } } // Output the quadratic estimate for comparrison. quadraticErrColumn->fromDouble(i, sqrt(V.get(i, i))); } }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void GenericFit::exec() { // Try to retrieve optional properties const int maxInterations = getProperty("MaxIterations"); Progress prog(this,0.0,1.0,maxInterations?maxInterations:1); std::string funIni = getProperty("Function"); m_function.reset( API::FunctionFactory::Instance().createInitialized(funIni) ); if (m_function.get() == NULL) { throw std::runtime_error("Function was not set."); } prog.report("Setting workspace"); API::Workspace_sptr ws = getProperty("InputWorkspace"); std::string input = getProperty("Input"); m_function->setWorkspace(ws,input); prog.report("Setting minimizer"); // force initial parameters to satisfy constraints of function m_function->setParametersToSatisfyConstraints(); // check if derivative defined in derived class bool isDerivDefined = true; try { m_function->functionDeriv(NULL); } catch (Exception::NotImplementedError&) { isDerivDefined = false; } // What minimizer to use std::string methodUsed = getProperty("Minimizer"); if ( !isDerivDefined && methodUsed.compare("Simplex") != 0 ) { methodUsed = "Simplex"; g_log.information() << "No derivatives available for this fitting function" << " therefore Simplex method used for fitting\n"; } // set-up minimizer std::string costFunction = getProperty("CostFunction"); IFuncMinimizer* minimizer = FuncMinimizerFactory::Instance().createUnwrapped(methodUsed); minimizer->initialize(m_function.get(), costFunction); // create and populate data containers. Warn user if nData < nParam // since as a rule of thumb this is required as a minimum to obtained 'accurate' // fitting parameter values. const size_t nParam = m_function->nActive(); const size_t nData = m_function->dataSize(); if (nParam == 0) { g_log.error("There are no active parameters."); setProperty("OutputChi2overDoF", minimizer->costFunctionVal()); throw std::runtime_error("There are no active parameters."); } if (nData == 0) { g_log.error("The data set is empty."); throw std::runtime_error("The data set is empty."); } if (nData < nParam) { g_log.error("Number of data points less than number of parameters to be fitted."); throw std::runtime_error("Number of data points less than number of parameters to be fitted."); } // finally do the fitting int iter = 0; int status = 0; double finalCostFuncVal = 0.0; double dof = static_cast<double>(nData - nParam); // dof stands for degrees of freedom // Standard least-squares used if derivative function defined otherwise simplex if ( methodUsed.compare("Simplex") != 0 ) { status = GSL_CONTINUE; while (status == GSL_CONTINUE && iter < maxInterations) { iter++; status = minimizer->iterate(); if (status != GSL_SUCCESS && minimizer->hasConverged() != GSL_SUCCESS) { // From experience it is found that gsl_multifit_fdfsolver_iterate occasionally get // stock - even after having achieved a sensible fit. This seem in particular to be a // problem on Linux. For now only fall back to Simplex if iter = 1 or 2, i.e. // gsl_multifit_fdfsolver_iterate has failed on the first or second hurdle if (iter < 3) { g_log.warning() << "GenericFit algorithm using " << methodUsed << " failed " << "reporting the following: " << gsl_strerror(status) << "\n" << "Try using Simplex method instead\n"; methodUsed = "Simplex"; delete minimizer; minimizer = FuncMinimizerFactory::Instance().createUnwrapped(methodUsed); minimizer->initialize(m_function.get(), costFunction); iter = 0; } break; } status = minimizer->hasConverged(); prog.report("Iteration "+boost::lexical_cast<std::string>(iter)); } finalCostFuncVal = minimizer->costFunctionVal() / dof; } if ( methodUsed.compare("Simplex") == 0 ) { status = GSL_CONTINUE; while (status == GSL_CONTINUE && iter < maxInterations) { iter++; status = minimizer->iterate(); if (status) // break if error { // if failed at first iteration try reducing the initial step size if (iter == 1) { g_log.information() << "Simplex step size reduced to 0.1\n"; delete minimizer; SimplexMinimizer* sm = new SimplexMinimizer; sm->initialize(m_function.get(), costFunction); sm->resetSize(0.1, m_function.get(), costFunction); minimizer = sm; status = GSL_CONTINUE; continue; } break; } status = minimizer->hasConverged(); prog.report("Iteration "+boost::lexical_cast<std::string>(iter)); } finalCostFuncVal = minimizer->costFunctionVal() / dof; } // Output summary to log file std::string reportOfFit = gsl_strerror(status); g_log.information() << "Method used = " << methodUsed << "\n" << "Iteration = " << iter << "\n"; Mantid::API::ICostFunction* costfun = Mantid::API::CostFunctionFactory::Instance().createUnwrapped(costFunction); if ( reportOfFit == "success" ) g_log.notice() << reportOfFit << " " << costfun->shortName() << " (" << costfun->name() << ") = " << finalCostFuncVal << "\n"; else g_log.warning() << reportOfFit << " " << costfun->shortName() << " (" << costfun->name() << ") = " << finalCostFuncVal << "\n"; for (size_t i = 0; i < m_function->nParams(); i++) { g_log.debug() << m_function->parameterName(i) << " = " << m_function->getParameter(i) << " \n"; } // also output summary to properties setProperty("OutputStatus", reportOfFit); setProperty("OutputChi2overDoF", finalCostFuncVal); setProperty("Minimizer", methodUsed); setPropertyValue("Function",*m_function); // if Output property is specified output additional workspaces std::vector<double> standardDeviations; std::string output = getProperty("Output"); gsl_matrix *covar(NULL); // only if derivative is defined for fitting function create covariance matrix output workspace if ( isDerivDefined ) { // calculate covariance matrix covar = gsl_matrix_alloc (nParam, nParam); minimizer->calCovarianceMatrix( 0.0, covar); // take standard deviations to be the square root of the diagonal elements of // the covariance matrix int iPNotFixed = 0; for(size_t i=0; i < m_function->nParams(); i++) { standardDeviations.push_back(1.0); if (m_function->isActive(i)) { standardDeviations[i] = sqrt(gsl_matrix_get(covar,iPNotFixed,iPNotFixed)); if (m_function->activeParameter(iPNotFixed) != m_function->getParameter(m_function->indexOfActive(iPNotFixed))) {// it means the active param is not the same as declared but transformed standardDeviations[i] *= fabs(transformationDerivative(iPNotFixed)); } iPNotFixed++; } } } if (!output.empty()) { // only if derivative is defined for fitting function create covariance matrix output workspace if ( isDerivDefined ) { // Create covariance matrix output workspace declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputNormalisedCovarianceMatrix","",Direction::Output), "The name of the TableWorkspace in which to store the final covariance matrix" ); setPropertyValue("OutputNormalisedCovarianceMatrix",output+"_NormalisedCovarianceMatrix"); Mantid::API::ITableWorkspace_sptr m_covariance = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_covariance->addColumn("str","Name"); std::vector<std::string> paramThatAreFitted; // used for populating 1st "name" column for(size_t i=0; i < m_function->nParams(); i++) { if (m_function->isActive(i)) { m_covariance->addColumn("double",m_function->parameterName(i)); paramThatAreFitted.push_back(m_function->parameterName(i)); } } for(size_t i=0; i<nParam; i++) { Mantid::API::TableRow row = m_covariance->appendRow(); row << paramThatAreFitted[i]; for(size_t j=0; j<nParam; j++) { if (j == i) row << 100.0; else { row << 100.0*gsl_matrix_get(covar,i,j)/sqrt(gsl_matrix_get(covar,i,i)*gsl_matrix_get(covar,j,j)); } } } setProperty("OutputNormalisedCovarianceMatrix",m_covariance); } // create output parameter table workspace to store final fit parameters // including error estimates if derivative of fitting function defined declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputParameters","",Direction::Output), "The name of the TableWorkspace in which to store the final fit parameters" ); setPropertyValue("OutputParameters",output+"_Parameters"); Mantid::API::ITableWorkspace_sptr m_result = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_result->addColumn("str","Name"); m_result->addColumn("double","Value"); if ( isDerivDefined ) m_result->addColumn("double","Error"); for(size_t i=0;i<m_function->nParams();i++) { Mantid::API::TableRow row = m_result->appendRow(); row << m_function->parameterName(i) << m_function->getParameter(i); if ( isDerivDefined && m_function->isActive(i)) { row << standardDeviations[i]; } } // Add chi-squared value at the end of parameter table Mantid::API::TableRow row = m_result->appendRow(); row << "Cost function value" << finalCostFuncVal; setProperty("OutputParameters",m_result); if ( isDerivDefined ) gsl_matrix_free(covar); } // Add Parameters, Errors and ParameterNames properties to output so they can be queried on the algorithm. declareProperty(new ArrayProperty<double> ("Parameters",new NullValidator<std::vector<double> >,Direction::Output)); declareProperty(new ArrayProperty<double> ("Errors",new NullValidator<std::vector<double> >,Direction::Output)); declareProperty(new ArrayProperty<std::string> ("ParameterNames",new NullValidator<std::vector<std::string> >,Direction::Output)); std::vector<double> params,errors; std::vector<std::string> parNames; for(size_t i=0;i<m_function->nParams();i++) { parNames.push_back(m_function->parameterName(i)); params.push_back(m_function->getParameter(i)); if (!standardDeviations.empty()) { errors.push_back(standardDeviations[i]); } else { errors.push_back(0.); } } setProperty("Parameters",params); setProperty("Errors",errors); setProperty("ParameterNames",parNames); // minimizer may have dynamically allocated memory hence make sure this memory is freed up delete minimizer; return; }
void HFIRDarkCurrentSubtraction::exec() { std::string output_message = ""; // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } // If the load algorithm isn't in the reduction properties, add it const bool persistent = getProperty("PersistentCorrection"); if (!reductionManager->existsProperty("DarkCurrentAlgorithm") && persistent) { AlgorithmProperty *algProp = new AlgorithmProperty("DarkCurrentAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(algProp); } Progress progress(this,0.0,1.0,10); MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); const std::string fileName = getPropertyValue("Filename"); MatrixWorkspace_sptr darkWS; std::string darkWSName = getPropertyValue("OutputDarkCurrentWorkspace"); progress.report("Subtracting dark current"); // Look for an entry for the dark current in the reduction table Poco::Path path(fileName); const std::string entryName = "DarkCurrent"+path.getBaseName(); if (reductionManager->existsProperty(entryName)) { darkWS = reductionManager->getProperty(entryName); darkWSName = reductionManager->getPropertyValue(entryName); output_message += darkWSName + '\n'; } else { // Load the dark current if we don't have it already if (darkWSName.size()==0) { darkWSName = "__dark_current_"+path.getBaseName(); setPropertyValue("OutputDarkCurrentWorkspace", darkWSName); } IAlgorithm_sptr loadAlg; if (!reductionManager->existsProperty("LoadAlgorithm")) { loadAlg = createChildAlgorithm("HFIRLoad", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); loadAlg->setProperty("ReductionProperties", reductionManagerName); loadAlg->executeAsChildAlg(); } else { IAlgorithm_sptr loadAlg0 = reductionManager->getProperty("LoadAlgorithm"); const std::string loadString = loadAlg0->toString(); loadAlg = Algorithm::fromString(loadString); loadAlg->setChild(true); loadAlg->setProperty("Filename", fileName); loadAlg->setProperty("ReductionProperties", reductionManagerName); loadAlg->setPropertyValue("OutputWorkspace", darkWSName); loadAlg->execute(); } darkWS = loadAlg->getProperty("OutputWorkspace"); output_message += "\n Loaded " + fileName + "\n"; if (loadAlg->existsProperty("OutputMessage")) { std::string msg = loadAlg->getPropertyValue("OutputMessage"); output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } setProperty("OutputDarkCurrentWorkspace", darkWS); reductionManager->declareProperty(new WorkspaceProperty<>(entryName,"",Direction::Output)); reductionManager->setPropertyValue(entryName, darkWSName); reductionManager->setProperty(entryName, darkWS); } progress.report(3, "Loaded dark current"); // Perform subtraction double darkTimer = getCountingTime(darkWS); double dataTimer = getCountingTime(inputWS); IAlgorithm_sptr scaleAlg = createChildAlgorithm("Scale", 0.3, 0.5); scaleAlg->setProperty("InputWorkspace", darkWS); scaleAlg->setProperty("Factor", dataTimer/darkTimer); scaleAlg->setProperty("Operation", "Multiply"); scaleAlg->executeAsChildAlg(); MatrixWorkspace_sptr scaledDarkWS = scaleAlg->getProperty("OutputWorkspace"); // Zero out timer and monitor so that we don't subtract them out for(size_t i=0; i<scaledDarkWS->dataY(0).size(); i++) { scaledDarkWS->dataY(DEFAULT_TIMER_ID)[i]=0.0; scaledDarkWS->dataE(DEFAULT_TIMER_ID)[i]=0.0; scaledDarkWS->dataY(DEFAULT_MONITOR_ID)[i]=0.0; scaledDarkWS->dataE(DEFAULT_MONITOR_ID)[i]=0.0; } IAlgorithm_sptr minusAlg = createChildAlgorithm("Minus", 0.5, 0.7); minusAlg->setProperty("LHSWorkspace", inputWS); minusAlg->setProperty("RHSWorkspace", scaledDarkWS); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); minusAlg->setProperty("OutputWorkspace", outputWS); minusAlg->executeAsChildAlg(); MatrixWorkspace_sptr correctedWS = minusAlg->getProperty("OutputWorkspace"); setProperty("OutputWorkspace", correctedWS); setProperty("OutputMessage", "Dark current subtracted: "+output_message); progress.report("Subtracted dark current"); }
AnimatableValueKeyframe::AnimatableValueKeyframe(const AnimatableValueKeyframe& copyFrom) : Keyframe(copyFrom.m_offset, copyFrom.m_composite, copyFrom.m_easing) { for (PropertyValueMap::const_iterator iter = copyFrom.m_propertyValues.begin(); iter != copyFrom.m_propertyValues.end(); ++iter) setPropertyValue(iter->key, iter->value.get()); }
bool CameraGigeSdkIc::grabSingleImage(Frame &frame, int camID){ // Retrieve a list with the video capture devices connected to the computer. DShowLib::Grabber::tVidCapDevListPtr pVidCapDevList = m_pGrabber->getAvailableVideoCaptureDevices(); if(pVidCapDevList == 0 || pVidCapDevList->empty()){ cout << "No device available." << endl; return false; }else{ // Print available devices. int numCam = -1; for(int i = 0; i < pVidCapDevList->size(); i++){ cout << "(" << i << ") " << pVidCapDevList->at(i).c_str() << endl; if(camID == i){ numCam = i; break; } } if(numCam == -1){ return false; }else{ // Open the selected video capture device. m_pGrabber->openDev(pVidCapDevList->at(numCam)); /*cout << "Available video formats : " << endl; DShowLib::Grabber::tVidFmtDescListPtr DecriptionList; DecriptionList = m_pGrabber->getAvailableVideoFormatDescs(); for( DShowLib::Grabber::tVidFmtDescList::iterator pDescription = DecriptionList->begin(); pDescription != DecriptionList->end(); pDescription++ ) { printf("%s\n", (*pDescription)->toString().c_str()); }*/ DShowLib::tFrameHandlerSinkPtr pSink; cout << "Current bits per pixel : " << m_pGrabber->getVideoFormat().getBitsPerPixel() << endl; switch(frame.getBitDepth()){ case MONO_8 : m_pGrabber->setVideoFormat("Y8 (1280x960-1280x960)"); // Set the image buffer format to eY800. eY800 means monochrome, 8 bits (1 byte) per pixel. // Let the sink create a matching MemBufferCollection with 1 buffer. pSink = DShowLib::FrameHandlerSink::create( DShowLib::eY800, 1 ); break; case MONO_12 : m_pGrabber->setVideoFormat("Y16 (1280x960-1280x960)"); // Disable overlay. // http://www.theimagingsourceforums.com/archive/index.php/t-319880.html m_pGrabber->setOverlayBitmapPathPosition(DShowLib::ePP_NONE); // Set the image buffer format to eY16. eY16 means monochrome, 16 bits (2 byte) per pixel. // Let the sink create a matching MemBufferCollection with 1 buffer. pSink = DShowLib::FrameHandlerSink::create( DShowLib::eY16, 1 ); break; default: return false; break; } cout << "New video format : " << m_pGrabber->getVideoFormat().getBitsPerPixel() << endl; // Get properties. _DSHOWLIB_NAMESPACE::tIVCDPropertyItemsPtr pItems = m_pGrabber->getAvailableVCDProperties(); // Set Exposure time. int exposure = frame.getExposure(); long eMin = getPropertyRangeMin(DShowLib::VCDID_Exposure, pItems); long eMax = getPropertyRangeMax(DShowLib::VCDID_Exposure, pItems); long e = getPropertyValue(DShowLib::VCDID_Exposure, pItems); cout << "Previous exposure time value : " << e << endl; if(exposure <= eMax && exposure >= eMin){ setPropertyValue(DShowLib::VCDID_Exposure, (long)exposure, pItems); cout << "New exposure time value : " << getPropertyValue(DShowLib::VCDID_Exposure, pItems) << endl; }else{ cout << "Fail to set exposure. Available range value is " << eMin << " to " << eMax << endl; return false; } // Set Gain (db) int gain = frame.getGain(); long gMin = getPropertyRangeMin(DShowLib::VCDID_Gain, pItems); long gMax = getPropertyRangeMax(DShowLib::VCDID_Gain, pItems); long g = getPropertyValue(DShowLib::VCDID_Gain, pItems); cout << "Previous gain value : " << g << endl; if(gain <= gMax && gain >= gMin){ setPropertyValue(DShowLib::VCDID_Gain, (long)gain, pItems); cout << "New gain value : " << getPropertyValue(DShowLib::VCDID_Gain, pItems) << endl; }else{ cout << "Fail to set gain. Available range value is " << gMin << " to " << gMax << endl; return false; } // Set the sink. m_pGrabber->setSinkType(pSink); // We use snap mode. pSink->setSnapMode(true); // Prepare the live mode, to get the output size if the sink. if(!m_pGrabber->prepareLive(false)){ std::cerr << "Could not render the VideoFormat into a eY800 sink."; return false; } // Retrieve the output type and dimension of the handler sink. // The dimension of the sink could be different from the VideoFormat, when // you use filters. DShowLib::FrameTypeInfo info; pSink->getOutputFrameType(info); cout << info.getBitsPerPixel() << endl; Mat newImg; DShowLib::Grabber::tMemBufferCollectionPtr pCollection; switch(info.getBitsPerPixel()){ case 8 : { newImg = Mat(info.dim.cy, info.dim.cx, CV_8UC1, Scalar(0)); BYTE* pBuf[1]; // Allocate image buffers of the above calculate buffer size. pBuf[0] = new BYTE[info.buffersize]; // Create a new MemBuffer collection that uses our own image buffers. pCollection = DShowLib::MemBufferCollection::create( info, 1, pBuf ); if( pCollection == 0 || !pSink->setMemBufferCollection(pCollection)){ std::cerr << "Could not set the new MemBufferCollection, because types do not match."; return false; } m_pGrabber->startLive(false); pSink->snapImages(1); memcpy(newImg.ptr(), pBuf[0], info.buffersize); } break; case 16 : { newImg = Mat(info.dim.cy, info.dim.cx, CV_16UC1, Scalar(0)); BYTE * pBuf[1]; // Allocate image buffers of the above calculate buffer size. pBuf[0] = new BYTE[info.buffersize]; // Create a new MemBuffer collection that uses our own image buffers. pCollection = DShowLib::MemBufferCollection::create(info, 1, pBuf); if(pCollection == 0 || !pSink->setMemBufferCollection(pCollection)){ std::cerr << "Could not set the new MemBufferCollection, because types do not match."; return false; } m_pGrabber->startLive(false); pSink->snapImages(1); memcpy(newImg.ptr(), pBuf[0], info.buffersize); } break; default: return false; break; } m_pGrabber->stopLive(); m_pGrabber->closeDev(); //Timestamping. string acquisitionDate = TimeDate::localDateTime(microsec_clock::universal_time(),"%Y:%m:%d:%H:%M:%S"); boost::posix_time::ptime time = boost::posix_time::microsec_clock::universal_time(); string acqDateInMicrosec = to_iso_extended_string(time); frame = Frame(newImg, 0, 0, acquisitionDate); frame.setAcqDateMicro(acqDateInMicrosec); frame.setFPS(0); //cout << "save " << endl; //pCollection->save( "yio*.bmp" ); double minVal, maxVal; minMaxLoc(newImg, &minVal, &maxVal); cout << "minVal :" << minVal << endl; cout << "maxVal :" << maxVal << endl; unsigned short * ptr; double t = (double)getTickCount(); for(int i = 0; i < newImg.rows; i++){ ptr = newImg.ptr<unsigned short>(i); for(int j = 0; j < newImg.cols; j++){ ptr[j] = ptr[j] >> 4; } } t = (((double)getTickCount() - t )/getTickFrequency())*1000; cout << "time decalage : " << t << endl; minMaxLoc(newImg, &minVal, &maxVal); cout << "minVal :" << minVal << endl; cout << "maxVal :" << maxVal << endl; } } return true; }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void Fit1D::exec() { // Custom initialization prepare(); // check if derivative defined in derived class bool isDerivDefined = true; gsl_matrix * M = NULL; try { const std::vector<double> inTest(m_parameterNames.size(),1.0); std::vector<double> outTest(m_parameterNames.size()); const double xValuesTest = 0; JacobianImpl J; M = gsl_matrix_alloc(m_parameterNames.size(),1); J.setJ(M); // note nData set to zero (last argument) hence this should avoid further memory problems functionDeriv(&(inTest.front()), &J, &xValuesTest, 0); } catch (Exception::NotImplementedError&) { isDerivDefined = false; } gsl_matrix_free(M); // Try to retrieve optional properties int histNumber = getProperty("WorkspaceIndex"); const int maxInterations = getProperty("MaxIterations"); // Get the input workspace MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace"); // number of histogram is equal to the number of spectra const size_t numberOfSpectra = localworkspace->getNumberHistograms(); // Check that the index given is valid if ( histNumber >= static_cast<int>(numberOfSpectra) ) { g_log.warning("Invalid Workspace index given, using first Workspace"); histNumber = 0; } // Retrieve the spectrum into a vector const MantidVec& XValues = localworkspace->readX(histNumber); const MantidVec& YValues = localworkspace->readY(histNumber); const MantidVec& YErrors = localworkspace->readE(histNumber); //Read in the fitting range data that we were sent double startX = getProperty("StartX"); double endX = getProperty("EndX"); //check if the values had been set, otherwise use defaults if ( isEmpty( startX ) ) { startX = XValues.front(); modifyStartOfRange(startX); // does nothing by default but derived class may provide a more intelligent value } if ( isEmpty( endX ) ) { endX = XValues.back(); modifyEndOfRange(endX); // does nothing by default but derived class may previde a more intelligent value } int m_minX; int m_maxX; // Check the validity of startX if ( startX < XValues.front() ) { g_log.warning("StartX out of range! Set to start of frame."); startX = XValues.front(); } // Get the corresponding bin boundary that comes before (or coincides with) this value for (m_minX = 0; XValues[m_minX+1] < startX; ++m_minX) {} // Check the validity of endX and get the bin boundary that come after (or coincides with) it if ( endX >= XValues.back() || endX < startX ) { g_log.warning("EndX out of range! Set to end of frame"); endX = XValues.back(); m_maxX = static_cast<int>(YValues.size()); } else { for (m_maxX = m_minX; XValues[m_maxX] < endX; ++m_maxX) {} } afterDataRangedDetermined(m_minX, m_maxX); // create and populate GSL data container warn user if l_data.n < l_data.p // since as a rule of thumb this is required as a minimum to obtained 'accurate' // fitting parameter values. FitData l_data(this,getProperty("Fix")); l_data.n = m_maxX - m_minX; // m_minX and m_maxX are array index markers. I.e. e.g. 0 & 19. if (l_data.n == 0) { g_log.error("The data set is empty."); throw std::runtime_error("The data set is empty."); } if (l_data.n < l_data.p) { g_log.error("Number of data points less than number of parameters to be fitted."); throw std::runtime_error("Number of data points less than number of parameters to be fitted."); } l_data.X = new double[l_data.n]; l_data.sigmaData = new double[l_data.n]; l_data.forSimplexLSwrap = new double[l_data.n]; l_data.parameters = new double[nParams()]; // check if histogram data in which case use mid points of histogram bins const bool isHistogram = localworkspace->isHistogramData(); for (unsigned int i = 0; i < l_data.n; ++i) { if (isHistogram) l_data.X[i] = 0.5*(XValues[m_minX+i]+XValues[m_minX+i+1]); // take mid-point if histogram bin else l_data.X[i] = XValues[m_minX+i]; } l_data.Y = &YValues[m_minX]; // check that no error is negative or zero for (unsigned int i = 0; i < l_data.n; ++i) { if (YErrors[m_minX+i] <= 0.0) { l_data.sigmaData[i] = 1.0; } else l_data.sigmaData[i] = YErrors[m_minX+i]; } // create array of fitted parameter. Take these to those input by the user. However, for doing the // underlying fitting it might be more efficient to actually perform the fitting on some of other // form of the fitted parameters. For instance, take the Gaussian sigma parameter. In practice it // in fact more efficient to perform the fitting not on sigma but 1/sigma^2. The methods // modifyInitialFittedParameters() and modifyFinalFittedParameters() are used to allow for this; // by default these function do nothing. m_fittedParameter.clear(); for (size_t i = 0; i < nParams(); i++) { m_fittedParameter.push_back(getProperty(m_parameterNames[i])); } modifyInitialFittedParameters(m_fittedParameter); // does nothing except if overwritten by derived class for (size_t i = 0; i < nParams(); i++) { l_data.parameters[i] = m_fittedParameter[i]; } // set-up initial guess for fit parameters gsl_vector *initFuncArg; initFuncArg = gsl_vector_alloc(l_data.p); for (size_t i = 0,j = 0; i < nParams(); i++) { if (l_data.active[i]) gsl_vector_set(initFuncArg, j++, m_fittedParameter[i]); } // set-up GSL container to be used with GSL simplex algorithm gsl_multimin_function gslSimplexContainer; gslSimplexContainer.n = l_data.p; // n here refers to number of parameters gslSimplexContainer.f = &gsl_costFunction; gslSimplexContainer.params = &l_data; // set-up GSL least squares container gsl_multifit_function_fdf f; f.f = &gsl_f; f.df = &gsl_df; f.fdf = &gsl_fdf; f.n = l_data.n; f.p = l_data.p; f.params = &l_data; // set-up remaining GSL machinery for least squared const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; gsl_multifit_fdfsolver *s = NULL; if (isDerivDefined) { s = gsl_multifit_fdfsolver_alloc(T, l_data.n, l_data.p); gsl_multifit_fdfsolver_set(s, &f, initFuncArg); } // set-up remaining GSL machinery to use simplex algorithm const gsl_multimin_fminimizer_type *simplexType = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *simplexMinimizer = NULL; gsl_vector *simplexStepSize = NULL; if (!isDerivDefined) { simplexMinimizer = gsl_multimin_fminimizer_alloc(simplexType, l_data.p); simplexStepSize = gsl_vector_alloc(l_data.p); gsl_vector_set_all (simplexStepSize, 1.0); // is this always a sensible starting step size? gsl_multimin_fminimizer_set(simplexMinimizer, &gslSimplexContainer, initFuncArg, simplexStepSize); } // finally do the fitting int iter = 0; int status; double size; // for simplex algorithm double finalCostFuncVal; double dof = static_cast<double>(l_data.n - l_data.p); // dof stands for degrees of freedom // Standard least-squares used if derivative function defined otherwise simplex Progress prog(this,0.0,1.0,maxInterations); if (isDerivDefined) { do { iter++; status = gsl_multifit_fdfsolver_iterate(s); if (status) // break if error break; status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); double chi = gsl_blas_dnrm2(s->f); finalCostFuncVal = chi*chi / dof; // put final converged fitting values back into m_fittedParameter for (size_t i = 0, j = 0; i < nParams(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(s->x,j++); } else { do { iter++; status = gsl_multimin_fminimizer_iterate(simplexMinimizer); if (status) // break if error break; size = gsl_multimin_fminimizer_size(simplexMinimizer); status = gsl_multimin_test_size(size, 1e-2); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); finalCostFuncVal = simplexMinimizer->fval / dof; // put final converged fitting values back into m_fittedParameter for (unsigned int i = 0, j = 0; i < m_fittedParameter.size(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(simplexMinimizer->x,j++); } modifyFinalFittedParameters(m_fittedParameter); // do nothing except if overwritten by derived class // Output summary to log file std::string reportOfFit = gsl_strerror(status); g_log.information() << "Iteration = " << iter << "\n" << "Status = " << reportOfFit << "\n" << "Chi^2/DoF = " << finalCostFuncVal << "\n"; for (size_t i = 0; i < m_fittedParameter.size(); i++) g_log.information() << m_parameterNames[i] << " = " << m_fittedParameter[i] << " \n"; // also output summary to properties setProperty("OutputStatus", reportOfFit); setProperty("OutputChi2overDoF", finalCostFuncVal); for (size_t i = 0; i < m_fittedParameter.size(); i++) setProperty(m_parameterNames[i], m_fittedParameter[i]); std::string output = getProperty("Output"); if (!output.empty()) { // calculate covariance matrix if derivatives available gsl_matrix *covar(NULL); std::vector<double> standardDeviations; std::vector<double> sdExtended; if (isDerivDefined) { covar = gsl_matrix_alloc (l_data.p, l_data.p); gsl_multifit_covar (s->J, 0.0, covar); int iPNotFixed = 0; for(size_t i=0;i<nParams();i++) { sdExtended.push_back(1.0); if (l_data.active[i]) { sdExtended[i] = sqrt(gsl_matrix_get(covar,iPNotFixed,iPNotFixed)); iPNotFixed++; } } modifyFinalFittedParameters(sdExtended); for(size_t i=0;i<nParams();i++) if (l_data.active[i]) standardDeviations.push_back(sdExtended[i]); declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputNormalisedCovarianceMatrix","",Direction::Output), "The name of the TableWorkspace in which to store the final covariance matrix" ); setPropertyValue("OutputNormalisedCovarianceMatrix",output+"_NormalisedCovarianceMatrix"); Mantid::API::ITableWorkspace_sptr m_covariance = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_covariance->addColumn("str","Name"); std::vector<std::string> paramThatAreFitted; // used for populating 1st "name" column for(size_t i=0;i<nParams();i++) { if (l_data.active[i]) { m_covariance->addColumn("double",m_parameterNames[i]); paramThatAreFitted.push_back(m_parameterNames[i]); } } for(size_t i=0;i<l_data.p;i++) { Mantid::API::TableRow row = m_covariance->appendRow(); row << paramThatAreFitted[i]; for(size_t j=0;j<l_data.p;j++) { if (j == i) row << 1.0; else { row << 100.0*gsl_matrix_get(covar,i,j)/sqrt(gsl_matrix_get(covar,i,i)*gsl_matrix_get(covar,j,j)); } } } setProperty("OutputNormalisedCovarianceMatrix",m_covariance); } declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputParameters","",Direction::Output), "The name of the TableWorkspace in which to store the final fit parameters" ); declareProperty(new WorkspaceProperty<MatrixWorkspace>("OutputWorkspace","",Direction::Output), "Name of the output Workspace holding resulting simlated spectrum"); setPropertyValue("OutputParameters",output+"_Parameters"); setPropertyValue("OutputWorkspace",output+"_Workspace"); // Save the final fit parameters in the output table workspace Mantid::API::ITableWorkspace_sptr m_result = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_result->addColumn("str","Name"); m_result->addColumn("double","Value"); if (isDerivDefined) m_result->addColumn("double","Error"); Mantid::API::TableRow row = m_result->appendRow(); row << "Chi^2/DoF" << finalCostFuncVal; for(size_t i=0;i<nParams();i++) { Mantid::API::TableRow row = m_result->appendRow(); row << m_parameterNames[i] << m_fittedParameter[i]; if (isDerivDefined && l_data.active[i]) { // perhaps want to scale standard deviations with sqrt(finalCostFuncVal) row << sdExtended[i]; } } setProperty("OutputParameters",m_result); // Save the fitted and simulated spectra in the output workspace MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); int iSpec = getProperty("WorkspaceIndex"); const MantidVec& inputX = inputWorkspace->readX(iSpec); const MantidVec& inputY = inputWorkspace->readY(iSpec); int histN = isHistogram ? 1 : 0; Mantid::DataObjects::Workspace2D_sptr ws = boost::dynamic_pointer_cast<Mantid::DataObjects::Workspace2D> ( Mantid::API::WorkspaceFactory::Instance().create( "Workspace2D", 3, l_data.n + histN, l_data.n) ); ws->setTitle(""); ws->getAxis(0)->unit() = inputWorkspace->getAxis(0)->unit();// UnitFactory::Instance().create("TOF"); for(int i=0;i<3;i++) ws->dataX(i).assign(inputX.begin()+m_minX,inputX.begin()+m_maxX+histN); ws->dataY(0).assign(inputY.begin()+m_minX,inputY.begin()+m_maxX); MantidVec& Y = ws->dataY(1); MantidVec& E = ws->dataY(2); double* lOut = new double[l_data.n]; // to capture output from call to function() modifyInitialFittedParameters(m_fittedParameter); // does nothing except if overwritten by derived class function(&m_fittedParameter[0], lOut, l_data.X, l_data.n); modifyInitialFittedParameters(m_fittedParameter); // reverse the effect of modifyInitialFittedParameters - if any for(unsigned int i=0; i<l_data.n; i++) { Y[i] = lOut[i]; E[i] = l_data.Y[i] - Y[i]; } delete [] lOut; setProperty("OutputWorkspace",boost::dynamic_pointer_cast<MatrixWorkspace>(ws)); if (isDerivDefined) gsl_matrix_free(covar); } // clean up dynamically allocated gsl stuff if (isDerivDefined) gsl_multifit_fdfsolver_free(s); else { gsl_vector_free(simplexStepSize); gsl_multimin_fminimizer_free(simplexMinimizer); } delete [] l_data.X; delete [] l_data.sigmaData; delete [] l_data.forSimplexLSwrap; delete [] l_data.parameters; gsl_vector_free (initFuncArg); return; }
// test the size() function for various types of set and append of object to // the response data object. Test set and append of single type. void testSizeMethod() { // Test with a variety of object types in the From ResponseData // Build the class CIMClass CIMclass1 = buildClass(); // Build a CIM Instance. NOTE: key is defaulted in class CIMInstance CIMInst1 = CIMclass1.buildInstance(true, true, CIMPropertyList()); // Clone the instance and change key CIMInstance CIMInst2 = CIMInst1.clone(); setPropertyValue(CIMInst2, "id", 2); CIMInstance CIMInst3 = CIMInst1.clone(); setPropertyValue(CIMInst3, "id", 3); CIMInstance CIMInst4 = CIMInst1.clone(); setPropertyValue(CIMInst4, "id", 4); // build CIMInstance array Array<CIMInstance> CIMInstArray; CIMInstArray.append(CIMInst1); CIMInstArray.append(CIMInst2); CIMInstArray.append(CIMInst3); CIMInstArray.append(CIMInst3); // Build SCMO instances SCMOClass SCMO_CSClass(CIMclass1); VCOUT << "Creating SCMOInstance from CIMInstance" << endl; SCMOInstance SCMO_CSInstance3(SCMO_CSClass,CIMInst3); SCMOInstance SCMO_CSInstance4(SCMO_CSClass,CIMInst4); // Create array of 2 SCMO Instances Array<SCMOInstance> SCMOInstArray; SCMOInstArray.append(SCMO_CSInstance3); SCMOInstArray.append(SCMO_CSInstance4); // tests with CIM objects (C++ Interface) { CIMResponseData crd = CIMResponseData(CIMResponseData::RESP_INSTANCES); crd.setInstances(CIMInstArray); PEGASUS_TEST_ASSERT(crd.size() == 4); crd.appendInstances(CIMInstArray); PEGASUS_TEST_ASSERT(crd.size() == 8); crd.appendInstance(CIMInst1); PEGASUS_TEST_ASSERT(crd.size() == 9); crd.appendSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd.size() == 11); PEGASUS_TEST_ASSERT(crd.valid()); } { CIMResponseData crd = CIMResponseData(CIMResponseData::RESP_INSTANCES); crd.setInstance(CIMInst1); PEGASUS_TEST_ASSERT(crd.size() == 1); crd.appendInstances(CIMInstArray); PEGASUS_TEST_ASSERT(crd.size() == 5); crd.appendInstance(CIMInst1); PEGASUS_TEST_ASSERT(crd.size() == 6); crd.appendSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd.size() == 8); PEGASUS_TEST_ASSERT(crd.valid()); } // test with objects { CIMResponseData crd = CIMResponseData(CIMResponseData::RESP_OBJECTS); Array<CIMObject> x; x.append((CIMObject)CIMInst1); x.append((CIMObject)CIMInst2); // Append an array of CIMInstances crd.setObjects(x); PEGASUS_TEST_ASSERT(crd.size() == 2); crd.appendObject((CIMObject)CIMInst1); PEGASUS_TEST_ASSERT(crd.size() == 3); PEGASUS_TEST_ASSERT(crd.valid()); } // test with SCMOInst { CIMResponseData crd = CIMResponseData(CIMResponseData::RESP_INSTANCES); crd.setSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd.size() == 2); crd.appendSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd.size() == 4); PEGASUS_TEST_ASSERT(crd.valid()); } { // Create array of 2 SCMO Instances Array<SCMOInstance> SCMOInstArray; SCMOInstArray.append(SCMO_CSInstance3); SCMOInstArray.append(SCMO_CSInstance4); CIMResponseData crd = CIMResponseData(CIMResponseData::RESP_INSTANCES); crd.appendSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd.size() == 2); crd.appendSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd.size() == 4); PEGASUS_TEST_ASSERT(crd.valid()); } // Test with path objects String s1 = "//atp:77/root/cimv25:" "TennisPlayer.last=\"Rafter\",first=\"Patrick\""; String s2 = "//atp:77/root/cimv25:" "TennisPlayer.first=\"Patrick\",last=\"Rafter\""; CIMObjectPath r1 = s1; CIMObjectPath r2 = s2; Array<CIMObjectPath> refArray; refArray.append(r1); refArray.append(r2); refArray.append(r1); refArray.append(r2); CIMResponseData crd = CIMResponseData(CIMResponseData::RESP_OBJECTPATHS); crd.setInstanceNames(refArray); PEGASUS_TEST_ASSERT(crd.size() == 4); PEGASUS_TEST_ASSERT(crd.valid()); // KS_TBD There is not appendinstancenames today in ResponseData //crd.appendInstanceNames(refArray); // Test with XML and binary { } }
void FontFace::setPropertyFromString(const Document* document, const String& s, CSSPropertyID propertyID, ExceptionState& exceptionState) { RefPtrWillBeRawPtr<CSSValue> value = parseCSSValue(document, s, propertyID); if (!value || !setPropertyValue(value, propertyID)) exceptionState.throwDOMException(SyntaxError, "Failed to set '" + s + "' as a property value."); }
// test size method and moveObjects method void test02() { // Test with a variety of object types in the From ResponseData // Build the class CIMClass CIMclass1 = buildClass(); // Build a CIM Instance. NOTE: key is defaulted in class CIMInstance CIMInst1 = CIMclass1.buildInstance(true, true, CIMPropertyList()); // Clone the instance and change key CIMInstance CIMInst2 = CIMInst1.clone(); setPropertyValue(CIMInst2, "id", 2); CIMInstance CIMInst3 = CIMInst1.clone(); setPropertyValue(CIMInst3, "id", 3); CIMInstance CIMInst4 = CIMInst1.clone(); setPropertyValue(CIMInst4, "id", 4); // build CIMInstance array Array<CIMInstance> CIMInstArray; CIMInstArray.append(CIMInst1); CIMInstArray.append(CIMInst2); // Build SCMO instances SCMOClass SCMO_CSClass(CIMclass1); VCOUT << "Creating SCMOInstance from CIMInstance" << endl; SCMOInstance SCMO_CSInstance3(SCMO_CSClass,CIMInst3); SCMOInstance SCMO_CSInstance4(SCMO_CSClass,CIMInst4); // Create array of 2 SCMO Instances Array<SCMOInstance> SCMOInstArray; SCMOInstArray.append(SCMO_CSInstance3); SCMOInstArray.append(SCMO_CSInstance4); // Create CIMReponseData object CIMResponseData crd1 = CIMResponseData(CIMResponseData::RESP_INSTANCES); PEGASUS_TEST_ASSERT(crd1.valid()); // set SCMO array into the object crd1.setSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd1.valid()); VCOUT << crd1.size() << endl; PEGASUS_TEST_ASSERT(crd1.size() == 2); // append a CIM Instance crd1.appendInstance(CIMInst1); PEGASUS_TEST_ASSERT(crd1.valid()); VCOUT << crd1.size() << endl; PEGASUS_TEST_ASSERT(crd1.size() == 3); // Append an array of CIMInstances crd1.appendInstances(CIMInstArray); PEGASUS_TEST_ASSERT(crd1.valid()); VCOUT << crd1.size() << endl; PEGASUS_TEST_ASSERT(crd1.size() == 5); CIMResponseData crdTo = CIMResponseData(CIMResponseData::RESP_INSTANCES); VCOUT << "Before from = " << crd1.size() << ", to = " << crdTo.size() << endl; PEGASUS_TEST_ASSERT(crdTo.valid()); Uint32 rtn = crdTo.moveObjects(crd1, 3); VCOUT << "After from = " << crd1.size() << ", to = " << crdTo.size() << endl; PEGASUS_TEST_ASSERT(crdTo.valid()); PEGASUS_TEST_ASSERT(crd1.valid()); PEGASUS_TEST_ASSERT(rtn ==3); PEGASUS_TEST_ASSERT(crd1.size() == 2); PEGASUS_TEST_ASSERT(crdTo.size() == 3); CIMResponseData crdTo2 = CIMResponseData(CIMResponseData::RESP_INSTANCES); VCOUT << "Before from = " << crd1.size() << ", to = " << crdTo2.size() << endl; Uint32 rtn2 = crdTo2.moveObjects(crd1, 9); VCOUT << "After from = " << crd1.size() << ", to = " << crdTo2.size() << endl; PEGASUS_TEST_ASSERT(rtn2 ==2); PEGASUS_TEST_ASSERT(crd1.size() == 0); PEGASUS_TEST_ASSERT(crdTo2.size() == 2); PEGASUS_TEST_ASSERT(crd1.valid()); PEGASUS_TEST_ASSERT(crdTo2.valid()); // Repeat the test but starting with set CIM Instance Array to start // Create CIMReponseData object CIMResponseData crd2 = CIMResponseData(CIMResponseData::RESP_INSTANCES); crd2.setInstances(CIMInstArray); PEGASUS_TEST_ASSERT(crd2.size() == 2); PEGASUS_TEST_ASSERT(crd2.valid()); crd2.appendInstance(CIMInst1); VCOUT << crd2.size() << endl; PEGASUS_TEST_ASSERT(crd2.size() == 3); crd2.appendSCMO(SCMOInstArray); PEGASUS_TEST_ASSERT(crd2.valid()); VCOUT << crd2.size() << endl; PEGASUS_TEST_ASSERT(crd2.size() == 5); // Test XML formatting. CIMResponseData crd3 = CIMResponseData(CIMResponseData::RESP_INSTANCES); // set CIM instances into the responseData. crd3.appendInstances(CIMInstArray); VCOUT << "crd3 size " << crd3.size() << endl; PEGASUS_TEST_ASSERT(crd3.size() == 2); // Confirm that we can encode into a buffer. Buffer buf1; crd3.encodeXmlResponse(buf1, true); PEGASUS_TEST_ASSERT(crd3.size() == 2); CIMBuffer bufa; crd3.encodeInternalXmlResponse(bufa, true); CIMResponseData crd4 = CIMResponseData(CIMResponseData::RESP_INSTANCES); //// The following fails. Apparently not enough data in the buffer. Think it //// is the namespace from the buffer that does not exist. //// FUTURE. Check this but not important since the real test is in the msg //// serializer and deserializer. //// PEGASUS_TEST_ASSERT(crd4.setXml(bufa)); //// cout << "crd4 size: " << crd4.size() << endl; //// PEGASUS_TEST_ASSERT(crd4.size() == 4); }
void SANSSensitivityCorrection::exec() { // Output log m_output_message = ""; Progress progress(this, 0.0, 1.0, 10); // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } if (!reductionManager->existsProperty("SensitivityAlgorithm")) { auto algProp = make_unique<AlgorithmProperty>("SensitivityAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(std::move(algProp)); } progress.report("Loading sensitivity file"); const std::string fileName = getPropertyValue("Filename"); // Look for an entry for the dark current in the reduction table Poco::Path path(fileName); const std::string entryName = "Sensitivity" + path.getBaseName(); MatrixWorkspace_sptr floodWS; std::string floodWSName = "__sensitivity_" + path.getBaseName(); if (reductionManager->existsProperty(entryName)) { std::string wsName = reductionManager->getPropertyValue(entryName); floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>( AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(wsName)); m_output_message += " |Using " + wsName + "\n"; g_log.debug() << "SANSSensitivityCorrection :: Using sensitivity workspace: " << wsName << "\n"; } else { // Load the flood field if we don't have it already // First, try to determine whether we need to load data or a sensitivity // workspace... if (!floodWS && fileCheck(fileName)) { g_log.debug() << "SANSSensitivityCorrection :: Loading sensitivity file: " << fileName << "\n"; IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); loadAlg->executeAsChildAlg(); Workspace_sptr floodWS_ws = loadAlg->getProperty("OutputWorkspace"); floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(floodWS_ws); // Check that it's really a sensitivity file if (!floodWS->run().hasProperty("is_sensitivity")) { // Reset pointer floodWS.reset(); g_log.error() << "A processed Mantid workspace was loaded but it " "wasn't a sensitivity file!\n"; } } // ... if we don't, just load the data and process it if (!floodWS) { // Read in default beam center double center_x = getProperty("BeamCenterX"); double center_y = getProperty("BeamCenterY"); if (isEmpty(center_x) || isEmpty(center_y)) { if (reductionManager->existsProperty("LatestBeamCenterX") && reductionManager->existsProperty("LatestBeamCenterY")) { center_x = reductionManager->getProperty("LatestBeamCenterX"); center_y = reductionManager->getProperty("LatestBeamCenterY"); m_output_message += " |Setting beam center to [" + Poco::NumberFormatter::format(center_x, 1) + ", " + Poco::NumberFormatter::format(center_y, 1) + "]\n"; } else m_output_message += " |No beam center provided: skipping!\n"; } const std::string rawFloodWSName = "__flood_data_" + path.getBaseName(); MatrixWorkspace_sptr rawFloodWS; if (!reductionManager->existsProperty("LoadAlgorithm")) { IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX")) loadAlg->setProperty("BeamCenterX", center_x); if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY")) loadAlg->setProperty("BeamCenterY", center_y); loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName); loadAlg->executeAsChildAlg(); Workspace_sptr tmpWS = loadAlg->getProperty("OutputWorkspace"); rawFloodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(tmpWS); m_output_message += " | Loaded " + fileName + " (Load algorithm)\n"; } else { // Get load algorithm as a string so that we can create a completely // new proxy and ensure that we don't overwrite existing properties IAlgorithm_sptr loadAlg0 = reductionManager->getProperty("LoadAlgorithm"); const std::string loadString = loadAlg0->toString(); IAlgorithm_sptr loadAlg = Algorithm::fromString(loadString); loadAlg->setChild(true); loadAlg->setProperty("Filename", fileName); loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName); if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX")) loadAlg->setProperty("BeamCenterX", center_x); if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY")) loadAlg->setProperty("BeamCenterY", center_y); loadAlg->execute(); rawFloodWS = loadAlg->getProperty("OutputWorkspace"); m_output_message += " |Loaded " + fileName + "\n"; if (loadAlg->existsProperty("OutputMessage")) { std::string msg = loadAlg->getPropertyValue("OutputMessage"); m_output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } } // Check whether we just loaded a flood field data set, or the actual // sensitivity if (!rawFloodWS->run().hasProperty("is_sensitivity")) { const std::string darkCurrentFile = getPropertyValue("DarkCurrentFile"); // Look for a dark current subtraction algorithm std::string dark_result; if (reductionManager->existsProperty("DarkCurrentAlgorithm")) { IAlgorithm_sptr darkAlg = reductionManager->getProperty("DarkCurrentAlgorithm"); darkAlg->setChild(true); darkAlg->setProperty("InputWorkspace", rawFloodWS); darkAlg->setProperty("OutputWorkspace", rawFloodWS); // Execute as-is if we use the sample dark current, otherwise check // whether a dark current file was provided. // Otherwise do nothing if (getProperty("UseSampleDC")) { darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); } else if (!darkCurrentFile.empty()) { darkAlg->setProperty("Filename", darkCurrentFile); darkAlg->setProperty("PersistentCorrection", false); darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); else dark_result = " Dark current subtracted\n"; } } else if (!darkCurrentFile.empty()) { // We need to subtract the dark current for the flood field but no // dark // current subtraction was set for the sample! Use the default dark // current algorithm if we can find it. if (reductionManager->existsProperty("DefaultDarkCurrentAlgorithm")) { IAlgorithm_sptr darkAlg = reductionManager->getProperty("DefaultDarkCurrentAlgorithm"); darkAlg->setChild(true); darkAlg->setProperty("InputWorkspace", rawFloodWS); darkAlg->setProperty("OutputWorkspace", rawFloodWS); darkAlg->setProperty("Filename", darkCurrentFile); darkAlg->setProperty("PersistentCorrection", false); darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); } else { // We are running out of options g_log.error() << "No dark current algorithm provided to load [" << getPropertyValue("DarkCurrentFile") << "]: skipped!\n"; dark_result = " No dark current algorithm provided: skipped\n"; } } m_output_message += " |" + Poco::replace(dark_result, "\n", "\n |") + "\n"; // Look for solid angle correction algorithm if (reductionManager->existsProperty("SANSSolidAngleCorrection")) { IAlgorithm_sptr solidAlg = reductionManager->getProperty("SANSSolidAngleCorrection"); solidAlg->setChild(true); solidAlg->setProperty("InputWorkspace", rawFloodWS); solidAlg->setProperty("OutputWorkspace", rawFloodWS); solidAlg->execute(); std::string msg = "Solid angle correction applied\n"; if (solidAlg->existsProperty("OutputMessage")) msg = solidAlg->getPropertyValue("OutputMessage"); m_output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } // Apply transmission correction as needed double floodTransmissionValue = getProperty("FloodTransmissionValue"); double floodTransmissionError = getProperty("FloodTransmissionError"); if (!isEmpty(floodTransmissionValue)) { g_log.debug() << "SANSSensitivityCorrection :: Applying transmission " "to flood field\n"; IAlgorithm_sptr transAlg = createChildAlgorithm("ApplyTransmissionCorrection"); transAlg->setProperty("InputWorkspace", rawFloodWS); transAlg->setProperty("OutputWorkspace", rawFloodWS); transAlg->setProperty("TransmissionValue", floodTransmissionValue); transAlg->setProperty("TransmissionError", floodTransmissionError); transAlg->setProperty("ThetaDependent", true); transAlg->execute(); rawFloodWS = transAlg->getProperty("OutputWorkspace"); m_output_message += " |Applied transmission to flood field\n"; } // Calculate detector sensitivity IAlgorithm_sptr effAlg = createChildAlgorithm("CalculateEfficiency"); effAlg->setProperty("InputWorkspace", rawFloodWS); const double minEff = getProperty("MinEfficiency"); const double maxEff = getProperty("MaxEfficiency"); const std::string maskFullComponent = getPropertyValue("MaskedFullComponent"); const std::string maskEdges = getPropertyValue("MaskedEdges"); const std::string maskComponent = getPropertyValue("MaskedComponent"); effAlg->setProperty("MinEfficiency", minEff); effAlg->setProperty("MaxEfficiency", maxEff); effAlg->setProperty("MaskedFullComponent", maskFullComponent); effAlg->setProperty("MaskedEdges", maskEdges); effAlg->setProperty("MaskedComponent", maskComponent); effAlg->execute(); floodWS = effAlg->getProperty("OutputWorkspace"); } else { floodWS = rawFloodWS; } // Patch as needed if (reductionManager->existsProperty("SensitivityPatchAlgorithm")) { IAlgorithm_sptr patchAlg = reductionManager->getProperty("SensitivityPatchAlgorithm"); patchAlg->setChild(true); patchAlg->setProperty("Workspace", floodWS); patchAlg->execute(); m_output_message += " |Sensitivity patch applied\n"; } floodWS->mutableRun().addProperty("is_sensitivity", 1, "", true); } std::string floodWSOutputName = getPropertyValue("OutputSensitivityWorkspace"); if (floodWSOutputName.empty()) { setPropertyValue("OutputSensitivityWorkspace", floodWSName); AnalysisDataService::Instance().addOrReplace(floodWSName, floodWS); reductionManager->declareProperty( Kernel::make_unique<WorkspaceProperty<>>(entryName, floodWSName, Direction::InOut)); reductionManager->setPropertyValue(entryName, floodWSName); reductionManager->setProperty(entryName, floodWS); } setProperty("OutputSensitivityWorkspace", floodWS); } progress.report(3, "Loaded flood field"); // Check whether we need to apply the correction to a workspace MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); if (inputWS) { // Divide sample data by detector efficiency IAlgorithm_sptr divideAlg = createChildAlgorithm("Divide", 0.6, 0.7); divideAlg->setProperty("LHSWorkspace", inputWS); divideAlg->setProperty("RHSWorkspace", floodWS); divideAlg->executeAsChildAlg(); MatrixWorkspace_sptr outputWS = divideAlg->getProperty("OutputWorkspace"); // Copy over the efficiency's masked pixels to the reduced workspace IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors", 0.75, 0.85); maskAlg->setProperty("Workspace", outputWS); maskAlg->setProperty("MaskedWorkspace", floodWS); maskAlg->executeAsChildAlg(); setProperty("OutputWorkspace", outputWS); } setProperty("OutputMessage", "Sensitivity correction computed\n" + m_output_message); progress.report("Performed sensitivity correction"); }