PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
anonymizer.h
Go to the documentation of this file.
1
12#ifndef PACS_DCM_MODIFY_ANONYMIZER_HPP
13#define PACS_DCM_MODIFY_ANONYMIZER_HPP
14
19
20#include <atomic>
21#include <chrono>
22#include <map>
23#include <string>
24#include <vector>
25
27
32public:
38 std::string map(const std::string& original_uid) {
39 auto it = mapping_.find(original_uid);
40 if (it != mapping_.end()) {
41 return it->second;
42 }
43
44 auto new_uid = generate_uid();
45 mapping_[original_uid] = new_uid;
46 return new_uid;
47 }
48
52 void clear() {
53 mapping_.clear();
54 }
55
56private:
57 std::string generate_uid() {
58 static std::atomic<uint64_t> counter{0};
59 auto now = std::chrono::system_clock::now();
60 auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
61 now.time_since_epoch()).count();
62
63 return std::string(uid_root_) + "." + std::to_string(timestamp) + "." +
64 std::to_string(++counter);
65 }
66
67 std::map<std::string, std::string> mapping_;
68 static constexpr const char* uid_root_ = "1.2.826.0.1.3680043.8.1055.2";
69};
70
76 bool replace_uids{true};
77
79 std::string patient_name_replacement{"ANONYMOUS"};
80
82 std::string patient_id_prefix{"ANON"};
83
86
88 bool remove_address{true};
89
92
94 bool remove_institution{false};
95
98
100 bool keep_private_tags{false};
101};
102
114public:
118 anonymizer() = default;
119
124 explicit anonymizer(anonymize_options opts) : options_(std::move(opts)) {}
125
131 using namespace kcenon::pacs::core;
132 using namespace kcenon::pacs::encoding;
133
134 // Patient identifying information
135 anonymize_patient_info(dataset);
136
137 // UIDs
139 anonymize_uids(dataset);
140 }
141
142 // Dates
145 }
146
147 // Referring physician
150 }
151
152 // Institution
154 dataset.remove(dicom_tag{0x0008, 0x0080}); // InstitutionName
155 dataset.remove(dicom_tag{0x0008, 0x0081}); // InstitutionAddress
156 }
157
158 // Descriptions (may contain PHI in free text)
161 dataset.remove(dicom_tag{0x0008, 0x103E}); // SeriesDescription
162 }
163
164 // Address and other contact info
166 dataset.remove(dicom_tag{0x0010, 0x1040}); // PatientAddress
167 dataset.remove(dicom_tag{0x0010, 0x2154}); // PatientTelephoneNumbers
168 }
169
170 // Remove private tags unless explicitly kept
172 remove_private_tags(dataset);
173 }
174
175 // Additional PHI tags
176 remove_additional_phi(dataset);
177 }
178
184
189 const anonymize_options& options() const { return options_; }
190
195 void set_options(anonymize_options opts) { options_ = std::move(opts); }
196
197private:
199 using namespace kcenon::pacs::core;
200 using namespace kcenon::pacs::encoding;
201
202 // Patient Name
203 if (!options_.patient_name_replacement.empty()) {
204 dataset.set_string(tags::patient_name, vr_type::PN,
206 } else {
207 dataset.remove(tags::patient_name);
208 }
209
210 // Patient ID
211 std::string patient_id = options_.patient_id_prefix +
212 std::to_string(++patient_counter_);
213 dataset.set_string(tags::patient_id, vr_type::LO, patient_id);
214
215 // Patient's Birth Name, Mother's Maiden Name
216 dataset.remove(dicom_tag{0x0010, 0x1005}); // PatientBirthName
217 dataset.remove(dicom_tag{0x0010, 0x1060}); // PatientMotherBirthName
218
219 // Other patient IDs
220 dataset.remove(dicom_tag{0x0010, 0x1000}); // OtherPatientIDs
221 dataset.remove(dicom_tag{0x0010, 0x1001}); // OtherPatientNames
222 }
223
225 using namespace kcenon::pacs::core;
226 using namespace kcenon::pacs::encoding;
227
228 // Study Instance UID
229 auto study_uid = dataset.get_string(tags::study_instance_uid);
230 if (!study_uid.empty()) {
231 dataset.set_string(tags::study_instance_uid, vr_type::UI,
232 uid_mapper_.map(study_uid));
233 }
234
235 // Series Instance UID
236 auto series_uid = dataset.get_string(tags::series_instance_uid);
237 if (!series_uid.empty()) {
238 dataset.set_string(tags::series_instance_uid, vr_type::UI,
239 uid_mapper_.map(series_uid));
240 }
241
242 // SOP Instance UID
243 auto sop_uid = dataset.get_string(tags::sop_instance_uid);
244 if (!sop_uid.empty()) {
245 dataset.set_string(tags::sop_instance_uid, vr_type::UI,
246 uid_mapper_.map(sop_uid));
247 }
248
249 // Frame of Reference UID
250 auto frame_uid = dataset.get_string(dicom_tag{0x0020, 0x0052});
251 if (!frame_uid.empty()) {
252 dataset.set_string(dicom_tag{0x0020, 0x0052}, vr_type::UI,
253 uid_mapper_.map(frame_uid));
254 }
255 }
256
258 std::vector<core::dicom_tag> private_tags;
259
260 for (const auto& [tag, element] : dataset) {
261 if (tag.is_private()) {
262 private_tags.push_back(tag);
263 }
264 }
265
266 for (const auto& tag : private_tags) {
267 dataset.remove(tag);
268 }
269 }
270
272 // Accession Number (may be linked to hospital records)
273 dataset.remove(core::dicom_tag{0x0008, 0x0050});
274
275 // Patient comments
276 dataset.remove(core::dicom_tag{0x0010, 0x4000});
277
278 // Study comments
279 dataset.remove(core::dicom_tag{0x0032, 0x4000});
280
281 // Requested Procedure Description
282 dataset.remove(core::dicom_tag{0x0032, 0x1060});
283
284 // Performed Procedure Step Description
285 dataset.remove(core::dicom_tag{0x0040, 0x0254});
286
287 // Device Serial Number
288 dataset.remove(core::dicom_tag{0x0018, 0x1000});
289 }
290
293 std::atomic<uint64_t> patient_counter_{0};
294};
295
296} // namespace kcenon::pacs::dcm_modify
297
298#endif // PACS_DCM_MODIFY_ANONYMIZER_HPP
auto remove(dicom_tag tag) -> bool
Remove an element from the dataset.
void set_string(dicom_tag tag, encoding::vr_type vr, std::string_view value)
Set a string value for the given tag.
auto get_string(dicom_tag tag, std::string_view default_value="") const -> std::string
Get the string value of an element.
DICOM Anonymizer - removes or replaces PHI from datasets.
Definition anonymizer.h:113
const anonymize_options & options() const
Get the current options.
Definition anonymizer.h:189
std::atomic< uint64_t > patient_counter_
Definition anonymizer.h:293
anonymizer()=default
Construct an anonymizer with default options.
void anonymize(core::dicom_dataset &dataset)
Anonymize a DICOM dataset in place.
Definition anonymizer.h:130
void remove_additional_phi(core::dicom_dataset &dataset)
Definition anonymizer.h:271
void anonymize_patient_info(core::dicom_dataset &dataset)
Definition anonymizer.h:198
void anonymize_uids(core::dicom_dataset &dataset)
Definition anonymizer.h:224
uid_mapper & get_uid_mapper()
Get the UID mapper for consistent UID replacement.
Definition anonymizer.h:183
anonymizer(anonymize_options opts)
Construct an anonymizer with custom options.
Definition anonymizer.h:124
void set_options(anonymize_options opts)
Set new options.
Definition anonymizer.h:195
void remove_private_tags(core::dicom_dataset &dataset)
Definition anonymizer.h:257
UID mapping for consistent anonymization across related instances.
Definition anonymizer.h:31
std::string map(const std::string &original_uid)
Get or create a replacement UID for the original UID.
Definition anonymizer.h:38
static constexpr const char * uid_root_
Definition anonymizer.h:68
std::map< std::string, std::string > mapping_
Definition anonymizer.h:67
void clear()
Clear all mappings.
Definition anonymizer.h:52
DICOM Dataset - ordered collection of Data Elements.
DICOM Tag representation (Group, Element pairs)
Compile-time constants for commonly used DICOM tags.
constexpr dicom_tag referring_physician_name
Referring Physician's Name.
constexpr dicom_tag study_description
Study Description.
constexpr dicom_tag patient_id
Patient ID.
constexpr dicom_tag sop_instance_uid
SOP Instance UID.
constexpr dicom_tag patient_birth_date
Patient's Birth Date.
constexpr dicom_tag study_instance_uid
Study Instance UID.
constexpr dicom_tag patient_name
Patient's Name.
constexpr dicom_tag series_instance_uid
Series Instance UID.
bool remove_referring_physician
Remove referring physician name.
Definition anonymizer.h:91
std::string patient_name_replacement
Replace patient name with this value (empty = remove)
Definition anonymizer.h:79
bool remove_descriptions
Remove study/series descriptions.
Definition anonymizer.h:97
bool remove_address
Remove patient address.
Definition anonymizer.h:88
bool replace_uids
Replace UIDs with new generated UIDs.
Definition anonymizer.h:76
std::string patient_id_prefix
Replace patient ID with this prefix + counter.
Definition anonymizer.h:82
bool remove_institution
Remove institution name.
Definition anonymizer.h:94
bool keep_private_tags
Keep private tags (vendor-specific)
Definition anonymizer.h:100
bool remove_birth_date
Remove patient birth date.
Definition anonymizer.h:85