Mercurial > hg > orthanc
changeset 344:cd6749e53a03
anonymization from orthanc explorer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 21 Jan 2013 13:23:26 +0100 |
parents | b1edbd636cb8 |
children | 795ce0fa8e8a |
files | OrthancExplorer/explorer.html OrthancExplorer/explorer.js OrthancServer/OrthancRestApi.cpp |
diffstat | 3 files changed, 192 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancExplorer/explorer.html Fri Jan 18 10:25:55 2013 +0100 +++ b/OrthancExplorer/explorer.html Mon Jan 21 13:23:26 2013 +0100 @@ -123,6 +123,7 @@ <p> <a href="#" data-role="button" data-icon="delete" id="study-delete">Delete this study</a> <a href="#" data-role="button" data-icon="gear" id="study-archive">Download ZIP</a> + <a href="#" data-role="button" data-icon="star" id="study-anonymize">Anonymize</a> </p> </div> </div> @@ -159,6 +160,7 @@ <a href="#" data-role="button" data-icon="search" id="series-preview">Preview this series</a> <a href="#" data-role="button" data-icon="forward" id="series-store">Store in another DICOM modality</a> <a href="#" data-role="button" data-icon="gear" id="series-archive">Download ZIP</a> + <a href="#" data-role="button" data-icon="star" id="series-anonymize">Anonymize</a> </p> </div> </div>
--- a/OrthancExplorer/explorer.js Fri Jan 18 10:25:55 2013 +0100 +++ b/OrthancExplorer/explorer.js Mon Jan 21 13:23:26 2013 +0100 @@ -144,6 +144,7 @@ url: '../' + type + '/' + uuid, dataType: 'json', async: false, + cache: false, success: function(s) { callback(s); } @@ -159,6 +160,7 @@ url: '../' + type, dataType: 'json', async: false, + cache: false, success: function(s) { uuids = s; } @@ -171,6 +173,7 @@ url: '../' + type + '/' + uuid, dataType: 'json', async: true, + cache: false, success: function(s) { resources.push(s); } @@ -324,6 +327,7 @@ url: '../system', dataType: 'json', async: false, + cache: false, success: function(s) { if (s.Name != "") { $('.orthanc-name').html('<a class="ui-link" href="explorer.html">' + s.Name + '</a> » '); @@ -385,6 +389,7 @@ type: 'GET', dataType: 'text', async: false, + cache: false, success: function (s) { var v = (s == '1') ? 'on' : 'off'; $('#protection').val(v).slider('refresh'); @@ -542,6 +547,7 @@ $.ajax({ url: '../instances/' + instance.ID + '/tags', + cache: false, dataType: 'json', success: function(s) { $('#dicom-tree').tree('loadData', ConvertForTree(s)); @@ -707,6 +713,7 @@ type: 'GET', dataType: 'json', async: false, + cache: false, success: function(modalities) { var clickedModality = ''; var items = $('<ul>') @@ -808,3 +815,54 @@ async: false }); }); + + + +function OpenAnonymizeResourceDialog(path, title) +{ + $(document).simpledialog2({ + mode: 'button', + animate: false, + headerText: title, + headerClose: true, + width: '500px', + buttons : { + 'OK': { + click: function () { + $.ajax({ + url: path + '/anonymize', + type: 'POST', + data: '{}', + dataType: 'json', + async: false, + cache: false, + success: function(s) { + $.mobile.changePage('#patient?uuid=' + s.PatientID); + } + }); + }, + icon: "delete", + theme: "c" + }, + 'Cancel': { + click: function () { + } + } + } + }); +} + +$('#instance-anonymize').live('click', function() { + OpenAnonymizeResourceDialog('../instances/' + $.mobile.pageData.uuid, + 'Anonymize this instance?'); +}); + +$('#study-anonymize').live('click', function() { + OpenAnonymizeResourceDialog('../studies/' + $.mobile.pageData.uuid, + 'Anonymize this study?'); +}); + +$('#series-anonymize').live('click', function() { + OpenAnonymizeResourceDialog('../series/' + $.mobile.pageData.uuid, + 'Anonymize this series?'); +});
--- a/OrthancServer/OrthancRestApi.cpp Fri Jan 18 10:25:55 2013 +0100 +++ b/OrthancServer/OrthancRestApi.cpp Mon Jan 21 13:23:26 2013 +0100 @@ -1166,59 +1166,70 @@ ChangeType changeType, RestApi::PostCall& call) { - RETRIEVE_CONTEXT(call); + Json::Value result = Json::objectValue; - boost::mutex::scoped_lock lock(cacheMutex_); - - typedef std::list<std::string> Instances; - Instances instances; - std::string id = call.GetUriComponent("id", ""); - context.GetIndex().GetChildInstances(instances, id); - - if (instances.size() == 0) { - return; - } + boost::mutex::scoped_lock lock(cacheMutex_); + RETRIEVE_CONTEXT(call); - replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); + typedef std::list<std::string> Instances; + Instances instances; + std::string id = call.GetUriComponent("id", ""); + context.GetIndex().GetChildInstances(instances, id); - std::string newSeriesId; - for (Instances::const_iterator it = instances.begin(); - it != instances.end(); it++) - { - LOG(INFO) << "Modifying instance " << *it; - ParsedDicomFile& original = context.GetDicomFile(*it); - std::auto_ptr<ParsedDicomFile> modified(original.Clone()); - ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); - - std::string modifiedInstance; - if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) + if (instances.size() == 0) { - LOG(ERROR) << "Error while storing a modified instance " << *it; return; } - DicomInstanceHasher modifiedHasher = modified->GetHasher(); - DicomInstanceHasher originalHasher = original.GetHasher(); + replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); + + std::string newSeriesId, newPatientId; + for (Instances::const_iterator it = instances.begin(); + it != instances.end(); it++) + { + LOG(INFO) << "Modifying instance " << *it; + ParsedDicomFile& original = context.GetDicomFile(*it); + std::auto_ptr<ParsedDicomFile> modified(original.Clone()); + ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); + + std::string modifiedInstance; + if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) + { + LOG(ERROR) << "Error while storing a modified instance " << *it; + return; + } - if (newSeriesId.size() == 0) - { - assert(id == originalHasher.HashSeries()); - newSeriesId = modifiedHasher.HashSeries(); - context.GetIndex().SetMetadata(newSeriesId, metadataType, id); + DicomInstanceHasher modifiedHasher = modified->GetHasher(); + DicomInstanceHasher originalHasher = original.GetHasher(); + + if (newSeriesId.size() == 0) + { + assert(id == originalHasher.HashSeries()); + newSeriesId = modifiedHasher.HashSeries(); + context.GetIndex().SetMetadata(newSeriesId, metadataType, id); + } + + if (newPatientId.size() == 0) + { + newPatientId = modifiedHasher.HashPatient(); + } + + assert(*it == originalHasher.HashInstance()); + assert(modifiedInstance == modifiedHasher.HashInstance()); + context.GetIndex().SetMetadata(modifiedInstance, metadataType, *it); } - assert(*it == originalHasher.HashInstance()); - assert(modifiedInstance == modifiedHasher.HashInstance()); - context.GetIndex().SetMetadata(modifiedInstance, metadataType, *it); + context.GetIndex().LogChange(changeType, newSeriesId); + + assert(newSeriesId.size() != 0); + result["Type"] = ToString(ResourceType_Series); + result["ID"] = newSeriesId; + result["Path"] = GetBasePath(ResourceType_Series, newSeriesId); + result["PatientID"] = newPatientId; } - context.GetIndex().LogChange(changeType, newSeriesId); - - assert(newSeriesId.size() != 0); - Json::Value result = Json::objectValue; - result["ID"] = newSeriesId; - result["Path"] = GetBasePath(ResourceType_Series, newSeriesId); + // Do not answer before the lock has been released call.GetOutput().AnswerJson(result); } @@ -1230,88 +1241,101 @@ ChangeType changeType, RestApi::PostCall& call) { - RETRIEVE_CONTEXT(call); - boost::mutex::scoped_lock lock(cacheMutex_); - - typedef std::list<std::string> Instances; - typedef std::map<std::string, std::string> SeriesUidMap; + Json::Value result = Json::objectValue; - Instances instances; - std::string id = call.GetUriComponent("id", ""); - context.GetIndex().GetChildInstances(instances, id); - - if (instances.size() == 0) { - return; - } - - std::string newStudyId; - replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); - - SeriesUidMap seriesUidMap; - for (Instances::const_iterator it = instances.begin(); - it != instances.end(); it++) - { - LOG(INFO) << "Modifying instance " << *it; - ParsedDicomFile& original = context.GetDicomFile(*it); + boost::mutex::scoped_lock lock(cacheMutex_); + RETRIEVE_CONTEXT(call); - std::string seriesUid; - if (!original.GetTagValue(seriesUid, DICOM_TAG_SERIES_INSTANCE_UID)) - { - throw OrthancException(ErrorCode_InternalError); - } + typedef std::list<std::string> Instances; + typedef std::map<std::string, std::string> SeriesUidMap; - bool isNewSeries; - SeriesUidMap::const_iterator it2 = seriesUidMap.find(seriesUid); - if (it2 == seriesUidMap.end()) + Instances instances; + std::string id = call.GetUriComponent("id", ""); + context.GetIndex().GetChildInstances(instances, id); + + if (instances.size() == 0) { - std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); - seriesUidMap[seriesUid] = newSeriesUid; - replacements[DICOM_TAG_SERIES_INSTANCE_UID] = newSeriesUid; - isNewSeries = true; - } - else - { - replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; - isNewSeries = false; - } - - std::auto_ptr<ParsedDicomFile> modified(original.Clone()); - ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); - - std::string modifiedInstance; - if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) - { - LOG(ERROR) << "Error while storing a modified instance " << *it; return; } - DicomInstanceHasher modifiedHasher = modified->GetHasher(); - DicomInstanceHasher originalHasher = original.GetHasher(); + std::string newPatientId; + std::string newStudyId; + replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); + + SeriesUidMap seriesUidMap; + for (Instances::const_iterator it = instances.begin(); + it != instances.end(); it++) + { + LOG(INFO) << "Modifying instance " << *it; + ParsedDicomFile& original = context.GetDicomFile(*it); + + std::string seriesUid; + if (!original.GetTagValue(seriesUid, DICOM_TAG_SERIES_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_InternalError); + } + + bool isNewSeries; + SeriesUidMap::const_iterator it2 = seriesUidMap.find(seriesUid); + if (it2 == seriesUidMap.end()) + { + std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); + seriesUidMap[seriesUid] = newSeriesUid; + replacements[DICOM_TAG_SERIES_INSTANCE_UID] = newSeriesUid; + isNewSeries = true; + } + else + { + replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; + isNewSeries = false; + } - if (isNewSeries) - { - context.GetIndex().SetMetadata - (modifiedHasher.HashSeries(), metadataType, originalHasher.HashSeries()); + std::auto_ptr<ParsedDicomFile> modified(original.Clone()); + ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); + + std::string modifiedInstance; + if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) + { + LOG(ERROR) << "Error while storing a modified instance " << *it; + return; + } + + DicomInstanceHasher modifiedHasher = modified->GetHasher(); + DicomInstanceHasher originalHasher = original.GetHasher(); + + if (isNewSeries) + { + context.GetIndex().SetMetadata + (modifiedHasher.HashSeries(), metadataType, originalHasher.HashSeries()); + } + + if (newStudyId.size() == 0) + { + newStudyId = modifiedHasher.HashStudy(); + context.GetIndex().SetMetadata(newStudyId, metadataType, originalHasher.HashStudy()); + } + + if (newPatientId.size() == 0) + { + newPatientId = modifiedHasher.HashPatient(); + } + + assert(*it == originalHasher.HashInstance()); + assert(modifiedInstance == modifiedHasher.HashInstance()); + context.GetIndex().SetMetadata(modifiedInstance, metadataType, *it); } - if (newStudyId.size() == 0) - { - newStudyId = modifiedHasher.HashStudy(); - context.GetIndex().SetMetadata(newStudyId, metadataType, originalHasher.HashStudy()); - } + context.GetIndex().LogChange(changeType, newStudyId); - assert(*it == originalHasher.HashInstance()); - assert(modifiedInstance == modifiedHasher.HashInstance()); - context.GetIndex().SetMetadata(modifiedInstance, metadataType, *it); + assert(newStudyId.size() != 0); + result["Type"] = ToString(ResourceType_Study); + result["ID"] = newStudyId; + result["Path"] = GetBasePath(ResourceType_Study, newStudyId); + result["PatientID"] = newPatientId; } - context.GetIndex().LogChange(changeType, newStudyId); - - assert(newStudyId.size() != 0); - Json::Value result = Json::objectValue; - result["ID"] = newStudyId; - result["Path"] = GetBasePath(ResourceType_Study, newStudyId); + // Do not answer before the lock has been released call.GetOutput().AnswerJson(result); }