void spectraSysTrig_dNdetashift() {

  // === General Settings ===

  // Note centrality is by 2.5% bins, low bin is inclusive, high bin is exclusive
  // i.e. for 0-10% use minCent=0, maxCent=4. 


  int minCent[12] = {0,2,4,6,8,10,12,14,16,20,24,28};
  int maxCent[12] = {2,4,6,8,10,12,14,16,20,24,28,32};
  
  // absolute values of eta are used, negative eta values are included
  // for full eta range set etaMin=0 etaMax=2.4
  Double_t  etaMin = 0.0;
  Double_t  etaMax = 0.4;

double dndeta[12]= {1612,1313,1082,893.9,731.6,596.8, 482.3,383.9, 266.5, 153.2,79.5, 36.3 };
double dndetaerr[12] = {55,45, 38, 31.4, 26.3, 23.1, 18.7, 16.2, 14.2, 9.7, 6.57, 3.99};

  double ptbins[20]={0.3,0.4,0.5,0.6,0.8,1.0,1.2,1.6,2.0,2.5,3.0,3.5,4.0,5.0,6.0,8.0,10.0,12.0,16.,22.};

  
  // Input File
  TFile *f = new TFile("LowPtSpectrum_fine_Full_d.root");
  TFile *fcorr = new TFile("validation3D_HydjetNoWedge_100k_flowSQ_vertexZ10.root");
  TFile *fcorrAMPT;
  TFile *fcorrDataMix = new TFile("validation3D_20pionBadWedge_SQ12_vertexZ10.root");
  // =========================

  gStyle->SetErrorX(0);
  gStyle->SetOptStat(0);


  set_plot_style();

  char dirname[256] = "spectrumGoodTightdz10chi40";
  TH1D * spec[10][12];
  TH1D * eff[10][12];
  TH1D * fak[10][12];
  TH1D * sim[10][12];
  TH1D * rec[10][12];

  TGraphErrors * gSpectrum[10][12];
  TF1 * f1[10][12];

  Double_t  meanpt[10][12];
  Double_t  meanpterr[10][12];

  double integral[4][12];
  
    Double_t px[100],py[100],pxe[100],pye[100];
  for( int c=0; c<12; c++)
  {
    for( int j=0; j<4; j++)
    {
      if ( j==0) spec[j][c] = getSpectrum( f, Form("%s/tracks3D",dirname), minCent[c], maxCent[c], etaMin, etaMax ); 
      if ( j==1) spec[j][c] = getSpectrum( f, Form("%s/tracks3D_c94",dirname), minCent[c], maxCent[c], etaMin, etaMax ); 
      if ( j==2) spec[j][c] = getSpectrum( f, Form("%s/tracks3D_c97",dirname), minCent[c], maxCent[c], etaMin, etaMax ); 
      if ( j==3) spec[j][c] = getSpectrum( f, Form("%s/tracks3D_c100",dirname), minCent[c], maxCent[c], etaMin, etaMax ); 
      eff[j][c] = getSpectrum( fcorr, "hitrkPixelEffAnalyzer/heff3D", minCent[c], maxCent[c], etaMin, etaMax );
      sim[j][c] = getSpectrum( fcorr, "hitrkPixelEffAnalyzer/hsim3D", minCent[c], maxCent[c], etaMin, etaMax );
      fak[j][c] = getSpectrum( fcorr, "hitrkPixelEffAnalyzer/hfak3D", minCent[c], maxCent[c], etaMin, etaMax );
      rec[j][c] = getSpectrum( fcorr, "hitrkPixelEffAnalyzer/hrec3D", minCent[c], maxCent[c], etaMin, etaMax );

      // determine correction factors


      TH1F * nevts;

      if( j==0)  nevts = (TH1F *) f->Get(Form("%s/nevts",dirname));
      if( j==1)  nevts = (TH1F *) f->Get(Form("%s/nevts_c94",dirname));
      if( j==2)  nevts = (TH1F *) f->Get(Form("%s/nevts_c97",dirname));
      if( j==3)  nevts = (TH1F *) f->Get(Form("%s/nevts_c100",dirname));
      double Nevt = nevts->Integral( nevts->GetXaxis()->FindBin(minCent[c]+0.001), 
                                     nevts->GetXaxis()->FindBin(maxCent[c]-0.001) );


      Double_t maxy = 0.;
      Double_t miny = 100000.;
    integral[j][c] = 0;
    for( int i=0; i<=19;i++)
    {
      double ptmin = ptbins[i]; double ptmax = ptbins[i+1];

      double iptmin = spec[j][c]->FindBin(ptmin+1e-3);
      double iptmax = spec[j][c]->FindBin(ptmax-1e-3);
      double icptmin = eff[j][c]->FindBin(ptmin+1e-3);
      double icptmax = eff[j][c]->FindBin(ptmax-1e-3);
      double pt = 0.;
      for( int k=iptmin;k<=iptmax;k++) pt += spec[j][c]->GetBinCenter(k) * spec[j][c]->GetBinContent(k);
      pt /= spec[j][c]->Integral(iptmin,iptmax);

      double yielderr;
      double yield = spec[j][c]->IntegralAndError(iptmin,iptmax,yielderr);
      yield /= (ptmax-ptmin) * Nevt * 2 * (etaMax-etaMin);
      yielderr /= (ptmax-ptmin) * Nevt * 2 * (etaMax-etaMin);

      double efmin = eff[j][c]->GetBinContent(icptmin)/sim[j][c]->GetBinContent(icptmin);
      double efmax = eff[j][c]->GetBinContent(icptmax)/sim[j][c]->GetBinContent(icptmax);
      double famin = fak[j][c]->GetBinContent(icptmin)/rec[j][c]->GetBinContent(icptmin);
      double famax = fak[j][c]->GetBinContent(icptmax)/rec[j][c]->GetBinContent(icptmax);

      double ef = (pt-ptmin)*(efmax-efmin)/(ptmax-ptmin)+efmin;
      double fa = (pt-ptmin)*(famax-famin)/(ptmax-ptmin)+famin;
      yield *= (1-fa)/ef;

      px[i] = pt;
      py[i] = yield;
      if( py[i] > maxy ) maxy = py[i];
      if( py[i] < miny ) miny = py[i];
      pxe[i] = 0.;
      pye[i] = yielderr;
      if ( yield > -1. ) integral[j][c] += yield;
    }


      gSpectrum[j][c] = new TGraphErrors( 19, px, py, pxe, pye );
      gSpectrum[j][c]->SetMarkerStyle(20);
      f1[j][c] = new TF1(Form("f1_%d_%d",c,j),"6.28318531 * x * [2]*pow((1+sqrt(0.01947978 + x*x)-0.13957) /[1],-[0])",0.3,3.1);
     f1[j][c]->SetParameters(10.8327,2.221289,dndeta[c]);
     if(j==3) f1[j][c]->SetParameters(10.8327,2.221289,dndeta[c]*2);
     f1[j][c]->SetParameters(10.8327,2.221289,dndeta[c]);
      f1[j][c]->SetLineColor(kBlue);
      f1[j][c]->SetLineWidth(1);
      f1[j][c]->SetLineStyle(1);
       gSpectrum[j][c]->Fit(Form("f1_%d_%d",c,j),"0RQNS");
      TF1 * fitptmx = new TF1("fitptmx","6.28318531 * x * x * [2]*pow((1+sqrt(0.01947978 + x*x)-0.13957) /[1],-[0])",0.0,3.1);
      fitptmx->SetParameters(f1[j][c]->GetParameter(0),f1[j][c]->GetParameter(1), f1[j][c]->GetParameter(2) );
    double numerator = fitptmx->Integral(0.0,0.3);
    double denominator = f1[j][c]->Integral(0.0,0.3);
    for( int p = 0; p<gSpectrum[j][c]->GetN(); p++)
    {
       Double_t  ppx, ppy;
       gSpectrum[j][c]->GetPoint(p,ppx,ppy);
       if ( 0.3 < ppx && ppx < 0.6 ) numerator += ppx * ppy * 0.1;
       if ( 0.6 < ppx && ppx < 1.2 ) numerator += ppx * ppy * 0.2;
       if ( 1.2 < ppx && ppx < 2.0 ) numerator += ppx * ppy * 0.4;
       if ( 2.0 < ppx && ppx < 4.0 ) numerator += ppx * ppy * 0.5;
       if ( 4.0 < ppx && ppx < 6.0 ) numerator += ppx * ppy * 1.0;
       if ( 0.3 < ppx && ppx < 0.6 ) denominator += ppy * 0.1;
       if ( 0.6 < ppx && ppx < 1.2 ) denominator += ppy * 0.2;
       if ( 1.2 < ppx && ppx < 2.0 ) denominator += ppy * 0.4;
       if ( 2.0 < ppx && ppx < 4.0 ) denominator += ppy * 0.5;
       if ( 4.0 < ppx && ppx < 6.0 ) denominator += ppy * 1.0;
    }
    meanpt[j][c] = numerator / denominator;


      meanpterr[j][c] = 0.;
    }
    
  }

 
  TH1D* hDumCen = new TH1D("hDumCen",";Centrality (%);<p_{T}> Ratio",40,0.,80.); 
  hDumCen->GetXaxis()->CenterTitle(); hDumCen->GetYaxis()->SetTitleOffset(1.1);
  hDumCen->SetMaximum(1.5); hDumCen->SetMinimum(0.5);

  TCanvas *c1 = new TCanvas("c1","Mean Pt",600,600);
 
  c1->cd();
  hDumCen->Draw();

  TGraphErrors * gmean[4];
  
  int colors[4] = {0,kRed, kBlack, kBlue};

  for( int j=1; j<4; j++)
  {
    Double_t mx[12], mxe[12], my[12], mye[12];
    for(int i=0;i<12;i++) 
    { 
      mx[i] = (double)(maxCent[i]+minCent[i]) * 1.25;
      mxe[i] = 0; 
      my[i] = meanpt[j][i] / meanpt[0][i];
      mye[i] = my[i] * sqrt( meanpterr[j][i]*meanpterr[j][i]/meanpt[j][i]/meanpt[j][i] 
                           + meanpterr[0][i]*meanpterr[0][i]/meanpt[0][i]/meanpt[0][i] );
    
    }  

    gmean[j] = new TGraphErrors(12, mx, my, mxe, mye);
    gmean[j]->SetMarkerStyle(20);
    gmean[j]->SetMarkerColor(colors[j]);
    gmean[j]->SetLineColor(colors[j]);
    gmean[j]->Draw("p");
  
  }
  TLegend *legPt = new TLegend(0.45,0.7,0.89,0.89);
  legPt->SetFillColor(0); legPt->SetBorderSize(0);
  legPt->AddEntry(gmean[1],"Trig 94","lp");
  legPt->AddEntry(gmean[2],"Trig 97","lp");
  legPt->AddEntry(gmean[3],"Trig 100","lp");

  legPt->Draw();

  TLatex *  tex = new TLatex(20,0.8,Form( "GoodTightMergedTracks, %4.1f < |#eta| < %4.1f",etaMin, etaMax ));
    tex->SetTextSize(0.035);
    tex->Draw();

  TH1D* hDumPt = new TH1D("hDumPt",";p_{T} [GeV/c];ratio 1/N_{evt} d^{2}N_{ch}/d#etadp_{T}",40,0.,6.); hDumPt->SetMaximum(1.5);
  hDumPt->GetXaxis()->CenterTitle(); hDumPt->GetYaxis()->SetTitleOffset(1.1);

  hDumPt->SetMaximum(1.25); hDumPt->SetMinimum(0.75);

  TCanvas *c8 = new TCanvas("c8","Spectrum",1000,800);
  c8->Divide(4,3,0,0);

  TGraphErrors * gRatio[4][12]; 

  for( int q=0;q<12; q++)
  {
    c8->cd(q+1);
    int i = q;
    hDumPt->Draw();
    for( int j=0; j<4; j++)
    { 
      Double_t rx[100],ry[100],rxe[100],rye[100];
      Double_t dx, nx, ny, dy, dye, nye; 
      for( int p=0;p<gSpectrum[0][i]->GetN();p++)
      {
        gSpectrum[0][i]->GetPoint(p,dx,dy);
        dye = gSpectrum[0][i]->GetErrorY(p);
        gSpectrum[j][i]->GetPoint(p,nx,ny);
        nye = gSpectrum[j][i]->GetErrorY(p);
        rx[p] = nx; rxe[p]=0;
        ry[p] = ny / dy;
        rye[p] = ry[p] * sqrt ( nye*nye/ny/ny + dye*dye/dy/dy);        
      }
      gRatio[j][i] = new TGraphErrors(gSpectrum[0][i]->GetN(), rx, ry, rxe, rye);
      gRatio[j][i]->SetMarkerStyle(20);
      gRatio[j][i]->SetMarkerColor(colors[j]);
      gRatio[j][i]->SetLineColor(colors[j]);
      gRatio[j][i]->Draw("p"); 
    tex = new TLatex(1,0.87,Form("%d-%d Cent.",(int)(minCent[i]*2.5),(int)(maxCent[i]*2.5)));
    tex->SetTextSize(0.045);
    tex->Draw();

    if( i==0) legPt->Draw();
  
    tex = new TLatex(1,0.85,Form("%4.1f < |#eta| < %4.1f",etaMin,etaMax));
    tex->SetTextSize(0.045);
    if( i==0) tex->Draw();
    tex = new TLatex(1,0.83,Form("GoodTightMergedTracks",etaMin,etaMax));
    tex->SetTextSize(0.045);
    if( i==0) tex->Draw();
    }
  } 

  cout << "Normalization Errors from Integrals\n\n\n";

  for( int c=0; c<12; c++)
  {
    cout << Form("%d-%d Cent.",(int)(minCent[c]*2.5),(int)(maxCent[c]*2.5)) << "  ";
    for( int j = 1; j<4; j++)
    {
      cout << integral[j][c] / integral[0][c] << "  ";
    }
    cout << endl;
  }

}
double MazurkaTransformer::getSpectrumSquared(int index) {
   mz_complex num = getSpectrum(index);
   return num.re * num.re + num.im * num.im;
}
double MazurkaTransformer::getSpectrumMagnitude(int index) {
   mz_complex num = getSpectrum(index);
   return sqrt(num.re * num.re + num.im * num.im);
}
示例#4
0
void ModeratorTzero::execEvent(const std::string &emode) {
  g_log.information("Processing event workspace");

  const MatrixWorkspace_const_sptr matrixInputWS =
      getProperty("InputWorkspace");

  // generate the output workspace pointer
  API::MatrixWorkspace_sptr matrixOutputWS = getProperty("OutputWorkspace");
  if (matrixOutputWS != matrixInputWS) {
    matrixOutputWS = matrixInputWS->clone();
    setProperty("OutputWorkspace", matrixOutputWS);
  }
  auto outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS);

  // calculate tof shift once for all neutrons if emode==Direct
  double t0_direct(-1);
  if (emode == "Direct") {
    Kernel::Property *eiprop = outputWS->run().getProperty("Ei");
    double Ei = boost::lexical_cast<double>(eiprop->value());
    mu::Parser parser;
    parser.DefineVar("incidentEnergy", &Ei); // associate E1 to this parser
    parser.SetExpr(m_formula);
    t0_direct = parser.Eval();
  }

  const auto &spectrumInfo = outputWS->spectrumInfo();
  const double Lss = spectrumInfo.l1();

  // Loop over the spectra
  const size_t numHists = static_cast<size_t>(outputWS->getNumberHistograms());
  Progress prog(this, 0.0, 1.0, numHists); // report progress of algorithm
  PARALLEL_FOR_IF(Kernel::threadSafe(*outputWS))
  for (int i = 0; i < static_cast<int>(numHists); ++i) {
    PARALLEL_START_INTERUPT_REGION
    size_t wsIndex = static_cast<size_t>(i);
    EventList &evlist = outputWS->getSpectrum(wsIndex);
    if (evlist.getNumberEvents() > 0) // don't bother with empty lists
    {
      double L1(Lss); // distance from source to sample
      double L2(-1);  // distance from sample to detector

      if (spectrumInfo.hasDetectors(i)) {
        if (spectrumInfo.isMonitor(i)) {
          // redefine the sample as the monitor
          L1 = Lss + spectrumInfo.l2(i); // L2 in SpectrumInfo defined negative
          L2 = 0;
        } else {
          L2 = spectrumInfo.l2(i);
        }
      } else {
        g_log.error() << "Unable to calculate distances to/from detector" << i
                      << '\n';
      }

      if (L2 >= 0) {
        // One parser for each parallel processor needed (except Edirect mode)
        double E1;
        mu::Parser parser;
        parser.DefineVar("incidentEnergy", &E1); // associate E1 to this parser
        parser.SetExpr(m_formula);

        // fast neutrons are shifted by min_t0_next, irrespective of tof
        double v1_max = L1 / m_t1min;
        E1 = m_convfactor * v1_max * v1_max;
        double min_t0_next = parser.Eval();

        if (emode == "Indirect") {
          double t2(-1.0); // time from sample to detector. (-1) signals error
          if (spectrumInfo.isMonitor(i)) {
            t2 = 0.0;
          } else {
            static const double convFact =
                1.0e-6 * sqrt(2 * PhysicalConstants::meV /
                              PhysicalConstants::NeutronMass);
            std::vector<double> wsProp =
                spectrumInfo.detector(i).getNumberParameter("Efixed");
            if (!wsProp.empty()) {
              double E2 = wsProp.at(0);        //[E2]=meV
              double v2 = convFact * sqrt(E2); //[v2]=meter/microsec
              t2 = L2 / v2;
            } else {
              // t2 is kept to -1 if no Efixed is found
              g_log.debug() << "Efixed not found for detector " << i << '\n';
            }
          }
          if (t2 >= 0) // t2 < 0 when no detector info is available
          {
            // fix the histogram bins
            auto &x = evlist.mutableX();
            for (double &tof : x) {
              if (tof < m_t1min + t2)
                tof -= min_t0_next;
              else
                tof -= CalculateT0indirect(tof, L1, t2, E1, parser);
            }

            MantidVec tofs = evlist.getTofs();
            for (double &tof : tofs) {
              if (tof < m_t1min + t2)
                tof -= min_t0_next;
              else
                tof -= CalculateT0indirect(tof, L1, t2, E1, parser);
            }
            evlist.setTofs(tofs);
            evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED);
          } // end of if( t2>= 0)
        }   // end of if(emode=="Indirect")
        else if (emode == "Elastic") {
          // Apply t0 correction to histogram bins
          auto &x = evlist.mutableX();
          for (double &tof : x) {
            if (tof < m_t1min * (L1 + L2) / L1)
              tof -= min_t0_next;
            else
              tof -= CalculateT0elastic(tof, L1 + L2, E1, parser);
          }

          MantidVec tofs = evlist.getTofs();
          for (double &tof : tofs) {
            // add a [-0.1,0.1] microsecond noise to avoid artifacts
            // resulting from original tof data
            if (tof < m_t1min * (L1 + L2) / L1)
              tof -= min_t0_next;
            else
              tof -= CalculateT0elastic(tof, L1 + L2, E1, parser);
          }
          evlist.setTofs(tofs);
          evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED);
        } // end of else if(emode=="Elastic")
        else if (emode == "Direct") {
          // fix the histogram bins
          evlist.mutableX() -= t0_direct;

          MantidVec tofs = evlist.getTofs();
          for (double &tof : tofs) {
            tof -= t0_direct;
          }
          evlist.setTofs(tofs);
          evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED);
        } // end of else if(emode=="Direct")
      }   // end of if(L2 >= 0)
    }     // end of if (evlist.getNumberEvents() > 0)
    prog.report();
    PARALLEL_END_INTERUPT_REGION
  } // end of for (int i = 0; i < static_cast<int>(numHists); ++i)
  PARALLEL_CHECK_INTERUPT_REGION
  outputWS->clearMRU(); // Clears the Most Recent Used lists */
} // end of void ModeratorTzero::execEvent()
示例#5
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 in_ws = 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.
  auto localworkspace = replaceSpecialValues(in_ws);

  // 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
  auto &outSpec = outputWorkspace->getSpectrum(0);
  auto &YSum = outSpec.mutableY();
  auto &YError = outSpec.mutableE();
  auto &FracSum = outWS->dataF(0);
  std::vector<double> 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;

  const auto &spectrumInfo = localworkspace->spectrumInfo();
  // Loop over spectra
  for (const auto i : m_indices) {
    // 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;
    }

    if (spectrumInfo.hasDetectors(i)) {
      // Skip monitors, if the property is set to do so
      if (!m_keepMonitors && spectrumInfo.isMonitor(i))
        continue;
      // Skip masked detectors
      if (spectrumInfo.isMasked(i)) {
        numMasked++;
        continue;
      }
    }
    numSpectra++;

    // Retrieve the spectrum into a vector
    const auto &YValues = localworkspace->y(i);
    const auto &YErrors = localworkspace->e(i);
    const auto &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 (numSpectra > nZeros[i])
        YSum[i] *= double(numSpectra - nZeros[i]) / Weight[i];
      if (nZeros[i] != 0)
        numZeros += nZeros[i];
    }
  }

  // Create the correct representation
  outWS->finalize();
}
示例#6
0
/**
 * This function deals with the logic necessary for summing a Workspace2D.
 * @param outSpec The spectrum for the summed output.
 * @param progress The progress indicator.
 * @param numSpectra The number of spectra contributed to the sum.
 * @param numMasked The spectra dropped from the summations because they are
 * masked.
 * @param numZeros The number of zero bins in histogram workspace or empty
 * spectra for event workspace.
 */
void SumSpectra::doWorkspace2D(ISpectrum &outSpec, Progress &progress,
                               size_t &numSpectra, size_t &numMasked,
                               size_t &numZeros) {
  // Get references to the output workspaces's data vectors
  auto &OutputYSum = outSpec.mutableY();
  auto &OutputYError = outSpec.mutableE();

  std::vector<double> Weight;
  std::vector<size_t> nZeros;
  if (m_calculateWeightedSum) {
    Weight.assign(OutputYSum.size(), 0);
    nZeros.assign(OutputYSum.size(), 0);
  }
  numSpectra = 0;
  numMasked = 0;
  numZeros = 0;

  MatrixWorkspace_sptr in_ws = getProperty("InputWorkspace");
  // Clean workspace of any NANs or Inf values
  auto localworkspace = replaceSpecialValues(in_ws);
  const auto &spectrumInfo = localworkspace->spectrumInfo();
  // Loop over spectra
  for (const auto wsIndex : this->m_indices) {
    // Don't go outside the range.
    if ((wsIndex >= this->m_numberOfSpectra) || (wsIndex < 0)) {
      g_log.error() << "Invalid index " << wsIndex
                    << " was specified. Sum was aborted.\n";
      break;
    }

    if (spectrumInfo.hasDetectors(wsIndex)) {
      // Skip monitors, if the property is set to do so
      if (!m_keepMonitors && spectrumInfo.isMonitor(wsIndex))
        continue;
      // Skip masked detectors
      if (spectrumInfo.isMasked(wsIndex)) {
        numMasked++;
        continue;
      }
    }
    numSpectra++;

    const auto &YValues = localworkspace->y(wsIndex);
    const auto &YErrors = localworkspace->e(wsIndex);

    // Retrieve the spectrum into a vector

    for (int i = 0; i < m_yLength; ++i) {
      if (m_calculateWeightedSum) {
        if (std::isnormal(YErrors[i])) {
          const double errsq = YErrors[i] * YErrors[i];
          OutputYError[i] += errsq;
          Weight[i] += 1. / errsq;
          OutputYSum[i] += YValues[i] / errsq;
        } else {
          nZeros[i]++;
        }

      } else {
        OutputYSum[i] += YValues[i];
        OutputYError[i] += YErrors[i] * YErrors[i];
      }
    }

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

    progress.report();
  }

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