pdnl-process 0.5__tar.gz → 0.6__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.
- {pdnl_process-0.5 → pdnl_process-0.6}/PKG-INFO +2 -2
- {pdnl_process-0.5 → pdnl_process-0.6}/pdnl_process/main.py +32 -53
- {pdnl_process-0.5 → pdnl_process-0.6}/pyproject.toml +2 -2
- {pdnl_process-0.5 → pdnl_process-0.6}/.github/workflows/publish.yml +0 -0
- {pdnl_process-0.5 → pdnl_process-0.6}/.gitignore +0 -0
- {pdnl_process-0.5 → pdnl_process-0.6}/README.md +0 -0
- {pdnl_process-0.5 → pdnl_process-0.6}/pdnl_process/__init__.py +0 -0
|
@@ -23,6 +23,7 @@ def main():
|
|
|
23
23
|
parser.add_argument('-o', '--output_path', help="path to write outputs to", required=True)
|
|
24
24
|
parser.add_argument('-s', '--staining_code', help="stain protocol used to stain the input image", default='H-DAB')
|
|
25
25
|
parser.add_argument('-p', '--parameters_file', help=".json file containing processing parameters", default=None)
|
|
26
|
+
parser.add_argument('--debug_level', help="outputs extra files", default='normal')
|
|
26
27
|
args = parser.parse_args()
|
|
27
28
|
|
|
28
29
|
if args.parameters_file:
|
|
@@ -31,79 +32,51 @@ def main():
|
|
|
31
32
|
params = {}
|
|
32
33
|
|
|
33
34
|
os.makedirs(args.output_path, exist_ok=True)
|
|
34
|
-
|
|
35
|
-
# preprocess the chunks
|
|
36
|
-
# TODO: move all pdnl_sana.process code into here, then other scripts import these functions
|
|
37
|
-
print('Preprocessing chunks...', flush=True)
|
|
38
|
-
histogram = None
|
|
39
|
-
for d in tqdm(os.listdir(args.input_path)):
|
|
40
|
-
if not os.path.isdir(os.path.join(args.input_path, d)):
|
|
41
|
-
continue
|
|
42
|
-
|
|
43
|
-
i, j = list(map(int, d.split('_')))
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
# get the background image
|
|
37
|
+
# TODO: test how big the concatenated frame will be, and move to big roi mode if too big
|
|
38
|
+
rois = pdnl_sana.slide.concatenate_chunks(args.input_path)
|
|
39
|
+
for roi_name in rois:
|
|
40
|
+
frame, mask, frame_loc = rois[roi_name]
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
converter = pdnl_sana.geo.Converter(mpp, ds)
|
|
54
|
-
frame = pdnl_sana.image.Frame(os.path.join(in_d, 'frame.png'), level=level, converter=converter)
|
|
55
|
-
mask = pdnl_sana.image.Frame(os.path.join(in_d, 'mask.png'), level=level, converter=converter)
|
|
42
|
+
# TODO: move all pdnl_sana.process code into here, then other scripts import these functions
|
|
43
|
+
out_d = os.path.join(args.output_path, roi_name)
|
|
44
|
+
os.makedirs(out_d, exist_ok=True)
|
|
45
|
+
logger = pdnl_sana.logging.Logger(args.debug_level, os.path.join(out_d, 'log.pkl'))
|
|
56
46
|
|
|
57
|
-
|
|
47
|
+
# TODO: shouldn't be omitting the mask here, but leaving it here so all data is generated in the same way for now.
|
|
48
|
+
# this was a fix for the background code, but that code is solved now
|
|
58
49
|
if args.staining_code == 'H-DAB':
|
|
59
50
|
processor = pdnl_sana.process.HDABProcessor(
|
|
60
|
-
logger, frame,
|
|
51
|
+
logger, frame,
|
|
52
|
+
#main_mask=mask,
|
|
61
53
|
apply_smoothing=params.get('apply_smoothing', False),
|
|
62
54
|
normalize_background=params.get('normalize_background', False),
|
|
63
|
-
stain_vector=params.get('stain_vector', None)
|
|
55
|
+
stain_vector=params.get('stain_vector', None),
|
|
56
|
+
radius=200, overlap=0.5,
|
|
64
57
|
)
|
|
65
58
|
if args.staining_code == 'CV-DAB':
|
|
66
59
|
processor = pdnl_sana.process.CVDABProcessor(
|
|
67
|
-
logger, frame,
|
|
60
|
+
logger, frame,
|
|
61
|
+
#main_mask=mask,
|
|
68
62
|
apply_smoothing=params.get('apply_smoothing', False),
|
|
69
63
|
normalize_background=params.get('normalize_background', False),
|
|
70
64
|
stain_vector=params.get('stain_vector', None)
|
|
71
65
|
)
|
|
72
66
|
hist = processor.dab.get_histogram(mask=processor.main_mask)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
else:
|
|
76
|
-
histogram = histogram + hist
|
|
77
|
-
processor.dab.save(os.path.join(out_d, 'stain.npy'))
|
|
67
|
+
stain = processor.dab.copy()
|
|
68
|
+
stain.save(os.path.join(out_d, 'stain.npy'))
|
|
78
69
|
|
|
79
|
-
|
|
80
|
-
if not histogram is None:
|
|
70
|
+
# calculate the threshold
|
|
81
71
|
triangular_strictness = params.get('triangular_strictness', 0.0)
|
|
82
72
|
threshold = pdnl_sana.threshold.triangular_method(
|
|
83
|
-
|
|
73
|
+
hist,
|
|
84
74
|
strictness=triangular_strictness,
|
|
85
|
-
debug=True
|
|
86
75
|
)
|
|
87
|
-
else:
|
|
88
|
-
threshold = 0
|
|
89
76
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
# apply the threshold to the pre-processed chunks
|
|
95
|
-
print('Processing chunks...', flush=True)
|
|
96
|
-
for d in tqdm(os.listdir(args.output_path)):
|
|
97
|
-
if not os.path.isdir(os.path.join(args.input_path, d)):
|
|
98
|
-
continue
|
|
99
|
-
|
|
100
|
-
i, j = list(map(int, d.split('_')))
|
|
101
|
-
|
|
102
|
-
in_d = os.path.join(args.input_path, f'{i}_{j}')
|
|
103
|
-
out_d = os.path.join(args.output_path, f'{i}_{j}')
|
|
104
|
-
|
|
105
|
-
mask = pdnl_sana.image.Frame(os.path.join(in_d, 'mask.png'))
|
|
106
|
-
stain = pdnl_sana.image.Frame(os.path.join(out_d, 'stain.npy'))
|
|
77
|
+
minimum_threshold = params.get('minimum_threshold', 0)
|
|
78
|
+
if threshold < minimum_threshold:
|
|
79
|
+
threshold = minimum_threshold
|
|
107
80
|
|
|
108
81
|
stain.mask(mask)
|
|
109
82
|
stain.threshold(threshold)
|
|
@@ -112,12 +85,18 @@ def main():
|
|
|
112
85
|
for filt in morphology_filters:
|
|
113
86
|
stain.apply_morphology_filter(filt)
|
|
114
87
|
|
|
88
|
+
if args.debug_level in ['debug', 'full']:
|
|
89
|
+
frame.save(os.path.join(out_d, 'frame.png'))
|
|
90
|
+
|
|
91
|
+
if args.debug_level == 'full':
|
|
92
|
+
plt.show()
|
|
115
93
|
stain.save(os.path.join(out_d, 'pos.png'))
|
|
116
|
-
|
|
94
|
+
mask.save(os.path.join(out_d, 'mask.png'))
|
|
117
95
|
logger.data['triangular_strictness'] = triangular_strictness
|
|
118
96
|
logger.data['minimum_threshold'] = minimum_threshold
|
|
119
97
|
logger.data['morphology_filter'] = morphology_filters
|
|
120
98
|
logger.data['threshold'] = threshold
|
|
99
|
+
logger.data['frame_loc'] = frame_loc
|
|
121
100
|
logger.write_data()
|
|
122
101
|
|
|
123
102
|
if __name__ == "__main__":
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pdnl_process"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Noah Capp", email="noahmcapp@gmail.com" },
|
|
10
10
|
]
|
|
@@ -28,4 +28,4 @@ classifiers = [
|
|
|
28
28
|
Homepage = "https://github.com/PennCompPathology/pdnl_process"
|
|
29
29
|
|
|
30
30
|
[project.scripts]
|
|
31
|
-
pdnl_process = "pdnl_process:main"
|
|
31
|
+
pdnl_process = "pdnl_process:main"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|