@@ -1260,7 +1260,7 @@ def dicom_deidentifier(
1260
1260
else :
1261
1261
custom_config_df = None
1262
1262
action_groups_df = pd .read_csv (
1263
- filepath_or_buffer = "./python/ tmp/action-groups-dcm.csv" ,
1263
+ filepath_or_buffer = "./tmp/action-groups-dcm.csv" ,
1264
1264
index_col = 0 ,
1265
1265
)
1266
1266
with Path ("./tmp/session-data/user-options.json" ).open () as file :
@@ -1362,6 +1362,128 @@ async def handle_submit_button_click(user_options: UserOptionsClass) -> list[Any
1362
1362
return dicom_pair_fps
1363
1363
1364
1364
1365
+ def generate_action_groups () -> None :
1366
+ threshold = 8
1367
+ acceptable_actions = {"" , "K" , "C" , "Z" , "X" }
1368
+ with request .urlopen (
1369
+ "https://dicom.nema.org/medical/dicom/current/output/chtml/part15/chapter_e.html" ,
1370
+ ) as response :
1371
+ html = response .read ()
1372
+ df_table = pd .read_html (html )[3 ].fillna ("" )
1373
+ dicom_tags = df_table ["Tag" ].str .replace ("[(,)]" , "" , regex = True ).to_list ()
1374
+ basic_profile = ["X" for i in df_table ["Basic Prof." ].to_list ()]
1375
+ retain_safe_private_option = df_table ["Rtn. Safe Priv. Opt." ].to_list ()
1376
+ retain_uids_option = df_table ["Rtn. UIDs Opt." ].to_list ()
1377
+ retain_device_identity_option = df_table ["Rtn. Dev. Id. Opt." ].to_list ()
1378
+ retain_patient_characteristics_option = [
1379
+ "K" if i == "C" else i for i in df_table ["Rtn. Pat. Chars. Opt." ].to_list ()
1380
+ ]
1381
+ retain_long_modified_dates_option = df_table ["Rtn. Long. Modif. Dates Opt." ]
1382
+ retain_description_option = [
1383
+ "K" if i == "C" else i for i in df_table ["Clean Desc. Opt." ].to_list ()
1384
+ ]
1385
+ output = [
1386
+ basic_profile ,
1387
+ retain_safe_private_option ,
1388
+ retain_uids_option ,
1389
+ retain_device_identity_option ,
1390
+ retain_patient_characteristics_option ,
1391
+ retain_long_modified_dates_option ,
1392
+ retain_description_option ,
1393
+ ]
1394
+ dicom_tag_to_nema_action = dict (zip (dicom_tags , list (map (list , zip (* output )))))
1395
+ dicom_tag_to_nema_action_df = pd .DataFrame (dicom_tag_to_nema_action ).transpose ()
1396
+ dicom_tag_to_nema_action_df .columns = [
1397
+ "Default" ,
1398
+ "Rtn. Safe Priv. Opt." ,
1399
+ "Rtn. UIDs Opt." ,
1400
+ "Rtn. Dev. Id. Opt." ,
1401
+ "Rtn. Pat. Chars. Opt." ,
1402
+ "Rtn. Long. Modif. Dates Opt." ,
1403
+ "Clean Desc. Opt." ,
1404
+ ]
1405
+ dicom_tag_to_nema_action_df .insert (
1406
+ 0 ,
1407
+ "Name" ,
1408
+ ["" for i in range (len (dicom_tag_to_nema_action_df ))],
1409
+ )
1410
+ dicom_tag_to_nema_action_df .loc ["00100010" , "Default" ] = "Z"
1411
+ dicom_tag_to_nema_action_df .loc ["00100020" , "Default" ] = "Z"
1412
+ dicom_tag_to_nema_action_df = dicom_tag_to_nema_action_df .rename (
1413
+ columns = {"Clean Desc. Opt." : "Rtn. Desc. Opt." },
1414
+ )
1415
+ dicom_tag_to_nema_action_df .insert (
1416
+ loc = 6 ,
1417
+ column = "Offset Long. Modif. Dates Opt." ,
1418
+ value = dicom_tag_to_nema_action_df ["Rtn. Long. Modif. Dates Opt." ],
1419
+ )
1420
+ dicom_tag_to_nema_action_df .insert (
1421
+ loc = 7 ,
1422
+ column = "Remove Long. Modif. Dates Opt." ,
1423
+ value = dicom_tag_to_nema_action_df ["Rtn. Long. Modif. Dates Opt." ],
1424
+ )
1425
+ dicom_tag_to_nema_action_df = dicom_tag_to_nema_action_df .replace (
1426
+ to_replace = {"Rtn. Long. Modif. Dates Opt." : "C" },
1427
+ value = "K" ,
1428
+ )
1429
+ dicom_tag_to_nema_action_df = dicom_tag_to_nema_action_df .replace (
1430
+ to_replace = {"Remove Long. Modif. Dates Opt." : "C" },
1431
+ value = "X" ,
1432
+ )
1433
+ dicom_tag_to_nema_action_df = dicom_tag_to_nema_action_df .replace (
1434
+ to_replace = {
1435
+ "Rtn. Safe Priv. Opt." : "C" ,
1436
+ "Rtn. UIDs Opt." : "C" ,
1437
+ "Rtn. Dev. Id. Opt." : "C" ,
1438
+ "Rtn. Pat. Chars. Opt." : "C" ,
1439
+ "Rtn. Desc. Opt." : "C" ,
1440
+ },
1441
+ value = "K" ,
1442
+ )
1443
+ for action in ("D" , "X/Z" , "X/Z/D" , "X/D" , "Z/D" ):
1444
+ dicom_tag_to_nema_action_df = dicom_tag_to_nema_action_df .replace (
1445
+ to_replace = action ,
1446
+ value = "X" ,
1447
+ )
1448
+ for tag_idx in dicom_tag_to_nema_action_df .index :
1449
+ tag = "(" + tag_idx [0 :4 ] + "," + tag_idx [4 :9 ] + ")"
1450
+ if len (tag_idx ) > threshold :
1451
+ if tag_idx != "ggggeeee where gggg is odd" :
1452
+ msg = "Tag index error"
1453
+ raise ValueError (msg )
1454
+ tag = "(" + tag_idx [0 :4 ] + "," + tag_idx [4 :8 ] + ")" + tag_idx [8 :]
1455
+ dicom_tag_to_nema_action_df .loc [tag_idx , "Name" ] = df_table .loc [
1456
+ df_table ["Tag" ] == tag ,
1457
+ "Attribute Name" ,
1458
+ ].item ()
1459
+ if tag_idx in ["00100010" , "00100020" ]:
1460
+ dicom_tag_to_nema_action_df .loc [tag_idx , "Default" ] = "Z"
1461
+ elif (
1462
+ "K" not in dicom_tag_to_nema_action_df .loc [tag_idx ].to_numpy ().tolist ()[1 :]
1463
+ ):
1464
+ dicom_tag_to_nema_action_df .loc [tag_idx , "Default" ] = "X"
1465
+ dicom_tag_to_nema_action_df = dicom_tag_to_nema_action_df .sort_values (by = "Name" )
1466
+
1467
+ patient_id_actions = dicom_tag_to_nema_action_df .loc ["00100010" ].to_numpy ()[2 :]
1468
+ patient_name_actions = dicom_tag_to_nema_action_df .loc ["00100020" ].to_numpy ()[2 :]
1469
+ if not (
1470
+ all (action == "" for action in patient_id_actions )
1471
+ and all (action == "" for action in patient_name_actions )
1472
+ ):
1473
+ msg = "Patient ID and name actions must remain empty except the default one"
1474
+ raise ValueError (
1475
+ msg ,
1476
+ )
1477
+
1478
+ dicom_tag_to_nema_action_arr = dicom_tag_to_nema_action_df .iloc [:, 1 :].to_numpy ()
1479
+ action_set = set (dicom_tag_to_nema_action_arr .flatten ())
1480
+ if not action_set <= acceptable_actions :
1481
+ msg = "Unacceptable values found in action table"
1482
+ raise ValueError (msg )
1483
+
1484
+ dicom_tag_to_nema_action_df .to_csv ("./tmp/action-groups-dcm.csv" )
1485
+
1486
+
1365
1487
def ndarray_size (arr : NDArray [Any ]) -> int :
1366
1488
return arr .itemsize * arr .size
1367
1489
@@ -1374,6 +1496,9 @@ def meddisc() -> None:
1374
1496
]
1375
1497
for directory in tmp_directories :
1376
1498
directory .mkdir (parents = True , exist_ok = True )
1499
+ csv_path = Path ("tmp/action-groups-dcm.csv" )
1500
+ if not csv_path .exists ():
1501
+ generate_action_groups ()
1377
1502
if os .getenv ("STAGING" ):
1378
1503
if not Path ("tmp/fullchain.pem" ).exists ():
1379
1504
subprocess .run (
0 commit comments