double ConvertSpectrumAxis::getEfixed(IDetector_const_sptr detector, MatrixWorkspace_const_sptr inputWS, int emode) const { double efixed(0); double efixedProp = getProperty("Efixed"); if (efixedProp != EMPTY_DBL()) { efixed = efixedProp; g_log.debug() << "Detector: " << detector->getID() << " Efixed: " << efixed << "\n"; } else { if (emode == 1) { if (inputWS->run().hasProperty("Ei")) { Kernel::Property *p = inputWS->run().getProperty("Ei"); Kernel::PropertyWithValue<double> *doublep = dynamic_cast<Kernel::PropertyWithValue<double> *>(p); if (doublep) { efixed = (*doublep)(); } else { efixed = 0.0; g_log.warning() << "Efixed could not be found for detector " << detector->getID() << ", set to 0.0\n"; } } else { efixed = 0.0; g_log.warning() << "Efixed could not be found for detector " << detector->getID() << ", set to 0.0\n"; } } else if (emode == 2) { std::vector<double> efixedVec = detector->getNumberParameter("Efixed"); if (efixedVec.empty()) { int detid = detector->getID(); IDetector_const_sptr detectorSingle = inputWS->getInstrument()->getDetector(detid); efixedVec = detectorSingle->getNumberParameter("Efixed"); } if (!efixedVec.empty()) { efixed = efixedVec.at(0); g_log.debug() << "Detector: " << detector->getID() << " EFixed: " << efixed << "\n"; } else { efixed = 0.0; g_log.warning() << "Efixed could not be found for detector " << detector->getID() << ", set to 0.0\n"; } } } return efixed; }
double ConvertSpectrumAxis2::getEfixed(IDetector_const_sptr detector, MatrixWorkspace_const_sptr inputWS, int emode) const { double efixed(0); double efixedProp = getProperty("Efixed"); if (efixedProp != EMPTY_DBL()) { efixed = efixedProp; g_log.debug() << "Detector: " << detector->getID() << " Efixed: " << efixed << "\n"; } else { if (emode == 1) { if (inputWS->run().hasProperty("Ei")) { efixed = inputWS->run().getLogAsSingleValue("Ei"); } else { throw std::invalid_argument("Could not retrieve Efixed from the " "workspace. Please provide a value."); } } else if (emode == 2) { std::vector<double> efixedVec = detector->getNumberParameter("Efixed"); if (efixedVec.empty()) { int detid = detector->getID(); IDetector_const_sptr detectorSingle = inputWS->getInstrument()->getDetector(detid); efixedVec = detectorSingle->getNumberParameter("Efixed"); } if (!efixedVec.empty()) { efixed = efixedVec.at(0); g_log.debug() << "Detector: " << detector->getID() << " EFixed: " << efixed << "\n"; } else { g_log.warning() << "Efixed could not be found for detector " << detector->getID() << ", please provide a value\n"; throw std::invalid_argument("Could not retrieve Efixed from the " "detector. Please provide a value."); } } } return efixed; }
// calculate time from sample to detector void ModeratorTzeroLinear::calculateTfLi(MatrixWorkspace_const_sptr inputWS, size_t i, double &t_f, double &L_i) { static const double convFact = 1.0e-6 * sqrt(2 * PhysicalConstants::meV / PhysicalConstants::NeutronMass); static const double TfError = -1.0; // signal error when calculating final // time // Get detector position IDetector_const_sptr det; try { det = inputWS->getDetector(i); } catch (Exception::NotFoundError &) { t_f = TfError; return; } if (det->isMonitor()) { L_i = m_instrument->getSource()->getDistance(*det); t_f = 0.0; // t_f=0.0 since there is no sample to detector path } else { IComponent_const_sptr sample = m_instrument->getSample(); try { L_i = m_instrument->getSource()->getDistance(*sample); } catch (Exception::NotFoundError &) { g_log.error("Unable to calculate source-sample distance"); throw Exception::InstrumentDefinitionError( "Unable to calculate source-sample distance", inputWS->getTitle()); } // Get final energy E_f, final velocity v_f std::vector<double> wsProp = det->getNumberParameter("Efixed"); if (!wsProp.empty()) { double E_f = wsProp.at(0); //[E_f]=meV double v_f = convFact * sqrt(E_f); //[v_f]=meter/microsec try { // obtain L_f, calculate t_f double L_f = det->getDistance(*sample); t_f = L_f / v_f; // g_log.debug() << "detector: " << i << " L_f=" << L_f << " t_f=" << // t_f << '\n'; } catch (Exception::NotFoundError &) { g_log.error("Unable to calculate detector-sample distance"); throw Exception::InstrumentDefinitionError( "Unable to calculate detector-sample distance", inputWS->getTitle()); } } else { g_log.debug() << "Efixed not found for detector " << i << '\n'; t_f = TfError; } } } // end of CalculateTf(const MatrixWorkspace_sptr inputWS, size_t i)
//calculate time from sample to detector double ModeratorTzero::CalculateT2(MatrixWorkspace_sptr inputWS, size_t i) { static const double convFact = 1.0e-6*sqrt(2*PhysicalConstants::meV/PhysicalConstants::NeutronMass); double t2(-1.0); // negative initialization signals error // Get detector position IDetector_const_sptr det; try { det = inputWS->getDetector(i); } catch (Exception::NotFoundError&) { return t2; } if( det->isMonitor() ) { t2 = 0.0; //t2=0.0 since there is no sample to detector path } else { IComponent_const_sptr sample = m_instrument->getSample(); // Get final energy E_f, final velocity v_f std::vector< double > wsProp=det->getNumberParameter("Efixed"); if ( !wsProp.empty() ) { double E2 = wsProp.at(0); //[E2]=meV double v2 = convFact * sqrt(E2); //[v2]=meter/microsec try { double L2 = det->getDistance(*sample); t2 = L2 / v2; } catch (Exception::NotFoundError &) { g_log.error("Unable to calculate detector-sample distance"); throw Exception::InstrumentDefinitionError("Unable to calculate detector-sample distance", inputWS->getTitle()); } } else { g_log.debug() <<"Efixed not found for detector "<< i << std::endl; } } return t2; } // end of CalculateT2(const MatrixWorkspace_sptr inputWS, size_t i)
void ModeratorTzero::execEvent(const std::string &emode) { g_log.information("Processing event workspace"); const MatrixWorkspace_const_sptr matrixInputWS = getProperty("InputWorkspace"); EventWorkspace_const_sptr inputWS = boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS); // generate the output workspace pointer const size_t numHists = static_cast<size_t>(inputWS->getNumberHistograms()); Mantid::API::MatrixWorkspace_sptr matrixOutputWS = getProperty("OutputWorkspace"); EventWorkspace_sptr outputWS; if (matrixOutputWS == matrixInputWS) { outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS); } else { // Make a brand new EventWorkspace outputWS = boost::dynamic_pointer_cast<EventWorkspace>( WorkspaceFactory::Instance().create("EventWorkspace", numHists, 2, 1)); // Copy geometry over. WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, false); // You need to copy over the data as well. outputWS->copyDataFrom((*inputWS)); // Cast to the matrixOutputWS and save it matrixOutputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS); setProperty("OutputWorkspace", matrixOutputWS); } // Get pointers to sample and source IComponent_const_sptr source = m_instrument->getSource(); IComponent_const_sptr sample = m_instrument->getSample(); double Lss = source->getDistance(*sample); // distance from source to sample // calculate tof shift once for all neutrons if emode==Direct double t0_direct(-1); if (emode == "Direct") { Kernel::Property *eiprop = inputWS->run().getProperty("Ei"); double Ei = boost::lexical_cast<double>(eiprop->value()); mu::Parser parser; parser.DefineVar("incidentEnergy", &Ei); // associate E1 to this parser parser.SetExpr(m_formula); t0_direct = parser.Eval(); } // Loop over the spectra Progress prog(this, 0.0, 1.0, numHists); // report progress of algorithm PARALLEL_FOR1(outputWS) for (int i = 0; i < static_cast<int>(numHists); ++i) { PARALLEL_START_INTERUPT_REGION size_t wsIndex = static_cast<size_t>(i); EventList &evlist = outputWS->getEventList(wsIndex); if (evlist.getNumberEvents() > 0) // don't bother with empty lists { IDetector_const_sptr det; double L1(Lss); // distance from source to sample double L2(-1); // distance from sample to detector try { det = inputWS->getDetector(i); if (det->isMonitor()) { // redefine the sample as the monitor L1 = source->getDistance(*det); L2 = 0; } else { L2 = sample->getDistance(*det); } } catch (Exception::NotFoundError &) { g_log.error() << "Unable to calculate distances to/from detector" << i << std::endl; } if (L2 >= 0) { // One parser for each parallel processor needed (except Edirect mode) double E1; mu::Parser parser; parser.DefineVar("incidentEnergy", &E1); // associate E1 to this parser parser.SetExpr(m_formula); // fast neutrons are shifted by min_t0_next, irrespective of tof double v1_max = L1 / m_t1min; E1 = m_convfactor * v1_max * v1_max; double min_t0_next = parser.Eval(); if (emode == "Indirect") { double t2(-1.0); // time from sample to detector. (-1) signals error if (det->isMonitor()) { t2 = 0.0; } else { static const double convFact = 1.0e-6 * sqrt(2 * PhysicalConstants::meV / PhysicalConstants::NeutronMass); std::vector<double> wsProp = det->getNumberParameter("Efixed"); if (!wsProp.empty()) { double E2 = wsProp.at(0); //[E2]=meV double v2 = convFact * sqrt(E2); //[v2]=meter/microsec t2 = L2 / v2; } else { // t2 is kept to -1 if no Efixed is found g_log.debug() << "Efixed not found for detector " << i << std::endl; } } if (t2 >= 0) // t2 < 0 when no detector info is available { // fix the histogram bins MantidVec &x = evlist.dataX(); for (double &tof : x) { if (tof < m_t1min + t2) tof -= min_t0_next; else tof -= CalculateT0indirect(tof, L1, t2, E1, parser); } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { if (tof < m_t1min + t2) tof -= min_t0_next; else tof -= CalculateT0indirect(tof, L1, t2, E1, parser); } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } // end of if( t2>= 0) } // end of if(emode=="Indirect") else if (emode == "Elastic") { // Apply t0 correction to histogram bins MantidVec &x = evlist.dataX(); for (double &tof : x) { if (tof < m_t1min * (L1 + L2) / L1) tof -= min_t0_next; else tof -= CalculateT0elastic(tof, L1 + L2, E1, parser); } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { // add a [-0.1,0.1] microsecond noise to avoid artifacts // resulting from original tof data if (tof < m_t1min * (L1 + L2) / L1) tof -= min_t0_next; else tof -= CalculateT0elastic(tof, L1 + L2, E1, parser); } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); MantidVec tofs_b = evlist.getTofs(); MantidVec xarray = evlist.readX(); } // end of else if(emode=="Elastic") else if (emode == "Direct") { // fix the histogram bins MantidVec &x = evlist.dataX(); for (double &tof : x) { tof -= t0_direct; } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { tof -= t0_direct; } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } // end of else if(emode=="Direct") } // end of if(L2 >= 0) } // end of if (evlist.getNumberEvents() > 0) prog.report(); PARALLEL_END_INTERUPT_REGION } // end of for (int i = 0; i < static_cast<int>(numHists); ++i) PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); // Clears the Most Recent Used lists */ } // end of void ModeratorTzero::execEvent()
void CorrectKiKf::exec() { // Get the workspaces this->inputWS = this->getProperty("InputWorkspace"); this->outputWS = this->getProperty("OutputWorkspace"); // If input and output workspaces are not the same, create a new workspace for the output if (this->outputWS != this->inputWS) { this->outputWS = API::WorkspaceFactory::Instance().create(this->inputWS); } //Check if it is an event workspace EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventW != NULL) { this->execEvent(); return; } const size_t size = this->inputWS->blocksize(); // Calculate the number of spectra in this workspace const int numberOfSpectra = static_cast<int>(this->inputWS->size() / size); API::Progress prog(this,0.0,1.0,numberOfSpectra); const bool histogram = this->inputWS->isHistogramData(); bool negativeEnergyWarning = false; const std::string emodeStr = getProperty("EMode"); double efixedProp = getProperty("EFixed"); if( efixedProp == EMPTY_DBL() ) { if (emodeStr == "Direct") { // Check if it has been store on the run object for this workspace if( this->inputWS->run().hasProperty("Ei")) { Kernel::Property* eiprop = this->inputWS->run().getProperty("Ei"); efixedProp = boost::lexical_cast<double>(eiprop->value()); g_log.debug() << "Using stored Ei value " << efixedProp << "\n"; } else { throw std::invalid_argument("No Ei value has been set or stored within the run information."); } } else { // If not specified, will try to get Ef from the parameter file for indirect geometry, // but it will be done for each spectrum separately, in case of different analyzer crystals } } PARALLEL_FOR2(inputWS,outputWS) for (int64_t i = 0; i < int64_t(numberOfSpectra); ++i) { PARALLEL_START_INTERUPT_REGION double Efi = 0; // Now get the detector object for this histogram to check if monitor // or to get Ef for indirect geometry if (emodeStr == "Indirect") { if ( efixedProp != EMPTY_DBL()) Efi = efixedProp; else try { IDetector_const_sptr det = inputWS->getDetector(i); if (!det->isMonitor()) { std::vector< double > wsProp=det->getNumberParameter("Efixed"); if ( wsProp.size() > 0 ) { Efi=wsProp.at(0); g_log.debug() << i << " Ef: "<< Efi<<" (from parameter file)\n"; } else { g_log.information() <<"Ef not found for spectrum "<< i << std::endl; throw std::invalid_argument("No Ef value has been set or found."); } } } catch(std::runtime_error&) { g_log.information() << "Spectrum " << i << ": cannot find detector" << "\n"; } } MantidVec& yOut = outputWS->dataY(i); MantidVec& eOut = outputWS->dataE(i); const MantidVec& xIn = inputWS->readX(i); const MantidVec& yIn = inputWS->readY(i); const MantidVec& eIn = inputWS->readE(i); //Copy the energy transfer axis outputWS->setX( i, inputWS->refX(i) ); for (unsigned int j = 0; j < size; ++j) { const double deltaE = histogram ? 0.5*(xIn[j]+xIn[j+1]) : xIn[j]; double Ei=0.; double Ef=0.; double kioverkf = 1.; if (emodeStr == "Direct") //Ei=Efixed { Ei = efixedProp; Ef = Ei - deltaE; } else //Ef=Efixed { Ef = Efi; Ei = Efi + deltaE; } // if Ei or Ef is negative, it should be a warning // however, if the intensity is 0 (histogram goes to energy transfer higher than Ei) it is still ok, so no warning. if ((Ei <= 0)||(Ef <= 0)) { kioverkf=0.; if (yIn[j]!=0) negativeEnergyWarning=true; } else kioverkf = std::sqrt( Ei / Ef ); yOut[j] = yIn[j]*kioverkf; eOut[j] = eIn[j]*kioverkf; } prog.report(); PARALLEL_END_INTERUPT_REGION }//end for i PARALLEL_CHECK_INTERUPT_REGION if (negativeEnergyWarning) g_log.information() <<"Ef <= 0 or Ei <= 0 in at least one spectrum!!!!"<<std::endl; if ((negativeEnergyWarning) && ( efixedProp == EMPTY_DBL())) g_log.information()<<"Try to set fixed energy"<<std::endl ; this->setProperty("OutputWorkspace",this->outputWS); return; }
void CorrectKiKf::execEvent() { g_log.information("Processing event workspace"); const MatrixWorkspace_const_sptr matrixInputWS = this->getProperty("InputWorkspace"); EventWorkspace_const_sptr inputWS= boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS); // generate the output workspace pointer API::MatrixWorkspace_sptr matrixOutputWS = this->getProperty("OutputWorkspace"); EventWorkspace_sptr outputWS; if (matrixOutputWS == matrixInputWS) outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS); else { //Make a brand new EventWorkspace outputWS = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", inputWS->getNumberHistograms(), 2, 1)); //Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, false); //You need to copy over the data as well. outputWS->copyDataFrom( (*inputWS) ); //Cast to the matrixOutputWS and save it matrixOutputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS); this->setProperty("OutputWorkspace", matrixOutputWS); } const std::string emodeStr = getProperty("EMode"); double efixedProp = getProperty("EFixed"),efixed; if( efixedProp == EMPTY_DBL() ) { if (emodeStr == "Direct") { // Check if it has been store on the run object for this workspace if( this->inputWS->run().hasProperty("Ei")) { Kernel::Property* eiprop = this->inputWS->run().getProperty("Ei"); efixedProp = boost::lexical_cast<double>(eiprop->value()); g_log.debug() << "Using stored Ei value " << efixedProp << "\n"; } else { throw std::invalid_argument("No Ei value has been set or stored within the run information."); } } else { // If not specified, will try to get Ef from the parameter file for indirect geometry, // but it will be done for each spectrum separately, in case of different analyzer crystals } } int64_t numHistograms = static_cast<int64_t>(inputWS->getNumberHistograms()); API::Progress prog = API::Progress(this, 0.0, 1.0, numHistograms); PARALLEL_FOR1(outputWS) for (int64_t i=0; i < numHistograms; ++i) { PARALLEL_START_INTERUPT_REGION double Efi = 0; // Now get the detector object for this histogram to check if monitor // or to get Ef for indirect geometry if (emodeStr == "Indirect") { if ( efixedProp != EMPTY_DBL()) Efi = efixedProp; else try { IDetector_const_sptr det = inputWS->getDetector(i); if (!det->isMonitor()) { std::vector< double > wsProp=det->getNumberParameter("Efixed"); if ( wsProp.size() > 0 ) { Efi=wsProp.at(0); g_log.debug() << i << " Ef: "<< Efi<<" (from parameter file)\n"; } else { g_log.information() <<"Ef not found for spectrum "<< i << std::endl; throw std::invalid_argument("No Ef value has been set or found."); } } } catch(std::runtime_error&) { g_log.information() << "Spectrum " << i << ": cannot find detector" << "\n"; } } if (emodeStr == "Indirect") efixed=Efi; else efixed=efixedProp; //Do the correction EventList *evlist=outputWS->getEventListPtr(i); switch (evlist->getEventType()) { case TOF: //Switch to weights if needed. evlist->switchTo(WEIGHTED); // Fall through case WEIGHTED: correctKiKfEventHelper(evlist->getWeightedEvents(), efixed,emodeStr); break; case WEIGHTED_NOTIME: correctKiKfEventHelper(evlist->getWeightedEventsNoTime(), efixed,emodeStr); break; } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); if (inputWS->getNumberEvents( ) != outputWS->getNumberEvents( )) { g_log.information() <<"Ef <= 0 or Ei <= 0 for "<<inputWS->getNumberEvents( )-outputWS->getNumberEvents( )<<" events, out of "<<inputWS->getNumberEvents( )<<std::endl; if ( efixedProp == EMPTY_DBL()) g_log.information()<<"Try to set fixed energy"<<std::endl ; } }