def combineGnabCnvr(dataD):

    print " "
    print " ************************************************************* "
    print " ************************************************************* "
    print " "
    print " in combineGnabCnvr ... "

    # check that the input feature matrix looks ok ...
    try:
        numRow = len(dataD['rowLabels'])
        numCol = len(dataD['colLabels'])
        rowLabels = dataD['rowLabels']
        colLabels = dataD['colLabels']
        print " %d rows x %d columns " % (numRow, numCol)
        # print rowLabels[:5]
        # print rowLabels[-5:]
    except:
        print " ERROR in combineGnabCnvr ??? bad data ??? "
        return (dataD)

    # next, we need to find all of the GNAB features and all of the CNVR
    # features
    print " --> assigning gnab / cnvr flags ... "

    gnabFeatIncSubstrings = [ ":y_n", ":code_potential" ]
    gnabFeatAmpSubstrings = [ ":y_amp", ":cp_amp" ]
    gnabFeatDelSubstrings = [ ":y_del", ":cp_del" ]
    cnvrFeatExcSubstrings = [ "Gistic" ]

    isGnab = setFeatBits(rowLabels, "B:GNAB:", gnabFeatIncSubstrings, [])
    isCnvr = setFeatBits(rowLabels, "N:CNVR:", [], cnvrFeatExcSubstrings)

    print len(isGnab), max(isGnab)
    print len(isCnvr), max(isCnvr)

    if (not max(isGnab) and not max(isCnvr)):
        print " missing either GNAB or CNVR features ... "
        return (dataD)

    # now we need to map each of the GNAB features to one or more CNVR features
    mapVec = [0] * numRow

    for iR in range(numRow):

        if (iR % 1000 == 0):
            print iR, numRow

        if (isGnab[iR]):
            mapVec[iR] = []
            gnabLabel = rowLabels[iR]

            try:
                gnabTokens = gnabLabel.split(':')
                gnabChrName = gnabTokens[3].upper()
                gnabStart = int(gnabTokens[4])
                gnabStop = int(gnabTokens[5])
            except:
                print " FAILED to parse GNAB feature name ??? ", gnabLabel
                continue

            # avoid X and Y chromosome genes ...
            if (gnabChrName.endswith("X")):
                continue
            if (gnabChrName.endswith("Y")):
                continue

            for jR in range(numRow):
                if (isCnvr[jR]):
                    cnvrLabel = rowLabels[jR]
                    cnvrTokens = cnvrLabel.split(':')
                    cnvrChrName = cnvrTokens[3].upper()
                    if (gnabChrName != cnvrChrName):
                        continue
                    # print " comparing ... ", gnabLabel, cnvrLabel
                    cnvrStart = int(cnvrTokens[4])
                    if (gnabStop < cnvrStart):
                        continue
                    cnvrStop = int(cnvrTokens[5])
                    if (gnabStart > cnvrStop):
                        continue
                    mapVec[iR] += [jR]
                    # print " found match! ", gnabLabel, cnvrLabel, iR, jR,
                    # mapVec[iR]

            if (0):
                if (len(mapVec[iR]) > 5):
                    print iR, gnabLabel, len(mapVec[iR])
                    for kR in mapVec[iR]:
                        print "         ", kR, rowLabels[kR]
                # sys.exit(-1)

    # now we need to actually loop over the data ...
    dMat = dataD['dataMatrix']

    # -------------------------------------------------------------------------
    if (0):
        # FIRST we want to check for any "adjacent normal" samples and set those to 0 ...
        # --> ACTUALLY, deciding NOT to do this anymore ( 31 oct 2012 )  NEW CHANGE
        numGNABfeat = 0
        numCNVRfeat = 0
        for iRow in range(numRow):
            curFeature = rowLabels[iRow]
            if (curFeature.startswith("B:GNAB:")):
                numGNABfeat += 1
            elif (curFeature.startswith("N:CNVR:")):
                numCNVRfeat += 1
        print " number of GNAB features : %d " % (numGNABfeat)
        print " number of CNVR features : %d " % (numCNVRfeat)
        print " "

        numGNABset = 0
        numCNVRset = 0
        numGNABfeat = 0
        numCNVRfeat = 0
        numNormalCol = 0
        for iCol in range(numCol):
            curLabel = colLabels[iCol]
            if (curLabel.startswith("TCGA-")):
                if (len(curLabel) >= 15):
                    sampleType = curLabel[13:15]
                    if (sampleType == '11'):
                        numNormalCol += 1
                        # print iCol, curLabel
                        for iRow in range(numRow):
                            curFeature = rowLabels[iRow]
                            if (curFeature.startswith("B:GNAB:")):
                                # print curFeature, dMat[iRow][iCol]
                                if (dMat[iRow][iCol] == "NA" or dMat[iRow][iCol] == NA_VALUE):
                                    dMat[iRow][iCol] = 0
                                    numGNABset += 1
                            elif (curFeature.startswith("N:CNVR:")):
                                if (curFeature.find(":chrX:") > 0):
                                    continue
                                if (curFeature.find(":chrY:") > 0):
                                    continue
                                # print curFeature, dMat[iRow][iCol]
                                if (dMat[iRow][iCol] == "NA" or dMat[iRow][iCol] == NA_VALUE):
                                    dMat[iRow][iCol] = 0.
                                    numCNVRset += 1
    # -------------------------------------------------------------------------

    ## cnvrThreshold = 2.
    ## cnvrThreshold = 1.
    cnvrAmpThresh =  0.30
    cnvrDelThresh = -0.46

    print " --> now checking for deletions and amplifications ... ", cnvrAmpThresh, cnvrDelThresh
    print "     and creating new y_del and y_amp features "

    numNewFeat = 0
    newNameVec = []
    newDataMat = []

    for iR in range(numRow):

        if (iR % 1000 == 0):
            print iR, numRow

        if (isGnab[iR]):

            print " "
            print " having a look at this feature: "
            print iR, rowLabels[iR], len(mapVec[iR])
            print mapVec[iR]

            # how often is this gene mutated?
            numYes = 0
            numDel = 0
            numAmp = 0
            numYesDel = 0
            numYesAmp = 0

            maxCN = -999.
            minCN =  999.

            for iCol in range(numCol):
                mutFlag = 0
                ampFlag = 0
                delFlag = 0
                for jR in mapVec[iR]:
                    if (dMat[iR][iCol] == 1):
                        mutFlag = 1
                    if (dMat[jR][iCol] == NA_VALUE):
                        continue
                    if (dMat[jR][iCol] > maxCN):
                        maxCN = dMat[jR][iCol]
                    if (dMat[jR][iCol] < minCN):
                        minCN = dMat[jR][iCol]
                    if (dMat[jR][iCol] < cnvrDelThresh):
                        delFlag = 1
                    if (dMat[jR][iCol] > cnvrAmpThresh):
                        ampFlag = 1
                numYes += mutFlag
                numDel += delFlag
                numAmp += ampFlag
                if (mutFlag or delFlag): numYesDel += 1
                if (mutFlag or ampFlag): numYesAmp += 1

            addDelFeat = 0
            addAmpFeat = 0
            fThresh = 0.025
            if (numYes + numAmp + numDel > 0):
                print "         --> %3d mutations (%3d mut or del, %3d mut or amp) " % \
                                ( numYes, numYesDel, numYesAmp )
                print "             %3d deletions " % numDel, minCN
                print "             %3d amplifications " % numAmp, maxCN
                if (numYesDel > 0):
                    delFrac1 = float(numYesDel-numYes)/float(numCol)
                    delFrac2 = float(numYesDel-numDel)/float(numCol)
                    delFrac3 = 0
                    if ( numYes > 0 ): delFrac3 += float(numYesDel/numYes)
                    if ( numDel > 0 ): delFrac3 += float(numYesDel/numDel)
                    if ( delFrac1>fThresh and delFrac2>fThresh ):
                        print "                 deletion looks significant      ", numYesDel, numYes, numDel, numCol, delFrac1, delFrac2, delFrac3
                        addDelFeat = 1
                    else:
                        print "                 deletion does not seem significant (?) ", numYesDel, numYes, numDel, numCol, delFrac1, delFrac2, delFrac3
                if (numYesAmp > 0):
                    ampFrac1 = float(numYesAmp-numYes)/float(numCol)
                    ampFrac2 = float(numYesAmp-numAmp)/float(numCol)
                    ampFrac3 = 0
                    if ( numYes > 0 ): ampFrac3 += float(numYesAmp/numYes)
                    if ( numAmp > 0 ): ampFrac3 += float(numYesAmp/numAmp)
                    if ( ampFrac1>fThresh and ampFrac2>fThresh ):
                        print "                 amplification looks significant ", numYesAmp, numYes, numAmp, numCol, ampFrac1, ampFrac2, ampFrac3
                        addAmpFeat = 1
                    else:
                        print "                 amplification does not seem significant (?) ", numYesAmp, numYes, numAmp, numCol, ampFrac1, ampFrac2, ampFrac3

            ## add the "DEL" feature if appropriate ...
            if ( addDelFeat ):
                numNewFeat += 1
                curFeatName = rowLabels[iR]
                newFeatName = makeNewFeatureName(curFeatName, gnabFeatIncSubstrings, gnabFeatDelSubstrings)
                print "         newFeatName <%s> " % newFeatName

                # make sure that there is not already a feature by this name!!!
                addFeat = 1
                for aLabel in rowLabels:
                    if (aLabel == newFeatName):
                        addFeat = 0
                        print "             oops ??? <%s> already exists ??? " % aLabel

                if (addFeat):
                    print "     --> adding this new feature: ", newFeatName
                    newNameVec += [newFeatName]
                    newDataMat += [numpy.zeros(numCol)]
                    numBitsOn = 0
                    for iCol in range(numCol):

                        # we need to start with NA
                        newDataMat[-1][iCol] = NA_VALUE

                        # if we already have a 'yes' for the mutation, that's
                        # all we need ...
                        if (dMat[iR][iCol] == 1):
                            newDataMat[-1][iCol] = 1
                            numBitsOn += 1
                            continue

                        # if not, then check for deletions ...
                        for jR in mapVec[iR]:
                            if (dMat[jR][iCol] == NA_VALUE): continue
                            if (newDataMat[-1][iCol] == 1): continue
                            if (dMat[jR][iCol] < cnvrDelThresh):
                                newDataMat[-1][iCol] = 1
                                numBitsOn += 1

                        # if we have set this bit we are done ...
                        if (newDataMat[-1][iCol] == 1): continue

                        # and otherwise if we have no mutation, set it to 0
                        if (dMat[iR][iCol] == 0): newDataMat[-1][iCol] = 0

                    print "         number of bits set: ", numBitsOn


            ## add the "AMP" feature if appropriate ...
            if ( addAmpFeat ):
                numNewFeat += 1
                curFeatName = rowLabels[iR]
                newFeatName = makeNewFeatureName(curFeatName, gnabFeatIncSubstrings, gnabFeatAmpSubstrings)
                print "         newFeatName <%s> " % newFeatName

                # make sure that there is not already a feature by this name!!!
                addFeat = 1
                for aLabel in rowLabels:
                    if (aLabel == newFeatName):
                        addFeat = 0
                        print "             oops ??? <%s> already exists ??? " % aLabel

                if (addFeat):
                    print "     --> adding this new feature: ", newFeatName
                    newNameVec += [newFeatName]
                    newDataMat += [numpy.zeros(numCol)]
                    numBitsOn = 0
                    for iCol in range(numCol):

                        # we need to start with NA
                        newDataMat[-1][iCol] = NA_VALUE

                        # if we already have a 'yes' for the mutation, that's
                        # all we need ...
                        if (dMat[iR][iCol] == 1):
                            newDataMat[-1][iCol] = 1
                            numBitsOn += 1
                            continue
                        # if not, then check for amplifications ...
                        for jR in mapVec[iR]:
                            if (dMat[jR][iCol] == NA_VALUE): continue
                            if (newDataMat[-1][iCol] == 1): continue
                            if (dMat[jR][iCol] > cnvrAmpThresh):
                                newDataMat[-1][iCol] = 1
                                numBitsOn += 1

                        # if we have set this bit we are done ...
                        if (newDataMat[-1][iCol] == 1): continue

                        # and otherwise if we have no mutation, set it to 0
                        if (dMat[iR][iCol] == 0): newDataMat[-1][iCol] = 0

                    print "         number of bits set: ", numBitsOn


    # if ( numNewFeat == 0 ):
    # print " --> NO new features "
    # print " --> finished with combineGnabCnvr ... "
    # return ( dataD )

    print " "
    print " --> number of new features : ", numNewFeat
    if ( 0 ):
        if (numNewFeat > 0):
            print len(newNameVec)
            print len(newDataMat), len(newDataMat[0])
            for ii in range(numNewFeat):
                if (newNameVec[ii].find("CSMD1") > 0):
                    print newNameVec[ii]
                    print newDataMat[ii]
            print " "

    # now we need to append these new features to the input data matrix
    newRowLabels = [0] * (numRow + numNewFeat)
    newMatrix = [0] * (numRow + numNewFeat)
    for iR in range(numRow):
        newRowLabels[iR] = rowLabels[iR]
        newMatrix[iR] = dMat[iR]
    for iR in range(numNewFeat):
        newRowLabels[iR + numRow] = newNameVec[iR]
        newMatrix[iR + numRow] = newDataMat[iR]

    dataD['rowLabels'] = newRowLabels
    dataD['dataMatrix'] = newMatrix

    print " "
    print " --> finished with combineGnabCnvr ... "
    print " "

    return (dataD)