Split a phenotype on a scored_call and if no label is specified
        use the format '<phenotype> <scored_call><+/->'
        to specify a label give the positive and negative label

        Args:
            phenotype (str): name of the phenotype to threshold
            scored_name (str): scored call name to apply value from
            positive_label (str): name to apply for positive lable (default: <phenotype> <scored_call>+)
            negative_label (str): name to apply for negative lable (default: <phenotype> <scored_call>-)

        Returns:
            CellDataFrame: The CellDataFrame modified.

def threshold(self,phenotype,scored_name,positive_label=None,negative_label=None):
        """
        Split a phenotype on a scored_call and if no label is specified
        use the format '<phenotype> <scored_call><+/->'
        to specify a label give the positive and negative label

        Args:
            phenotype (str): name of the phenotype to threshold
            scored_name (str): scored call name to apply value from
            positive_label (str): name to apply for positive lable (default: <phenotype> <scored_call>+)
            negative_label (str): name to apply for negative lable (default: <phenotype> <scored_call>-)

        Returns:
            CellDataFrame: The CellDataFrame modified.
        """
        if positive_label is None and negative_label is not None or \
           negative_label is None and positive_label is not None: raise ValueError("Error if you want to specify labels, give both positive and negative")
        if phenotype not in self.phenotypes: raise ValueError("Error phenotype "+str(phenotype)+" is not in the data.")
        if scored_name not in self.scored_names: raise ValueError("Error scored_name "+str(scored_name)+" is not in the data.")
        if positive_label is None and negative_label is None:
            positive_label = phenotype+' '+scored_name+'+'
            negative_label = phenotype+' '+scored_name+'-'
        elif positive_label == negative_label: raise ValueError("Cant have the same label for positive and negative.")
        def _swap_in(d,pheno,scored,phenotype_calls,scored_calls,pos,neg):
            if pheno not in phenotype_calls.keys(): return d
            keepers = [(k,v) for k,v in phenotype_calls.items() if k!=phenotype]
            if scored not in scored_calls.keys(): raise ValueError("Error scored calls are not unified across samples")
            scored_value = scored_calls[scored]
            phenotype_value = phenotype_calls[pheno]
            if phenotype_value == 0:
                keepers += [(pos,0),(neg,0)]
            elif scored_value == 1:
                keepers += [(pos,1),(neg,0)]
            elif scored_value == 0:
                keepers += [(pos,0),(neg,1)]
            else: raise ValueError("Format error.  These values should only ever be zero or one.")
            return dict(keepers)
        data = self.copy()
        data['phenotype_calls'] = self.apply(lambda x:
                _swap_in(x,phenotype,scored_name,x['phenotype_calls'],x['scored_calls'],positive_label,negative_label)
            ,1)
        def _set_label(d):
            vals = [k for k,v in d.items() if v==1]
            return np.nan if len(vals) == 0 else vals[0]
        data['phenotype_label'] = data.apply(lambda x:
                _set_label(x['phenotype_calls'])
            ,1)
        return data.copy()