//#################### LOADING METHODS #################### DICOMVolumeChoice VolumeChoiceSection::load(std::istream& is) try { LineIO::read_checked_line(is, "VolumeChoice"); LineIO::read_checked_line(is, "{"); std::string dicomdirFilename, patientHandle, studyHandle, seriesHandle; int minX, minY, minZ, maxX, maxY, maxZ; WindowSettings windowSettings; std::string line; for(int count=0; ; ++count) { LineIO::read_trimmed_line(is, line, "volume choice property"); if(line == "}") { // Note: This won't detect duplicate properties. const int PROPERTIES_NEEDED = 11; if(count == PROPERTIES_NEEDED) break; else throw Exception("Incorrect number of volume choice properties"); } // Parse the field. std::string name, value; boost::tie(name, value) = FieldIO::parse_field(line); // Set the appropriate property. if(name == "DICOMDIR") dicomdirFilename = value; else if(name == "MaxX") maxX = lexical_cast<int>(value); else if(name == "MaxY") maxY = lexical_cast<int>(value); else if(name == "MaxZ") maxZ = lexical_cast<int>(value); else if(name == "MinX") minX = lexical_cast<int>(value); else if(name == "MinY") minY = lexical_cast<int>(value); else if(name == "MinZ") minZ = lexical_cast<int>(value); else if(name == "Patient") patientHandle = value; else if(name == "Series") seriesHandle = value; else if(name == "Study") studyHandle = value; else if(name == "Window") { size_t space = value.find(' '); double centre = lexical_cast<double>(value.substr(0, space)); double width = lexical_cast<double>(value.substr(space+1)); windowSettings = WindowSettings(centre, width); } else throw Exception("Unknown volume choice property: " + name); } return DICOMVolumeChoice(dicomdirFilename, patientHandle, studyHandle, seriesHandle, minX, minY, minZ, maxX, maxY, maxZ, windowSettings); } catch(bad_lexical_cast&) { throw Exception("One of the volume choice properties was of the wrong type"); }
/////////////////////////////////////////////////////////////////////////////// /// \brief Deletes the most recent history index of the specified /// WindowSettings object. /// /// \param id The AssetId defining the WindowSettings stack to revert. /// \return The next most recent history index for the WindowSettings object. /// If there is a problem deleting the most recent window settings or /// if there is no next most recent history index, a /// default-constructed WindowSettings object will be returned. /// /// \ingroup loading WindowSettings revertWindowSettings(const AssetId& id) { try { std::shared_ptr<bed::Bed> bed = bed::openWritable(id.bed); if (!bed) throw std::runtime_error("Could not open bed for writing!"); bed::Db& db = bed->getDb(); if (db.getInt(BE_WND_WINDOW_SETTINGS_SQL_TABLE_EXISTS, 0) == 0) throw std::runtime_error("WindowSettings table does not exist!"); bed::Transaction transaction(db, bed::Transaction::Immediate); int history_index = 0; bed::Stmt latest(db, BE_WND_WINDOW_SETTINGS_SQLID_LATEST_INDEX); latest.bind(1, id.asset.value()); if (latest.step()) history_index = latest.getInt(0); bed::Stmt remove(db, BE_WND_WINDOW_SETTINGS_SQLID_REVERT); remove.bind(1, id.asset.value()); remove.bind(2, history_index); remove.step(); transaction.commit(); return loadWindowSettings(*bed, id.asset); } catch (const bed::Db::error& err) { BE_LOG(VWarning) << "Database error while reverting window settings!" << BE_LOG_NL << " Bed: " << id.bed << BE_LOG_NL << "WindowSettings ID: " << id.asset << BE_LOG_NL << " Exception: " << err.what() << BE_LOG_NL << " SQL: " << err.sql() << BE_LOG_END; } catch (const std::runtime_error& err) { BE_LOG(VWarning) << "Exception while reverting window settings!" << BE_LOG_NL << " Bed: " << id.bed << BE_LOG_NL << "WindowSettings ID: " << id.asset << BE_LOG_NL << " Exception: " << err.what() << BE_LOG_END; } return WindowSettings(); }
/////////////////////////////////////////////////////////////////////////////// /// \brief Load a set of WindowSettings from a bed. /// /// \details Each WindowSettings Id represents a stack of current and previous /// values. This allows the user to revert to previous settings if /// new settings are tried and not supported. /// /// \param bed The bed to load from. /// \param id The Id of the WindowSettings stack to load. /// /// \ingroup loading WindowSettings loadWindowSettings(bed::Bed& bed, const Id& id) { try { bed::StmtCache& cache = bed.getStmtCache(); bed::CachedStmt& stmt = cache.hold(Id(BE_WND_WINDOW_SETTINGS_SQLID_LOAD), BE_WND_WINDOW_SETTINGS_SQL_LOAD); stmt.bind(1, id.value()); if (stmt.step()) { WindowSettings ws; ws.id.bed = bed.getId(); ws.id.asset = id; ws.mode = static_cast<WindowSettings::Mode>(stmt.getInt(0)); ws.system_positioned = stmt.getBool(1); ws.save_position_on_close = stmt.getBool(2); ws.position.x = stmt.getInt(3); ws.position.y = stmt.getInt(4); ws.size.x = stmt.getInt(5); ws.size.y = stmt.getInt(6); ws.monitor_index = stmt.getInt(7); ws.refresh_rate = stmt.getUInt(8); ws.v_sync = static_cast<WindowSettings::VSyncMode>(stmt.getInt(9)); ws.msaa_level = stmt.getUInt(10); ws.red_bits = stmt.getUInt(11); ws.green_bits = stmt.getUInt(12); ws.blue_bits = stmt.getUInt(13); ws.alpha_bits = stmt.getUInt(14); ws.depth_bits = stmt.getUInt(15); ws.stencil_bits = stmt.getUInt(16); ws.srgb_capable = stmt.getBool(17); ws.use_custom_gamma = stmt.getBool(18); ws.custom_gamma = float(stmt.getDouble(19)); ws.context_version_major = stmt.getUInt(20); ws.context_version_minor = stmt.getUInt(21); ws.forward_compatible_context = stmt.getBool(22); ws.debug_context = stmt.getBool(23); ws.context_profile_type = static_cast<WindowSettings::ContextProfileType>(stmt.getInt(24)); return ws; } else throw std::runtime_error("WindowSettings record not found!"); } catch (const bed::Db::error& err) { BE_LOG(VWarning) << "Database error while loading window settings!" << BE_LOG_NL << " Bed: " << bed.getId() << BE_LOG_NL << "WindowSettings ID: " << id << BE_LOG_NL << " Exception: " << err.what() << BE_LOG_NL << " SQL: " << err.sql() << BE_LOG_END; } catch (const std::runtime_error& err) { BE_LOG(VWarning) << "Exception while loading window settings!" << BE_LOG_NL << " Bed: " << bed.getId() << BE_LOG_NL << "WindowSettings ID: " << id << BE_LOG_NL << " Exception: " << err.what() << BE_LOG_END; } return WindowSettings(); }
//#################### PRIVATE METHODS #################### void DICOMVolumeLoader::execute_impl() try { typedef itk::GDCMImageIO ImageIO; typedef itk::Image<int,2> Image2D; typedef itk::Image<int,3> Image3D; typedef itk::JoinSeriesImageFilter<Image2D,Image3D> Joiner; typedef itk::ImageFileReader<Image2D> Reader; typedef itk::RegionOfInterestImageFilter<Image2D,Image2D> RegionExtractor; // Set up the desired region for each of the slices. Image2D::RegionType region; itk::Index<2> index = {{m_volumeChoice.minX, m_volumeChoice.minY}}; itk::Size<2> size = {{m_volumeChoice.maxX + 1 - m_volumeChoice.minX, m_volumeChoice.maxY + 1 - m_volumeChoice.minY}}; region.SetIndex(index); region.SetSize(size); std::vector<std::string> imageFilenames = m_dicomdir->image_filenames(m_volumeChoice.patientKey, m_volumeChoice.studyKey, m_volumeChoice.seriesKey); std::vector<Image2D::Pointer> images(imageFilenames.size()); for(int i=m_volumeChoice.minZ; i<=m_volumeChoice.maxZ; ++i) { std::string imageFilename = m_volumeChoice.filePrefix + imageFilenames[i]; if(!is_aborted()) { set_progress(i - m_volumeChoice.minZ); set_status("Loading image " + imageFilename + "..."); } else return; // Load the image. Reader::Pointer reader = Reader::New(); reader->SetFileName(imageFilename); ImageIO::Pointer gdcmImageIO = ImageIO::New(); reader->SetImageIO(gdcmImageIO); reader->Update(); // Extract the relevant sub-region. RegionExtractor::Pointer extractor = RegionExtractor::New(); extractor->SetInput(reader->GetOutput()); extractor->SetRegionOfInterest(region); extractor->Update(); // Store the image. images[i] = extractor->GetOutput(); images[i]->SetMetaDataDictionary(reader->GetMetaDataDictionary()); } // Get the window centre and width if they haven't been explicitly specified by the user. if(m_volumeChoice.windowSettings.unspecified()) { std::string windowCentreStr = read_header_field(images[m_volumeChoice.minZ], "0028|1050"); std::string windowWidthStr = read_header_field(images[m_volumeChoice.minZ], "0028|1051"); std::string validChars = "-0123456789"; windowCentreStr = windowCentreStr.substr(0, windowCentreStr.find_first_not_of(validChars)); windowWidthStr = windowWidthStr.substr(0, windowWidthStr.find_first_not_of(validChars)); double windowCentre = lexical_cast<double>(windowCentreStr); double windowWidth = lexical_cast<double>(windowWidthStr); m_volumeChoice.windowSettings = WindowSettings(windowCentre, windowWidth); } // Make the images into a volume. Joiner::Pointer joiner = Joiner::New(); double minSliceLocation = 0; try { minSliceLocation = lexical_cast<double>(read_header_field(images[m_volumeChoice.minZ], "0020|1041")); } catch(bad_lexical_cast&) { throw Exception("The SliceLocation value for the slice was not of the appropriate type"); } joiner->SetOrigin(minSliceLocation); double sliceThickness = 0; if(m_volumeChoice.minZ + 1 <= m_volumeChoice.maxZ) { try { double nextSliceLocation = lexical_cast<double>(read_header_field(images[m_volumeChoice.minZ+1], "0020|1041")); sliceThickness = fabs(nextSliceLocation - minSliceLocation); } catch(bad_lexical_cast&) {} } if(sliceThickness == 0) { try { sliceThickness = lexical_cast<double>(read_header_field(images[m_volumeChoice.minZ], "0018|0050")); } catch(bad_lexical_cast&) { throw Exception("The SliceThickness value for the slice was not of the appropriate type"); } } joiner->SetSpacing(sliceThickness); for(int i=m_volumeChoice.minZ; i<=m_volumeChoice.maxZ; ++i) joiner->PushBackInput(images[i]); joiner->Update(); Image3D::Pointer volumeImage = joiner->GetOutput(); // Determine the modality of the images. DICOMVolume::Modality modality = DICOMVolume::UNSUPPORTED_MODALITY; std::string modalityString = read_header_field(images[m_volumeChoice.minZ], "0008|0060"); if(modalityString == "CT") modality = DICOMVolume::CT; else if(modalityString == "MR") modality = DICOMVolume::MR; if(modality == DICOMVolume::UNSUPPORTED_MODALITY) { throw Exception("Cannot currently handle modalities other than CT and MR - sorry!"); } m_volume.reset(new DICOMVolume(volumeImage, modality)); } catch(std::exception& e) { abort(); set_status(e.what()); }