// -----------------------------------------------------------------------------
// Sort the entries of filtMagUpdateMap and set the threshold to be ? percentile
// -----------------------------------------------------------------------------
Real_t BFReconstructionEngine::SetNonHomThreshold(RealImageType::Pointer magUpdateMap)
{
  size_t dims[1] =
  { m_Geometry->N_z* m_Geometry->N_x};
  RealArrayType::Pointer TempMagMap = RealArrayType::New(dims, "TempMagMap");

  uint32_t ArrLength = m_Geometry->N_z * m_Geometry->N_x;
  Real_t threshold;

  //Copy into a new list for sorting
  Real_t* src = magUpdateMap->getPointer();
  Real_t* dest = TempMagMap->getPointer();
  ::memcpy(dest, src, ArrLength * sizeof(Real_t));

#ifdef DEBUG
  Real_t TempSum = 0;
  for(uint32_t i = 0; i < ArrLength; i++)
  { TempSum += TempMagMap->d[i]; }

  if(getVerbose()) { std::cout << "Temp mag map average= " << TempSum / ArrLength << std::endl; }
#endif //DEBUG

  /* for (uint32_t i = 0; i < m_Geometry->N_z; i++)
        for (uint32_t j = 0; j < m_Geometry->N_x; j++)
        {
            //TempMagMap->d[i*geometry->N_x+j]=i*geometry->N_x+j;
            TempMagMap->d[i * (uint32_t)m_Geometry->N_x + j] = magUpdateMap->getValue(i, j);
        } */

  uint32_t percentile_index = ArrLength / MBIR::Constants::k_NumNonHomogeniousIter;
  if(getVerbose()) { std::cout << "Percentile to select= " << percentile_index << std::endl; }

  //Partial selection sort

  /*Real_t max;
    uint32_t max_index;
    for (uint32_t i = 0; i <= percentile_index; i++)
    {
        max = TempMagMap->d[i];
        max_index = i;
        for (uint32_t j = i + 1; j < ArrLength; j++)
        {
            if(TempMagMap->d[j] > max)
            {
                max = TempMagMap->d[j];
                max_index = j;
            }
        }
        Real_t temp = TempMagMap->d[i];
        TempMagMap->d[i] = TempMagMap->d[max_index];
        TempMagMap->d[max_index] = temp;
    }
  threshold = TempMagMap->d[percentile_index];*/

  threshold = RandomizedSelect(TempMagMap, 0, ArrLength - 1, ArrLength - percentile_index);

  return threshold;
}
uint8_t BFReconstructionEngine::stopCriteria(RealImageType::Pointer magUpdateMap, UInt8Image_t::Pointer magUpdateMask, Real_t PrevMagSum, uint32_t EffIterCount)
{

  uint8_t exit_status = 1;
  if(getVeryVerbose())
  {
    Real_t TempSum = 0;
    for (int32_t j = 0; j < m_Geometry->N_z; j++)
    {
      for (int32_t k = 0; k < m_Geometry->N_x; k++)
      {
        TempSum += magUpdateMap->getValue(j, k);
      }
    }
    std::cout << "**********************************************" << std::endl;
    std::cout << "Average mag after voxel update" << TempSum / (m_Geometry->N_z * m_Geometry->N_x) << std::endl;
    std::cout << "**********************************************" << std::endl;
  }

#ifdef NHICD
  //In non homogenous mode check stopping criteria only after a full equit = equivalet iteration
  if(EffIterCount % MBIR::Constants::k_NumNonHomogeniousIter == 0 && EffIterCount > 0 && PrevMagSum > 0)
#else
  if(EffIterCount > 0 && PrevMagSum > 0)
#endif //NHICD
  {

    Real_t TempSum = 0;
    uint32_t counter = 0;
    for (int32_t j = 0; j < m_Geometry->N_z; j++)
      for (int32_t k = 0; k < m_Geometry->N_x; k++)
        if(magUpdateMask->getValue(j, k) == 1)
        {
          TempSum += magUpdateMap->getValue(j, k);
          counter++;
        }

    if(getVeryVerbose()) {std::cout << "Number of elements in the ROI after an equit= " << counter << std::endl;}

    if(getVerbose())
    {
      std::cout << "************************************************" << std::endl;
      std::cout << EffIterCount + 1 << " " << (fabs(TempSum) / fabs(PrevMagSum)) << std::endl;
      std::cout << "************************************************" << std::endl;
    }
    if( (fabs(TempSum) / fabs(PrevMagSum)) < m_TomoInputs->StopThreshold && EffIterCount > 0)
    {
      if(getVerbose()) { std::cout << "This is the terminating point " << EffIterCount << std::endl; }
      m_TomoInputs->StopThreshold *= m_AdvParams->THRESHOLD_REDUCTION_FACTOR; //Reducing the thresold for subsequent iterations
      if(getVerbose()) { std::cout << "New threshold" << m_TomoInputs->StopThreshold << std::endl; }
      exit_status = 0;
    }

  }

  return exit_status;
}
// -----------------------------------------------------------------------------
//Function to generate a randomized list from a given input list
// -----------------------------------------------------------------------------
VoxelUpdateList::Pointer BFReconstructionEngine::GenRandList(VoxelUpdateList::Pointer InpList)
{
  VoxelUpdateList::Pointer OpList;

  const uint32_t rangeMin = 0;
  const uint32_t rangeMax = std::numeric_limits<uint32_t>::max();
  typedef boost::uniform_int<uint32_t> NumberDistribution;
  typedef boost::mt19937 RandomNumberGenerator;
  typedef boost::variate_generator<RandomNumberGenerator&, NumberDistribution> Generator;

  NumberDistribution distribution(rangeMin, rangeMax);
  RandomNumberGenerator generator;
  Generator numberGenerator(generator, distribution);
  boost::uint32_t arg = static_cast<boost::uint32_t>(EIMTOMO_getMilliSeconds());
  generator.seed(arg); // seed with the current time

  int32_t ArraySize = InpList.NumElts;

  OpList.NumElts = ArraySize;
  OpList.Array = (struct ImgIdx*)(malloc(ArraySize * sizeof(struct ImgIdx)));

  size_t dims[3] =
  { ArraySize, 0, 0};
  Int32ArrayType::Pointer Counter = Int32ArrayType::New(dims, "Counter");

  for (int32_t j_new = 0; j_new < ArraySize; j_new++)
  {
    Counter->d[j_new] = j_new;
  }

  for(int32_t test_iter = 0; test_iter < InpList.NumElts; test_iter++)
  {
    int32_t Index = numberGenerator() % ArraySize;
    OpList.Array[test_iter] = InpList.Array[Counter->d[Index]];
    Counter->d[Index] = Counter->d[ArraySize - 1];
    ArraySize--;
  }

#ifdef DEBUG
  if(getVerbose()) { std::cout << "Input" << std::endl; }
  maxList(InpList);

  if(getVerbose()) { std::cout << "Output" << std::endl; }
  maxList(OpList);

#endif //Debug
  return OpList;
}
IoContext IoWorker::doMap() const
{
    const TraceSet &set = getTraceSet();
    TraceSet::Iterator iter = set.between(getBeginPos(), getEndPos());
    TraceSet::Iterator endIter = set.end();

    IoContext data;

    // Get event ids
    std::set<event_id_t> readEventIds {};
    for (const std::string &eventName : readSyscalls) {
        event_id_t id = getEventId(set, eventName);
        readEventIds.insert(id);
    }
    std::set<event_id_t> writeEventIds {};
    for (const std::string &eventName : writeSyscalls) {
        event_id_t id = getEventId(set, eventName);
        writeEventIds.insert(id);
    }
    std::set<event_id_t> readWriteEventIds {};
    for (const std::string &eventName : readWriteSyscalls) {
        event_id_t id = getEventId(set, eventName);
        readWriteEventIds.insert(id);
    }
    std::set<event_id_t> exitEventIds {};
    for (const std::string &eventName : exitSyscalls) {
        event_id_t id = getEventId(set, eventName);
        exitEventIds.insert(id);
    }

    // Iterate through events
    uint64_t count = 0;
    for ((void)iter; iter != endIter; ++iter) {
        count++;
        const auto &event = *iter;
        event_id_t id = event.getId();
        if (readEventIds.find(id) != readEventIds.end()) {
            data.handleSysRead(event);
        } else if (writeEventIds.find(id) != writeEventIds.end()) {
            data.handleSysWrite(event);
        } else if (readWriteEventIds.find(id) != readWriteEventIds.end()) {
            data.handleSysReadWrite(event);
        } else if (exitEventIds.find(id) != exitEventIds.end()) {
            data.handleExitSyscall(event);
        }
    }

    if (getVerbose()) {
        const timestamp_t *begin = getBeginPos();
        const timestamp_t *end = getEndPos();
        std::string beginString = begin ? std::to_string(*begin) : "START";
        std::string endString = end ? std::to_string(*end) : "END";
        std::cout << "Worker " << getId() << " processed " << count << " events between timestamps "
                  << beginString << " and " << endString << std::endl;
    }

    data.handleEnd();

    return data;
}
Пример #5
0
void _LogWrite(char *file, int line, const char *format, ...)
{
	va_list arg;
	time_t t = time(NULL);
	struct tm tm = *localtime(&t);
	char timeStr[32];
	sprintf(timeStr,"%4d-%.2d-%.2d %.2d:%.2d:%.2d",
					1900+tm.tm_year,
					tm.tm_mon+1,
					tm.tm_mday,
					tm.tm_hour,
					tm.tm_min,
					tm.tm_sec);
	if ( getVerbose() )
	{
		fprintf(stdout, "%s  %s:%d:", timeStr, file, line);
		va_start(arg, format);
		vfprintf(stdout, format, arg);
		va_end(arg);
	}

	if ( getDaemonize() )	
	{
		FILE *logFile;

		logFile = fopen((const char *)getLogFile(), "a");
		if ( ! logFile )
		{
			fprintf(stderr, "Error: Unable to open log file for writing!\n");
			fprintf(stderr, "%s  %s:%d:",timeStr, file, line);
			va_start(arg, format);
			vfprintf(stderr, format, arg);
			va_end(arg);
			return;
		}
		fprintf(logFile, "%s  %s:%d:",timeStr, file, line);
		va_start(arg, format);
		vfprintf(logFile, format, arg);
		va_end(arg);

		fclose(logFile);
	}
}
Пример #6
0
bool IApplication::start()
{
	if(getVerbose())
	{
		Options::instance()->setOption<bool>(Options::log_options::enable, true);
		Options::instance()->setOption<uint32>(Options::log_options::level, logLevelDebug);
		Options::instance()->setOption<bool>(Options::log_options::serialize, true);		
	}

	OS_ASSERT(Engine::exists() == false);
	if(Engine::create()->start(getRecoveryMode()) == false)
		return false;

	// N.B.: è necessario avviare il thread di listener dopo aver avviato l'engine in modo da evitare di processare comandi prima che quest'ultimo sia stato inizializzato
	if(m_notifyListener != nullptr)
		m_notifyListener->start();

	return true;
}
// -----------------------------------------------------------------------------
// Read the Input data from the supplied data file
// -----------------------------------------------------------------------------
int BFReconstructionEngine::readInputData()
{
  TomoFilter::Pointer dataReader = TomoFilter::NullPointer();
  std::string extension = MXAFileInfo::extension(m_TomoInputs->sinoFile);

  if(extension.compare("bin") == 0)
  {
    dataReader = RawSinogramInitializer::NewTomoFilter();
  }
  else
    // if(extension.compare("mrc") == 0 || extension.compare("ali") == 0)
  {
    // We are going to assume that the user has selected a valid MRC file to get this far so we are just going to try
    // to read the file as an MRC file which may really cause issues but there does not seem to be any standard file
    // extensions for MRC files.
    dataReader = MRCSinogramInitializer::NewTomoFilter();
  }

  //  {
  //    setErrorCondition(-1);
  //    notify("A supported file reader for the input file was not found.", 100, Observable::UpdateErrorMessage);
  //    return -1;
  //  }
  dataReader->setTomoInputs(m_TomoInputs);
  dataReader->setSinogram(m_Sinogram);
  dataReader->setAdvParams(m_AdvParams);
  dataReader->setObservers(getObservers());
  dataReader->setVerbose(getVerbose());
  dataReader->setVeryVerbose(getVeryVerbose());
  dataReader->execute();
  if(dataReader->getErrorCondition() < 0)
  {
    std::stringstream ss;
    ss << "Error reading the input file: '" << m_TomoInputs->sinoFile << "'. MBIR currently considers .bin as a raw binary file "
       << "and any other file as an MRC input file. If this is NOT the case for your data consider contacting the developers "
       << " of this software.";
    notify(ss.str(), 100, Observable::UpdateErrorMessage);
    setErrorCondition(dataReader->getErrorCondition());
    return -1;
  }
  return 0;
}
Пример #8
0
// insert start and goal nodes into the abstract graph before running
// any search.
node*
DefaultInsertionPolicy::insert(node* n)
	throw(std::invalid_argument)
{
	node* retVal = 0;
	resetMetrics();

	//assert(insertedStartNode == 0 && insertedGoalNode == 0);
	if(n->getLabelL(kParent) == -1)
	{
		ClusterNode* target = dynamic_cast<ClusterNode*>(n);
		AbstractCluster* cluster = map->getCluster(
			target->getParentClusterId());

		if(getVerbose())
		{
			const int x = target->getLabelL(kFirstData);
			const int y = target->getLabelL(kFirstData+1);
			std::cout << "inserting node ("<<x<<", "<<y<<") "
				"into abstract graph"<<std::endl;
		}

		cluster->addParent(target);
		graph* absg = map->getAbstractGraph(1);
		retVal = absg->getNode(target->getLabelL(kParent));
		addNode(retVal);
		//assert(retVal);
		
		searchTime = cluster->getSearchTime();
		nodesExpanded = cluster->getNodesExpanded();
		nodesGenerated = cluster->getNodesGenerated();
		nodesTouched = cluster->getNodesTouched();
	}
	else
	{
		retVal = map->getAbstractGraph(1)->getNode(
				n->getLabelL(kParent));
	}

	return retVal;
}
// -----------------------------------------------------------------------------
// Initialize the Geometry data from a rough reconstruction
// -----------------------------------------------------------------------------
int BFReconstructionEngine::initializeRoughReconstructionData()
{
  InitialReconstructionInitializer::Pointer geomInitializer = InitialReconstructionInitializer::NullPointer();
  std::string extension = MXAFileInfo::extension(m_TomoInputs->initialReconFile);
  if (m_TomoInputs->initialReconFile.empty() == true)
  {
    // This will just initialize all the values to Zero (0) or a DefaultValue Set by user
    geomInitializer = InitialReconstructionInitializer::New();
  }
  else if (extension.compare("bin") == 0 )
  {
    // This will read the values from a binary file
    geomInitializer = InitialReconstructionBinReader::NewInitialReconstructionInitializer();
  }
  else if (extension.compare("mrc") == 0)
  {
    notify("We are not dealing with mrc volume files.", 0, Observable::UpdateErrorMessage);
    return -1;
  }
  else
  {
    notify("Could not find a compatible reader for the initial reconstruction data file. The program will now end.", 0, Observable::UpdateErrorMessage);
    return -1;
  }
  geomInitializer->setSinogram(m_Sinogram);
  geomInitializer->setTomoInputs(m_TomoInputs);
  geomInitializer->setGeometry(m_Geometry);
  geomInitializer->setAdvParams(m_AdvParams);
  geomInitializer->setObservers(getObservers());
  geomInitializer->setVerbose(getVerbose());
  geomInitializer->setVeryVerbose(getVeryVerbose());
  geomInitializer->execute();

  if(geomInitializer->getErrorCondition() < 0)
  {
    notify("Error reading Initial Reconstruction Data from File", 100, Observable::UpdateProgressValueAndMessage);
    setErrorCondition(geomInitializer->getErrorCondition());
    return -1;
  }
  return 0;
}
Пример #10
0
// addParent is responsible for adding new abstract nodes to the cluster and
// creating intra-edges that connect the new node to existing abstract nodes. 
void 
AbstractCluster::addParent(node* _p) throw(std::invalid_argument)
{
	Timer t;
	t.startTimer();
	ClusterNode* p = dynamic_cast<ClusterNode*>(_p);

	if(p == 0)
		throw std::invalid_argument(
				"AbstractCluster::addParent: arg not of type AbstractClusterNode");

	if(p->getParentClusterId() != this->getId())
		throw std::invalid_argument(
				"AbstractCluster::addParent: arg not assigned to this cluster");

	if(parents.find(p->getUniqueID()) != parents.end())
		return; // node already in parents collection

	if(p->getLabelL(kAbstractionLevel) == 0)
	{
		ClusterNode* p2 = dynamic_cast<ClusterNode*>(
				map->getNodeFactory()->newNode(p));
		p2->setLabelL(kAbstractionLevel, 1);
		p2->setLabelL(kParent, -1);
		map->getAbstractGraph(1)->addNode(p2);
		p->setLabelL(kParent, p2->getNum());
		p = p2;
	}
	
	if(getVerbose())
	{
		std::cout << "AbstractCluster::addParent ";
		p->Print(std::cout);
		std::cout << std::endl;
	}

	p->setParentClusterId(this->getId());
	parents.insert(std::pair<int, node*>(p->getUniqueID(), p));
	connectParent(p);
	searchTime = t.endTimer();
}
// -----------------------------------------------------------------------------
// Updates the voxels specified in the list for homogenous update. For non homgenous
// update computes the list. Calls the parallel update of voxels routine
// -----------------------------------------------------------------------------
uint8_t BFReconstructionEngine::updateVoxels(int16_t OuterIter,
                                             int16_t Iter,
                                             std::vector<AMatrixCol::Pointer>& TempCol,
                                             RealVolumeType::Pointer ErrorSino,
                                             std::vector<AMatrixCol::Pointer>& VoxelLineResponse,
                                             CostData::Pointer cost,
                                             QGGMRF::QGGMRF_Values* BFQGGMRF_values,
                                             RealImageType::Pointer magUpdateMap,
                                             RealImageType::Pointer filtMagUpdateMap,
                                             UInt8Image_t::Pointer magUpdateMask,
                                             UInt8Image_t::Pointer m_VisitCount,
                                             Real_t PrevMagSum,
                                             uint32_t EffIterCount)

{

#if ROI
  //variables used to stop the process
  Real_t AverageUpdate = 0;
  Real_t AverageMagnitudeOfRecon = 0;
#endif

  unsigned int updateType = MBIR::VoxelUpdateType::RegularRandomOrderUpdate;
  VoxelUpdateList::Pointer NHList;//non homogenous list of voxels to update


#ifdef NHICD
  if(0 == EffIterCount % 2)
  {
    updateType = MBIR::VoxelUpdateType::HomogeniousUpdate;
  }
  else
  {
    updateType = MBIR::VoxelUpdateType::NonHomogeniousUpdate;
  }
#endif//NHICD end if

#if defined (OpenMBIR_USE_PARALLEL_ALGORITHMS)
  tbb::task_scheduler_init init;
  int m_NumThreads = init.default_num_threads();
#else
  int m_NumThreads = 1;
#endif //Parallel algorithms

  std::stringstream ss;
  uint8_t exit_status = 1; //Indicates normal exit ; else indicates to stop inner iterations
  uint16_t subIterations = 1;
  std::string indent("    ");
  uint8_t err = 0;


  if(updateType == MBIR::VoxelUpdateType::RegularRandomOrderUpdate)
  {
    ss << indent << "Regular Random Order update of Voxels" << std::endl;
  }
  else if(updateType == MBIR::VoxelUpdateType::HomogeniousUpdate)
  {
    ss << indent << "Homogenous update of voxels" << std::endl;
  }
  else if(updateType == MBIR::VoxelUpdateType::NonHomogeniousUpdate)
  {
    ss << indent << "Non Homogenous update of voxels" << std::endl;
    subIterations = SUB_ITER;
  }
  else
  {
    ss << indent << "Unknown Voxel Update Type. Returning Now" << std::endl;
    notify(ss.str(), 0, Observable::UpdateErrorMessage);
    return exit_status;
  }

  if(getVerbose())
  {
    std::cout << ss.str() << std::endl;
  }

  Real_t NH_Threshold = 0.0;
  int totalLoops = m_TomoInputs->NumOuterIter * m_TomoInputs->NumIter;

#ifdef DEBUG
  if (getVeryVerbose())
  {
    std::cout << "Max of list in ReconEngineExtra = " << std::endl;
    m_VoxelIdxList->printMaxList(std::cout);
  }
#endif //DEBUG

  for (uint16_t NH_Iter = 0; NH_Iter < subIterations; ++NH_Iter) //This can be varied
    //so each iterations of the voxels has multiple passes over the voxels
    //but generally its set to 1
  {

    ss.str(" ");
    ss << "Outer Iteration: " << OuterIter << " of " << m_TomoInputs->NumOuterIter;
    ss << "   Inner Iteration: " << Iter << " of " << m_TomoInputs->NumIter;
    ss << "   SubLoop: " << NH_Iter << " of " << subIterations;
    float currentLoop = static_cast<float>(OuterIter * m_TomoInputs->NumIter + Iter);
    notify(ss.str(), currentLoop / totalLoops * 100.0f, Observable::UpdateProgressValueAndMessage);
    if(updateType == MBIR::VoxelUpdateType::NonHomogeniousUpdate)
    {
#ifdef DEBUG
      Real_t TempSum = 0;
      for (int32_t j = 0; j < m_Geometry->N_z; j++)
      {
        for (int32_t k = 0; k < m_Geometry->N_x; k++)
        {
          TempSum += magUpdateMap->getValue(j, k);
        }
      }
      if (getVeryVerbose())
      {
        std::cout << "**********************************************" << std::endl;
        std::cout << "Average mag Prior to VSC" << TempSum / (m_Geometry->N_z * m_Geometry->N_x) << std::endl;
        std::cout << "**********************************************" << std::endl;
      }
#endif //debug

      //Compute a filtered version of the magnitude update map
      ComputeVSC(magUpdateMap, filtMagUpdateMap);

#ifdef DEBUG
      TempSum = 0;
      for (int32_t j = 0; j < m_Geometry->N_z; j++)
      {
        for (int32_t k = 0; k < m_Geometry->N_x; k++)
        {
          TempSum += magUpdateMap->getValue(j, k);
        }
      }
      if (getVeryVerbose())
      {
        std::cout << "**********************************************" << std::endl;
        std::cout << "Average mag Prior to NH Thresh" << TempSum / (m_Geometry->N_z * m_Geometry->N_x) << std::endl;
        std::cout << "**********************************************" << std::endl;
      }
#endif //debug

      START_TIMER;
      NH_Threshold = SetNonHomThreshold(filtMagUpdateMap);
      STOP_TIMER;
      PRINT_TIME("  SetNonHomThreshold");
      if(getVerbose()) { std::cout << indent << "NHICD Threshold: " << NH_Threshold << std::endl; }
      //Generate a new List based on the NH_threshold
      m_VoxelIdxList = GenNonHomList(NH_Threshold, filtMagUpdateMap);
    }


    START_TIMER;
#if defined (OpenMBIR_USE_PARALLEL_ALGORITHMS)

    std::vector<int> yCount(m_NumThreads, 0);
    int t = 0;

    for (int y = 0; y < m_Geometry->N_y; ++y)
    {
      yCount[t]++;
      ++t;
      if(t == m_NumThreads)
      {
        t = 0;
      }
    }


    //Checking which voxels are going to be visited and setting their magnitude value to zero
    for(int32_t tmpiter = 0; tmpiter < m_VoxelIdxList->numElements(); tmpiter++)
    {
      //   m_VisitCount->setValue(1, m_VoxelIdxList.Array[tmpiter].zidx, m_VoxelIdxList.Array[tmpiter].xidx);
      m_VisitCount->setValue(1, m_VoxelIdxList->zIdx(tmpiter), m_VoxelIdxList->xIdx(tmpiter));
      //   magUpdateMap->setValue(0, m_VoxelIdxList.Array[tmpiter].zidx, m_VoxelIdxList.Array[tmpiter].xidx);
      magUpdateMap->setValue(0, m_VoxelIdxList->zIdx(tmpiter), m_VoxelIdxList->xIdx(tmpiter));
    }

    uint16_t yStart = 0;
    uint16_t yStop = 0;

    tbb::task_list taskList;

    //Variables to maintain stopping criteria for regular type ICD
    boost::shared_array<Real_t> averageUpdate(new Real_t[m_NumThreads]);
    ::memset(averageUpdate.get(), 0, sizeof(Real_t) * m_NumThreads);
    boost::shared_array<Real_t> averageMagnitudeOfRecon(new Real_t[m_NumThreads]);
    ::memset(averageMagnitudeOfRecon.get(), 0, sizeof(Real_t) * m_NumThreads);

    size_t dims[3];
    //Initialize individual magnitude maps for the separate threads
    dims[0] = m_Geometry->N_z; //height
    dims[1] = m_Geometry->N_x; //width
    std::vector<RealImageType::Pointer> magUpdateMaps;

    std::vector<VoxelUpdateList::Pointer> NewList(m_NumThreads);
    int16_t EffCoresUsed = 0;

    if(getVerbose()) { std::cout << " Starting multicore allocation with " << m_NumThreads << " threads.." << std::endl; }

    for (int t = 0; t < m_NumThreads; ++t)
    {

      yStart = yStop;
      yStop = yStart + yCount[t];

      if (getVeryVerbose())
      {
        std::cout << "Thread :" << t << "(" << yStart << "," << yStop << ")" << std::endl;
      }

      if(yStart == yStop)
      {
        continue;
      } // Processor has NO tasks to run because we have less Y's than cores
      else
      {
        EffCoresUsed++;
      }

      RealImageType::Pointer _magUpdateMap = RealImageType::New(dims, "Mag Update Map");
      _magUpdateMap->initializeWithZeros();
      magUpdateMaps.push_back(_magUpdateMap);

      //NewList[t] = m_VoxelIdxList;
      NewList[t] = VoxelUpdateList::GenRandList(m_VoxelIdxList);

      BFUpdateYSlice& a =
        *new (tbb::task::allocate_root()) BFUpdateYSlice(yStart, yStop, m_Geometry, OuterIter, Iter,
                                                         m_Sinogram, TempCol, ErrorSino,
                                                         VoxelLineResponse, m_ForwardModel.get(),
                                                         magUpdateMask,
                                                         _magUpdateMap,
                                                         magUpdateMask, updateType,
                                                         averageUpdate.get() + t,
                                                         averageMagnitudeOfRecon.get() + t,
                                                         m_AdvParams->ZERO_SKIPPING,
                                                         BFQGGMRF_values, NewList[t] );
      taskList.push_back(a);
    }

    tbb::task::spawn_root_and_wait(taskList);

    if(getVerbose())
    {
      std::cout << " Voxel update complete using " << EffCoresUsed << " threads" << std::endl;
    }

    // Now sum up magnitude update map values
    //TODO: replace by a TBB reduce operation
    for (int t = 0; t < m_NumThreads; ++t)
    {

#ifdef DEBUG
      if(getVeryVerbose()) //TODO: Change variable name averageUpdate to totalUpdate
      {
        std::cout << "Total Update for thread " << t << ":" << averageUpdate[t] << std::endl;
        std::cout << "Total Magnitude for thread " << t << ":" << averageMagnitudeOfRecon[t] << std::endl;
      }
#endif //Debug
      AverageUpdate += averageUpdate[t];
      AverageMagnitudeOfRecon += averageMagnitudeOfRecon[t];
    }
    averageUpdate.reset(); // We are forcing the array to be deallocated, we could wait till the current scope terminates then the arrays would be automatically cleaned up
    averageMagnitudeOfRecon.reset(); // We are forcing the array to be deallocated, we could wait till the current scope terminates then the arrays would be automatically cleaned up
    NewList.resize(0); // Frees all the pointers

    //From individual threads update the magnitude map
    if(getVerbose()) { std::cout << " Magnitude Map Update.." << std::endl; }
    RealImageType::Pointer TempPointer;
    for(int32_t tmpiter = 0; tmpiter < m_VoxelIdxList->numElements(); tmpiter++)
    {
      Real_t TempSum = 0;
      for (uint16_t t = 0; t < magUpdateMaps.size(); ++t)
      {
        TempPointer = magUpdateMaps[t];
        TempSum += TempPointer->getValue(m_VoxelIdxList->zIdx(tmpiter), m_VoxelIdxList->xIdx(tmpiter));
      }

      //Set the overall magnitude update map
      magUpdateMap->setValue(TempSum, m_VoxelIdxList->zIdx(tmpiter), m_VoxelIdxList->xIdx(tmpiter));
    }

#else //TODO modify the single thread code to handle the list based iterations
    uint16_t yStop = m_Geometry->N_y;
    uint16_t yStart = 0;
    boost::shared_array<Real_t> averageUpdate(new Real_t[m_NumThreads]);
    ::memset(averageUpdate.get(), 0, sizeof(Real_t) * m_NumThreads);
    boost::shared_array<Real_t> averageMagnitudeOfRecon(new Real_t[m_NumThreads]);
    ::memset(averageMagnitudeOfRecon.get(), 0, sizeof(Real_t) * m_NumThreads);

    size_t dims[3];
    //Initialize individual magnitude maps for the separate threads
    dims[0] = m_Geometry->N_z; //height
    dims[1] = m_Geometry->N_x; //width
    RealImageType::Pointer _magUpdateMap = RealImageType::New(dims, "Mag Update Map");
    _magUpdateMap->initializeWithZeros();

    struct List NewList = m_VoxelIdxList;
    NewList = GenRandList(NewList);


    BFUpdateYSlice yVoxelUpdate = BFUpdateYSlice(yStart, yStop, m_Geometry, OuterIter, Iter,
                                                 m_Sinogram, TempCol, ErrorSino,
                                                 VoxelLineResponse, m_ForwardModel.get(),
                                                 magUpdateMask,
                                                 _magUpdateMap,
                                                 magUpdateMask, updateType,
                                                 averageUpdate,
                                                 averageMagnitudeOfRecon,
                                                 m_AdvParams->ZERO_SKIPPING,
                                                 BFQGGMRF_values, NewList);

    /*BFUpdateYSlice(yStart, yStop, m_Geometry, OuterIter, Iter,
           m_Sinogram, TempCol, ErrorSino,
           VoxelLineResponse, m_ForwardModel.get(), mask,
           magUpdateMap,
           magUpdateMask, updateType,
           NH_Threshold,
           averageUpdate,
           averageMagnitudeOfRecon ,
           m_AdvParams->ZERO_SKIPPING,
           BFQGGMRF_values, m_VoxelIdxList);*/

    yVoxelUpdate.execute();

    //    AverageUpdate += averageUpdate[0];
    //    AverageMagnitudeOfRecon += averageMagnitudeOfRecon[0];
    averageUpdate.reset(); // We are forcing the array to be deallocated, we could wait till the current scope terminates then the arrays would be automatically cleaned up
    averageMagnitudeOfRecon.reset(); // We are forcing the array to be deallocated, we could wait till the current scope terminates then the arrays would be automatically cleaned up

#endif //Parallel algorithms
    /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */STOP_TIMER;
    ss.str("");
    ss << "Inner Iter: " << Iter << " Voxel Update";
    PRINT_TIME(ss.str());

    if(getVerbose())
    {
      std::cout << "Total Update " << AverageUpdate << std::endl;
      std::cout << "Total Mag " << AverageMagnitudeOfRecon << std::endl;
    }

    if(getCancel() == true)
    {
      setErrorCondition(err);
      return exit_status;
    }

  }

  //Stopping criteria code
  exit_status = stopCriteria(magUpdateMap, magUpdateMask, PrevMagSum, EffIterCount);

#ifdef WRITE_INTERMEDIATE_RESULTS

  if(Iter == NumOfWrites * WriteCount)
  {
    WriteCount++;
    sprintf(buffer, "%d", Iter);
    sprintf(Filename, "ReconstructedObjectAfterIter");
    strcat(Filename, buffer);
    strcat(Filename, ".bin");
    Fp3 = fopen(Filename, "w");
    TempPointer = geometry->Object;
    NumOfBytesWritten = fwrite(&(geometry->Object->d[0][0][0]), sizeof(Real_t), geometry->N_x * geometry->N_y * geometry->N_z, Fp3);
    printf("%d\n", NumOfBytesWritten);

    fclose(Fp3);
  }
#endif //write Intermediate results

#ifdef NHICD
  /* NHList will go out of scope at the end of this function which will cause its destructor to be called and the memory automatically cleaned up */
  //  if(updateType == MBIR::VoxelUpdateType::NonHomogeniousUpdate && NHList.Array != NULL)
  //  {
  //    free(NHList.Array);
  //    std::cout<<"Freeing memory allocated to non-homogenous List"<<std::endl;
  //  }
#endif //NHICD

  if(getVerbose()) { std::cout << "exiting voxel update routine" << std::endl; }
  return exit_status;

}
Пример #12
0
// a transition point connects two nodes on the map. usually the nodes are on the
// border of two adjacent clusters (in which case the transition results in an
// inter-edge being created) but this is not necessary.
void 
AbstractCluster::addTransition(node* from_, node* to_, double edgeweight)
	throw(std::invalid_argument)
{
	if(edgeweight < 0)
		throw std::invalid_argument(
			"AbstractCluster::addTransition edge weight cannot be < 0");

	ClusterNode* from = dynamic_cast<ClusterNode*>(from_);
	ClusterNode* to = dynamic_cast<ClusterNode*>(to_);
	assert(from && to);

	graph *g = map->getAbstractGraph(1);
	ClusterNode* absfrom = 
		dynamic_cast<ClusterNode*>(g->getNode(from->getLabelL(kParent)));
	ClusterNode* absto = 
		dynamic_cast<ClusterNode*>(g->getNode(to->getLabelL(kParent)));
	
	// Try to reuse existing nodes from the abstract graph, else create new.
	if(absfrom == 0)
	{
		if(from->getLabelL(kFirstData) == 20 && from->getLabelL(kFirstData+1) == 0)
			std::cout << "master\n";
		AbstractCluster* parentCluster =
			map->getCluster(from->getParentClusterId());
		parentCluster->addParent(from); // also creates intra-edges
		absfrom = dynamic_cast<ClusterNode*>(g->getNode(from->getLabelL(kParent)));
		assert(absfrom);
	}
	if(absto == 0)
	{	
		AbstractCluster* parentCluster = 
			map->getCluster(to->getParentClusterId());
		parentCluster->addParent(to); // also creates intra-edges
		absto = dynamic_cast<ClusterNode*>(g->getNode(to->getLabelL(kParent)));
		assert(absto);
	}

	edge* e = g->findEdge(absfrom->getNum(), absto->getNum());
	if(!e)
	{
		edge* e = map->getEdgeFactory()->newEdge(absfrom->getNum(), 
				absto->getNum(), edgeweight);
		g->addEdge(e);

		if(getVerbose())
		{
			std::cout << "AbstractCluster::addTransition between ";
			from->Print(std::cout);
			to->Print(std::cout);
			std::cout << " cost: "<<edgeweight<<std::endl;
		}
	}
	else
	{
		if(getVerbose())
		{
			std::cout << "AbstractCluster::addTransition edge already exists: ";
			from->Print(std::cout);
			to->Print(std::cout);
			std::cout << " cost: "<<e->getWeight()<<std::endl;
		}
	}
}
Пример #13
0
// -----------------------------------------------------------------------------
// Main ICD reconstruction
// -----------------------------------------------------------------------------
void BFReconstructionEngine::execute()
{
  uint64_t totalTime = EIMTOMO_getMilliSeconds();
  int32_t err = 0;

  std::stringstream ss;

  // int16_t i,j,k,Idx;
  size_t dims[3];



  uint16_t maxNumberOfDetectorElts;
  uint8_t status; //set to 1 if ICD has converged

  Real_t checksum = 0, temp;

  RealImageType::Pointer voxelProfile;
  RealVolumeType::Pointer detectorResponse;
  RealVolumeType::Pointer h_t;

  RealVolumeType::Pointer y_Est; //Estimated Sinogram
  RealVolumeType::Pointer finalSinogram; //To store and write the final sinogram resulting from our reconstruction
  RealVolumeType::Pointer errorSino; //Error Sinogram

  std::string indent("");

  //#ifdef COST_CALCULATE //Commented out because if not the code fails to run.
  std::string filepath(m_TomoInputs->tempDir);
  filepath = filepath.append(MXADir::getSeparator()).append(MBIR::Defaults::CostFunctionFile);

  CostData::Pointer cost = CostData::New();
  cost->initOutputFile(filepath);
  //#endif

#if OpenMBIR_USE_PARALLEL_ALGORITHMS
  tbb::task_scheduler_init init;
#endif

  // Initialize the Sinogram
  if(m_TomoInputs == NULL)
  {
    setErrorCondition(-1);
    notify("Error: The TomoInput Structure was NULL. The proper API is to supply this class with that structure,", 100, Observable::UpdateErrorMessage);
    return;
  }
  //Based on the inputs , calculate the "other" variables in the structure definition
  if(m_Sinogram == NULL)
  {
    setErrorCondition(-1);
    notify("Error: The Sinogram Structure was NULL. The proper API is to supply this class with that structure,", 100, Observable::UpdateErrorMessage);
    return;
  }
  if(m_Geometry == NULL)
  {
    setErrorCondition(-1);
    notify("Error: The Geometry Structure was NULL. The proper API is to supply this class with that structure,", 100, Observable::UpdateErrorMessage);
    return;
  }
  if (m_ForwardModel.get() == NULL)
  {
    setErrorCondition(-1);
    notify("Error: The forward model was not set.", 100, Observable::UpdateErrorMessage);
    return;
  }

  // Read the Input data from the supplied data file - reconstruction from previous resolution ?
  err = readInputData();
  if(err < 0)
  {
    return;
  }
  if (getCancel() == true) { setErrorCondition(-999); return; }


  if (getCancel() == true) { setErrorCondition(-999); return; }


  //Additional parameters associated with the system
  err = m_ForwardModel->createNuisanceParameters(m_Sinogram);
  if(err < 0)
  {
    return;
  }

  //Periodically checking if user has sent a cancel signal from the GUI
  if (getCancel() == true) { setErrorCondition(-999); return; }

  m_ForwardModel->printNuisanceParameters(m_Sinogram);

  //Take log of the input data after subtracting offset
  m_ForwardModel->processRawCounts(m_Sinogram);


  // Initialize the Geometry data from a rough reconstruction
  err = initializeRoughReconstructionData();
  if(err < 0)
  {
    return;
  }
  if (getCancel() == true) { setErrorCondition(-999); return; }

  // Get the actual boundaries in the X Direction since we "Extend Object" which makes
  // the output mrc file much wider than they really need to be.
  uint16_t cropStart = 0;
  uint16_t cropEnd = m_Geometry->N_x;
  computeOriginalXDims(cropStart, cropEnd);
  //  std::cout << "Crop Start: " << cropStart << std::endl;
  //  std::cout << "Crop End:   " << cropEnd << std::endl;

  m_ForwardModel->allocateNuisanceParameters(m_Sinogram);

  //#ifdef COST_CALCULATE
  //  dims[0] = (m_TomoInputs->NumIter+1)*m_TomoInputs->NumOuterIter*3;
  //#endif

  dims[0] = m_Sinogram->N_theta;
  dims[1] = m_Sinogram->N_r;
  dims[2] = m_Sinogram->N_t;

  y_Est = RealVolumeType::New(dims, "y_Est");//y_Est = A*x_{initial}
  errorSino = RealVolumeType::New(dims, "ErrorSino");// y - y_est
  m_ForwardModel->weightInitialization(dims); //Initialize the \lambda matrix

  finalSinogram = RealVolumeType::New(dims, "Final Sinogram"); //Debug variable to store the final A*x_{Final}

  /*************** Computation of partial Amatrix *************/

  //calculate the trapezoidal voxel profile for each angle.Also the angles in the Sinogram
  // Structure are converted to radians
  voxelProfile = calculateVoxelProfile(); //This is used for computation of the partial A matrix

  //Pre compute sine and cos theta to speed up computations
  DetectorParameters::Pointer haadfParameters = DetectorParameters::New();
  haadfParameters->setOffsetR ( ((m_TomoInputs->delta_xz / sqrt(3.0)) + m_Sinogram->delta_r / 2) / m_AdvParams->DETECTOR_RESPONSE_BINS);
  haadfParameters->setOffsetT ( ((m_TomoInputs->delta_xz / 2) + m_Sinogram->delta_t / 2) / m_AdvParams->DETECTOR_RESPONSE_BINS);
  haadfParameters->setBeamWidth(m_Sinogram->delta_r);
  haadfParameters->calculateSinCos(m_Sinogram);
  //Initialize the e-beam
  haadfParameters->initializeBeamProfile(m_Sinogram, m_AdvParams); //The shape of the averaging kernel for the detector


  if (getCancel() == true) { setErrorCondition(-999); return; }

  //calculate sine and cosine of all angles and store in the global arrays sine and cosine
  DetectorResponse::Pointer dResponseFilter = DetectorResponse::New();
  dResponseFilter->setTomoInputs(m_TomoInputs);
  dResponseFilter->setSinogram(m_Sinogram);
  dResponseFilter->setAdvParams(m_AdvParams);
  dResponseFilter->setDetectorParameters(haadfParameters);
  dResponseFilter->setVoxelProfile(voxelProfile);
  dResponseFilter->setObservers(getObservers());
  dResponseFilter->setVerbose(getVerbose());
  dResponseFilter->setVeryVerbose(getVeryVerbose());
  dResponseFilter->execute();
  if(dResponseFilter->getErrorCondition() < 0)
  {
    ss.str("");
    ss << "Error Calling function detectorResponse in file " << __FILE__ << "(" << __LINE__ << ")" << std::endl;
    setErrorCondition(-2);
    notify(ss.str(), 100, Observable::UpdateErrorMessage);
    return;
  }
  detectorResponse = dResponseFilter->getResponse();
  // Writer the Detector Response to an output file
  DetectorResponseWriter::Pointer responseWriter = DetectorResponseWriter::New();
  responseWriter->setTomoInputs(m_TomoInputs);
  responseWriter->setSinogram(m_Sinogram);
  responseWriter->setAdvParams(m_AdvParams);
  responseWriter->setObservers(getObservers());
  responseWriter->setResponse(detectorResponse);
  responseWriter->setVerbose(getVerbose());
  responseWriter->setVeryVerbose(getVeryVerbose());
  responseWriter->execute();
  if(responseWriter->getErrorCondition() < 0)
  {
    ss.str("");
    ss << __FILE__ << "(" << __LINE__ << ") " << "Error writing detector response to file." <<  std::endl;
    setErrorCondition(-3);
    notify(ss.str(), 100, Observable::UpdateErrorMessage);
    return;
  }

  if (getCancel() == true) { setErrorCondition(-999); return; }

  // Initialize H_t volume
  dims[0] = 1;
  dims[1] = m_Sinogram->N_theta;
  dims[2] = m_AdvParams->DETECTOR_RESPONSE_BINS;
  h_t = RealVolumeType::New(dims, "h_t");
  initializeHt(h_t, haadfParameters->getOffsetT() );

  checksum = 0;

  ss.str("");
  ss << "Calculating A Matrix....";
  notify(ss.str(), 0, Observable::UpdateProgressMessage);


  std::vector<AMatrixCol::Pointer> voxelLineResponse(m_Geometry->N_y);

  maxNumberOfDetectorElts = (uint16_t)((m_TomoInputs->delta_xy / m_Sinogram->delta_t) + 2);
  dims[0] = maxNumberOfDetectorElts;
  for (uint16_t i = 0; i < m_Geometry->N_y; i++)
  {
    AMatrixCol::Pointer vlr = AMatrixCol::New(dims, 0);
    voxelLineResponse[i] = vlr;
  }

  //Calculating A-Matrix one column at a time
  //For each entry the idea is to initially allocate space for Sinogram.N_theta * Sinogram.N_x
  // And then store only the non zero entries by allocating a new array of the desired size
  std::vector<AMatrixCol::Pointer> tempCol(m_Geometry->N_x * m_Geometry->N_z);

  checksum = 0;
  temp = 0;
  uint32_t voxel_count = 0;
  for (uint16_t z = 0; z < m_Geometry->N_z; z++)
  {
    for (uint16_t x = 0; x < m_Geometry->N_x; x++)
    {
      tempCol[voxel_count] = AMatrixCol::calculateAMatrixColumnPartial(m_Sinogram, m_Geometry, m_TomoInputs, m_AdvParams,
                             z, x, 0, detectorResponse, haadfParameters);
      temp += tempCol[voxel_count]->count;
      if(0 == tempCol[voxel_count]->count )
      {
        //If this line is never hit and the Object is badly initialized
        //set it to zero
        for (uint16_t y = 0; y < m_Geometry->N_y; y++)
        {
          m_Geometry->Object->setValue(0.0, z, x, y);
        }
      }
      voxel_count++;
    }
  }

  storeVoxelResponse(h_t, voxelLineResponse, haadfParameters);

  if (getCancel() == true) { setErrorCondition(-999); return; }

  if(getVerbose())
  {
    printf("Number of non zero entries of the forward projector is %lf\n", temp);
    printf("Geometry-Z %d\n", m_Geometry->N_z);
  }
  /************ End of A matrix partial computations **********************/

  //Gain and Offset Parameters Initialization of the forward model
  m_ForwardModel->gainAndOffsetInitialization(m_Sinogram->N_theta);

  initializeVolume(y_Est, 0.0);


  if (getCancel() == true) { setErrorCondition(-999); return; }

  //Forward Project Geometry->Object one slice at a time and compute the  Sinogram for each slice
  // Forward Project using the Forward Model
  err = m_ForwardModel->forwardProject(m_Sinogram, m_Geometry, tempCol, voxelLineResponse, y_Est , errorSino);
  if (err < 0)
  {
    return;
  }
  if (getCancel() == true) { setErrorCondition(-999); return; }


#ifdef FORWARD_PROJECT_MODE
  return 0; //exit the program once we finish forward projecting the object
#endif//Forward Project mode

  // Initialize the Prior Model parameters - here we are using a QGGMRF Prior Model
  QGGMRF::QGGMRF_Values QGGMRF_values;
  QGGMRF::initializePriorModel(m_TomoInputs, &QGGMRF_values, NULL);

#ifdef COST_CALCULATE
  err = calculateCost(cost, m_Sinogram, m_Geometry, errorSino, &QGGMRF_values);
#endif //Cost calculation endif

  Real_t TempBraggValue, DesBraggValue;
#ifdef BRAGG_CORRECTION
  if(m_TomoInputs->NumIter > 1)
  {
    //Get the value of the Bragg threshold from the User Interface the first time
    DesBraggValue = m_ForwardModel->getBraggThreshold();
    if (getVeryVerbose()) {std::cout << "Desired Bragg threshold =" << DesBraggValue << std::endl;}
    TempBraggValue = DefBraggThreshold;//m_ForwardModel->getBraggThreshold();
    m_ForwardModel->setBraggThreshold(TempBraggValue); //setting the Threshold T of \beta_{T,\delta}
    //the \delta value is set in BFMultiResolutionReconstruction.cpp
  }
  else
  {
    TempBraggValue = m_ForwardModel->getBraggThreshold();
    m_ForwardModel->setBraggThreshold(TempBraggValue);
  }
#endif //Bragg correction
  if (getVeryVerbose()) {std::cout << "Bragg threshold =" << TempBraggValue << std::endl;}


  //Generate a List
  if (getVeryVerbose()) {std::cout << "Generating a list of voxels to update" << std::endl;}

  //Takes all the voxels along x-z slice and forms a list
  m_VoxelIdxList = VoxelUpdateList::GenRegularList(m_Geometry->N_z, m_Geometry->N_x);
  //Randomize the list of voxels
  m_VoxelIdxList = VoxelUpdateList::GenRandList(m_VoxelIdxList);

  if(getVerbose())
  {
    std::cout << "Initial random order list .." << std::endl;
    m_VoxelIdxList->printMaxList(std::cout);
  }

  // Create a copy of the Voxel Update List because we are going to adjust the VoxelUpdateList instance variable
  // with values for the array pointer and number of elements based on the iteration
  VoxelUpdateList::Pointer TempList = VoxelUpdateList::New(m_VoxelIdxList->numElements(), m_VoxelIdxList->getArray() );
  uint32_t listselector = 0; //For the homogenous updates this cycles through the random list one sublist at a time


  //Initialize the update magnitude arrays (for NHICD mainly) & stopping criteria
  dims[0] = m_Geometry->N_z; //height
  dims[1] = m_Geometry->N_x; //width
  dims[2] = 0;
  RealImageType::Pointer magUpdateMap = RealImageType::New(dims, "Update Map for voxel lines");
  RealImageType::Pointer filtMagUpdateMap = RealImageType::New(dims, "Filter Update Map for voxel lines");
  UInt8Image_t::Pointer magUpdateMask = UInt8Image_t::New(dims, "Update Mask for selecting voxel lines NHICD");//TODO: Remove this variable. Under the new formulation not needed
  Real_t PrevMagSum = 0;

  magUpdateMap->initializeWithZeros();
  filtMagUpdateMap->initializeWithZeros();
#if ROI
  //A mask to check the stopping criteria for the algorithm
  initializeROIMask(magUpdateMask);
#endif


  //Debugging variable to check if all voxels are visited
  dims[0] = m_Geometry->N_z;
  dims[1] = m_Geometry->N_x;
  dims[2] = 0;
  UInt8Image_t::Pointer m_VisitCount = UInt8Image_t::New(dims, "VisitCount");

  uint32_t EffIterCount = 0; //Maintains number of calls to updatevoxelroutine


  //Loop through every voxel updating it by solving a cost function

  for (int16_t reconOuterIter = 0; reconOuterIter < m_TomoInputs->NumOuterIter; reconOuterIter++)
  {
    ss.str(""); // Clear the string stream
    indent = "";
    //The first time we may need to update voxels multiple times and then on
    //just optimize over I,d,sigma,f once each outer loop;
    //Each outer loop after the first outer iter updates a subset of the voxels
    //followed by other parameters if needed
    if(reconOuterIter > 0)
    {
      m_TomoInputs->NumIter = 1;//Inner iterations
      m_ForwardModel->setBraggThreshold(TempBraggValue);
    }

    for (int16_t reconInnerIter = 0; reconInnerIter < m_TomoInputs->NumIter; reconInnerIter++)
    {
      // If at the inner most loops at the coarsest resolution donot apply Bragg
      // Only at the coarsest scale the NumIter > 1
      if(m_TomoInputs->NumIter > 1 && reconInnerIter == 0)
      {
        m_ForwardModel->setBraggThreshold(DefBraggThreshold);
      }
#ifdef DEBUG
      //Prints the ratio of the sinogram entries selected
      m_ForwardModel->printRatioSelected(m_Sinogram);
#endif //DEBUG
      ss.str("");
      ss << "Outer Iterations: " << reconOuterIter << "/" << m_TomoInputs->NumOuterIter << " Inner Iterations: " << reconInnerIter << "/" << m_TomoInputs->NumIter << std::endl;

      indent = "    ";
#ifdef DEBUG
      // This is all done PRIOR to calling what will become a method
      if (getVeryVerbose()) {std::cout << "Bragg Threshold =" << m_ForwardModel->getBraggThreshold() << std::endl;}
#endif //DEBUG

      // This could contain multiple Subloops also - voxel update
      /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

#ifdef NHICD //NHICD alternates between updating a fixed subset of voxels and a
      //list created on the fly based on the previous iterations
      // Creating a sublist of voxels for the Homogenous
      // iterations - cycle through the partial sub lists
      if(EffIterCount % 2 == 0) //Even iterations == Homogenous update
      {
        listselector %= MBIR::Constants::k_NumHomogeniousIter;// A variable to cycle through the randmoized list of voxels

        int32_t nElements = floor((Real_t)TempList->numElements() / MBIR::Constants::k_NumHomogeniousIter);

        //If the number of voxels is NOT exactly divisible by NUM_NON .. then compensate and make the last of the lists longer
        if(listselector == MBIR::Constants::k_NumHomogeniousIter - 1)
        {
          nElements += (TempList->numElements() - nElements * MBIR::Constants::k_NumHomogeniousIter);
          if(getVeryVerbose())
          {
            std::cout << "**********Adjusted number of voxel lines for last iter**************" << std::endl;
            std::cout << nElements << std::endl;
            std::cout << "**********************************" << std::endl;
          }
        }

        //Set the list array for updating voxels
        int32_t start = (uint32_t)(floor(((Real_t)TempList->numElements() / MBIR::Constants::k_NumHomogeniousIter)) * listselector);
        m_VoxelIdxList = TempList->subList(nElements, start);
        //m_VoxelIdxList.Array = &(TempList.Array[]);

        if (getVeryVerbose())
        {
          std::cout << "Partial random order list for homogenous ICD .." << std::endl;
          m_VoxelIdxList->printMaxList(std::cout);
        }

        listselector++;
        //printList(m_VoxelIdxList);
      }
#endif //NHICD

#ifdef DEBUG
      Real_t TempSum = 0;
      for (int32_t j = 0; j < m_Geometry->N_z; j++)
      {
        for (int32_t k = 0; k < m_Geometry->N_x; k++)
        {
          TempSum += magUpdateMap->getValue(j, k);
        }
      }
      if (getVeryVerbose())
      {
        std::cout << "**********************************************" << std::endl;
        std::cout << "Average mag prior to calling update voxel = " << TempSum / (m_Geometry->N_z * m_Geometry->N_x) << std::endl;
        std::cout << "**********************************************" << std::endl;
      }
#endif //debug

      status = updateVoxels(reconOuterIter, reconInnerIter, tempCol,
                            errorSino, voxelLineResponse, cost, &QGGMRF_values,
                            magUpdateMap, filtMagUpdateMap, magUpdateMask, m_VisitCount,
                            PrevMagSum,
                            EffIterCount);
#ifdef NHICD
      if(EffIterCount % MBIR::Constants::k_NumNonHomogeniousIter == 0) // At the end of half an
        //equivalent iteration compute average Magnitude of recon to test
        //stopping criteria
      {
        PrevMagSum = roiVolumeSum(magUpdateMask);
        if (getVeryVerbose()) {std::cout << " Previous Magnitude of the Recon = " << PrevMagSum << std::endl;}
      }
#else
      PrevMagSum = roiVolumeSum(magUpdateMask);
      std::cout << " Previous Magnitude of the Recon = " << PrevMagSum << std::endl;
#endif //NHICD

      //Debugging information to test if every voxel is getting touched
#ifdef NHICD
      //Debug every equivalent iteration
      if(EffIterCount % (2 * MBIR::Constants::k_NumNonHomogeniousIter) == 0 && EffIterCount > 0)
#endif //NHICD
      {
        for (int16_t j = 0; j < m_Geometry->N_z; j++)
        {
          for (int16_t k = 0; k < m_Geometry->N_x; k++)
          {
            if(m_VisitCount->getValue(j, k) == 0)
            {
              printf("Pixel (%d %d) not visited\n", j, k);
            }
          }
        }
        //Reset the visit counter once we have cycled through
        //all voxels once via the homogenous updates
        for (int16_t j = 0; j < m_Geometry->N_z; j++)
        {
          for (int16_t k = 0; k < m_Geometry->N_x; k++)
          { m_VisitCount->setValue(0, j, k); }
        }

      }
      //end of debug

      EffIterCount++; //cycles between the two types of voxel updates

      /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

      if(status == 0)
      {
        break; //stop inner loop if we have hit the threshold value for x
      }
      // Check to see if we are canceled.
      if (getCancel() == true)
      {
        setErrorCondition(-999);
        return;
      }

      // Write out the MRC File ; If NHICD only after half an equit do a write
#ifdef NHICD
      if(EffIterCount % (MBIR::Constants::k_NumNonHomogeniousIter) == 0)
#endif //NHICD
      {
        ss.str("");
        ss << m_TomoInputs->tempDir << MXADir::getSeparator() << reconOuterIter << "_" << reconInnerIter << "_" << MBIR::Defaults::ReconstructedMrcFile;
        writeMRCFile(ss.str(), cropStart, cropEnd);
        notify(ss.str(), 0, Observable::UpdateIntermediateImage);
        m_TomoInputs->tempFiles.push_back(ss.str());
      }

#ifdef COST_CALCULATE //typically run only for debugging
      /*********************Cost Calculation*************************************/
      int16_t err = calculateCost(cost, m_Sinogram, m_Geometry, errorSino, &QGGMRF_values);
      if(err < 0)
      {
        std::cout << "Cost went up after voxel update" << std::endl;
        return;
        //      break;
      }
      /**************************************************************************/
#endif //Cost calculation endif

#ifdef BRAGG_CORRECTION
      //If at the last iteration of the inner loops at coarsest resolution adjust parameters
      if(reconInnerIter == m_TomoInputs->NumIter - 1 && reconInnerIter != 0)
      {
        //The first time at the coarsest resolution at the end of
        // inner iterations set the Bragg Threshold
        TempBraggValue = DesBraggValue;//threshold;
        m_ForwardModel->setBraggThreshold(TempBraggValue);
      }

#endif //Bragg correction

    } /* ++++++++++ END Inner Iteration Loop +++++++++++++++ */


    if(0 == status && reconOuterIter >= 1) //if stopping criteria is met and
      //number of iterations is greater than 1
    {
      if (getVeryVerbose()) {std::cout << "Exiting the code because status =0" << std::endl;}
      break;
    }

    if(getVeryVerbose())
    { std::cout << " Starting nuisance parameter estimation" << std::endl; }

    if(m_TomoInputs->NumOuterIter > 1) //Dont update any parameters if we just have one outer iteration
    {
      if(m_AdvParams->JOINT_ESTIMATION)
      {
        m_ForwardModel->jointEstimation(m_Sinogram, errorSino, y_Est, cost);
        m_ForwardModel->updateSelector(m_Sinogram, errorSino);

#ifdef COST_CALCULATE //Debug info
        int16_t err = calculateCost(cost, m_Sinogram, m_Geometry, errorSino, &QGGMRF_values);
        if(err < 0)
        {
          std::cout << "Cost went up after offset update" << std::endl;
          break;
        }
#endif//cost

      }  //Joint estimation endif


      if(m_AdvParams->NOISE_ESTIMATION)
      {
        m_ForwardModel->updateWeights(m_Sinogram, errorSino);
        m_ForwardModel->updateSelector(m_Sinogram, errorSino);
#ifdef COST_CALCULATE
        //err = calculateCost(cost, Weight, errorSino);
        err = calculateCost(cost, m_Sinogram, m_Geometry, errorSino, &QGGMRF_values);
        if (err < 0 && reconOuterIter > 1)
        {
          std::cout << "Cost went up after variance update" << std::endl;
          std::cout << "Effective iterations =" << EffIterCount << std::endl;
          return;
          //break;
        }
#endif//cost

      }
      if(getVeryVerbose())
      { std::cout << " Ending nuisance parameter estimation" << std::endl; }

    }

  }/* ++++++++++ END Outer Iteration Loop +++++++++++++++ */

  indent = "";
#if DEBUG_COSTS
  cost->printCosts(std::cout);
#endif

#ifdef FORWARD_PROJECT_MODE
  int fileError = 0;
  FILE* Fp6;
  MAKE_OUTPUT_FILE(Fp6, fileError, m_TomoInputs->tempDir, MBIR::Defaults::BFForwardProjectedObjectFile);
  if (fileError == 1)
  {

  }
#endif

  if (getCancel() == true) { setErrorCondition(-999); return; }

  /* Write the Gains,Offsets and variance to an output file */
  m_ForwardModel->writeNuisanceParameters(m_Sinogram);


  //Compute final value of Ax_{final}
  Real_t temp_final = 0.0;
  for (uint16_t i_theta = 0; i_theta < m_Sinogram->N_theta; i_theta++)
  {
    for (uint16_t i_r = 0; i_r < m_Sinogram->N_r; i_r++)
    {
      for (uint16_t i_t = 0; i_t < m_Sinogram->N_t; i_t++)
      {
        temp_final = m_Sinogram->counts->getValue(i_theta, i_r, i_t) - errorSino->getValue(i_theta, i_r, i_t);
        finalSinogram->setValue(temp_final, i_theta, i_r, i_t);
      }
    }
  }

  // This is writing the "ReconstructedSinogram.bin" file
  m_ForwardModel->writeSinogramFile(m_Sinogram, finalSinogram); // Writes the sinogram to a file

  if (getCancel() == true) { setErrorCondition(-999); return; }

  // Writes ReconstructedObject.bin file for next resolution
  {
    std::stringstream ss;
    ss << m_TomoInputs->tempDir << MXADir::getSeparator() << MBIR::Defaults::ReconstructedObjectFile;
    writeReconstructionFile(ss.str());
  }
  // Write out the VTK file
  if (m_TomoInputs->vtkOutputFile.empty() == false)
  {
    writeVtkFile(m_TomoInputs->vtkOutputFile, cropStart, cropEnd);
  }
  // Write out the MRC File
  if (m_TomoInputs->mrcOutputFile.empty() == false)
  {
    writeMRCFile(m_TomoInputs->mrcOutputFile, cropStart, cropEnd);
  }

  //Write out avizo fire file
  if (m_TomoInputs->avizoOutputFile.empty() == false)
  {
    writeAvizoFile(m_TomoInputs->avizoOutputFile, cropStart, cropEnd);
  }

  //Debug : Writing out the selector array as an MRC file
  m_ForwardModel->writeSelectorMrc(m_TomoInputs->braggSelectorFile, m_Sinogram, m_Geometry, errorSino);
  if (getVerbose())
  {
    std::cout << "Final Dimensions of Object: " << std::endl;
    std::cout << "  Nx = " << m_Geometry->N_x << std::endl;
    std::cout << "  Ny = " << m_Geometry->N_y << std::endl;
    std::cout << "  Nz = " << m_Geometry->N_z << std::endl;

#ifdef NHICD
    std::cout << "Number of equivalet iterations taken =" << EffIterCount / MBIR::Constants::k_NumNonHomogeniousIter << std::endl;
#else
    std::cout << "Number of equivalet iterations taken =" << EffIterCount / MBIR::Constants::k_NumHomogeniousIter << std::endl;
#endif //NHICD
  }
  notify("Reconstruction Complete", 100, Observable::UpdateProgressValueAndMessage);
  setErrorCondition(0);

  if (getVerbose()) {std::cout << "Total Running Time for Execute: " << (EIMTOMO_getMilliSeconds() - totalTime) / 1000 << std::endl;}

  return;
}
Пример #14
0
int main(int argc, char* argv[] )
{
    srand(time(NULL));

    int verbose = 0;

    char outputFile[256];
    int doOutput = getWriteToFile( argc, argv, outputFile, 256);
    
    if (argc == 1)
    {
        showUsageAndExit();
    }

    moleculizer* pMoleculizer = createNewMoleculizerObject();

    setRateExtrapolation( pMoleculizer, 1 );
    int result = loadModelFile( pMoleculizer, argc, argv);

    switch(result)
    {
    case 0:
        printf("Model loaded successfully.\n");
        break;
    case 1:
        printf("Unknown error on load.  Aborting\n");
        return 1;
    case 2:
        printf("Document unparsable.  Aborting.\n");
        return 1;
    case 3:
        printf("Moleculizer has already loaded rules. Ignoring and continuing.\n");
        return 1;
    }

  int numIter = getNumberOfIterations(argc, argv);
  int maxSpecies = getMaxNumSpecies( argc, argv);
  int maxRxns = getMaxNumReactions( argc, argv);

  if (numIter > 0 && (maxSpecies > 0 || maxRxns > 0) )
  {
      // ANCHOR
      printf("Error, if either (max species and/or max rxns) can be set or numIters. ");
      showUsageAndExit();
      
  }

  verbose = getVerbose(argc, argv);
  
  if(numIter == -1 )
  {
      int numRxns;
      int numSpec;

      species** speciesArray;
      reaction** rxnArray;
      
      int errorCode = \
          getBoundedNetwork( pMoleculizer, maxSpecies, maxRxns, &speciesArray, &numSpec, &rxnArray, &numRxns );

      if (errorCode)
      {
          printf("Unknown erorr.  Check error messages for description.  Exiting...\n");
          exit(1);
      }
      else
      {
          numIter = 10;
          printf("Network generated to %d species and %d reactions.\n", numSpec, numRxns);
      }
  }
  else
  {
      int iter = 0;

      for( iter = 0; iter != numIter; ++iter)
      {
          species** theSpecies;
          int numSpecies = 0;

          getAllExteriorSpecies( pMoleculizer, &theSpecies, &numSpecies);

          if (numSpecies == 0)
          {
              printf("Entire network has been generated on the %dth iteration.\n", iter);
              freeSpeciesArray( theSpecies, numSpecies);
              break;
          }
          
          /* Get a random number in the range [0, numSpecies) */
          int speciesNumber = rand() % numSpecies;

          printf("Iteration %d: Expanding %s\n", iter + 1, theSpecies[speciesNumber]->name);
          incrementSpecies( pMoleculizer, theSpecies[speciesNumber]->name);

          freeSpeciesArray( theSpecies, numSpecies);
      }

  }

  if (numIter == -1)
  {
      printf("Expanded entire network.\n");
  }
  else
  {
      printf("Expanded %d iterations.", numIter);
  }

  printf("\n##########################################\n");

  printf("There are %d species and %d reactions.\n", 
         getNumberOfSpecies(pMoleculizer),
         getNumberOfReactions(pMoleculizer) );


  if ( verbose )
  {
      showAllSpecies( pMoleculizer );
      showAllReactions( pMoleculizer);
  }

  if (doOutput)
  {
      writeDotFile(pMoleculizer, outputFile);
  }
           
  freeMoleculizerObject( pMoleculizer );
  return 0;

}