def main(sample='pru',
         l_min=20.,
         l_max=150.,
         z_min=0.1,
         z_max=0.4,
         RIN=100.,
         ROUT=5000.,
         proxy_angle='theta_sat_w1',
         plim=0.,
         Rn_min=0.,
         Rn_max=1000.,
         ndots=10,
         ncores=10,
         h=0.7):
    '''
        
        INPUT
        ---------------------------------------------------------
        sample         (str) sample name
        l_min          (int) lower limit of galaxy members - >=
        l_max          (int) higher limit of galaxy members - <
        z_min          (float) lower limit for z - >=
        z_max          (float) higher limit for z - <
        RIN            (float) Inner bin radius of profile
        ROUT           (float) Outer bin radius of profile
        proxy_angle    (str) proxy definition of the angle to compute the quadrupole
        plim           (float) Cut in centre probability - select clusters with Pcen > plim
        Rn_min         (float) Mpc - Select clusters with a distance to their neirest neighbour >= Rn_min 
        Rn_max         (float) Mpc - Select clusters with a distance to their neirest neighbour < Rn_max 
        ndots          (int) Number of bins of the profile
        ncores         (int) to run in parallel, number of cores
        h              (float) H0 = 100.*h
        '''

    cosmo = LambdaCDM(H0=100 * h, Om0=0.3, Ode0=0.7)
    tini = time.time()

    print('Sample ', sample)
    print('Selecting groups with:')
    print(l_min, ' <= Lambda < ', l_max)
    print(z_min, ' <= z < ', z_max)
    print(Rn_min, ' <= Rprox < ', Rn_max)
    print('P_cen lim ', plim)
    print('Profile has ', ndots, 'bins')
    print('from ', RIN, 'kpc to ', ROUT, 'kpc')
    print('Angle proxy ', proxy_angle)
    print('h ', h)

    # Defining radial bins
    bines = np.logspace(np.log10(RIN), np.log10(ROUT), num=ndots + 1)
    R = (bines[:-1] + np.diff(bines) * 0.5) * 1.e-3

    #reading cats

    L = Table(f[1].data).to_pandas()
    angles = fits.open(folder + 'SAT_angles.fits')[1].data
    borderid = np.loadtxt(folder + 'redMapperID_border.list')

    zlambda = L.Z_LAMBDA
    zspec = L.Z_SPEC
    Z_c = zspec
    Z_c[Z_c < 0] = zlambda[Z_c < 0]
    L.Z_LAMBDA = Z_c
    Pcen = angles.P_cen
    Rprox = angles.Rprox

    mrich = (L.LAMBDA >= l_min) * (L.LAMBDA < l_max)
    mz = (L.Z_LAMBDA >= z_min) * (L.Z_LAMBDA < z_max)
    mborder = (~np.in1d(L.ID, borderid))
    mpcen = (Pcen > plim)
    mprox = (Rprox >= Rn_min) * (Rprox < Rn_max)
    mlenses = mrich * mz * mborder * mpcen * mprox
    Nlenses = mlenses.sum()

    if Nlenses < ncores:
        ncores = Nlenses

    print('Nlenses', Nlenses)
    print('CORRIENDO EN ', ncores, ' CORES')

    # A = fits.open('/mnt/clemente/lensing/RodriguezGroups/angle_Rgroups_FINAL.fits')[1].data
    # theta  = A.theta[mlenses]

    L = L[mlenses]

    if 'control' in proxy_angle:
        theta = np.zeros(sum(mlenses))
        print('entro en control')
    else:
        theta = angles[mlenses][proxy_angle]

    # SPLIT LENSING CAT

    lbins = int(round(Nlenses / float(ncores), 0))
    slices = ((np.arange(lbins) + 1) * ncores).astype(int)
    slices = slices[(slices < Nlenses)]
    Lsplit = np.split(L.iloc[:], slices)
    Tsplit = np.split(theta, slices)

    # WHERE THE SUMS ARE GOING TO BE SAVED

    DSIGMAwsum_T = np.zeros(ndots)
    DSIGMAwsum_X = np.zeros(ndots)
    WEIGHTsum = np.zeros(ndots)
    Mwsum = np.zeros(ndots)

    BOOTwsum_T = np.zeros((100, ndots))
    BOOTwsum_X = np.zeros((100, ndots))
    BOOTwsum = np.zeros((100, ndots))

    GAMMATcos_wsum = np.zeros(ndots)
    GAMMAXsin_wsum = np.zeros(ndots)
    WEIGHTcos_sum = np.zeros(ndots)
    WEIGHTsin_sum = np.zeros(ndots)

    BOOTwsum_Tcos = np.zeros((100, ndots))
    BOOTwsum_Xsin = np.zeros((100, ndots))
    BOOTwsum_cos = np.zeros((100, ndots))
    BOOTwsum_sin = np.zeros((100, ndots))

    Ntot = []
    tslice = np.array([])

    for l in range(len(Lsplit)):

        print('RUN ', l + 1, ' OF ', len(Lsplit))

        t1 = time.time()

        num = len(Lsplit[l])

        rin = RIN * np.ones(num)
        rout = ROUT * np.ones(num)
        nd = ndots * np.ones(num)

        if num == 1:
            entrada = [
                Lsplit[l].CATID.iloc[0], Lsplit[l].RA.iloc[0],
                Lsplit[l].DEC.iloc[0], Lsplit[l].Z_LAMBDA.iloc[0],
                Tsplit[l][0], RIN, ROUT, ndots
            ]

            salida = [partial_profile_unpack(entrada)]
        else:
            entrada = np.array([
                Lsplit[l].CATID.iloc[:], Lsplit[l].RA, Lsplit[l].DEC,
                Lsplit[l].Z_LAMBDA, Tsplit[l][:], rin, rout, nd
            ]).T

            pool = Pool(processes=(num))
            salida = np.array(pool.map(partial_profile_unpack, entrada))
            pool.terminate()

        for profilesums in salida:

            DSIGMAwsum_T += profilesums['DSIGMAwsum_T']
            DSIGMAwsum_X += profilesums['DSIGMAwsum_X']
            WEIGHTsum += profilesums['WEIGHTsum']
            Mwsum += profilesums['Mwsum']

            BOOTwsum_T += profilesums['BOOTwsum_T']
            BOOTwsum_X += profilesums['BOOTwsum_X']
            BOOTwsum += profilesums['BOOTwsum']

            GAMMATcos_wsum += profilesums['GAMMATcos_wsum']
            GAMMAXsin_wsum += profilesums['GAMMAXsin_wsum']
            WEIGHTcos_sum += profilesums['WEIGHTcos_sum']
            WEIGHTsin_sum += profilesums['WEIGHTsin_sum']

            BOOTwsum_Tcos += profilesums['BOOTwsum_Tcos']
            BOOTwsum_Xsin += profilesums['BOOTwsum_Xsin']
            BOOTwsum_cos += profilesums['BOOTwsum_cos']
            BOOTwsum_sin += profilesums['BOOTwsum_sin']

            Ntot = np.append(Ntot, profilesums['Ntot'])

        t2 = time.time()
        ts = (t2 - t1) / 60.
        tslice = np.append(tslice, ts)
        print('TIME SLICE')
        print(ts)
        print('Estimated ramaining time')
        print(np.mean(tslice) * (len(Lsplit) - (l + 1)))

    # COMPUTING PROFILE

    Mcorr = Mwsum / WEIGHTsum
    DSigma_T = (DSIGMAwsum_T / WEIGHTsum) / (1 + Mcorr)
    DSigma_X = (DSIGMAwsum_X / WEIGHTsum) / (1 + Mcorr)
    eDSigma_T = np.std((BOOTwsum_T / BOOTwsum), axis=0) / (1 + Mcorr)
    eDSigma_X = np.std((BOOTwsum_X / BOOTwsum), axis=0) / (1 + Mcorr)

    GAMMA_Tcos = (GAMMATcos_wsum / WEIGHTcos_sum) / (1 + Mcorr)
    GAMMA_Xsin = (GAMMAXsin_wsum / WEIGHTsin_sum) / (1 + Mcorr)
    eGAMMA_Tcos = np.std((BOOTwsum_Tcos / BOOTwsum_cos), axis=0) / (1 + Mcorr)
    eGAMMA_Xsin = np.std((BOOTwsum_Xsin / BOOTwsum_sin), axis=0) / (1 + Mcorr)

    # AVERAGE LENS PARAMETERS

    zmean = np.average(L.Z_LAMBDA, weights=Ntot)
    l_mean = np.average(L.LAMBDA, weights=Ntot)

    # FITING AN NFW MODEL

    H = cosmo.H(zmean).value / (1.0e3 * pc)  #H at z_pair s-1
    roc = (3.0 *
           (H**2.0)) / (8.0 * np.pi * G)  #critical density at z_pair (kg.m-3)
    roc_mpc = roc * ((pc * 1.0e6)**3.0)

    try:
        nfw = NFW_stack_fit(R, DSigma_T, eDSigma_T, zmean, roc)
    except:
        nfw = [0.01, 0., 100., [0., 0.], [0., 0.], -999., 0.]

    M200_NFW = (800.0 * np.pi * roc_mpc * (nfw[0]**3)) / (3.0 * Msun)
    e_M200_NFW = ((800.0 * np.pi * roc_mpc * (nfw[0]**2)) / (Msun)) * nfw[1]
    le_M200 = (np.log(10.) / M200_NFW) * e_M200_NFW

    # WRITING OUTPUT FITS FILE

    tbhdu = fits.BinTableHDU.from_columns([
        fits.Column(name='Rp', format='D', array=R),
        fits.Column(name='DSigma_T', format='D', array=DSigma_T),
        fits.Column(name='error_DSigma_T', format='D', array=eDSigma_T),
        fits.Column(name='DSigma_X', format='D', array=DSigma_X),
        fits.Column(name='error_DSigma_X', format='D', array=eDSigma_X),
        fits.Column(name='GAMMA_Tcos', format='D', array=GAMMA_Tcos),
        fits.Column(name='error_GAMMA_Tcos', format='D', array=eGAMMA_Tcos),
        fits.Column(name='GAMMA_Xsin', format='D', array=GAMMA_Xsin),
        fits.Column(name='error_GAMMA_Xsin', format='D', array=eGAMMA_Xsin)
    ])

    h = tbhdu.header
    h.append(('N_LENSES', np.int(Nlenses)))
    h.append(('l_min', np.int(l_min)))
    h.append(('l_max', np.int(l_max)))
    h.append(('z_min', np.round(z_min, 4)))
    h.append(('z_max', np.round(z_max, 4)))
    h.append(('Rn_min', np.round(Rn_min, 4)))
    h.append(('Rn_max', np.round(Rn_max, 4)))
    h.append(('plim', np.round(plim, 4)))
    h.append(('lM200_NFW', np.round(np.log10(M200_NFW), 4)))
    h.append(('elM200_NFW', np.round(le_M200, 4)))
    h.append(('CHI2_NFW', np.round(nfw[2], 4)))
    h.append(('l_mean', np.round(l_mean, 4)))
    h.append(('z_mean', np.round(zmean, 4)))

    tbhdu.writeto(folder + 'profile_' + sample + '.fits', overwrite=True)

    tfin = time.time()

    print('TOTAL TIME ', (tfin - tini) / 60.)