PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
metadata_service.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
19#pragma once
20
21#include <chrono>
22#include <cstdint>
23#include <memory>
24#include <optional>
25#include <string>
26#include <string_view>
27#include <unordered_map>
28#include <unordered_set>
29#include <vector>
30
31namespace kcenon::pacs::storage {
32class index_database;
33} // namespace kcenon::pacs::storage
34
35namespace kcenon::pacs::web {
36
48
52[[nodiscard]] std::string_view preset_to_string(metadata_preset preset);
53
57[[nodiscard]] std::optional<metadata_preset> preset_from_string(
58 std::string_view str);
59
65 std::vector<std::string> tags;
66
68 std::optional<metadata_preset> preset;
69
71 bool include_private{false};
72};
73
77struct tag_value {
79 std::string tag;
80
82 std::string value;
83
85 bool is_array{false};
86};
87
93 bool success{false};
94
96 std::string error_message;
97
99 std::unordered_map<std::string, std::string> tags;
100
103 std::unordered_map<std::string, std::string> tag_map) {
105 r.success = true;
106 r.tags = std::move(tag_map);
107 return r;
108 }
109
111 static metadata_response error(std::string message) {
113 r.success = false;
114 r.error_message = std::move(message);
115 return r;
116 }
117};
118
124 std::string sop_instance_uid;
125
127 std::optional<int> instance_number;
128
130 std::optional<double> slice_location;
131
133 std::optional<std::vector<double>> image_position_patient;
134
136 std::optional<std::string> acquisition_time;
137};
138
142enum class sort_order {
143 position,
146};
147
151[[nodiscard]] std::string_view sort_order_to_string(sort_order order);
152
156[[nodiscard]] std::optional<sort_order> sort_order_from_string(
157 std::string_view str);
158
164 bool success{false};
165
167 std::string error_message;
168
170 std::vector<sorted_instance> instances;
171
173 size_t total{0};
174
176 static sorted_instances_response ok(std::vector<sorted_instance> inst,
177 size_t count) {
179 r.success = true;
180 r.instances = std::move(inst);
181 r.total = count;
182 return r;
183 }
184
186 static sorted_instances_response error(std::string message) {
188 r.success = false;
189 r.error_message = std::move(message);
190 return r;
191 }
192};
193
199 bool success{false};
200
202 std::string error_message;
203
205 std::string previous;
206
208 std::string next;
209
211 size_t index{0};
212
214 size_t total{0};
215
217 std::string first;
218
220 std::string last;
221
225 r.success = true;
226 return r;
227 }
228
230 static navigation_info error(std::string message) {
232 r.success = false;
233 r.error_message = std::move(message);
234 return r;
235 }
236};
237
243 std::string name;
244
246 double center;
247
249 double width;
250};
251
257 bool success{false};
258
260 std::string error_message;
261
263 std::vector<double> window_center;
264
266 std::vector<double> window_width;
267
269 std::vector<std::string> window_explanations;
270
272 double rescale_slope{1.0};
273
275 double rescale_intercept{0.0};
276
278 static voi_lut_info ok() {
279 voi_lut_info r;
280 r.success = true;
281 return r;
282 }
283
285 static voi_lut_info error(std::string message) {
286 voi_lut_info r;
287 r.success = false;
288 r.error_message = std::move(message);
289 return r;
290 }
291};
292
298 bool success{false};
299
301 std::string error_message;
302
304 uint32_t total_frames{1};
305
307 std::optional<double> frame_time;
308
310 std::optional<double> frame_rate;
311
313 uint16_t rows{0};
314
316 uint16_t columns{0};
317
319 static frame_info ok() {
320 frame_info r;
321 r.success = true;
322 return r;
323 }
324
326 static frame_info error(std::string message) {
327 frame_info r;
328 r.success = false;
329 r.error_message = std::move(message);
330 return r;
331 }
332};
333
345public:
350 explicit metadata_service(
351 std::shared_ptr<storage::index_database> database);
352
355
361
362 // =========================================================================
363 // Selective Metadata Retrieval
364 // =========================================================================
365
372 [[nodiscard]] metadata_response get_metadata(
373 std::string_view sop_instance_uid,
374 const metadata_request& request);
375
381 [[nodiscard]] static std::unordered_set<std::string> get_preset_tags(
382 metadata_preset preset);
383
384 // =========================================================================
385 // Series Navigation
386 // =========================================================================
387
396 std::string_view series_uid,
398 bool ascending = true);
399
405 [[nodiscard]] navigation_info get_navigation(
406 std::string_view sop_instance_uid);
407
408 // =========================================================================
409 // Window/Level Presets
410 // =========================================================================
411
417 [[nodiscard]] static std::vector<window_level_preset>
418 get_window_level_presets(std::string_view modality);
419
425 [[nodiscard]] voi_lut_info get_voi_lut(std::string_view sop_instance_uid);
426
427 // =========================================================================
428 // Multi-frame Support
429 // =========================================================================
430
436 [[nodiscard]] frame_info get_frame_info(std::string_view sop_instance_uid);
437
438private:
440 std::shared_ptr<storage::index_database> database_;
441
447 [[nodiscard]] std::unordered_map<std::string, std::string> read_dicom_tags(
448 std::string_view file_path,
449 const std::unordered_set<std::string>& requested_tags,
450 bool include_private);
451
457 [[nodiscard]] std::optional<std::string> get_series_uid(
458 std::string_view sop_instance_uid);
459};
460
461} // namespace kcenon::pacs::web
Service for selective metadata retrieval and series navigation.
metadata_service & operator=(const metadata_service &)=delete
sorted_instances_response get_sorted_instances(std::string_view series_uid, sort_order order=sort_order::position, bool ascending=true)
Get sorted instances for a series.
metadata_service(metadata_service &&)=delete
static std::vector< window_level_preset > get_window_level_presets(std::string_view modality)
Get window/level presets for a modality.
std::shared_ptr< storage::index_database > database_
Database for instance lookups.
static std::unordered_set< std::string > get_preset_tags(metadata_preset preset)
Get tags for a specific preset.
metadata_service(const metadata_service &)=delete
Non-copyable, non-movable.
metadata_service(std::shared_ptr< storage::index_database > database)
Construct metadata service with database.
std::optional< std::string > get_series_uid(std::string_view sop_instance_uid)
Get series UID for an instance.
std::unordered_map< std::string, std::string > read_dicom_tags(std::string_view file_path, const std::unordered_set< std::string > &requested_tags, bool include_private)
Read DICOM dataset from file.
frame_info get_frame_info(std::string_view sop_instance_uid)
Get frame information for an instance.
voi_lut_info get_voi_lut(std::string_view sop_instance_uid)
Get VOI LUT info from an instance.
metadata_service & operator=(metadata_service &&)=delete
navigation_info get_navigation(std::string_view sop_instance_uid)
Get navigation info for an instance.
metadata_response get_metadata(std::string_view sop_instance_uid, const metadata_request &request)
Get selective metadata for an instance.
sort_order
Sort order for series instances.
@ instance_number
Sort by InstanceNumber.
@ position
Sort by ImagePositionPatient/SliceLocation.
@ acquisition_time
Sort by AcquisitionTime.
std::string_view preset_to_string(metadata_preset preset)
Convert preset enum to string.
std::optional< sort_order > sort_order_from_string(std::string_view str)
Parse sort order from string.
std::optional< metadata_preset > preset_from_string(std::string_view str)
Parse preset from string.
metadata_preset
Metadata preset types for common use cases.
@ image_display
Rows, Columns, Bits, PhotometricInterpretation.
@ patient_info
Patient demographics.
@ acquisition
KVP, ExposureTime, SliceThickness.
@ positioning
ImagePosition, ImageOrientation, PixelSpacing.
@ multiframe
NumberOfFrames, FrameTime.
@ window_level
WindowCenter, WindowWidth, Rescale values.
std::string_view sort_order_to_string(sort_order order)
Convert sort order enum to string.
Multi-frame information.
std::optional< double > frame_time
Frame time in milliseconds (for cine)
uint16_t columns
Image columns.
static frame_info ok()
Create a success result.
std::optional< double > frame_rate
Frame rate (frames per second)
std::string error_message
Error message if failed.
bool success
Whether the operation succeeded.
static frame_info error(std::string message)
Create an error result.
uint32_t total_frames
Total number of frames.
Parameters for selective metadata retrieval.
bool include_private
Include private tags in response.
std::vector< std::string > tags
Specific tags to retrieve (hex format: "00280010")
std::optional< metadata_preset > preset
Preset to apply.
Response for selective metadata retrieval.
static metadata_response error(std::string message)
Create an error result.
static metadata_response ok(std::unordered_map< std::string, std::string > tag_map)
Create a success result.
std::string error_message
Error message if failed.
bool success
Whether the operation succeeded.
std::unordered_map< std::string, std::string > tags
Retrieved tag values.
Navigation info for an instance.
std::string first
First instance UID.
static navigation_info error(std::string message)
Create an error result.
std::string error_message
Error message if failed.
bool success
Whether the operation succeeded.
std::string next
Next instance UID (empty if last)
std::string last
Last instance UID.
size_t total
Total instances in series.
size_t index
Current index (0-based)
std::string previous
Previous instance UID (empty if first)
static navigation_info ok()
Create a success result.
Instance info for series navigation.
std::optional< std::vector< double > > image_position_patient
Image Position Patient (if available)
std::optional< double > slice_location
Slice location (if available)
std::string sop_instance_uid
SOP Instance UID.
std::optional< std::string > acquisition_time
Acquisition time (if available)
std::optional< int > instance_number
Instance number (if available)
Response for sorted instances query.
std::vector< sorted_instance > instances
Sorted instances.
static sorted_instances_response ok(std::vector< sorted_instance > inst, size_t count)
Create a success result.
std::string error_message
Error message if failed.
static sorted_instances_response error(std::string message)
Create an error result.
bool success
Whether the operation succeeded.
size_t total
Total number of instances.
DICOM tag value in metadata response.
std::string tag
Tag in hex format (e.g., "00280010")
std::string value
Value as string (numeric values converted to string)
bool is_array
Whether this is an array/sequence (for multi-valued elements)
VOI LUT information from DICOM.
bool success
Whether the operation succeeded.
std::string error_message
Error message if failed.
std::vector< double > window_width
Window width values.
static voi_lut_info error(std::string message)
Create an error result.
double rescale_intercept
Rescale intercept.
static voi_lut_info ok()
Create a success result.
std::vector< std::string > window_explanations
Window explanations (optional descriptions)
std::vector< double > window_center
Window center values.
std::string name
Preset name (e.g., "Lung", "Bone")