def execute(self, ct, lm, cid, spacing, chest_regions=None, chest_types=None, pairs=None, pheno_names=None): """Compute the phenotypes for the specified structures for the specified threshold values. The following values are computed for the specified structures. 'AxialCSA': Axial cross-sectional area 'CoronalCSA': Coronoal cross-sectional area 'SagittalCSA': Sagitall cross-sectional area 'HUMean': Mean value of the structure's HU values 'HUStd': Standard deviation of the structure's HU values 'HUKurtosis': Kurtosis of the structure's HU values. Fisher's definition is used, meaning that normal distribution has kurtosis of 0. The calculation is corrected for statistical bias. 'HUSkewness': Skewness of the structure's HU values. The calculation is corrected for statistical bias. 'HUMode': Mode of the structure's HU values 'HUMedian': Median of the structure's HU values 'HUMin': Min HU value for the structure 'HUMax': Max HU value for the structure The following set of phenotypes are identical to the above except that computation is isolated to the HU interval [-50, 90]. These phenotypes are capture lean muscle information and only have meaning for muscle structures. 'leanAxialCSA': Axial cross-sectional area 'leanCoronalCSA': Coronoal cross-sectional area 'leanSagittalCSA': Sagitall cross-sectional area 'leanHUMean': Mean value of the structure's HU values 'leanHUStd': Standard deviation of the structure's HU values 'leanHUKurtosis': Kurtosis of the structure's HU values. Fisher's definition is used, meaning that normal distribution has kurtosis of 0. The calculation is corrected for statistical bias. 'leanHUSkewness': Skewness of the structure's HU values. The calculation is corrected for statistical bias. 'leanHUMode': Mode of the structure's HU values 'leanHUMedian': Median of the structure's HU values 'leanHUMin': Min HU value for the structure 'leanHUMax': Max HU value for the structure Parameters ---------- ct : array, shape ( X, Y, Z ) The 3D CT image array lm : array, shape ( X, Y, Z ) The 3D label map array cid : string Case ID spacing : array, shape ( 3 ) The x, y, and z spacing, respectively, of the CT volume chest_regions : array, shape ( R ), optional Array of integers, with each element in the interval [0, 255], indicating the chest regions over which to compute the LAA. If none specified, the chest regions specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. chest_types : array, shape ( T ), optional Array of integers, with each element in the interval [0, 255], indicating the chest types over which to compute the LAA. If none specified, the chest types specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pairs : array, shape ( P, 2 ), optional Array of chest-region chest-type pairs over which to compute the LAA. The first column indicates the chest region, and the second column indicates the chest type. Each element should be in the interal [0, 255]. If none specified, the pairs specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pheno_names : list of strings, optional Names of phenotypes to compute. These names must conform to the accepted phenotype names, listed above. If none are given, all will be computed. Specified names given here will take precedence over any specified in the constructor. Returns ------- df : pandas dataframe Dataframe containing info about machine, run time, and chest region chest type phenotype quantities. """ assert len(ct.shape) == len(lm.shape), \ "CT and label map are not the same dimension" dim = len(ct.shape) for i in xrange(0, dim): assert ct.shape[0] == lm.shape[0], \ "Disagreement in CT and label map dimension" assert type(cid) == str, "cid must be a string" self.cid_ = cid self._spacing = spacing phenos_to_compute = self.pheno_names_ if pheno_names is not None: phenos_to_compute = pheno_names elif self.requested_pheno_names is not None: phenos_to_compute = self.requested_pheno_names rs = None ts = None ps = None if chest_regions is not None: rs = chest_regions elif self.chest_regions_ is not None: rs = self.chest_regions_ if chest_types is not None: ts = chest_types elif self.chest_types_ is not None: ts = self.chest_types_ if pairs is not None: ps = pairs elif self.pairs_ is not None: ps = self.pairs_ parser = RegionTypeParser(lm) if rs == None and ts == None and ps == None: rs = parser.get_all_chest_regions() ts = parser.get_chest_types() ps = parser.get_all_pairs() lean_ct_mask = np.logical_and(ct >= -50, ct <= 90) # Now compute the phenotypes and populate the data frame c = ChestConventions() if rs is not None: for r in rs: if r != 0: mask = parser.get_mask(chest_region=r) lean_mask = np.logical_and(mask, lean_ct_mask) for n in phenos_to_compute: if 'lean' in n: self.add_pheno_group(ct, lean_mask, c.GetChestRegionName(r), c.GetChestWildCardName(), n) else: self.add_pheno_group(ct, mask, c.GetChestRegionName(r), c.GetChestWildCardName(), n) if ts is not None: for t in ts: if t != 0: mask = parser.get_mask(chest_type=t) lean_mask = np.logical_and(mask, lean_ct_mask) for n in phenos_to_compute: if 'lean' in n: self.add_pheno_group(ct, lean_mask, c.GetChestWildCardName(), c.GetChestTypeName(r), n) else: self.add_pheno_group(ct, mask, c.GetChestWildCardName(), c.GetChestTypeName(r), n) if ps is not None: for p in ps: if not (p[0] == 0 and p[1] == 0): mask = parser.get_mask(chest_region=p[0], chest_type=p[1]) lean_mask = np.logical_and(mask, lean_ct_mask) for n in phenos_to_compute: if 'lean' in n: self.add_pheno_group(ct, lean_mask, c.GetChestRegionName(p[0]), c.GetChestTypeName(p[1]), n) else: self.add_pheno_group(ct, mask, c.GetChestRegionName(p[0]), c.GetChestTypeName(p[1]), n) return self._df
def remap_lm(lm, region_maps=None, type_maps=None, pair_maps=None): """Overwrites values in an input label map using the specified mappings. Parameters ---------- lm : array The input data. Each value is assumed to be an unsigned short (16 bit) data type, where the least significant 8 bits encode the chest region, and the most significant 8 bits encode the chest type. region_maps : list of lists, optional Each element of the list is a 2-element list or a list with two elements, where the individual elements are strings indicating chest regions. The 2D lists / tuples indicate the mappings to be performed. E.g. [('LeftLung', 'WholeLung')] indicates that all occurrences of 'LeftLung' should be replaced with 'WholeLung'. All type information is preserved. type_maps : list of lists, optional Each element of the list is a 2-element list or a list with two elements, where the individual elements are strings indicating chest types. The 2D lists / tuples indicate the mappings to be performed. E.g. [('Airway', 'UndefinedType')] indicates that all occurrences of 'Airway' should be replaced with 'UndefinedType'. All region information is preserved. pairs_maps : list of lists of lists, optional Each element of the list is a 2-element list: the firs element is itself a 2-element list indicating a region-type pair; the second element is a 2-element region-type pair to be mapped to. String names are used to designate the regions and types. E.g. [['LeftLung', 'Vessel'], ['WholeLung', 'UndefinedType']] will map all occurrences of the 'LeftLung'-'Vessel' pair to 'WholeLung'-'UndefinedType'. Returns ------- remapped_lm : array A label map with the same dimensions as the input with labelings redefined according to the specified rules. """ remapped_lm = np.copy(lm) parser = RegionTypeParser(lm) lm_types = lm >> 8 lm_regions = lm - (lm >> 8 << 8) c = ChestConventions() if region_maps is not None: for m in xrange(0, len(region_maps)): assert len(region_maps[m]) == 2, "Mapping not understood" mask = \ parser.get_mask(chest_region=\ c.GetChestRegionValueFromName(region_maps[m][0])) lm_regions[mask] = \ c.GetChestRegionValueFromName(region_maps[m][1]) if type_maps is not None: for m in xrange(0, len(type_maps)): assert len(type_maps[m]) == 2, "Mapping not understood" mask = \ parser.get_mask(chest_type=\ c.GetChestTypeValueFromName(type_maps[m][0])) lm_types[mask] = \ c.GetChestTypeValueFromName(type_maps[m][1]) if pair_maps is not None: for m in xrange(0, len(pair_maps)): assert len(pair_maps[m]) == 2, "Mapping not understood" assert len(pair_maps[m][0]) == 2, "Mapping not understood" assert len(pair_maps[m][1]) == 2, "Mapping not understood" mask = \ parser.get_mask(chest_region=\ c.GetChestRegionValueFromName(pair_maps[m][0][0]), chest_type=\ c.GetChestTypeValueFromName(pair_maps[m][0][1])) lm_regions[mask] = \ c.GetChestRegionValueFromName(pair_maps[m][1][0]) lm_types[mask] = \ c.GetChestTypeValueFromName(pair_maps[m][1][1]) remapped_lm = (lm_types << 8) | lm_regions return remapped_lm
def execute(self, ct, lm, cid, chest_regions=None, chest_types=None, pairs=None): """Compute the phenotypes for the specified structures for the specified threshold values. Parameters ---------- ct : array, shape ( X, Y, Z ) The 3D CT image array lm : array, shape ( X, Y, Z ) The 3D label map array cid : string Case ID chest_regions : array, shape ( R ), optional Array of integers, with each element in the interval [0, 255], indicating the chest regions over which to compute the LAA. If none specified, the chest regions specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. chest_types : array, shape ( T ), optional Array of integers, with each element in the interval [0, 255], indicating the chest types over which to compute the LAA. If none specified, the chest types specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pairs : array, shape ( P, 2 ), optional Array of chest-region chest-type pairs over which to compute the LAA. The first column indicates the chest region, and the second column indicates the chest type. Each element should be in the interal [0, 255]. If none specified, the pairs specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. Returns ------- df : pandas dataframe Dataframe containing info about machine, run time, and chest region chest type phenotype quantities. """ assert len(ct.shape) == len(lm.shape), \ "CT and label map are not the same dimension" dim = len(ct.shape) for i in xrange(0, dim): assert ct.shape[0] == lm.shape[0], \ "Disagreement in CT and label map dimension" assert type(cid) == str, "cid must be a string" self.cid_ = cid rs = None ts = None ps = None if chest_regions is not None: rs = chest_regions elif self.chest_regions_ is not None: rs = self.chest_regions_ if chest_types is not None: ts = chest_types elif self.chest_types_ is not None: ts = self.chest_types_ if pairs is not None: ps = pairs elif self.pairs_ is not None: ps = self.pairs_ parser = RegionTypeParser(lm) if rs == None and ts == None and ps == None: rs = parser.get_all_chest_regions() ts = parser.get_chest_types() ps = parser.get_all_pairs() # Now compute the phenotypes and populate the data frame c = ChestConventions() if rs is not None: for r in rs: if r != 0: mask = parser.get_mask(chest_region=r) for tt in self.threshs_: pheno_name = 'LAA' + str(int(np.abs(np.round(tt)))) pheno_val = float( np.sum(ct[mask] <= tt)) / np.sum(mask) self.add_pheno([ c.GetChestRegionName(r), c.GetChestWildCardName() ], pheno_name, pheno_val) if ts is not None: for t in ts: if t != 0: mask = parser.get_mask(chest_type=t) for tt in self.threshs_: pheno_name = 'LAA' + str(int(np.abs(np.round(tt)))) pheno_val = float( np.sum(ct[mask] <= tt)) / np.sum(mask) self.add_pheno( [c.GetChestWildCardName(), c.GetChestTypeName(t)], pheno_name, pheno_val) if ps is not None: for p in ps: if not (p[0] == 0 and p[1] == 0): mask = parser.get_mask(chest_region=p[0], chest_type=p[1]) for tt in self.threshs_: pheno_name = 'LAA' + str(int(np.abs(np.round(tt)))) pheno_val = float( np.sum(ct[mask] <= tt)) / np.sum(mask) self.add_pheno([ c.GetChestRegionName(p[0]), c.GetChestTypeName(p[1]) ], pheno_name, pheno_val) return self._df
def execute(self, ct, lm, cid, spacing, chest_regions=None, chest_types=None, pairs=None, pheno_names=None): """Compute the phenotypes for the specified structures for the specified threshold values. The following values are computed for the specified structures. 'LAA950': fraction of the structure's region with CT HU values <= -950 'LAA910': fraction of the structure's region with CT HU values <= -910 'LAA856': fraction of the structure's region with CT HU values <= -856 'HAA700': fraction of the structure's region with CT HU values >= -700 'HAA600': fraction of the structure's region with CT HU values >= -600 'HAA500': fraction of the structure's region with CT HU values >= -500 'HAA250': fraction of the structure's region with CT HU values >= -250 'Perc10': HU value at the 10th percentile of the structure's HU histogram 'Perc15': HU value at the 15th percentile of the structure's HU histogram 'HUMean': Mean value of the structure's HU values 'HUStd': Standard deviation of the structure's HU values 'HUKurtosis': Kurtosis of the structure's HU values. Fisher's definition is used, meaning that normal distribution has kurtosis of 0. The calculation is corrected for statistical bias. 'HUSkewness': Skewness of the structure's HU values. The calculation is corrected for statistical bias. 'HUMode': Mode of the structure's HU values 'HUMedian': Median of the structure's HU values 'HUMin': Min HU value for the structure 'HUMax': Max HU value for the structure 'HUMean500': Mean CT value of the structure, but only considering CT values that are <= -500 HU 'HUStd500': Standard deviation of the structure's CT values, but only considering CT values that are <= -500 HU 'HUKurtosis500': Kurtosis of the structure's HU values, but only considering CT values that are <= -500 HU 'HUSkewness500': Skewness of the structure's HU values, but only considering CT values that are <= -500 HU 'HUMode500': Mode of the structure's HU values, but only considering CT values that are <= -500 HU 'HUMedian500': Median of the structure's HU values, but only considering CT values that are <= -500 HU 'HUMin500': Min HU value for the structure, but only considering CT values that are <= -500 HU 'HUMax500': Max HU value for the structure, but only considering CT values that are <= -500 HU 'Volume': Volume of the structure, measured in liters 'Mass': Mass of the structure measure in grams Parameters ---------- ct : array, shape ( X, Y, Z ) The 3D CT image array lm : array, shape ( X, Y, Z ) The 3D label map array cid : string Case ID spacing : array, shape ( 3 ) The x, y, and z spacing, respectively, of the CT volume chest_regions : array, shape ( R ), optional Array of integers, with each element in the interval [0, 255], indicating the chest regions over which to compute the LAA. If none specified, the chest regions specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. chest_types : array, shape ( T ), optional Array of integers, with each element in the interval [0, 255], indicating the chest types over which to compute the LAA. If none specified, the chest types specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pairs : array, shape ( P, 2 ), optional Array of chest-region chest-type pairs over which to compute the LAA. The first column indicates the chest region, and the second column indicates the chest type. Each element should be in the interal [0, 255]. If none specified, the pairs specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pheno_names : list of strings, optional Names of phenotypes to compute. These names must conform to the accepted phenotype names, listed above. If none are given, all will be computed. Specified names given here will take precedence over any specified in the constructor. Returns ------- df : pandas dataframe Dataframe containing info about machine, run time, and chest region chest type phenotype quantities. """ assert len(ct.shape) == len(lm.shape), \ "CT and label map are not the same dimension" dim = len(ct.shape) for i in xrange(0, dim): assert ct.shape[0] == lm.shape[0], \ "Disagreement in CT and label map dimension" assert type(cid) == str, "cid must be a string" self.cid_ = cid self._spacing = spacing phenos_to_compute = self.pheno_names_ if pheno_names is not None: phenos_to_compute = pheno_names elif self.requested_pheno_names is not None: phenos_to_compute = self.requested_pheno_names rs = None ts = None ps = None if chest_regions is not None: rs = chest_regions elif self.chest_regions_ is not None: rs = self.chest_regions_ if chest_types is not None: ts = chest_types elif self.chest_types_ is not None: ts = self.chest_types_ if pairs is not None: ps = pairs elif self.pairs_ is not None: ps = self.pairs_ parser = RegionTypeParser(lm) if rs == None and ts == None and ps == None: rs = parser.get_all_chest_regions() ts = parser.get_chest_types() ps = parser.get_all_pairs() # Now compute the phenotypes and populate the data frame c = ChestConventions() if rs is not None: for r in rs: if r != 0: mask = parser.get_mask(chest_region=r) for n in phenos_to_compute: self.add_pheno_group(ct, mask, c.GetChestRegionName(r), c.GetChestWildCardName(), n) if ts is not None: for t in ts: if t != 0: mask = parser.get_mask(chest_type=t) for n in phenos_to_compute: self.add_pheno_group(ct, mask, c.GetChestWildCardName(), c.GetChestTypeName(t), n) if ps is not None: for i in xrange(0, ps.shape[0]): if not (ps[i, 0] == 0 and ps[i, 1] == 0): mask = parser.get_mask(chest_region=int(ps[i, 0]), chest_type=int(ps[i, 1])) for n in phenos_to_compute: self.add_pheno_group( ct, mask, c.GetChestRegionName(int(ps[i, 0])), c.GetChestTypeName(int(ps[i, 1])), n) return self._df
def execute(self, ct, lm, cid, chest_regions=None, chest_types=None, pairs=None): """Compute the phenotypes for the specified structures for the specified threshold values. Parameters ---------- ct : array, shape ( X, Y, Z ) The 3D CT image array lm : array, shape ( X, Y, Z ) The 3D label map array cid : string Case ID chest_regions : array, shape ( R ), optional Array of integers, with each element in the interval [0, 255], indicating the chest regions over which to compute the LAA. If none specified, the chest regions specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. chest_types : array, shape ( T ), optional Array of integers, with each element in the interval [0, 255], indicating the chest types over which to compute the LAA. If none specified, the chest types specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pairs : array, shape ( P, 2 ), optional Array of chest-region chest-type pairs over which to compute the LAA. The first column indicates the chest region, and the second column indicates the chest type. Each element should be in the interal [0, 255]. If none specified, the pairs specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. Returns ------- df : pandas dataframe Dataframe containing info about machine, run time, and chest region chest type phenotype quantities. """ assert len(ct.shape) == len(lm.shape), "CT and label map are not the same dimension" dim = len(ct.shape) for i in xrange(0, dim): assert ct.shape[0] == lm.shape[0], "Disagreement in CT and label map dimension" assert type(cid) == str, "cid must be a string" self.cid_ = cid rs = None ts = None ps = None if chest_regions is not None: rs = chest_regions elif self.chest_regions_ is not None: rs = self.chest_regions_ if chest_types is not None: ts = chest_types elif self.chest_types_ is not None: ts = self.chest_types_ if pairs is not None: ps = pairs elif self.pairs_ is not None: ps = self.pairs_ parser = RegionTypeParser(lm) if rs == None and ts == None and ps == None: rs = parser.get_all_chest_regions() ts = parser.get_chest_types() ps = parser.get_all_pairs() # Now compute the phenotypes and populate the data frame c = ChestConventions() if rs is not None: for r in rs: if r != 0: mask = parser.get_mask(chest_region=r) for tt in self.threshs_: pheno_name = "LAA" + str(int(np.abs(np.round(tt)))) pheno_val = float(np.sum(ct[mask] <= tt)) / np.sum(mask) self.add_pheno([c.GetChestRegionName(r), c.GetChestWildCardName()], pheno_name, pheno_val) if ts is not None: for t in ts: if t != 0: mask = parser.get_mask(chest_type=t) for tt in self.threshs_: pheno_name = "LAA" + str(int(np.abs(np.round(tt)))) pheno_val = float(np.sum(ct[mask] <= tt)) / np.sum(mask) self.add_pheno([c.GetChestWildCardName(), c.GetChestTypeName(t)], pheno_name, pheno_val) if ps is not None: for p in ps: if not (p[0] == 0 and p[1] == 0): mask = parser.get_mask(chest_region=p[0], chest_type=p[1]) for tt in self.threshs_: pheno_name = "LAA" + str(int(np.abs(np.round(tt)))) pheno_val = float(np.sum(ct[mask] <= tt)) / np.sum(mask) self.add_pheno([c.GetChestRegionName(p[0]), c.GetChestTypeName(p[1])], pheno_name, pheno_val) return self._df
def execute(self, ct, lm, cid, spacing, chest_regions=None, chest_types=None, pairs=None, pheno_names=None): """Compute the phenotypes for the specified structures for the specified threshold values. The following values are computed for the specified structures. 'AxialCSA': Axial cross-sectional area 'CoronalCSA': Coronoal cross-sectional area 'SagittalCSA': Sagitall cross-sectional area 'HUMean': Mean value of the structure's HU values 'HUStd': Standard deviation of the structure's HU values 'HUKurtosis': Kurtosis of the structure's HU values. Fisher's definition is used, meaning that normal distribution has kurtosis of 0. The calculation is corrected for statistical bias. 'HUSkewness': Skewness of the structure's HU values. The calculation is corrected for statistical bias. 'HUMode': Mode of the structure's HU values 'HUMedian': Median of the structure's HU values 'HUMin': Min HU value for the structure 'HUMax': Max HU value for the structure The following set of phenotypes are identical to the above except that computation is isolated to the HU interval [-50, 90]. These phenotypes are capture lean muscle information and only have meaning for muscle structures. 'leanAxialCSA': Axial cross-sectional area 'leanCoronalCSA': Coronoal cross-sectional area 'leanSagittalCSA': Sagitall cross-sectional area 'leanHUMean': Mean value of the structure's HU values 'leanHUStd': Standard deviation of the structure's HU values 'leanHUKurtosis': Kurtosis of the structure's HU values. Fisher's definition is used, meaning that normal distribution has kurtosis of 0. The calculation is corrected for statistical bias. 'leanHUSkewness': Skewness of the structure's HU values. The calculation is corrected for statistical bias. 'leanHUMode': Mode of the structure's HU values 'leanHUMedian': Median of the structure's HU values 'leanHUMin': Min HU value for the structure 'leanHUMax': Max HU value for the structure Parameters ---------- ct : array, shape ( X, Y, Z ) The 3D CT image array lm : array, shape ( X, Y, Z ) The 3D label map array cid : string Case ID spacing : array, shape ( 3 ) The x, y, and z spacing, respectively, of the CT volume chest_regions : array, shape ( R ), optional Array of integers, with each element in the interval [0, 255], indicating the chest regions over which to compute the LAA. If none specified, the chest regions specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. chest_types : array, shape ( T ), optional Array of integers, with each element in the interval [0, 255], indicating the chest types over which to compute the LAA. If none specified, the chest types specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pairs : array, shape ( P, 2 ), optional Array of chest-region chest-type pairs over which to compute the LAA. The first column indicates the chest region, and the second column indicates the chest type. Each element should be in the interal [0, 255]. If none specified, the pairs specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pheno_names : list of strings, optional Names of phenotypes to compute. These names must conform to the accepted phenotype names, listed above. If none are given, all will be computed. Specified names given here will take precedence over any specified in the constructor. Returns ------- df : pandas dataframe Dataframe containing info about machine, run time, and chest region chest type phenotype quantities. """ print("Executing new\n"); assert len(ct.shape) == len(lm.shape), \ "CT and label map are not the same dimension" dim = len(ct.shape) for i in xrange(0, dim): assert ct.shape[0] == lm.shape[0], \ "Disagreement in CT and label map dimension" assert type(cid) == str, "cid must be a string" self.cid_ = cid self._spacing = spacing phenos_to_compute = self.pheno_names_ if pheno_names is not None: phenos_to_compute = pheno_names elif self.requested_pheno_names is not None: phenos_to_compute = self.requested_pheno_names rs = None ts = None ps = None if chest_regions is not None: rs = chest_regions elif self.chest_regions_ is not None: rs = self.chest_regions_ if chest_types is not None: ts = chest_types elif self.chest_types_ is not None: ts = self.chest_types_ if pairs is not None: ps = pairs elif self.pairs_ is not None: ps = self.pairs_ parser = RegionTypeParser(lm) if rs == None and ts == None and ps == None: rs = parser.get_all_chest_regions() ts = parser.get_chest_types() ps = parser.get_all_pairs() lean_ct_mask = np.logical_and(ct >= -50, ct <= 90) # Now compute the phenotypes and populate the data frame c = ChestConventions() if rs is not None: for r in rs: if r != 0: mask = parser.get_mask(chest_region=r) lean_mask = np.logical_and(mask, lean_ct_mask) for n in phenos_to_compute: if 'lean' in n: self.add_pheno_group(ct, lean_mask, c.GetChestRegionName(r), c.GetChestWildCardName(), n) else: self.add_pheno_group(ct, mask, c.GetChestRegionName(r), c.GetChestWildCardName(), n) if ts is not None: for t in ts: if t != 0: mask = parser.get_mask(chest_type=t) lean_mask = np.logical_and(mask, lean_ct_mask) for n in phenos_to_compute: if 'lean' in n: self.add_pheno_group(ct, lean_mask, c.GetChestWildCardName(), c.GetChestTypeName(r), n) else: self.add_pheno_group(ct, mask, c.GetChestWildCardName(), c.GetChestTypeName(r), n) if ps is not None: for p in ps: if not (p[0] == 0 and p[1] == 0): mask = parser.get_mask(chest_region=p[0], chest_type=p[1]) lean_mask = np.logical_and(mask, lean_ct_mask) for n in phenos_to_compute: if 'lean' in n: self.add_pheno_group(ct, lean_mask, c.GetChestRegionName(p[0]), c.GetChestTypeName(p[1]), n) else: self.add_pheno_group(ct, mask, c.GetChestRegionName(p[0]), c.GetChestTypeName(p[1]), n) return self._df
def execute(self, ct, lm, cid, spacing, chest_regions=None, chest_types=None, pairs=None, pheno_names=None): """Compute the phenotypes for the specified structures for the specified threshold values. The following values are computed for the specified structures. 'LAA950': fraction of the structure's region with CT HU values <= -950 'LAA910': fraction of the structure's region with CT HU values <= -910 'LAA856': fraction of the structure's region with CT HU values <= -856 'HAA700': fraction of the structure's region with CT HU values >= -700 'HAA600': fraction of the structure's region with CT HU values >= -600 'HAA500': fraction of the structure's region with CT HU values >= -500 'HAA250': fraction of the structure's region with CT HU values >= -250 'Perc10': HU value at the 10th percentile of the structure's HU histogram 'Perc15': HU value at the 15th percentile of the structure's HU histogram 'HUMean': Mean value of the structure's HU values 'HUStd': Standard deviation of the structure's HU values 'HUKurtosis': Kurtosis of the structure's HU values. Fisher's definition is used, meaning that normal distribution has kurtosis of 0. The calculation is corrected for statistical bias. 'HUSkewness': Skewness of the structure's HU values. The calculation is corrected for statistical bias. 'HUMode': Mode of the structure's HU values 'HUMedian': Median of the structure's HU values 'HUMin': Min HU value for the structure 'HUMax': Max HU value for the structure 'HUMean500': Mean CT value of the structure, but only considering CT values that are <= -500 HU 'HUStd500': Standard deviation of the structure's CT values, but only considering CT values that are <= -500 HU 'HUKurtosis500': Kurtosis of the structure's HU values, but only considering CT values that are <= -500 HU 'HUSkewness500': Skewness of the structure's HU values, but only considering CT values that are <= -500 HU 'HUMode500': Mode of the structure's HU values, but only considering CT values that are <= -500 HU 'HUMedian500': Median of the structure's HU values, but only considering CT values that are <= -500 HU 'HUMin500': Min HU value for the structure, but only considering CT values that are <= -500 HU 'HUMax500': Max HU value for the structure, but only considering CT values that are <= -500 HU 'Volume': Volume of the structure, measured in liters 'Mass': Mass of the structure measure in grams 'NormalParenchyma': A "chest-type-based" phenotype. It is the percentage of a given region occupied by the 'NormalParenchyma' chest-type 'PanlobularEmphysema': A "chest-type-based" phenotype. It is the percentage of a given region occupied by the 'PanlobularEmphysema' chest-type 'ParaseptalEmphysema': A "chest-type-based" phenotype. It is the percentage of a given region occupied by the 'ParaseptalEmphysema' chest-type 'MildCentrilobularEmphysema': A "chest-type-based" phenotype. It is the percentage of a given region occupied by the 'MildCentrilobularEmphysema' chest-type 'ModerateCentrilobularEmphysema': A "chest-type-based" phenotype. It is the percentage of a given region occupied by the 'ModerateCentrilobularEmphysema' chest-type 'SevereCentrilobularEmphysema': A "chest-type-based" phenotype. It is the percentage of a given region occupied by the 'SevereCentrilobularEmphysema' chest-type 'MildParaseptalEmphysema': A "chest-type-based" phenotype. It is the percentage of a given region occupied by the 'MildParaseptalEmphysema' chest-type Parameters ---------- ct : array, shape ( X, Y, Z ) The 3D CT image array lm : array, shape ( X, Y, Z ) The 3D label map array cid : string Case ID spacing : array, shape ( 3 ) The x, y, and z spacing, respectively, of the CT volume chest_regions : array, shape ( R ), optional Array of integers, with each element in the interval [0, 255], indicating the chest regions over which to compute the LAA. If none specified, the chest regions specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. chest_types : array, shape ( T ), optional Array of integers, with each element in the interval [0, 255], indicating the chest types over which to compute the LAA. If none specified, the chest types specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pairs : array, shape ( P, 2 ), optional Array of chest-region chest-type pairs over which to compute the LAA. The first column indicates the chest region, and the second column indicates the chest type. Each element should be in the interal [0, 255]. If none specified, the pairs specified in the class constructor will be used. If chest regions, chest types, and chest pairs are left unspecified both here and in the constructor, then the complete set of entities found in the label map will be used. pheno_names : list of strings, optional Names of phenotypes to compute. These names must conform to the accepted phenotype names, listed above. If none are given, all will be computed. Specified names given here will take precedence over any specified in the constructor. Returns ------- df : pandas dataframe Dataframe containing info about machine, run time, and chest region chest type phenotype quantities. """ assert len(ct.shape) == len(lm.shape), \ "CT and label map are not the same dimension" dim = len(ct.shape) for i in xrange(0, dim): assert ct.shape[0] == lm.shape[0], \ "Disagreement in CT and label map dimension" assert type(cid) == str, "cid must be a string" self.cid_ = cid self._spacing = spacing phenos_to_compute = self.pheno_names_ if pheno_names is not None: phenos_to_compute = pheno_names elif self.requested_pheno_names is not None: phenos_to_compute = self.requested_pheno_names rs = None ts = None ps = None if chest_regions is not None: rs = chest_regions elif self.chest_regions_ is not None: rs = self.chest_regions_ if chest_types is not None: ts = chest_types elif self.chest_types_ is not None: ts = self.chest_types_ if pairs is not None: ps = pairs elif self.pairs_ is not None: ps = self.pairs_ parser = RegionTypeParser(lm) if rs == None and ts == None and ps == None: rs = parser.get_all_chest_regions() ts = parser.get_chest_types() ps = parser.get_all_pairs() # Now compute the phenotypes and populate the data frame c = ChestConventions() if rs is not None: for r in rs: if r != 0: mask = parser.get_mask(chest_region=r) for n in phenos_to_compute: # First check to see if 'pheno_name' is a valid chest # type. If it is, then it as a "chest-type-based" # phenotype, and it is computed as the percentage of the # given region occupied by the given chest-type if c.IsChestType(n): chest_type_val = \ c.GetChestTypeValueFromName(n) tmp_mask = \ parser.get_mask(chest_type=chest_type_val) pheno_val = \ np.sum(np.logical_and(tmp_mask, mask))/\ float(np.sum(mask)) self.add_pheno([c.GetChestRegionName(r), c.GetChestWildCardName()], n, pheno_val) else: self.add_pheno_group(ct, mask, c.GetChestRegionName(r), c.GetChestWildCardName(), n) if ts is not None: for t in ts: if t != 0: mask = parser.get_mask(chest_type=t) for n in phenos_to_compute: self.add_pheno_group(ct, mask, c.GetChestWildCardName(), c.GetChestTypeName(t), n) if ps is not None: for i in xrange(0, ps.shape[0]): if not (ps[i, 0] == 0 and ps[i, 1] == 0): mask = parser.get_mask(chest_region=int(ps[i, 0]), chest_type=int(ps[i, 1])) for n in phenos_to_compute: self.add_pheno_group(ct, mask, c.GetChestRegionName(int(ps[i, 0])), c.GetChestTypeName(int(ps[i, 1])), n) return self._df