//#################### 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");
}
Beispiel #2
0
///////////////////////////////////////////////////////////////////////////////
/// \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();
}
Beispiel #3
0
///////////////////////////////////////////////////////////////////////////////
/// \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());
}