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
Example #3
0
    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
Example #4
0
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
Example #5
0
    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