public void Anonymize_PatientName_ShouldUseOriginalDicomEncoding() { const string fileName = "GH064.dcm"; var originalDicom = DicomFile.Open($"./Test Data/{fileName}"); var securityProfile = DicomAnonymizer.SecurityProfile.LoadProfile(null, DicomAnonymizer.SecurityProfileOptions.BasicProfile); securityProfile.PatientName = "kökö"; var dicomAnonymizer = new DicomAnonymizer(securityProfile); var anonymizedDicom = dicomAnonymizer.Anonymize(originalDicom); // Ensure that we are using valid input data for test. Assert.Equal(Encoding.ASCII, DicomEncoding.Default); Assert.NotEqual(DicomEncoding.GetEncoding(originalDicom.Dataset.GetString(DicomTag.SpecificCharacterSet)), DicomEncoding.Default); // Ensure DICOM encoding same as original. Assert.Equal(originalDicom.Dataset.GetString(DicomTag.SpecificCharacterSet), anonymizedDicom.Dataset.GetString(DicomTag.SpecificCharacterSet)); Assert.Equal("kökö", anonymizedDicom.Dataset.GetString(DicomTag.PatientName)); }
public void TestStrict() { DicomFile file = CreateTestFile(); DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.ValidationOptions = ValidationOptions.RelaxAllChecks; try { //this ought to work. anonymizer.Anonymize(file); } catch (Exception) { Assert.Fail("Not strict - no exception expected."); } anonymizer = new DicomAnonymizer(); Assert.IsTrue(anonymizer.ValidationOptions == ValidationOptions.Default); //strict by default //should throw. anonymizer.Anonymize(CreateTestFile()); }
public DicomEditorComponent() { _dicomTagData = new Table <DicomEditorTag>(); _dicomTagData.Columns.Add(new TableColumn <DicomEditorTag, string>(SR.ColumnHeadingGroupElement, delegate(DicomEditorTag d) { return(d.DisplayKey); }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return(DicomEditorTag.TagCompare(one, two, SortType.GroupElement)); })); _dicomTagData.Columns.Add(new TableColumn <DicomEditorTag, string>(SR.ColumnHeadingTagName, delegate(DicomEditorTag d) { return(d.TagName); }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return(DicomEditorTag.TagCompare(one, two, SortType.TagName)); })); _dicomTagData.Columns.Add(new TableColumn <DicomEditorTag, string>(SR.ColumnHeadingVR, delegate(DicomEditorTag d) { return(d.Vr); }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return(DicomEditorTag.TagCompare(one, two, SortType.Vr)); })); _dicomTagData.Columns.Add(new TableColumn <DicomEditorTag, string>(SR.ColumnHeadingLength, delegate(DicomEditorTag d) { return(d.Length); }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return(DicomEditorTag.TagCompare(one, two, SortType.Length)); })); _dicomTagData.Columns.Add(new TableColumn <DicomEditorTag, string>(SR.ColumnHeadingValue, delegate(DicomEditorTag d) { return(d.Value); }, delegate(DicomEditorTag d, string value) { if (d.IsEditable()) { d.Value = value; _dirtyFlags[_position] = true; EventsHelper.Fire(_tagEditedEvent, this, EventArgs.Empty); } }, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return(DicomEditorTag.TagCompare(one, two, SortType.Value)); })); _title = ""; _loadedFiles = new List <DicomFile>(); _position = 0; _dirtyFlags = new List <bool>(); _anonymizer = new DicomAnonymizer(); _anonymizer.ValidationOptions = ValidationOptions.RelaxAllChecks; }
public void AddFile_AnonymizedSeries_AllFilesAddedToSameStudySeriesNode() { var dicomFiles = GetDicomFilesFromWebZip( "https://www.creatis.insa-lyon.fr/~jpr/PUBLIC/gdcm/gdcmSampleData/Philips_Medical_Images/mr711-mr712/abd1.zip"); // Anonymize all files var anonymizer = new DicomAnonymizer(); foreach (var dicomFile in dicomFiles) { anonymizer.AnonymizeInPlace(dicomFile); } // Create DICOM directory var dicomDir = new DicomDirectory(); foreach (var dicomFile in dicomFiles) { dicomDir.AddFile(dicomFile); } var imageNodes = dicomDir.RootDirectoryRecord.LowerLevelDirectoryRecord.LowerLevelDirectoryRecord .LowerLevelDirectoryRecordCollection; }
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."); }
public void TestFileMetaInformation() { Initialize(); string oldUid = _file.DataSet[DicomTags.SopInstanceUid].ToString(); StudyData studyPrototype = CreateStudyPrototype(); DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.StudyDataPrototype = studyPrototype; anonymizer.Anonymize(_file); Assert.AreNotEqual(oldUid, _file.DataSet[DicomTags.SopInstanceUid].ToString(), "Patient Confidentiality Issue - SOP Instance Uid is not anonymized."); Assert.AreNotEqual(oldUid, _file.MetaInfo[DicomTags.MediaStorageSopInstanceUid].ToString(), "Patient Confidentiality Issue - Media Storage SOP Instance Uid is not anonymized."); Assert.AreNotEqual(oldUid, _file.MediaStorageSopInstanceUid, "Patient Confidentiality Issue - Media Storage SOP Instance Uid is not anonymized."); Assert.AreEqual(_file.DataSet[DicomTags.SopInstanceUid].ToString(), _file.MetaInfo[DicomTags.MediaStorageSopInstanceUid].ToString(), "MetaInfo Media Storage SOP Instance doesn't match DataSet SOP Instance."); Assert.AreEqual(_file.DataSet[DicomTags.SopClassUid].ToString(), _file.MetaInfo[DicomTags.MediaStorageSopClassUid].ToString(), "MetaInfo Media Storage SOP Class doesn't match DataSet SOP Class."); }
private List <SopInstanceNode> DoBuildTree() { bool doAnonymize = _anonymize; Dictionary <string, string> uidMap = new Dictionary <string, string>(); List <SopInstanceNode> sops = new List <SopInstanceNode>(); // TODO: perform some performance tests to adjust these weights float aweight = doAnonymize ? 0.45f : 0; // portion of the work to anonymize the instances float pweight = (1 - aweight) * 0.75f; // portion of the work to reassign uids float mweight = 1 - pweight - aweight; // portion of the work to remap related uids int count = _patients.Count; int now = 0; this.Progress = 0; // traverse the tree assign new instance uids foreach (PatientNode patient in _patients) { if (patient.Parent != _rootNode) { throw new NullReferenceException("Unsynchronized parent-child relationship"); } now++; foreach (StudyNode study in patient.Studies) { if (study.Parent != patient) { throw new NullReferenceException("Unsynchronized parent-child relationship"); } string studyUid = NewUid(); uidMap.Add(study.InstanceUid, studyUid); study.InstanceUid = studyUid; foreach (SeriesNode series in study.Series) { if (series.Parent != study) { throw new NullReferenceException("Unsynchronized parent-child relationship"); } string seriesUid = NewUid(); uidMap.Add(series.InstanceUid, seriesUid); series.InstanceUid = seriesUid; foreach (SopInstanceNode sop in series.Images) { if (sop.Parent != series) { throw new NullReferenceException("Unsynchronized parent-child relationship"); } string sopUid = NewUid(); uidMap.Add(sop.InstanceUid, sopUid); sop.InstanceUid = sopUid; patient.Update(sop.DicomData); study.Update(sop.DicomData, true); series.Update(sop.DicomData, true); sop.Update(sop.DicomData, true); sops.Add(sop); } } } this.Progress = mweight * now / count; } // map any uids that point to an instance that was just reassigned count = sops.Count; now = 0; foreach (SopInstanceNode sop in sops) { MapKnownUids(sop.DicomData, uidMap); now++; this.Progress = mweight * now / count; } // run the anonymizer if required if (doAnonymize) { DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.ValidationOptions = ValidationOptions.RelaxAllChecks; count = sops.Count; now = 0; foreach (SopInstanceNode sop in sops) { anonymizer.Anonymize(sop.DicomFile); SeriesNode series = sop.Parent; StudyNode study = series.Parent; PatientNode patient = study.Parent; // overwrite the anonymized data with any edited properties // anonymizer writes in new anonymized uids based on the new structure, so don't overwrite them! // instead, get the new uids and put them back into the node patient.Update(sop.DicomData); study.Update(sop.DicomData, false); study.InstanceUid = sop.DicomData[DicomTags.StudyInstanceUid].GetString(0, ""); series.Update(sop.DicomData, false); series.InstanceUid = sop.DicomData[DicomTags.SeriesInstanceUid].GetString(0, ""); sop.Update(sop.DicomData, false); sop.InstanceUid = sop.DicomData[DicomTags.SopInstanceUid].GetString(0, ""); now++; this.Progress = mweight * now / count; } } return(sops); }
public dicomInfoTools(DicomFile file, bool anonymize) { if (anonymize) { var anonymizer = new DicomAnonymizer(); anonymizer.AnonymizeInPlace(file); } dateFormat = "dd.MM.yyyy"; timeFormat = "HH:mm:ss"; if (file.Dataset.Contains(DicomTag.Columns)) { imageWidth = file.Dataset.Get <int>(DicomTag.Columns); //Debug.Log($"Image Width found in dataset: {imageWidth}."); } else { imageWidth = 512; Debug.Log($"Image Width NOT found in dataset. Defaulting to: {imageWidth}."); } imageTransferSyntax = file.Dataset.InternalTransferSyntax.UID.ToString(); if (file.Dataset.Contains(DicomTag.Rows)) { imageHeight = file.Dataset.Get <int>(DicomTag.Rows); //Debug.Log($"Image Height found in dataset: {imageHeight}."); } else { imageHeight = 512; Debug.Log($"Image Height NOT found in dataset. Defaulting to: {imageHeight}."); } if (file.Dataset.Contains(DicomTag.RescaleSlope)) { imageRescaleSlope = file.Dataset.Get <int>(DicomTag.RescaleSlope); //Debug.Log($"Image Rescale Slope found in dataset: {imageRescaleSlope}."); } else { imageRescaleSlope = 1; Debug.Log($"Image Rescale Slope NOT found in dataset. Defaulting to: {imageRescaleSlope}."); } if (file.Dataset.Contains(DicomTag.RescaleIntercept)) { imageRescaleIntercept = file.Dataset.Get <int>(DicomTag.RescaleIntercept); //Debug.Log($"Image Rescale Intercept found in dataset: {imageRescaleIntercept}."); } else { imageRescaleIntercept = -1024; Debug.Log($"Image Rescale Intercept NOT found in dataset. Defaulting to: {imageRescaleIntercept}."); } if (file.Dataset.Contains(DicomTag.WindowWidth)) { imageWindowWidth = file.Dataset.Get <int>(DicomTag.WindowWidth); //Debug.Log($"Image Window Width found in dataset: {imageWindowWidth}."); } else { imageWindowWidth = 300; Debug.Log($"Image Window Width NOT found in dataset. Defaulting to: {imageWindowWidth}."); } if (file.Dataset.Contains(DicomTag.WindowCenter)) { imageWindowCenter = file.Dataset.Get <int>(DicomTag.WindowCenter); //Debug.Log($"Image Window Center found in dataset: {imageWindowCenter}."); } else { imageWindowCenter = 100; Debug.Log($"Image Window Center NOT found in dataset. Defaulting to: {imageWindowCenter}."); } if (file.Dataset.Contains(DicomTag.ImageOrientationPatient)) { imageOrientationPatient = file.Dataset.Get <double[]>(DicomTag.ImageOrientationPatient); //Debug.Log($"Image Orientation of Patient found in dataset: {imageOrientationPatient}."); } else { imageOrientationPatient = null; Debug.Log($"Image Orientation of Patient NOT found in dataset. Defaulting to: {imageOrientationPatient}."); } if (file.Dataset.Contains(DicomTag.PatientID)) { var id = file.Dataset.Get <string>(DicomTag.PatientID, "N/A"); int num; bool isParsable = Int32.TryParse(id, out num); if (isParsable) { patientId = num; } else { patientId = 0; } } else { patientId = 0; } if (file.Dataset.Contains(DicomTag.PatientAge)) { var age = file.Dataset.Get <string>(DicomTag.PatientAge, "N/A"); age = age.Substring(0, 3); int num; bool isParsable = Int32.TryParse(age, out num); if (isParsable) { patientAge = num; } else { patientAge = 0; } } else { patientAge = 0; } if (file.Dataset.Contains(DicomTag.PatientSex)) { patientSex = file.Dataset.Get <string>(DicomTag.PatientSex, "N/A"); } else { patientSex = "N/A"; } if (file.Dataset.Contains(DicomTag.PatientName)) { patientName = file.Dataset.Get <string>(DicomTag.PatientName, "N/A"); } else { patientName = "N/A"; } if (file.Dataset.Contains(DicomTag.PatientBirthDate)) { var date = file.Dataset.Get <string>(DicomTag.PatientBirthDate, "N/A"); string format = "yyyyMMdd"; bool isFormattable = DateTime.TryParseExact(date, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime newDate); if (isFormattable) { patientBd = newDate; //Debug.Log($"{date} converts to {patientBd.ToString(dateFormat)}."); } else { patientBd = DateTime.MinValue; //Debug.Log($"{date} is not in the correct format."); } } else { patientBd = DateTime.MinValue; } if (file.Dataset.Contains(DicomTag.StudyID)) { var id = file.Dataset.Get <string>(DicomTag.StudyID, "N/A"); int num; bool isParsable = Int32.TryParse(id, out num); if (isParsable) { studyId = num; } else { studyId = 0; } } else { studyId = 0; } if (file.Dataset.Contains(DicomTag.StudyDate)) { var date = file.Dataset.Get <string>(DicomTag.StudyDate, "N/A"); string format = "yyyyMMdd"; bool isFormattable = DateTime.TryParseExact(date, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime newDate); if (isFormattable) { studyDate = newDate; //Debug.Log($"{date} converts to {studyDate.ToString(dateFormat)}."); } else { studyDate = DateTime.MinValue; //Debug.Log($"{date} is not in the correct format."); } } else { studyDate = DateTime.MinValue; } if (file.Dataset.Contains(DicomTag.StudyTime)) { var time = file.Dataset.Get <string>(DicomTag.StudyTime, "N/A"); string format = "HHmmss.ffffff"; bool isFormattable = DateTime.TryParseExact(time, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime newTime); if (isFormattable) { studyTime = newTime; //Debug.Log($"{time} converts to {newTime.ToString(timeFormat)}."); } else { studyTime = DateTime.MinValue; //Debug.Log($"{time} is not in the correct format."); } } else { studyTime = DateTime.MinValue; } if (file.Dataset.Contains(DicomTag.StudyDescription)) { studyDescription = file.Dataset.Get <string>(DicomTag.StudyDescription, "N/A"); //Debug.Log(studyDescription.Length); studyDescription = studyDescription.Remove(studyDescription.Length - 1); //Debug.Log(studyDescription.Length); } else { studyDescription = "N/A"; } if (file.Dataset.Contains(DicomTag.SeriesDescription)) { studySeriesDescription = file.Dataset.Get <string>(DicomTag.SeriesDescription, "N/A"); } else { studySeriesDescription = "N/A"; } if (file.Dataset.Contains(DicomTag.ProtocolName)) { studyProtocolName = file.Dataset.Get <string>(DicomTag.ProtocolName, "N/A"); } else { studyProtocolName = "N/A"; } if (file.Dataset.Contains(DicomTag.SliceThickness)) { var thickness = file.Dataset.Get <string>(DicomTag.SliceThickness, "N/A"); float num; bool isParsable = Single.TryParse(thickness, out num); if (isParsable) { studySliceThickness = num; } else { studySliceThickness = 0f; } } else { studySliceThickness = 0f; } if (file.Dataset.Contains(DicomTag.ReferringPhysicianName)) { studyDoctorName = file.Dataset.Get <string>(DicomTag.ReferringPhysicianName, "N/A"); } else { studyDoctorName = "N/A"; } if (file.Dataset.Contains(DicomTag.Modality)) { modality = file.Dataset.Get <string>(DicomTag.Modality, "N/A"); } else { modality = "N/A"; } if (file.Dataset.Contains(DicomTag.Manufacturer)) { modalityManufacturer = file.Dataset.Get <string>(DicomTag.Manufacturer, "N/A"); } else { modalityManufacturer = "N/A"; } orientationPatient = GetPatientOrientationString(imageOrientationPatient); //Debug.Log($"Patient orientation: {orientationPatient}"); GetDicomInfoString(); //Debug.Log($"Image frame width: {imageWidth} pixels and frame height: {imageHeight} pixels."); //Debug.Log($"Image Transfer Syntax: {imageTransferSyntax.ToString()}. Applying Decompression Transfer Syntax: {defaultDicomTransferSyntax.ToString()}"); //Debug.Log($"Image Rescale Slope: {imageRescaleSlope} and Rescale Intercept: {imageRescaleIntercept}"); }
public void TestValidatePatientsNameAllowEmpty() { Initialize(); _file.DataSet[DicomTags.PatientsName].SetStringValue("Patient^Anonymous^Mr"); StudyData studyPrototype = CreateStudyPrototype(); studyPrototype.PatientsNameRaw = ""; DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.ValidationOptions = ValidationOptions.AllowEmptyPatientName; anonymizer.StudyDataPrototype = studyPrototype; anonymizer.Anonymize(_file); }
public void TestValidatePatientsNameNotEqual() { Initialize(); _file.DataSet[DicomTags.PatientsName].SetStringValue("Patient^Anonymous^Mr"); StudyData studyPrototype = CreateStudyPrototype(); studyPrototype.PatientsNameRaw = "PATIENT^ANONYMOUS"; DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.StudyDataPrototype = studyPrototype; anonymizer.Anonymize(_file); }
public void TestPrototypes() { Initialize(); StudyData studyPrototype = new StudyData(); studyPrototype.PatientId = "123"; studyPrototype.PatientsBirthDateRaw = "19760810"; studyPrototype.PatientsNameRaw = "Patient^Anonymous"; studyPrototype.PatientsSex = "M"; studyPrototype.StudyDateRaw = "20080220"; studyPrototype.StudyDescription= "Test"; studyPrototype.StudyId = "Test"; SeriesData seriesPrototype = new SeriesData(); seriesPrototype.SeriesDescription = "Series"; seriesPrototype.ProtocolName = "Protocol"; seriesPrototype.SeriesNumber = "1"; DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.StudyDataPrototype = studyPrototype; anonymizer.SeriesDataPrototype = seriesPrototype; anonymizer.Anonymize(_file); AfterAnonymize(studyPrototype, seriesPrototype); //validate the adjusted dates. Assert.AreEqual("20080220", _anonymizedDateData.InstanceCreationDate, "Anonymized InstanceCreationDate doesn't match StudyDate"); Assert.AreEqual("20080220", _anonymizedDateData.SeriesDate, "Anonymized SeriesDate doesn't match StudyDate"); Assert.AreEqual("20080220", _anonymizedDateData.ContentDate, "Anonymized ContentDate doesn't match StudyDate"); Assert.AreEqual("20080220100406", _anonymizedDateData.AcquisitionDatetime, "Anonymized AcquisitionDatetime doesn't match StudyDate/Time"); }
public void TestSimple() { Initialize(); DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.ValidationOptions = ValidationOptions.RelaxAllChecks; anonymizer.Anonymize(_file); AfterAnonymize(new StudyData(), new SeriesData()); ValidateNullDates(_anonymizedDateData); }
public void TestStrict() { DicomFile file = CreateTestFile(); DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.ValidationOptions = ValidationOptions.RelaxAllChecks; try { //this ought to work. anonymizer.Anonymize(file); } catch(Exception) { Assert.Fail("Not strict - no exception expected."); } anonymizer = new DicomAnonymizer(); Assert.IsTrue(anonymizer.ValidationOptions == ValidationOptions.Default); //strict by default //should throw. anonymizer.Anonymize(CreateTestFile()); }
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."); }
public void TestValidateAccessionNotEqual() { Initialize(); _file.DataSet[DicomTags.AccessionNumber].SetStringValue("1234"); StudyData studyPrototype = CreateStudyPrototype(); studyPrototype.AccessionNumber = "1234"; DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.StudyDataPrototype = studyPrototype; anonymizer.Anonymize(_file); }
string WorkerFunc(Tuple <string, Tuple <int, int, int, int>, List <string> > param, BackgroundWorker worker, DoWorkEventArgs e) { List <string> lFailed = new List <string>(); string strPath = param.Item1; Tuple <int, int, int, int> lCrop = param.Item2; List <string> files = param.Item3; bool bCrop = lCrop.Item1 + lCrop.Item2 + lCrop.Item3 + lCrop.Item4 > 0 ? true : false; DicomUIDGenerator uidGen = new DicomUIDGenerator(); List <Tuple <string, string, string, string> > listDCM = new List <Tuple <string, string, string, string> >(); int i = 0, k = 0; // Randomize input list Random rand = new Random(); // For each spot in the array, pick // a random item to swap into that spot. for (k = 0; k < files.Count - 1; k++) { int j = rand.Next(k, files.Count); string temp = files[k]; files[k] = files[j]; files[j] = temp; } DateTime dt = DateTime.Now; int nSuccess = 0; foreach (string strFile in files) { i++; DicomFile file; try { file = DicomFile.Open(strFile); } catch (Exception ex) { // Transmit message back with worker? lFailed.Add(strFile); System.Diagnostics.Debug.WriteLine(ex.ToString()); continue; } string strOriginalPatientID = ""; try { strOriginalPatientID = file.Dataset.GetValue <string>(DicomTag.PatientID, 0); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } DicomAnonymizer anon = new DicomAnonymizer(); DicomFile fileAnon; try { fileAnon = anon.Anonymize(file); } catch (Exception ex) { // Transmit message back with worker? lFailed.Add(strFile); System.Diagnostics.Debug.WriteLine(ex.ToString()); continue; } DicomTag[] tagsToRemove = { DicomTag.StudyDate, DicomTag.StudyTime, DicomTag.PatientID, DicomTag.StudyID, DicomTag.StudyInstanceUID }; foreach (DicomTag d in tagsToRemove) { try { fileAnon.Dataset.Remove(d); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Error removing element: " + ex.ToString()); } } fileAnon.Dataset.Add(DicomTag.StudyInstanceUID, DicomUID.Generate()); fileAnon.Dataset.Add(DicomTag.StudyDate, dt.Year.ToString("0000") + dt.Month.ToString("00") + dt.Day.ToString("00")); fileAnon.Dataset.Add(DicomTag.StudyTime, dt.Hour.ToString("00") + dt.Minute.ToString("00") + dt.Second.ToString("00")); fileAnon.Dataset.Add(DicomTag.PatientID, i.ToString()); fileAnon.Dataset.Add(DicomTag.StudyID, i.ToString()); string strStudyID = fileAnon.Dataset.GetValue <string>(DicomTag.StudyInstanceUID, 0); try { var header = DicomPixelData.Create(fileAnon.Dataset); var pixelData = PixelDataFactory.Create(header, header.NumberOfFrames - 1); int rows = header.Height; int columns = header.Width; Array a; byte[] result; bool b16bit = false; if (pixelData is GrayscalePixelDataU16) { ushort[] pixels = ((GrayscalePixelDataU16)pixelData).Data; a = pixels; b16bit = true; } else if (pixelData is GrayscalePixelDataS16) { short[] pixels = ((GrayscalePixelDataS16)pixelData).Data; a = pixels; b16bit = true; } else if (pixelData is GrayscalePixelDataU32) { uint[] pixels = ((GrayscalePixelDataU32)pixelData).Data; a = pixels; } else if (pixelData is GrayscalePixelDataS32) { int[] pixels = ((GrayscalePixelDataS32)pixelData).Data; a = pixels; } else if (pixelData is GrayscalePixelDataU8) { byte[] pixels = ((GrayscalePixelDataU8)pixelData).Data; a = pixels; } else { throw new Exception("DICOM image format not supported (this program only supports greyscale)."); } // Can't seem to figure out the byte formatting between 16-bit greyscale DCM versus C#'s 16-bit greyscale. //b16bit = false; if (bCrop) { // Top if (lCrop.Item1 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (columns * lCrop.Item1)); Array.Copy(a, columns * lCrop.Item1, cropped, 0, cropped.Length); a = cropped; rows -= lCrop.Item1; } // Right if (lCrop.Item2 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (rows * lCrop.Item2)); for (k = 0; k < rows; k++) { Array.Copy(a, k * columns, cropped, k * (columns - lCrop.Item2), columns - lCrop.Item2); } a = cropped; columns -= lCrop.Item2; } // Bottom if (lCrop.Item3 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (columns * lCrop.Item3)); Array.Copy(a, 0, cropped, 0, cropped.Length); a = cropped; rows -= lCrop.Item3; } // Left if (lCrop.Item4 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (rows * lCrop.Item4)); for (k = 0; k < rows; k++) { Array.Copy(a, k * columns + lCrop.Item4, cropped, k * (columns - lCrop.Item4), columns - lCrop.Item4); } a = cropped; columns -= lCrop.Item4; } // Now we need to copy the Array "a" into a byte array. // But first! Should we make sure that it's actually a 16-bit array? int nBytes = a.Length * System.Runtime.InteropServices.Marshal.SizeOf(a.GetValue(0)); result = new byte[nBytes]; Buffer.BlockCopy(a, 0, result, 0, nBytes); Dicom.IO.Buffer.MemoryByteBuffer buffer = new Dicom.IO.Buffer.MemoryByteBuffer(result); DicomDataset dataset = new DicomDataset(); dataset = fileAnon.Dataset.Clone(); dataset.AddOrUpdate(DicomTag.Rows, (ushort)rows); dataset.AddOrUpdate(DicomTag.Columns, (ushort)columns); DicomPixelData newPixelData = DicomPixelData.Create(dataset, true); newPixelData.BitsStored = header.BitsStored; newPixelData.SamplesPerPixel = header.SamplesPerPixel; newPixelData.HighBit = header.HighBit; newPixelData.PhotometricInterpretation = header.PhotometricInterpretation; newPixelData.PixelRepresentation = header.PixelRepresentation; newPixelData.PlanarConfiguration = header.PlanarConfiguration; newPixelData.Height = (ushort)rows; newPixelData.Width = (ushort)columns; newPixelData.AddFrame(buffer); fileAnon = new DicomFile(dataset); } // Only do this if it's a 16bit file that we want a 16bit png for if (b16bit) { int nBytes = a.Length * System.Runtime.InteropServices.Marshal.SizeOf(a.GetValue(0)); result = new byte[nBytes]; // If we're using a format that's "16bit" but actually less, scale the values? if (header.BitsStored < header.BitsAllocated) { int nShift = header.BitsAllocated - header.BitsStored; int nFlag = (0x1 << header.BitsStored) - 1; for (k = 0; k < a.Length; k++) { a.SetValue((ushort)(((nFlag - ((ushort)a.GetValue(k) & nFlag)) << nShift) & 0xFFFF), k); } } Buffer.BlockCopy(a, 0, result, 0, nBytes); unsafe { fixed(byte *ptr = result) { using (Bitmap img16 = new Bitmap(columns, rows, 4 * ((2 * columns + 3) / 4), System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, new IntPtr(ptr))) { SaveBmp(img16, strPath + "/Anonymised/" + strStudyID + "-16bitGreyscale.tif"); //img16.Save(strPath + "/Anonymised/" + strStudyID + "-16bitGreyscale.png"); } } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Failed to crop image"); System.Diagnostics.Debug.WriteLine(ex.ToString()); } fileAnon.Save(strPath + "/Anonymised/" + strStudyID + ".dcm"); listDCM.Add(new Tuple <string, string, string, string>(i.ToString(), strStudyID, strFile, strOriginalPatientID)); var img = new DicomImage(strPath + "/Anonymised/" + strStudyID + ".dcm"); // Convert DCM to a 32-bit per pixel (8-bit per each color RGB + 8-bit unused) PNG file try { Dicom.IO.PinnedIntArray px = img.RenderImage().Pixels; int[] pxi = px.Data; byte[] result = new byte[px.ByteSize]; Buffer.BlockCopy(pxi, 0, result, 0, result.Length); unsafe { fixed(byte *ptr = result) { using (Bitmap image = new Bitmap(img.Width, img.Height, img.Width * 4, System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(ptr))) { image.Save(strPath + "/Anonymised/" + strStudyID + ".png"); } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } worker.ReportProgress(i * 100 / files.Count); nSuccess++; //Console.WriteLine("Anonymized image " + i + " (of " + nFrames + " frame" + (nFrames == 1 ? "" : "s") + "): " + strFile); } // Create a map file using (System.IO.StreamWriter file = new System.IO.StreamWriter(new FileStream(strPath + "/Anonymised/Map.csv", FileMode.Create, FileAccess.ReadWrite), Encoding.UTF8)) { file.WriteLine("NewPatientID,NewStudyInstanceUID,OriginalFile,OriginalPatientID"); foreach (Tuple <string, string, string, string> line in listDCM) { file.WriteLine(line.Item1 + "," + line.Item2 + "," + line.Item3 + "," + line.Item4); } } string strRet = nSuccess.ToString() + " images successfully anonymised, Map.csv created.\nOutput at:\n" + strPath + "\\Anonymised"; if (lFailed.Count > 0) { strRet += "\nThese files failed to anonymise:"; foreach (string sf in lFailed) { strRet += "\n" + sf; } } return(strRet); }
public void TestValidatePatientsBirthDateAllowEqual() { Initialize(); _file.DataSet[DicomTags.PatientsBirthDate].SetStringValue("19760810"); StudyData studyPrototype = CreateStudyPrototype(); studyPrototype.PatientsBirthDateRaw = "19760810"; DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.ValidationOptions = ValidationOptions.AllowEqualBirthDate; anonymizer.StudyDataPrototype = studyPrototype; anonymizer.Anonymize(_file); }
public DataTable ProcessPipelineData(DataTable toProcess, IDataLoadEventListener listener, GracefulCancellationToken cancellationToken) { //Things we ignore, Lookups, SupportingSql etc if (_extractCommand == null) { listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Ignoring non dataset command ")); return(toProcess); } //if it isn't a dicom dataset don't process it if (!toProcess.Columns.Contains(RelativeArchiveColumnName)) { listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Warning, "Dataset " + _extractCommand.DatasetBundle.DataSet + " did not contain field '" + RelativeArchiveColumnName + "' so we will not attempt to extract images")); return(toProcess); } if (_putter == null) { _putter = (IPutDicomFilesInExtractionDirectories) new ObjectConstructor().Construct(PutterType); } var projectNumber = _extractCommand.Configuration.Project.ProjectNumber.Value; var mappingServer = new MappingRepository(UIDMappingServer); var destinationDirectory = new DirectoryInfo(Path.Combine(_extractCommand.GetExtractionDirectory().FullName, "Images")); var releaseCol = _extractCommand.QueryBuilder.SelectColumns.Select(c => c.IColumn).Single(c => c.IsExtractionIdentifier); // See: ftp://medical.nema.org/medical/dicom/2011/11_15pu.pdf var flags = DicomAnonymizer.SecurityProfileOptions.BasicProfile | DicomAnonymizer.SecurityProfileOptions.CleanStructdCont | DicomAnonymizer.SecurityProfileOptions.CleanDesc | DicomAnonymizer.SecurityProfileOptions.RetainUIDs; if (RetainDates) { flags |= DicomAnonymizer.SecurityProfileOptions.RetainLongFullDates; } var profile = DicomAnonymizer.SecurityProfile.LoadProfile(null, flags); var anonymiser = new DicomAnonymizer(profile); using (var pool = new ZipPool()) { _sw.Start(); foreach (DataRow row in toProcess.Rows) { if (_errors > 0 && _errors > ErrorThreshold) { throw new Exception($"Number of errors reported ({_errors}) reached the threshold ({ErrorThreshold})"); } cancellationToken.ThrowIfAbortRequested(); var path = new AmbiguousFilePath(ArchiveRootIfAny, (string)row[RelativeArchiveColumnName]); DicomFile dicomFile; try { dicomFile = path.GetDataset(pool); } catch (Exception e) { listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Error, $"Failed to get image at path '{path.FullPath}'", e)); _errors++; continue; } //get the new patient ID var releaseId = row[releaseCol.GetRuntimeName()].ToString(); DicomDataset ds; try { ds = anonymiser.Anonymize(dicomFile.Dataset); } catch (Exception e) { listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Error, $"Failed to anonymize image at path '{path.FullPath}'", e)); _errors++; continue; } //now we want to explicitly use our own release Id regardless of what FoDicom said ds.AddOrUpdate(DicomTag.PatientID, releaseId); //rewrite the UIDs foreach (var kvp in UIDMapping.SupportedTags) { if (!ds.Contains(kvp.Key)) { continue; } var value = ds.GetValue <string>(kvp.Key, 0); //if it has a value for this UID if (value == null) { continue; } var releaseValue = mappingServer.GetOrAllocateMapping(value, projectNumber, kvp.Value); //change value in dataset ds.AddOrUpdate(kvp.Key, releaseValue); //and change value in DataTable if (toProcess.Columns.Contains(kvp.Key.DictionaryEntry.Keyword)) { row[kvp.Key.DictionaryEntry.Keyword] = releaseValue; } } var newPath = _putter.WriteOutDataset(destinationDirectory, releaseId, ds); row[RelativeArchiveColumnName] = newPath; _anonymisedImagesCount++; listener.OnProgress(this, new ProgressEventArgs("Writing ANO images", new ProgressMeasurement(_anonymisedImagesCount, ProgressType.Records), _sw.Elapsed)); } _sw.Stop(); } return(toProcess); }
public void TestValidateStudyIdNotEqual() { Initialize(); _file.DataSet[DicomTags.StudyId].SetStringValue("123"); StudyData studyPrototype = CreateStudyPrototype(); studyPrototype.StudyId = "123"; DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.StudyDataPrototype = studyPrototype; anonymizer.Anonymize(_file); }
private void Anonymize(IBackgroundTaskContext context) { //TODO (Marmot) This probably should be its own WorkItem type and have it done in the background there. var study = (StudyTableItem)context.UserState; var anonymizedInstances = new AuditedInstances(); try { context.ReportProgress(new BackgroundTaskProgress(0, SR.MessageAnonymizingStudy)); var loader = study.Server.GetService <IStudyLoader>(); int numberOfSops = loader.Start(new StudyLoaderArgs(study.StudyInstanceUid, null)); if (numberOfSops <= 0) { return; } var anonymizer = new DicomAnonymizer { StudyDataPrototype = _component.AnonymizedData }; if (_component.PreserveSeriesData) { //The default anonymizer removes the series data, so we just clone the original. anonymizer.AnonymizeSeriesDataDelegate = original => original.Clone(); } // Setup the ImportFilesUtility to perform the import var configuration = DicomServer.GetConfiguration(); // setup auditing information var result = EventResult.Success; string patientsSex = null; for (int i = 0; i < numberOfSops; ++i) { using (var sop = loader.LoadNextSop()) { if (sop != null && (_component.KeepReportsAndAttachments || !IsReportOrAttachmentSopClass(sop.SopClassUid))) { //preserve the patient sex. if (patientsSex == null) { anonymizer.StudyDataPrototype.PatientsSex = patientsSex = sop.PatientsSex ?? ""; } var localSopDataSource = sop.DataSource as ILocalSopDataSource; if (localSopDataSource != null) { string filename = string.Format("{0}.dcm", i); DicomFile file = (localSopDataSource).File; // make sure we anonymize a new instance, not the same instance that the Sop cache holds!! file = new DicomFile(filename, file.MetaInfo.Copy(), file.DataSet.Copy()); anonymizer.Anonymize(file); // TODO (CR Jun 2012): Importing each file separately? Platform.GetService((IPublishFiles w) => w.PublishLocal(new List <DicomFile> { file })); string studyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].ToString(); string patientId = file.DataSet[DicomTags.PatientId].ToString(); string patientsName = file.DataSet[DicomTags.PatientsName].ToString(); anonymizedInstances.AddInstance(patientId, patientsName, studyInstanceUid); var progressPercent = (int)Math.Floor((i + 1) / (float)numberOfSops * 100); var progressMessage = String.Format(SR.MessageAnonymizingStudy, file.MediaStorageSopInstanceUid); context.ReportProgress(new BackgroundTaskProgress(progressPercent, progressMessage)); } } } } AuditHelper.LogCreateInstances(new[] { configuration.AETitle }, anonymizedInstances, EventSource.CurrentUser, result); context.Complete(); } catch (Exception e) { AuditHelper.LogCreateInstances(new[] { string.Empty }, anonymizedInstances, EventSource.CurrentUser, EventResult.MajorFailure); context.Error(e); } }
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)); }