PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
seg_storage.cpp
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
11
12#include <algorithm>
13#include <array>
14#include <unordered_map>
15
17
18// =============================================================================
19// Transfer Syntaxes
20// =============================================================================
21
22std::vector<std::string> get_seg_transfer_syntaxes() {
23 return {
24 // Explicit VR Little Endian (preferred for interoperability)
25 "1.2.840.10008.1.2.1",
26 // Implicit VR Little Endian (universal baseline)
27 "1.2.840.10008.1.2",
28 // HTJ2K Lossless (high-throughput lossless for segmentation data)
29 "1.2.840.10008.1.2.4.201",
30 // JPEG 2000 Lossless (good for binary data)
31 "1.2.840.10008.1.2.4.90",
32 // RLE Lossless (excellent for binary segmentations)
33 "1.2.840.10008.1.2.5",
34 // JPEG Lossless
35 "1.2.840.10008.1.2.4.70"
36 };
37}
38
39// =============================================================================
40// Segmentation Type
41// =============================================================================
42
43std::string_view to_string(segmentation_type type) noexcept {
44 switch (type) {
46 return "BINARY";
48 return "FRACTIONAL";
49 }
50 return "BINARY";
51}
52
53segmentation_type parse_segmentation_type(std::string_view value) noexcept {
54 if (value == "FRACTIONAL") {
56 }
58}
59
60bool is_valid_segmentation_type(std::string_view value) noexcept {
61 return value == "BINARY" || value == "FRACTIONAL";
62}
63
64// =============================================================================
65// Segmentation Fractional Type
66// =============================================================================
67
68std::string_view to_string(segmentation_fractional_type type) noexcept {
69 switch (type) {
71 return "PROBABILITY";
73 return "OCCUPANCY";
74 }
75 return "PROBABILITY";
76}
77
79parse_segmentation_fractional_type(std::string_view value) noexcept {
80 if (value == "OCCUPANCY") {
82 }
84}
85
86// =============================================================================
87// Segment Algorithm Type
88// =============================================================================
89
90std::string_view to_string(segment_algorithm_type type) noexcept {
91 switch (type) {
93 return "AUTOMATIC";
95 return "SEMIAUTOMATIC";
97 return "MANUAL";
98 }
99 return "MANUAL";
100}
101
103parse_segment_algorithm_type(std::string_view value) noexcept {
104 if (value == "AUTOMATIC") {
106 }
107 if (value == "SEMIAUTOMATIC") {
109 }
111}
112
113bool is_valid_segment_algorithm_type(std::string_view value) noexcept {
114 return value == "AUTOMATIC" ||
115 value == "SEMIAUTOMATIC" ||
116 value == "MANUAL";
117}
118
119// =============================================================================
120// Segment Colors
121// =============================================================================
122
123namespace {
124
125// Common anatomical structure colors (CIELab values scaled to 16-bit)
126// L*: 0-100 -> 0-65535
127// a*, b*: -128 to 127 -> 0-65535 (32768 = 0)
128
129const std::unordered_map<std::string_view, segment_color> standard_colors = {
130 // Organs
131 {"Liver", {43690, 39321, 42597}}, // Brown
132 {"Kidney", {36044, 43690, 29491}}, // Dark red
133 {"Spleen", {38229, 42597, 30583}}, // Purple-red
134 {"Pancreas", {47185, 37945, 39321}}, // Tan
135 {"Heart", {32768, 49151, 32768}}, // Red
136 {"Lung", {54612, 32112, 34078}}, // Pink
137 {"Brain", {54612, 34406, 32768}}, // Pink-gray
138 {"Bone", {61166, 32768, 35389}}, // Light yellow
139 {"Muscle", {40894, 39977, 32768}}, // Brown-red
140
141 // Tumors/Lesions
142 {"Tumor", {32768, 52428, 32768}}, // Bright red
143 {"Lesion", {36044, 49151, 36044}}, // Orange-red
144 {"Nodule", {40894, 45874, 34406}}, // Orange
145
146 // Vessels
147 {"Artery", {29491, 52428, 32768}}, // Dark red
148 {"Vein", {32768, 32768, 45874}}, // Blue
149 {"Vessel", {36044, 45874, 38229}}, // Red-orange
150
151 // Other
152 {"Air", {58981, 32768, 32768}}, // Light gray
153 {"Fat", {52428, 35389, 29491}}, // Yellow
154 {"Fluid", {45874, 32768, 49151}}, // Blue
155 {"Default", {43690, 32768, 32768}} // Gray
156};
157
158} // namespace
159
160segment_color get_recommended_segment_color(std::string_view segment_label) noexcept {
161 auto it = standard_colors.find(segment_label);
162 if (it != standard_colors.end()) {
163 return it->second;
164 }
165 // Return default gray for unknown structures
166 return standard_colors.at("Default");
167}
168
169// =============================================================================
170// SOP Class Information
171// =============================================================================
172
173namespace {
174
175constexpr std::array<seg_sop_class_info, 4> seg_sop_classes = {{
176 {
178 "Segmentation Storage",
179 "Binary or fractional segmentation of medical images",
180 false,
181 false
182 },
183 {
185 "Surface Segmentation Storage",
186 "3D surface mesh segmentation",
187 false,
188 true
189 },
190 {
192 "Heightmap Segmentation Storage",
193 "Height-value based retinal layer boundary segmentation (Sup 240)",
194 false,
195 false
196 },
197 {
199 "Label Map Segmentation Storage",
200 "Non-overlapping integer label voxel classification (Sup 243)",
201 false,
202 false
203 }
204}};
205
206} // namespace
207
208std::vector<std::string> get_seg_storage_sop_classes(bool include_surface) {
209 std::vector<std::string> result;
210 result.reserve(include_surface ? 4 : 3);
211
212 for (const auto& info : seg_sop_classes) {
213 if (!info.is_surface || include_surface) {
214 result.emplace_back(info.uid);
215 }
216 }
217
218 return result;
219}
220
221const seg_sop_class_info*
222get_seg_sop_class_info(std::string_view uid) noexcept {
223 auto it = std::find_if(
224 seg_sop_classes.begin(),
225 seg_sop_classes.end(),
226 [uid](const auto& info) { return info.uid == uid; }
227 );
228
229 if (it != seg_sop_classes.end()) {
230 return &(*it);
231 }
232 return nullptr;
233}
234
235bool is_seg_storage_sop_class(std::string_view uid) noexcept {
236 return get_seg_sop_class_info(uid) != nullptr;
237}
238
239bool is_surface_segmentation_sop_class(std::string_view uid) noexcept {
241}
242
243// =============================================================================
244// Segment Category Codes
245// =============================================================================
246
247namespace {
248
249struct category_code_info {
250 std::string_view code;
251 std::string_view meaning;
252};
253
254constexpr std::array<category_code_info, 7> category_codes = {{
255 {"85756007", "Tissue"}, // SNOMED CT
256 {"123037004", "Anatomical Structure"}, // SNOMED CT
257 {"260787004", "Physical Object"}, // SNOMED CT
258 {"49755003", "Morphologically Abnormal Structure"}, // SNOMED CT
259 {"246464006", "Function"}, // SNOMED CT
260 {"272737002", "Spatial Concept"}, // SNOMED CT
261 {"91720002", "Body Substance"} // SNOMED CT
262}};
263
264} // namespace
265
266std::string_view get_segment_category_code(segment_category category) noexcept {
267 auto index = static_cast<size_t>(category);
268 if (index < category_codes.size()) {
269 return category_codes[index].code;
270 }
271 return category_codes[0].code; // Default to tissue
272}
273
274std::string_view get_segment_category_meaning(segment_category category) noexcept {
275 auto index = static_cast<size_t>(category);
276 if (index < category_codes.size()) {
277 return category_codes[index].meaning;
278 }
279 return category_codes[0].meaning;
280}
281
282} // namespace kcenon::pacs::services::sop_classes
std::string_view get_segment_category_code(segment_category category) noexcept
Get SNOMED CT code for segment category.
const seg_sop_class_info * get_seg_sop_class_info(std::string_view uid) noexcept
Get information about a specific SEG SOP Class.
constexpr std::string_view label_map_segmentation_storage_uid
Label Map Segmentation Storage SOP Class UID (Supplement 243)
Definition seg_storage.h:50
segment_algorithm_type parse_segment_algorithm_type(std::string_view value) noexcept
Parse segment algorithm type from DICOM string.
segment_algorithm_type
Segment algorithm type (0062,0008)
@ automatic
AUTOMATIC - Fully automated segmentation.
@ semiautomatic
SEMIAUTOMATIC - Semi-automated with user input.
segmentation_fractional_type parse_segmentation_fractional_type(std::string_view value) noexcept
Parse segmentation fractional type from DICOM string.
bool is_valid_segmentation_type(std::string_view value) noexcept
Check if segmentation type string is valid.
constexpr std::string_view heightmap_segmentation_storage_uid
Heightmap Segmentation Storage SOP Class UID (Supplement 240)
Definition seg_storage.h:46
bool is_surface_segmentation_sop_class(std::string_view uid) noexcept
Check if a SOP Class UID is Surface Segmentation.
segmentation_type parse_segmentation_type(std::string_view value) noexcept
Parse segmentation type from DICOM string.
std::vector< std::string > get_seg_storage_sop_classes(bool include_surface=true)
Get all SEG Storage SOP Class UIDs.
constexpr std::string_view surface_segmentation_storage_uid
Surface Segmentation Storage SOP Class UID.
Definition seg_storage.h:42
std::vector< std::string > get_seg_transfer_syntaxes()
Get recommended transfer syntaxes for SEG objects.
bool is_valid_segment_algorithm_type(std::string_view value) noexcept
Check if segment algorithm type string is valid.
segmentation_type
Segmentation type (0062,0001)
Definition seg_storage.h:79
@ binary
BINARY - Binary segmentation (0 or 1)
@ fractional
FRACTIONAL - Fractional/probabilistic segmentation.
constexpr std::string_view segmentation_storage_uid
Segmentation Storage SOP Class UID.
Definition seg_storage.h:38
bool is_seg_storage_sop_class(std::string_view uid) noexcept
Check if a SOP Class UID is a SEG Storage SOP Class.
segmentation_fractional_type
Segmentation fractional type (0062,0010)
@ probability
PROBABILITY - Values represent probability (0.0-1.0)
@ occupancy
OCCUPANCY - Values represent fractional occupancy.
segment_color get_recommended_segment_color(std::string_view segment_label) noexcept
Get recommended color for common segment types.
std::string_view get_segment_category_meaning(segment_category category) noexcept
Get code meaning for segment category.
segment_category
Common anatomical property categories (CID 7150)
std::string_view to_string(dx_photometric_interpretation interp) noexcept
Convert photometric interpretation enum to DICOM string.
std::string_view code
std::string_view meaning
Segmentation (SEG) Storage SOP Classes.
Standard segment colors for common anatomical structures.
std::string_view uid