Ejemplo n.º 1
0
/** Converts an EventWorkspace to an equivalent Workspace2D
 * @param inputMatrixW :: input event workspace
 * @return a MatrixWorkspace_sptr
 */
MatrixWorkspace_sptr
EventWorkspaceHelpers::convertEventTo2D(MatrixWorkspace_sptr inputMatrixW) {
  EventWorkspace_sptr inputW =
      boost::dynamic_pointer_cast<EventWorkspace>(inputMatrixW);
  if (!inputW)
    throw std::invalid_argument("EventWorkspaceHelpers::convertEventTo2D(): "
                                "Input workspace is not an EventWorkspace.");

  size_t numBins = inputW->blocksize();

  // Make a workspace 2D version of it
  MatrixWorkspace_sptr outputW;
  outputW = WorkspaceFactory::Instance().create(
      "Workspace2D", inputW->getNumberHistograms(), numBins + 1, numBins);
  WorkspaceFactory::Instance().initializeFromParent(inputW, outputW, false);

  // Now let's set all the X bins and values
  for (size_t i = 0; i < inputW->getNumberHistograms(); i++) {
    outputW->getSpectrum(i).copyInfoFrom(inputW->getSpectrum(i));
    outputW->setX(i, inputW->refX(i));

    MantidVec &Yout = outputW->dataY(i);
    const MantidVec &Yin = inputW->readY(i);
    for (size_t j = 0; j < numBins; j++)
      Yout[j] = Yin[j];

    MantidVec &Eout = outputW->dataE(i);
    const MantidVec &Ein = inputW->readE(i);
    for (size_t j = 0; j < numBins; j++)
      Eout[j] = Ein[j];
  }

  return outputW;
}
Ejemplo n.º 2
0
void CompressEvents::exec()
{
  // Get the input workspace
  EventWorkspace_sptr inputWS = getProperty("InputWorkspace");
  EventWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  double tolerance = getProperty("Tolerance");

  // Some starting things
  bool inplace = (inputWS == outputWS);
  const int noSpectra = static_cast<int>(inputWS->getNumberHistograms());
  Progress prog(this,0.0,1.0, noSpectra*2);

  // Sort the input workspace in-place by TOF. This can be faster if there are few event lists.
  inputWS->sortAll(TOF_SORT, &prog);

  // Are we making a copy of the input workspace?
  if (!inplace)
  {
    //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);
    // We DONT copy the data though

    // Do we want to parallelize over event lists, or in each event list
    bool parallel_in_each = noSpectra < PARALLEL_GET_MAX_THREADS;
    //parallel_in_each = false;

    // Loop over the histograms (detector spectra)
    // Don't parallelize the loop if we are going to parallelize each event list.
    // cppcheck-suppress syntaxError
    PRAGMA_OMP( parallel for schedule(dynamic) if (!parallel_in_each) )
    for (int i = 0; i < noSpectra; ++i)
    {
      PARALLEL_START_INTERUPT_REGION
      //the loop variable i can't be signed because of OpenMp rules inforced in Linux. Using this signed type suppresses warnings below
      const size_t index = static_cast<size_t>(i);
      // The input event list
      EventList& input_el = inputWS->getEventList(index);
      // And on the output side
      EventList & output_el = outputWS->getOrAddEventList(index);
      // Copy other settings into output
      output_el.setX( input_el.ptrX() );

      // The EventList method does the work.
      input_el.compressEvents(tolerance, &output_el, parallel_in_each);

      prog.report("Compressing");
      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

  }
Ejemplo n.º 3
0
    /** Executes the rebin algorithm
    *
    *  @throw runtime_error Thrown if the bin range does not intersect the range of the input workspace
    */
    void SortEvents::exec()
    {
      // Get the input workspace
      EventWorkspace_sptr eventW = getProperty("InputWorkspace");
      //And other properties
      std::string sortoption = getPropertyValue("SortBy");

      //------- EventWorkspace ---------------------------
      const size_t histnumber = eventW->getNumberHistograms();

      //Initialize progress reporting.
      Progress prog(this,0.0,1.0, histnumber);

      DataObjects::EventSortType sortType = DataObjects::TOF_SORT;
      if (sortoption == "Pulse Time")
        sortType = DataObjects::PULSETIME_SORT;
      else if (sortoption == "Pulse Time + TOF")
        sortType = DataObjects::PULSETIMETOF_SORT;

      //This runs the SortEvents algorithm in parallel
      eventW->sortAll(sortType, &prog);

      return;
    }
Ejemplo n.º 4
0
/** Carries out the bin-by-bin normalisation
 *  @param inputWorkspace The input workspace
 *  @param outputWorkspace The result workspace
 */
void NormaliseToMonitor::normaliseBinByBin(API::MatrixWorkspace_sptr inputWorkspace,
                                           API::MatrixWorkspace_sptr& outputWorkspace)
{ 
  EventWorkspace_sptr inputEvent = boost::dynamic_pointer_cast<EventWorkspace>(inputWorkspace);
  EventWorkspace_sptr outputEvent;

  // Only create output workspace if different to input one
  if (outputWorkspace != inputWorkspace )
  {
    if (inputEvent)
    {
      //Make a brand new EventWorkspace
      outputEvent = boost::dynamic_pointer_cast<EventWorkspace>(
          API::WorkspaceFactory::Instance().create("EventWorkspace", inputEvent->getNumberHistograms(), 2, 1));
      //Copy geometry and data
      API::WorkspaceFactory::Instance().initializeFromParent(inputEvent, outputEvent, false);
      outputEvent->copyDataFrom( (*inputEvent) );
      outputWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace>(outputEvent);
    }
    else
      outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace);
  }

  // Get hold of the monitor spectrum
  const MantidVec& monX = m_monitor->readX(0);
  MantidVec& monY = m_monitor->dataY(0);
  MantidVec& monE = m_monitor->dataE(0);
  // Calculate the overall normalisation just the once if bins are all matching
  if (m_commonBins) this->normalisationFactor(m_monitor->readX(0),&monY,&monE);


  const size_t numHists = inputWorkspace->getNumberHistograms();
  MantidVec::size_type specLength = inputWorkspace->blocksize();
  Progress prog(this,0.0,1.0,numHists);
  // Loop over spectra
  PARALLEL_FOR3(inputWorkspace,outputWorkspace,m_monitor)
  for (int64_t i = 0; i < int64_t(numHists); ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    prog.report();

    const MantidVec& X = inputWorkspace->readX(i);
    // If not rebinning, just point to our monitor spectra, otherwise create new vectors
    MantidVec* Y = ( m_commonBins ? &monY : new MantidVec(specLength) );
    MantidVec* E = ( m_commonBins ? &monE : new MantidVec(specLength) );

    if (!m_commonBins)
    {
      // ConvertUnits can give X vectors of all zeroes - skip these, they cause problems
      if (X.back() == 0.0 && X.front() == 0.0) continue;
      // Rebin the monitor spectrum to match the binning of the current data spectrum
      VectorHelper::rebinHistogram(monX,monY,monE,X,*Y,*E,false);
      // Recalculate the overall normalisation factor
      this->normalisationFactor(X,Y,E);
    }

    if (inputEvent)
    {
      // ----------------------------------- EventWorkspace ---------------------------------------
      EventList & outEL = outputEvent->getEventList(i);
      outEL.divide(X, *Y, *E);
    }
    else
    {
      // ----------------------------------- Workspace2D ---------------------------------------
      const MantidVec& inY = inputWorkspace->readY(i);
      const MantidVec& inE = inputWorkspace->readE(i);
      MantidVec& YOut = outputWorkspace->dataY(i);
      MantidVec& EOut = outputWorkspace->dataE(i);
      outputWorkspace->dataX(i) = inputWorkspace->readX(i);
      // The code below comes more or less straight out of Divide.cpp
      for (MantidVec::size_type k = 0; k < specLength; ++k)
      {
        // Get references to the input Y's
        const double& leftY = inY[k];
        const double& rightY = (*Y)[k];

        // Calculate result and store in local variable to avoid overwriting original data if
        // output workspace is same as one of the input ones
        const double newY = leftY/rightY;

        if (fabs(rightY)>1.0e-12 && fabs(newY)>1.0e-12)
        {
          const double lhsFactor = (inE[k]<1.0e-12|| fabs(leftY)<1.0e-12) ? 0.0 : pow((inE[k]/leftY),2);
          const double rhsFactor = (*E)[k]<1.0e-12 ? 0.0 : pow(((*E)[k]/rightY),2);
          EOut[k] = std::abs(newY) * sqrt(lhsFactor+rhsFactor);
        }

        // Now store the result
        YOut[k] = newY;
      } // end Workspace2D case
    } // end loop over current spectrum

    if (!m_commonBins) { delete Y; delete E; }
    PARALLEL_END_INTERUPT_REGION
  } // end loop over spectra
  PARALLEL_CHECK_INTERUPT_REGION
}
void SANSSolidAngleCorrection::execEvent() {
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  EventWorkspace_sptr inputEventWS =
      boost::dynamic_pointer_cast<EventWorkspace>(inputWS);

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

  // generate the output workspace pointer
  MatrixWorkspace_sptr outputWS = this->getProperty("OutputWorkspace");
  EventWorkspace_sptr outputEventWS;
  if (outputWS == inputWS)
    outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS);
  else {
    // Make a brand new EventWorkspace
    outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(
        WorkspaceFactory::Instance().create(
            "EventWorkspace", inputEventWS->getNumberHistograms(), 2, 1));
    // Copy geometry over.
    WorkspaceFactory::Instance().initializeFromParent(inputEventWS,
                                                      outputEventWS, false);
    // You need to copy over the data as well.
    outputEventWS->copyDataFrom((*inputEventWS));

    // Cast to the matrixOutputWS and save it
    outputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputEventWS);
    this->setProperty("OutputWorkspace", outputWS);
  }

  progress.report("Solid Angle Correction");

  PARALLEL_FOR2(inputEventWS, outputEventWS)
  for (int i = 0; i < numberOfSpectra; i++) {
    PARALLEL_START_INTERUPT_REGION
    IDetector_const_sptr det;
    try {
      det = inputEventWS->getDetector(i);
    } catch (Exception::NotFoundError &) {
      g_log.warning() << "Spectrum index " << i
                      << " has no detector assigned to it - discarding"
                      << std::endl;
      // Catch if no detector. Next line tests whether this happened - test
      // placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a
      // catch
      // in an openmp block.
    }
    if (!det)
      continue;

    // Skip if we have a monitor or if the detector is masked.
    if (det->isMonitor() || det->isMasked())
      continue;

    // Compute solid angle correction factor
    const bool is_tube = getProperty("DetectorTubes");
    const double tanTheta = tan(inputEventWS->detectorTwoTheta(det));
    const double theta_term = sqrt(tanTheta * tanTheta + 1.0);
    double corr;
    if (is_tube) {
      const double tanAlpha = tan(getYTubeAngle(det, inputWS));
      const double alpha_term = sqrt(tanAlpha * tanAlpha + 1.0);
      corr = alpha_term * theta_term * theta_term;
    } else {
      corr = theta_term * theta_term * theta_term;
    }
    EventList &el = outputEventWS->getEventList(i);
    el *= corr;
    progress.report("Solid Angle Correction");
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  setProperty("OutputMessage", "Solid angle correction applied");
}
Ejemplo n.º 6
0
  /** Execute the algorithm.
   */
  void IntegrateEllipsoids::exec()
  {
    // get the input workspace
    EventWorkspace_sptr wksp = getProperty("InputWorkspace");

    // this only works for unweighted events
    if (wksp->getEventType() != API::TOF)
    {
      throw std::runtime_error("IntegrateEllipsoids only works for raw events");
    }
    // error out if there are not events
    if (wksp->getNumberEvents() <= 0)
    {
      throw std::runtime_error("IntegrateEllipsoids does not work for empty event lists");
    }

    PeaksWorkspace_sptr in_peak_ws;
    in_peak_ws = boost::dynamic_pointer_cast<PeaksWorkspace>(
         AnalysisDataService::Instance().retrieve( getProperty("PeaksWorkspace")) );

    if (!in_peak_ws)
    {
      throw std::runtime_error("Could not read the peaks workspace");
    }

    Mantid::DataObjects::PeaksWorkspace_sptr peak_ws = getProperty("OutputWorkspace");
    if ( peak_ws != in_peak_ws )
    {
      peak_ws = in_peak_ws->clone();
    }
                                                   // get UBinv and the list of
                                                   // peak Q's for the integrator
    std::vector<Peak> & peaks = peak_ws->getPeaks();
    size_t n_peaks            = peak_ws->getNumberPeaks();
    size_t indexed_count      = 0;
    std::vector<V3D> peak_q_list;
    std::vector<V3D> hkl_vectors;
    for ( size_t i = 0; i < n_peaks; i++ )         // Note: we skip un-indexed peaks
    {
      V3D hkl( peaks[i].getH(), peaks[i].getK(), peaks[i].getL() );  
      if ( Geometry::IndexingUtils::ValidIndex( hkl, 1.0 ) )    // use tolerance == 1 to 
                                                                // just check for (0,0,0) 
      {
        peak_q_list.push_back( V3D( peaks[i].getQLabFrame() ) );
        V3D miller_ind( (double)boost::math::iround<double>(hkl[0]), 
                        (double)boost::math::iround<double>(hkl[1]),
                        (double)boost::math::iround<double>(hkl[2]) );
        hkl_vectors.push_back( V3D(miller_ind) );
        indexed_count++;
      }
    }

    if ( indexed_count < 3 )
    {
      throw std::runtime_error(
            "At least three linearly independent indexed peaks are needed.");
    }
                                             // Get UB using indexed peaks and
                                             // lab-Q vectors
    Matrix<double> UB(3,3,false);
    Geometry::IndexingUtils::Optimize_UB( UB, hkl_vectors, peak_q_list );
    Matrix<double> UBinv( UB );
    UBinv.Invert();
    UBinv *= (1.0/(2.0 * M_PI));

    double radius            = getProperty( "RegionRadius" );
    bool   specify_size      = getProperty( "SpecifySize" );
    double peak_radius       = getProperty( "PeakSize" );
    double back_inner_radius = getProperty( "BackgroundInnerSize" );
    double back_outer_radius = getProperty( "BackgroundOuterSize" );
    if ( specify_size )
    {
      if ( back_outer_radius > radius )
        throw std::runtime_error("BackgroundOuterSize must be less than or equal to the RegionRadius");

      if ( back_inner_radius >= back_outer_radius )
        throw std::runtime_error("BackgroundInnerSize must be less BackgroundOuterSize");

      if ( peak_radius > back_inner_radius )
        throw std::runtime_error("PeakSize must be less than or equal to the BackgroundInnerSize");
    }
                    
                                                  // make the integrator
    Integrate3DEvents integrator( peak_q_list, UBinv, radius );

                                                  // get the events and add
                                                  // them to the inegrator
    // set up a descripter of where we are going
    this->initTargetWSDescr(wksp);

    // units conersion helper
    UnitsConversionHelper unitConv;
    unitConv.initialize(m_targWSDescr, "Momentum");

    // initialize the MD coordinates conversion class
    MDTransf_sptr q_converter = MDTransfFactory::Instance().create(m_targWSDescr.AlgID);
    q_converter->initialize(m_targWSDescr);

    // set up the progress bar
    const size_t numSpectra = wksp->getNumberHistograms();
    Progress prog(this, 0.5, 1.0, numSpectra);

    // loop through the eventlists
    std::vector<double> buffer(DIMS);

    std::vector<V3D>  event_qs;
    for (std::size_t i = 0; i < numSpectra; ++i)
    {
      // get a reference to the event list
      const EventList& events = wksp->getEventList(i);

      // check to see if the event list is empty
      if (events.empty())
      {
        prog.report();
        continue; // nothing to do
      }

      // update which pixel is being converted
      std::vector<coord_t>locCoord(DIMS, 0.);
      unitConv.updateConversion(i);
      q_converter->calcYDepCoordinates(locCoord, i);

      // loop over the events
      double signal(1.);  // ignorable garbage
      double errorSq(1.); // ignorable garbage
      const std::vector<TofEvent>& raw_events = events.getEvents();
      event_qs.clear();
      for (auto event = raw_events.begin(); event != raw_events.end(); ++event)
      {
        double val = unitConv.convertUnits( event->tof() );
        q_converter->calcMatrixCoord( val, locCoord, signal, errorSq );
        for ( size_t dim = 0; dim < DIMS; ++dim )
        {
          buffer[dim] = locCoord[dim];
        }
        V3D q_vec( buffer[0], buffer[1], buffer[2] );
        event_qs.push_back( q_vec );
      } // end of loop over events in list

      integrator.addEvents( event_qs );

      prog.report();
    } // end of loop over spectra

    double inti;
    double sigi;
    for ( size_t i = 0; i < n_peaks; i++ )
    {
      V3D hkl( peaks[i].getH(), peaks[i].getK(), peaks[i].getL() );
      if ( Geometry::IndexingUtils::ValidIndex( hkl, 1.0 ) ) 
      {
        V3D peak_q( peaks[i].getQLabFrame() );
        integrator.ellipseIntegrateEvents( peak_q, 
          specify_size, peak_radius, back_inner_radius, back_outer_radius,
          inti, sigi );
        peaks[i].setIntensity( inti );
        peaks[i].setSigmaIntensity( sigi );
      }
      else
      {
        peaks[i].setIntensity( 0.0 );
        peaks[i].setSigmaIntensity( 0.0 );
      }
  
    }

    peak_ws->mutableRun().addProperty("PeaksIntegrated", 1, true);

    setProperty("OutputWorkspace", peak_ws);
  }