Esempio n. 1
0
/** Execute the algorithm.
 */
void SaveIsawUB::exec() {
  try {
    Workspace_sptr ws1 = getProperty("InputWorkspace");
    ExperimentInfo_sptr ws;
    MultipleExperimentInfos_sptr MDWS =
        boost::dynamic_pointer_cast<MultipleExperimentInfos>(ws1);
    if (MDWS != nullptr) {
      ws = MDWS->getExperimentInfo(0);
    } else {
      ws = boost::dynamic_pointer_cast<ExperimentInfo>(ws1);
    }

    if (!ws)
      throw std::invalid_argument("Must specify either a MatrixWorkspace or a "
                                  "PeaksWorkspace or a MDWorkspace.");

    if (!ws->sample().hasOrientedLattice())
      throw std::invalid_argument(
          "Workspace must have an oriented lattice to save");

    std::string Filename = getProperty("Filename");

    ofstream out;
    out.open(Filename.c_str());

    OrientedLattice lattice = ws->sample().getOrientedLattice();
    Kernel::DblMatrix ub = lattice.getUB();
    Kernel::DblMatrix modub = lattice.getModUB();

    // Write the ISAW UB matrix
    const int beam = 2;
    const int up = 1;
    const int back = 0;
    out << fixed;

    for (size_t basis = 0; basis < 3; basis++) {
      out << setw(11) << setprecision(8) << ub[beam][basis] << setw(12)
          << setprecision(8) << ub[back][basis] << setw(12) << setprecision(8)
          << ub[up][basis] << " \n";
    }

    int ModDim = 0;
    for (int i = 0; i < 3; i++) {
      if (lattice.getModVec(i) == V3D(0, 0, 0))
        continue;
      else
        ModDim++;
    }

    if (ModDim > 0) {
      out << "ModUB: \n";
      for (size_t basis = 0; basis < 3; basis++) {
        out << setw(11) << setprecision(8) << modub[beam][basis] << setw(12)
            << setprecision(8) << modub[back][basis] << setw(12)
            << setprecision(8) << modub[up][basis] << " \n";
      }
    }

    //                out << "Lattice Parameters: \n";
    out << setw(11) << setprecision(4) << lattice.a() << setw(12)
        << setprecision(4) << lattice.b() << setw(12) << setprecision(4)
        << lattice.c() << setw(12) << setprecision(4) << lattice.alpha()
        << setw(12) << setprecision(4) << lattice.beta() << setw(12)
        << setprecision(4) << lattice.gamma() << setw(12) << setprecision(4)
        << lattice.volume() << " \n";
    double ErrorVolume = getErrorVolume(lattice);
    out << setw(11) << setprecision(4) << lattice.errora() << setw(12)
        << setprecision(4) << lattice.errorb() << setw(12) << setprecision(4)
        << lattice.errorc() << setw(12) << setprecision(4)
        << lattice.erroralpha() << setw(12) << setprecision(4)
        << lattice.errorbeta() << setw(12) << setprecision(4)
        << lattice.errorgamma() << setw(12) << setprecision(4) << ErrorVolume
        << " \n";

    out << "\n";
    if (ModDim >= 1) {
      out << "Modulation Vector 1:   " << setw(12) << setprecision(4)
          << lattice.getdh(0) << setw(12) << setprecision(4) << lattice.getdk(0)
          << setw(12) << setprecision(4) << lattice.getdl(0) << " \n";

      out << "Modulation Vector 1 error:   " << setw(6) << setprecision(4)
          << lattice.getdherr(0) << setw(12) << setprecision(4)
          << lattice.getdkerr(0) << setw(12) << setprecision(4)
          << lattice.getdlerr(0) << " \n\n";
    }
    if (ModDim >= 2) {
      out << "Modulation Vector 2:   " << setw(12) << setprecision(4)
          << lattice.getdh(1) << setw(12) << setprecision(4) << lattice.getdk(1)
          << setw(12) << setprecision(4) << lattice.getdl(1) << " \n";

      out << "Modulation Vector 2 error:   " << setw(6) << setprecision(4)
          << lattice.getdherr(1) << setw(12) << setprecision(4)
          << lattice.getdkerr(1) << setw(12) << setprecision(4)
          << lattice.getdlerr(1) << " \n\n";
    }
    if (ModDim == 3) {
      out << "Modulation Vector 3:   " << setw(12) << setprecision(4)
          << lattice.getdh(2) << setw(12) << setprecision(4) << lattice.getdk(2)
          << setw(12) << setprecision(4) << lattice.getdl(2) << " \n";

      out << "Modulation Vector 3 error:   " << setw(6) << setprecision(4)
          << lattice.getdherr(2) << setw(12) << setprecision(4)
          << lattice.getdkerr(2) << setw(12) << setprecision(4)
          << lattice.getdlerr(2) << " \n\n";
    }
    if (ModDim >= 1) {
      out << "Max Order:        " << lattice.getMaxOrder() << " \n";
      out << "Cross Terms:      " << lattice.getCrossTerm() << " \n";
    }

    out << "\n";

    if (ModDim == 0) {
      out << "The above matrix is the Transpose of the UB Matrix. ";
      out << "The UB matrix maps the column\n";
      out << "vector (h,k,l ) to the column vector ";
      out << "(q'x,q'y,q'z).\n";
      out << "|Q'|=1/dspacing and its coordinates are a ";
      out << "right-hand coordinate system where\n";
      out << " x is the beam direction and z is vertically ";
      out << "upward.(IPNS convention)\n";
    } else {
      out << "The above matrix is the Transpose of the UB Matrix and the "
             "Transpose of ModUB. ";
      out << "The UB matrix together with ModUB maps the column vector "
             "(h,k,l,m,n,p) \n";
      out << "to the column vector (q'x,q'y,q'z).\n";
      out << "The columns of ModUB are the coordinates of modulation vectors "
             "in Qlab. \n";
      out << "|Q'|=1/dspacing and its coordinates are a ";
      out << "right-hand coordinate system where";
      out << " x is the beam direction and z is vertically ";
      out << "upward.(IPNS convention)\n";
    }

    out.close();

  } catch (exception &s) {
    throw std::invalid_argument(s.what());
  }
}
/** Execute the algorithm.
 */
void IntegrateEllipsoids::exec() {
  // get the input workspace
  MatrixWorkspace_sptr wksp = getProperty("InputWorkspace");

  EventWorkspace_sptr eventWS =
      boost::dynamic_pointer_cast<EventWorkspace>(wksp);
  Workspace2D_sptr histoWS = boost::dynamic_pointer_cast<Workspace2D>(wksp);
  if (!eventWS && !histoWS) {
    throw std::runtime_error("IntegrateEllipsoids needs either a "
                             "EventWorkspace or Workspace2D as input.");
  }

  // error out if there are not events
  if (eventWS && eventWS->getNumberEvents() <= 0) {
    throw std::runtime_error(
        "IntegrateEllipsoids does not work for empty event lists");
  }

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

  double radius_m = getProperty("RegionRadius");
  double radius_s = getProperty("SatelliteRegionRadius");
  int numSigmas = getProperty("NumSigmas");
  double cutoffIsigI = getProperty("CutoffIsigI");
  bool specify_size = getProperty("SpecifySize");
  double peak_radius = getProperty("PeakSize");
  double sate_peak_radius = getProperty("SatellitePeakSize");
  double back_inner_radius = getProperty("BackgroundInnerSize");
  double sate_back_inner_radius = getProperty("SatelliteBackgroundInnerSize");
  double back_outer_radius = getProperty("BackgroundOuterSize");
  double sate_back_outer_radius = getProperty("SatelliteBackgroundOuterSize");
  bool hkl_integ = getProperty("IntegrateInHKL");
  bool integrateEdge = getProperty("IntegrateIfOnEdge");
  bool adaptiveQBackground = getProperty("AdaptiveQBackground");
  double adaptiveQMultiplier = getProperty("AdaptiveQMultiplier");
  double adaptiveQBackgroundMultiplier = 0.0;
  bool useOnePercentBackgroundCorrection =
      getProperty("UseOnePercentBackgroundCorrection");
  if (adaptiveQBackground)
    adaptiveQBackgroundMultiplier = adaptiveQMultiplier;
  if (!integrateEdge) {
    // This only fails in the unit tests which say that MaskBTP is not
    // registered
    try {
      runMaskDetectors(in_peak_ws, "Tube", "edges");
      runMaskDetectors(in_peak_ws, "Pixel", "edges");
    } catch (...) {
      g_log.error("Can't execute MaskBTP algorithm for this instrument to set "
                  "edge for IntegrateIfOnEdge option");
    }
    calculateE1(in_peak_ws->detectorInfo()); // fill E1Vec for use in detectorQ
  }

  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<std::pair<double, V3D>> qList;
  std::vector<V3D> hkl_vectors;
  std::vector<V3D> mnp_vectors;
  int ModDim = 0;
  for (size_t i = 0; i < n_peaks; i++) // Note: we skip un-indexed peaks
  {
    V3D hkl(peaks[i].getIntHKL());
    V3D mnp(peaks[i].getIntMNP());

    if (mnp[0] != 0 && ModDim == 0)
      ModDim = 1;
    if (mnp[1] != 0 && ModDim == 1)
      ModDim = 2;
    if (mnp[2] != 0 && ModDim == 2)
      ModDim = 3;

    // use tolerance == 1 to just check for (0,0,0,0,0,0)
    if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0)) {
      peak_q_list.emplace_back(peaks[i].getQLabFrame());
      qList.emplace_back(1., V3D(peaks[i].getQLabFrame()));
      hkl_vectors.push_back(hkl);
      mnp_vectors.push_back(mnp);
      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);
  Matrix<double> modUB(3, 3, false);
  Matrix<double> modHKL(3, 3, false);
  Geometry::IndexingUtils::Optimize_6dUB(UB, modUB, hkl_vectors, mnp_vectors,
                                         ModDim, peak_q_list);

  int maxOrder = 0;
  bool CT = false;
  if (peak_ws->sample().hasOrientedLattice()) {
    OrientedLattice lattice = peak_ws->mutableSample().getOrientedLattice();
    lattice.setUB(UB);
    lattice.setModUB(modUB);
    modHKL = lattice.getModHKL();
    maxOrder = lattice.getMaxOrder();
    CT = lattice.getCrossTerm();
  }

  Matrix<double> UBinv(UB);
  UBinv.Invert();
  UBinv *= (1.0 / (2.0 * M_PI));

  std::vector<double> PeakRadiusVector(n_peaks, peak_radius);
  std::vector<double> BackgroundInnerRadiusVector(n_peaks, back_inner_radius);
  std::vector<double> BackgroundOuterRadiusVector(n_peaks, back_outer_radius);
  if (specify_size) {
    if (back_outer_radius > radius_m)
      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(qList, hkl_vectors, mnp_vectors, UBinv, modHKL,
                               radius_m, radius_s, maxOrder, CT,
                               useOnePercentBackgroundCorrection);

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

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

  if (eventWS) {
    // process as EventWorkspace
    qListFromEventWS(integrator, prog, eventWS, UBinv, hkl_integ);
  } else {
    // process as Workspace2D
    qListFromHistoWS(integrator, prog, histoWS, UBinv, hkl_integ);
  }

  double inti;
  double sigi;
  std::vector<double> principalaxis1, principalaxis2, principalaxis3;
  std::vector<double> sateprincipalaxis1, sateprincipalaxis2,
      sateprincipalaxis3;
  for (size_t i = 0; i < n_peaks; i++) {
    const V3D hkl(peaks[i].getIntHKL());
    const V3D mnp(peaks[i].getIntMNP());

    if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0) ||
        Geometry::IndexingUtils::ValidIndex(mnp, 1.0)) {
      const V3D peak_q = peaks[i].getQLabFrame();
      // modulus of Q
      const double lenQpeak = adaptiveQMultiplier != 0.0 ? peak_q.norm() : 0.0;

      double adaptiveRadius = adaptiveQMultiplier * lenQpeak + peak_radius;
      if (mnp != V3D(0, 0, 0))
        adaptiveRadius = adaptiveQMultiplier * lenQpeak + sate_peak_radius;

      if (adaptiveRadius <= 0.0) {
        g_log.error() << "Error: Radius for integration sphere of peak " << i
                      << " is negative =  " << adaptiveRadius << '\n';
        peaks[i].setIntensity(0.0);
        peaks[i].setSigmaIntensity(0.0);
        PeakRadiusVector[i] = 0.0;
        BackgroundInnerRadiusVector[i] = 0.0;
        BackgroundOuterRadiusVector[i] = 0.0;
        continue;
      }

      double adaptiveBack_inner_radius;
      double adaptiveBack_outer_radius;
      if (mnp == V3D(0, 0, 0)) {
        adaptiveBack_inner_radius =
            adaptiveQBackgroundMultiplier * lenQpeak + back_inner_radius;
        adaptiveBack_outer_radius =
            adaptiveQBackgroundMultiplier * lenQpeak + back_outer_radius;
      } else {
        adaptiveBack_inner_radius =
            adaptiveQBackgroundMultiplier * lenQpeak + sate_back_inner_radius;
        adaptiveBack_outer_radius =
            adaptiveQBackgroundMultiplier * lenQpeak + sate_back_outer_radius;
      }
      PeakRadiusVector[i] = adaptiveRadius;
      BackgroundInnerRadiusVector[i] = adaptiveBack_inner_radius;
      BackgroundOuterRadiusVector[i] = adaptiveBack_outer_radius;

      std::vector<double> axes_radii;
      Mantid::Geometry::PeakShape_const_sptr shape =
          integrator.ellipseIntegrateModEvents(
              E1Vec, peak_q, hkl, mnp, specify_size, adaptiveRadius,
              adaptiveBack_inner_radius, adaptiveBack_outer_radius, axes_radii,
              inti, sigi);
      peaks[i].setIntensity(inti);
      peaks[i].setSigmaIntensity(sigi);
      peaks[i].setPeakShape(shape);
      if (axes_radii.size() == 3) {
        if (inti / sigi > cutoffIsigI || cutoffIsigI == EMPTY_DBL()) {
          if (mnp == V3D(0, 0, 0)) {
            principalaxis1.push_back(axes_radii[0]);
            principalaxis2.push_back(axes_radii[1]);
            principalaxis3.push_back(axes_radii[2]);
          } else {
            sateprincipalaxis1.push_back(axes_radii[0]);
            sateprincipalaxis2.push_back(axes_radii[1]);
            sateprincipalaxis3.push_back(axes_radii[2]);
          }
        }
      }
    } else {
      peaks[i].setIntensity(0.0);
      peaks[i].setSigmaIntensity(0.0);
    }
  }
  if (principalaxis1.size() > 1) {
    Statistics stats1 = getStatistics(principalaxis1);
    g_log.notice() << "principalaxis1: "
                   << " mean " << stats1.mean << " standard_deviation "
                   << stats1.standard_deviation << " minimum " << stats1.minimum
                   << " maximum " << stats1.maximum << " median "
                   << stats1.median << "\n";
    Statistics stats2 = getStatistics(principalaxis2);
    g_log.notice() << "principalaxis2: "
                   << " mean " << stats2.mean << " standard_deviation "
                   << stats2.standard_deviation << " minimum " << stats2.minimum
                   << " maximum " << stats2.maximum << " median "
                   << stats2.median << "\n";
    Statistics stats3 = getStatistics(principalaxis3);
    g_log.notice() << "principalaxis3: "
                   << " mean " << stats3.mean << " standard_deviation "
                   << stats3.standard_deviation << " minimum " << stats3.minimum
                   << " maximum " << stats3.maximum << " median "
                   << stats3.median << "\n";

    if (sateprincipalaxis1.size() > 1) {
      Statistics satestats1 = getStatistics(sateprincipalaxis1);
      g_log.notice() << "sateprincipalaxis1: "
                     << " mean " << satestats1.mean << " standard_deviation "
                     << satestats1.standard_deviation << " minimum "
                     << satestats1.minimum << " maximum " << satestats1.maximum
                     << " median " << satestats1.median << "\n";
      Statistics satestats2 = getStatistics(sateprincipalaxis2);
      g_log.notice() << "sateprincipalaxis2: "
                     << " mean " << satestats2.mean << " standard_deviation "
                     << satestats2.standard_deviation << " minimum "
                     << satestats2.minimum << " maximum " << satestats2.maximum
                     << " median " << satestats2.median << "\n";
      Statistics satestats3 = getStatistics(sateprincipalaxis3);
      g_log.notice() << "sateprincipalaxis3: "
                     << " mean " << satestats3.mean << " standard_deviation "
                     << satestats3.standard_deviation << " minimum "
                     << satestats3.minimum << " maximum " << satestats3.maximum
                     << " median " << satestats3.median << "\n";
    }

    constexpr size_t histogramNumber = 3;
    Workspace_sptr wsProfile = WorkspaceFactory::Instance().create(
        "Workspace2D", histogramNumber, principalaxis1.size(),
        principalaxis1.size());
    Workspace2D_sptr wsProfile2D =
        boost::dynamic_pointer_cast<Workspace2D>(wsProfile);
    AnalysisDataService::Instance().addOrReplace("EllipsoidAxes", wsProfile2D);

    // set output workspace
    Points points(principalaxis1.size(), LinearGenerator(0, 1));
    wsProfile2D->setHistogram(0, points, Counts(std::move(principalaxis1)));
    wsProfile2D->setHistogram(1, points, Counts(std::move(principalaxis2)));
    wsProfile2D->setHistogram(2, points, Counts(std::move(principalaxis3)));

    if (cutoffIsigI != EMPTY_DBL()) {
      principalaxis1.clear();
      principalaxis2.clear();
      principalaxis3.clear();
      sateprincipalaxis1.clear();
      sateprincipalaxis2.clear();
      sateprincipalaxis3.clear();
      specify_size = true;
      peak_radius = std::max(std::max(stats1.mean, stats2.mean), stats3.mean) +
                    numSigmas * std::max(std::max(stats1.standard_deviation,
                                                  stats2.standard_deviation),
                                         stats3.standard_deviation);
      back_inner_radius = peak_radius;
      back_outer_radius = peak_radius * 1.25992105; // A factor of 2 ^ (1/3)
      // will make the background
      // shell volume equal to the peak region volume.
      for (size_t i = 0; i < n_peaks; i++) {
        V3D hkl(peaks[i].getIntHKL());
        V3D mnp(peaks[i].getIntMNP());
        if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0) ||
            Geometry::IndexingUtils::ValidIndex(mnp, 1.0)) {
          const V3D peak_q = peaks[i].getQLabFrame();
          std::vector<double> axes_radii;
          integrator.ellipseIntegrateModEvents(
              E1Vec, peak_q, hkl, mnp, specify_size, peak_radius,
              back_inner_radius, back_outer_radius, axes_radii, inti, sigi);
          peaks[i].setIntensity(inti);
          peaks[i].setSigmaIntensity(sigi);
          if (axes_radii.size() == 3) {
            if (mnp == V3D(0, 0, 0)) {
              principalaxis1.push_back(axes_radii[0]);
              principalaxis2.push_back(axes_radii[1]);
              principalaxis3.push_back(axes_radii[2]);
            } else {
              sateprincipalaxis1.push_back(axes_radii[0]);
              sateprincipalaxis2.push_back(axes_radii[1]);
              sateprincipalaxis3.push_back(axes_radii[2]);
            }
          }
        } else {
          peaks[i].setIntensity(0.0);
          peaks[i].setSigmaIntensity(0.0);
        }
      }
      if (principalaxis1.size() > 1) {
        Workspace_sptr wsProfile2 = WorkspaceFactory::Instance().create(
            "Workspace2D", histogramNumber, principalaxis1.size(),
            principalaxis1.size());
        Workspace2D_sptr wsProfile2D2 =
            boost::dynamic_pointer_cast<Workspace2D>(wsProfile2);
        AnalysisDataService::Instance().addOrReplace("EllipsoidAxes_2ndPass",
                                                     wsProfile2D2);

        Points profilePoints(principalaxis1.size(), LinearGenerator(0, 1));
        wsProfile2D->setHistogram(0, profilePoints,
                                  Counts(std::move(principalaxis1)));
        wsProfile2D->setHistogram(1, profilePoints,
                                  Counts(std::move(principalaxis2)));
        wsProfile2D->setHistogram(2, profilePoints,
                                  Counts(std::move(principalaxis3)));
      }
    }
  }

  // This flag is used by the PeaksWorkspace to evaluate whether it has been
  // integrated.
  peak_ws->mutableRun().addProperty("PeaksIntegrated", 1, true);
  // These flags are specific to the algorithm.
  peak_ws->mutableRun().addProperty("PeakRadius", PeakRadiusVector, true);
  peak_ws->mutableRun().addProperty("BackgroundInnerRadius",
                                    BackgroundInnerRadiusVector, true);
  peak_ws->mutableRun().addProperty("BackgroundOuterRadius",
                                    BackgroundOuterRadiusVector, true);

  setProperty("OutputWorkspace", peak_ws);
}