clf_heart = joblib.load( args.detector + '/clf_heart' )
reg_heart = joblib.load( args.detector + '/reg_heart' )

clf_heart.set_params(n_jobs=args.n_jobs)
reg_heart.set_params(n_jobs=args.n_jobs)

print "done loading detectors"
print "preprocessing..."

img = irtk.imread( args.input, dtype='float32', force_neurological=True )

grad = irtk.Image(nd.gaussian_gradient_magnitude( img, 0.5 ),
              img.get_header())

sat = integral_image(img)
sat_grad = integral_image(grad)

blurred_img = nd.gaussian_filter(img,0.5)
gradZ = nd.sobel( blurred_img, axis=0 ).astype('float32')
gradY = nd.sobel( blurred_img, axis=1 ).astype('float32')
gradX = nd.sobel( blurred_img, axis=2 ).astype('float32')

irtk.imwrite(args.output + "/img.nii.gz", img)
irtk.imwrite(args.output + "/grad.nii.gz", grad)

print "done preprocessing"

del blurred_img
del grad
def get_training_data_regression( img, seg ):
    seg = irtk.imread( seg, dtype='int32', force_neurological=True )
    img = irtk.imread( img, dtype='int32', force_neurological=True )

    #u0,v0,w0 = get_orientation_training(seg)
    brain_center, heart_center, left_lung, right_lung = get_centers(seg)
    
    grad = irtk.Image(nd.gaussian_gradient_magnitude( img, 0.5 ),
                      img.get_header())

    blurred_img = nd.gaussian_filter(img,0.5)
    gradZ = nd.sobel( blurred_img, axis=0 ).astype('float32')
    gradY = nd.sobel( blurred_img, axis=1 ).astype('float32')
    gradX = nd.sobel( blurred_img, axis=2 ).astype('float32')

    new_seg = irtk.zeros( seg.get_header() )
    new_seg[seg==3] = 1 # lung 1
    new_seg[seg==4] = 1 # lung 2
    new_seg[seg==5] = 2 # heart
    new_seg[seg==8] = 3 # liver
    seg = new_seg

    center1 =  np.array(nd.center_of_mass( (seg == 1).view(np.ndarray) ),
                        dtype='float32')
    center2 =  np.array(nd.center_of_mass( (seg == 2).view(np.ndarray) ),
                        dtype='float32')
    center3 =  np.array(nd.center_of_mass( (seg == 3).view(np.ndarray) ),
                        dtype='float32')
    
    sat = integral_image(img)
    sat_grad = integral_image(grad)

    m = np.zeros(img.shape, dtype='uint8')
    m[brain_center[0],
      brain_center[1],
      brain_center[2]] = 1
    
    X = []
    Y = []
    for l in range(1,nb_labels):
        coords = np.argwhere(seg==l)

        coords = coords[np.random.randint( 0,
                                           coords.shape[0],
                                           args.n_samples)].astype('int32')

        if args.not_centered:
            x1 = get_block_comparisons_cpp( sat, coords,
                                            offsets1, sizes1,
                                            offsets2, sizes2,n_jobs=args.n_jobs )
            x2 = get_block_comparisons_cpp( sat_grad, coords,
                                            offsets3, sizes3,
                                            offsets4, sizes4,
                                            n_jobs=args.n_jobs )
            x_grad1 = get_grad( coords.astype('int32'), offsets5.astype('int32'),
                                gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32') )
            x_grad2 = get_grad( coords.astype('int32'), offsets6.astype('int32'),
                                gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32') )
        else:
            # u = np.tile(u0,(coords.shape[0],1))
            # v = np.tile(v0,(coords.shape[0],1))
            # w = np.tile(w0,(coords.shape[0],1))
            u,v,w = get_orientation_training_jitter( brain_center,
                                                     heart_center,
                                                     left_lung,
                                                     right_lung,
                                                     coords.shape[0],
                                                     brain_jitter=args.brain_jitter,
                                                     heart_jitter=args.heart_jitter,
                                                     lung_jitter=args.lung_jitter )

            x1 = get_block_comparisons_cpp_uvw( sat, coords,
                                                w,v,u,
                                                offsets1, sizes1,
                                                offsets2, sizes2,n_jobs=args.n_jobs )
            x2 = get_block_comparisons_cpp_uvw( sat_grad, coords,
                                                w,v,u,
                                                offsets3, sizes3,
                                                offsets4, sizes4,
                                                n_jobs=args.n_jobs )
            x3 = get_grad_comparisons_cpp_uvw( gradZ, gradY, gradX,
                                               coords,
                                               offsets5, offsets6,
                                               w,v,u,
                                               n_jobs=args.n_jobs )
            # x_grad1 = get_grad_uvw( coords.astype('int32'), offsets5.astype('int32'),
            #                         gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'),
            #                         w.astype('float32'), v.astype('float32'), u.astype('float32') )

            # x_grad2 = get_grad_uvw( coords.astype('int32'), offsets6.astype('int32'),
            #                         gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'),
            #                         w.astype('float32'), v.astype('float32'), u.astype('float32') )
             
        #x = np.concatenate( ( x1, x2, x_grad1 > x_grad2 ), axis=1 )
        x = np.concatenate( ( x1, x2, x3 ), axis=1 )

        if l == 1:
            y = center1[np.newaxis,...] - coords.astype('float32')
            if not args.not_centered:
                y = np.concatenate( ( (y*w).sum(axis=1)[...,np.newaxis],
                                      (y*v).sum(axis=1)[...,np.newaxis],
                                      (y*u).sum(axis=1)[...,np.newaxis] ),
                                    axis=1 )
        elif l == 2:
            y = center2[np.newaxis,...] - coords.astype('float32')
            if not args.not_centered:
                y = np.concatenate( ( (y*w).sum(axis=1)[...,np.newaxis],
                                      (y*v).sum(axis=1)[...,np.newaxis],
                                      (y*u).sum(axis=1)[...,np.newaxis] ),
                                    axis=1 )
        else:
            y = center3[np.newaxis,...] - coords.astype('float32')
            if not args.not_centered:
                y = np.concatenate( ( (y*w).sum(axis=1)[...,np.newaxis],
                                      (y*v).sum(axis=1)[...,np.newaxis],
                                      (y*u).sum(axis=1)[...,np.newaxis] ),
                                    axis=1 )

        X.append(x)
        Y.append(y)
            
    return X,Y
def run( o_size, d_size):
    offsets1 = np.random.randint( -o_size, o_size+1, size=(n_tests,3) ).astype('int32')
    sizes1 = np.random.randint( 0, d_size+1, size=(n_tests,1) ).astype('int32')             
    offsets2 = np.random.randint( -o_size, o_size+1, size=(n_tests,3) ).astype('int32')
    sizes2 = np.random.randint( 0, d_size+1, size=(n_tests,1) ).astype('int32')
    offsets3 = np.random.randint( -o_size, o_size+1, size=(n_tests,3) ).astype('int32')
    sizes3 = np.random.randint( 0, d_size+1, size=(n_tests,1) ).astype('int32')             
    offsets4 = np.random.randint( -o_size, o_size+1, size=(n_tests,3) ).astype('int32')
    sizes4 = np.random.randint( 0, d_size+1, size=(n_tests,1) ).astype('int32') 
    offsets5 = np.random.randint( -o_size, o_size+1, size=(n_tests/3,3) ).astype('int32')
    offsets6 = np.random.randint( -o_size, o_size+1, size=(n_tests/3,3) ).astype('int32')

    # we use only squares for rotation invariance
    sizes1 = np.tile(sizes1,(1,3))
    sizes2 = np.tile(sizes2,(1,3))
    sizes3 = np.tile(sizes3,(1,3))
    sizes4 = np.tile(sizes4,(1,3))
    
    X_train = []
    Y_train = []
    X_test = []
    Y_test = []

    n = 0
    for f in all_files:
        n += 1
        patient_id = os.path.basename(f)[:-len("_img.nii.gz")]
        img = irtk.imread( f, dtype='int32', force_neurological=True )
        seg = irtk.imread( myfolder + "/" + patient_id + "_seg.nii.gz", dtype='int32', force_neurological=True )

        brain_center, heart_center, left_lung, right_lung = get_centers(seg)
    
        grad = irtk.Image(nd.gaussian_gradient_magnitude( img, 0.5 ),
                          img.get_header())

        blurred_img = nd.gaussian_filter(img,0.5)
        gradZ = nd.sobel( blurred_img, axis=0 )
        gradY = nd.sobel( blurred_img, axis=1 )
        gradX = nd.sobel( blurred_img, axis=2 )

        new_seg = irtk.zeros( seg.get_header() )
        new_seg[seg==5] = 1 # heart
        seg = new_seg

        sat = integral_image(img)
        sat_grad = integral_image(grad)

        m = np.zeros(img.shape, dtype='uint8')
        m[brain_center[0],
          brain_center[1],
          brain_center[2]] = 1

        narrow_band = nd.distance_transform_edt(np.logical_not(m))
        narrow_band[narrow_band<30] = 0
        narrow_band[narrow_band>120] = 0
        narrow_band[img==0] = 0
    
        X = []
        Y = []
        for l in range(2):
            coords = np.argwhere(np.logical_and(narrow_band>0,seg==l))

            if l==0:
                coords = coords[np.random.randint( 0,
                                                   coords.shape[0],
                                                   n_samples)].astype('int32')
            else:
                coords = coords[np.random.randint( 0,
                                                   coords.shape[0],
                                                   n_samples)].astype('int32')

            if l == 0:
                u,v,w = get_random_orientation(coords.shape[0])
            else:
                u,v,w = get_orientation_training_jitter( brain_center,
                                                         heart_center,
                                                         left_lung,
                                                         right_lung,
                                                         coords.shape[0],
                                                         brain_jitter=10,
                                                         heart_jitter=5,
                                                         lung_jitter=5 )

            x1 = get_block_comparisons_cpp_uvw( sat, coords,
                                                w,v,u,
                                                offsets1, sizes1,
                                                offsets2, sizes2,
                                                n_jobs=10 )
            x2 = get_block_comparisons_cpp_uvw( sat_grad, coords,
                                                 w,v,u,
                                                offsets3, sizes3,
                                                offsets4, sizes4,
                                                n_jobs=10 )
            x_grad1 = get_grad_uvw( coords.astype('int32'), offsets5.astype('int32'),
                                    gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'),
                                    w.astype('float32'), v.astype('float32'), u.astype('float32') )

            x_grad2 = get_grad_uvw( coords.astype('int32'), offsets6.astype('int32'),
                                    gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'),
                                    w.astype('float32'), v.astype('float32'), u.astype('float32') )

            x = np.concatenate( ( x1, x2, x_grad1 > x_grad2 ), axis=1 )
            #x = np.concatenate( ( x1, x2 ), axis=1 )
        
            y = seg[coords[:,0],
                    coords[:,1],
                    coords[:,2]]
            
            if n < 30:
                X_train.extend(x)
                Y_train.extend(y)
            else:
                X_test.extend(x)
                Y_test.extend(y)

    print "train:",len(X_train),len(Y_train)
    forest = RandomForestClassifier( n_estimators=100,
                                     oob_score=True,
                                     n_jobs=10 )#,min_samples_leaf=10)

    forest.fit(X_train,Y_train)
    oob_score = forest.oob_score_

    print "test:",len(X_test),len(Y_test)
    test_score = forest.score( X_test, Y_test)

    print [oob_score,test_score,o_size,d_size]
    return [oob_score,test_score,o_size,d_size]
def get_training_data_classification( img, seg, label_name ):
    seg = irtk.imread( seg, dtype='int32', force_neurological=True )
    img = irtk.imread( img, dtype='int32', force_neurological=True )

    #u0,v0,w0 = get_orientation_training(seg)
    brain_center, heart_center, left_lung, right_lung = get_centers(seg)
    
    grad = irtk.Image(nd.gaussian_gradient_magnitude( img, 0.5 ),
                      img.get_header())

    blurred_img = nd.gaussian_filter(img,0.5)
    gradZ = nd.sobel( blurred_img, axis=0 ).astype('float32')
    gradY = nd.sobel( blurred_img, axis=1 ).astype('float32')
    gradX = nd.sobel( blurred_img, axis=2 ).astype('float32')

    new_seg = irtk.zeros( seg.get_header() )
    if label_name == "lungs":
        new_seg[seg==3] = 1 # lung 1
        new_seg[seg==4] = 1 # lung 2
    elif label_name == "heart":
        new_seg[seg==5] = 1 # heart
    elif label_name == "liver":
        new_seg[seg==8] = 1 # liver
    seg = new_seg

    sat = integral_image(img)
    sat_grad = integral_image(grad)

    m = np.zeros(img.shape, dtype='uint8')
    m[brain_center[0],
      brain_center[1],
      brain_center[2]] = 1

    narrow_band = nd.distance_transform_edt(np.logical_not(m))
    if args.narrow_band:
        narrow_band[narrow_band<30] = 0
        narrow_band[narrow_band>120] = 0
    narrow_band[img==0] = 0
    
    X = []
    Y = []
    for l in range(2):
        coords = np.argwhere(np.logical_and(narrow_band>0,seg==l))

        if l==0:
            coords = coords[np.random.randint( 0,
                                               coords.shape[0],
                                               int(args.factor_background*args.n_samples))].astype('int32')
        else:
            coords = coords[np.random.randint( 0,
                                               coords.shape[0],
                                               args.n_samples)].astype('int32')

        if args.not_centered:
            x1 = get_block_comparisons_cpp( sat, coords,
                                            offsets1, sizes1,
                                            offsets2, sizes2,
                                            n_jobs=args.n_jobs )
            x2 = get_block_comparisons_cpp( sat_grad, coords,
                                            offsets3, sizes3,
                                            offsets4, sizes4,
                                            n_jobs=args.n_jobs )
            x_grad1 = get_grad( coords.astype('int32'), offsets5.astype('int32'),
                                gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'))
            x_grad2 = get_grad( coords.astype('int32'), offsets6.astype('int32'),
                                gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'))
        else:

            if l == 0:
                u,v,w = get_random_orientation(coords.shape[0])
            else:
                # u = np.tile(u0,(coords.shape[0],1))
                # v = np.tile(v0,(coords.shape[0],1))
                # w = np.tile(w0,(coords.shape[0],1))
                u,v,w = get_orientation_training_jitter( brain_center,
                                                         heart_center,
                                                         left_lung,
                                                         right_lung,
                                                         coords.shape[0],
                                                         brain_jitter=args.brain_jitter,
                                                         heart_jitter=args.heart_jitter,
                                                         lung_jitter=args.lung_jitter )

            x1 = get_block_comparisons_cpp_uvw( sat, coords,
                                                w,v,u,
                                                offsets1, sizes1,
                                                offsets2, sizes2,
                                                n_jobs=args.n_jobs )
            x2 = get_block_comparisons_cpp_uvw( sat_grad, coords,
                                                 w,v,u,
                                                offsets3, sizes3,
                                                offsets4, sizes4,
                                                n_jobs=args.n_jobs )
            x3 = get_grad_comparisons_cpp_uvw( gradZ, gradY, gradX,
                                               coords,
                                               offsets5, offsets6,
                                               w,v,u,
                                               n_jobs=args.n_jobs )
            # x_grad1 = get_grad_uvw( coords.astype('int32'), offsets5.astype('int32'),
            #                         gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'),
            #                         w.astype('float32'), v.astype('float32'), u.astype('float32') )

            # x_grad2 = get_grad_uvw( coords.astype('int32'), offsets6.astype('int32'),
            #                         gradZ.astype('float32'), gradY.astype('float32'), gradX.astype('float32'),
            #                         w.astype('float32'), v.astype('float32'), u.astype('float32') )

        R = np.linalg.norm( coords - brain_center, axis=1 )
        #x = np.concatenate( ( x1, x2, x_grad1 > x_grad2, R[...,np.newaxis] ), axis=1 )
        x = np.concatenate( ( x1, x2, x3, R[...,np.newaxis] ), axis=1 )
        
        y = seg[coords[:,0],
                coords[:,1],
                coords[:,2]]

        X.extend(x)
        Y.extend(y)

    return (X,Y)