# HG changeset patch # User Sebastien Jodogne # Date 1404484274 -7200 # Node ID b067017a8a5be89b801e0005fa05eb7a513504ee # Parent f3929718ea7eb042584b63b6a66362ebb0011ae2 anonymization refactoring diff -r f3929718ea7e -r b067017a8a5b Core/Lua/LuaContext.cpp --- a/Core/Lua/LuaContext.cpp Fri Jul 04 15:31:42 2014 +0200 +++ b/Core/Lua/LuaContext.cpp Fri Jul 04 16:31:14 2014 +0200 @@ -79,7 +79,7 @@ lua_pop(state, 1); } - LOG(INFO) << "Lua says: " << result; + LOG(WARNING) << "Lua says: " << result; that->log_.append(result); that->log_.append("\n"); diff -r f3929718ea7e -r b067017a8a5b OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Fri Jul 04 15:31:42 2014 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Fri Jul 04 16:31:14 2014 +0200 @@ -252,47 +252,53 @@ /** - * Compute the resulting DICOM instance and store it into the Orthanc store. + * Compute the resulting DICOM instance. **/ std::auto_ptr modified(original.Clone()); modification.Apply(*modified); + + /** + * Prepare the metadata information to associate with the + * resulting DICOM instance (AnonymizedFrom/ModifiedFrom). + **/ + + DicomInstanceHasher modifiedHasher = modified->GetHasher(); + ServerIndex::MetadataMap metadata; + + if (originalHasher.HashSeries() != modifiedHasher.HashSeries()) + { + metadata[std::make_pair(ResourceType_Series, metadataType)] = originalHasher.HashSeries(); + } + + if (originalHasher.HashStudy() != modifiedHasher.HashStudy()) + { + metadata[std::make_pair(ResourceType_Study, metadataType)] = originalHasher.HashStudy(); + } + + if (originalHasher.HashPatient() != modifiedHasher.HashPatient()) + { + metadata[std::make_pair(ResourceType_Patient, metadataType)] = originalHasher.HashPatient(); + } + + assert(*it == originalHasher.HashInstance()); + metadata[std::make_pair(ResourceType_Instance, metadataType)] = *it; + + + /** + * Store the resulting DICOM instance into the Orthanc store. + **/ + std::string modifiedInstance; - if (context.Store(modifiedInstance, *modified) != StoreStatus_Success) + if (context.Store(modifiedInstance, *modified, metadata) != StoreStatus_Success) { LOG(ERROR) << "Error while storing a modified instance " << *it; return; } - - /** - * Record metadata information (AnonymizedFrom/ModifiedFrom). - **/ - - DicomInstanceHasher modifiedHasher = modified->GetHasher(); - - if (originalHasher.HashSeries() != modifiedHasher.HashSeries()) - { - context.GetIndex().SetMetadata(modifiedHasher.HashSeries(), - metadataType, originalHasher.HashSeries()); - } - - if (originalHasher.HashStudy() != modifiedHasher.HashStudy()) - { - context.GetIndex().SetMetadata(modifiedHasher.HashStudy(), - metadataType, originalHasher.HashStudy()); - } - - if (originalHasher.HashPatient() != modifiedHasher.HashPatient()) - { - context.GetIndex().SetMetadata(modifiedHasher.HashPatient(), - metadataType, originalHasher.HashPatient()); - } - - assert(*it == originalHasher.HashInstance()); + // Sanity checks in debug mode assert(modifiedInstance == modifiedHasher.HashInstance()); - context.GetIndex().SetMetadata(modifiedInstance, metadataType, *it); /** diff -r f3929718ea7e -r b067017a8a5b OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Fri Jul 04 15:31:42 2014 +0200 +++ b/OrthancServer/ServerContext.cpp Fri Jul 04 16:31:14 2014 +0200 @@ -120,16 +120,18 @@ } - void ServerContext::ApplyOnStoredInstance(const Json::Value& simplified, - const std::string& instanceId) + void ServerContext::ApplyOnStoredInstance(const std::string& instanceId, + const Json::Value& simplifiedDicom, + const Json::Value& metadata) { LuaContextLocker locker(*this); if (locker.GetLua().IsExistingFunction(ON_STORED_INSTANCE)) { LuaFunctionCall call(locker.GetLua(), ON_STORED_INSTANCE); - call.PushJson(simplified); call.PushString(instanceId); + call.PushJson(simplifiedDicom); + call.PushJson(metadata); Json::Value result; call.ExecuteToJson(result); @@ -138,19 +140,22 @@ std::cout << result; } +#if 1 { // Autorouting test RemoteModalityParameters p = Configuration::GetModalityUsingSymbolicName("sample"); ServerJob job; ServerCommandInstance& a = job.AddCommand(new StoreScuCommand(*this, p)); - ServerCommandInstance& b = job.AddCommand(new DeleteInstanceCommand(*this)); a.AddInput(instanceId); - a.ConnectNext(b); + + /*ServerCommandInstance& b = job.AddCommand(new DeleteInstanceCommand(*this)); + a.ConnectNext(b);*/ job.SetDescription("Autorouting test"); scheduler_.Submit(job); } +#endif } @@ -158,7 +163,8 @@ size_t dicomSize, const DicomMap& dicomSummary, const Json::Value& dicomJson, - const std::string& remoteAet) + const std::string& remoteAet, + const ServerIndex::MetadataMap& metadata) { Json::Value simplified; SimplifyTags(simplified, dicomJson); @@ -186,7 +192,7 @@ attachments.push_back(dicomInfo); attachments.push_back(jsonInfo); - StoreStatus status = index_.Store(dicomSummary, attachments, remoteAet); + StoreStatus status = index_.Store(dicomSummary, attachments, remoteAet, metadata); if (status != StoreStatus_Success) { @@ -219,7 +225,12 @@ try { DicomInstanceHasher hasher(dicomSummary); - ApplyOnStoredInstance(simplified, hasher.HashInstance()); + std::string instanceId = hasher.HashInstance(); + + Json::Value metadata; + index_.GetMetadata(metadata, instanceId); + + ApplyOnStoredInstance(instanceId, simplified, metadata); } catch (OrthancException&) { @@ -329,7 +340,8 @@ StoreStatus ServerContext::Store(std::string& resultPublicId, ParsedDicomFile& dicomInstance, const char* dicomBuffer, - size_t dicomSize) + size_t dicomSize, + const ServerIndex::MetadataMap& metadata) { DicomMap dicomSummary; FromDcmtkBridge::Convert(dicomSummary, *GetDicom(dicomInstance).getDataset()); @@ -345,7 +357,7 @@ StoreStatus status = StoreStatus_Failure; if (dicomSize > 0) { - status = Store(dicomBuffer, dicomSize, dicomSummary, dicomJson, ""); + status = Store(dicomBuffer, dicomSize, dicomSummary, dicomJson, "", metadata); } return status; @@ -363,7 +375,8 @@ StoreStatus ServerContext::Store(std::string& resultPublicId, - ParsedDicomFile& dicomInstance) + ParsedDicomFile& dicomInstance, + const ServerIndex::MetadataMap& metadata) { std::string buffer; if (!FromDcmtkBridge::SaveToMemoryBuffer(buffer, GetDicom(dicomInstance).getDataset())) @@ -372,23 +385,25 @@ } if (buffer.size() == 0) - return Store(resultPublicId, dicomInstance, NULL, 0); + return Store(resultPublicId, dicomInstance, NULL, 0, metadata); else - return Store(resultPublicId, dicomInstance, &buffer[0], buffer.size()); + return Store(resultPublicId, dicomInstance, &buffer[0], buffer.size(), metadata); } StoreStatus ServerContext::Store(std::string& resultPublicId, const char* dicomBuffer, - size_t dicomSize) + size_t dicomSize, + const ServerIndex::MetadataMap& metadata) { ParsedDicomFile dicom(dicomBuffer, dicomSize); - return Store(resultPublicId, dicom, dicomBuffer, dicomSize); + return Store(resultPublicId, dicom, dicomBuffer, dicomSize, metadata); } StoreStatus ServerContext::Store(std::string& resultPublicId, - const std::string& dicomContent) + const std::string& dicomContent, + const ServerIndex::MetadataMap& metadata) { if (dicomContent.size() == 0) { @@ -396,7 +411,7 @@ } else { - return Store(resultPublicId, &dicomContent[0], dicomContent.size()); + return Store(resultPublicId, &dicomContent[0], dicomContent.size(), metadata); } } diff -r f3929718ea7e -r b067017a8a5b OrthancServer/ServerContext.h --- a/OrthancServer/ServerContext.h Fri Jul 04 15:31:42 2014 +0200 +++ b/OrthancServer/ServerContext.h Fri Jul 04 16:31:14 2014 +0200 @@ -68,8 +68,9 @@ bool ApplyReceivedInstanceFilter(const Json::Value& simplified, const std::string& remoteAet); - void ApplyOnStoredInstance(const Json::Value& simplified, - const std::string& instanceId); + void ApplyOnStoredInstance(const std::string& instanceId, + const Json::Value& simplifiedDicom, + const Json::Value& metadata); FileStorage storage_; ServerIndex index_; @@ -148,26 +149,33 @@ const void* data, size_t size); + + // TODO SIMPLIFY THESE MANY "Store" methods! StoreStatus Store(const char* dicomInstance, size_t dicomSize, const DicomMap& dicomSummary, const Json::Value& dicomJson, - const std::string& remoteAet); + const std::string& remoteAet, + const ServerIndex::MetadataMap& metadata = ServerIndex::MetadataMap()); StoreStatus Store(std::string& resultPublicId, ParsedDicomFile& dicomInstance, const char* dicomBuffer, - size_t dicomSize); + size_t dicomSize, + const ServerIndex::MetadataMap& metadata = ServerIndex::MetadataMap()); StoreStatus Store(std::string& resultPublicId, - ParsedDicomFile& dicomInstance); + ParsedDicomFile& dicomInstance, + const ServerIndex::MetadataMap& metadata = ServerIndex::MetadataMap()); StoreStatus Store(std::string& resultPublicId, const char* dicomBuffer, - size_t dicomSize); + size_t dicomSize, + const ServerIndex::MetadataMap& metadata = ServerIndex::MetadataMap()); StoreStatus Store(std::string& resultPublicId, - const std::string& dicomContent); + const std::string& dicomContent, + const ServerIndex::MetadataMap& metadata = ServerIndex::MetadataMap()); void AnswerDicomFile(RestApiOutput& output, const std::string& instancePublicId, diff -r f3929718ea7e -r b067017a8a5b OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Fri Jul 04 15:31:42 2014 +0200 +++ b/OrthancServer/ServerIndex.cpp Fri Jul 04 16:31:14 2014 +0200 @@ -384,7 +384,8 @@ StoreStatus ServerIndex::Store(const DicomMap& dicomSummary, const Attachments& attachments, - const std::string& remoteAet) + const std::string& remoteAet, + const MetadataMap* metadata) { boost::mutex::scoped_lock lock(mutex_); listener_->Reset(); @@ -519,7 +520,37 @@ db_->AddAttachment(instance, *it); } - // Attach the metadata + // Attach the user-specified metadata + if (metadata) + { + for (MetadataMap::const_iterator + it = metadata->begin(); it != metadata->end(); ++it) + { + switch (it->first.first) + { + case ResourceType_Patient: + db_->SetMetadata(patient, it->first.second, it->second); + break; + + case ResourceType_Study: + db_->SetMetadata(study, it->first.second, it->second); + break; + + case ResourceType_Series: + db_->SetMetadata(series, it->first.second, it->second); + break; + + case ResourceType_Instance: + db_->SetMetadata(instance, it->first.second, it->second); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + } + + // Attach the auto-computer metadata std::string now = Toolbox::GetNowIsoString(); db_->SetMetadata(instance, MetadataType_Instance_ReceptionDate, now); db_->SetMetadata(series, MetadataType_LastUpdate, now); @@ -1694,4 +1725,33 @@ } + bool ServerIndex::GetMetadata(Json::Value& target, + const std::string& publicId) + { + boost::mutex::scoped_lock lock(mutex_); + + target = Json::objectValue; + + ResourceType type; + int64_t id; + if (!db_->LookupResource(publicId, id, type)) + { + return false; + } + + std::list metadata; + db_->ListAvailableMetadata(metadata, id); + + for (std::list::const_iterator + it = metadata.begin(); it != metadata.end(); it++) + { + std::string key = EnumerationToString(*it); + std::string value = db_->GetMetadata(id, *it); + target[key] = value; + } + + return true; + } + + } diff -r f3929718ea7e -r b067017a8a5b OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Fri Jul 04 15:31:42 2014 +0200 +++ b/OrthancServer/ServerIndex.h Fri Jul 04 16:31:14 2014 +0200 @@ -54,6 +54,10 @@ class ServerIndex : public boost::noncopyable { + public: + typedef std::list Attachments; + typedef std::map< std::pair, std::string> MetadataMap; + private: class Transaction; struct UnstableResourcePayload; @@ -98,9 +102,12 @@ /* in */ int64_t id, /* in */ ResourceType type); + StoreStatus Store(const DicomMap& dicomSummary, + const Attachments& attachments, + const std::string& remoteAet, + const MetadataMap* metadata); + public: - typedef std::list Attachments; - ServerIndex(ServerContext& context, const std::string& dbPath); @@ -124,7 +131,18 @@ StoreStatus Store(const DicomMap& dicomSummary, const Attachments& attachments, - const std::string& remoteAet); + const std::string& remoteAet) + { + return Store(dicomSummary, attachments, remoteAet, NULL); + } + + StoreStatus Store(const DicomMap& dicomSummary, + const Attachments& attachments, + const std::string& remoteAet, + const MetadataMap& metadata) + { + return Store(dicomSummary, attachments, remoteAet, &metadata); + } void ComputeStatistics(Json::Value& target); @@ -183,6 +201,9 @@ void ListAvailableMetadata(std::list& target, const std::string& publicId); + bool GetMetadata(Json::Value& target, + const std::string& publicId); + void ListAvailableAttachments(std::list& target, const std::string& publicId, ResourceType expectedType); diff -r f3929718ea7e -r b067017a8a5b Resources/Samples/Lua/Autorouting.lua --- a/Resources/Samples/Lua/Autorouting.lua Fri Jul 04 15:31:42 2014 +0200 +++ b/Resources/Samples/Lua/Autorouting.lua Fri Jul 04 16:31:14 2014 +0200 @@ -1,5 +1,6 @@ -function OnStoredInstance(tags, instance) - PrintRecursive(tags) +function OnStoredInstance(instance, tags, metadata) + --PrintRecursive(tags) + PrintRecursive(metadata) return { { "store", instance, "pacs" }, { "delete", instance }