void DicomArray::Print(FILE* fp) const { for (size_t i = 0; i < elements_.size(); i++) { DicomTag t = elements_[i]->GetTag(); std::string s = elements_[i]->GetValue().AsString(); printf("0x%04x 0x%04x [%s]\n", t.GetGroup(), t.GetElement(), s.c_str()); } }
void DicomArray::Print(FILE* fp) const { for (size_t i = 0; i < elements_.size(); i++) { DicomTag t = elements_[i]->GetTag(); const DicomValue& v = elements_[i]->GetValue(); std::string s = v.IsNull() ? "(null)" : v.GetContent(); printf("0x%04x 0x%04x [%s]\n", t.GetGroup(), t.GetElement(), s.c_str()); } }
void DatabaseWrapperBase::SetIdentifierTag(int64_t id, const DicomTag& tag, const std::string& value) { SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO DicomIdentifiers VALUES(?, ?, ?, ?)"); s.BindInt64(0, id); s.BindInt(1, tag.GetGroup()); s.BindInt(2, tag.GetElement()); s.BindString(3, value); s.Run(); }
TEST(DicomFormat, Tag) { ASSERT_EQ("PatientName", FromDcmtkBridge::GetName(DicomTag(0x0010, 0x0010))); DicomTag t = FromDcmtkBridge::ParseTag("SeriesDescription"); ASSERT_EQ(0x0008, t.GetGroup()); ASSERT_EQ(0x103E, t.GetElement()); t = FromDcmtkBridge::ParseTag("0020-e040"); ASSERT_EQ(0x0020, t.GetGroup()); ASSERT_EQ(0xe040, t.GetElement()); }
static void ExtractTagFromInstances(std::set<std::string>& target, ServerContext& context, const DicomTag& tag, const std::list<std::string>& instances) { // WARNING: This function is slow, as it reads the JSON file // summarizing each instance of interest from the hard drive. std::string formatted = tag.Format(); for (std::list<std::string>::const_iterator it = instances.begin(); it != instances.end(); ++it) { Json::Value dicom; context.ReadJson(dicom, *it); if (dicom.isMember(formatted)) { const Json::Value& source = dicom[formatted]; if (source.type() == Json::objectValue && source.isMember("Type") && source.isMember("Value") && source["Type"].asString() == "String" && source["Value"].type() == Json::stringValue) { target.insert(source["Value"].asString()); } } } }
void DatabaseWrapperBase::LookupIdentifier(std::list<int64_t>& target, ResourceType level, const DicomTag& tag, IdentifierConstraintType type, const std::string& value) { static const char* COMMON = ("SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " "d.id = r.internalId AND r.resourceType=? AND " "d.tagGroup=? AND d.tagElement=? AND "); std::auto_ptr<SQLite::Statement> s; switch (type) { case IdentifierConstraintType_GreaterOrEqual: s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value>=?")); break; case IdentifierConstraintType_SmallerOrEqual: s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value<=?")); break; case IdentifierConstraintType_Wildcard: s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value GLOB ?")); break; case IdentifierConstraintType_Equal: default: s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value=?")); break; } assert(s.get() != NULL); s->BindInt(0, level); s->BindInt(1, tag.GetGroup()); s->BindInt(2, tag.GetElement()); s->BindString(3, value); target.clear(); while (s->Step()) { target.push_back(s->ColumnInt64(0)); } }
DcmTagKey ToDcmtkBridge::Convert(const DicomTag& tag) { return DcmTagKey(tag.GetGroup(), tag.GetElement()); }
void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, const DicomMap& input, const std::list<DicomTag>& sequencesToReturn, const std::string& remoteIp, const std::string& remoteAet, const std::string& calledAet) { /** * Ensure that the remote modality is known to Orthanc. **/ RemoteModalityParameters modality; if (!Configuration::LookupDicomModalityUsingAETitle(modality, remoteAet)) { throw OrthancException(ErrorCode_UnknownModality); } bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false); /** * Possibly apply the user-supplied Lua filter. **/ DicomMap lua; const DicomMap* filteredInput = &input; if (ApplyLuaFilter(lua, input, remoteIp, remoteAet, calledAet)) { filteredInput = &lua; } /** * Retrieve the query level. **/ assert(filteredInput != NULL); const DicomValue* levelTmp = filteredInput->TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL); if (levelTmp == NULL || levelTmp->IsNull() || levelTmp->IsBinary()) { LOG(ERROR) << "C-FIND request without the tag 0008,0052 (QueryRetrieveLevel)"; throw OrthancException(ErrorCode_BadRequest); } ResourceType level = StringToResourceType(levelTmp->GetContent().c_str()); if (level != ResourceType_Patient && level != ResourceType_Study && level != ResourceType_Series && level != ResourceType_Instance) { throw OrthancException(ErrorCode_NotImplemented); } DicomArray query(*filteredInput); LOG(INFO) << "DICOM C-Find request at level: " << EnumerationToString(level); for (size_t i = 0; i < query.GetSize(); i++) { if (!query.GetElement(i).GetValue().IsNull()) { LOG(INFO) << " " << query.GetElement(i).GetTag() << " " << FromDcmtkBridge::GetName(query.GetElement(i).GetTag()) << " = " << query.GetElement(i).GetValue().GetContent(); } } for (std::list<DicomTag>::const_iterator it = sequencesToReturn.begin(); it != sequencesToReturn.end(); ++it) { LOG(INFO) << " (" << it->Format() << ") " << FromDcmtkBridge::GetName(*it) << " : sequence tag whose content will be copied"; } /** * Build up the query object. **/ LookupResource finder(level); for (size_t i = 0; i < query.GetSize(); i++) { const DicomTag tag = query.GetElement(i).GetTag(); if (query.GetElement(i).GetValue().IsNull() || tag == DICOM_TAG_QUERY_RETRIEVE_LEVEL || tag == DICOM_TAG_SPECIFIC_CHARACTER_SET) { continue; } std::string value = query.GetElement(i).GetValue().GetContent(); if (value.size() == 0) { // An empty string corresponds to a "*" wildcard constraint, so we ignore it continue; } if (FilterQueryTag(value, level, tag, modality.GetManufacturer())) { ValueRepresentation vr = FromDcmtkBridge::LookupValueRepresentation(tag); // DICOM specifies that searches must be case sensitive, except // for tags with a PN value representation bool sensitive = true; if (vr == ValueRepresentation_PersonName) { sensitive = caseSensitivePN; } finder.AddDicomConstraint(tag, value, sensitive); } else { LOG(INFO) << "Because of a patch for the manufacturer of the remote modality, " << "ignoring constraint on tag (" << tag.Format() << ") " << FromDcmtkBridge::GetName(tag); } } /** * Run the query. **/ size_t maxResults = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; std::vector<std::string> resources, instances; context_.GetIndex().FindCandidates(resources, instances, finder); assert(resources.size() == instances.size()); bool complete = true; for (size_t i = 0; i < instances.size(); i++) { Json::Value dicom; context_.ReadJson(dicom, instances[i]); if (finder.IsMatch(dicom)) { if (maxResults != 0 && answers.GetSize() >= maxResults) { complete = false; break; } else { std::auto_ptr<DicomMap> counters(ComputeCounters(context_, instances[i], level, input)); AddAnswer(answers, dicom, query, sequencesToReturn, counters.get()); } } } LOG(INFO) << "Number of matching resources: " << answers.GetSize(); answers.SetComplete(complete); }