2023-08-23

使用diompyler-core来读取剂量统计信息的方法

from dicompylercore import dicomparser, dvh, dvhcalc
rs_file = r"D:\code\temp\RS.dcm"
rd_file = r"d:\code\temp\RD_PI-V-25F.dcm"
rtss = dicomparser.DicomParser(rs_file)
rtdose = dicomparser.DicomParser(rd_file)
structures = rtss.GetStructures()

参考这个使用dicompyler-core,直接从RTStruct和RTDose文件中,读取ROI剂量统计信息的文章:
DVH参数计算(1)
GitHub - dicompyler/dicompyler-core: A library of core radiation therapy modules for DICOM RT used by dicompyler

Github上面的简单介绍:
A library of core radiation therapy modules for DICOM / DICOM RT used by dicompyler. This package includes:

  • dicomparser: parse DICOM objects in an easy-to-use manner
  • dvh: Pythonic access to dose volume histogram (DVH) data
  • dvhcalc: Independent DVH calculation using DICOM RT Dose & RT Structure Set
  • dose: Pythonic access to RT Dose data including dose summation

不知道为啥dicompyler-0.4.2以后就没更新了,现在RTplan协议貌似改了,一打开plan就奔溃,另外如果有中文目录也会崩溃。

首先是安装dicompyler-core,这里用conda虚拟环境

conda create -name dicompyler 
conda activate dicompyler
# 安装依赖包
conda install numpy pydicom matplotlib pillow shapely scikit-image scipy
# jupyter虚拟环境
conda install ipykernel
python -m ipykernel install --user --name dicompyler

在这一段的时候报错:

calcdvh = dvh.DVH.from_dicom_dvh(rtdose.ds, 10)
# Error
AttributeError: 'FileDataset' object has no attribute 'DVHSequence'

参考这个链接,是因为RTdose文件里面没有包含DVHSequence信息,建议使用dvhcalc重新计算
'FileDataset' object has no attribute 'DVHSequence' · Issue #219 · dicompyler/dicompyler-core · GitHub

计算dvh的方法:

from dicompylercore import dicomparser, dvhcalc

rs_file = r"D:\code\temp\RS.dcm"
rd_file = r"d:\code\temp\RD_PI-V-25F.dcm"

rtss = dicomparser.DicomParser(rs_file)
structures = rtss.GetStructures()
structure = list(structures.values())
for stuc in structures:
    print(f"id: {stuc:^3},   name:  {structures[stuc]['name']}")

# 创建一个空字典来保存每个结构的DVH
dvh_dict = {}

# 遍历structures字典的键
for structure_id in structures:
    # 获取结构名称
    structure_name = structures[structure_id]['name']
    print(f"Parsering dvh for {structure_name}")
    # 使用get_dvh计算DVH并保存到dvh_dict中
    dvh_dict[structure_name] = dvhcalc.get_dvh(rs_file, rd_file, structure_id)

# 此时,dvh_dict包含了所有结构的DVH,使用结构名称作为键
print(dvh_dict.keys())
#dict_keys(['Mark', 'b-ptv', 'i-ptv', 'r-ptv', 'nt', 'Ring', 'Spinal cord', 'PTV', 'Rectum', 'Bladder', 'Sigmoid', 'Bone marrow', 'Bowel bag', 'Femur_R', 'Femur_L', 'External', 'CTV'])

查看bladder的剂量统计信息

dvh_dict['Bladder']

DVH(cumulative, 4817 bins: [0.0:48.17] Gy, volume: 139.8125 cm3, name: 'Bladder', rx_dose: 0 Gy)

dvh_dict['Bladder'].describe()
Structure: Bladder
-----
DVH Type:  cumulative, abs dose: Gy, abs volume: cm3
Volume:    139.81 cm3
Max Dose:  48.17 Gy
Min Dose:  20.25 Gy
Mean Dose: 42.11 Gy
D100:      20.24 Gy
D98:       26.66 Gy
D95:       29.62 Gy
D2cc:      47.78 Gy

这里文件中得到的是cumulative dvh, absolute dose, absolute volume 的
获取剂量统计信息的方法:

#  max, min, mean
dvh_dict['Bladder'].volume
dvh_dict['Bladder'].max
dvh_dict['Bladder'].mean

# absolute dose for absolue volume
dvh_dict['Bladder'].D2cc
dvh_dict['Bladder'].D10cc
dvh_dict['Bladder'].statistic('D0.3cc').value

# relative volume for absolute dose
# 返回DVHValue类,使用.value得到值,.units得到单位
dvh_dict['Bladder'].relative_volume.statistic('V40Gy')
# dvh.DVHValue(69.89271345552079, '%')

如果出现不同的结构名称,在不建议修改原始的RTstruct文件的情况下,可以考虑使用映射来统一不同的结构名称,修改后的代码如下:

from dicompylercore import dicomparser, dvhcalc

rs_file = r"D:\code\temp\RS.dcm"
rd_file = r"d:\code\temp\RD_PI-V-25F.dcm"

rtss = dicomparser.DicomParser(rs_file)
structures = rtss.GetStructures()
structure = list(structures.values())
for stuc in structures:
    print(f"id: {stuc:^3},   name:  {structures[stuc]['name']}")

name_mapping = {
    'Rectum_1': 'Rectum',
    'Rectum_v2': 'Rectum',
    'Lung-left_variant': 'Lung Left',
    # 更多可能的名称变体和它们的标准名称
}

def get_standard_name(original_name):
    return name_mapping.get(original_name, original_name)

# 创建一个空字典来保存每个结构的DVH
dvh_dict = {}

# 遍历structures字典的键
for structure_id in structures:
    # 获取结构名称
    original_name = structures[structure_id]['name']
    standard_name = get_standard_name(original_name)

    print(f"Parsering dvh for {standard_name}")
    # 使用get_dvh计算DVH并保存到dvh_dict中
    dvh_dict[standard_name] = dvhcalc.get_dvh(rs_file, rd_file, structure_id)

# 此时,dvh_dict包含了所有结构的DVH,使用结构名称作为键
print("Done !!!!")

最后是找到的参考文档,似乎是readthedocs这个网站自动生成的。
dicompyler-core Documentation

Documentation

Be sure to check out the latest release for the user manual PDF, which is geared towards the user interface. For power-users, dvha.readthedocs.io contains detailed documentation for backend tools (e.g., if you want to perform queries with python commands).

另外,还有个

DVH Analysis的软件
GitHub - cutright/DVH-Analytics: A DICOM Database Application for Radiation Oncology

也可以批量分析RT dose
导入数据库,
计算DVH
Query 导出CSV
计算EUD,TCP和NTCP

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 京心❤️达三店:何海港 2023年8月23日 落地真经 严格就是爱,放纵既是害 正能量语录 每一颗螺丝都有标准 每...
    京心达何海港阅读 66评论 0 0
  • 大家都是白开水,你装什么优乐美没事就吃点溜溜梅,没能力别说话自不量力最可怕看清自己是谁,摆好自己的位置,管好你的脾...
    潇潇暮雨声阅读 237评论 0 3
  • 复杂的一天,情绪不稳定的天没。
    橙橙的火阅读 53评论 0 0
  • 投射我儿读书明理,修身做人,每天情绪平和稳定,阳光快乐,越来越会调节自己的情绪和压力。 投射我儿家人、他人、社会都...
    花开生两面阅读 63评论 0 0
  • 八月五号16点50分,大姐兰波尔驾鹤西去。 大姐在七月二十九号台风杜苏芮余威影响深圳时,在横风横雨之中过马路时被私...
    蓝哥饕客青阅读 774评论 0 0

友情链接更多精彩内容