Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.1.5 instead.
Reason given by maintainers: License terms are being clarified

ctbodycomp

CT体成分2D/3D特征提取与独立校正。支持按类别或单个名称选择基础特征,以及独立的身高、体重、BSA和骨参照校正。

安装

在本项目目录运行python -m pip install .。开发时使用python -m pip install -e .。 支持Python 3.10及以上,依赖numpy、nibabel、pandas;测试需要pytest。

四类基础特征

类别 代码 数量
形态:面积或体积 morphometry 11
一阶统计:Mean、SD、P10、P50、P90、IQR firstorder 66
组成与分布:组织比值或占比,百分比 composition 12
复合:面积或体积×平均HU composite 11
合计 100

旧脚本的8项骨参照比和8项骨参照比×HU不再混入基础输出。

组织代码:SM骨骼肌(1)、SF皮下脂肪(4)、IMF肌间脂肪(2)、VF其余内脏脂肪(3)、PVAT血管周围脂肪(6)、EAT心外膜脂肪(7)、AorticPVAT主动脉周围脂肪(8)、Bone骨(5)、CVF(6/7/8)、VF_total(3/6/7/8)、TF(2/3/4/6/7/8)。基础标签互斥。

先提取第一类,再校正

from ctbodycomp import BodyCompositionExtractor, FeatureNormalizer

extractor = BodyCompositionExtractor(
    mode="3D",
    features={"morphometry": ["SM_Volume", "SF_Volume", "Bone_Volume"]},
)
raw = extractor.execute(image="ct.nii.gz", mask="bc_mask.nii.gz")

# 只校正指定组织;原始结果与校正结果是两个独立字典。
normalizer = FeatureNormalizer(
    mode="3D", methods=["height", "weight", "bsa", "bone"], tissues=["SM", "SF"]
)
corrected = normalizer.execute(raw, height_cm=170, weight_kg=65)

校正器根据第一类形态指标计算校正指数;开启include_composite=True时,同时读取一阶Mean并计算校正指数×Mean。不读取影像,不对HU本身或组成比值二次校正。可以把提取结果保存后,换一组校正方式再次计算。骨校正需提前提取同一范围的Bone_Volume或Bone_Area。

方法 公式 2D单位 3D单位
height 原始面积/体积 ÷ 身高(m)² cm²/m² cm³/m²
weight 原始面积/体积 ÷ 体重(kg) cm²/kg cm³/kg
bsa 原始面积/体积 ÷ BSA(m²) cm²/m² cm³/m²
bone 原始面积/体积 ÷ 同范围骨面积/体积 无量纲 无量纲

2D和3D都使用身高²。默认BSA使用Mosteller公式:sqrt(height_cm * weight_kg / 3600),也可通过bsa_m2直接提供已知BSA;提供值优先,来源记录在normalizer.last_diagnostics。Mosteller公式参考:原始论文。

身高、体重、BSA需为有限正数;只选择骨校正时不需要身高体重。缺少所选方法需要的参数会抛出明确错误。骨量为0时骨校正输出NaN。CSV校正失败时保留原始特征及失败原因。

若提取全部11个形态特征且启用全部校正,height、weight、bsa各11项,bone对10个非骨组织输出,共43项。与100项基础特征分开存储。骨校正包括CVF和TF两个聚合组织,不输出恒为1的Bone/Bone。实际输出量由所选组织、特征和校正方式决定。

可选:校正指数 × 平均HU

从0.1.1开始,校正指数与校正后的复合特征统一由FeatureNormalizer管理。使用include_composite=True,同一次校正返回“指数”和“指数×同组织平均HU”,每一对相邻排列。两者均属于校正模块,与四类基础特征分开。默认不开启校正复合项。

from ctbodycomp import BodyCompositionExtractor, FeatureNormalizer

extractor = BodyCompositionExtractor(
    mode="3D",
    features={
        "morphometry": ["SM_Volume", "Bone_Volume"],
        "firstorder": ["SM_Mean"],
    },
)
raw = extractor.execute("ct.nii.gz", "bc_mask.nii.gz")
normalizer = FeatureNormalizer(
    mode="3D", methods=["height", "bone"], tissues=["SM"],
    include_composite=True,
)
corrected = normalizer.execute(raw, height_cm=170)
# normalization_height_SM_Volume
# normalized_composite_height_SM_VolumeMean
# normalization_bone_SM_Volume
# normalized_composite_bone_SM_VolumeMean
units = normalizer.get_units(raw)

2D将模式改为2D,将第一类特征的Volume改为Area,输出为normalized_composite_height_SM_AreaMean等。

方法 公式,μ为同组织平均HU 2D单位 3D单位 全部组织数量
height (面积/体积 ÷ 身高(m)²) × μ cm²·HU/m² cm³·HU/m² 11
weight (面积/体积 ÷ 体重(kg)) × μ cm²·HU/kg cm³·HU/kg 11
bsa (面积/体积 ÷ BSA(m²)) × μ cm²·HU/m² cm³·HU/m² 11
bone (面积/体积 ÷ 同范围骨面积/体积) × μ HU HU 10

共43项可选校正复合特征,不输出Bone/Bone×HU。每种模式最多有100项基础特征+43项校正指数+43项校正复合特征=186项。2D和3D是两种模式,不合并计数。负平均HU保留符号;指数或均值为NaN/无穷时结果为NaN,不解释为实际组织质量。

通过methods选择校正方式,通过tissues选择组织;tissues=None从输入已有的形态指标中选择组织。开启复合项需要同时提取目标组织的Mean。可用get_normalized_composite_catalog("3D")查询完整复合名称、单位、指数键和均值键。

对于已经保存的校正指数字典,仍支持NormalizedCompositeCalculator(mode, methods, tissues).execute(indices, raw)单独补算复合项;两个字典需来自同一病例、同一范围。

2D两层的计算顺序:先将两层面积与两层平均HU分别等权平均,面积平均值进行校正,再乘HU平均值。因此结果是“校正后的平均面积指数 × 平均HU”,与基础复合类的“逐层面积×HU后平均”定义不同。例如两层面积0.06、0.18 cm²,均值10、30 HU,身高1 m:校正复合为0.12×20=2.4 cm²·HU/m²,而基础复合为(0.06×10+0.18×30)/2=3 cm²·HU。

选择类别或单项

from ctbodycomp import BodyCompositionExtractor, get_feature_catalog

extractor = BodyCompositionExtractor(mode="2D", spine_label=7)
extractor.disableAllFeatures()
extractor.enableFeaturesByName(
    morphometry=["SM_Area", "Bone_Area"],
    firstorder=["SM_Mean", "SM_P50"],
    composition=["MFF"],
)
raw = extractor.execute("ct.nii.gz", "bc_mask.nii.gz", spine_mask="spine.nii.gz")

# 按整个类别启用:
extractor.enableFeatureClassByName("firstorder")
# 查询当前模式下全部可用名称、英文输出键和单位:
catalog = get_feature_catalog("2D")

构造参数features=None默认启用全部四类;features={}不启用任何特征。映射中未列出的类别不提取,类别中的[]或None表示该类全部。enableFeaturesByName替换指定类别的选择,其他已启用类别保持不变,因此要只选择几项时先调用disableAllFeatures()。支持全部启用enableAllFeatures()和单类别关闭enableFeatureClassByName("firstorder", False)。

只输出选择的特征,内部依赖按需计算。例如只选Mean不计算分位数,只选形态不计算HU统计;只选一个组成比值时也不输出其内部依赖的组织面积/体积。

输入与选层

  • 必需:CT与BC mask。接受文件路径或nibabel图像对象,图像需3D且空间匹配,尺寸以mm解释;不重采样。
  • 可选:Spine mask。不提供时3D计算整幅CT,2D在整幅CT全部层中选中间层。
  • 2D有Spine mask时需spine_label,例如7或8。仅对该标签实际出现的切片排序,奇数取中间一层,偶数取中间两层。
  • 3D有Spine mask时默认范围spine_range=(7, 18),可配置,取首末层之间的完整范围。新库依据affine识别上下方向,支持数组轴置换。
  • 每个选中切片的组织ROI来自完整BC mask平面,Spine mask仅定位。斜位影像保持原切片平面。
  • 2D两层基础特征先逐层计算再等权平均。独立校正使用这个平均后的形态值;骨校正因此是“平均组织面积/平均骨面积”,不同于旧脚本的“两层骨比值平均”。
  • SD使用ddof=0;分位数为线性插值;非有限CT值不进入HU统计;空组织的面积/体积为0,HU统计为NaN;任一层某基础指标NaN,则两层平均也为NaN。

诊断信息在extractor.last_diagnostics,与纯数值特征分开。无Spine mask请传None;填写了错误文件路径不会自动退回全图计算。

CSV分两步运行

新库的CSV使用有意义的列名(区分大小写),不同于旧脚本按列位置读取:

ID,Image,Mask,SpineMask,Height_cm,Weight_kg
001,ct.nii.gz,bc_mask.nii.gz,,170,65

必需Image、Mask,其他列可选;SpineMask可省略或留空。相对路径相对于输入CSV目录。Height_cm、Weight_kg、可选BSA_m2由校正步骤读取,逐病例值优先于命令行公共值。

# 查询特征名
ctbodycomp features --mode 3D

# 仅提取肌肉、皮下脂肪和骨的体积
ctbodycomp extract cases.csv raw.csv --mode 3D --config examples/morphometry_3d.json

# 对提取结果进行校正,原始列也保留在输出中
ctbodycomp normalize raw.csv corrected.csv --mode 3D --methods height weight bsa bone --tissues SM SF

# 2D单标签、部分特征
ctbodycomp extract cases.csv raw_2d.csv --mode 2D --label 7 --config examples/selected_2d.json
ctbodycomp normalize raw_2d.csv corrected_2d.csv --mode 2D --methods bone --tissues SM

需要校正复合时,提取配置必须包含目标组织的firstorder_*_Mean。在同一校正步骤增加--include-composite即可:

# 示例配置包含肌肉、骨体积和肌肉Mean
ctbodycomp extract cases.csv raw.csv --mode 3D --config examples/normalized_composite_3d.json
ctbodycomp normalize raw.csv corrected.csv --mode 3D --methods height weight bsa bone --tissues SM --include-composite

# 查询校正复合特征及所需输入
ctbodycomp features --mode 3D --normalized-composite

校正CSV保留基础特征,按“校正指数、对应复合项”的顺序追加列,使用统一的normalization_status、normalization_error记录结果。缺少所需Mean列时记录失败;Mean数值为空时对应复合项为NaN。影像不存在也不影响已成功提取结果的后续计算。

如需对已有校正CSV补算复合项,也保留单独命令:ctbodycomp normalized-composite corrected.csv products.csv --mode 3D --methods height bone --tissues SM。

配置JSON直接写“类别→特征名称列表”。命令返回0表示成功,1表示输出中存在失败病例,参数错误返回2。输出目录需存在,输出不能覆盖输入文件;重复输出路径会替换先前结果。

完整使用示例

源码包中的 examples/reference_usage/README.md 提供五种完整提取示例:2D T12、2D无脊柱、3D T12、3D T1–T12、3D无脊柱,以及独立校正示例。每种情况同时提供可运行的Python脚本和Markdown教程,不依赖额外本地辅助脚本。

输入使用 cases.example.csv 和 cases_without_spine.example.csv 通用模板。模板不包含实际病例数据,使用前替换为自己的影像路径。示例计算结果写入示例目录下的 results/,不会纳入发布包。

测试和构建

在项目根目录运行:

python -m pip install -e '.[test]'
python -m pytest -q -p no:cacheprovider
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/ctbodycomp-0.1.1-py3-none-any.whl dist/ctbodycomp-0.1.1.tar.gz

wheel只包含库模块和安装元数据;源码包另外包含测试与使用教程。虚拟环境、缓存、本地影像、实际病例表和计算结果不纳入发布文件。PUBLISHING.md 仅保留在开发目录供维护者参考,不随发布包分发。

作者、邮箱和许可证字段当前未设置,可在后续版本补充。本项目目前没有声明MIT或Apache-2.0授权。

Metadata

Release files for ctbodycomp 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ctbodycomp 0.1.1
File Size Uploaded
ctbodycomp-0.1.1.tar.gz 36.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ctbodycomp 0.1.1
File Interpreter ABI Platform
ctbodycomp-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 56.8 kB

Release files / ctbodycomp-0.1.1.tar.gz

Download URL ctbodycomp-0.1.1.tar.gz
Size 36.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6cb716573ca4e8962740b9b68b938c4d46f129247276d83d32378df503e60f4e
BLAKE2b-256 checksum
How to use checksums
4c68c20779951a6541e8915df875e1d66a2e068a070eed673b750a1e92a38579
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.9

Release files / ctbodycomp-0.1.1-py3-none-any.whl

Download URL ctbodycomp-0.1.1-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d42256003fbfad12f31c9728903d2d9fc93978d425b1a7c188a24019401233e8
BLAKE2b-256 checksum
How to use checksums
803695a7e9716c5ab34e838f9147291637484b775d31c1dc49ec43c6d3ad9e46
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.9

Release history Release notifications | RSS feed

0.1.5

2 release files

0.1.4

2 release files

0.1.2

2 release files

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page