Beispiel #1
0
bool mitk::SlicedData::VerifyRequestedRegion()
{
  if(GetTimeGeometry() == NULL) return false;

  unsigned int i;

  // Is the requested region within the LargestPossibleRegion?
  // Note that the test is indeed against the largest possible region
  // rather than the buffered region; see DataObject::VerifyRequestedRegion.
  const IndexType &requestedRegionIndex = m_RequestedRegion.GetIndex();
  const IndexType &largestPossibleRegionIndex
    = GetLargestPossibleRegion().GetIndex();

  const SizeType& requestedRegionSize = m_RequestedRegion.GetSize();
  const SizeType& largestPossibleRegionSize
    = GetLargestPossibleRegion().GetSize();

  for (i=0; i< RegionDimension; ++i)
  {
    if ( (requestedRegionIndex[i] < largestPossibleRegionIndex[i]) ||
      ((requestedRegionIndex[i] + static_cast<long>(requestedRegionSize[i]))
    > (largestPossibleRegionIndex[i]+static_cast<long>(largestPossibleRegionSize[i]))))
    {
      return false;
    }
  }

  return true;
}
Beispiel #2
0
void mitk::SlicedData::SetRequestedRegionToLargestPossibleRegion()
{
  m_UseLargestPossibleRegion = true;
  if(GetGeometry()==NULL)
    return;
  unsigned int i;
  const RegionType::IndexType & index = GetLargestPossibleRegion().GetIndex();
  const RegionType::SizeType & size = GetLargestPossibleRegion().GetSize();
  for(i=0;i<RegionDimension;++i)
  {
    m_RequestedRegion.SetIndex(i, index[i]);
    m_RequestedRegion.SetSize(i, size[i]);
  }
}
bool mitk::SlicedData::RequestedRegionIsOutsideOfTheBufferedRegion()
{
  // Is the requested region within the currently buffered data?
  // SlicedData and subclasses store entire volumes or slices. The
  // methods IsVolumeSet() and IsSliceSet are provided to check,
  // a volume or slice, respectively, is available. Thus, these
  // methods used here.
  const IndexType &requestedRegionIndex = m_RequestedRegion.GetIndex();

  const SizeType &requestedRegionSize = m_RequestedRegion.GetSize();
  const SizeType &largestPossibleRegionSize = GetLargestPossibleRegion().GetSize();

  // are whole channels requested?
  int c, cEnd;
  c = requestedRegionIndex[4];
  cEnd = c + static_cast<long>(requestedRegionSize[4]);
  if (requestedRegionSize[3] == largestPossibleRegionSize[3])
  {
    for (; c < cEnd; ++c)
      if (IsChannelSet(c) == false)
        return true;
    return false;
  }

  // are whole volumes requested?
  int t, tEnd;
  t = requestedRegionIndex[3];
  tEnd = t + static_cast<long>(requestedRegionSize[3]);
  if (requestedRegionSize[2] == largestPossibleRegionSize[2])
  {
    for (; c < cEnd; ++c)
      for (; t < tEnd; ++t)
        if (IsVolumeSet(t, c) == false)
          return true;
    return false;
  }

  // ok, only slices are requested. Check if they are available.
  int s, sEnd;
  s = requestedRegionIndex[2];
  sEnd = s + static_cast<long>(requestedRegionSize[2]);
  for (; c < cEnd; ++c)
    for (; t < tEnd; ++t)
      for (; s < sEnd; ++s)
        if (IsSliceSet(s, t, c) == false)
          return true;

  return false;
}
Beispiel #4
0
static void
CreateNoNaNMask(itk::Image<TPixel, VImageDimension>* itkValue, mitk::Image::Pointer mask, mitk::Image::Pointer& newMask)
{
  typedef itk::Image< TPixel, VImageDimension>                 LFloatImageType;
  typedef itk::Image< unsigned short, VImageDimension>          LMaskImageType;
  typename LMaskImageType::Pointer itkMask = LMaskImageType::New();

  mitk::CastToItkImage(mask, itkMask);

  typedef itk::ImageDuplicator< LMaskImageType > DuplicatorType;
  typename DuplicatorType::Pointer duplicator = DuplicatorType::New();
  duplicator->SetInputImage(itkMask);
  duplicator->Update();

  auto tmpMask = duplicator->GetOutput();

  itk::ImageRegionIterator<LMaskImageType> mask1Iter(itkMask, itkMask->GetLargestPossibleRegion());
  itk::ImageRegionIterator<LMaskImageType> mask2Iter(tmpMask, tmpMask->GetLargestPossibleRegion());
  itk::ImageRegionIterator<LFloatImageType> imageIter(itkValue, itkValue->GetLargestPossibleRegion());
  while (!mask1Iter.IsAtEnd())
  {
    mask2Iter.Set(0);
    if (mask1Iter.Value() > 0)
    {
      // Is not NaN
      if (imageIter.Value() == imageIter.Value())
      {
        mask2Iter.Set(1);
      }
    }
    ++mask1Iter;
    ++mask2Iter;
    ++imageIter;
  }

  newMask->InitializeByItk(tmpMask);
  mitk::GrabItkImageMemory(tmpMask, newMask);
}
Beispiel #5
0
std::vector<cleaver::AbstractScalarField*>
NRRDTools::segmentationToIndicatorFunctions(std::string filename, double sigma) {
  // read file using ITK
  if (filename.find(".nrrd") != std::string::npos) {
    itk::NrrdImageIOFactory::RegisterOneFactory();
  } else if (filename.find(".mha") != std::string::npos) {
    itk::MetaImageIOFactory::RegisterOneFactory();
  }
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(filename);
  reader->Update();
  ImageType::Pointer image = reader->GetOutput();
  //determine the number of labels in the segmentations
  ImageCalculatorFilterType::Pointer imageCalculatorFilter
    = ImageCalculatorFilterType::New();
  imageCalculatorFilter->SetImage(reader->GetOutput());
  imageCalculatorFilter->Compute();
  auto maxLabel = static_cast<size_t>(imageCalculatorFilter->GetMaximum());
  auto minLabel = static_cast<size_t>(imageCalculatorFilter->GetMinimum());
  std::vector<cleaver::AbstractScalarField*> fields;
  //extract images from each label for an indicator function
  for (size_t i = minLabel, num = 0; i <= maxLabel; i++, num++) {
    //pull out this label
    ThreshType::Pointer thresh = ThreshType::New();
    thresh->SetInput(image);
    thresh->SetOutsideValue(0);
    thresh->ThresholdOutside(static_cast<double>(i) - 0.001,
      static_cast<double>(i) + 0.001);
    thresh->Update();
    //change the values to be from 0 to 1
    MultiplyImageFilterType::Pointer multiplyImageFilter =
      MultiplyImageFilterType::New();
    multiplyImageFilter->SetInput(thresh->GetOutput());
    multiplyImageFilter->SetConstant(1. / static_cast<double>(i));
    multiplyImageFilter->Update();
    //do some blurring
    GaussianBlurType::Pointer blur = GaussianBlurType::New();
    blur->SetInput(multiplyImageFilter->GetOutput());
    blur->SetVariance(sigma * sigma);
    blur->Update();
    //find the average value between
    ImageCalculatorFilterType::Pointer calc =
      ImageCalculatorFilterType::New();
    calc->SetImage(blur->GetOutput());
    calc->Compute();
    float mx = calc->GetMaximum();
    float mn = calc->GetMinimum();
    auto md = (mx + mn) / 2.f;
    //create a distance map with that minimum value as the levelset
    DMapType::Pointer dm = DMapType::New();
    dm->SetInput(blur->GetOutput());
    dm->SetInsideValue(md + 0.1f);
    dm->SetOutsideValue(md -0.1f);
    dm->Update();
    //MultiplyImageFilterType::Pointer mult =
    //  MultiplyImageFilterType::New();
    //mult->SetInput(blur->GetOutput());
    //mult->SetConstant(-20. / (mx - mn));
    //mult->Update();
    /*SubtractImageFilterType::Pointer subtractFilter
      = SubtractImageFilterType::New();
    subtractFilter->SetInput1(mult->GetOutput());
    subtractFilter->SetConstant2(1.);
    subtractFilter->Update();*/
    //convert the image to a cleaver "abstract field"
    auto img = dm->GetOutput();
    auto region = img->GetLargestPossibleRegion();
    auto numPixel = region.GetNumberOfPixels();
    float *data = new float[numPixel];
    auto x = region.GetSize()[0], y = region.GetSize()[1], z = region.GetSize()[2];
    fields.push_back(new cleaver::FloatField(data, x, y, z));
    auto beg = filename.find_last_of("/") + 1;
    auto name = filename.substr(beg, filename.size() - beg);
    auto fin = name.find_last_of(".");
    name = name.substr(0, fin);
    std::stringstream ss;
    ss << name << i;
    fields[num]->setName(ss.str());
    itk::ImageRegionConstIterator<ImageType> imageIterator(img, region);
    size_t pixel = 0;
    while (!imageIterator.IsAtEnd()) {
      // Get the value of the current pixel
      float val = static_cast<float>(imageIterator.Get());
      ((cleaver::FloatField*)fields[num])->data()[pixel++] = -val;
      ++imageIterator;
    }
    auto spacing = img->GetSpacing();
    ((cleaver::FloatField*)fields[num])->setScale(
      cleaver::vec3(spacing[0], spacing[1], spacing[2]));
    //NRRDTools::saveNRRDFile(fields[num], "a" + std::to_string(num));
  }
  return fields;
}
Beispiel #6
0
int main(int argc, char **argv) {
    args::ArgumentParser parser(
        "Calculates T1/B1 maps from MP2/3-RAGE data\nhttp://github.com/spinicist/QUIT");
    args::Positional<std::string> input_path(parser, "INPUT FILE", "Path to complex MP-RAGE data");
    args::HelpFlag                help(parser, "HELP", "Show this help message", {'h', "help"});
    args::Flag           verbose(parser, "VERBOSE", "Print more information", {'v', "verbose"});
    args::ValueFlag<int> threads(parser,
                                 "THREADS",
                                 "Use N threads (default=4, 0=hardware limit)",
                                 {'T', "threads"},
                                 QI::GetDefaultThreads());
    args::ValueFlag<std::string> outarg(
        parser, "OUTPREFIX", "Add a prefix to output filenames", {'o', "out"});
    args::ValueFlag<std::string> json_file(
        parser, "FILE", "Read JSON input from file instead of stdin", {"file"});
    args::ValueFlag<float> beta_arg(
        parser,
        "BETA",
        "Regularisation factor for robust contrast calculation "
        "(https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0099676)",
        {'b', "beta"},
        0.0);
    args::Flag t1(parser, "T1", "Calculate T1 map via spline look-up", {'t', "t1"});
    QI::ParseArgs(parser, argc, argv, verbose, threads);

    auto inFile = QI::ReadImage<QI::SeriesXF>(QI::CheckPos(input_path), verbose);

    auto ti_1                     = itk::ExtractImageFilter<QI::SeriesXF, QI::VolumeXF>::New();
    auto ti_2                     = itk::ExtractImageFilter<QI::SeriesXF, QI::VolumeXF>::New();
    auto region                   = inFile->GetLargestPossibleRegion();
    region.GetModifiableSize()[3] = 0;
    ti_1->SetExtractionRegion(region);
    ti_1->SetDirectionCollapseToSubmatrix();
    ti_1->SetInput(inFile);
    region.GetModifiableIndex()[3] = 1;
    ti_2->SetExtractionRegion(region);
    ti_2->SetDirectionCollapseToSubmatrix();
    ti_2->SetInput(inFile);

    QI::Log(verbose, "Generating MP2 contrasts");
    using BinaryFilter = itk::BinaryGeneratorImageFilter<QI::VolumeXF, QI::VolumeXF, QI::VolumeF>;
    auto MP2Filter     = BinaryFilter::New();
    MP2Filter->SetInput1(ti_1->GetOutput());
    MP2Filter->SetInput2(ti_2->GetOutput());
    const float &beta = beta_arg.Get();
    MP2Filter->SetFunctor([&](const std::complex<float> &p1, const std::complex<float> &p2) {
        return MP2Contrast(p1, p2, beta);
    });
    MP2Filter->Update();
    const std::string out_prefix = outarg ? outarg.Get() : QI::StripExt(input_path.Get());
    QI::WriteImage(MP2Filter->GetOutput(), out_prefix + "_MP2" + QI::OutExt(), verbose);

    if (t1) {
        QI::Log(verbose, "Reading sequence information");
        rapidjson::Document input =
            json_file ? QI::ReadJSON(json_file.Get()) : QI::ReadJSON(std::cin);
        QI::MP2RAGESequence mp2rage_sequence(input["MP2RAGE"]);
        QI::Log(verbose, "Building look-up spline");
        int            num_entries = 100;
        Eigen::ArrayXd T1_values   = Eigen::ArrayXd::LinSpaced(num_entries, 0.25, 4.0);
        Eigen::ArrayXd MP2_values(num_entries);
        for (int i = 0; i < num_entries; i++) {
            const auto  sig = One_MP2RAGE(1., T1_values[i], 1., mp2rage_sequence);
            const float mp2 = MP2Contrast(sig[0], sig[1]);
            if ((i > 0) && (mp2 > MP2_values[i - 1])) {
                num_entries = i;
                break;
            } else {
                MP2_values[i] = mp2;
            }
        }
        QI::Log(verbose, "Lookup table length = {}", num_entries);
        QI::SplineInterpolator mp2_to_t1(MP2_values.head(num_entries), T1_values.head(num_entries));
        if (beta) {
            QI::Log(verbose, "Recalculating unregularised MP2 image");
            MP2Filter->SetFunctor(
                [&](const std::complex<float> &p1, const std::complex<float> &p2) {
                    return MP2Contrast(p1, p2, 0.0);
                });
            MP2Filter->Update();
        }
        using UnaryFilter   = itk::UnaryGeneratorImageFilter<QI::VolumeF, QI::VolumeF>;
        auto T1LookupFilter = UnaryFilter::New();
        T1LookupFilter->SetInput(MP2Filter->GetOutput());
        auto lookup = [&](const float &p) { return mp2_to_t1(p); };
        T1LookupFilter->SetFunctor(lookup);
        QI::Log(verbose, "Calculating T1");
        T1LookupFilter->Update();
        QI::WriteImage(T1LookupFilter->GetOutput(), out_prefix + "_MP2_T1" + QI::OutExt(), verbose);
    }
    QI::Log(verbose, "Finished.");
    return EXIT_SUCCESS;
}