// ----------------------------------------------------------------------------- // 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; }
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); } }
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; }
// 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; }
// 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; }
// 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; } } }
// ----------------------------------------------------------------------------- // 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; }
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; }