53void insert_sequence(dicom_dataset& ds, dicom_tag tag,
54 std::vector<dicom_dataset> items) {
55 dicom_element seq_elem(tag, vr_type::SQ);
56 seq_elem.sequence_items() = std::move(items);
57 ds.insert(std::move(seq_elem));
60std::string current_datetime() {
61 auto now = std::chrono::system_clock::now();
62 auto time_t_now = std::chrono::system_clock::to_time_t(now);
65 gmtime_s(&tm_now, &time_t_now);
67 gmtime_r(&time_t_now, &tm_now);
70 std::strftime(buf,
sizeof(buf),
"%Y%m%d%H%M%S", &tm_now);
74std::string current_date() {
75 return current_datetime().substr(0, 8);
78std::string current_time() {
79 return current_datetime().substr(8, 6);
82dicom_dataset make_code_item(
const std::string& code_value,
83 const std::string& scheme,
105 result.
error_message =
"AI result SOP Instance UID is required";
118 "1.2.840.10008.5.1.4.1.1.88.22");
140 sr.set_string(
dicom_tag{0x0008, 0x0070}, vr_type::LO,
"");
180 auto concept_name = make_code_item(
181 "AIRA-001",
"99PACS",
"AI Result Assessment");
192 std::vector<dicom_dataset> content_items;
200 auto name = make_code_item(
"AIRA-010",
"99PACS",
"Assessment Decision");
203 auto value = make_code_item(
208 constexpr dicom_tag concept_code_sequence{0x0040, 0xA168};
209 insert_sequence(item, concept_code_sequence, {value});
211 content_items.push_back(std::move(item));
220 auto name = make_code_item(
"AIRA-020",
"99PACS",
"Assessor");
223 constexpr dicom_tag person_name{0x0040, 0xA123};
224 item.set_string(person_name, vr_type::PN, assessment.
assessor_name);
226 content_items.push_back(std::move(item));
235 auto name = make_code_item(
"AIRA-030",
"99PACS",
"Assessment Comment");
241 content_items.push_back(std::move(item));
250 auto name = make_code_item(
"AIRA-040",
"99PACS",
251 "Modification Description");
257 content_items.push_back(std::move(item));
266 auto name = make_code_item(
"AIRA-050",
"99PACS",
"Rejection Reason");
269 auto value = make_code_item(
272 assessment.
rejection->reason_description);
273 constexpr dicom_tag concept_code_sequence{0x0040, 0xA168};
274 insert_sequence(item, concept_code_sequence, {value});
276 content_items.push_back(std::move(item));
286 std::vector<dicom_dataset> ref_items;
294 ref_items.push_back(std::move(ref_item));
306 ref_items.push_back(std::move(mod_ref));
310 std::move(ref_items));
314 static constexpr const char* uid_root =
"1.2.826.0.1.3680043.2.1545.1";
315 static std::mt19937_64 gen{std::random_device{}()};
316 static std::uniform_int_distribution<uint64_t> dist;
318 auto now = std::chrono::system_clock::now();
319 auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
320 now.time_since_epoch()).count();
322 return std::string(uid_root) +
"." + std::to_string(timestamp) +
323 "." + std::to_string(dist(gen) % 100000);
336 return "AIRA-ACCEPT";
345 return "AI Result Accepted";
IHE AIRA (AI Result Assessment) - Assessment Creator Actor.
assessment_creation_result create_assessment(const ai_assessment &assessment) const
Create an assessment SR document for an AI result.
static std::string assessment_type_to_meaning(assessment_type type)
Convert assessment_type to human-readable meaning.
static std::string status_to_completion_flag(assessment_status status)
Convert assessment_status to DICOM completion flag value.
void build_referenced_sop_sequence(core::dicom_dataset &sr, const ai_assessment &assessment) const
void build_patient_module(core::dicom_dataset &sr, const ai_assessment &assessment) const
static std::string assessment_type_to_code(assessment_type type)
Convert assessment_type to DICOM coded value.
void build_sr_content(core::dicom_dataset &sr, const ai_assessment &assessment) const
std::string generate_uid() const
void set_string(dicom_tag tag, encoding::vr_type vr, std::string_view value)
Set a string value for the given tag.
Compile-time constants for commonly used DICOM tags.
assessment_type
Assessment decision made by a clinician on an AI result.
@ accept
Clinician accepts AI result as-is.
@ reject
Clinician rejects AI result with reason.
@ modify
Clinician modifies AI result (e.g., edits segmentation)
auto to_string(inference_status_code status) -> std::string
Convert inference status code to string.
assessment_status
Assessment status tracking.
@ amended
Previously finalized assessment has been amended.
@ draft
Assessment in progress, not yet finalized.
@ final_
Assessment finalized and signed off.
Complete assessment of an AI result.
std::optional< assessment_rejection > rejection
Rejection details (only for assessment_type::reject)
assessment_status status
Current status of the assessment.
assessed_result_reference ai_result
Reference to the AI result being assessed.
assessment_type type
Assessment type (accept/modify/reject)
std::optional< std::string > comment
Free-text comment about the assessment.
std::string assessor_name
Clinician who performed the assessment.
std::optional< assessment_modification > modification
Modification details (only for assessment_type::modify)
std::string study_instance_uid
Study Instance UID containing the AI result.
std::string sop_class_uid
SOP Class UID of the AI result.
std::string sop_instance_uid
SOP Instance UID of the AI result.
Result of creating an assessment SR document.
std::string assessment_uid
SOP Instance UID of the created assessment.
std::optional< core::dicom_dataset > sr_dataset
The created assessment SR dataset.
std::string error_message
Error message (if failed)
bool success
Whether creation succeeded.