Switch to unified view

a b/CLI/DensityAnalysis/DensityAnalysis.py
1
#!/usr/bin/env python-real
2
3
import sys
4
import os
5
from datetime import date
6
7
import numpy as np
8
9
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10
from MusculoskeletalAnalysisCLITools import (
11
  crop,
12
  densityMap,
13
  readImg,
14
  readMask,
15
  writeReport,
16
)
17
18
19
OUTPUT_FIELDS = [
20
    ("Date Analysis Performed", "The current date"),
21
    ("Input Volume", "Name of the input volume"),
22
    ("Area by Slice", "The area of the segment in each slice of each slice"),
23
    ("Mean Density by Slice", "The average density of the segmented area each slice"),
24
    ("Standard Deviation of Density by Slice", "The standard deviation of the density of each slice"),
25
    ("Min Density by Slice", "The lowest density in the segment of each slice"),
26
    ("Max Density by Slice", "The highest density in the segment of each slice"),
27
    ("Mean Area", "The mean area of the segment of all slices"),
28
    ("Standard Deviation of Area", "The standard deviation of the segmented area of all slices"),
29
    ("Min Area", "The area of the smallest segment slice"),
30
    ("Max Area", "The area of the largest segment slice"),
31
    ("Mean Density", "The average density of the entire segmented volume"),
32
    ("Standard Deviation of Density", "The standard deviation of density of the segmented volume"),
33
    ("Min Density", "The minimum density of the segmented volume"),
34
    ("Max Density", "The maximum density of the segmented volume"),
35
]
36
37
38
# Performs analysis on cortical bone
39
# image: 3D image black and white of bone
40
# mask: 3D labelmap of bone area, including cavities
41
# voxSize: The physical side length of the voxels, in mm
42
# slope, intercept and scale: parameters of the equation for converting image values to mgHA/ccm
43
# output: The name of the output directory
44
def main(inputImg, inputMask, voxSize, slope, intercept, name, output):
45
    imgData = readImg(inputImg)
46
    (_, maskData) = readMask(inputMask)
47
    (maskData, imgData) = crop(maskData, imgData)
48
    if np.count_nonzero(maskData) == 0:
49
         raise Exception("Segmentation mask is empty.")
50
    density = densityMap(imgData, slope, intercept)
51
52
    c = density.shape[2]
53
    area = np.zeros(c);
54
    meanDens = np.zeros(c);
55
    stdDens = np.zeros(c);
56
    minDens = np.zeros(c);
57
    maxDens = np.zeros(c);
58
    print("""<filter-progress>{}</filter-progress>""".format(.25))
59
    sys.stdout.flush()
60
    # Get stats for each slice
61
    for sliceNum in range(c):
62
        sliceDensity = density[:,:,sliceNum]
63
        maskDensity = sliceDensity[maskData[:,:,sliceNum]]
64
        area[sliceNum] = len(maskDensity) * voxSize**2
65
        if(area[sliceNum] != 0):
66
            meanDens[sliceNum] = np.mean(maskDensity)
67
            stdDens[sliceNum] = np.std(maskDensity)
68
            minDens[sliceNum] = np.min(maskDensity)
69
            maxDens[sliceNum] = np.max(maskDensity)
70
    print("""<filter-progress>{}</filter-progress>""".format(.50))
71
    sys.stdout.flush()
72
    # Get average area of all slices
73
    meanArea = np.mean(area)
74
    stdArea =  np.std(area)
75
    minArea = np.min(area)
76
    maxArea = np.max(area)
77
    print("""<filter-progress>{}</filter-progress>""".format(.75))
78
    sys.stdout.flush()
79
    # Get average density of entire bone
80
    fullDensity = density[maskData]
81
    meanDensity = np.mean(fullDensity)
82
    stdDensity = np.std(fullDensity)
83
    minDensity = np.min(fullDensity)
84
    maxDensity = np.max(fullDensity)
85
86
    fPath = os.path.join(output, "density.txt")
87
88
    header = [field[0] for field in OUTPUT_FIELDS]
89
90
    data = [
91
        date.today(),
92
        name,
93
        area,
94
        meanDens,
95
        stdDens,
96
        minDens,
97
        maxDens,
98
        meanArea,
99
        stdArea,
100
        minArea,
101
        maxArea,
102
        meanDensity,
103
        stdDensity,
104
        minDensity,
105
        maxDensity
106
    ]
107
    writeReport(fPath, header, data)
108
109
110
111
if __name__ == "__main__":
112
    if len(sys.argv) < 8:
113
        print(sys.argv)
114
        print("Usage: CancellousAnalysis <input> <mask> <voxelSize> <slope> <intercept> <name> <output>")
115
        sys.exit(1)
116
    main(sys.argv[1], sys.argv[2], float(sys.argv[3]), float(sys.argv[4]), float(sys.argv[5]), str(sys.argv[6]), str(sys.argv[7]))