/*
 *  Sum up all the unmasked detector pixels.
 *
 * @param rebinnedWS: workspace where all the wavelength bins have been grouped together
 * @param sum: sum of all the unmasked detector pixels (counts)
 * @param error: error on sum (counts)
 * @param nPixels: number of unmasked detector pixels that contributed to sum
 */
void CalculateEfficiency::sumUnmaskedDetectors(MatrixWorkspace_sptr rebinnedWS,
    double& sum, double& error, int& nPixels)
{
    // Number of spectra
    const int numberOfSpectra = static_cast<int>(rebinnedWS->getNumberHistograms());
    sum = 0.0;
    error = 0.0;
    nPixels = 0;

    for (int i = 0; i < numberOfSpectra; i++)
    {
      progress(0.2+0.2*i/numberOfSpectra, "Computing sensitivity");
      // Get the detector object for this spectrum
      IDetector_const_sptr det = rebinnedWS->getDetector(i);
      // If this detector is masked, skip to the next one
      if ( det->isMasked() ) continue;
      // If this detector is a monitor, skip to the next one
      if ( det->isMonitor() ) continue;

      // Retrieve the spectrum into a vector
      const MantidVec& YValues = rebinnedWS->readY(i);
      const MantidVec& YErrors = rebinnedWS->readE(i);

      sum += YValues[0];
      error += YErrors[0]*YErrors[0];
      nPixels++;
    }

    error = std::sqrt(error);
}
Example #2
0
/**  Calculate the integral asymmetry for a pair of workspaces (red & green).
*   @param ws_red :: The red workspace
*   @param ws_green :: The green workspace
*   @param Y :: Reference to a variable receiving the value of asymmetry
*   @param E :: Reference to a variable receiving the value of the error
*/
void PlotAsymmetryByLogValue::calcIntAsymmetry(MatrixWorkspace_sptr ws_red,
                                               MatrixWorkspace_sptr ws_green,
                                               double &Y, double &E) {
  if (!m_int) { //  "Differential asymmetry"

    MatrixWorkspace_sptr tmpWS = WorkspaceFactory::Instance().create(
        ws_red, 1, ws_red->readX(0).size(), ws_red->readY(0).size());

    for (size_t i = 0; i < tmpWS->dataY(0).size(); i++) {
      double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i];
      FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0;
      double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i];
      BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0;
      double ZF = (ws_green->readY(0)[i] - ws_red->readY(0)[i]) * FNORM;
      double ZB = (ws_green->readY(1)[i] - ws_red->readY(1)[i]) * BNORM;
      tmpWS->dataY(0)[i] = ZB - ZF;
      tmpWS->dataE(0)[i] = (1.0 + ZF * ZF) * FNORM + (1.0 + ZB * ZB) * BNORM;
    }

    IAlgorithm_sptr integr = createChildAlgorithm("Integration");
    integr->setProperty("InputWorkspace", tmpWS);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace");

    Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
    E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
  } else {
    //  "Integral asymmetry"
    IAlgorithm_sptr integr = createChildAlgorithm("Integration");
    integr->setProperty("InputWorkspace", ws_red);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace");

    integr = createChildAlgorithm("Integration");
    integr->setProperty("InputWorkspace", ws_green);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace");

    double YIF = (intWS_green->readY(0)[0] - intWS_red->readY(0)[0]) /
                 (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]);
    double YIB = (intWS_green->readY(1)[0] - intWS_red->readY(1)[0]) /
                 (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]);

    Y = YIB - YIF;

    double VARIF =
        (1.0 + YIF * YIF) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]);
    double VARIB =
        (1.0 + YIB * YIB) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]);

    E = sqrt(VARIF + VARIB);
  }
}
Example #3
0
/**  Calculate the integral asymmetry for a workspace.
*   The calculation is done by AsymmetryCalc and Integration algorithms.
*   @param ws :: The workspace
*   @param Y :: Reference to a variable receiving the value of asymmetry
*   @param E :: Reference to a variable receiving the value of the error
*/
void PlotAsymmetryByLogValue::calcIntAsymmetry(MatrixWorkspace_sptr ws,
                                               double &Y, double &E) {

  if (!m_int) { //  "Differential asymmetry"
    IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc");
    asym->setLogging(false);
    asym->setProperty("InputWorkspace", ws);
    asym->execute();
    MatrixWorkspace_sptr asymWS = asym->getProperty("OutputWorkspace");

    IAlgorithm_sptr integr = createChildAlgorithm("Integration");
    integr->setLogging(false);
    integr->setProperty("InputWorkspace", asymWS);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace");

    Y = out->readY(0)[0];
    E = out->readE(0)[0];
  } else {
    //  "Integral asymmetry"
    IAlgorithm_sptr integr = createChildAlgorithm("Integration");
    integr->setLogging(false);
    integr->setProperty("InputWorkspace", ws);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr intWS = integr->getProperty("OutputWorkspace");

    IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc");
    asym->setLogging(false);
    asym->setProperty("InputWorkspace", intWS);
    asym->execute();
    MatrixWorkspace_sptr out = asym->getProperty("OutputWorkspace");

    Y = out->readY(0)[0];
    E = out->readE(0)[0];
  }
}
Example #4
0
/**
 * Groups the workspace according to grouping provided.
 *
 * @param ws :: Workspace to group
 * @param  g :: The grouping information
 * @return Sptr to created grouped workspace
 */
MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_const_sptr ws, const Grouping& g)
{
  // As I couldn't specify multiple groups for GroupDetectors, I am going down quite a complicated
  // route - for every group distinct grouped workspace is created using GroupDetectors. These
  // workspaces are then merged into the output workspace.

  // Create output workspace
  MatrixWorkspace_sptr outWs =
    WorkspaceFactory::Instance().create(ws, g.groups.size(), ws->readX(0).size(), ws->blocksize());

  for(size_t gi = 0; gi < g.groups.size(); gi++)
  {
    Mantid::API::IAlgorithm_sptr alg = AlgorithmManager::Instance().create("GroupDetectors");
    alg->setChild(true); // So Output workspace is not added to the ADS
    alg->initialize();
    alg->setProperty("InputWorkspace", boost::const_pointer_cast<MatrixWorkspace>(ws));
    alg->setPropertyValue("SpectraList", g.groups[gi]);
    alg->setPropertyValue("OutputWorkspace", "grouped"); // Is not actually used, just to make validators happy
    alg->execute();

    MatrixWorkspace_sptr grouped = alg->getProperty("OutputWorkspace");

    // Copy the spectrum
    *(outWs->getSpectrum(gi)) = *(grouped->getSpectrum(0));

    // Update spectrum number
    outWs->getSpectrum(gi)->setSpectrumNo(static_cast<specid_t>(gi));

    // Copy to the output workspace
    outWs->dataY(gi) = grouped->readY(0);
    outWs->dataX(gi) = grouped->readX(0);
    outWs->dataE(gi) = grouped->readE(0);
  }

  return outWs;
}
Example #5
0
/**  Checks input properties and compares them to previous values
*   @param is :: [output] Number of the first run
*   @param ie :: [output] Number of the last run
*/
void PlotAsymmetryByLogValue::checkProperties(size_t &is, size_t &ie) {

  // Log Value
  m_logName = getPropertyValue("LogValue");
  // Get function to apply to logValue
  m_logFunc = getPropertyValue("Function");
  // Get type of computation
  m_int = (getPropertyValue("Type") == "Integral");
  // Get grouping properties
  m_forward_list = getProperty("ForwardSpectra");
  m_backward_list = getProperty("BackwardSpectra");
  // Get green and red periods
  m_red = getProperty("Red");
  m_green = getProperty("Green");
  // Get time min and time max
  m_minTime = getProperty("TimeMin");
  m_maxTime = getProperty("TimeMax");
  // Get type of dead-time corrections
  m_dtcType = getPropertyValue("DeadTimeCorrType");
  m_dtcFile = getPropertyValue("DeadTimeCorrFile");
  // Get runs
  std::string firstFN = getProperty("FirstRun");
  std::string lastFN = getProperty("LastRun");

  // Parse run names and get the number of runs
  parseRunNames(firstFN, lastFN, m_filenameBase, m_filenameExt,
                m_filenameZeros);
  is = atoi(firstFN.c_str()); // starting run number
  ie = atoi(lastFN.c_str());  // last run number
  if (ie < is) {
    throw std::runtime_error(
        "First run number is greater than last run number");
  }

  // Create a string holding all the properties
  std::ostringstream ss;
  ss << m_filenameBase << "," << m_filenameExt << "," << m_filenameZeros << ",";
  ss << m_dtcType << "," << m_dtcFile << ",";
  ss << getPropertyValue("ForwardSpectra") << ","
     << getPropertyValue("BackwardSpectra") << ",";
  ss << m_int << "," << m_minTime << "," << m_maxTime << ",";
  ss << m_red << "," << m_green << ",";
  ss << m_logName << ", " << m_logFunc;
  m_allProperties = ss.str();

  // Check if we can re-use results from previous run
  // We can reuse results if:
  // 1. There is a ws in the ADS with name m_currResName
  // 2. It is a MatrixWorkspace
  // 3. It has a title equatl to m_allProperties
  // This ws stores previous results as described below
  if (AnalysisDataService::Instance().doesExist(m_currResName)) {
    MatrixWorkspace_sptr prevResults =
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
            m_currResName);
    if (prevResults) {
      if (m_allProperties == prevResults->getTitle()) {
        // We can re-use results
        size_t nPoints = prevResults->blocksize();
        size_t nHisto = prevResults->getNumberHistograms();

        if (nHisto == 2) {
          // Only 'red' data
          for (size_t i = 0; i < nPoints; i++) {
            // The first spectrum contains: X -> run number, Y -> log value
            // The second spectrum contains: Y -> redY, E -> redE
            size_t run = static_cast<size_t>(prevResults->readX(0)[i]);
            if ((run >= is) && (run <= ie)) {
              m_logValue[run] = prevResults->readY(0)[i];
              m_redY[run] = prevResults->readY(1)[i];
              m_redE[run] = prevResults->readE(1)[i];
            }
          }
        } else {
          // 'Red' and 'Green' data
          for (size_t i = 0; i < nPoints; i++) {
            // The first spectrum contains: X -> run number, Y -> log value
            // The second spectrum contains: Y -> diffY, E -> diffE
            // The third spectrum contains: Y -> redY, E -> redE
            // The fourth spectrum contains: Y -> greenY, E -> greeE
            // The fifth spectrum contains: Y -> sumY, E -> sumE
            size_t run = static_cast<size_t>(prevResults->readX(0)[i]);
            if ((run >= is) && (run <= ie)) {
              m_logValue[run] = prevResults->readY(0)[i];
              m_diffY[run] = prevResults->readY(1)[i];
              m_diffE[run] = prevResults->readE(1)[i];
              m_redY[run] = prevResults->readY(2)[i];
              m_redE[run] = prevResults->readE(2)[i];
              m_greenY[run] = prevResults->readY(3)[i];
              m_greenE[run] = prevResults->readE(3)[i];
              m_sumY[run] = prevResults->readY(4)[i];
              m_sumE[run] = prevResults->readE(4)[i];
            }
          }
        }
      }
    }
  }
}
  /**
   * Set errors in Diff spectrum after a fit
   * @param data :: [input/output] Workspace containing spectrum to set errors to
   */
  void ALCBaselineModellingModel::setErrorsAfterFit (MatrixWorkspace_sptr data) {

    data->dataE(2)=data->readE(0);
  }
/**
 * This function handles the logic for summing RebinnedOutput workspaces.
 * @param outputWorkspace the workspace to hold the summed input
 * @param progress the progress indicator
 * @param numSpectra
 * @param numMasked
 * @param numZeros
 */
void SumSpectra::doRebinnedOutput(MatrixWorkspace_sptr outputWorkspace,
                                  Progress &progress, size_t &numSpectra,
                                  size_t &numMasked, size_t &numZeros) {
  // Get a copy of the input workspace
  MatrixWorkspace_sptr temp = getProperty("InputWorkspace");

  // First, we need to clean the input workspace for nan's and inf's in order
  // to treat the data correctly later. This will create a new private
  // workspace that will be retrieved as mutable.
  IAlgorithm_sptr alg = this->createChildAlgorithm("ReplaceSpecialValues");
  alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", temp);
  std::string outName = "_" + temp->getName() + "_clean";
  alg->setProperty("OutputWorkspace", outName);
  alg->setProperty("NaNValue", 0.0);
  alg->setProperty("NaNError", 0.0);
  alg->setProperty("InfinityValue", 0.0);
  alg->setProperty("InfinityError", 0.0);
  alg->executeAsChildAlg();
  MatrixWorkspace_sptr localworkspace = alg->getProperty("OutputWorkspace");

  // Transform to real workspace types
  RebinnedOutput_sptr inWS =
      boost::dynamic_pointer_cast<RebinnedOutput>(localworkspace);
  RebinnedOutput_sptr outWS =
      boost::dynamic_pointer_cast<RebinnedOutput>(outputWorkspace);

  // Get references to the output workspaces's data vectors
  ISpectrum *outSpec = outputWorkspace->getSpectrum(0);
  MantidVec &YSum = outSpec->dataY();
  MantidVec &YError = outSpec->dataE();
  MantidVec &FracSum = outWS->dataF(0);
  MantidVec Weight;
  std::vector<size_t> nZeros;
  if (m_calculateWeightedSum) {
    Weight.assign(YSum.size(), 0);
    nZeros.assign(YSum.size(), 0);
  }
  numSpectra = 0;
  numMasked = 0;
  numZeros = 0;

  // Loop over spectra
  std::set<int>::iterator it;
  // for (int i = m_minSpec; i <= m_maxSpec; ++i)
  for (it = m_indices.begin(); it != m_indices.end(); ++it) {
    int i = *it;
    // Don't go outside the range.
    if ((i >= m_numberOfSpectra) || (i < 0)) {
      g_log.error() << "Invalid index " << i
                    << " was specified. Sum was aborted.\n";
      break;
    }

    try {
      // Get the detector object for this spectrum
      Geometry::IDetector_const_sptr det = localworkspace->getDetector(i);
      // Skip monitors, if the property is set to do so
      if (!m_keepMonitors && det->isMonitor())
        continue;
      // Skip masked detectors
      if (det->isMasked()) {
        numMasked++;
        continue;
      }
    } catch (...) {
      // if the detector not found just carry on
    }
    numSpectra++;

    // Retrieve the spectrum into a vector
    const MantidVec &YValues = localworkspace->readY(i);
    const MantidVec &YErrors = localworkspace->readE(i);
    const MantidVec &FracArea = inWS->readF(i);

    if (m_calculateWeightedSum) {
      for (int k = 0; k < this->m_yLength; ++k) {
        if (YErrors[k] != 0) {
          double errsq = YErrors[k] * YErrors[k] * FracArea[k] * FracArea[k];
          YError[k] += errsq;
          Weight[k] += 1. / errsq;
          YSum[k] += YValues[k] * FracArea[k] / errsq;
          FracSum[k] += FracArea[k];
        } else {
          nZeros[k]++;
          FracSum[k] += FracArea[k];
        }
      }
    } else {
      for (int k = 0; k < this->m_yLength; ++k) {
        YSum[k] += YValues[k] * FracArea[k];
        YError[k] += YErrors[k] * YErrors[k] * FracArea[k] * FracArea[k];
        FracSum[k] += FracArea[k];
      }
    }

    // Map all the detectors onto the spectrum of the output
    outSpec->addDetectorIDs(localworkspace->getSpectrum(i)->getDetectorIDs());

    progress.report();
  }

  if (m_calculateWeightedSum) {
    numZeros = 0;
    for (size_t i = 0; i < Weight.size(); i++) {
      if (nZeros[i] == 0)
        YSum[i] *= double(numSpectra) / Weight[i];
      else
        numZeros += nZeros[i];
    }
  }

  // Create the correct representation
  outWS->finalize();
}
void CalculateEfficiency::normalizeDetectors(MatrixWorkspace_sptr rebinnedWS,
    MatrixWorkspace_sptr outputWS, double sum, double error, int nPixels,
    double min_eff, double max_eff)
{
    // Number of spectra
    const size_t numberOfSpectra = rebinnedWS->getNumberHistograms();

    // Empty vector to store the pixels that outside the acceptable efficiency range
    std::vector<size_t> dets_to_mask;

    for (size_t i = 0; i < numberOfSpectra; i++)
    {
      const double currProgress = 0.4+0.2*((double)i/(double)numberOfSpectra);
      progress(currProgress, "Computing sensitivity");
      // Get the detector object for this spectrum
      IDetector_const_sptr det = rebinnedWS->getDetector(i);
      // If this detector is masked, skip to the next one
      if ( det->isMasked() ) continue;

      // Retrieve the spectrum into a vector
      const MantidVec& YIn = rebinnedWS->readY(i);
      const MantidVec& EIn = rebinnedWS->readE(i);
      MantidVec& YOut = outputWS->dataY(i);
      MantidVec& EOut = outputWS->dataE(i);
      // If this detector is a monitor, skip to the next one
      if ( det->isMonitor() )
      {
        YOut[0] = 1.0;
        EOut[0] = 0.0;
        continue;
      }

      // Normalize counts to get relative efficiency
      YOut[0] = nPixels/sum * YIn[0];
      const double err_sum = YIn[0]/sum*error;
      EOut[0] = nPixels/std::abs(sum) * std::sqrt(EIn[0]*EIn[0] + err_sum*err_sum);

      // Mask this detector if the signal is outside the acceptable band
      if ( !isEmpty(min_eff) && YOut[0] < min_eff ) dets_to_mask.push_back(i);
      if ( !isEmpty(max_eff) && YOut[0] > max_eff ) dets_to_mask.push_back(i);

    }

    // If we identified pixels to be masked, mask them now
    if ( !dets_to_mask.empty() )
    {
      // Mask detectors that were found to be outside the acceptable efficiency band
      try
      {
        IAlgorithm_sptr mask = createChildAlgorithm("MaskDetectors", 0.8, 0.9);
        // First we mask detectors in the output workspace
        mask->setProperty<MatrixWorkspace_sptr>("Workspace", outputWS);
        mask->setProperty< std::vector<size_t> >("WorkspaceIndexList", dets_to_mask);
        mask->execute();

        mask = createChildAlgorithm("MaskDetectors", 0.9, 1.0);
        // Then we mask the same detectors in the input workspace
        mask->setProperty<MatrixWorkspace_sptr>("Workspace", rebinnedWS);
        mask->setProperty< std::vector<size_t> >("WorkspaceIndexList", dets_to_mask);
        mask->execute();
      } catch (std::invalid_argument& err)
      {
        std::stringstream e;
        e << "Invalid argument to MaskDetectors Child Algorithm: " << err.what();
        g_log.error(e.str());
      } catch (std::runtime_error& err)
      {
        std::stringstream e;
        e << "Unable to successfully run MaskDetectors Child Algorithm: " << err.what();
        g_log.error(e.str());
      }
    }
}
Example #9
0
/** Execute the algorithm.
 */
void MaxEnt::exec() {

  // MaxEnt parameters
  // Complex data?
  bool complex = getProperty("ComplexData");
  // Image must be positive?
  bool positiveImage = getProperty("PositiveImage");
  // Autoshift
  bool autoShift = getProperty("AutoShift");
  // Increase the number of points in the image by this factor
  size_t densityFactor = getProperty("DensityFactor");
  // Background (default level, sky background, etc)
  double background = getProperty("A");
  // Chi target
  double chiTarget = getProperty("ChiTarget");
  // Required precision for Chi arget
  double chiEps = getProperty("ChiEps");
  // Maximum degree of non-parallelism between S and C
  double angle = getProperty("MaxAngle");
  // Distance penalty for current image
  double distEps = getProperty("DistancePenalty");
  // Maximum number of iterations
  size_t niter = getProperty("MaxIterations");
  // Maximum number of iterations in alpha chop
  size_t alphaIter = getProperty("AlphaChopIterations");
  // Number of spectra and datapoints
  // Read input workspace
  MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  // Number of spectra
  size_t nspec = inWS->getNumberHistograms();
  // Number of data points
  size_t npoints = inWS->blocksize() * densityFactor;
  // Number of X bins
  size_t npointsX = inWS->isHistogramData() ? npoints + 1 : npoints;

  // The type of entropy we are going to use (depends on the type of image,
  // positive only, or positive and/or negative)
  MaxentData_sptr maxentData;
  if (positiveImage) {
    maxentData = boost::make_shared<MaxentData>(
        boost::make_shared<MaxentEntropyPositiveValues>());
  } else {
    maxentData = boost::make_shared<MaxentData>(
        boost::make_shared<MaxentEntropyNegativeValues>());
  }

  // Output workspaces
  MatrixWorkspace_sptr outImageWS;
  MatrixWorkspace_sptr outDataWS;
  MatrixWorkspace_sptr outEvolChi;
  MatrixWorkspace_sptr outEvolTest;

  nspec = complex ? nspec / 2 : nspec;
  outImageWS =
      WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints);
  outDataWS =
      WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints);
  outEvolChi = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter);
  outEvolTest = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter);

  npoints *= 2;
  for (size_t s = 0; s < nspec; s++) {

    // Start distribution (flat background)
    std::vector<double> image(npoints, background);

    if (complex) {
      auto dataRe = inWS->readY(s);
      auto dataIm = inWS->readY(s + nspec);
      auto errorsRe = inWS->readE(s);
      auto errorsIm = inWS->readE(s + nspec);
      maxentData->loadComplex(dataRe, dataIm, errorsRe, errorsIm, image,
                              background);
    } else {
      auto data = inWS->readY(s);
      auto error = inWS->readE(s);
      maxentData->loadReal(data, error, image, background);
    }

    // To record the algorithm's progress
    std::vector<double> evolChi(niter, 0.);
    std::vector<double> evolTest(niter, 0.);

    // Progress
    Progress progress(this, 0, 1, niter);

    // Run maxent algorithm
    for (size_t it = 0; it < niter; it++) {

      // Calculate quadratic model coefficients
      // (SB eq. 21 and 24)
      maxentData->calculateQuadraticCoefficients();
      double currAngle = maxentData->getAngle();
      double currChisq = maxentData->getChisq();
      auto coeffs = maxentData->getQuadraticCoefficients();

      // Calculate delta to construct new image (SB eq. 25)
      auto delta = move(coeffs, chiTarget / currChisq, chiEps, alphaIter);

      // Apply distance penalty (SB eq. 33)
      image = maxentData->getImage();
      delta = applyDistancePenalty(delta, coeffs, image, background, distEps);

      // Update image according to 'delta' and calculate the new Chi-square
      maxentData->updateImage(delta);
      currChisq = maxentData->getChisq();

      // Record the evolution of Chi-square and angle(S,C)
      evolChi[it] = currChisq;
      evolTest[it] = currAngle;

      // Stop condition, solution found
      if ((std::abs(currChisq / chiTarget - 1.) < chiEps) &&
          (currAngle < angle)) {
        break;
      }

      // Check for canceling the algorithm
      if (!(it % 1000)) {
        interruption_point();
      }

      progress.report();

    } // iterations

    // Get calculated data
    auto solData = maxentData->getReconstructedData();
    auto solImage = maxentData->getImage();

    // Populate the output workspaces
    populateDataWS(inWS, s, nspec, solData, outDataWS);
    populateImageWS(inWS, s, nspec, solImage, outImageWS, autoShift);

    // Populate workspaces recording the evolution of Chi and Test
    // X values
    for (size_t it = 0; it < niter; it++) {
      outEvolChi->dataX(s)[it] = static_cast<double>(it);
      outEvolTest->dataX(s)[it] = static_cast<double>(it);
    }
    // Y values
    outEvolChi->dataY(s).assign(evolChi.begin(), evolChi.end());
    outEvolTest->dataY(s).assign(evolTest.begin(), evolTest.end());
    // No errors

  } // Next spectrum

  setProperty("EvolChi", outEvolChi);
  setProperty("EvolAngle", outEvolTest);
  setProperty("ReconstructedImage", outImageWS);
  setProperty("ReconstructedData", outDataWS);
}
/**  Calculate the integral asymmetry for a workspace (red & green).
*   The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms.
*   @param ws_red :: The red workspace
*   @param ws_green :: The green workspace
*   @param Y :: Reference to a variable receiving the value of asymmetry
*   @param E :: Reference to a variable receiving the value of the error
*/
void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws_red,
        API::MatrixWorkspace_sptr ws_green,double& Y, double& E)
{
    if ( !m_autogroup )
    {
        groupDetectors(ws_red,m_backward_list);
        groupDetectors(ws_red,m_forward_list);
        groupDetectors(ws_green,m_backward_list);
        groupDetectors(ws_green,m_forward_list);
    }

    Property* startXprop = getProperty("TimeMin");
    Property* endXprop = getProperty("TimeMax");
    bool setX = !startXprop->isDefault() && !endXprop->isDefault();
    double startX(0.0),endX(0.0);
    if (setX)
    {
        startX = getProperty("TimeMin");
        endX = getProperty("TimeMax");
    }
    if (!m_int)
    {   //  "Differential asymmetry"

        API::MatrixWorkspace_sptr tmpWS = API::WorkspaceFactory::Instance().create(
                                              ws_red,1,ws_red->readX(0).size(),ws_red->readY(0).size());

        for(size_t i=0; i<tmpWS->dataY(0).size(); i++)
        {
            double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i];
            FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0;
            double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i];
            BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0;
            double ZF = ( ws_green->readY(0)[i] - ws_red->readY(0)[i] ) * FNORM;
            double ZB = ( ws_green->readY(1)[i] - ws_red->readY(1)[i] ) * BNORM;
            tmpWS->dataY(0)[i] = ZB - ZF;
            tmpWS->dataE(0)[i] = (1.0+ZF*ZF)*FNORM+(1.0+ZB*ZB)*BNORM;
        }

        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace",tmpWS);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace");

        Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
        E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
    }
    else
    {
        //  "Integral asymmetry"
        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace", ws_red);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace");

        integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace", ws_green);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace");

        double YIF = ( intWS_green->readY(0)[0] - intWS_red->readY(0)[0] ) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] );
        double YIB = ( intWS_green->readY(1)[0] - intWS_red->readY(1)[0] ) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] );

        Y = YIB - YIF;

        double VARIF = (1.0 + YIF*YIF) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] );
        double VARIB = (1.0 + YIB*YIB) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] );

        E = sqrt( VARIF + VARIB );
    }

}
/**  Calculate the integral asymmetry for a workspace.
*   The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms.
*   @param ws :: The workspace
*   @param Y :: Reference to a variable receiving the value of asymmetry
*   @param E :: Reference to a variable receiving the value of the error
*/
void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws, double& Y, double& E)
{
    Property* startXprop = getProperty("TimeMin");
    Property* endXprop = getProperty("TimeMax");
    bool setX = !startXprop->isDefault() && !endXprop->isDefault();
    double startX(0.0),endX(0.0);
    if (setX)
    {
        startX = getProperty("TimeMin");
        endX = getProperty("TimeMax");
    }
    if (!m_int)
    {   //  "Differential asymmetry"
        IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc");
        asym->initialize();
        asym->setProperty("InputWorkspace",ws);
        asym->setPropertyValue("OutputWorkspace","tmp");
        if ( !m_autogroup )
        {
            asym->setProperty("ForwardSpectra",m_forward_list);
            asym->setProperty("BackwardSpectra",m_backward_list);
        }
        asym->execute();
        MatrixWorkspace_sptr asymWS = asym->getProperty("OutputWorkspace");

        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace",asymWS);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace");

        Y = out->readY(0)[0];
        E = out->readE(0)[0];
    }
    else
    {
        //  "Integral asymmetry"
        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace", ws);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr intWS = integr->getProperty("OutputWorkspace");

        IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc");
        asym->initialize();
        asym->setProperty("InputWorkspace",intWS);
        asym->setPropertyValue("OutputWorkspace","tmp");
        if ( !m_autogroup )
        {
            asym->setProperty("ForwardSpectra",m_forward_list);
            asym->setProperty("BackwardSpectra",m_backward_list);
        }
        asym->execute();
        MatrixWorkspace_sptr out = asym->getProperty("OutputWorkspace");

        Y = out->readY(0)[0];
        E = out->readE(0)[0];

    }


}
Example #12
0
void SofQWCentre::exec() {
  using namespace Geometry;

  MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");

  // Do the full check for common binning
  if (!WorkspaceHelpers::commonBoundaries(inputWorkspace)) {
    g_log.error(
        "The input workspace must have common binning across all spectra");
    throw std::invalid_argument(
        "The input workspace must have common binning across all spectra");
  }

  std::vector<double> verticalAxis;
  MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace(
      inputWorkspace, getProperty("QAxisBinning"), verticalAxis);
  setProperty("OutputWorkspace", outputWorkspace);

  // Holds the spectrum-detector mapping
  std::vector<specnum_t> specNumberMapping;
  std::vector<detid_t> detIDMapping;

  m_EmodeProperties.initCachedValues(*inputWorkspace, this);
  int emode = m_EmodeProperties.m_emode;

  // Get a pointer to the instrument contained in the workspace
  Instrument_const_sptr instrument = inputWorkspace->getInstrument();

  // Get the distance between the source and the sample (assume in metres)
  IComponent_const_sptr source = instrument->getSource();
  IComponent_const_sptr sample = instrument->getSample();
  V3D beamDir = sample->getPos() - source->getPos();
  beamDir.normalize();

  try {
    double l1 = source->getDistance(*sample);
    g_log.debug() << "Source-sample distance: " << l1 << '\n';
  } catch (Exception::NotFoundError &) {
    g_log.error("Unable to calculate source-sample distance");
    throw Exception::InstrumentDefinitionError(
        "Unable to calculate source-sample distance",
        inputWorkspace->getTitle());
  }

  // Conversion constant for E->k. k(A^-1) = sqrt(energyToK*E(meV))
  const double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass *
                           PhysicalConstants::meV * 1e-20 /
                           (PhysicalConstants::h * PhysicalConstants::h);

  // Loop over input workspace bins, reassigning data to correct bin in output
  // qw workspace
  const size_t numHists = inputWorkspace->getNumberHistograms();
  const size_t numBins = inputWorkspace->blocksize();
  Progress prog(this, 0.0, 1.0, numHists);
  for (int64_t i = 0; i < int64_t(numHists); ++i) {
    try {
      // Now get the detector object for this histogram
      IDetector_const_sptr spectrumDet = inputWorkspace->getDetector(i);
      if (spectrumDet->isMonitor())
        continue;

      const double efixed = m_EmodeProperties.getEFixed(*spectrumDet);

      // For inelastic scattering the simple relationship q=4*pi*sinTheta/lambda
      // does not hold. In order to
      // be completely general we must calculate the momentum transfer by
      // calculating the incident and final
      // wave vectors and then use |q| = sqrt[(ki - kf)*(ki - kf)]
      DetectorGroup_const_sptr detGroup =
          boost::dynamic_pointer_cast<const DetectorGroup>(spectrumDet);
      std::vector<IDetector_const_sptr> detectors;
      if (detGroup) {
        detectors = detGroup->getDetectors();
      } else {
        detectors.push_back(spectrumDet);
      }

      const size_t numDets = detectors.size();
      const double numDets_d = static_cast<double>(
          numDets); // cache to reduce number of static casts
      const MantidVec &Y = inputWorkspace->readY(i);
      const MantidVec &E = inputWorkspace->readE(i);
      const MantidVec &X = inputWorkspace->readX(i);

      // Loop over the detectors and for each bin calculate Q
      for (size_t idet = 0; idet < numDets; ++idet) {
        IDetector_const_sptr det = detectors[idet];
        // Calculate kf vector direction and then Q for each energy bin
        V3D scatterDir = (det->getPos() - sample->getPos());
        scatterDir.normalize();
        for (size_t j = 0; j < numBins; ++j) {
          const double deltaE = 0.5 * (X[j] + X[j + 1]);
          // Compute ki and kf wave vectors and therefore q = ki - kf
          double ei(0.0), ef(0.0);
          if (emode == 1) {
            ei = efixed;
            ef = efixed - deltaE;
            if (ef < 0) {
              std::string mess =
                  "Energy transfer requested in Direct mode exceeds incident "
                  "energy.\n Found for det ID: " +
                  std::to_string(idet) + " bin No " + std::to_string(j) +
                  " with Ei=" + boost::lexical_cast<std::string>(efixed) +
                  " and energy transfer: " +
                  boost::lexical_cast<std::string>(deltaE);
              throw std::runtime_error(mess);
            }
          } else {
            ei = efixed + deltaE;
            ef = efixed;
            if (ef < 0) {
              std::string mess =
                  "Incident energy of a neutron is negative. Are you trying to "
                  "process Direct data in Indirect mode?\n Found for det ID: " +
                  std::to_string(idet) + " bin No " + std::to_string(j) +
                  " with efied=" + boost::lexical_cast<std::string>(efixed) +
                  " and energy transfer: " +
                  boost::lexical_cast<std::string>(deltaE);
              throw std::runtime_error(mess);
            }
          }

          if (ei < 0)
            throw std::runtime_error(
                "Negative incident energy. Check binning.");

          const V3D ki = beamDir * sqrt(energyToK * ei);
          const V3D kf = scatterDir * (sqrt(energyToK * (ef)));
          const double q = (ki - kf).norm();

          // Test whether it's in range of the Q axis
          if (q < verticalAxis.front() || q > verticalAxis.back())
            continue;
          // Find which q bin this point lies in
          const MantidVec::difference_type qIndex =
              std::upper_bound(verticalAxis.begin(), verticalAxis.end(), q) -
              verticalAxis.begin() - 1;

          // Add this spectra-detector pair to the mapping
          specNumberMapping.push_back(
              outputWorkspace->getSpectrum(qIndex).getSpectrumNo());
          detIDMapping.push_back(det->getID());

          // And add the data and it's error to that bin, taking into account
          // the number of detectors contributing to this bin
          outputWorkspace->dataY(qIndex)[j] += Y[j] / numDets_d;
          // Standard error on the average
          outputWorkspace->dataE(qIndex)[j] =
              sqrt((pow(outputWorkspace->readE(qIndex)[j], 2) + pow(E[j], 2)) /
                   numDets_d);
        }
      }

    } catch (Exception::NotFoundError &) {
      // Get to here if exception thrown when calculating distance to detector
      // Presumably, if we get to here the spectrum will be all zeroes anyway
      // (from conversion to E)
      continue;
    }
    prog.report();
  }

  // If the input workspace was a distribution, need to divide by q bin width
  if (inputWorkspace->isDistribution())
    this->makeDistribution(outputWorkspace, verticalAxis);

  // Set the output spectrum-detector mapping
  SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping);
  outputWorkspace->updateSpectraUsing(outputDetectorMap);
}
/** Convert a SPICE 2D Det MatrixWorkspace to MDEvents and append to an
 * MDEventWorkspace
 * It is optional to use a virtual instrument or copy from input data workspace
 * @brief ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents
 * @param dataws :: data matrix workspace
 * @param usevirtual :: boolean flag to use virtual instrument
 * @param startdetid :: starting detid for detectors from this workspace mapping
 * to virtual instrument in MDEventWorkspace
 * @param runnumber :: run number for all MDEvents created from this matrix
 * workspace
 */
void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents(
    MatrixWorkspace_sptr dataws, bool usevirtual, const detid_t &startdetid,
    const int runnumber) {
  // Create transformation matrix from which the transformation is
  Kernel::DblMatrix rotationMatrix;
  setupTransferMatrix(dataws, rotationMatrix);

  g_log.information() << "Before insert new event, output workspace has "
                      << m_outputWS->getNEvents() << "Events.\n";

  // Creates a new instance of the MDEventInserte to output workspace
  MDEventWorkspace<MDEvent<3>, 3>::sptr mdws_mdevt_3 =
      boost::dynamic_pointer_cast<MDEventWorkspace<MDEvent<3>, 3>>(m_outputWS);
  MDEventInserter<MDEventWorkspace<MDEvent<3>, 3>::sptr> inserter(mdws_mdevt_3);

  // Calcualte k_i: it is assumed that all k_i are same for one Pt.
  // number, i.e., one 2D XML file
  Kernel::V3D sourcePos = dataws->getInstrument()->getSource()->getPos();
  Kernel::V3D samplePos = dataws->getInstrument()->getSample()->getPos();
  if (dataws->readX(0).size() != 2)
    throw std::runtime_error(
        "Input matrix workspace has wrong dimension in X-axis.");
  double momentum = 0.5 * (dataws->readX(0)[0] + dataws->readX(0)[1]);
  Kernel::V3D ki = (samplePos - sourcePos) * (momentum / sourcePos.norm());

  g_log.debug() << "Source at " << sourcePos.toString()
                << ", Norm = " << sourcePos.norm()
                << ", momentum = " << momentum << "\n"
                << "k_i = " << ki.toString() << "\n";

  // Go though each spectrum to conver to MDEvent
  size_t numspec = dataws->getNumberHistograms();
  double maxsignal = 0;
  size_t nummdevents = 0;
  for (size_t iws = 0; iws < numspec; ++iws) {
    // Get detector positions and signal
    double signal = dataws->readY(iws)[0];
    // Skip event with 0 signal
    if (signal < 0.001)
      continue;
    double error = dataws->readE(iws)[0];
    Kernel::V3D detpos = dataws->getDetector(iws)->getPos();
    std::vector<Mantid::coord_t> q_sample(3);

    // Calculate Q-sample and new detector ID in virtual instrument.
    Kernel::V3D qlab = convertToQSample(samplePos, ki, detpos, momentum,
                                        q_sample, rotationMatrix);
    detid_t native_detid = dataws->getDetector(iws)->getID();
    detid_t detid = native_detid + startdetid;

    // Insert
    inserter.insertMDEvent(
        static_cast<float>(signal), static_cast<float>(error * error),
        static_cast<uint16_t>(runnumber), detid, q_sample.data());
    updateQRange(q_sample);

    g_log.debug() << "Q-lab = " << qlab.toString() << "\n";
    g_log.debug() << "Insert DetID " << detid << ", signal = " << signal
                  << ", with q_sample = " << q_sample[0] << ", " << q_sample[1]
                  << ", " << q_sample[2] << "\n";

    // Update some statistical inforamtion
    if (signal > maxsignal)
      maxsignal = signal;
    ++nummdevents;
  }

  g_log.information() << "Imported Matrixworkspace: Max. Signal = " << maxsignal
                      << ", Add " << nummdevents << " MDEvents "
                      << "\n";

  // Add experiment info including instrument, goniometer and run number
  ExperimentInfo_sptr expinfo = boost::make_shared<ExperimentInfo>();
  if (usevirtual)
    expinfo->setInstrument(m_virtualInstrument);
  else {
    Geometry::Instrument_const_sptr tmp_inst = dataws->getInstrument();
    expinfo->setInstrument(tmp_inst);
  }
  expinfo->mutableRun().setGoniometer(dataws->run().getGoniometer(), false);
  expinfo->mutableRun().addProperty("run_number", runnumber);
  // Add all the other propertys from original data workspace
  const std::vector<Kernel::Property *> vec_property =
      dataws->run().getProperties();
  for (auto property : vec_property) {
    expinfo->mutableRun().addProperty(property->clone());
  }

  m_outputWS->addExperimentInfo(expinfo);

  return;
}
Example #14
0
  //----------------------------------------------------------------------------------------------
  /// @copydoc Mantid::API::Algorithm::exec()
  void ResetNegatives::exec()
  {
    MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace");
    MatrixWorkspace_sptr outputWS = this->getProperty("OutputWorkspace");

    // get the minimum for each spectrum
    IAlgorithm_sptr alg = this->createChildAlgorithm("Min", 0., .1);
    alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS);
    alg->executeAsChildAlg();
    MatrixWorkspace_const_sptr minWS = alg->getProperty("OutputWorkspace");

    // determine if there is anything to do
    int64_t nHist = static_cast<int64_t>(minWS->getNumberHistograms());
    bool hasNegative = false;
    for (int64_t i = 0; i < nHist; i++)
    {
      if (minWS->readY(i)[0] < 0)
      {
        hasNegative = true;
      }
      break;
    }

    // get out early if there is nothing to do
    if (!hasNegative)
    {
      g_log.information() << "No values are negative. Copying InputWorkspace to OutputWorkspace\n";
      if (inputWS != outputWS)
      {
        IAlgorithm_sptr alg = this->createChildAlgorithm("CloneWorkspace", .1, 1.);
        alg->setProperty<Workspace_sptr>("InputWorkspace", inputWS);
        alg->executeAsChildAlg();

        Workspace_sptr temp = alg->getProperty("OutputWorkspace");
        setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(temp));
      }
      return;
    }

    // sort the event list to make it fast and thread safe
    DataObjects::EventWorkspace_const_sptr eventWS
                 = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>( inputWS );
    if (eventWS)
      eventWS->sortAll(DataObjects::TOF_SORT, NULL);

    Progress prog(this, .1, 1., 2*nHist);

    // generate output workspace - copy X and dY
    outputWS = API::WorkspaceFactory::Instance().create(inputWS);
    PARALLEL_FOR2(inputWS,outputWS)
    for (int64_t i = 0; i < nHist; i++)
    {
      PARALLEL_START_INTERUPT_REGION
      outputWS->dataY(i) = inputWS->readY(i);
      outputWS->dataE(i) = inputWS->readE(i);
      outputWS->setX(i, inputWS->refX(i)); // share the pointer more
      prog.report();
      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

    // do the actual work
    if (this->getProperty("AddMinimum"))
    {
        this->pushMinimum(minWS, outputWS, prog);
    }
    else
    {
      this->changeNegatives(minWS, this->getProperty("ResetValue"), outputWS, prog);
    }

    setProperty("OutputWorkspace",outputWS);
  }