radiomicsj 2.1.16__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- radiomicsj-2.1.16/PKG-INFO +11 -0
- radiomicsj-2.1.16/README.md +31 -0
- radiomicsj-2.1.16/radiomicsj/__init__.py +8 -0
- radiomicsj-2.1.16/radiomicsj/core.py +153 -0
- radiomicsj-2.1.16/radiomicsj/jars/SparseBitSet-1.2.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/commons-cli-1.5.0.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/commons-codec-1.13.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/commons-collections4-4.4.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/commons-compress-1.19.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/commons-math3-3.6.1.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/curvesapi-1.06.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/ij-1.54p.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/poi-4.1.2.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/poi-ooxml-4.1.2.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/poi-ooxml-schemas-4.1.2.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/radiomicsj-2.1.16.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/vecmath-1.5.2.jar +0 -0
- radiomicsj-2.1.16/radiomicsj/jars/xmlbeans-3.1.0.jar +0 -0
- radiomicsj-2.1.16/radiomicsj.egg-info/PKG-INFO +11 -0
- radiomicsj-2.1.16/radiomicsj.egg-info/SOURCES.txt +23 -0
- radiomicsj-2.1.16/radiomicsj.egg-info/dependency_links.txt +1 -0
- radiomicsj-2.1.16/radiomicsj.egg-info/requires.txt +3 -0
- radiomicsj-2.1.16/radiomicsj.egg-info/top_level.txt +1 -0
- radiomicsj-2.1.16/setup.cfg +4 -0
- radiomicsj-2.1.16/setup.py +28 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: radiomicsj
|
|
3
|
+
Version: 2.1.16
|
|
4
|
+
Summary: Python wrapper for RadiomicsJ
|
|
5
|
+
Author: Tatsuaki Kobayashi
|
|
6
|
+
Requires-Dist: jpype1>=1.3.0
|
|
7
|
+
Requires-Dist: numpy
|
|
8
|
+
Requires-Dist: pandas
|
|
9
|
+
Dynamic: author
|
|
10
|
+
Dynamic: requires-dist
|
|
11
|
+
Dynamic: summary
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# RadiomicsJ (Python Wrapper)
|
|
2
|
+
|
|
3
|
+
RadiomicsJ(Python wrapper) is an image feature extraction tool implemented in Java.
|
|
4
|
+
|
|
5
|
+
## Main Function
|
|
6
|
+
- Radiomics Feature calculation.
|
|
7
|
+
- Calculation results will return by Pandas DataFrame.
|
|
8
|
+
|
|
9
|
+
## Install Requirements
|
|
10
|
+
|
|
11
|
+
### When use : pip
|
|
12
|
+
You need install Java (>= JDK 8), and add it's jdk/bin to environment path.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install radiomicsj
|
|
16
|
+
|
|
17
|
+
## Example
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from radiomicsj.core import RadiomicsJExtractor
|
|
21
|
+
|
|
22
|
+
# init
|
|
23
|
+
extractor = RadiomicsJExtractor("path/to/params.properties")
|
|
24
|
+
|
|
25
|
+
results = []
|
|
26
|
+
for image_path, mask_path in my_image_list:
|
|
27
|
+
df = extractor.execute(image_path, mask_path)
|
|
28
|
+
results.append(df)
|
|
29
|
+
|
|
30
|
+
# If you want to set properties case by case.
|
|
31
|
+
# extractor.load_settings("path/to/another_params.properties")
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'''
|
|
2
|
+
@CopyRight : Visionary Imaging Services, Inc.
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import math
|
|
7
|
+
import jpype
|
|
8
|
+
import jpype.imports
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
# Mavenのビルド時に自動置換されるバージョン情報
|
|
13
|
+
__version__ = "2.1.16"
|
|
14
|
+
if __version__.startswith("${"):
|
|
15
|
+
__version__ = "0.0.0.dev0"
|
|
16
|
+
|
|
17
|
+
def start_jvm():
|
|
18
|
+
"""JVMを起動し、jarsフォルダ内のすべてのJARをクラスパスに追加する"""
|
|
19
|
+
if jpype.isJVMStarted():
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
package_dir = os.path.dirname(os.path.abspath(__file__))
|
|
23
|
+
jars_dir = os.path.join(package_dir, "jars")
|
|
24
|
+
|
|
25
|
+
if not os.path.exists(jars_dir):
|
|
26
|
+
raise FileNotFoundError(f"Jars directory not found at: {jars_dir}")
|
|
27
|
+
|
|
28
|
+
jar_path = os.path.join(jars_dir, "*")
|
|
29
|
+
jpype.startJVM(classpath=[jar_path])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class RadiomicsJExtractor:
|
|
33
|
+
"""
|
|
34
|
+
RadiomicsJの機能を利用して特徴量を抽出するクラス。
|
|
35
|
+
インスタンス化時に一度だけ設定を読み込むことで、連続処理を高速化します。
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, config_prop_path: str = None):
|
|
39
|
+
"""
|
|
40
|
+
Args:
|
|
41
|
+
config_prop_path (str, optional): 設定プロパティファイルのパス。
|
|
42
|
+
"""
|
|
43
|
+
if not jpype.isJVMStarted():
|
|
44
|
+
start_jvm()
|
|
45
|
+
|
|
46
|
+
self._RadiomicsJClass = jpype.JClass("io.github.tatsunidas.radiomics.main.RadiomicsJ")
|
|
47
|
+
self.radj = self._RadiomicsJClass()
|
|
48
|
+
|
|
49
|
+
# ImageJのパッケージを取得
|
|
50
|
+
self.ij = jpype.JPackage("ij")
|
|
51
|
+
|
|
52
|
+
if config_prop_path is not None:
|
|
53
|
+
self.load_settings(config_prop_path)
|
|
54
|
+
|
|
55
|
+
def load_settings(self, config_prop_path: str):
|
|
56
|
+
"""プロパティファイルを読み込み、設定を更新します。"""
|
|
57
|
+
if not os.path.exists(config_prop_path):
|
|
58
|
+
raise FileNotFoundError(f"Config file not found: {config_prop_path}")
|
|
59
|
+
self.radj.loadSettings(config_prop_path)
|
|
60
|
+
|
|
61
|
+
def _numpy_to_imageplus(self, arr: np.ndarray, spacing: tuple, title: str) -> "ij.ImagePlus":
|
|
62
|
+
"""
|
|
63
|
+
NumPy ndarray to ImagePlus directly.
|
|
64
|
+
arr : (Z, Y, X) 3d-array, if ndarray sorted by ordered (X, Y, Z), do np.transpose(arr, (2, 1, 0)) before input.
|
|
65
|
+
spacing : (x,y,z) voxel size
|
|
66
|
+
"""
|
|
67
|
+
# ImageJは内部的にfloat配列を扱うため、float32に変換
|
|
68
|
+
arr_f = arr.astype(np.float32)
|
|
69
|
+
|
|
70
|
+
if arr.ndim == 2:
|
|
71
|
+
h, w = arr_f.shape
|
|
72
|
+
# メモリコピーを最小限にJArrayへ変換
|
|
73
|
+
jarr = jpype.JArray(jpype.JFloat)(arr_f.ravel())
|
|
74
|
+
proc = self.ij.process.FloatProcessor(w, h, jarr)
|
|
75
|
+
img_plus = self.ij.ImagePlus(title, proc)
|
|
76
|
+
|
|
77
|
+
cal = img_plus.getCalibration()
|
|
78
|
+
cal.pixelWidth = spacing[0]
|
|
79
|
+
cal.pixelHeight = spacing[1]
|
|
80
|
+
|
|
81
|
+
elif arr.ndim == 3:
|
|
82
|
+
d, h, w = arr_f.shape
|
|
83
|
+
stack = self.ij.ImageStack(w, h)
|
|
84
|
+
|
|
85
|
+
for i in range(d):
|
|
86
|
+
# 1スライスごとにJArrayに変換してスタックに追加
|
|
87
|
+
slice_arr = arr_f[i, :, :]
|
|
88
|
+
jarr = jpype.JArray(jpype.JFloat)(slice_arr.ravel())
|
|
89
|
+
proc = self.ij.process.FloatProcessor(w, h, jarr)
|
|
90
|
+
stack.addSlice(str(i), proc)
|
|
91
|
+
|
|
92
|
+
img_plus = self.ij.ImagePlus(title, stack)
|
|
93
|
+
|
|
94
|
+
cal = img_plus.getCalibration()
|
|
95
|
+
cal.pixelWidth = spacing[0]
|
|
96
|
+
cal.pixelHeight = spacing[1]
|
|
97
|
+
cal.pixelDepth = spacing[2]
|
|
98
|
+
else:
|
|
99
|
+
raise ValueError("NumPy array must be 2D or 3D.")
|
|
100
|
+
|
|
101
|
+
return img_plus
|
|
102
|
+
|
|
103
|
+
def execute(self, image, mask, spacing=(1.0, 1.0, 1.0)) -> pd.DataFrame:
|
|
104
|
+
"""
|
|
105
|
+
特徴量を計算し、Pandas DataFrameとして返します。
|
|
106
|
+
Args:
|
|
107
|
+
image: ファイルパス(str) または NumPy配列(np.ndarray)
|
|
108
|
+
mask: ファイルパス(str) または NumPy配列(np.ndarray)
|
|
109
|
+
spacing (tuple): NumPy配列の場合のピクセル間隔 (x, y, z)。デフォルトは(1.0, 1.0, 1.0)
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
pd.DataFrame: 計算された特徴量
|
|
113
|
+
"""
|
|
114
|
+
# Imageの変換
|
|
115
|
+
if isinstance(image, np.ndarray):
|
|
116
|
+
target_image = self._numpy_to_imageplus(image, spacing, title="target_image")
|
|
117
|
+
else:
|
|
118
|
+
target_image = image
|
|
119
|
+
|
|
120
|
+
# Maskの変換
|
|
121
|
+
if isinstance(mask, np.ndarray):
|
|
122
|
+
target_mask = self._numpy_to_imageplus(mask, spacing, title="target_mask")
|
|
123
|
+
else:
|
|
124
|
+
target_mask = mask
|
|
125
|
+
|
|
126
|
+
# Java側の実行 (JPypeが自動で String と ImagePlus のオーバーロードを判別してくれます)
|
|
127
|
+
res_table = self.radj.execute(target_image, target_mask, self._RadiomicsJClass.targetLabel)
|
|
128
|
+
|
|
129
|
+
if res_table is None or res_table.size() == 0:
|
|
130
|
+
return pd.DataFrame()
|
|
131
|
+
|
|
132
|
+
# DataFrameへの変換処理
|
|
133
|
+
headings = [str(h) for h in res_table.getHeadings()]
|
|
134
|
+
num_rows = res_table.size()
|
|
135
|
+
data_list = []
|
|
136
|
+
for i in range(num_rows):
|
|
137
|
+
row_dict = {}
|
|
138
|
+
for h in headings:
|
|
139
|
+
val = res_table.getValue(h, i)
|
|
140
|
+
if math.isnan(val):
|
|
141
|
+
str_val = res_table.getStringValue(h, i)
|
|
142
|
+
row_dict[h] = str(str_val) if str_val is not None else float('nan')
|
|
143
|
+
else:
|
|
144
|
+
row_dict[h] = val
|
|
145
|
+
data_list.append(row_dict)
|
|
146
|
+
|
|
147
|
+
return pd.DataFrame(data_list)
|
|
148
|
+
|
|
149
|
+
def calculate_features(image, mask, config_prop_path: str = None, spacing=(1.0, 1.0, 1.0)) -> pd.DataFrame:
|
|
150
|
+
"""単一処理用の簡易ラッパー関数"""
|
|
151
|
+
extractor = RadiomicsJExtractor(config_prop_path)
|
|
152
|
+
return extractor.execute(image, mask, spacing=spacing)
|
|
153
|
+
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: radiomicsj
|
|
3
|
+
Version: 2.1.16
|
|
4
|
+
Summary: Python wrapper for RadiomicsJ
|
|
5
|
+
Author: Tatsuaki Kobayashi
|
|
6
|
+
Requires-Dist: jpype1>=1.3.0
|
|
7
|
+
Requires-Dist: numpy
|
|
8
|
+
Requires-Dist: pandas
|
|
9
|
+
Dynamic: author
|
|
10
|
+
Dynamic: requires-dist
|
|
11
|
+
Dynamic: summary
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
radiomicsj/__init__.py
|
|
4
|
+
radiomicsj/core.py
|
|
5
|
+
radiomicsj.egg-info/PKG-INFO
|
|
6
|
+
radiomicsj.egg-info/SOURCES.txt
|
|
7
|
+
radiomicsj.egg-info/dependency_links.txt
|
|
8
|
+
radiomicsj.egg-info/requires.txt
|
|
9
|
+
radiomicsj.egg-info/top_level.txt
|
|
10
|
+
radiomicsj/jars/SparseBitSet-1.2.jar
|
|
11
|
+
radiomicsj/jars/commons-cli-1.5.0.jar
|
|
12
|
+
radiomicsj/jars/commons-codec-1.13.jar
|
|
13
|
+
radiomicsj/jars/commons-collections4-4.4.jar
|
|
14
|
+
radiomicsj/jars/commons-compress-1.19.jar
|
|
15
|
+
radiomicsj/jars/commons-math3-3.6.1.jar
|
|
16
|
+
radiomicsj/jars/curvesapi-1.06.jar
|
|
17
|
+
radiomicsj/jars/ij-1.54p.jar
|
|
18
|
+
radiomicsj/jars/poi-4.1.2.jar
|
|
19
|
+
radiomicsj/jars/poi-ooxml-4.1.2.jar
|
|
20
|
+
radiomicsj/jars/poi-ooxml-schemas-4.1.2.jar
|
|
21
|
+
radiomicsj/jars/radiomicsj-2.1.16.jar
|
|
22
|
+
radiomicsj/jars/vecmath-1.5.2.jar
|
|
23
|
+
radiomicsj/jars/xmlbeans-3.1.0.jar
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
radiomicsj
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
'''
|
|
3
|
+
@Copy right Visionary Imaging Services, Inc.
|
|
4
|
+
@since 2026
|
|
5
|
+
'''
|
|
6
|
+
|
|
7
|
+
from setuptools import setup
|
|
8
|
+
|
|
9
|
+
version_str = "2.1.16"
|
|
10
|
+
if version_str.startswith("${"):
|
|
11
|
+
version_str = "0.0.0.dev0"
|
|
12
|
+
|
|
13
|
+
setup(
|
|
14
|
+
name="radiomicsj",
|
|
15
|
+
version=version_str,
|
|
16
|
+
description="Python wrapper for RadiomicsJ",
|
|
17
|
+
author="Tatsuaki Kobayashi",
|
|
18
|
+
packages=["radiomicsj", "radiomicsj.jars"],
|
|
19
|
+
package_data={
|
|
20
|
+
"radiomicsj": ["jars/*.jar"],
|
|
21
|
+
},
|
|
22
|
+
include_package_data=True,
|
|
23
|
+
install_requires=[
|
|
24
|
+
"jpype1>=1.3.0",
|
|
25
|
+
"numpy",
|
|
26
|
+
"pandas"
|
|
27
|
+
],
|
|
28
|
+
)
|