Esempio n. 1
0
/**
 * This function calculates the exponential contribution to the He3 tube
 * efficiency.
 * @param spectraIndex :: the current index to calculate
 * @param idet :: the current detector pointer
 * @throw out_of_range if twice tube thickness is greater than tube diameter
 * @return the exponential contribution for the given detector
 */
double He3TubeEfficiency::calculateExponential(
    std::size_t spectraIndex,
    boost::shared_ptr<const Geometry::IDetector> idet) {
  // Get the parameters for the current associated tube
  double pressure =
      this->getParameter("TubePressure", spectraIndex, "tube_pressure", idet);
  double tubethickness =
      this->getParameter("TubeThickness", spectraIndex, "tube_thickness", idet);
  double temperature = this->getParameter("TubeTemperature", spectraIndex,
                                          "tube_temperature", idet);

  double detRadius(0.0);
  Kernel::V3D detAxis;
  this->getDetectorGeometry(idet, detRadius, detAxis);
  double detDiameter = 2.0 * detRadius;
  double twiceTubeThickness = 2.0 * tubethickness;

  // 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 center
  Kernel::V3D vectorFromSample = idet->getPos() - this->samplePos;
  vectorFromSample.normalize();
  Kernel::Quat rot = idet->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);

  const double straight_path = detDiameter - twiceTubeThickness;
  if (std::fabs(straight_path - 0.0) < TOL) {
    throw std::out_of_range("Twice tube thickness cannot be greater than "
                            "or equal to the tube diameter");
  }

  const double pathlength = straight_path / sinTheta;
  return EXP_SCALAR_CONST * (pressure / temperature) * pathlength;
}
/** Executes the algorithm
*
*  @throw runtime_error Thrown if algorithm cannot execute
*/
void DiffractionEventCalibrateDetectors::exec() {
  // Try to retrieve optional properties
  const int maxIterations = getProperty("MaxIterations");
  const double peakOpt = getProperty("LocationOfPeakToOptimize");

  // Get the input workspace
  EventWorkspace_sptr inputW = getProperty("InputWorkspace");

  // retrieve the properties
  const std::string rb_params = getProperty("Params");

  // Get some stuff from the input workspace
  Instrument_const_sptr inst = inputW->getInstrument();

  // Build a list of Rectangular Detectors
  std::vector<boost::shared_ptr<RectangularDetector>> detList;
  // --------- Loading only one bank ----------------------------------
  std::string onebank = getProperty("BankName");
  bool doOneBank = (onebank != "");
  for (int i = 0; i < inst->nelements(); i++) {
    boost::shared_ptr<RectangularDetector> det;
    boost::shared_ptr<ICompAssembly> assem;
    boost::shared_ptr<ICompAssembly> assem2;

    det = boost::dynamic_pointer_cast<RectangularDetector>((*inst)[i]);
    if (det) {
      if (det->getName().compare(onebank) == 0)
        detList.push_back(det);
      if (!doOneBank)
        detList.push_back(det);
    } else {
      // Also, look in the first sub-level for RectangularDetectors (e.g. PG3).
      // We are not doing a full recursive search since that will be very long
      // for lots of pixels.
      assem = boost::dynamic_pointer_cast<ICompAssembly>((*inst)[i]);
      if (assem) {
        for (int j = 0; j < assem->nelements(); j++) {
          det = boost::dynamic_pointer_cast<RectangularDetector>((*assem)[j]);
          if (det) {
            if (det->getName().compare(onebank) == 0)
              detList.push_back(det);
            if (!doOneBank)
              detList.push_back(det);

          } else {
            // Also, look in the second sub-level for RectangularDetectors (e.g.
            // PG3).
            // We are not doing a full recursive search since that will be very
            // long for lots of pixels.
            assem2 = boost::dynamic_pointer_cast<ICompAssembly>((*assem)[j]);
            if (assem2) {
              for (int k = 0; k < assem2->nelements(); k++) {
                det = boost::dynamic_pointer_cast<RectangularDetector>(
                    (*assem2)[k]);
                if (det) {
                  if (det->getName().compare(onebank) == 0)
                    detList.push_back(det);
                  if (!doOneBank)
                    detList.push_back(det);
                }
              }
            }
          }
        }
      }
    }
  }

  // set-up minimizer

  std::string inname = getProperty("InputWorkspace");
  std::string outname = inname + "2"; // getProperty("OutputWorkspace");

  IAlgorithm_sptr algS = createChildAlgorithm("SortEvents");
  algS->setProperty("InputWorkspace", inputW);
  algS->setPropertyValue("SortBy", "X Value");
  algS->executeAsChildAlg();

  // Write DetCal File
  std::string filename = getProperty("DetCalFilename");
  std::fstream outfile;
  outfile.open(filename.c_str(), std::ios::out);

  if (detList.size() > 1) {
    outfile << "#\n";
    outfile << "#  Mantid Optimized .DetCal file for SNAP with TWO detector "
               "panels\n";
    outfile << "#  Old Panel, nominal size and distance at -90 degrees.\n";
    outfile << "#  New Panel, nominal size and distance at +90 degrees.\n";
    outfile << "#\n";
    outfile << "# Lengths are in centimeters.\n";
    outfile << "# Base and up give directions of unit vectors for a local\n";
    outfile << "# x,y coordinate system on the face of the detector.\n";
    outfile << "#\n";
    outfile << "# " << DateAndTime::getCurrentTime().toFormattedString("%c")
            << "\n";
    outfile << "#\n";
    outfile << "6         L1     T0_SHIFT\n";
    IComponent_const_sptr source = inst->getSource();
    IComponent_const_sptr sample = inst->getSample();
    outfile << "7  " << source->getDistance(*sample) * 100 << "            0\n";
    outfile << "4 DETNUM  NROWS  NCOLS  WIDTH   HEIGHT   DEPTH   DETD   "
               "CenterX   CenterY   CenterZ    BaseX    BaseY    BaseZ      "
               "UpX      UpY      UpZ\n";
  }

  Progress prog(this, 0.0, 1.0, detList.size());
  for (int det = 0; det < static_cast<int>(detList.size()); det++) {
    std::string par[6];
    par[0] = detList[det]->getName();
    par[1] = inname;
    par[2] = outname;
    std::ostringstream strpeakOpt;
    strpeakOpt << peakOpt;
    par[3] = strpeakOpt.str();
    par[4] = rb_params;

    // --- Create a GroupingWorkspace for this detector name ------
    CPUTimer tim;
    IAlgorithm_sptr alg2 =
        AlgorithmFactory::Instance().create("CreateGroupingWorkspace", 1);
    alg2->initialize();
    alg2->setProperty("InputWorkspace", inputW);
    alg2->setPropertyValue("GroupNames", detList[det]->getName());
    std::string groupWSName = "group_" + detList[det]->getName();
    alg2->setPropertyValue("OutputWorkspace", groupWSName);
    alg2->executeAsChildAlg();
    par[5] = groupWSName;
    std::cout << tim << " to CreateGroupingWorkspace\n";

    const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
    gsl_multimin_fminimizer *s = nullptr;
    gsl_vector *ss, *x;
    gsl_multimin_function minex_func;

    // finally do the fitting

    int nopt = 6;
    int iter = 0;
    int status = 0;

    /* Starting point */
    x = gsl_vector_alloc(nopt);
    gsl_vector_set(x, 0, 0.0);
    gsl_vector_set(x, 1, 0.0);
    gsl_vector_set(x, 2, 0.0);
    gsl_vector_set(x, 3, 0.0);
    gsl_vector_set(x, 4, 0.0);
    gsl_vector_set(x, 5, 0.0);

    /* Set initial step sizes to 0.1 */
    ss = gsl_vector_alloc(nopt);
    gsl_vector_set_all(ss, 0.1);

    /* Initialize method and iterate */
    minex_func.n = nopt;
    minex_func.f = &Mantid::Algorithms::gsl_costFunction;
    minex_func.params = &par;

    s = gsl_multimin_fminimizer_alloc(T, nopt);
    gsl_multimin_fminimizer_set(s, &minex_func, x, ss);

    do {
      iter++;
      status = gsl_multimin_fminimizer_iterate(s);

      if (status)
        break;

      double size = gsl_multimin_fminimizer_size(s);
      status = gsl_multimin_test_size(size, 1e-2);

    } while (status == GSL_CONTINUE && iter < maxIterations &&
             s->fval != -0.000);

    // Output summary to log file
    if (s->fval != -0.000)
      movedetector(gsl_vector_get(s->x, 0), gsl_vector_get(s->x, 1),
                   gsl_vector_get(s->x, 2), gsl_vector_get(s->x, 3),
                   gsl_vector_get(s->x, 4), gsl_vector_get(s->x, 5), par[0],
                   getProperty("InputWorkspace"));
    else {
      gsl_vector_set(s->x, 0, 0.0);
      gsl_vector_set(s->x, 1, 0.0);
      gsl_vector_set(s->x, 2, 0.0);
      gsl_vector_set(s->x, 3, 0.0);
      gsl_vector_set(s->x, 4, 0.0);
      gsl_vector_set(s->x, 5, 0.0);
    }

    std::string reportOfDiffractionEventCalibrateDetectors =
        gsl_strerror(status);
    if (s->fval == -0.000)
      reportOfDiffractionEventCalibrateDetectors = "No events";

    g_log.information() << "Detector = " << det << "\n"
                        << "Method used = "
                        << "Simplex"
                        << "\n"
                        << "Iteration = " << iter << "\n"
                        << "Status = "
                        << reportOfDiffractionEventCalibrateDetectors << "\n"
                        << "Minimize PeakLoc-" << peakOpt << " = " << s->fval
                        << "\n";
    // Move in cm for small shifts
    g_log.information() << "Move (X)   = " << gsl_vector_get(s->x, 0) * 0.01
                        << "  \n";
    g_log.information() << "Move (Y)   = " << gsl_vector_get(s->x, 1) * 0.01
                        << "  \n";
    g_log.information() << "Move (Z)   = " << gsl_vector_get(s->x, 2) * 0.01
                        << "  \n";
    g_log.information() << "Rotate (X) = " << gsl_vector_get(s->x, 3) << "  \n";
    g_log.information() << "Rotate (Y) = " << gsl_vector_get(s->x, 4) << "  \n";
    g_log.information() << "Rotate (Z) = " << gsl_vector_get(s->x, 5) << "  \n";

    Kernel::V3D CalCenter =
        V3D(gsl_vector_get(s->x, 0) * 0.01, gsl_vector_get(s->x, 1) * 0.01,
            gsl_vector_get(s->x, 2) * 0.01);
    Kernel::V3D Center = detList[det]->getPos() + CalCenter;
    int pixmax = detList[det]->xpixels() - 1;
    int pixmid = (detList[det]->ypixels() - 1) / 2;
    BoundingBox box;
    detList[det]->getAtXY(pixmax, pixmid)->getBoundingBox(box);
    double baseX = box.xMax();
    double baseY = box.yMax();
    double baseZ = box.zMax();
    Kernel::V3D Base = V3D(baseX, baseY, baseZ) + CalCenter;
    pixmid = (detList[det]->xpixels() - 1) / 2;
    pixmax = detList[det]->ypixels() - 1;
    detList[det]->getAtXY(pixmid, pixmax)->getBoundingBox(box);
    double upX = box.xMax();
    double upY = box.yMax();
    double upZ = box.zMax();
    Kernel::V3D Up = V3D(upX, upY, upZ) + CalCenter;
    Base -= Center;
    Up -= Center;
    // Rotate around x
    baseX = Base[0];
    baseY = Base[1];
    baseZ = Base[2];
    double deg2rad = M_PI / 180.0;
    double angle = gsl_vector_get(s->x, 3) * deg2rad;
    Base = V3D(baseX, baseY * cos(angle) - baseZ * sin(angle),
               baseY * sin(angle) + baseZ * cos(angle));
    upX = Up[0];
    upY = Up[1];
    upZ = Up[2];
    Up = V3D(upX, upY * cos(angle) - upZ * sin(angle),
             upY * sin(angle) + upZ * cos(angle));
    // Rotate around y
    baseX = Base[0];
    baseY = Base[1];
    baseZ = Base[2];
    angle = gsl_vector_get(s->x, 4) * deg2rad;
    Base = V3D(baseZ * sin(angle) + baseX * cos(angle), baseY,
               baseZ * cos(angle) - baseX * sin(angle));
    upX = Up[0];
    upY = Up[1];
    upZ = Up[2];
    Up = V3D(upZ * cos(angle) - upX * sin(angle), upY,
             upZ * sin(angle) + upX * cos(angle));
    // Rotate around z
    baseX = Base[0];
    baseY = Base[1];
    baseZ = Base[2];
    angle = gsl_vector_get(s->x, 5) * deg2rad;
    Base = V3D(baseX * cos(angle) - baseY * sin(angle),
               baseX * sin(angle) + baseY * cos(angle), baseZ);
    upX = Up[0];
    upY = Up[1];
    upZ = Up[2];
    Up = V3D(upX * cos(angle) - upY * sin(angle),
             upX * sin(angle) + upY * cos(angle), upZ);
    Base.normalize();
    Up.normalize();
    Center *= 100.0;
    // << det+1  << "  "
    outfile << "5  " << detList[det]->getName().substr(4) << "  "
            << detList[det]->xpixels() << "  " << detList[det]->ypixels()
            << "  " << 100.0 * detList[det]->xsize() << "  "
            << 100.0 * detList[det]->ysize() << "  "
            << "0.2000"
            << "  " << Center.norm() << "  ";
    Center.write(outfile);
    outfile << "  ";
    Base.write(outfile);
    outfile << "  ";
    Up.write(outfile);
    outfile << "\n";

    // clean up dynamically allocated gsl stuff
    gsl_vector_free(x);
    gsl_vector_free(ss);
    gsl_multimin_fminimizer_free(s);

    // Remove the now-unneeded grouping workspace
    AnalysisDataService::Instance().remove(groupWSName);
    prog.report(detList[det]->getName());
  }

  // Closing
  outfile.close();
}
/**
 * This function calculates the given skew basis vector.
 *
 * @param basis : The "base" basis vector.
 * @param scale : Scale factor for the basis vector.
 */
void vtkDataSetToNonOrthogonalDataSet::findSkewBasis(Kernel::V3D &basis,
                                                     double scale) {
  basis = m_skewMat * basis;
  basis /= scale;
  basis.normalize();
}