Exemple #1
0
        public void RleTest()
        {
            DicomFile file = new DicomFile("RleCodecTest.dcm");

            SetupMR(file.DataSet);

            SetupMetaInfo(file);

            RleTest(file);

            file = new DicomFile("MultiframeRleCodecTest.dcm");

            SetupMultiframeXA(file.DataSet, 511, 511, 5);

            RleTest(file);


            file = new DicomFile("MultiframeRleCodecTest.dcm");

            SetupMultiframeXA(file.DataSet, 63, 63, 1);

            RleTest(file);

            file = new DicomFile("MultiframeRleCodecTest.dcm");

            SetupMultiframeXA(file.DataSet, 1024, 1024, 3);

            RleTest(file);

            file = new DicomFile("MultiframeRleCodecTest.dcm");

            SetupMultiframeXA(file.DataSet, 512, 512, 2);

            RleTest(file);
        }
			public void Validate(DicomFile dicomFile)
			{
				DicomAttributeCollection sopInstanceDataset = dicomFile.DataSet;
				DicomAttributeCollection metaInfo = dicomFile.MetaInfo;

				DicomAttribute attribute = metaInfo[DicomTags.MediaStorageSopClassUid];
				// we want to skip Media Storage Directory Storage (DICOMDIR directories)
				if ("1.2.840.10008.1.3.10" == attribute.ToString())
					throw new DataStoreException("Cannot process dicom directory files.");

				DicomValidator.ValidateStudyInstanceUID(sopInstanceDataset[DicomTags.StudyInstanceUid]);
				DicomValidator.ValidateSeriesInstanceUID(sopInstanceDataset[DicomTags.SeriesInstanceUid]);
				DicomValidator.ValidateSOPInstanceUID(sopInstanceDataset[DicomTags.SopInstanceUid]);
				DicomValidator.ValidateTransferSyntaxUID(metaInfo[DicomTags.TransferSyntaxUid]);
				
				if (dicomFile.SopClass == null)
					throw new DataStoreException("The sop class must not be empty.");

				DicomValidator.ValidateSopClassUid(dicomFile.SopClass.Uid);

				Study study = new Study();
				study.Initialize(dicomFile);

				_validator.ValidatePersistentObject(study);
			}
Exemple #3
0
        public void OpenFile(DicomFile file)
        {
            try
            {
                lvDicom.BeginUpdate();

                Reset();

                _file = file;

                new DicomDatasetWalker(_file.FileMetaInfo).Walk(new DumpWalker(this));
                new DicomDatasetWalker(_file.Dataset).Walk(new DumpWalker(this));

                //if (_file.Dataset.Contains(DicomTag.PixelData))
                    menuItemView.Enabled = true;
                menuItemSyntax.Enabled = true;
                menuItemSave.Enabled = true;

                menuItemJpegLossy.Enabled = _file.Dataset.Get<int>(DicomTag.BitsStored, 0, 16) <= 12;
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    this,
                    "Exception while loading DICOM file: " + ex.Message,
                    "Error loading DICOM file",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
            finally
            {
                lvDicom.EndUpdate();
            }
        }
Exemple #4
0
 /// <summary>
 /// Initializes DICOM C-Store request to be sent to SCP.
 /// </summary>
 /// <param name="file">DICOM file to be sent</param>
 /// <param name="priority">Priority of request</param>
 public DicomCStoreRequest(DicomFile file, DicomPriority priority = DicomPriority.Medium)
     : base(DicomCommandField.CStoreRequest, file.Dataset.Get<DicomUID>(DicomTag.SOPClassUID), priority)
 {
     File = file;
     Dataset = file.Dataset;
     SOPInstanceUID = File.Dataset.Get<DicomUID>(DicomTag.SOPInstanceUID);
 }
Exemple #5
0
        public void WriteOptionsTest(DicomFile sourceFile, DicomWriteOptions options)
        {
            bool result = sourceFile.Save(options);

            Assert.AreEqual(result, true);

            DicomFile newFile = new DicomFile(sourceFile.Filename);

            DicomReadOptions readOptions = DicomReadOptions.Default;
            newFile.Load(readOptions);

            Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), true);

            // update a tag, and make sure it shows they're different
            newFile.DataSet[DicomTags.PatientsName].Values = "NewPatient^First";
            Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), false);

            // Now update the original file with the name, and they should be the same again
            sourceFile.DataSet[DicomTags.PatientsName].Values = "NewPatient^First";
            Assert.AreEqual(sourceFile.DataSet.Equals(newFile.DataSet), true);

            // Return the original string value.
            sourceFile.DataSet[DicomTags.PatientsName].SetStringValue("Patient^Test");

        }
        public void TestFile()
        {
            string filename = "OutOfRange.dcm";

            DicomFile file = new DicomFile(filename, new DicomAttributeCollection(), new DicomAttributeCollection());
            SetupMR(file.DataSet);
            SetupMetaInfo(file);

            DicomTag tag = new DicomTag(0x00030010, "Test", "TestBad", DicomVr.LOvr, false, 1, 1, false);

            file.DataSet[tag].SetStringValue("Test");

            file.Save(filename);

            file = new DicomFile(filename);

            file.DataSet.IgnoreOutOfRangeTags = true;

            file.Load();

            Assert.IsNotNull(file.DataSet.GetAttribute(tag));

            file = new DicomFile(filename);

            file.DataSet.IgnoreOutOfRangeTags = false;

            try
            {
                file.Load();
                Assert.Fail("file.Load failed");
            }
            catch (DicomException)
            {
            }
        }
		protected override void OnExecute(CommandProcessor theProcessor)
		{
		    if (!File.Exists(_path))
			{
				Platform.Log(LogLevel.Error, "Unexpected error finding file to add to XML {0}", _path);
				throw new ApplicationException("Unexpected error finding file to add to XML {0}" + _path);
			}

			var finfo = new FileInfo(_path);
			long fileSize = finfo.Length;

			var dicomFile = new DicomFile(_path);
			dicomFile.Load(DicomReadOptions.StorePixelDataReferences | DicomReadOptions.Default);

		    _sopInstanceUid = dicomFile.DataSet[DicomTags.SopInstanceUid];
		    _seriesInstanceUid = dicomFile.DataSet[DicomTags.SeriesInstanceUid];

			// Setup the insert parameters
			if (false == _stream.AddFile(dicomFile, fileSize))
			{
				Platform.Log(LogLevel.Error, "Unexpected error adding SOP to XML Study Descriptor for file {0}",
				             _path);
				throw new ApplicationException("Unexpected error adding SOP to XML Study Descriptor for SOP: " +
				                               dicomFile.MediaStorageSopInstanceUid);
			}
		}
			public void Validate(DicomFile dicomFile)
			{
				const string metaInfoErrorMessageFormat = "Invalid DICOM File Meta Info ({0})";

				DicomAttributeCollection sopInstanceDataset = dicomFile.DataSet;
				DicomAttributeCollection metaInfo = dicomFile.MetaInfo;

				DicomAttribute attribute = metaInfo[DicomTags.MediaStorageSopClassUid];
				// we want to skip Media Storage Directory Storage (DICOMDIR directories)
				if ("1.2.840.10008.1.3.10" == attribute.ToString())
					throw new DataStoreException("Cannot process DICOM directory files.");

				DicomValidator.ValidateStudyInstanceUID(sopInstanceDataset[DicomTags.StudyInstanceUid]);
				DicomValidator.ValidateSeriesInstanceUID(sopInstanceDataset[DicomTags.SeriesInstanceUid]);
				DicomValidator.ValidateSOPInstanceUID(sopInstanceDataset[DicomTags.SopInstanceUid]);
				DicomValidator.ValidateTransferSyntaxUID(metaInfo[DicomTags.TransferSyntaxUid]);

				if (dicomFile.SopClass == null)
					throw new DataStoreException(string.Format(metaInfoErrorMessageFormat, "SOP Class UID is missing"));

				try
				{
					DicomValidator.ValidateSopClassUid(dicomFile.SopClass.Uid);
				}
				catch (DicomDataException ex)
				{
					throw new DataStoreException(string.Format(metaInfoErrorMessageFormat, "SOP Class UID is missing"), ex);
				}

				Study study = new Study();
				study.Initialize(dicomFile);

				_validator.ValidatePersistentObject(study);
			}
Exemple #9
0
	    public static void LosslessImageTest(TransferSyntax syntax, DicomFile theFile)
		{
			if (File.Exists(theFile.Filename))
				File.Delete(theFile.Filename);

			DicomFile saveCopy = new DicomFile(theFile.Filename, theFile.MetaInfo.Copy(), theFile.DataSet.Copy());

			theFile.ChangeTransferSyntax(syntax);

			theFile.Save(DicomWriteOptions.ExplicitLengthSequence);

			DicomFile newFile = new DicomFile(theFile.Filename);

			newFile.Load(DicomReadOptions.Default);

			newFile.ChangeTransferSyntax(saveCopy.TransferSyntax);

			List<DicomAttributeComparisonResult> list = new List<DicomAttributeComparisonResult>();
			bool result = newFile.DataSet.Equals(saveCopy.DataSet, ref list);

			StringBuilder sb = new StringBuilder();
			foreach (DicomAttributeComparisonResult compareResult in list)
				sb.AppendFormat("Comparison Failure: {0}, ", compareResult.Details);

			Assert.IsTrue(result,sb.ToString());
		}
Exemple #10
0
 public static DicomFile Clone(this DicomFile original)
 {
     var df = new DicomFile();
     df.FileMetaInfo.Add(original.FileMetaInfo);
     df.Dataset.Add(original.Dataset);
     df.Dataset.InternalTransferSyntax = original.Dataset.InternalTransferSyntax;
     return df;
 }
		public void ConstructorTests()
		{
			DicomFile file = new DicomFile(null);

			file = new DicomFile("filename");

			file = new DicomFile(null, new DicomAttributeCollection(), new DicomAttributeCollection());
		}
Exemple #12
0
 /// <summary>
 /// Initializes DICOM C-Store request to be sent to SCP.
 /// </summary>
 /// <param name="file">DICOM file to be sent</param>
 /// <param name="priority">Priority of request</param>
 public DicomCStoreRequest(DicomFile file, DicomPriority priority = DicomPriority.Medium)
     : base(DicomCommandField.CStoreRequest, file.FileMetaInfo.MediaStorageSOPClassUID, priority)
 {
     File = file;
     Dataset = file.Dataset;
     AffectedSOPClassUID = File.FileMetaInfo.MediaStorageSOPClassUID;
     SOPInstanceUID = File.FileMetaInfo.MediaStorageSOPInstanceUID;
 }
		/// <summary>
		/// Constructs a new <see cref="SopInstanceNode"/> using the given <see cref="DicomFile"/> as a template.
		/// </summary>
		/// <param name="sourceDicomFile">The <see cref="DicomFile"/> from which to initialize this node.</param>
		public SopInstanceNode(DicomMessageBase sourceDicomFile)
		{
			_dicomFile = new DicomFile("", sourceDicomFile.MetaInfo.Copy(), sourceDicomFile.DataSet.Copy());

			_instanceUid = sourceDicomFile.DataSet[DicomTags.SopInstanceUid].GetString(0, "");
			if (_instanceUid == "")
				_instanceUid = StudyBuilder.NewUid();
		}
Exemple #14
0
 /// <summary>
 /// Transcode a <see cref="DicomFile"/> from <see cref="IDicomTranscoder.InputSyntax"/> to <see cref="IDicomTranscoder.OutputSyntax"/>.
 /// </summary>
 /// <param name="file">DICOM file.</param>
 /// <returns>New, transcoded, DICOM file.</returns>
 public DicomFile Transcode(DicomFile file)
 {
     var f = new DicomFile();
     f.FileMetaInfo.Add(file.FileMetaInfo);
     f.FileMetaInfo.TransferSyntax = OutputSyntax;
     f.Dataset.InternalTransferSyntax = OutputSyntax;
     f.Dataset.Add(Transcode(file.Dataset));
     return f;
 }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="file">The file to save.</param>
        /// <param name="failOnExists">If the file already exists, the file will save.</param>
        /// <param name="path">The path for the file.</param>
        public SaveDicomFileCommand(string path, DicomFile file, bool failOnExists)
            : base("Save DICOM File", true)
        {
            Platform.CheckForNullReference(file, "Dicom File object");
            Platform.CheckForNullReference(path, "Path to save file");

            _path = path;
            _file = file;
            _failOnExists = failOnExists;
        }
Exemple #16
0
        private void ButtonLoadFile_Click(object sender, EventArgs e)
        {
            openFileDialog.DefaultExt = "dcm";
            openFileDialog.ShowDialog();

            DicomFile dicomFile = new DicomFile(openFileDialog.FileName);

            dicomFile.Load(DicomReadOptions.Default);

            _theStream.AddFile(dicomFile);
        }
        public void SetupMetaInfo(DicomFile theFile)
        {
            DicomAttributeCollection theSet = theFile.MetaInfo;

            theSet[DicomTags.MediaStorageSopClassUid].SetStringValue(theFile.DataSet[DicomTags.SopClassUid].GetString(0, ""));
            theSet[DicomTags.MediaStorageSopInstanceUid].SetStringValue(theFile.DataSet[DicomTags.SopInstanceUid].GetString(0, ""));
            theFile.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian;

            theSet[DicomTags.ImplementationClassUid].SetStringValue("1.1.1.1.1.11.1");
            theSet[DicomTags.ImplementationVersionName].SetStringValue("CC DICOM 1.0");
        }
		private void SetupImageWithIconSequence(DicomFile file, bool explicitVr)
		{
			DicomAttributeCollection dataSet = file.DataSet;

			SetupSecondaryCapture(dataSet);
			CreateIconImageSequence(dataSet);

			SetupMetaInfo(file);

			file.TransferSyntax = explicitVr ? TransferSyntax.ExplicitVrLittleEndian : TransferSyntax.ImplicitVrLittleEndian;
		}
Exemple #19
0
 public void Load()
 {
     _dicomFile = new DicomFile(_sourceFilename);
     try
     {
         _dicomFile.Load();
     }
     catch (Exception e)
     {
         Platform.Log(LogLevel.Error, e, "Unexpected exception loading DICOM file: {0}", _sourceFilename);
     }
 }
Exemple #20
0
		public void Load()
		{
			_dicomFile = new DicomFile(_sourceFilename);
			try
			{
				_dicomFile.Load();
			}
			catch (Exception e)
			{
				Logger.LogErrorException(e, "Unexpected exception loading DICOM file: {0}", _sourceFilename);
			}
		}
		public void TestIgnoreOutOfRangeTags()
		{
			DicomFile file = new DicomFile();
			DicomAttributeCollection collection = file.DataSet;

			SetupMR(collection);
			collection.IgnoreOutOfRangeTags = true;

			DicomTag tag = new DicomTag(0x00030010, "Test", "TestBad", DicomVr.STvr, false, 1, 1, false);

			Assert.IsNotNull(collection.GetAttribute(tag));
			Assert.IsNotNull(collection[tag]);
	
			try
			{
				DicomAttribute attrib = collection[tag.TagValue];
				Assert.Fail("DicomAttributeCollection.GetAttribute failed");
			}
			catch (DicomException)
			{
			}

			collection.IgnoreOutOfRangeTags = false;

			try
			{
				collection.GetAttribute(tag);
				Assert.Fail("DicomAttributeCollection.GetAttribute failed");
			}
			catch (DicomException)
			{
			}

			try
			{
				DicomAttribute attrib = collection[tag];
				Assert.Fail("DicomAttributeCollection.GetAttribute failed");
			}
			catch (DicomException)
			{
			}

			try
			{
				DicomAttribute attrib = collection[tag.TagValue];
				Assert.Fail("DicomAttributeCollection.GetAttribute failed");
			}
			catch (DicomException)
			{
			}
		}
Exemple #22
0
        public void MultiframeCreateFileTest()
        {
            DicomFile file = new DicomFile("MultiframeCreateFileTest.dcm");

            DicomAttributeCollection dataSet = file.DataSet;

            SetupMultiframeXA(dataSet, 511, 511, 5);

            SetupMetaInfo(file);

            // Little Endian Tests
            file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian;

            DicomWriteOptions writeOptions = DicomWriteOptions.Default;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.ExplicitLengthSequence;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.ExplicitLengthSequenceItem;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.ExplicitLengthSequence | DicomWriteOptions.ExplicitLengthSequenceItem;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.None;
            WriteOptionsTest(file, writeOptions);

            // Big Endian Tests
            file.Filename = "MultiframeBigEndianCreateFileTest.dcm";
            file.TransferSyntax = TransferSyntax.ExplicitVrBigEndian;

            writeOptions = DicomWriteOptions.Default;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.ExplicitLengthSequence;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.ExplicitLengthSequenceItem;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.ExplicitLengthSequence | DicomWriteOptions.ExplicitLengthSequenceItem;
            WriteOptionsTest(file, writeOptions);

            writeOptions = DicomWriteOptions.None;
            WriteOptionsTest(file, writeOptions);

        }
		private DicomFile CreateTestFile()
		{
			DicomFile file = new DicomFile();

			SetupMultiframeXA(file.DataSet, 128, 128, 2);

			file.DataSet[DicomTags.PatientsName].SetStringValue("Doe^Jon^Mr");

			//NOTE: this is not intended to be a realistic dataset; we're just testing the anonymizer.

			//set fixed values for dates (SetupMultiframeXA uses today's date)
			file.DataSet[DicomTags.InstanceCreationDate].SetStringValue("20080219");
			file.DataSet[DicomTags.InstanceCreationTime].SetStringValue("143600");
			file.DataSet[DicomTags.StudyDate].SetStringValue("20080219");
			file.DataSet[DicomTags.StudyTime].SetStringValue("143600");
			file.DataSet[DicomTags.SeriesDate].SetStringValue("20080219");
			file.DataSet[DicomTags.SeriesTime].SetStringValue("143700");
			
			//add a couple of the dates that get adjusted.
			file.DataSet[DicomTags.ContentDate].SetStringValue("20080219");
			file.DataSet[DicomTags.AcquisitionDatetime].SetStringValue("20080219100406");

			//add a couple of the Uids that get remapped (ones that aren't already in the data set).
			file.DataSet[DicomTags.ReferencedSopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
			file.DataSet[DicomTags.Uid].SetStringValue(DicomUid.GenerateUid().UID);

			//add a couple of the tags that get removed.
			file.DataSet[DicomTags.InstanceCreatorUid].SetStringValue(DicomUid.GenerateUid().UID);
			file.DataSet[DicomTags.StorageMediaFileSetUid].SetStringValue(DicomUid.GenerateUid().UID);

			//add a couple of the tags that get nulled.
			file.DataSet[DicomTags.StationName].SetStringValue("STATION1");
			file.DataSet[DicomTags.PatientComments].SetStringValue("Claustrophobic");

			//sequence
			DicomSequenceItem item = new DicomSequenceItem();
			file.DataSet[DicomTags.ReferencedImageSequence].AddSequenceItem(item);
			item[DicomTags.ReferencedSopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
			item[DicomTags.ReferencedFrameOfReferenceUid].SetStringValue(DicomUid.GenerateUid().UID);
			//will be removed
			item[DicomTags.InstanceCreatorUid].SetStringValue(DicomUid.GenerateUid().UID);

			//nested sequence; will be removed
			item[DicomTags.RequestAttributesSequence].AddSequenceItem(item = new DicomSequenceItem());
			item[DicomTags.RequestedProcedureId].SetStringValue("XA123");
			item[DicomTags.ScheduledProcedureStepId].SetStringValue("XA1234");
			return file;
		}
			public void UpdateSopInstance(DicomFile file)
			{
				GetValidator().Validate(file);

				string studyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid];
				Study study = GetStudy(studyInstanceUid);

				bool newStudy = false;
				bool studyDirty = false;

				if (study == null)
				{
					study = new Study();
					study.StoreTime = DateTime.Now;

					string studyStoragePath = GetStudyStorageLocator().GetStudyStorageDirectory(studyInstanceUid);
					if (String.IsNullOrEmpty(studyStoragePath))
						throw new DataStoreException("The study storage path is empty.");

					studyStoragePath = Path.GetFullPath(studyStoragePath);
					if (!Directory.Exists(studyStoragePath))
						throw new DirectoryNotFoundException(String.Format("The specified directory does not exist ({0}).", studyStoragePath));

					UriBuilder uriBuilder = new UriBuilder();
					uriBuilder.Scheme = "file";
					uriBuilder.Path = Path.Combine(studyStoragePath, "studyXml.xml");

					study.StudyXmlUri = new DicomUri(uriBuilder.Uri);
					newStudy = true;
				}

				EventHandler studyDirtyDelegate = delegate { studyDirty = true; };
				study.Changed += studyDirtyDelegate;

				try
				{
					study.Update(file);
				}
				finally
				{
					study.Changed -= studyDirtyDelegate;
				}

				if (studyDirty || newStudy)
					_studiesToUpdateInDatastore[study.StudyInstanceUid] = study;

				_studiesToUpdateInXml[study.StudyInstanceUid] = study;
			}
		/// <summary>
		/// Creates an in-memory DICOM image
		/// </summary>
		/// <returns></returns>
		internal static DicomFile CreateDicomImage(int rows = 20, int columns = 30, bool bitsAllocated16 = true, bool signed = false, int numberOfFrames = 1, Endian endian = Endian.Little, bool useOB = false)
		{
			var sopClassUid = bitsAllocated16 ? SopClass.MultiFrameGrayscaleWordSecondaryCaptureImageStorageUid : SopClass.MultiFrameGrayscaleByteSecondaryCaptureImageStorageUid;
			var sopInstanceUid = DicomUid.GenerateUid().UID;

			var dcf = new DicomFile();
			dcf.MediaStorageSopClassUid = sopClassUid;
			dcf.MediaStorageSopInstanceUid = sopInstanceUid;
			dcf.TransferSyntax = endian == Endian.Little ? TransferSyntax.ExplicitVrLittleEndian : TransferSyntax.ExplicitVrBigEndian;
			dcf.DataSet[DicomTags.PatientId].SetStringValue("TEST");
			dcf.DataSet[DicomTags.PatientsName].SetStringValue("TEST");
			dcf.DataSet[DicomTags.StudyInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
			dcf.DataSet[DicomTags.StudyId].SetStringValue("TEST");
			dcf.DataSet[DicomTags.StudyDescription].SetStringValue("TEST");
			dcf.DataSet[DicomTags.SeriesInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
			dcf.DataSet[DicomTags.SeriesNumber].SetInt32(0, 1);
			dcf.DataSet[DicomTags.SeriesDescription].SetStringValue("TEST");
			dcf.DataSet[DicomTags.SopClassUid].SetStringValue(sopClassUid);
			dcf.DataSet[DicomTags.SopInstanceUid].SetStringValue(sopInstanceUid);
			dcf.DataSet[DicomTags.InstanceNumber].SetInt32(0, 1);

			var frameSize = rows*columns*(bitsAllocated16 ? 2 : 1);
			var data = new byte[numberOfFrames*frameSize];
			for (var n = 0; n < numberOfFrames; ++n)
			{
				var value = (byte) (0xFF & (n + 0x80));

				for (var k = 0; k < frameSize; ++k)
					data[n*frameSize + k] = (byte) ((value + k)%255);
			}

			var pixelDataTag = DicomTagDictionary.GetDicomTag(DicomTags.PixelData);
			pixelDataTag = new DicomTag(pixelDataTag.TagValue, pixelDataTag.Name, pixelDataTag.VariableName, useOB ? DicomVr.OBvr : DicomVr.OWvr, pixelDataTag.MultiVR, pixelDataTag.VMLow, pixelDataTag.VMHigh, pixelDataTag.Retired);

			dcf.DataSet[DicomTags.PhotometricInterpretation].SetStringValue(PhotometricInterpretation.Monochrome2.Code);
			dcf.DataSet[DicomTags.SamplesPerPixel].SetInt32(0, 1);
			dcf.DataSet[DicomTags.PixelRepresentation].SetInt32(0, signed ? 1 : 0);
			dcf.DataSet[DicomTags.BitsAllocated].SetInt32(0, bitsAllocated16 ? 16 : 8);
			dcf.DataSet[DicomTags.BitsStored].SetInt32(0, bitsAllocated16 ? 16 : 8);
			dcf.DataSet[DicomTags.HighBit].SetInt32(0, bitsAllocated16 ? 15 : 7);
			dcf.DataSet[DicomTags.Rows].SetInt32(0, rows);
			dcf.DataSet[DicomTags.Columns].SetInt32(0, columns);
			dcf.DataSet[DicomTags.NumberOfFrames].SetInt32(0, numberOfFrames);
			dcf.DataSet[pixelDataTag].Values = data;

			return dcf;
		}
Exemple #26
0
		private StorageScu SetupScu()
		{
			StorageScu scu = new StorageScu("TestAe", "AssocTestServer", "localhost", 2112);

			IList<DicomAttributeCollection> list = SetupMRSeries(4, 2, DicomUid.GenerateUid().UID);

			foreach (DicomAttributeCollection collection in list)
			{
				DicomFile file = new DicomFile("test", new DicomAttributeCollection(), collection);
				file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian;
				file.MediaStorageSopClassUid = SopClass.MrImageStorage.Uid;
				file.MediaStorageSopInstanceUid = collection[DicomTags.SopInstanceUid].ToString();

				scu.AddStorageInstance(new StorageInstance(file));
			}

			return scu;
		}
Exemple #27
0
		public void ScuAbortTest()
		{
			int port = 2112;

			/* Setup the Server */
			ServerAssociationParameters serverParameters = new ServerAssociationParameters("AssocTestServer", new IPEndPoint(IPAddress.Any, port));
			byte pcid = serverParameters.AddPresentationContext(SopClass.MrImageStorage);
			serverParameters.AddTransferSyntax(pcid, TransferSyntax.ExplicitVrLittleEndian);
			serverParameters.AddTransferSyntax(pcid, TransferSyntax.ExplicitVrBigEndian);
			serverParameters.AddTransferSyntax(pcid, TransferSyntax.ImplicitVrLittleEndian);

			_serverType = TestTypes.Receive;
			DicomServer.StartListening(serverParameters, ServerHandlerCreator);

			StorageScu scu = SetupScu();

			IList<DicomAttributeCollection> list = SetupMRSeries(4, 2, DicomUid.GenerateUid().UID);

			foreach (DicomAttributeCollection collection in list)
			{
				DicomFile file = new DicomFile("test",new DicomAttributeCollection(),collection );
				file.TransferSyntax = TransferSyntax.ExplicitVrLittleEndian;
				file.MediaStorageSopClassUid = SopClass.MrImageStorage.Uid;
				file.MediaStorageSopInstanceUid = collection[DicomTags.SopInstanceUid].ToString();

				scu.AddStorageInstance(new StorageInstance(file));
			}

			scu.ImageStoreCompleted += delegate(object o, StorageInstance instance)
			                           	{
											// Test abort
			                           		scu.Abort();
			                           	};

			scu.Send();
			scu.Join();

			Assert.AreEqual(scu.Status, ScuOperationStatus.NetworkError);

			// StopListening
			DicomServer.StopListening(serverParameters);
		}
		private void SetupEncapsulatedImageWithIconSequence(DicomFile file, bool encapsulateIconPixelData)
		{
			var codec = new NullDicomCodec();

			DicomAttributeCollection dataSet = file.DataSet;

			SetupSecondaryCapture(dataSet);

			SetupMetaInfo(file);

			file.TransferSyntax = TransferSyntax.ImplicitVrLittleEndian;
			file.ChangeTransferSyntax(codec.CodecTransferSyntax);

			// explicitly create the icon sequence as either encapsulated or native, so that we are not depending on correct behaviour elsewhere...
			CreateIconImageSequence(dataSet);

			if (encapsulateIconPixelData)
			{
				var dataset = ((DicomAttributeSQ) dataSet[DicomTags.IconImageSequence])[0];
				var pixelData = dataset[DicomTags.PixelData];

				var pd = new DicomUncompressedPixelData(dataset);
				using (var pixelStream = ((DicomAttributeBinary) pixelData).AsStream())
				{
					//Before compression, make the pixel data more "typical", so it's harder to mess up the codecs.
					//NOTE: Could combine mask and align into one method so we're not iterating twice, but I prefer having the methods separate.
					if (DicomUncompressedPixelData.RightAlign(pixelStream, pd.BitsAllocated, pd.BitsStored, pd.HighBit))
					{
						var newHighBit = (ushort) (pd.HighBit - pd.LowBit);

						pd.HighBit = newHighBit; //correct high bit after right-aligning.
						dataset[DicomTags.HighBit].SetUInt16(0, newHighBit);
					}
					DicomUncompressedPixelData.ZeroUnusedBits(pixelStream, pd.BitsAllocated, pd.BitsStored, pd.HighBit);
				}

				// Set transfer syntax before compression, the codecs need it.
				var fragments = new DicomCompressedPixelData(pd) {TransferSyntax = codec.CodecTransferSyntax};
				codec.Encode(pd, fragments, null);
				fragments.UpdateAttributeCollection(dataset);
			}
		}
Exemple #29
0
		/// <summary>
		/// Searches the given path for DICOM object files, automatically parsing for patient and study instance information.
		/// </summary>
		/// <param name="path">The file path on which to search for files.</param>
		/// <param name="recursive">True if the paths should be processed recursively; False otherwise.</param>
		public void AddPath(string path, bool recursive)
		{
			if (File.Exists(path))
			{
				try
				{
					DicomFile dcf = new DicomFile(path);
					dcf.Load(DicomReadOptions.Default | DicomReadOptions.DoNotStorePixelDataInDataSet);

					List<string> s = InternalAddStudy(dcf.DataSet[DicomTags.PatientId].ToString(), dcf.DataSet[DicomTags.PatientsName].ToString(), dcf.DataSet[DicomTags.StudyInstanceUid].ToString());
					s.Add(path);
				}
				catch (DicomException) {}
			}
			else if (recursive && Directory.Exists(path))
			{
				foreach (string subpaths in Directory.GetFileSystemEntries(path))
					AddPath(subpaths);
			}
		}
Exemple #30
0
        private void LoadFiles(DirectoryInfo dir)
        {
         
            FileInfo[] files = dir.GetFiles();

            foreach (FileInfo file in files)
            {

                DicomFile dicomFile = new DicomFile(file.FullName);

                try
                {

                    DicomReadOptions options = new DicomReadOptions();


                    dicomFile.Load(options);
                    _theStream.AddFile(dicomFile);
                    /*
					if (true == dicomFile.Load())
					{
						_theStream.AddFile(dicomFile);
					}
                     * */
                }
                catch (DicomException) 
                {
                    // TODO:  Add some logging for failed files
                }

            }

            String[] subdirectories = Directory.GetDirectories(dir.FullName);
            foreach (String subPath in subdirectories)
            {
                DirectoryInfo subDir = new DirectoryInfo(subPath);
                LoadFiles(subDir);
                continue;
            }

        }
Exemple #31
0
        /// <summary>
        /// Choose the final content type given compatibleContentTypesByOrderOfPreference and dicomFile
        /// </summary>
        /// <param name="compatibleContentTypesByOrderOfPreference"></param>
        /// <param name="dicomFile"></param>
        /// <returns></returns>
        private static string PickFinalContentType(string[] compatibleContentTypesByOrderOfPreference, DicomFile dicomFile)
        {
            string chosenContentType = null;
            int    nbFrames          = dicomFile.Dataset.Get <int>(DicomTag.NumberOfFrames);

            //if compatibleContentTypesByOrderOfPreference is null,
            //it means we must choose a default content type based on image content:
            //  *Single Frame Image Objects
            //      If the contentType parameter is not present in the request, the response shall contain an image/jpeg MIME
            //      type, if compatible with the ‘Accept’ field of the GET method.
            //  *Multi Frame Image Objects
            //      If the contentType parameter is not present in the request, the response shall contain a application/dicom
            //      MIME type.

            //not sure if this is how we distinguish multi frame objects?
            bool isMultiFrame       = nbFrames > 1;
            bool chooseDefaultValue = compatibleContentTypesByOrderOfPreference == null;

            if (chooseDefaultValue)
            {
                if (isMultiFrame)
                {
                    chosenContentType = AppDicomContentType;
                }
                else
                {
                    chosenContentType = JpegImageContentType;
                }
            }
            else
            {
                //we need to take the compatible one
                chosenContentType = compatibleContentTypesByOrderOfPreference
                                    .Intersect(new[] { AppDicomContentType, JpegImageContentType })
                                    .First();
            }
            return(chosenContentType);
        }
Exemple #32
0
        public async Task <HttpResponseMessage> GetStudyInstances(HttpRequestMessage requestMessage, string requestType,
                                                                  string studyUID, string seriesUID, string objectUID, string contentType = null, string charset = null,
                                                                  string transferSyntax = null, string anonymize = null)
        {
            //we do not handle anonymization
            if (anonymize == "yes")
            {
                return(requestMessage.CreateErrorResponse(HttpStatusCode.NotAcceptable,
                                                          String.Format("anonymise is not supported on the server", contentType)));
            }

            //we extract the content types from contentType value
            string[] contentTypes;
            bool     canParseContentTypeParameter = ExtractContentTypesFromContentTypeParameter(contentType,
                                                                                                out contentTypes);

            if (!canParseContentTypeParameter)
            {
                return(requestMessage.CreateErrorResponse(HttpStatusCode.NotAcceptable,
                                                          String.Format("contentType parameter (value: {0}) cannot be parsed", contentType)));
            }


            //8.1.5 The Web Client shall provide list of content types it supports in the "Accept" field of the GET method. The
            //value of the contentType parameter of the request shall be one of the values specified in that field.
            string[] acceptContentTypesHeader =
                requestMessage.Headers.Accept.Select(header => header.MediaType).ToArray();

            // */* means that we accept everything for the content Header
            bool acceptAllTypesInAcceptHeader = acceptContentTypesHeader.Contains("*/*");
            bool isRequestedContentTypeCompatibleWithAcceptContentHeader = acceptAllTypesInAcceptHeader ||
                                                                           contentTypes == null ||
                                                                           acceptContentTypesHeader.Intersect(
                contentTypes).Any();

            if (!isRequestedContentTypeCompatibleWithAcceptContentHeader)
            {
                return(requestMessage.CreateErrorResponse(HttpStatusCode.NotAcceptable,
                                                          String.Format("content type {0} is not compatible with types specified in  Accept Header",
                                                                        contentType)));
            }

            //6.3.2.1 The MIME type shall be one on the MIME types defined in the contentType parameter, preferably the most
            //desired by the Web Client, and shall be in any case compatible with the ‘Accept’ field of the GET method.
            //Note: The HTTP behavior is that an error (406 – Not Acceptable) is returned if the required content type cannot
            //be served.
            string[] compatibleContentTypesByOrderOfPreference =
                GetCompatibleContentTypesByOrderOfPreference(contentTypes,
                                                             acceptContentTypesHeader);

            //if there is no type that can be handled by our server, we return an error
            if (compatibleContentTypesByOrderOfPreference != null &&
                !compatibleContentTypesByOrderOfPreference.Contains(JpegImageContentType) &&
                !compatibleContentTypesByOrderOfPreference.Contains(AppDicomContentType))
            {
                return(requestMessage.CreateErrorResponse(HttpStatusCode.NotAcceptable,
                                                          String.Format("content type(s) {0} cannot be served",
                                                                        String.Join(" - ", compatibleContentTypesByOrderOfPreference)
                                                                        )));
            }

            //we now need to handle the case where contentType is not specified, but in this case, the default value
            //depends on the image, so we need to open it

            string dicomImagePath = _dicomImageFinderService.GetImageByInstanceUid(objectUID);

            if (dicomImagePath == null)
            {
                return(requestMessage.CreateErrorResponse(HttpStatusCode.NotFound, "no image found"));
            }

            try
            {
                IOManager.SetImplementation(DesktopIOManager.Instance);

                DicomFile dicomFile = await DicomFile.OpenAsync(dicomImagePath);

                string finalContentType = PickFinalContentType(compatibleContentTypesByOrderOfPreference, dicomFile);

                return(ReturnImageAsHttpResponse(dicomFile,
                                                 finalContentType, transferSyntax));
            }
            catch (Exception ex)
            {
                Trace.TraceError("exception when sending image: " + ex.ToString());

                return(requestMessage.CreateErrorResponse(HttpStatusCode.InternalServerError, "server internal error"));
            }
        }
        protected void ProcessFile(Model.WorkQueue item, WorkQueueUid sop, string path, StudyXml studyXml, IDicomCodecFactory theCodecFactory)
        {
            DicomFile file;

            _instanceStats = new CompressInstanceStatistics();

            _instanceStats.ProcessTime.Start();

            // Use the command processor for rollback capabilities.
            using (ServerCommandProcessor processor = new ServerCommandProcessor("Processing WorkQueue Compress DICOM File"))
            {
                string modality = String.Empty;

                try
                {
                    file = new DicomFile(path);

                    _instanceStats.FileLoadTime.Start();
                    file.Load(DicomReadOptions.StorePixelDataReferences | DicomReadOptions.Default);
                    _instanceStats.FileLoadTime.End();

                    modality = file.DataSet[DicomTags.Modality].GetString(0, String.Empty);

                    FileInfo fileInfo = new FileInfo(path);
                    _instanceStats.FileSize = (ulong)fileInfo.Length;

                    // Get the Patients Name for processing purposes.
                    String patientsName = file.DataSet[DicomTags.PatientsName].GetString(0, "");

                    if (file.TransferSyntax.Equals(theCodecFactory.CodecTransferSyntax))
                    {
                        // Delete the WorkQueueUid item
                        processor.AddCommand(new DeleteWorkQueueUidCommand(sop));

                        // Do the actual processing
                        if (!processor.Execute())
                        {
                            Platform.Log(LogLevel.Warn, "Failure deleteing WorkQueueUid: {0} for SOP: {1}", processor.Description, file.MediaStorageSopInstanceUid);
                            Platform.Log(LogLevel.Warn, "Compression file that failed: {0}", file.Filename);
                        }
                        else
                        {
                            Platform.Log(LogLevel.Warn, "Skip compressing SOP {0}. Its current transfer syntax is {1}",
                                         file.MediaStorageSopInstanceUid, file.TransferSyntax.Name);
                        }
                    }
                    else
                    {
                        IDicomCodec codec = theCodecFactory.GetDicomCodec();

                        // Create a context for applying actions from the rules engine
                        var context = new ServerActionContext(file, StorageLocation.FilesystemKey, ServerPartition, item.StudyStorageKey);
                        context.CommandProcessor = processor;

                        var parms           = theCodecFactory.GetCodecParameters(item.Data);
                        var compressCommand =
                            new DicomCompressCommand(context.Message, theCodecFactory.CodecTransferSyntax, codec, parms);
                        processor.AddCommand(compressCommand);

                        var save = new SaveDicomFileCommand(file.Filename, file, false);
                        processor.AddCommand(save);

                        // Update the StudyStream object, must be done after compression
                        // and after the compressed image has been successfully saved
                        var insertStudyXmlCommand = new UpdateStudyXmlCommand(file, studyXml, StorageLocation);
                        processor.AddCommand(insertStudyXmlCommand);

                        // Delete the WorkQueueUid item
                        processor.AddCommand(new DeleteWorkQueueUidCommand(sop));

                        // Do the actual processing
                        if (!processor.Execute())
                        {
                            _instanceStats.CompressTime.Add(compressCommand.CompressTime);
                            Platform.Log(LogLevel.Error, "Failure compressing command {0} for SOP: {1}", processor.Description, file.MediaStorageSopInstanceUid);
                            Platform.Log(LogLevel.Error, "Compression file that failed: {0}", file.Filename);
                            throw new ApplicationException("Unexpected failure (" + processor.FailureReason + ") executing command for SOP: " + file.MediaStorageSopInstanceUid, processor.FailureException);
                        }
                        _instanceStats.CompressTime.Add(compressCommand.CompressTime);
                        Platform.Log(ServerPlatform.InstanceLogLevel, "Compress SOP: {0} for Patient {1}", file.MediaStorageSopInstanceUid,
                                     patientsName);
                    }
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}.  Rolling back operation.",
                                 processor.Description);
                    processor.Rollback();

                    throw;
                }
                finally
                {
                    _instanceStats.ProcessTime.End();
                    _studyStats.AddSubStats(_instanceStats);

                    _studyStats.StudyInstanceUid = StorageLocation.StudyInstanceUid;
                    if (String.IsNullOrEmpty(modality) == false)
                    {
                        _studyStats.Modality = modality;
                    }

                    // Update the statistics
                    _studyStats.NumInstances++;
                }
            }
        }
        public GridBasedVoxelDataStructure Load(DicomFile dicomFile)
        {
            GridBasedVoxelDataStructure grid = new GridBasedVoxelDataStructure();
            PixelDataInfo DicomHeader        = new PixelDataInfo(dicomFile);
            Point3d       size = GetSize(dicomFile);

            grid.ConstantGridSpacing = true;
            grid.GridSpacing         = GetSpacing(dicomFile);
            grid.XCoords             = GetCoords(dicomFile, (int)size.X, DicomHeader.RowDir.X, DicomHeader.ColDir.X, DicomHeader.ImagePositionPatient.X, 1);
            grid.YCoords             = GetCoords(dicomFile, (int)size.Y, DicomHeader.RowDir.Y, DicomHeader.ColDir.Y, DicomHeader.ImagePositionPatient.Y, 1);
            grid.ZCoords             = GetCoords(dicomFile, (int)size.Z, DicomHeader.RowDir.Z, DicomHeader.ColDir.Z, DicomHeader.ImagePositionPatient.Z, 1);

            grid.Data = new float[(int)size.X * (int)size.Y * (int)size.Z];

            int currYIndex = 0;
            int currZIndex = 0;
            int currXIndex = 0;

            DicomPixelData dicomPixelData = DicomPixelData.Create(dicomFile.Dataset);
            PixelDataInfo  tempHeaderInfo = new PixelDataInfo(dicomFile);

            for (int j = 0; j < tempHeaderInfo.GridFrameOffsetVector.Length; j++)
            {
                byte[]  framePixelData = dicomPixelData.GetFrame(j).Data;
                float[] dataArray      = GetDataArray(framePixelData, tempHeaderInfo.BitsAllocated, tempHeaderInfo.PixelRepresentation);
                for (int k = 0; k < dataArray.Length; k++)
                {
                    int currRow = k % tempHeaderInfo.Columns;
                    int currCol = (int)Math.Floor((double)(k / (tempHeaderInfo.Columns)));
                    currXIndex = (int)Math.Abs(tempHeaderInfo.RowDir.X) * currRow + (int)Math.Abs(tempHeaderInfo.ColDir.X) * currCol
                                 + (1 - (int)Math.Abs(tempHeaderInfo.RowDir.X) - (int)Math.Abs(tempHeaderInfo.ColDir.X)) * (j);;
                    currYIndex = (int)Math.Abs(tempHeaderInfo.RowDir.Y) * currRow + (int)Math.Abs(tempHeaderInfo.ColDir.Y) * currCol
                                 + (1 - (int)Math.Abs(tempHeaderInfo.RowDir.Y) - (int)Math.Abs(tempHeaderInfo.ColDir.Y)) * (j);;
                    currZIndex = (int)Math.Abs(tempHeaderInfo.RowDir.Z) * currRow + (int)Math.Abs(tempHeaderInfo.ColDir.Z) * currCol
                                 + (1 - (int)Math.Abs(tempHeaderInfo.RowDir.Z) - (int)Math.Abs(tempHeaderInfo.ColDir.Z)) * (j);

                    //Rescale back to actual HUs
                    dataArray[k] = dataArray[k] * tempHeaderInfo.RescaleSlope + tempHeaderInfo.RescaleIntercept;
                    grid.SetVoxelByIndices(currXIndex, currYIndex, currZIndex, dataArray[k]);

                    if (dataArray[k] > grid.MaxVoxel.Value)
                    {
                        grid.MaxVoxel.Value      = dataArray[k];
                        grid.MaxVoxel.Position.X = grid.XCoords[currXIndex];
                        grid.MaxVoxel.Position.Y = grid.YCoords[currYIndex];
                        grid.MaxVoxel.Position.Z = grid.ZCoords[currZIndex];
                    }
                    if (dataArray[k] < grid.MinVoxel.Value)
                    {
                        grid.MinVoxel.Value      = dataArray[k];
                        grid.MinVoxel.Position.X = grid.XCoords[currXIndex];
                        grid.MinVoxel.Position.Y = grid.YCoords[currYIndex];
                        grid.MinVoxel.Position.Z = grid.ZCoords[currZIndex];
                    }
                }
            }

            grid.XRange = new Range(grid.XCoords[0], grid.XCoords[grid.XCoords.Length - 1]);
            grid.YRange = new Range(grid.YCoords[0], grid.YCoords[grid.YCoords.Length - 1]);
            grid.ZRange = new Range(grid.ZCoords[0], grid.ZCoords[grid.ZCoords.Length - 1]);

            //grid.ComputeMax();
            return(grid);
        }
        public async Task DownloadServiceNoApiConnection()
        {
            var(segmentationId, modelId, data) = await StartFakeSegmentationAsync(@"Images\1ValidSmall\");

            var applicationEntity = new GatewayApplicationEntity("RListenerTest", 144, "127.0.0.1");

            var mockSegmentationClient = GetMockInnerEyeSegmentationClient();

            // Fake a no response when getting progress
            mockSegmentationClient.SegmentationResultException = new HttpRequestException();

            // Create a Data receiver to receive the RT struct result
            using (var dicomDataReceiver = new ListenerDataReceiver(new ListenerDicomSaver(CreateTemporaryDirectory().FullName)))
            {
                var eventCount = 0;
                var folderPath = string.Empty;

                dicomDataReceiver.DataReceived += (sender, e) =>
                {
                    folderPath = e.FolderPath;
                    Interlocked.Increment(ref eventCount);
                };

                StartDicomDataReceiver(dicomDataReceiver, applicationEntity.Port);

                using (var pushService = CreatePushService())
                    using (var downloadService = CreateDownloadService(mockSegmentationClient))
                        using (var downloadQueue = downloadService.DownloadQueue)
                            using (var deadLetterQueue = downloadService.DeadletterMessageQueue)
                            {
                                pushService.Start();
                                downloadService.Start();

                                downloadQueue.Clear();

                                TransactionalEnqueue(
                                    downloadQueue,
                                    new DownloadQueueItem(
                                        segmentationId: segmentationId,
                                        modelId: modelId,
                                        resultsDirectory: CreateTemporaryDirectory().FullName,
                                        referenceDicomFiles: data,
                                        calledApplicationEntityTitle: applicationEntity.Title,
                                        callingApplicationEntityTitle: applicationEntity.Title,
                                        destinationApplicationEntity: applicationEntity,
                                        tagReplacementJsonString: JsonConvert.SerializeObject(_defaultTagReplacement),
                                        associationGuid: Guid.NewGuid(),
                                        associationDateTime: DateTime.UtcNow,
                                        isDryRun: false));

                                // Wait
                                await Task.Delay(TimeSpan.FromSeconds(5));

                                // Null the exception from the mock client
                                mockSegmentationClient.SegmentationResultException = null;

                                // Wait for all events to finish on the data received
                                SpinWait.SpinUntil(() => eventCount >= 3, TimeSpan.FromMinutes(5));

                                WaitUntilNoMessagesOnQueue(downloadQueue);

                                // Check this message has been de-queued
                                Assert.ThrowsException <MessageQueueReadException>(() => TransactionalDequeue <DownloadQueueItem>(downloadQueue));

                                Assert.ThrowsException <MessageQueueReadException>(() => TransactionalDequeue <DownloadQueueItem>(deadLetterQueue));
                            }

                dicomDataReceiver.StopServer();

                Assert.IsFalse(string.IsNullOrWhiteSpace(folderPath));

                var files = new DirectoryInfo(folderPath).GetFiles();

                // Check we have a file
                Assert.AreEqual(1, files.Length);

                var dicomFile = await DicomFile.OpenAsync(files[0].FullName);

                Assert.IsNotNull(dicomFile);

                TryDeleteDirectory(folderPath);
            }
        }
 private bool IsReportOrAttachment(DicomFile file)
 {
     return(AnonymizeStudyTool.IsReportOrAttachmentSopClass(file.SopClass != null ? file.SopClass.Uid : string.Empty));
 }
Exemple #37
0
        public void TestPatientModuleIod()
        {
            var dicomFile = new DicomFile();

            var module = new PatientModuleIod(dicomFile.DataSet);

            module.ResponsibleOrganization    = "Walt Disney";
            module.ResponsiblePerson          = "Roger Radcliffe";
            module.ResponsiblePersonRole      = ResponsiblePersonRole.Owner;
            module.PatientSpeciesDescription  = "Canine species";
            module.PatientSpeciesCodeSequence = SpeciesContextGroup.CanineSpecies;
            module.PatientBreedDescription    = "Dalmatian dog";
            module.PatientBreedCodeSequence   = new[] { BreedContextGroup.DalmatianDog };
            module.BreedRegistrationSequence  = new[]
            {
                new BreedRegistrationSequence
                {
                    BreedRegistrationNumber   = "101",
                    BreedRegistryCodeSequence = new BreedRegistry(
                        "WD",
                        "101",
                        "WALT_DISNESY_101",
                        "One hundred and one dalmatians")
                }
            };

            Assert.AreEqual(module.ResponsibleOrganization, "Walt Disney");
            Assert.AreEqual(module.ResponsiblePerson, "Roger Radcliffe");
            Assert.AreEqual(module.ResponsiblePersonRole, ResponsiblePersonRole.Owner);
            Assert.AreEqual(module.PatientSpeciesDescription, "Canine species");
            Assert.AreEqual(module.PatientSpeciesCodeSequence, SpeciesContextGroup.CanineSpecies);
            Assert.AreEqual(module.PatientBreedDescription, "Dalmatian dog");
            Assert.AreEqual(module.PatientBreedCodeSequence.Length, 1);
            Assert.AreEqual(module.PatientBreedCodeSequence[0], BreedContextGroup.DalmatianDog);
            Assert.AreEqual(module.BreedRegistrationSequence.Length, 1);
            Assert.AreEqual(module.BreedRegistrationSequence[0].BreedRegistrationNumber, "101");
            Assert.AreEqual(module.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodingSchemeDesignator, "WD");
            Assert.AreEqual(module.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodingSchemeVersion, "101");
            Assert.AreEqual(module.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodeValue, "WALT_DISNESY_101");
            Assert.AreEqual(module.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodeMeaning, "One hundred and one dalmatians");

            dicomFile.Save("TestPatientModuleIod.dcm");

            var reloadedDicomFile = new DicomFile("TestPatientModuleIod.dcm");

            reloadedDicomFile.Load();

            var realoadedModule = new PatientModuleIod(reloadedDicomFile.DataSet);

            Assert.AreEqual(realoadedModule.ResponsibleOrganization, "Walt Disney");
            Assert.AreEqual(realoadedModule.ResponsiblePerson, "Roger Radcliffe");
            Assert.AreEqual(realoadedModule.ResponsiblePersonRole, ResponsiblePersonRole.Owner);
            Assert.AreEqual(realoadedModule.PatientSpeciesDescription, "Canine species");
            Assert.AreEqual(realoadedModule.PatientSpeciesCodeSequence, SpeciesContextGroup.CanineSpecies);
            Assert.AreEqual(realoadedModule.PatientBreedDescription, "Dalmatian dog");
            Assert.AreEqual(realoadedModule.PatientBreedCodeSequence.Length, 1);
            Assert.AreEqual(realoadedModule.PatientBreedCodeSequence[0], BreedContextGroup.DalmatianDog);
            Assert.AreEqual(realoadedModule.BreedRegistrationSequence.Length, 1);
            Assert.AreEqual(realoadedModule.BreedRegistrationSequence[0].BreedRegistrationNumber, "101");
            Assert.AreEqual(realoadedModule.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodingSchemeDesignator, "WD");
            Assert.AreEqual(realoadedModule.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodingSchemeVersion, "101");
            Assert.AreEqual(realoadedModule.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodeValue, "WALT_DISNESY_101");
            Assert.AreEqual(realoadedModule.BreedRegistrationSequence[0].BreedRegistryCodeSequence.CodeMeaning, "One hundred and one dalmatians");
        }
        public async Task DicomSendFilesTest()
        {
            var dataSender        = new DicomDataSender();
            var applicationEntity = new GatewayApplicationEntity("RListenerTest", 131, "127.0.0.1");

            var dicomFiles = new DirectoryInfo(@"Images\1ValidSmall\").GetFiles().Select(x => DicomFile.Open(x.FullName)).ToArray();
            var rtFile     = await DicomFile.OpenAsync(@"Images\LargeSeriesWithContour\rtstruct.dcm");

            var resultsDirectory = CreateTemporaryDirectory();

            using (var dicomDataReceiver = new ListenerDataReceiver(new ListenerDicomSaver(resultsDirectory.FullName)))
            {
                StartDicomDataReceiver(dicomDataReceiver, applicationEntity.Port);

                var results = await dataSender.SendFilesAsync(
                    "Hello",
                    applicationEntity.Title,
                    applicationEntity.Port,
                    applicationEntity.IpAddress,
                    dicomFiles);

                foreach (var result in results)
                {
                    // Check we can send non-RT files
                    Assert.AreEqual(DicomOperationResult.Success, result.Item2);
                }

                var rtResult = await dataSender.SendFilesAsync(
                    "Hello",
                    applicationEntity.Title,
                    applicationEntity.Port,
                    applicationEntity.IpAddress,
                    rtFile);

                Assert.AreEqual(1, rtResult.Count());

                foreach (var result in rtResult)
                {
                    // Check we can send RT files
                    Assert.AreEqual(DicomOperationResult.Success, result.Item2);
                }

                dicomDataReceiver.StopServer();
            }
        }
Exemple #39
0
        protected override void ProcessItem(Model.WorkQueue item)
        {
            Platform.CheckForNullReference(item, "item");
            Platform.CheckForNullReference(item.StudyStorageKey, "item.StudyStorageKey");

            var context = new StudyProcessorContext(StorageLocation);

            // TODO: Should we enforce the patient's name rule?
            // If we do, the Study record will have the new patient's name
            // but how should we handle the name in the Patient record?
            bool enforceNameRules = false;
            var  processor        = new SopInstanceProcessor(context)
            {
                EnforceNameRules = enforceNameRules
            };

            var seriesMap = new Dictionary <string, List <string> >();

            bool   successful         = true;
            string failureDescription = null;

            // The processor stores its state in the Data column
            ReadQueueData(item);


            if (_queueData.State == null || !_queueData.State.ExecuteAtLeastOnce)
            {
                // Added for ticket #9673:
                // If the study folder does not exist and the study has been archived, trigger a restore and we're done
                if (!Directory.Exists(StorageLocation.GetStudyPath()))
                {
                    if (StorageLocation.ArchiveLocations.Count > 0)
                    {
                        Platform.Log(LogLevel.Info,
                                     "Reprocessing archived study {0} for Patient {1} (PatientId:{2} A#:{3}) on Partition {4} without study data on the filesystem.  Inserting Restore Request.",
                                     Study.StudyInstanceUid, Study.PatientsName, Study.PatientId,
                                     Study.AccessionNumber, ServerPartition.Description);

                        PostProcessing(item, WorkQueueProcessorStatus.Complete, WorkQueueProcessorDatabaseUpdate.ResetQueueState);

                        // Post process had to be done first so the study is unlocked so the RestoreRequest can be inserted.
                        ServerHelper.InsertRestoreRequest(StorageLocation);

                        RaiseAlert(WorkQueueItem, AlertLevel.Warning,
                                   string.Format(
                                       "Found study {0} for Patient {1} (A#:{2})on Partition {3} without storage folder, restoring study.",
                                       Study.StudyInstanceUid, Study.PatientsName, Study.AccessionNumber, ServerPartition.Description));
                        return;
                    }
                }

                if (Study == null)
                {
                    Platform.Log(LogLevel.Info,
                                 "Reprocessing study {0} on Partition {1}", StorageLocation.StudyInstanceUid,
                                 ServerPartition.Description);
                }
                else
                {
                    Platform.Log(LogLevel.Info,
                                 "Reprocessing study {0} for Patient {1} (PatientId:{2} A#:{3}) on Partition {4}",
                                 Study.StudyInstanceUid, Study.PatientsName, Study.PatientId,
                                 Study.AccessionNumber, ServerPartition.Description);
                }

                CleanupDatabase();
            }
            else
            {
                if (_queueData.State.Completed)
                {
                    #region SAFE-GUARD CODE: PREVENT INFINITE LOOP

                    // The processor indicated it had completed reprocessing in previous run. The entry should have been removed and this block of code should never be called.
                    // However, we have seen ReprocessStudy entries that mysterously contain rows in the WorkQueueUid table.
                    // The rows prevent the entry from being removed from the database and the ReprocessStudy keeps repeating itself.


                    // update the state first, increment the CompleteAttemptCount
                    _queueData.State.ExecuteAtLeastOnce = true;
                    _queueData.State.Completed          = true;
                    _queueData.State.CompleteAttemptCount++;
                    SaveState(item, _queueData);

                    if (_queueData.State.CompleteAttemptCount < 10)
                    {
                        // maybe there was db error in previous attempt to remove the entry. Let's try again.
                        Platform.Log(LogLevel.Info, "Resuming Reprocessing study {0} but it was already completed!!!", StorageLocation.StudyInstanceUid);
                        PostProcessing(item, WorkQueueProcessorStatus.Complete, WorkQueueProcessorDatabaseUpdate.ResetQueueState);
                    }
                    else
                    {
                        // we are definitely stuck.
                        Platform.Log(LogLevel.Error, "ReprocessStudy {0} for study {1} appears stuck. Aborting it.", item.Key, StorageLocation.StudyInstanceUid);
                        item.FailureDescription = "This entry had completed but could not be removed.";
                        PostProcessingFailure(item, WorkQueueProcessorFailureType.Fatal);
                    }

                    return;

                    #endregion
                }

                if (Study == null)
                {
                    Platform.Log(LogLevel.Info,
                                 "Resuming Reprocessing study {0} on Partition {1}", StorageLocation.StudyInstanceUid,
                                 ServerPartition.Description);
                }
                else
                {
                    Platform.Log(LogLevel.Info,
                                 "Resuming Reprocessing study {0} for Patient {1} (PatientId:{2} A#:{3}) on Partition {4}",
                                 Study.StudyInstanceUid, Study.PatientsName, Study.PatientId,
                                 Study.AccessionNumber, ServerPartition.Description);
                }
            }

            StudyXml studyXml = LoadStudyXml();

            int reprocessedCounter = 0;
            var removedFiles       = new List <FileInfo>();
            try
            {
                // Traverse the directories, process 500 files at a time
                FileProcessor.Process(StorageLocation.GetStudyPath(), "*.*",
                                      delegate(string path, out bool cancel)
                {
                    #region Reprocess File

                    var file = new FileInfo(path);

                    // ignore all files except those ending ".dcm"
                    // ignore "bad(0).dcm" files too
                    if (Regex.IsMatch(file.Name.ToUpper(), "[0-9]+\\.DCM$"))
                    {
                        try
                        {
                            var dicomFile = new DicomFile(path);
                            dicomFile.Load(DicomReadOptions.StorePixelDataReferences | DicomReadOptions.Default);

                            string seriesUid   = dicomFile.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty);
                            string instanceUid = dicomFile.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty);
                            if (studyXml.Contains(seriesUid, instanceUid))
                            {
                                if (!seriesMap.ContainsKey(seriesUid))
                                {
                                    seriesMap.Add(seriesUid, new List <string>());
                                }
                                if (!seriesMap[seriesUid].Contains(instanceUid))
                                {
                                    seriesMap[seriesUid].Add(instanceUid);
                                }
                                else
                                {
                                    Platform.Log(LogLevel.Warn, "SOP Instance UID in {0} appears more than once in the study.", path);
                                }
                            }
                            else
                            {
                                Platform.Log(ServerPlatform.InstanceLogLevel, "Reprocessing SOP {0} for study {1}", instanceUid, StorageLocation.StudyInstanceUid);
                                string groupId          = ServerHelper.GetUidGroup(dicomFile, StorageLocation.ServerPartition, WorkQueueItem.InsertTime);
                                ProcessingResult result = processor.ProcessFile(groupId, dicomFile, studyXml, true, false, null, null);
                                switch (result.Status)
                                {
                                case ProcessingStatus.Success:
                                    reprocessedCounter++;
                                    if (!seriesMap.ContainsKey(seriesUid))
                                    {
                                        seriesMap.Add(seriesUid, new List <string>());
                                    }

                                    if (!seriesMap[seriesUid].Contains(instanceUid))
                                    {
                                        seriesMap[seriesUid].Add(instanceUid);
                                    }
                                    else
                                    {
                                        Platform.Log(LogLevel.Warn, "SOP Instance UID in {0} appears more than once in the study.", path);
                                    }
                                    break;

                                case ProcessingStatus.Reconciled:
                                    Platform.Log(LogLevel.Warn, "SOP was unexpectedly reconciled on reprocess SOP {0} for study {1}. It will be removed from the folder.", instanceUid, StorageLocation.StudyInstanceUid);
                                    failureDescription = String.Format("SOP Was reconciled: {0}", instanceUid);

                                    // Added for #10620 (Previously we didn't do anything here)
                                    // Because we are reprocessing files in the study folder, when file needs to be reconciled it is copied to the reconcile folder
                                    // Therefore, we need to delete the one in the study folder. Otherwise, there will be problem when the SIQ entry is reconciled.
                                    // InstanceAlreadyExistsException will also be thrown by the SOpInstanceProcessor if this ReprocessStudy WQI
                                    // resumes and reprocesses the same file again.
                                    // Note: we are sure that the file has been copied to the Reconcile folder and there's no way back.
                                    // We must get rid of this file in the study folder.
                                    FileUtils.Delete(path);

                                    // Special handling: if the file is one which we're supposed to reprocess at the end (see ProcessAdditionalFiles), we must remove the file from the list
                                    if (_additionalFilesToProcess != null && _additionalFilesToProcess.Contains(path))
                                    {
                                        _additionalFilesToProcess.Remove(path);
                                    }

                                    break;
                                }
                            }
                        }
                        catch (DicomException ex)
                        {
                            // TODO : should we fail the reprocess instead? Deleting an dicom file can lead to incomplete study.
                            removedFiles.Add(file);
                            Platform.Log(LogLevel.Warn, "Skip reprocessing and delete {0}: Not readable.", path);
                            FileUtils.Delete(path);
                            failureDescription = ex.Message;
                        }
                    }
                    else if (!file.Extension.Equals(".xml") && !file.Extension.Equals(".gz"))
                    {
                        // not a ".dcm" or header file, delete it
                        removedFiles.Add(file);
                        FileUtils.Delete(path);
                    }

                    #endregion

                    cancel = reprocessedCounter >= 500;
                }, true);

                if (studyXml != null)
                {
                    EnsureConsistentObjectCount(studyXml, seriesMap);
                    SaveStudyXml(studyXml);
                }

                // Completed if either all files have been reprocessed
                // or no more dicom files left that can be reprocessed.
                _completed = reprocessedCounter == 0;
            }
            catch (Exception e)
            {
                successful         = false;
                failureDescription = e.Message;
                Platform.Log(LogLevel.Error, e, "Unexpected exception when reprocessing study: {0}", StorageLocation.StudyInstanceUid);
                Platform.Log(LogLevel.Error, "Study may be in invalid unprocessed state.  Study location: {0}", StorageLocation.GetStudyPath());
                throw;
            }
            finally
            {
                LogRemovedFiles(removedFiles);

                // Update the state
                _queueData.State.ExecuteAtLeastOnce = true;
                _queueData.State.Completed          = _completed;
                _queueData.State.CompleteAttemptCount++;
                SaveState(item, _queueData);

                if (!successful)
                {
                    FailQueueItem(item, failureDescription);
                }
                else
                {
                    if (!_completed)
                    {
                        // Put it back to Pending
                        PostProcessing(item, WorkQueueProcessorStatus.Pending, WorkQueueProcessorDatabaseUpdate.None);
                    }
                    else
                    {
                        LogHistory();

                        // Run Study / Series Rules Engine.
                        var engine = new StudyRulesEngine(StorageLocation, ServerPartition);
                        engine.Apply(ServerRuleApplyTimeEnum.StudyProcessed);

                        // Log the FilesystemQueue related entries
                        StorageLocation.LogFilesystemQueue();

                        PostProcessing(item, WorkQueueProcessorStatus.Complete, WorkQueueProcessorDatabaseUpdate.ResetQueueState);

                        Platform.Log(LogLevel.Info, "Completed reprocessing of study {0} on partition {1}", StorageLocation.StudyInstanceUid, ServerPartition.Description);
                    }
                }
            }
        }
Exemple #40
0
        public void DicomFile_Open_DoesNotThrow(string fileName)
        {
            var e = Record.Exception(() => DicomFile.Open(fileName));

            Assert.Null(e);
        }
Exemple #41
0
        public void Go()
        {
            string[] files = BuildFileList();
            var      args  = new SelectFolderDialogCreationArgs
            {
                Path = GetDirectoryOfFirstPath(),
                AllowCreateNewFolder = true,
                Prompt = "Select output folder"
            };

            var result = base.Context.DesktopWindow.ShowSelectFolderDialogBox(args);

            if (result.Action != DialogBoxAction.Ok)
            {
                return;
            }

            try
            {
                foreach (string file in files)
                {
                    DicomFile dicomFile = new DicomFile(file);
                    dicomFile.Load();

                    if (dicomFile.TransferSyntax.Encapsulated)
                    {
                        continue;
                    }

                    DicomAttribute attribute;
                    if (!dicomFile.DataSet.TryGetAttribute(DicomTags.PixelData, out attribute))
                    {
                        continue;
                    }

                    new OverlayPlaneModuleIod(dicomFile.DataSet).ExtractEmbeddedOverlays();
                    var rawPixelData = (byte[])attribute.Values;

                    DicomPixelData pd = new DicomUncompressedPixelData(dicomFile);
                    if (DicomUncompressedPixelData.ZeroUnusedBits(rawPixelData, pd.BitsAllocated, pd.BitsStored, pd.HighBit))
                    {
                        Platform.Log(LogLevel.Info, "Zeroed some unused bits.");
                    }
                    if (DicomUncompressedPixelData.RightAlign(rawPixelData, pd.BitsAllocated, pd.BitsStored, pd.HighBit))
                    {
                        var newHighBit = (ushort)(pd.HighBit - pd.LowBit);
                        Platform.Log(LogLevel.Info, "Right aligned pixel data (High Bit: {0}->{1}).", pd.HighBit, newHighBit);

                        pd.HighBit = newHighBit;                         //correct high bit after right-aligning.
                        dicomFile.DataSet[DicomTags.HighBit].SetUInt16(0, newHighBit);
                    }

                    string sourceFileName = System.IO.Path.GetFileNameWithoutExtension(file);
                    string fileName       = System.IO.Path.Combine(result.FileName, sourceFileName);
                    fileName += ".fixed-pixeldata.dcm";
                    dicomFile.Save(fileName);
                }
            }
            catch (Exception e)
            {
                ExceptionHandler.Report(e, Context.DesktopWindow);
            }
        }
Exemple #42
0
 public TestDataSource(DicomFile file)
     : base(file)
 {
     _file = file;
 }
Exemple #43
0
        /// <summary>
        /// Imports the specified <see cref="DicomMessageBase"/> object into the system.
        /// The object will be inserted into the <see cref="WorkQueue"/> for processing and
        /// if it's a duplicate, proper checks will be done and depending on the policy, it will be
        /// ignored, rejected or inserted into the <see cref="StudyIntegrityQueue"/> for manual intervention.
        /// </summary>
        /// <param name="message">The DICOM object to be imported.</param>
        /// <returns>An instance of <see cref="DicomProcessingResult"/> that describes the result of the processing.</returns>
        /// <exception cref="DicomDataException">Thrown when the DICOM object contains invalid data</exception>
        public DicomProcessingResult Import(DicomMessageBase message)
        {
            Platform.CheckForNullReference(message, "message");
            String    studyInstanceUid  = message.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty);
            String    seriesInstanceUid = message.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty);
            String    sopInstanceUid    = message.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty);
            String    accessionNumber   = message.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty);
            String    patientsName      = message.DataSet[DicomTags.PatientsName].GetString(0, string.Empty);
            DicomFile file = null;

            // Scrub the name for invalid characters.
            string newName = XmlUtils.XmlCharacterScrub(patientsName);

            if (!newName.Equals(patientsName))
            {
                message.DataSet[DicomTags.PatientsName].SetStringValue(newName);
            }

            var result = new DicomProcessingResult
            {
                Successful        = true,
                StudyInstanceUid  = studyInstanceUid,
                SeriesInstanceUid = seriesInstanceUid,
                SopInstanceUid    = sopInstanceUid,
                AccessionNumber   = accessionNumber
            };

            try
            {
                Validate(message);
            }
            catch (DicomDataException e)
            {
                result.SetError(DicomStatuses.ProcessingFailure, e.Message);
                return(result);
            }

            // Use the command processor for rollback capabilities.
            using (var commandProcessor = new ServerCommandProcessor(String.Format("Processing Sop Instance {0}", sopInstanceUid)))
            {
                try
                {
                    string failureMessage;
                    StudyStorageLocation studyLocation = GetWritableOnlineStorage(message);

                    // GetWritableOnlineStorage should throw an exception if the study location cannot be found.
                    Platform.CheckForNullReference(studyLocation, "studyLocation");

                    if (!studyLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.Idle) &&
                        (!studyLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.ProcessingScheduled)))
                    {
                        failureMessage = String.Format("Study {0} on partition {1} is being processed: {2}, can't accept new images.",
                                                       studyLocation.StudyInstanceUid, _context.Partition.Description, studyLocation.QueueStudyStateEnum.Description);
                        result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                        return(result);
                    }
                    if (studyLocation.StudyStatusEnum.Equals(StudyStatusEnum.OnlineLossy))
                    {
                        if (studyLocation.IsLatestArchiveLossless)
                        {
                            result.DicomStatus = DicomStatuses.StorageStorageOutOfResources;
                            failureMessage     = String.Format("Study {0} on partition {1} can't accept new images due to lossy compression of the study.  Restoring study.",
                                                               studyLocation.StudyInstanceUid, _context.Partition.Description);
                            Platform.Log(LogLevel.Error, failureMessage);
                            if (ServerHelper.InsertRestoreRequest(studyLocation) == null)
                            {
                                Platform.Log(LogLevel.Warn, "Unable to insert Restore Request for Study");
                            }

                            result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                            result.RestoreRequested = true;
                            return(result);
                        }
                    }

                    String       path      = studyLocation.FilesystemPath;
                    const string extension = null;
                    String       finalDest = studyLocation.GetSopInstancePath(seriesInstanceUid, sopInstanceUid);
                    file = ConvertToDicomFile(message, finalDest, _context.SourceAE);

                    if (HasUnprocessedCopy(studyLocation.Key, seriesInstanceUid, sopInstanceUid))
                    {
                        var accept = false;

                        // This is a special case: #10569
                        // Allow user to revive an orphaned study by reprocessing the files found in the filesystem
                        if (File.Exists(finalDest))
                        {
                            accept = DuplicatePolicy.IsParitionDuplicatePolicyOverridden(studyLocation);
                        }

                        if (!accept)
                        {
                            failureMessage = string.Format("Another copy of the SOP Instance was received but has not been processed: {0}", sopInstanceUid);
                            result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage);
                            return(result);
                        }
                    }

                    if (File.Exists(finalDest))
                    {
                        result = HandleDuplicate(sopInstanceUid, studyLocation, commandProcessor, file);
                        if (!result.Successful)
                        {
                            return(result);
                        }
                    }
                    else
                    {
                        HandleNonDuplicate(seriesInstanceUid, sopInstanceUid, studyLocation, commandProcessor, file, path, false, extension);
                    }

                    if (commandProcessor.Execute())
                    {
                        result.DicomStatus = DicomStatuses.Success;
                    }
                    else
                    {
                        failureMessage =
                            String.Format("Failure processing message: {0}. Sending failure status.",
                                          commandProcessor.FailureReason);
                        result.SetError(DicomStatuses.ProcessingFailure, failureMessage);
                        // processor already rolled back
                        return(result);
                    }
                }
                catch (NoWritableFilesystemException)
                {
                    String failureMessage = String.Format("Unable to process image, no writable filesystem found for Study UID {0}.", sopInstanceUid);
                    commandProcessor.Rollback();
                    result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                }
                catch (StudyIsNearlineException e)
                {
                    String failureMessage = e.RestoreRequested
                                                ? String.Format("{0}. Restore has been requested.", e.Message)
                                                : e.Message;

                    Platform.Log(LogLevel.Error, failureMessage);
                    commandProcessor.Rollback();
                    result.SetError(DicomStatuses.ProcessingFailure, failureMessage);
                }
                catch (FilesystemNotWritableException)
                {
                    commandProcessor.Rollback();

                    string folder;
                    if (!FilesystemMonitor.Instance.GetWriteableIncomingFolder(_context.Partition, out folder))
                    {
                        String failureMessage =
                            String.Format("Unable to process image, study storage location is missing or not writeable: {0}.", sopInstanceUid);
                        result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                        return(result);
                    }

                    if (file == null)
                    {
                        file = ConvertToDicomFile(message, string.Empty, _context.SourceAE);
                    }

                    if (!SaveToFolder(folder, sopInstanceUid, studyInstanceUid, file))
                    {
                        String failureMessage =
                            String.Format("Study storage location not writeable and no writeable incoming folder: {0}.", sopInstanceUid);
                        result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage);
                        return(result);
                    }

                    Platform.Log(LogLevel.Info, "Saved existing SOP without writeable storage location to {0} folder: {1}",
                                 FilesystemMonitor.ImportDirectorySuffix, sopInstanceUid);
                    result.DicomStatus = DicomStatuses.Success;
                    return(result);
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}.  Rolling back operation.", commandProcessor.Description);
                    commandProcessor.Rollback();
                    result.SetError(result.DicomStatus ?? DicomStatuses.ProcessingFailure, e.Message);
                }
            }

            return(result);
        }
Exemple #44
0
        private void ProcessPDataTF(object state)
        {
            var pdu = (PDataTF)state;

            try {
                foreach (var pdv in pdu.PDVs)
                {
                    if (_dimse == null)
                    {
                        // create stream for receiving command
                        if (_dimseStream == null)
                        {
                            _dimseStream = new MemoryStream();
                        }
                    }
                    else
                    {
                        // create stream for receiving dataset
                        if (_dimseStream == null)
                        {
                            if (_dimse.Type == DicomCommandField.CStoreRequest)
                            {
                                var pc = Association.PresentationContexts.FirstOrDefault(x => x.ID == pdv.PCID);

                                var file = new DicomFile();
                                file.FileMetaInfo.MediaStorageSOPClassUID      = pc.AbstractSyntax;
                                file.FileMetaInfo.MediaStorageSOPInstanceUID   = _dimse.Command.Get <DicomUID>(DicomTag.AffectedSOPInstanceUID);
                                file.FileMetaInfo.TransferSyntax               = pc.AcceptedTransferSyntax;
                                file.FileMetaInfo.ImplementationClassUID       = Association.RemoteImplemetationClassUID;
                                file.FileMetaInfo.ImplementationVersionName    = Association.RemoteImplementationVersion;
                                file.FileMetaInfo.SourceApplicationEntityTitle = Association.CallingAE;

                                var fileName = TemporaryFile.Create();

                                file.Save(fileName);

                                _dimseStream = File.OpenWrite(fileName);
                                _dimseStream.Seek(0, SeekOrigin.End);
                            }
                            else
                            {
                                _dimseStream = new MemoryStream();
                            }
                        }
                    }

                    _dimseStream.Write(pdv.Value, 0, pdv.Value.Length);

                    if (pdv.IsLastFragment)
                    {
                        if (pdv.IsCommand)
                        {
                            _dimseStream.Seek(0, SeekOrigin.Begin);

                            var command = new DicomDataset();

                            var reader = new DicomReader();
                            reader.IsExplicitVR = false;
                            reader.Read(new StreamByteSource(_dimseStream), new DicomDatasetReaderObserver(command));

                            _dimseStream = null;

                            var type = command.Get <DicomCommandField>(DicomTag.CommandField);
                            switch (type)
                            {
                            case DicomCommandField.CStoreRequest:
                                _dimse = new DicomCStoreRequest(command);
                                break;

                            case DicomCommandField.CStoreResponse:
                                _dimse = new DicomCStoreResponse(command);
                                break;

                            case DicomCommandField.CFindRequest:
                                _dimse = new DicomCFindRequest(command);
                                break;

                            case DicomCommandField.CFindResponse:
                                _dimse = new DicomCFindResponse(command);
                                break;

                            case DicomCommandField.CMoveRequest:
                                _dimse = new DicomCMoveRequest(command);
                                break;

                            case DicomCommandField.CMoveResponse:
                                _dimse = new DicomCMoveResponse(command);
                                break;

                            case DicomCommandField.CEchoRequest:
                                _dimse = new DicomCEchoRequest(command);
                                break;

                            case DicomCommandField.CEchoResponse:
                                _dimse = new DicomCEchoResponse(command);
                                break;

                            case DicomCommandField.NActionRequest:
                                _dimse = new DicomNActionRequest(command);
                                break;

                            case DicomCommandField.NActionResponse:
                                _dimse = new DicomNActionResponse(command);
                                break;

                            case DicomCommandField.NCreateRequest:
                                _dimse = new DicomNCreateRequest(command);
                                break;

                            case DicomCommandField.NCreateResponse:
                                _dimse = new DicomNCreateResponse(command);
                                break;

                            case DicomCommandField.NDeleteRequest:
                                _dimse = new DicomNDeleteRequest(command);
                                break;

                            case DicomCommandField.NDeleteResponse:
                                _dimse = new DicomNDeleteResponse(command);
                                break;

                            case DicomCommandField.NEventReportRequest:
                                _dimse = new DicomNEventReportRequest(command);
                                break;

                            case DicomCommandField.NEventReportResponse:
                                _dimse = new DicomNEventReportResponse(command);
                                break;

                            case DicomCommandField.NGetRequest:
                                _dimse = new DicomNGetRequest(command);
                                break;

                            case DicomCommandField.NGetResponse:
                                _dimse = new DicomNGetResponse(command);
                                break;

                            case DicomCommandField.NSetRequest:
                                _dimse = new DicomNSetRequest(command);
                                break;

                            case DicomCommandField.NSetResponse:
                                _dimse = new DicomNSetResponse(command);
                                break;

                            default:
                                _dimse = new DicomMessage(command);
                                break;
                            }

                            if (!_dimse.HasDataset)
                            {
                                if (DicomMessage.IsRequest(_dimse.Type))
                                {
                                    ThreadPool.QueueUserWorkItem(PerformDimseCallback, _dimse);
                                }
                                else
                                {
                                    _processQueue.Queue((_dimse as DicomResponse).RequestMessageID, PerformDimseCallback, _dimse);
                                }
                                _dimse = null;
                                return;
                            }
                        }
                        else
                        {
                            if (_dimse.Type != DicomCommandField.CStoreRequest)
                            {
                                _dimseStream.Seek(0, SeekOrigin.Begin);

                                var pc = Association.PresentationContexts.FirstOrDefault(x => x.ID == pdv.PCID);

                                _dimse.Dataset = new DicomDataset();
                                _dimse.Dataset.InternalTransferSyntax = pc.AcceptedTransferSyntax;

                                var source = new StreamByteSource(_dimseStream);
                                source.Endian = pc.AcceptedTransferSyntax.Endian;

                                var reader = new DicomReader();
                                reader.IsExplicitVR = pc.AcceptedTransferSyntax.IsExplicitVR;
                                reader.Read(source, new DicomDatasetReaderObserver(_dimse.Dataset));

                                _dimseStream = null;
                            }
                            else
                            {
                                var fileName = (_dimseStream as FileStream).Name;
                                _dimseStream.Close();
                                _dimseStream = null;

                                var request = _dimse as DicomCStoreRequest;

                                try {
                                    request.File = DicomFile.Open(fileName);
                                } catch (Exception e) {
                                    // failed to parse received DICOM file; send error response instead of aborting connection
                                    SendResponse(new DicomCStoreResponse(request, new DicomStatus(DicomStatus.ProcessingFailure, e.Message)));
                                    Logger.Error("Error parsing C-Store dataset: " + e.ToString());
                                    (this as IDicomCStoreProvider).OnCStoreRequestException(fileName, e);
                                    return;
                                }

                                request.File.File.IsTempFile = true;
                                request.Dataset = request.File.Dataset;
                            }

                            if (DicomMessage.IsRequest(_dimse.Type))
                            {
                                ThreadPool.QueueUserWorkItem(PerformDimseCallback, _dimse);
                            }
                            else
                            {
                                _processQueue.Queue((_dimse as DicomResponse).RequestMessageID, PerformDimseCallback, _dimse);
                            }
                            _dimse = null;
                        }
                    }
                }
            } catch (Exception e) {
                SendAbort(DicomAbortSource.ServiceUser, DicomAbortReason.NotSpecified);
                Logger.Error("Exception processing P-Data-TF PDU: " + e.ToString());
            } finally {
                SendNextMessage();
            }
        }
Exemple #45
0
        /// <summary>
        /// Archive the specified <see cref="ArchiveQueue"/> item.
        /// </summary>
        /// <param name="queueItem">The ArchiveQueue item to archive.</param>
        public void Run(ArchiveQueue queueItem)
        {
            using (ArchiveProcessorContext executionContext = new ArchiveProcessorContext(queueItem))
            {
                try
                {
                    if (!GetStudyStorageLocation(queueItem))
                    {
                        Platform.Log(LogLevel.Error,
                                     "Unable to find readable study storage location for archival queue request {0}.  Delaying request.",
                                     queueItem.Key);
                        queueItem.FailureDescription = "Unable to find readable study storage location for archival queue request.";
                        _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Pending, Platform.Time.AddMinutes(2));
                        return;
                    }

                    // First, check to see if we can lock the study, if not just reschedule the queue entry.
                    if (!_storageLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.Idle))
                    {
                        Platform.Log(LogLevel.Info, "Study {0} on partition {1} is currently locked, delaying archival.", _storageLocation.StudyInstanceUid, _hsmArchive.ServerPartition.Description);
                        queueItem.FailureDescription = "Study is currently locked, delaying archival.";
                        _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Pending, Platform.Time.AddMinutes(2));
                        return;
                    }

                    StudyIntegrityValidator validator = new StudyIntegrityValidator();
                    validator.ValidateStudyState("Archive", _storageLocation, StudyIntegrityValidationModes.Default);

                    using (IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
                    {
                        ILockStudy          studyLock = update.GetBroker <ILockStudy>();
                        LockStudyParameters parms     = new LockStudyParameters
                        {
                            StudyStorageKey     = queueItem.StudyStorageKey,
                            QueueStudyStateEnum = QueueStudyStateEnum.ArchiveScheduled
                        };
                        bool retVal = studyLock.Execute(parms);
                        if (!parms.Successful || !retVal)
                        {
                            Platform.Log(LogLevel.Info, "Study {0} on partition {1} failed to lock, delaying archival.", _storageLocation.StudyInstanceUid, _hsmArchive.ServerPartition.Description);
                            queueItem.FailureDescription = "Study failed to lock, delaying archival.";
                            _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Pending, Platform.Time.AddMinutes(2));
                            return;
                        }
                        update.Commit();
                    }

                    string studyFolder = _storageLocation.GetStudyPath();

                    string studyXmlFile = _storageLocation.GetStudyXmlPath();

                    // Load the study Xml file, this is used to generate the list of dicom files to archive.
                    LoadStudyXml(studyXmlFile);

                    DicomFile file = LoadFileFromStudyXml();

                    string patientsName    = file.DataSet[DicomTags.PatientsName].GetString(0, string.Empty);
                    string patientId       = file.DataSet[DicomTags.PatientId].GetString(0, string.Empty);
                    string accessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty);

                    Platform.Log(LogLevel.Info,
                                 "Starting archival of study {0} for Patient {1} (PatientId:{2} A#:{3}) on Partition {4} on archive {5}",
                                 _storageLocation.StudyInstanceUid, patientsName, patientId,
                                 accessionNumber, _hsmArchive.ServerPartition.Description,
                                 _hsmArchive.PartitionArchive.Description);

                    // Use the command processor to do the archival.
                    using (ServerCommandProcessor commandProcessor = new ServerCommandProcessor("Archive"))
                    {
                        _archiveXml = new XmlDocument();

                        // Create the study date folder
                        string zipFilename = Path.Combine(_hsmArchive.HsmPath, _storageLocation.StudyFolder);
                        commandProcessor.AddCommand(new CreateDirectoryCommand(zipFilename));

                        // Create a folder for the study
                        zipFilename = Path.Combine(zipFilename, _storageLocation.StudyInstanceUid);
                        commandProcessor.AddCommand(new CreateDirectoryCommand(zipFilename));

                        // Save the archive data in the study folder, based on a filename with a date / time stamp
                        string filename = String.Format("{0}.zip", Platform.Time.ToString("yyyy-MM-dd-HHmm"));
                        zipFilename = Path.Combine(zipFilename, filename);


                        // Create the Xml data to store in the ArchiveStudyStorage table telling
                        // where the archived study is located.
                        XmlElement hsmArchiveElement = _archiveXml.CreateElement("HsmArchive");
                        _archiveXml.AppendChild(hsmArchiveElement);
                        XmlElement studyFolderElement = _archiveXml.CreateElement("StudyFolder");
                        hsmArchiveElement.AppendChild(studyFolderElement);
                        studyFolderElement.InnerText = _storageLocation.StudyFolder;
                        XmlElement filenameElement = _archiveXml.CreateElement("Filename");
                        hsmArchiveElement.AppendChild(filenameElement);
                        filenameElement.InnerText = filename;
                        XmlElement studyInstanceUidElement = _archiveXml.CreateElement("Uid");
                        hsmArchiveElement.AppendChild(studyInstanceUidElement);
                        studyInstanceUidElement.InnerText = _storageLocation.StudyInstanceUid;


                        // Create the Zip file
                        commandProcessor.AddCommand(
                            new CreateStudyZipCommand(zipFilename, _studyXml, studyFolder, executionContext.TempDirectory));

                        // Update the database.
                        commandProcessor.AddCommand(new InsertArchiveStudyStorageCommand(queueItem.StudyStorageKey, queueItem.PartitionArchiveKey, queueItem.GetKey(), _storageLocation.ServerTransferSyntaxKey, _archiveXml));


                        StudyRulesEngine studyEngine =
                            new StudyRulesEngine(_storageLocation, _hsmArchive.ServerPartition, _studyXml);
                        studyEngine.Apply(ServerRuleApplyTimeEnum.StudyArchived, commandProcessor);


                        if (!commandProcessor.Execute())
                        {
                            Platform.Log(LogLevel.Error,
                                         "Unexpected failure archiving study ({0}) to archive {1}: {2}, zip filename: {3}",
                                         _storageLocation.StudyInstanceUid, _hsmArchive.PartitionArchive.Description,
                                         commandProcessor.FailureReason, zipFilename);

                            queueItem.FailureDescription = commandProcessor.FailureReason;
                            _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Failed, Platform.Time);
                        }
                        else
                        {
                            Platform.Log(LogLevel.Info, "Successfully archived study {0} on {1} to zip {2}",
                                         _storageLocation.StudyInstanceUid,
                                         _hsmArchive.PartitionArchive.Description, zipFilename);
                        }

                        // Log the current FilesystemQueue settings
                        _storageLocation.LogFilesystemQueue();
                    }
                }
                catch (StudyIntegrityValidationFailure ex)
                {
                    StringBuilder error = new StringBuilder();
                    error.AppendLine(String.Format("Partition  : {0}", ex.ValidationStudyInfo.ServerAE));
                    error.AppendLine(String.Format("Patient    : {0}", ex.ValidationStudyInfo.PatientsName));
                    error.AppendLine(String.Format("Study Uid  : {0}", ex.ValidationStudyInfo.StudyInstaneUid));
                    error.AppendLine(String.Format("Accession# : {0}", ex.ValidationStudyInfo.AccessionNumber));
                    error.AppendLine(String.Format("Study Date : {0}", ex.ValidationStudyInfo.StudyDate));

                    queueItem.FailureDescription = error.ToString();
                    _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Failed, Platform.Time);
                }
                catch (Exception e)
                {
                    String msg = String.Format("Unexpected exception archiving study: {0} on {1}: {2}",
                                               _storageLocation.StudyInstanceUid, _hsmArchive.PartitionArchive.Description, e.Message);

                    Platform.Log(LogLevel.Error, e, msg);
                    queueItem.FailureDescription = msg;
                    _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Failed, Platform.Time);
                }
                finally
                {
                    // Unlock the Queue Entry
                    using (IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
                    {
                        ILockStudy          studyLock = update.GetBroker <ILockStudy>();
                        LockStudyParameters parms     = new LockStudyParameters
                        {
                            StudyStorageKey     = queueItem.StudyStorageKey,
                            QueueStudyStateEnum = QueueStudyStateEnum.Idle
                        };
                        bool retVal = studyLock.Execute(parms);
                        if (!parms.Successful || !retVal)
                        {
                            Platform.Log(LogLevel.Info, "Study {0} on partition {1} is failed to unlock.", _storageLocation.StudyInstanceUid, _hsmArchive.ServerPartition.Description);
                        }
                        update.Commit();
                    }
                }
            }
        }
Exemple #46
0
 protected override void Dispose(bool disposing)
 {
     base.Dispose(disposing);
     _file = null;
 }
Exemple #47
0
        public static DicomFile GenerateDicomFile(
            string studyInstanceUid,
            string seriesInstanceUid,
            string sopInstanceUid,
            string sopClassUid,
            int rows,
            int cols,
            TestFileBitDepth bitDepth,
            string transferSyntax,
            bool encode,
            int frames = 1,
            string photometricInterpretation = null)
        {
            var initialTs = DicomTransferSyntax.ExplicitVRLittleEndian;

            if (!encode)
            {
                initialTs = DicomTransferSyntax.Parse(transferSyntax);
            }

            var dicomFile = new DicomFile(
                new DicomDataset(initialTs)
            {
                { DicomTag.StudyInstanceUID, studyInstanceUid ?? TestUidGenerator.Generate() },
                { DicomTag.SeriesInstanceUID, seriesInstanceUid ?? TestUidGenerator.Generate() },
                { DicomTag.SOPInstanceUID, sopInstanceUid ?? TestUidGenerator.Generate() },
                { DicomTag.SOPClassUID, sopClassUid ?? TestUidGenerator.Generate() },
                { DicomTag.Rows, (ushort)rows },
                { DicomTag.Columns, (ushort)cols },
                { DicomTag.PhotometricInterpretation, photometricInterpretation ?? PhotometricInterpretation.Monochrome2.Value },
                { DicomTag.BitsAllocated, (ushort)bitDepth },
                { DicomTag.WindowWidth, ((bitDepth == TestFileBitDepth.EightBit) ? "256" : "65536") },
                { DicomTag.WindowCenter, ((bitDepth == TestFileBitDepth.EightBit) ? "128" : "32768") },
                { DicomTag.PatientID, TestUidGenerator.Generate() },
            });

            var pixelData = DicomPixelData.Create(dicomFile.Dataset, true);

            pixelData.SamplesPerPixel     = 1;
            pixelData.BitsStored          = (ushort)bitDepth;
            pixelData.HighBit             = (ushort)(bitDepth - 1);
            pixelData.PixelRepresentation = PixelRepresentation.Unsigned;

            for (int i = 0; i < frames; i++)
            {
                var buffer = new MemoryByteBuffer(
                    (bitDepth == TestFileBitDepth.SixteenBit)
                        ? GetBytesFor16BitImage(rows, cols, i)
                        : GetBytesFor8BitImage(rows, cols, i));

                pixelData.AddFrame(buffer);
            }

            if (encode && transferSyntax != DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID)
            {
                var transcoder =
                    new DicomTranscoder(
                        dicomFile.Dataset.InternalTransferSyntax,
                        DicomTransferSyntax.Parse(transferSyntax));
                dicomFile = transcoder.Transcode(dicomFile);
            }

            return(dicomFile);
        }
Exemple #48
0
        public static void LosslessImageTestWithBitsAllocatedConversion(TransferSyntax syntax, DicomFile theFile)
        {
            if (File.Exists(theFile.Filename))
            {
                File.Delete(theFile.Filename);
            }

            DicomFile saveCopy = new DicomFile(theFile.Filename, theFile.MetaInfo.Copy(), theFile.DataSet.Copy());

            theFile.ChangeTransferSyntax(syntax);

            theFile.Save(DicomWriteOptions.ExplicitLengthSequence);

            DicomFile newFile = new DicomFile(theFile.Filename);

            newFile.Load(DicomReadOptions.Default);

            newFile.ChangeTransferSyntax(saveCopy.TransferSyntax);

            string failureDescription;
            var    newPd = DicomPixelData.CreateFrom(newFile);
            var    oldPd = DicomPixelData.CreateFrom(saveCopy);

            bool result = Compare(newPd, oldPd, out failureDescription);

            Assert.IsFalse(result, failureDescription);

            Assert.IsFalse(newFile.DataSet.Equals(saveCopy.DataSet));

            DicomAttributeCollection newDataSet = newFile.DataSet.Copy(true, true, true);
            DicomAttributeCollection oldDataSet = theFile.DataSet.Copy(true, true, true);

            oldDataSet.RemoveAttribute(DicomTags.BitsAllocated);
            newDataSet.RemoveAttribute(DicomTags.BitsAllocated);
            oldDataSet.RemoveAttribute(DicomTags.PixelData);
            newDataSet.RemoveAttribute(DicomTags.PixelData);

            var results = new List <DicomAttributeComparisonResult>();

            bool check = oldDataSet.Equals(newDataSet, ref results);

            Assert.IsTrue(check, results.Count > 0 ? CollectionUtils.FirstElement(results).Details : string.Empty);

            for (int i = 0; i < oldPd.NumberOfFrames; i++)
            {
                var frame          = oldPd.GetFrame(i);
                var convertedFrame = DicomUncompressedPixelData.ToggleBitDepth(frame, frame.Length,
                                                                               oldPd.UncompressedFrameSize,
                                                                               oldPd.BitsStored, oldPd.BitsAllocated);
                var newFrame = newPd.GetFrame(i);

                int     pixelsVarying  = 0;
                decimal totalVariation = 0.0m;
                for (int j = 0; j < convertedFrame.Length; j++)
                {
                    if (convertedFrame[j] != newFrame[j])
                    {
                        pixelsVarying++;
                        totalVariation += Math.Abs(convertedFrame[i] - newFrame[i]);
                    }
                }

                if (pixelsVarying > 0)
                {
                    Assert.Fail(String.Format(
                                    "Tag (7fe0,0010) Pixel Data: {0} of {1} pixels varying, average difference: {2}",
                                    pixelsVarying, convertedFrame.Length, totalVariation / pixelsVarying));
                }
            }
        }
        public async Task DownloadServiceLiveCloudMockConfigEndToEndTest()
        {
            var resultDirectory = CreateTemporaryDirectory();

            var(segmentationId, modelId, data) = await StartRealSegmentationAsync(@"Images\1ValidSmall\");

            var applicationEntity = new GatewayApplicationEntity("RListenerTest", 140, "localhost");

            // Create a Data receiver to receive the RT struct result
            using (var dicomDataReceiver = new ListenerDataReceiver(new ListenerDicomSaver(CreateTemporaryDirectory().FullName)))
            {
                var eventCount = 0;
                var folderPath = string.Empty;

                dicomDataReceiver.DataReceived += (sender, e) =>
                {
                    folderPath = e.FolderPath;
                    Interlocked.Increment(ref eventCount);
                };

                StartDicomDataReceiver(dicomDataReceiver, applicationEntity.Port);

                using (var pushService = CreatePushService())
                    using (var downloadService = CreateDownloadService())
                        using (var downloadQueue = downloadService.DownloadQueue)
                        {
                            pushService.Start();
                            downloadService.Start();

                            TransactionalEnqueue(
                                downloadQueue,
                                new DownloadQueueItem(
                                    segmentationId: segmentationId,
                                    modelId: modelId,
                                    resultsDirectory: resultDirectory.FullName,
                                    referenceDicomFiles: data,
                                    calledApplicationEntityTitle: applicationEntity.Title,
                                    callingApplicationEntityTitle: applicationEntity.Title,
                                    destinationApplicationEntity: applicationEntity,
                                    tagReplacementJsonString: JsonConvert.SerializeObject(_defaultTagReplacement),
                                    associationGuid: Guid.NewGuid(),
                                    associationDateTime: DateTime.UtcNow,
                                    isDryRun: false));

                            // Wait for all events to finish on the data received
                            SpinWait.SpinUntil(() => eventCount >= 3, TimeSpan.FromMinutes(3));
                        }

                dicomDataReceiver.StopServer();

                Assert.IsFalse(string.IsNullOrWhiteSpace(folderPath));

                var files = new DirectoryInfo(folderPath).GetFiles();

                // Check we have a file
                Assert.AreEqual(1, files.Length);

                var dicomFile = await DicomFile.OpenAsync(files[0].FullName);

                Assert.IsNotNull(dicomFile);

                TryDeleteDirectory(folderPath);
            }
        }
Exemple #50
0
        /// <summary>
        /// Archive the specified <see cref="ArchiveQueue"/> item.
        /// </summary>
        /// <param name="queueItem">The ArchiveQueue item to archive.</param>
        public void Run(ArchiveQueue queueItem)
        {
            using (ArchiveProcessorContext executionContext = new ArchiveProcessorContext(queueItem))
            {
                try
                {
                    if (!GetStudyStorageLocation(queueItem))
                    {
                        Platform.Log(LogLevel.Error,
                                     "Unable to find readable study storage location for archival queue request {0}.  Delaying request.",
                                     queueItem.Key);
                        queueItem.FailureDescription = "Unable to find readable study storage location for archival queue request.";
                        _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Pending, Platform.Time.AddMinutes(2));
                        return;
                    }

                    // First, check to see if we can lock the study, if not just reschedule the queue entry.
                    if (!_storageLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.Idle))
                    {
                        Platform.Log(LogLevel.Info, "Study {0} on partition {1} is currently locked, delaying archival.", _storageLocation.StudyInstanceUid, _hsmArchive.ServerPartition.Description);
                        queueItem.FailureDescription = "Study is currently locked, delaying archival.";
                        _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Pending, Platform.Time.AddMinutes(2));
                        return;
                    }

                    StudyIntegrityValidator validator = new StudyIntegrityValidator();
                    validator.ValidateStudyState("Archive", _storageLocation, StudyIntegrityValidationModes.Default);

                    using (IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
                    {
                        ILockStudy          studyLock = update.GetBroker <ILockStudy>();
                        LockStudyParameters parms     = new LockStudyParameters
                        {
                            StudyStorageKey     = queueItem.StudyStorageKey,
                            QueueStudyStateEnum = QueueStudyStateEnum.ArchiveScheduled
                        };
                        bool retVal = studyLock.Execute(parms);
                        if (!parms.Successful || !retVal)
                        {
                            Platform.Log(LogLevel.Info, "Study {0} on partition {1} failed to lock, delaying archival.", _storageLocation.StudyInstanceUid, _hsmArchive.ServerPartition.Description);
                            queueItem.FailureDescription = "Study failed to lock, delaying archival.";
                            _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Pending, Platform.Time.AddMinutes(2));
                            return;
                        }
                        update.Commit();
                    }

                    string studyXmlFile = _storageLocation.GetStudyXmlPath();

                    // Load the study Xml file, this is used to generate the list of dicom files to archive.
                    LoadStudyXml(studyXmlFile);

                    DicomFile file = LoadFileFromStudyXml();

                    string patientsName    = file.DataSet[DicomTags.PatientsName].GetString(0, string.Empty);
                    string patientId       = file.DataSet[DicomTags.PatientId].GetString(0, string.Empty);
                    string accessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty);

                    Platform.Log(LogLevel.Info,
                                 "Starting archival of study {0} for Patient {1} (PatientId:{2} A#:{3}) on Partition {4} on archive {5}",
                                 _storageLocation.StudyInstanceUid, patientsName, patientId,
                                 accessionNumber, _hsmArchive.ServerPartition.Description,
                                 _hsmArchive.PartitionArchive.Description);

                    // Use the command processor to do the archival.
                    using (ServerCommandProcessor commandProcessor = new ServerCommandProcessor("Archive"))
                    {
                        var archiveStudyCmd = new ArchiveStudyCommand(_storageLocation, _hsmArchive.HsmPath, executionContext.TempDirectory, _hsmArchive.PartitionArchive)
                        {
                            ForceCompress = HsmSettings.Default.CompressZipFiles
                        };

                        commandProcessor.AddCommand(archiveStudyCmd);
                        commandProcessor.AddCommand(new UpdateArchiveQueueItemCommand(queueItem.GetKey(), _storageLocation.GetKey(), ArchiveQueueStatusEnum.Completed));

                        StudyRulesEngine studyEngine = new StudyRulesEngine(_storageLocation, _hsmArchive.ServerPartition, _studyXml);
                        studyEngine.Apply(ServerRuleApplyTimeEnum.StudyArchived, commandProcessor);


                        if (!commandProcessor.Execute())
                        {
                            Platform.Log(LogLevel.Error,
                                         "Unexpected failure archiving study ({0}) to archive {1}: {2}, zip filename: {3}",
                                         _storageLocation.StudyInstanceUid, _hsmArchive.PartitionArchive.Description,
                                         commandProcessor.FailureReason, archiveStudyCmd.OutputZipFilePath);

                            queueItem.FailureDescription = commandProcessor.FailureReason;
                            _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Failed, Platform.Time);
                        }
                        else
                        {
                            Platform.Log(LogLevel.Info, "Successfully archived study {0} on {1} to zip {2}",
                                         _storageLocation.StudyInstanceUid,
                                         _hsmArchive.PartitionArchive.Description, archiveStudyCmd.OutputZipFilePath);
                        }

                        // Log the current FilesystemQueue settings
                        _storageLocation.LogFilesystemQueue();
                    }
                }
                catch (StudyIntegrityValidationFailure ex)
                {
                    StringBuilder error = new StringBuilder();
                    error.AppendLine(String.Format("Partition  : {0}", ex.ValidationStudyInfo.ServerAE));
                    error.AppendLine(String.Format("Patient    : {0}", ex.ValidationStudyInfo.PatientsName));
                    error.AppendLine(String.Format("Study Uid  : {0}", ex.ValidationStudyInfo.StudyInstaneUid));
                    error.AppendLine(String.Format("Accession# : {0}", ex.ValidationStudyInfo.AccessionNumber));
                    error.AppendLine(String.Format("Study Date : {0}", ex.ValidationStudyInfo.StudyDate));

                    queueItem.FailureDescription = error.ToString();
                    _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Failed, Platform.Time);
                }
                catch (Exception e)
                {
                    String msg = String.Format("Unexpected exception archiving study: {0} on {1}: {2}",
                                               _storageLocation.StudyInstanceUid, _hsmArchive.PartitionArchive.Description, e.Message);

                    Platform.Log(LogLevel.Error, e, msg);
                    queueItem.FailureDescription = msg;
                    _hsmArchive.UpdateArchiveQueue(queueItem, ArchiveQueueStatusEnum.Failed, Platform.Time);
                }
                finally
                {
                    // Unlock the Queue Entry
                    using (IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
                    {
                        ILockStudy          studyLock = update.GetBroker <ILockStudy>();
                        LockStudyParameters parms     = new LockStudyParameters
                        {
                            StudyStorageKey     = queueItem.StudyStorageKey,
                            QueueStudyStateEnum = QueueStudyStateEnum.Idle
                        };
                        bool retVal = studyLock.Execute(parms);
                        if (!parms.Successful || !retVal)
                        {
                            Platform.Log(LogLevel.Info, "Study {0} on partition {1} is failed to unlock.", _storageLocation.StudyInstanceUid, _hsmArchive.ServerPartition.Description);
                        }
                        update.Commit();
                    }
                }
            }
        }
Exemple #51
0
 /// <summary>
 /// Replaces the hashed values in the anonymised Dicom file.
 /// </summary>
 /// <param name="dicomFile">The anonymised Dicom file.</param>
 /// <param name="referenceDicomFiles">The reference dicom files and its associated anonymized representation.</param>
 /// <param name="hashedDicomTags">The dicom tags that have been hashed.</param>
 public static void ReplaceHashedValues(
     DicomFile dicomFile,
     IEnumerable <(DicomFile Original, DicomFile Anonymized)> referenceDicomFiles,
Exemple #52
0
 public LocalStudyItem(string filename)
 {
     _filename = filename;
     _dcf      = new DicomFile(filename);
     _dcf.Load(DicomReadOptions.Default | DicomReadOptions.StorePixelDataReferences);
 }
Exemple #53
0
 public UpdateStudyStatusCommand(StudyStorageLocation location, DicomFile file)
     : base("Update StudyStorage and FilesystemStudyStorage")
 {
     _location = location;
     _file     = file;
 }
Exemple #54
0
        public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
        {
            Console.WriteLine("received cstore request " + request.ToString());

            if (File.Exists("singleImage.txt"))
            {
                Console.WriteLine("now save on ./images/file.jpg");

                File.Delete("./images/file.dcm");
                var dicomFile = new DicomFile(request.File.Dataset);
                //  dicomFile.ChangeTransferSyntax(DicomTransferSyntax.JPEGProcess14SV1);
                dicomFile.Save("./images/file.dcm");
                var image = new DicomImage("./images/file.dcm");
                File.Delete("./images/file.jpg");
                image.RenderImage().AsClonedBitmap().Save("./images/file.jpg");
            }
            else // else save image to database
            {
                Console.WriteLine("now save in database" + Environment.NewLine);
                try
                {
                    // get parameters
                    string dateString = "";
                    request.Dataset.TryGetSingleValue(DicomTag.StudyDate, out dateString);
                    DateTime date             = DateTime.ParseExact(dateString, "yyyyMMdd", CultureInfo.InvariantCulture);
                    string   StudyInstanceUID = "";
                    request.Dataset.TryGetSingleValue(DicomTag.StudyInstanceUID, out StudyInstanceUID);
                    string SeriesInstanceUID = "";
                    request.Dataset.TryGetSingleValue(DicomTag.SeriesInstanceUID, out SeriesInstanceUID);
                    string SOPInstanceUID = "";
                    request.Dataset.TryGetSingleValue(DicomTag.SOPInstanceUID, out SOPInstanceUID);

                    // save in database folder
                    var pathInDatabase = Path.GetFullPath("./databaseFolder");
                    // take last two numbers, for examples seriesinstanceuid ends with .150.0
                    var    seriesUIDs = SeriesInstanceUID.Split('.');
                    string seriesUID  = seriesUIDs[seriesUIDs.Length - 2] + "." + seriesUIDs[seriesUIDs.Length - 1];
                    var    sopUIDs    = SOPInstanceUID.Split('.');
                    string sopUID     = sopUIDs[sopUIDs.Length - 2] + "." + sopUIDs[sopUIDs.Length - 1];

                    pathInDatabase = Path.Combine(pathInDatabase, date.Year.ToString(), date.Month.ToString(), date.Day.ToString(),
                                                  StudyInstanceUID, seriesUID);
                    if (!Directory.Exists(pathInDatabase))
                    {
                        Directory.CreateDirectory(pathInDatabase);
                    }
                    string imagePath = Path.Combine(pathInDatabase,
                                                    sopUID + ".dcm");
                    if (!File.Exists(imagePath))
                    {
                        request.File.Save(imagePath);
                        Console.WriteLine("received and saved a file in database");
                    }
                    else
                    {
                        Console.WriteLine("File already present in database");
                    }

                    //DicomAnonymizer.SecurityProfileOptions.
                    var profile = new DicomAnonymizer.SecurityProfile();
                    profile.PatientName = "random";
                    DicomAnonymizer anonymizer        = new DicomAnonymizer(profile);
                    DicomDataset    anonymizedDataset = anonymizer.Anonymize(request.Dataset);

                    // DICOMANONYMYZER + DICOMDIR DATABASE
                    DicomDirectoryTest s = new DicomDirectoryTest();

                    //

                    // get more data
                    string PatientName = "";
                    anonymizedDataset.TryGetSingleValue(DicomTag.PatientName, out PatientName);
                    Console.WriteLine("patient name " + PatientName);
                    string PatientID = "";
                    anonymizedDataset.TryGetSingleValue(DicomTag.PatientID, out PatientID);


                    // add entry in database
                    var study = new StudyQueryOut
                    {
                        StudyInstanceUID = StudyInstanceUID,
                        PatientID        = PatientID,
                        PatientName      = PatientName,
                        StudyDate        = date
                    };
                    using (var db = new LiteDatabase("./databaseFolder/database.db"))
                    {
                        var studies = db.GetCollection <StudyQueryOut>("studies");
                        if (studies.FindById(StudyInstanceUID) == null)
                        {
                            studies.Insert(study);
                        }
                    }
                }
                catch (Exception ec) { Console.WriteLine(ec.Message + "   " + ec.ToString()); }
            }
            return(new DicomCStoreResponse(request, DicomStatus.Success));
        }
Exemple #55
0
        public void TestRemappedReferencedSopUids()
        {
            // setup some files with unique "uids"
            DicomFile[] originals = new DicomFile[8];
            for (int n = 0; n < originals.Length; n++)
            {
                originals[n] = new DicomFile();
                originals[n].DataSet[DicomTags.StudyInstanceUid].SetStringValue((1000 + (n >> 2)).ToString());
                originals[n].DataSet[DicomTags.SeriesInstanceUid].SetStringValue((100 + (n >> 1)).ToString());
                originals[n].DataSet[DicomTags.SopInstanceUid].SetStringValue((10 + n).ToString());
                originals[n].DataSet[DicomTags.SopClassUid].SetStringValue((11111111111).ToString());
            }

            // setup up some cyclic and self references
            for (int n = 0; n < originals.Length; n++)
            {
                DicomSequenceItem sq;
                DicomFile         n0File = originals[n];
                DicomFile         n1File = originals[(n + 1) % originals.Length];
                DicomFile         n2File = originals[(n + 2) % originals.Length];
                DicomFile         n4File = originals[(n + 4) % originals.Length];

                n0File.DataSet[DicomTags.Uid].SetStringValue(n0File.DataSet[DicomTags.SopInstanceUid].ToString());
                n0File.DataSet[DicomTags.ReferencedSopInstanceUid].SetStringValue(n1File.DataSet[DicomTags.SopInstanceUid].ToString());

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(DicomUid.GenerateUid().UID);
                sq[DicomTags.TextString].SetStringValue("UID of something not in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n0File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of self");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n1File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of next file in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n1File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of next file series in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n1File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of next file study in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n2File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of 2nd next file in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n2File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of 2nd next file series in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n2File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of 2nd next file study in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n4File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of 4th next file in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n4File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of 4th next file series in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.Uid].SetStringValue(n4File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("UID of 4th next file study in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
                sq[DicomTags.TextString].SetStringValue("Sop UID of something not in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n0File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Sop UID of self");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n1File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Sop UID of next file in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n2File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Sop UID of 2nd next file in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n4File.DataSet[DicomTags.SopInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Sop UID of 4th next file in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
                sq[DicomTags.TextString].SetStringValue("Series UID of something not in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n0File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Series UID of self series");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n1File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Series UID of next file series in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n2File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Series UID of 2nd next file series in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n4File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Series UID of 4th next file series in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.StudyInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
                sq[DicomTags.TextString].SetStringValue("Study UID of something not in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.StudyInstanceUid].SetStringValue(n0File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Study UID of self study");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.StudyInstanceUid].SetStringValue(n1File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Study UID of next file study in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.StudyInstanceUid].SetStringValue(n2File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Study UID of 2nd next file study in data set");

                n0File.DataSet[DicomTags.ContentSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.StudyInstanceUid].SetStringValue(n4File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.TextString].SetStringValue("Study UID of 4th next file study in data set");

                n0File.DataSet[DicomTags.ReferencedStudySequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.TextString].SetStringValue("A more typical hierarchical sop reference to self");
                sq[DicomTags.StudyInstanceUid].SetStringValue(n0File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.ReferencedSeriesSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n0File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.ReferencedSopSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n0File.DataSet[DicomTags.SopInstanceUid].ToString());

                n0File.DataSet[DicomTags.ReferencedStudySequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.TextString].SetStringValue("A more typical hierarchical sop reference to next");
                sq[DicomTags.StudyInstanceUid].SetStringValue(n1File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.ReferencedSeriesSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n1File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.ReferencedSopSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n1File.DataSet[DicomTags.SopInstanceUid].ToString());

                n0File.DataSet[DicomTags.ReferencedStudySequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.TextString].SetStringValue("A more typical hierarchical sop reference to 2nd next");
                sq[DicomTags.StudyInstanceUid].SetStringValue(n2File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.ReferencedSeriesSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n2File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.ReferencedSopSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n2File.DataSet[DicomTags.SopInstanceUid].ToString());

                n0File.DataSet[DicomTags.ReferencedStudySequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.TextString].SetStringValue("A more typical hierarchical sop reference to 4th next");
                sq[DicomTags.StudyInstanceUid].SetStringValue(n4File.DataSet[DicomTags.StudyInstanceUid].ToString());
                sq[DicomTags.ReferencedSeriesSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.SeriesInstanceUid].SetStringValue(n4File.DataSet[DicomTags.SeriesInstanceUid].ToString());
                sq[DicomTags.ReferencedSopSequence].AddSequenceItem(sq = new DicomSequenceItem());
                sq[DicomTags.ReferencedSopInstanceUid].SetStringValue(n4File.DataSet[DicomTags.SopInstanceUid].ToString());
            }

            // copy the originals and anonymize them
            DicomFile[]     anonymized = new DicomFile[originals.Length];
            DicomAnonymizer anonymizer = new DicomAnonymizer();

            anonymizer.ValidationOptions = ValidationOptions.RelaxAllChecks;
            for (int n = 0; n < anonymized.Length; n++)
            {
                anonymized[n] = new DicomFile(string.Empty, originals[n].MetaInfo.Copy(true, true, true), originals[n].DataSet.Copy(true, true, true));
                anonymizer.Anonymize(anonymized[n]);
            }

            // generate validation dump strings - unique uids are mapped to sequential numbers
            string originalDumpValidationString   = GenerateHierarchicalUidValidationDumpString(originals);
            string anonymizedDumpValidationString = GenerateHierarchicalUidValidationDumpString(anonymized);

            // if the hierarchical structure and pattern of uids is the same, then the relationships have been preserved.
            Assert.AreEqual(originalDumpValidationString, anonymizedDumpValidationString, "Relationships of anonymized data set differ compared to those of original data set.");
        }
Exemple #56
0
        private DicomProcessingResult HandleDuplicate(string sopInstanceUid, StudyStorageLocation studyLocation, ServerCommandProcessor commandProcessor, DicomFile file)
        {
            Study study = studyLocation.Study ??
                          studyLocation.LoadStudy(ServerExecutionContext.Current.PersistenceContext);

            if (study != null)
            {
                Platform.Log(LogLevel.Info, "Received duplicate SOP {0} (A#:{1} StudyUid:{2}  Patient: {3}  ID:{4})",
                             sopInstanceUid,
                             study.AccessionNumber, study.StudyInstanceUid,
                             study.PatientsName, study.PatientId);
            }
            else
            {
                Platform.Log(LogLevel.Info,
                             "Received duplicate SOP {0} (StudyUid:{1}). Existing files haven't been processed.",
                             sopInstanceUid, studyLocation.StudyInstanceUid);
            }

            SopProcessingContext  sopProcessingContext = new SopProcessingContext(commandProcessor, studyLocation, _context.ContextID);
            DicomProcessingResult result = DuplicateSopProcessorHelper.Process(sopProcessingContext, file);

            return(result);
        }
Exemple #57
0
        private static bool SaveToFolder(string folder, string sopInstanceUid, string studyInstanceUid, DicomFile file)
        {
            using (ServerCommandProcessor commandProcessor =
                       new ServerCommandProcessor(String.Format("Saving Sop Instance to Incoming {0}", sopInstanceUid)))
            {
                string path = Path.Combine(folder, studyInstanceUid);
                commandProcessor.AddCommand(new CreateDirectoryCommand(path));

                path  = Path.Combine(path, sopInstanceUid);
                path += ServerPlatform.DicomFileExtension;

                if (File.Exists(path))
                {
                    return(false);
                }

                commandProcessor.AddCommand(new SaveDicomFileCommand(path, file, true));

                return(commandProcessor.Execute());
            }
        }
Exemple #58
0
        private static void HandleNonDuplicate(string seriesInstanceUid, string sopInstanceUid, StudyStorageLocation studyLocation, ServerCommandProcessor commandProcessor, DicomFile file, string path, bool dupImage, string extension)
        {
            commandProcessor.AddCommand(new CreateDirectoryCommand(path));

            path = Path.Combine(path, studyLocation.PartitionFolder);
            commandProcessor.AddCommand(new CreateDirectoryCommand(path));

            path = Path.Combine(path, studyLocation.StudyFolder);
            commandProcessor.AddCommand(new CreateDirectoryCommand(path));

            path = Path.Combine(path, studyLocation.StudyInstanceUid);
            commandProcessor.AddCommand(new CreateDirectoryCommand(path));

            path = Path.Combine(path, seriesInstanceUid);
            commandProcessor.AddCommand(new CreateDirectoryCommand(path));

            path  = Path.Combine(path, sopInstanceUid);
            path += ServerPlatform.DicomFileExtension;

            commandProcessor.AddCommand(new SaveDicomFileCommand(path, file, true));

            commandProcessor.AddCommand(
                new UpdateWorkQueueCommand(file, studyLocation, dupImage));

            #region SPECIAL CODE FOR TESTING
            if (Diagnostics.Settings.SimulateFileCorruption)
            {
                commandProcessor.AddCommand(new CorruptDicomFileCommand(path));
            }
            #endregion
        }
Exemple #59
0
 public Slice(string filename)
 {
     dicomFile   = DicomFile.Open(filename);
     sliceInfo   = new SliceInfo(dicomFile);
     slicePixels = null; // slicePixels remains empty until loadPixels() is called
 }
Exemple #60
0
        public DicomFile GetDataset(ZipPool pool = null)
        {
            if (IsZipReference(FullPath))
            {
                var bits = FullPath.Split('!');

                var zip = pool != null?pool.OpenRead(bits[0]) : ZipFile.Open(bits[0], ZipArchiveMode.Read);

                try
                {
                    var entry = zip.GetEntry(bits[1]);

                    if (entry == null)
                    {
                        //Maybe user has formatted it dodgy
                        //e.g. \2015\3\18\2.25.177481563701402448825228719253578992342.dcm
                        string adjusted = bits[1].TrimStart('\\', '/');

                        //if that doesn't work
                        if ((entry = zip.GetEntry(adjusted)) == null)
                        {
                            //try normalizing the slashes
                            adjusted = adjusted.Replace('\\', '/');

                            //nope we just cannot get a legit path in this zip
                            if ((entry = zip.GetEntry(adjusted)) == null)
                            {
                                throw new AmbiguousFilePathResolutionException($"Could not find path '{bits[1]}' within zip archive '{bits[0]}'");
                            }
                        }

                        //we fixed it to something that actually exists so update our state that we don't make the same mistake again
                        FullPath = bits[0] + '!' + adjusted;
                    }

                    if (!IsDicomReference(bits[1]))
                    {
                        throw new AmbiguousFilePathResolutionException("Path provided '" + FullPath + "' was to a zip file but not to a dicom file entry");
                    }

                    var buffer = ByteStreamHelper.ReadFully(entry.Open());

                    //todo: when GH-627 goes live we can use FileReadOption  https://github.com/fo-dicom/fo-dicom/blob/GH-627/DICOM/DicomFile.cs
                    //using (var memoryStream = new MemoryStream(buffer))
                    var memoryStream = new MemoryStream(buffer);

                    return(DicomFile.Open(memoryStream));
                }
                finally
                {
                    if (pool == null)
                    {
                        zip.Dispose();
                    }
                }
            }

            if (!IsDicomReference(FullPath))
            {
                throw new AmbiguousFilePathResolutionException("Path provided '" + FullPath + "' was not to either an entry in a zip file or to a dicom file");
            }

            return(DicomFile.Open(FullPath));
        }