def bias_bySNR():
    '''
    Run multiple realisations and produces SB profile estimates for each run. Set up for measurment of e1, should be generalised.
    To Do:
    --Generalise to multiple parameters: fitParams and setting defaults for thes fitParams, so that routine does not have any information on these parameters
    --Mean output: Header information - fitParams and input value
    '''
    print 'Producing Bias by SNR ratio'

    nRealisation = 10000000 ##This labels the maximum number of iterations
    percentError = 1

    global imageParams    
    modPro.set_modelParameter(imageParams, fitParamsLabels, fitParamsValues)

    ##Get NoiseFree Image
    noiseFreeImage, disc = modPro.user_get_Pixelised_Model(imageParams, noiseType = None, sbProfileFunc = SBPro.gaussian_SBProfile_Weave)

    modelLookup = None
    if(len(fitParamsLabels) <= 2 and useLookup):
        modelLookup =  modPro.get_Model_Lookup(imageParams, fitParamsLabels, lookupRange, lookupWidth, noiseType = None, sbProfileFunc = SBPro.gaussian_SBProfile_Weave)
        print 'Created model lookup table'


    print 'Simulating Bias in SNR bins:\n'
    S = -1 #Counter
    filenames = []; SNRStore = []
    while True:
        S += 1
        SNR = SNRRange[0] + S*SNRRange[2]

        ##Exit Condition
        if(SNR > SNRRange[1]):
            break

        ##Set Model
        imageParams['SNR'] = SNR

        ## Store SNR for output
        SNRStore.append(SNR)

        ##Intialise output and set header
        filenames.append(Output+filePrefix+'_SNR'+str(SNR)+'.dat')
        handle = intialise_Output(filenames[S], mode = 'a')
        ##Write Header
        handle.write('# Bias Run Output. Following is input image parameters \n')
        for k in imageParams.keys():
            handle.write('#'+str(k)+' = '+str(imageParams[k])+'\n')

        ## Output Bias Corrected value
        bchandle = None
        if(biasCorrect):
            bchandle = intialise_Output(Output+filePrefix+'_SNR'+str(SNR)+'_BC.dat', mode = 'a')
            bchandle.write('# Bias Corrected Bias Run Output. Following is input image parameters \n')
            for k in imageParams.keys():
                bchandle.write('#'+str(k)+' = '+str(imageParams[k])+'\n')
            

        MaxL = np.zeros((nRealisation, len(fitParamsLabels))); BCMaxL = np.zeros(MaxL.shape); MaxLErr = np.zeros(MaxL.shape)
        for real in range(nRealisation):
            ## This version uses GALSIM default
            #image, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = 'G')

            ## GALSIM with user-defined SB Profile
            #image, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = 'G', sbProfileFunc = SBPro.gaussian_SBProfile_Weave)
            ## SYMPY - Very slow
            #modPro.get_Pixelised_Model_wrapFunction(0., imageParams, noiseType = 'G', outputImage = False, sbProfileFunc = SBPro.gaussian_SBProfile_Sympy)

            ## Entirely user-defined
            image, imageParams = modPro.user_get_Pixelised_Model(imageParams, noiseType = 'G', sbProfileFunc = SBPro.gaussian_SBProfile_Weave, inputImage = noiseFreeImage)

            #MLEx = ML.find_ML_Estimator(image, modelLookup = None, fitParams = fittedParameters.keys(),  outputHandle = None, setParams = imageParams, e1 = 0.35) ##Needs edited to remove information on e1 (passed in for now) - This should only ever be set to the parameters being fit

            ##Find usign lookup table where appropriate
            MLReturn = ML.find_ML_Estimator(image, modelLookup = modelLookup, fitParams = fitParamsLabels,  outputHandle = handle, searchMethod = minimiseMethod, preSearchMethod = preSearchMethod, bruteRange = bruteRange, biasCorrect = biasCorrect, bcoutputHandle = bchandle, error = errorType, setParams = imageParams.copy(), **initialGuess)
            if(biasCorrect):
                MaxL[real,:], BCMaxL[real,:] = MLReturn[0:2]
                if(len(MLReturn) == 3): #Erro is output
                    MaxLErr[real,:] = MLReturn[2]
            else:
                MaxL[real,:] = MLReturn[0]
                if(len(MLReturn) == 2):#Error is output
                    MaxLErr[real,:] =  MLReturn[1]

            if(real > 10000 and real%1000 == 0 and percentError > 0.):
                Mean = (MaxL[:real,:].mean(axis = 0)-fitParamsValues); Err = MaxL[:real,:].std(axis = 0)/np.sqrt(real)
                if((np.absolute(100.*(Err/Mean)) < percentError).sum() == MaxL.shape[1]):
                    print '\n For SNR:', SNR, ' percentage error was reached in ', real, ' simulated images'
                    print 'With mean, std, %Err:', Mean, Err, np.absolute(100.*(Err/Mean))
                    break

            #print '----- Realisation:', real, ':: Ex:', MLEx, ' Look:', MLLook, ' :: Ratio:', MLEx/MLLook
            #raw_input('Check')

        handle.close()


    ### Construct and output mean, std and error on mean for each fit parameter
    handle1 = intialise_Output(Output+filePrefix+'_Statistics.dat', mode = 'a')
    handle1.write('## Recovered statistics as a result of bias run. Output of form [Mean, StD, Error on Mean] repeated for all fit quantities \n')
    for k in fittedParameters.keys():
        handle1.write('#'+str(k)+' = '+str(fittedParameters[k])+'\n')

    handle2 = intialise_Output(Output+filePrefix+'_Bias.dat', mode = 'a')
    handle2.write('## Recovered statistics as a result of bias run. Output of form [Bias, StD, Error on Bias] repeated for all fit quantities \n')
    for k in fittedParameters.keys():
        handle2.write('#'+str(k)+' = '+str(fittedParameters[k])+'\n')

    ##Produce Mean, StD from sampling and output
    for f in range(len(filenames)):
        Input = np.genfromtxt(filenames[f])

        SNR = SNRStore[f]
        Mean = Input.mean(axis = 0); StD = Input.std(axis = 0); MeanStD = StD/np.sqrt(Input.shape[0])

        if(len(fittedParameters.keys()) == 1):
            out = np.array([SNR, Mean, StD, MeanStD])
            np.savetxt(handle1, out.reshape(1,out.shape[0]))
            
            out = np.array([SNR, Mean-fittedParameters.values()[0], StD, MeanStD])
            np.savetxt(handle2, out.reshape(1,out.shape[0]))

        else:
            out = np.array([ [SNR, Mean[l], StD[l], MeanStD[l]] for l in range(len(fittedParameters.keys())) ]).flatten()
            np.savetxt(handle1, out.reshape(1,out.shape[0]))
            
            out = np.array([ [SNR, Mean[l]-fittedParameters.values()[l], StD[l], MeanStD[l]] for l in range(len(fittedParameters.keys())) ]).flatten()
            np.savetxt(handle2, out.reshape(1,out.shape[0]))


    print 'Finished SNR Bias loop without incident'
        
    handle = open(filename, mode)

    if(verbose):
        print 'File will be output to: ',filename

    return handle
            


if __name__ == "__main__":

    print 'Running'

    handle = intialise_Output('./ML_Output/SNR_500./Test.dat', mode = 'a')

    for i in range(10000000):
        print 'Doing:', i

        imageShape = (50., 50.)
        imageParams = dict(size = 1.2, e1 = 0.3, e2 = 0., centroid = np.array(imageShape)/2, flux = 1.e5, \
                           magnification = 1., shear = [0., 0.], noise = 10., SNR = 50., stamp_size = imageShape, pixel_scale = 1.,\
                           modelType = 'gaussian')
        image, imageParams = ML.get_Pixelised_Model(imageParams, noiseType = 'G')

        print 'Finding ML'
        ML.find_ML_Estimator(image, fitParams = ['e1'],  outputHandle = handle, size = 1.2, e2 = 0., centroid = np.array(imageShape)/2, flux = 1.e5, magnification = 1., shear = [0., 0.], noise = 10., SNR = 50., stamp_size = imageShape, pixel_scale = 1., modelType = 'gaussian')
    
    print 'Finished Normally'