コード例 #1
0
ファイル: Detector.cpp プロジェクト: dezed/mantid
/**
Get the two theata angle signed according the quadrant
@param observer :: The observer position
@param axis :: The axis
@param instrumentUp :: instrument up direction.
@return The angle
*/
double Detector::getSignedTwoTheta(const V3D &observer, const V3D &axis,
                                   const V3D &instrumentUp) const {
  const V3D sampleDetVec = this->getPos() - observer;
  double angle = sampleDetVec.angle(axis);

  V3D cross = axis.cross_prod(sampleDetVec);
  V3D normToSurface = axis.cross_prod(instrumentUp);
  if (normToSurface.scalar_prod(cross) < 0) {
    angle *= -1;
  }
  return angle;
}
コード例 #2
0
/**  Set the U rotation matrix, to provide the transformation, which translate
  *an
  *  arbitrary vector V expressed in RLU (hkl)
  *  into another coordinate system defined by vectors u and v, expressed in RLU
  *(hkl)
  *  Author: Alex Buts
  *  @param u :: first vector of new coordinate system (in hkl units)
  *  @param v :: second vector of the new coordinate system
  *  @return the U matrix calculated
  *  The transformation from old coordinate system to new coordinate system is
  *performed by
  *  the whole UB matrix
  **/
const DblMatrix &OrientedLattice::setUFromVectors(const V3D &u, const V3D &v) {
  const DblMatrix &BMatrix = this->getB();
  V3D buVec = BMatrix * u;
  V3D bvVec = BMatrix * v;
  // try to make an orthonormal system
  if (buVec.norm2() < 1e-10)
    throw std::invalid_argument("|B.u|~0");
  if (bvVec.norm2() < 1e-10)
    throw std::invalid_argument("|B.v|~0");
  buVec.normalize(); // 1st unit vector, along Bu
  V3D bwVec = buVec.cross_prod(bvVec);
  if (bwVec.normalize() < 1e-5)
    throw std::invalid_argument(
        "u and v are parallel"); // 3rd unit vector, perpendicular to Bu,Bv
  bvVec = bwVec.cross_prod(
      buVec); // 2nd unit vector, perpendicular to Bu, in the Bu,Bv plane
  DblMatrix tau(3, 3), lab(3, 3), U(3, 3);
  /*lab      = U tau
  / 0 1 0 \     /bu[0] bv[0] bw[0]\
  | 0 0 1 | = U |bu[1] bv[1] bw[1]|
  \ 1 0 0 /     \bu[2] bv[2] bw[2]/
   */
  lab[0][1] = 1.;
  lab[1][2] = 1.;
  lab[2][0] = 1.;
  tau[0][0] = buVec[0];
  tau[0][1] = bvVec[0];
  tau[0][2] = bwVec[0];
  tau[1][0] = buVec[1];
  tau[1][1] = bvVec[1];
  tau[1][2] = bwVec[1];
  tau[2][0] = buVec[2];
  tau[2][1] = bvVec[2];
  tau[2][2] = bwVec[2];
  tau.Invert();
  U = lab * tau;
  this->setU(U);
  return getU();
}
コード例 #3
0
ファイル: ConventionalCell.cpp プロジェクト: trnielsen/mantid
  /**
   *  Change UB to a new matrix corresponding to a unit cell with the sides
   *  in increasing order of magnitude.  This is used to arrange the UB matrix
   *  for an orthorhombic cell into a standard order.
   *
   *  @param UB on input this should correspond to an orthorhombic cell. 
   *            On output, it will correspond to an orthorhombic cell with
   *            sides in increasing order.
   */
  void ConventionalCell::SetSidesIncreasing( Kernel::DblMatrix & UB )
  {
    V3D a_dir;
    V3D b_dir;
    V3D c_dir;
    IndexingUtils::GetABC( UB, a_dir, b_dir, c_dir );

    std::vector<V3D> edges;
    edges.push_back( a_dir );
    edges.push_back( b_dir );
    edges.push_back( c_dir );
    std::sort( edges.begin(), edges.end(), IndexingUtils::CompareMagnitude );

    V3D a = edges[0];
    V3D b = edges[1];
    V3D c = edges[2];

    V3D acrossb = a.cross_prod( b );           // keep a,b,c right handed
    if ( acrossb.scalar_prod(c) < 0 )
    {
      c = c * (-1);
    } 
    IndexingUtils::GetUB( UB, a, b, c );
  }
コード例 #4
0
ファイル: NiggliCell.cpp プロジェクト: spaceyatom/mantid
bool NiggliCell::MakeNiggliUB(const DblMatrix &UB, DblMatrix &newUB) {
  V3D a;
  V3D b;
  V3D c;

  if (!OrientedLattice::GetABC(UB, a, b, c)) {
    return false;
  }

  V3D v1;
  V3D v2;
  V3D v3;
  // first make a list of linear combinations
  // of vectors a,b,c with coefficients up to 5
  std::vector<V3D> directions;
  int N_coeff = 5;
  for (int i = -N_coeff; i <= N_coeff; i++) {
    for (int j = -N_coeff; j <= N_coeff; j++) {
      for (int k = -N_coeff; k <= N_coeff; k++) {
        if (i != 0 || j != 0 || k != 0) {
          v1 = a * i;
          v2 = b * j;
          v3 = c * k;
          V3D sum(v1);
          sum += v2;
          sum += v3;
          directions.push_back(sum);
        }
      }
    }
  }
  // next sort the list of linear combinations
  // in order of increasing length
  std::sort(directions.begin(), directions.end(), V3D::CompareMagnitude);

  // next form a list of possible UB matrices
  // using sides from the list of linear
  // combinations, using shorter directions first.
  // Keep trying more until 25 UBs are found.
  // Only keep UBs corresponding to cells with
  // at least a minimum cell volume
  std::vector<DblMatrix> UB_list;

  size_t num_needed = 25;
  size_t max_to_try = 5;
  while (UB_list.size() < num_needed && max_to_try < directions.size()) {
    max_to_try *= 2;
    size_t num_to_try = std::min(max_to_try, directions.size());

    V3D acrossb;
    double vol = 0;
    double min_vol = .1f; // what should this be? 0.1 works OK, but...?
    for (size_t i = 0; i < num_to_try - 2; i++) {
      a = directions[i];
      for (size_t j = i + 1; j < num_to_try - 1; j++) {
        b = directions[j];
        acrossb = a.cross_prod(b);
        for (size_t k = j + 1; k < num_to_try; k++) {
          c = directions[k];
          vol = acrossb.scalar_prod(c);
          if (vol > min_vol && HasNiggliAngles(a, b, c, 0.01)) {
            Matrix<double> new_tran(3, 3, false);
            OrientedLattice::GetUB(new_tran, a, b, c);
            UB_list.push_back(new_tran);
          }
        }
      }
    }
  }
  // if no valid UBs could be formed, return
  // false and the original UB
  if (UB_list.empty()) {
    newUB = UB;
    return false;
  }
  // now sort the UB's in order of increasing
  // total side length |a|+|b|+|c|
  std::sort(UB_list.begin(), UB_list.end(), CompareABCsum);

  // keep only those UB's with total side length
  // within .1% of the first one.  This can't
  // be much larger or "bad" UBs are made for
  // some tests with 5% noise
  double length_tol = 0.001;
  double total_length;

  std::vector<DblMatrix> short_list;
  short_list.push_back(UB_list[0]);
  OrientedLattice::GetABC(short_list[0], a, b, c);
  total_length = a.norm() + b.norm() + c.norm();

  bool got_short_list = false;
  size_t i = 1;
  while (i < UB_list.size() && !got_short_list) {
    OrientedLattice::GetABC(UB_list[i], v1, v2, v3);
    double next_length = v1.norm() + v2.norm() + v3.norm();
    if (fabs(next_length - total_length) / total_length < length_tol)
      short_list.push_back(UB_list[i]);
    else
      got_short_list = true;
    i++;
  }
  // now sort on the basis of difference of cell
  // angles from 90 degrees and return the one
  // with angles most different from 90
  std::sort(short_list.begin(), short_list.end(), CompareDiffFrom90);

  newUB = short_list[0];

  return true;
}