public AnonymizeStudyOutput AnonymizeStudy(AnonymizeStudyInput input) { // load study to anonymize IDataStoreReader reader = DataAccessLayer.GetIDataStoreReader(); IStudy study = reader.GetStudy(input.StudyInstanceUID); List<ISopInstance> sops = new List<ISopInstance>(study.GetSopInstances()); // ensure there is a valid output location if(string.IsNullOrEmpty(input.OutputDirectory)) { // create temp dir } string fullPath = Path.GetFullPath(input.OutputDirectory); if (!Directory.Exists(fullPath)) { Directory.CreateDirectory(fullPath); } // set up anonymization data StudyData studyData = new StudyData(); studyData.PatientId = input.PatientId; studyData.PatientsNameRaw = input.PatientsName; studyData.PatientsBirthDate = input.PatientsBirthDate; studyData.PatientsSex = input.PatientsSex; studyData.AccessionNumber = input.AccessionNumber; studyData.StudyDescription = input.StudyDescription; studyData.StudyDate = input.StudyDate; DicomAnonymizer anonymizer = new DicomAnonymizer(); anonymizer.StudyDataPrototype = studyData; //The default anonymizer removes the series data, so we just clone the original. anonymizer.AnonymizeSeriesDataDelegate = delegate(SeriesData original) { return original.Clone(); }; // anonymize each image in the study for (int i = 0; i < sops.Count; ++i) { ISopInstance sop = sops[i]; DicomFile file = new DicomFile(sop.GetLocationUri().LocalDiskPath); anonymizer.Anonymize(file); file.Save(string.Format("{0}\\{1}.dcm", fullPath, i)); } return new AnonymizeStudyOutput(sops.Count); }
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); } }
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; }