예제 #1
0
파일: MergeRuns.cpp 프로젝트: mducle/mantid
/** Calculates the rebin parameters in the case where the bins of the two
 * workspaces intersect.
 *  'Intersect' is used in the sense of two intersecting sets.
 *  @param X1 ::     The bin boundaries from the first workspace
 *  @param i ::      Indicates the index in X1 immediately before the overlap
 * region starts
 *  @param X2 ::     The bin boundaries from the second workspace
 *  @param params :: A reference to the vector of rebinning parameters
 */
void MergeRuns::intersectionParams(const MantidVec &X1, int64_t &i,
                                   const MantidVec &X2,
                                   std::vector<double> &params) const {
    // First calculate the number of bins in each workspace that are in the
    // overlap region
    int64_t overlapbins1, overlapbins2;
    overlapbins1 = X1.size() - i;
    for (overlapbins2 = 0; X2[overlapbins2] < X1.back(); ++overlapbins2) {
    }

    // We want to use whichever one has the larger bins (on average)
    if (overlapbins1 < overlapbins2) {
        // In this case we want the rest of the bins from the first workspace.....
        for (; i < static_cast<int64_t>(X1.size()); ++i) {
            params.push_back(X1[i] - X1[i - 1]);
            params.push_back(X1[i]);
        }
        // Now remove the last bin & boundary
        params.pop_back();
        params.pop_back();
        // ....and then the non-overlap ones from the second workspace
        for (size_t j = overlapbins2; j < X2.size(); ++j) {
            params.push_back(X2[j] - params.back());
            params.push_back(X2[j]);
        }
    } else {
        // In this case we just have to add all the bins from the second workspace
        for (size_t j = 1; j < X2.size(); ++j) {
            params.push_back(X2[j] - params.back());
            params.push_back(X2[j]);
        }
    }
}
예제 #2
0
/** Deals with the (rare) case where the flightpath is longer than the reference
 *  Note that in this case both T1 & T2 will be greater than Tmax
 */
std::pair<int, int>
UnwrapMonitor::handleFrameOverlapped(const MantidVec &xdata, const double &Ld,
                                     std::vector<double> &tempX) {
  // Calculate the interval to exclude
  const double Dt = (m_Tmax - m_Tmin) * (1 - (m_LRef / Ld));
  // This gives us new minimum & maximum tof values
  const double minT = m_Tmin + Dt;
  const double maxT = m_Tmax - Dt;
  // Can have situation where Ld is so much larger than Lref that everything
  // would be excluded.
  // This is an invalid input - warn and leave spectrum unwrapped
  if (minT > maxT) {
    g_log.warning() << "Invalid input, Ld (" << Ld << ") >> Lref (" << m_LRef
                    << "). Current spectrum will not be unwrapped.\n";
    return std::make_pair(0, static_cast<int>(xdata.size() - 1));
  }

  int min = 0, max = static_cast<int>(xdata.size());
  for (unsigned int j = 0; j < m_XSize; ++j) {
    const double T = xdata[j];
    if (T < minT) {
      min = j + 1;
      tempX.erase(tempX.begin());
    } else if (T > maxT) {
      tempX.erase(tempX.end() - (max - j), tempX.end());
      max = j - 1;
      break;
    }
  }
  return std::make_pair(min, max);
}
예제 #3
0
    /**
     * Find the overlap of the inputWS with the given polygon
     * @param oldAxis1 :: Axis 1 bin boundaries from the input grid
     * @param oldAxis2 :: Axis 2 bin boundaries from the input grid
     * @param newPoly :: The new polygon to test
     * @returns A list of intersection locations with weights of the overlap
     */
    std::vector<Rebin2D::BinWithWeight> 
    Rebin2D::findIntersections(const MantidVec & oldAxis1, const MantidVec & oldAxis2,
                               const Geometry::ConvexPolygon & newPoly) const
    {
      std::vector<BinWithWeight> overlaps;
      overlaps.reserve(5); // Have a guess at a posible limit

      const size_t nxpoints(oldAxis1.size()-1), nypoints(oldAxis2.size()-1);
      const double yn_lo(newPoly[0].Y()), yn_hi(newPoly[1].Y());
      const double xn_lo(newPoly[0].X()), xn_hi(newPoly[2].X());
      for(size_t i = 0; i < nypoints; ++i)
      {
        const double yo_lo(oldAxis2[i]), yo_hi(oldAxis2[i+1]);
        // Check if there is a possibility of overlap
        if( yo_hi < yn_lo || yo_lo > yn_hi ) continue;
        for(size_t j = 0; j < nxpoints; ++j)
        {
          const double xo_lo(oldAxis1[j]), xo_hi(oldAxis1[j+1]);
          // Check if there is a possibility of overlap
          if( xo_hi < xn_lo || xo_lo > xn_hi ) continue;
          ConvexPolygon oldPoly(xo_lo, xo_hi, yo_lo, yo_hi);
          try
          {
            ConvexPolygon overlap = intersectionByLaszlo(newPoly, oldPoly);
            overlaps.push_back(BinWithWeight(i,j,overlap.area()/oldPoly.area()));
          }
          catch(Geometry::NoIntersectionException &)
          {}            
        }
      }
      return overlaps;
    }
예제 #4
0
int UnwrapSNS::unwrapX(const MantidVec &datain, MantidVec &dataout,
                       const double &Ld) {
  MantidVec tempX_L; // lower half - to be frame wrapped
  tempX_L.reserve(m_XSize);
  tempX_L.clear();
  MantidVec tempX_U; // upper half - to not be frame wrapped
  tempX_U.reserve(m_XSize);
  tempX_U.clear();

  double filterVal = m_Tmin * Ld / m_LRef;
  dataout.clear();
  int specialBin = 0;
  for (int bin = 0; bin < m_XSize; ++bin) {
    // This is the time-of-flight value under consideration in the current
    // iteration of the loop
    const double tof = datain[bin];
    if (tof < filterVal) {
      tempX_L.push_back(tof + m_frameWidth);
      // Record the bins that fall in this range for copying over the data &
      // errors
      if (specialBin < bin)
        specialBin = bin;
    } else {
      tempX_U.push_back(tof);
    }
  } // loop over X values

  // now put it back into the vector supplied
  dataout.clear();
  dataout.insert(dataout.begin(), tempX_U.begin(), tempX_U.end());
  dataout.insert(dataout.end(), tempX_L.begin(), tempX_L.end());
  assert(datain.size() == dataout.size());

  return specialBin;
}
예제 #5
0
파일: MergeRuns.cpp 프로젝트: mducle/mantid
/** Calculates the rebin parameters in the case where the range of the second
 * workspace is
 *  entirely within that of the first workspace.
 *  'Inclusion' is used in the sense of a set being included in anothre.
 *  @param X1 ::     The bin boundaries from the first workspace
 *  @param i ::      Indicates the index in X1 immediately before the overlap
 * region starts
 *  @param X2 ::     The bin boundaries from the second workspace
 *  @param params :: A reference to the vector of rebinning parameters
 */
void MergeRuns::inclusionParams(const MantidVec &X1, int64_t &i,
                                const MantidVec &X2,
                                std::vector<double> &params) const {
    // First calculate the number of bins in each workspace that are in the
    // overlap region
    int64_t overlapbins1, overlapbins2;
    for (overlapbins1 = 1; X1[i + overlapbins1] < X2.back(); ++overlapbins1) {
    }
    //++overlapbins1;
    overlapbins2 = X2.size() - 1;

    // In the overlap region, we want to use whichever one has the larger bins (on
    // average)
    if (overlapbins1 + 1 <= overlapbins2) {
        // In the case where the first workspace has larger bins it's easy
        // - just add the rest of X1's bins
        for (; i < static_cast<int64_t>(X1.size()); ++i) {
            params.push_back(X1[i] - X1[i - 1]);
            params.push_back(X1[i]);
        }
    } else {
        // In this case we want all of X2's bins first (without the first and last
        // boundaries)
        for (size_t j = 1; j < X2.size() - 1; ++j) {
            params.push_back(X2[j] - params.back());
            params.push_back(X2[j]);
        }
        // And now those from X1 that lie above the overlap region
        i += overlapbins1;
        for (; i < static_cast<int64_t>(X1.size()); ++i) {
            params.push_back(X1[i] - params.back());
            params.push_back(X1[i]);
        }
    }
}
예제 #6
0
/**
 * Create workspace to store the structure factor.
 * First spectrum is the real part, second spectrum is the imaginary part
 * X values are the modulus of the Q-vectors
 * @param h5file file identifier
 * @param gws pointer to WorkspaceGroup being filled
 * @param setName string name of dataset
 * @param qvmod vector of Q-vectors' moduli
 * @param sorting_indexes permutation of qvmod indexes to render it in increasing order of momemtum transfer
 */
void LoadSassena::loadFQ(const hid_t& h5file, API::WorkspaceGroup_sptr gws, const std::string setName, const MantidVec &qvmod, const std::vector<int> &sorting_indexes)
{
  const std::string gwsName = this->getPropertyValue("OutputWorkspace");
  int nq = static_cast<int>( qvmod.size() ); //number of q-vectors

  DataObjects::Workspace2D_sptr ws = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(API::WorkspaceFactory::Instance().create("Workspace2D", 2, nq, nq));
  const std::string wsName = gwsName + std::string("_") + setName;
  ws->setTitle(wsName);

  double* buf = new double[nq*2];
  this->dataSetDouble(h5file,setName,buf);
  MantidVec& re = ws->dataY(0); // store the real part
  ws->dataX(0) = qvmod;  //X-axis values are the modulus of the q vector
  MantidVec& im = ws->dataY(1); // store the imaginary part
  ws->dataX(1) = qvmod;
  double *curr = buf;
  for(int iq=0; iq<nq; iq++){
    const int index=sorting_indexes[iq];
    re[index]=curr[0];
    im[index]=curr[1];
    curr+=2;
  }
  delete[] buf;

  // Set the Units
  ws->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("MomentumTransfer");

  this->registerWorkspace(gws,wsName,ws, "X-axis: Q-vector modulus; Y-axis: intermediate structure factor");
}
예제 #7
0
파일: Divide.cpp 프로젝트: mcvine/mantid
void Divide::performBinaryOperation(const MantidVec &lhsX,
                                    const MantidVec &lhsY,
                                    const MantidVec &lhsE, const double rhsY,
                                    const double rhsE, MantidVec &YOut,
                                    MantidVec &EOut) {
  (void)lhsX; // Avoid compiler warning

  if (rhsY == 0 && m_warnOnZeroDivide)
    g_log.warning() << "Division by zero: the RHS is a single-valued vector "
                       "with value zero."
                    << "\n";

  // Do the right-hand part of the error calculation just once
  const double rhsFactor = pow(rhsE / rhsY, 2);
  const int bins = static_cast<int>(lhsE.size());
  for (int j = 0; j < bins; ++j) {
    // Get reference to input Y
    const double leftY = lhsY[j];

    // see comment in the function above for the error formula
    EOut[j] = sqrt(pow(lhsE[j], 2) + pow(leftY, 2) * rhsFactor) / fabs(rhsY);
    // Copy the result last in case one of the input workspaces is also any
    // output
    YOut[j] = leftY / rhsY;
  }
}
/**
 * @param xValues The X data for the fitted spectrum
 */
void ComptonScatteringCountRate::createPositivityCM(const MantidVec &xValues) {
  // -- Constraint matrix for J(y) > 0 --
  // The first N columns are filled with J(y) for each mass + N_h for the first
  // mass hermite
  // terms included + (n+1) for each termn the background of order n
  // The background columns are filled with x^j/error where j=(1,n+1)
  const size_t nrows(xValues.size());
  size_t nColsCMatrix(m_fixedParamIndices.size());
  m_cmatrix = Kernel::DblMatrix(nrows, nColsCMatrix);

  // Fill background values as they don't change at all
  if (m_bkgdPolyN > 0) {
    size_t polyStartCol = nColsCMatrix - m_bkgdPolyN - 1;
    for (size_t i = 0; i < nrows; ++i) // rows
    {
      double *row = m_cmatrix[i];
      const double &xi = xValues[i];
      const double &erri = m_errors[i];
      size_t polyN = m_bkgdPolyN;
      for (size_t j = polyStartCol; j < nColsCMatrix; ++j) // cols
      {
        row[j] = std::pow(xi, static_cast<double>(polyN)) / erri;
        --polyN;
      }
    }
  }
}
예제 #9
0
void WeightedMean::performBinaryOperation(const MantidVec& lhsX, const MantidVec& lhsY, const MantidVec& lhsE,
                                          const double rhsY, const double rhsE, MantidVec& YOut, MantidVec& EOut)
{
	UNUSED_ARG(lhsX);
  assert( lhsX.size() == 1 );
  // If we get here we've got two single column workspaces so it's easy.
  if (lhsE[0] > 0.0 && rhsE > 0.0)
  {
    const double err1 = lhsE[0]*lhsE[0];
    const double err2 = rhsE*rhsE;
    YOut[0] = (lhsY[0]/err1)+(rhsY/err2);
    EOut[0] = (err1*err2)/(err1+err2);
    YOut[0] *= EOut[0];
    EOut[0] = sqrt(EOut[0]); 
  }
  else if (lhsE[0] > 0.0 && rhsE <= 0.0)
  {
    YOut[0] = lhsY[0];
    EOut[0] = lhsE[0];
  }
  else if (lhsE[0] <= 0.0 && rhsE > 0.0)
  {
    YOut[0] = rhsY;
    EOut[0] = rhsE;
  }
  else
  {
    YOut[0] = 0.0;
    EOut[0] = 0.0;
  }
}
예제 #10
0
/// Retrieve and check the Start/EndX parameters, if set
void Linear::setRange(const MantidVec& X, const MantidVec& Y)
{
  //read in the values that the user selected
  double startX = getProperty("StartX");
  double endX = getProperty("EndX");
  //If the user didn't a start default to the start of the data
  if ( isEmpty(startX) ) startX = X.front();
  //the default for the end is the end of the data
  if ( isEmpty(endX) ) endX = X.back();

  // Check the validity of startX
  if ( startX < X.front() )
  {
    g_log.warning("StartX out of range! Set to start of frame.");
    startX = X.front();
  }
  // Now get the corresponding bin boundary that comes before (or coincides with) this value
  for (m_minX = 0; X[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 >= X.back() || endX < startX )
  {
    if ( endX != X.back() )
    {
      g_log.warning("EndX out of range! Set to end of frame");
      endX = X.back();
    }
    m_maxX = static_cast<int>(Y.size());
  }
  else
  {
    for (m_maxX = m_minX; X[m_maxX] < endX; ++m_maxX) {}
  }  
}
예제 #11
0
파일: Divide.cpp 프로젝트: mcvine/mantid
void Divide::performBinaryOperation(const MantidVec &lhsX,
                                    const MantidVec &lhsY,
                                    const MantidVec &lhsE,
                                    const MantidVec &rhsY,
                                    const MantidVec &rhsE, MantidVec &YOut,
                                    MantidVec &EOut) {
  (void)lhsX; // Avoid compiler warning

  const int bins = static_cast<int>(lhsE.size());

  for (int j = 0; j < bins; ++j) {
    // Get references to the input Y's
    const double leftY = lhsY[j];
    const double rightY = rhsY[j];

    //  error dividing two uncorrelated numbers, re-arrange so that you don't
    //  get infinity if leftY==0 (when rightY=0 the Y value and the result will
    //  both be infinity)
    // (Sa/a)2 + (Sb/b)2 = (Sc/c)2
    // (Sa c/a)2 + (Sb c/b)2 = (Sc)2
    // = (Sa 1/b)2 + (Sb (a/b2))2
    // (Sc)2 = (1/b)2( (Sa)2 + (Sb a/b)2 )
    EOut[j] =
        sqrt(pow(lhsE[j], 2) + pow(leftY * rhsE[j] / rightY, 2)) / fabs(rightY);

    // Copy the result last in case one of the input workspaces is also any
    // output
    YOut[j] = leftY / rightY;
    ;
  }
}
예제 #12
0
 MantidVec
 operator()(const MantidVec &_Left,
            const MantidVec &_Right) const { // apply operator+ to operands
   MantidVec v(_Left.size());
   std::transform(_Left.begin(), _Left.end(), _Right.begin(), v.begin(),
                  SumGaussError<double>());
   return (v);
 }
예제 #13
0
파일: MergeRuns.cpp 프로젝트: mducle/mantid
/** Calculates the rebin paramters in the case where the two input workspaces do
 * not overlap at all.
 *  @param X1 ::     The bin boundaries from the first workspace
 *  @param X2 ::     The bin boundaries from the second workspace
 *  @param params :: A reference to the vector of rebinning parameters
 */
void MergeRuns::noOverlapParams(const MantidVec &X1, const MantidVec &X2,
                                std::vector<double> &params) const {
    // Add all the bins from the first workspace
    for (size_t i = 1; i < X1.size(); ++i) {
        params.push_back(X1[i - 1]);
        params.push_back(X1[i] - X1[i - 1]);
    }
    // Put a single bin in the 'gap' (but check first the 'gap' isn't zero)
    if (X1.back() < X2.front()) {
        params.push_back(X1.back());
        params.push_back(X2.front() - X1.back());
    }
    // Now add all the bins from the second workspace
    for (size_t j = 1; j < X2.size(); ++j) {
        params.push_back(X2[j - 1]);
        params.push_back(X2[j] - X2[j - 1]);
    }
    params.push_back(X2.back());
}
/// Returns vector with x-values of spectrum if MatrixWorkspace does not contain
/// histogram data.
MantidVec FunctionDomain1DSpectrumCreator::getVectorNonHistogram() const {
  const MantidVec wsXData = m_matrixWorkspace->readX(m_workspaceIndex);
  size_t wsXSize = wsXData.size();

  if (wsXSize < 1) {
    throw std::invalid_argument(
        "Workspace2D with less than one x-value cannot be processed.");
  }

  return MantidVec(wsXData);
}
예제 #15
0
파일: FFT.cpp 프로젝트: liyulun/mantid
/**
 * Returns the phase shift to apply
 * If "AutoShift" is set, calculates this automatically as -X[N/2]
 * Otherwise, returns user-supplied "Shift" (or zero if none set)
 * @param xValues :: [input] Reference to X values of input workspace
 * @returns :: Phase shift
 */
double FFT::getPhaseShift(const MantidVec &xValues) {
  double shift = 0.0;
  const bool autoshift = getProperty("AutoShift");
  if (autoshift) {
    const size_t mid = xValues.size() / 2;
    shift = -xValues[mid];
  } else {
    shift = getProperty("Shift");
  }
  shift *= 2 * M_PI;
  return shift;
}
예제 #16
0
    void PoissonErrors::performBinaryOperation(const MantidVec& lhsX, const MantidVec& lhsY, const MantidVec& lhsE,
                                               const double rhsY, const double rhsE, MantidVec& YOut, MantidVec& EOut)
    {
      (void) lhsE; (void) lhsX; //Avoid compiler warning

      assert( lhsX.size() == 1 );
      // If we get here we've got two single column workspaces so it's easy.
      YOut[0] = lhsY[0];
      
      const double fractional = rhsY ? rhsE/rhsY : 0.0;
      EOut[0] = fractional*lhsY[0];
    }
예제 #17
0
/** Zeroes data (Y/E) at the end of a spectrum
 *  @param start :: The index to start zeroing at
 *  @param end ::   The index to end zeroing at
 *  @param Y ::     The data vector
 *  @param E ::     The error vector
 */
void RemoveBins::RemoveFromEnds(int start, int end, MantidVec& Y, MantidVec& E)
{
  if ( start ) --start;
  int size = static_cast<int>(Y.size());
  if ( end > size ) end = size;
  for (int j = start; j < end; ++j)
  {
    Y[j] = 0.0;
    E[j] = 0.0;
  }

  return;
}
예제 #18
0
파일: Q1D2.cpp 프로젝트: trnielsen/mantid
/** Divides the number of counts in each output Q bin by the wrighting ("number that would expected to arrive")
*  The errors are propogated using the uncorrolated error estimate for multiplication/division
*  @param[in] normSum the weighting for each bin
*  @param[in] normError2 square of the error on the normalization
*  @param[in, out] counts counts in each bin
*  @param[in, out] errors input the _square_ of the error on each bin, output the total error (unsquared)
*/
void Q1D2::normalize(const MantidVec & normSum, const MantidVec & normError2, MantidVec & counts, MantidVec & errors) const
{
  for (size_t k = 0; k < counts.size(); ++k)
  {
    // the normalisation is a = b/c where b = counts c =normalistion term
    const double c = normSum[k];
    const double a = counts[k] /= c;
    // when a = b/c, the formula for Da, the error on a, in terms of Db, etc. is (Da/a)^2 = (Db/b)^2 + (Dc/c)^2
    //(Da)^2 = ((Db/b)^2 + (Dc/c)^2)*(b^2/c^2) = ((Db/c)^2 + (b*Dc/c^2)^2) = (Db^2 + (b*Dc/c)^2)/c^2 = (Db^2 + (Dc*a)^2)/c^2
    //this will work as long as c>0, but then the above formula above can't deal with 0 either
    const double aOverc = a/c;
    errors[k] = std::sqrt(errors[k]/(c*c) + normError2[k]*aOverc*aOverc);
  }
}
예제 #19
0
/**
 * Get the start and end of the x-interval.
 * @param X :: The x-vector of a spectrum.
 * @param isHistogram :: Is the x-vector comming form a histogram? If it's true
 * the bin
 *   centres are used.
 * @return :: A pair of start x and end x.
 */
std::pair<double, double> WienerSmooth::getStartEnd(const MantidVec &X,
                                                    bool isHistogram) const {
  const size_t n = X.size();
  if (n < 3) {
    // 3 is the smallest number for this method to work without breaking
    throw std::runtime_error(
        "Number of bins/data points cannot be smaller than 3.");
  }
  if (isHistogram) {
    return std::make_pair((X[0] + X[1]) / 2, (X[n - 1] + X[n - 2]) / 2);
  }
  // else
  return std::make_pair(X.front(), X.back());
}
 /** Execute the algorithm.
  */
 void WeightedMeanOfWorkspace::exec()
 {
   MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace");
   // Check if it is an event workspace
   EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
   if (eventW != NULL)
   {
     throw std::runtime_error("WeightedMeanOfWorkspace cannot handle EventWorkspaces!");
   }
   // Create the output workspace
   MatrixWorkspace_sptr singleValued = WorkspaceFactory::Instance().create("WorkspaceSingleValue", 1, 1, 1);
   // Calculate weighted mean
   std::size_t numHists = inputWS->getNumberHistograms();
   double averageValue = 0.0;
   double weightSum = 0.0;
   for (std::size_t i = 0; i < numHists; ++i)
   {
     try
     {
       IDetector_const_sptr det = inputWS->getDetector(i);
       if( det->isMonitor() || det->isMasked() )
       {
         continue;
       }
     }
     catch (...)
     {
       // Swallow these if no instrument is found
       ;
     }
     MantidVec y = inputWS->dataY(i);
     MantidVec e = inputWS->dataE(i);
     double weight = 0.0;
     for (std::size_t j = 0; j < y.size(); ++j)
     {
       if (!boost::math::isnan(y[j]) && !boost::math::isinf(y[j]) &&
           !boost::math::isnan(e[j]) && !boost::math::isinf(e[j]))
       {
         weight = 1.0 / (e[j] * e[j]);
         averageValue += (y[j] * weight);
         weightSum += weight;
       }
     }
   }
   singleValued->dataX(0)[0] = 0.0;
   singleValued->dataY(0)[0] = averageValue / weightSum;
   singleValued->dataE(0)[0] = std::sqrt(weightSum);
   this->setProperty("OutputWorkspace", singleValued);
 }
예제 #21
0
/** Returns the number of background points
  *
  * Given a list of peaks and a vector with spectrum count data, this method returns the number of background points
  * contained in this spectrum. It is used for extraction of the background in order to allocate the correct vector
  * size before filling it.
  *
  * @param peakPositions :: Peak positions.
  * @param correlationCounts :: Data vector the peak positions refer to.
  * @return Number of background points.
  */
size_t PoldiPeakSearch::getNumberOfBackgroundPoints(std::list<MantidVec::const_iterator> peakPositions, const MantidVec &correlationCounts) const
{
    /* subtracting 2, to match original algorithm, where
     * the first and the last point of the spectrum are not
     * considered in this calculation.
     */
    size_t totalDataPoints = correlationCounts.size() - 2;
    size_t occupiedByPeaks = peakPositions.size() * (m_doubleMinimumDistance + 1);

    if(occupiedByPeaks > totalDataPoints) {
        throw(std::runtime_error("More data points occupied by peaks than existing data points - not possible."));
    }

    return totalDataPoints - occupiedByPeaks;
}
예제 #22
0
파일: SaveGSS.cpp 프로젝트: nimgould/mantid
void SaveGSS::writeRALFdata(const int bank, const bool MultiplyByBinWidth,
                            std::stringstream &out, const MantidVec &X,
                            const MantidVec &Y, const MantidVec &E) const {
  const size_t datasize = Y.size();
  double bc1 = X[0] * 32;
  double bc2 = (X[1] - X[0]) * 32;
  // Logarithmic step
  double bc4 = (X[1] - X[0]) / X[0];
  if (boost::math::isnan(fabs(bc4)) || boost::math::isinf(bc4))
    bc4 = 0; // If X is zero for BANK

  // Write out the data header
  writeBankLine(out, "RALF", bank, datasize);
  out << std::fixed << " " << std::setprecision(0) << std::setw(8) << bc1
      << std::fixed << " " << std::setprecision(0) << std::setw(8) << bc2
      << std::fixed << " " << std::setprecision(0) << std::setw(8) << bc1
      << std::fixed << " " << std::setprecision(5) << std::setw(7) << bc4
      << " FXYE" << std::endl;

  // Do each Y entry
  for (size_t j = 0; j < datasize; j++) {
    // Calculate the error
    double Epos;
    if (MultiplyByBinWidth)
      Epos = E[j] * (X[j + 1] - X[j]); // E[j]*X[j]*bc4;
    else
      Epos = E[j];
    Epos = fixErrorValue(Epos);

    // The center of the X bin.
    out << std::fixed << std::setprecision(5) << std::setw(15)
        << 0.5 * (X[j] + X[j + 1]);

    // The Y value
    if (MultiplyByBinWidth)
      out << std::fixed << std::setprecision(8) << std::setw(18)
          << Y[j] * (X[j + 1] - X[j]);
    else
      out << std::fixed << std::setprecision(8) << std::setw(18) << Y[j];

    // The error
    out << std::fixed << std::setprecision(8) << std::setw(18) << Epos << "\n";
  }

  return;
}
예제 #23
0
    void Multiply::performBinaryOperation(const MantidVec& lhsX, const MantidVec& lhsY, const MantidVec& lhsE,
                                          const double rhsY, const double rhsE, MantidVec& YOut, MantidVec& EOut)
    {
      UNUSED_ARG(lhsX);
      const size_t bins = lhsE.size();
      for (size_t j=0; j<bins; ++j)
      {
        // Get reference to input Y
        const double leftY = lhsY[j];

        // see comment in the function above for the error formula
        EOut[j] = sqrt(pow(lhsE[j]*rhsY, 2) + pow(rhsE*leftY, 2));

        // Copy the result last in case one of the input workspaces is also any output
        YOut[j] = leftY*rhsY;
      }
    }
/// Returns vector with x-values of spectrum if MatrixWorkspace contains
/// histogram data.
MantidVec FunctionDomain1DSpectrumCreator::getVectorHistogram() const {
  const MantidVec wsXData = m_matrixWorkspace->readX(m_workspaceIndex);
  size_t wsXSize = wsXData.size();

  if (wsXSize < 2) {
    throw std::invalid_argument("Histogram Workspace2D with less than two "
                                "x-values cannot be processed.");
  }

  MantidVec x(wsXSize - 1);

  for (size_t i = 0; i < x.size(); ++i) {
    x[i] = (wsXData[i] + wsXData[i + 1]) / 2.0;
  }

  return x;
}
예제 #25
0
파일: Divide.cpp 프로젝트: trnielsen/mantid
    void Divide::performBinaryOperation(const MantidVec& lhsX, const MantidVec& lhsY, const MantidVec& lhsE,
                                        const double rhsY, const double rhsE, MantidVec& YOut, MantidVec& EOut)
    {
      (void) lhsX; //Avoid compiler warning
      // Do the right-hand part of the error calculation just once
      const double rhsFactor = pow(rhsE/rhsY,2);
      const int bins = static_cast<int>(lhsE.size());
      for (int j=0; j<bins; ++j)
      {
        // Get reference to input Y
        const double leftY = lhsY[j];

        // see comment in the function above for the error formula
        EOut[j] = sqrt( pow(lhsE[j], 2)+pow( leftY, 2)*rhsFactor )/rhsY;
        // Copy the result last in case one of the input workspaces is also any output
        YOut[j] = leftY/rhsY;
      }
    }
예제 #26
0
파일: SaveGSS.cpp 프로젝트: nimgould/mantid
/** Write data in SLOG format
  */
void SaveGSS::writeSLOGdata(const int bank, const bool MultiplyByBinWidth,
                            std::stringstream &out, const MantidVec &X,
                            const MantidVec &Y, const MantidVec &E) const {
  const size_t datasize = Y.size();
  double bc1 = X.front(); // minimum TOF in microseconds
  if (bc1 <= 0.) {
    throw std::runtime_error(
        "Cannot write out logarithmic data starting at zero");
  }
  double bc2 = 0.5 * (*(X.rbegin()) +
                      *(X.rbegin() + 1));      // maximum TOF (in microseconds?)
  double bc3 = (*(X.begin() + 1) - bc1) / bc1; // deltaT/T

  g_log.debug() << "SaveGSS(): Min TOF = " << bc1 << std::endl;

  writeBankLine(out, "SLOG", bank, datasize);
  out << std::fixed << " " << std::setprecision(0) << std::setw(10) << bc1
      << std::fixed << " " << std::setprecision(0) << std::setw(10) << bc2
      << std::fixed << " " << std::setprecision(7) << std::setw(10) << bc3
      << std::fixed << " 0 FXYE" << std::endl;

  for (size_t i = 0; i < datasize; i++) {
    double y = Y[i];
    double e = E[i];
    if (MultiplyByBinWidth) {
      // Multiple by bin width as
      double delta = X[i + 1] - X[i];
      y *= delta;
      e *= delta;
    }
    e = fixErrorValue(e);

    out << "  " << std::fixed << std::setprecision(9) << std::setw(20)
        << 0.5 * (X[i] + X[i + 1]) << "  " << std::fixed << std::setprecision(9)
        << std::setw(20) << y << "  " << std::fixed << std::setprecision(9)
        << std::setw(20) << e << std::setw(12) << " "
        << "\n"; // let it flush its own buffer
  }
  out << std::flush;

  return;
}
예제 #27
0
/**
 * Calculate detector efficiency given a formula, the efficiency at the elastic line,
 * and a vector with energies.
 *  Efficiency = f(Ei-DeltaE) / f(Ei)
 * Hope all compilers supports the NRVO (otherwise will copy the output vector)
 * @param eff0 :: calculated eff0
 * @param formula :: formula to calculate efficiency (parsed from IDF)
 * @param xIn :: Energy bins vector (X axis)
 * @return a vector with the efficiencies
 */
MantidVec DetectorEfficiencyCorUser::calculateEfficiency(double eff0,
		const std::string& formula, const MantidVec& xIn) {

	MantidVec effOut(xIn.size() - 1); // x are bins and have more one value than y

	try {
		double e;
		mu::Parser p;
		p.DefineVar("e", &e);
		p.SetExpr(formula);

		// copied from Jaques Ollivier Code
		bool conditionForEnergy = std::min( std::abs( *std::min_element(xIn.begin(), xIn.end()) ) , m_Ei) < m_Ei;

		MantidVec::const_iterator xIn_it = xIn.begin(); // DeltaE
		MantidVec::iterator effOut_it = effOut.begin();
		for (; effOut_it != effOut.end(); ++xIn_it, ++effOut_it) {
			if (conditionForEnergy ) {
        // cppcheck cannot see that this is used by reference by muparser
        e =  std::fabs(m_Ei + *xIn_it);
			}
			else {
        // cppcheck cannot see that this is used by reference by muparser
        // cppcheck-suppress unreadVariable
				e =  std::fabs(m_Ei - *xIn_it);
			}
			double eff = p.Eval();
			*effOut_it = eff / eff0;
		}
		return effOut;
	} catch (mu::Parser::exception_type &e) {
		throw Kernel::Exception::InstrumentDefinitionError(
				"Error calculating formula from string. Muparser error message is: "
						+ e.GetMsg());
	}

}
예제 #28
0
    /**
    * Copy over the metadata from the input matrix workspace to output MDEventWorkspace
    * @param mdEventWS :: The output MDEventWorkspace where metadata are copied to. The source of the metadata is the input matrix workspace
    *
    */
    void ConvertToMD::copyMetaData(API::IMDEventWorkspace_sptr &mdEventWS) const
    {


      // found detector which is not a monitor to get proper bin boundaries.
      size_t spectra_index(0);
      bool   dector_found(false);
      for(size_t i=0;i<m_InWS2D->getNumberHistograms(); ++i)
      {
        try
        {
          auto det=m_InWS2D->getDetector(i);
          if (!det->isMonitor())
          {
            spectra_index=i;
            dector_found = true;
            g_log.debug()<<"Using spectra N "<<i<< " as the source of the bin boundaries for the resolution corrections \n"; 
            break;
          }
        }
        catch(...)
        {}
      }
      if (!dector_found)
        g_log.warning()<<"No detectors in the workspace are associated with spectra. Using spectrum 0 trying to retrieve the bin boundaries \n"; 

      // retrieve representative bin boundaries
      MantidVec binBoundaries = m_InWS2D->readX(spectra_index);
      // check if the boundaries transformation is necessary
      if (m_Convertor->getUnitConversionHelper().isUnitConverted())
      {

        if( !dynamic_cast<DataObjects::EventWorkspace *>(m_InWS2D.get()))
        {
          g_log.information()<<" ConvertToMD converts input workspace units, but the bin boundaries are copied from the first workspace spectra. The resolution estimates can be incorrect if unit conversion depends on spectra number.\n";

          UnitsConversionHelper &unitConv = m_Convertor->getUnitConversionHelper();
          unitConv.updateConversion(spectra_index);
          for(size_t i=0;i<binBoundaries.size();i++)
          {
            binBoundaries[i] =unitConv.convertUnits(binBoundaries[i]);
          }
        }
        // sort bin boundaries in case if unit transformation have swapped them.
        if (binBoundaries[0]>binBoundaries[binBoundaries.size()-1])
        {
           g_log.information()<<"Bin boundaries are not arranged monotonously. Sorting performed\n"; 
           std::sort(binBoundaries.begin(),binBoundaries.end());
        }
      }

      // Replacement for SpectraDetectorMap::createIDGroupsMap using the ISpectrum objects instead
      auto mapping = boost::make_shared<det2group_map>();
      for ( size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i )
      {
        const auto& dets = m_InWS2D->getSpectrum(i)->getDetectorIDs();
        if(!dets.empty())
        {
          std::vector<detid_t> id_vector;
          std::copy(dets.begin(), dets.end(), std::back_inserter(id_vector));
          mapping->insert(std::make_pair(id_vector.front(), id_vector));
        }
      }

      uint16_t nexpts = mdEventWS->getNumExperimentInfo();
      for(uint16_t i = 0; i < nexpts; ++i)
      {
        ExperimentInfo_sptr expt = mdEventWS->getExperimentInfo(i);
        expt->mutableRun().storeHistogramBinBoundaries(binBoundaries);
        expt->cacheDetectorGroupings(*mapping);
      }


    }
예제 #29
0
/** Corrects a spectra for the detector efficiency calculated from detector information
Gets the detector information and uses this to calculate its efficiency
*  @param spectraIn :: index of the spectrum to get the efficiency for
*  @throw invalid_argument if the shape of a detector is isn't a cylinder aligned along one axis
*  @throw runtime_error if the SpectraDetectorMap has not been filled
*  @throw NotFoundError if the detector or its gas pressure or wall thickness were not found
*/
void DetectorEfficiencyCor::correctForEfficiency(int64_t spectraIn)
{
  IDetector_const_sptr det = m_inputWS->getDetector(spectraIn);
  if( det->isMonitor() || det->isMasked() )
  {
    return;
  }

  MantidVec & yout = m_outputWS->dataY(spectraIn);
  MantidVec & eout = m_outputWS->dataE(spectraIn);
  // Need the original values so this is not a reference
  const MantidVec yValues = m_inputWS->readY(spectraIn);
  const MantidVec eValues = m_inputWS->readE(spectraIn);

  // get a pointer to the detectors that created the spectrum
  const std::set<detid_t> dets = m_inputWS->getSpectrum(spectraIn)->getDetectorIDs();

  std::set<detid_t>::const_iterator it = dets.begin();
  std::set<detid_t>::const_iterator iend = dets.end();
  if ( it == iend )
  {
    throw Exception::NotFoundError("No detectors found", spectraIn);
  }
  
  // Storage for the reciprocal wave vectors that are calculated as the 
  //correction proceeds
  std::vector<double> oneOverWaveVectors(yValues.size());
  for( ; it != iend ; ++it )
  {
    IDetector_const_sptr det_member = m_inputWS->getInstrument()->getDetector(*it);
    
    Parameter_sptr par = m_paraMap->get(det_member.get(),"3He(atm)");
    if ( !par )
    {
      throw Exception::NotFoundError("3He(atm)", spectraIn);
    }
    const double atms = par->value<double>();
    par = m_paraMap->get(det_member.get(),"wallT(m)");
    if ( !par )
    {
      throw Exception::NotFoundError("wallT(m)", spectraIn);
    }
    const double wallThickness = par->value<double>();
    double detRadius(0.0);
    V3D detAxis;
    getDetectorGeometry(det_member, detRadius, detAxis);

   // now get the sin of the angle, it's the magnitude of the cross product of unit vector along the detector tube axis and a unit vector directed from the sample to the detector centre
    V3D vectorFromSample = det_member->getPos() - m_samplePos;
    vectorFromSample.normalize();
    Quat rot = det_member->getRotation();
    // rotate the original cylinder object axis to get the detector axis in the actual instrument
    rot.rotate(detAxis); 
    detAxis.normalize();
    // Scalar product is quicker than cross product
    double cosTheta = detAxis.scalar_prod(vectorFromSample);
    double sinTheta = std::sqrt(1.0 - cosTheta*cosTheta);
    // Detector constant
    const double det_const = g_helium_prefactor*(detRadius - wallThickness)*atms/sinTheta;

    MantidVec::const_iterator yinItr = yValues.begin();
    MantidVec::const_iterator einItr = eValues.begin();
    MantidVec::iterator youtItr = yout.begin();
    MantidVec::iterator eoutItr = eout.begin();
    MantidVec::const_iterator xItr = m_inputWS->readX(spectraIn).begin();
    std::vector<double>::iterator wavItr = oneOverWaveVectors.begin();

    for( ; youtItr != yout.end(); ++youtItr, ++eoutItr)
    {
      if( it == dets.begin() )
      {
        *youtItr = 0.0;
        *eoutItr = 0.0;
        *wavItr = calculateOneOverK(*xItr, *(xItr + 1 ));
      }
      const double oneOverWave = *wavItr;
      const double factor = 1.0/detectorEfficiency(det_const*oneOverWave);
      *youtItr += (*yinItr)*factor;
      *eoutItr += (*einItr)*factor;
      ++yinItr; ++einItr;
      ++xItr; ++wavItr;
    }
  }
}
void TOFSANSResolutionByPixel::exec() {
  MatrixWorkspace_sptr inOutWS = getProperty("Workspace");
  double deltaR = getProperty("DeltaR");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  // Convert to meters
  deltaR /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;

  const MatrixWorkspace_sptr sigmaModeratorVSwavelength =
      getProperty("SigmaModerator");

  // create interpolation table from sigmaModeratorVSwavelength
  Kernel::Interpolation lookUpTable;

  const MantidVec xInterpolate = sigmaModeratorVSwavelength->readX(0);
  const MantidVec yInterpolate = sigmaModeratorVSwavelength->readY(0);

  // prefer the input to be a pointworkspace and create interpolation function
  if (sigmaModeratorVSwavelength->isHistogramData()) {
    g_log.notice() << "mid-points of SigmaModerator histogram bins will be "
                      "used for interpolation.";

    for (size_t i = 0; i < xInterpolate.size() - 1; ++i) {
      const double midpoint = xInterpolate[i + 1] - xInterpolate[i];
      lookUpTable.addPoint(midpoint, yInterpolate[i]);
    }
  } else {
    for (size_t i = 0; i < xInterpolate.size(); ++i) {
      lookUpTable.addPoint(xInterpolate[i], yInterpolate[i]);
    }
  }

  const V3D samplePos = inOutWS->getInstrument()->getSample()->getPos();
  const V3D sourcePos = inOutWS->getInstrument()->getSource()->getPos();
  const V3D SSD = samplePos - sourcePos;
  const double L1 = SSD.norm();

  const int numberOfSpectra = static_cast<int>(inOutWS->getNumberHistograms());
  Progress progress(this, 0.0, 1.0, numberOfSpectra);

  for (int i = 0; i < numberOfSpectra; i++) {
    IDetector_const_sptr det;
    try {
      det = inOutWS->getDetector(i);
    } catch (Exception::NotFoundError &) {
      g_log.information() << "Spectrum index " << i
                          << " has no detector assigned to it - discarding"
                          << std::endl;
    }
    // If no detector found or if it's masked or a monitor, skip onto the next
    // spectrum
    if (!det || det->isMonitor() || det->isMasked())
      continue;

    // Get the flight path from the sample to the detector pixel
    const V3D scatteredFlightPathV3D = det->getPos() - samplePos;

    const double L2 = scatteredFlightPathV3D.norm();
    const double Lsum = L1 + L2;

    // calculate part that is wavelenght independent
    const double dTheta2 = (4.0 * M_PI * M_PI / 12.0) *
                           (3.0 * R1 * R1 / (L1 * L1) +
                            3.0 * R2 * R2 * Lsum * Lsum / (L1 * L1 * L2 * L2) +
                            (deltaR * deltaR) / (L2 * L2));

    // Multiplicative factor to go from lambda to Q
    // Don't get fooled by the function name...
    const double theta = inOutWS->detectorTwoTheta(det);
    const double factor = 4.0 * M_PI * sin(theta / 2.0);

    const MantidVec &xIn = inOutWS->readX(i);
    MantidVec &yIn = inOutWS->dataY(i);
    const size_t xLength = xIn.size();

    // for each wavelenght bin of each pixel calculate a q-resolution
    for (size_t j = 0; j < xLength - 1; j++) {
      // use the midpoint of each bin
      const double wl = (xIn[j + 1] + xIn[j]) / 2.0;
      // Calculate q. Alternatively q could be calculated using ConvertUnit
      const double q = factor / wl;

      // wavelenght spread from bin assumed to be
      const double sigmaSpreadFromBin = xIn[j + 1] - xIn[j];

      // wavelenght spread from moderatorm, converted from microseconds to
      // wavelengths
      const double sigmaModerator =
          lookUpTable.value(wl) * 3.9560 / (1000.0 * Lsum);

      // calculate wavelenght resolution from moderator and histogram time bin
      const double sigmaLambda =
          std::sqrt(sigmaSpreadFromBin * sigmaSpreadFromBin / 12.0 +
                    sigmaModerator * sigmaModerator);

      // calculate sigmaQ for a given lambda and pixel
      const double sigmaOverLambdaTimesQ = q * sigmaLambda / wl;
      const double sigmaQ = std::sqrt(
          dTheta2 / (wl * wl) + sigmaOverLambdaTimesQ * sigmaOverLambdaTimesQ);

      // update inout workspace with this sigmaQ
      yIn[j] = sigmaQ;
    }

    progress.report("Computing Q resolution");
  }
}