def return_numerical_ML_Bias(parameter_value, parameter_label, imageParams, order = 1, maxEval = 1000):
    import model_Production as modPro
    """
    Returns the theoretically motivated ML estiamtor bias due to finite data sample. First instance only calculates the linear bias. This is most useful for a `brute force` approach to the ML bias correction, as (in the Gaussian case) the result depends on the image: therefore K, J and L must be calculated over many samples; therefore, this is likely to be computationally expensive compared to the analytic method where the statistics of the image are known.

    Differs from the analytic case in the sense that *this method does nto assume that the statistics of the image are known*, so that one must consider many simulated images to obtain the bias components

    Requires:
    parameter_value: value of beta on which to calculate the bias (either intrinsic parameter value, or ML measurment itself)
    parameter_label: labels the parameter being varied. Must be of the form of the default model parameter dictionary.
    image: 2-dimensional ndarray containing the image to be analysed
    imageParams: model parameters set to the default value.
    order: not implemented yet. Defines to what order the bias is returned. Default is first order.

    Side Effects: None
    
    Returns: bias to stated order.
    """
    from image_measurement_ML import get_logLikelihood
    from derivatives import finite_difference_derivative

    ##Redefine input for ease of notation
    pVal = parameter_value; pLab = parameter_label

    ##Get derivative of log-likelihood wrt the parameter
    #If returnType = pix, then derivative is still kept in pixel form
    ##Note: even though for simple, uncorrelated noise, the ML point does not depend on the noise value, for the derivative it does. Therefore, it is likely that the noise value passed in via setParams, as measured on the image, must be accurate.

    nPix = np.prod(imageParams['stamp_size'])

    K = np.zeros(maxEval); J = np.zeros(maxEval); I = np.zeros(maxEval);

    for ev in range(maxEval):
        ## Get a new simulated image
        image, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = 'G', Verbose = debug)

        ## Store imageParams in temporary storage to ensure that dictionary in not overwritten
        iParams = deepcopy(imageParams)
        ## Take derivative of likelihood (function of image and model at entered parameter values) around the ML point (entered parameter values)
        dpixlnL = finite_difference_derivative(get_logLikelihood, pVal, args = [pLab, image, iParams, 'pix'], n = [1,2,3], dx = [0.0001, 0.0001], maxEval = 1000, eps = 1.e-3)

        K[ev] = dpixlnL[2].sum()/nPix
        
        J[ev] = (dpixlnL[0]*dpixlnL[1]).sum()/nPix
        
        I[ev] = -(dpixlnL[1].sum())/nPix

    K = K.mean()
    J = J.mean()
    I = I.mean()

    print 'Bias components found:'
    print 'K:', K
    print 'J:', J
    print 'I:', I

    bias = (K+(2.*J))/(2.*nPix*I*I)
    
    return bias
import src.model_Production as modPro
import src.measure_Bias as mBias
import src.image_measurement_ML as ML
import numpy as np

## Bias Measurement
S0 = 1.2; derLabel = 'T'
imageParams = modPro.default_ModelParameter_Dictionary()
imageParams['SNR'] = 50.
imageParams['size'] = 1.2
imageParams[derLabel] = S0
imageParams['stamp_size'] = np.array([50,50])
imageParams['centroid'] = (imageParams['stamp_size']+1)/2.

###Get image
image, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = 'G')

modelParams = imageParams.copy()

print 'modelParams test:', modelParams['stamp_size'], modelParams['noise']
print 'Estimated variance:', ML.estimate_Noise(image, maskCentroid = modelParams['centroid'])
raw_input('Check')

##Produce analytic bias
print 'Getting analytic bias:'
anbias = mBias.analytic_GaussianLikelihood_Bias(S0, derLabel, modelParams, diffType = 'ana')
print '\n ****** Analytic Bias is:', anbias

##Produce analytic bias
print 'Getting analytic bias:'
numanbias = mBias.analytic_GaussianLikelihood_Bias(S0, derLabel, modelParams, diffType = 'num')
#Single Run - Derivative
print 'Running'

imageParams = modPro.default_ModelParameter_Dictionary()
imageParams['SNR'] = 200.
imageParams['e2'] = 0.
imageParams['size'] = 6.
imageParams['stamp_size'] = [10,10]
imageParams['centroid'] = (np.array(imageParams['stamp_size'])+1)/2.


###Get image using GALSIM default models
#image, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = None, outputImage = True)
#image, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = None, outputImage = True, sbProfileFunc = modPro.gaussian_SBProfile)

image, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = None, outputImage = True, sbProfileFunc = SBPro.gaussian_SBProfile_Sympy)
###Get image using user-specified surface brightness model
#imageSB, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = None, outputImage = True, sbProfileFunc = modPro.gaussian_SBProfile)
imageSB, imageParams = modPro.get_Pixelised_Model(imageParams, noiseType = None, outputImage = True, sbProfileFunc = SBPro.gaussian_SBProfile_Sympy)


print 'Ratio of Sum of Image:', image.sum(), imageSB.sum(), image.sum()/imageSB.sum(), imageParams['flux']

### Plot Residual
import pylab as pl

#pl.imshow((imageSB/image))
pl.imshow((image))
#pl.set_title('GALSIM - User-Specified')
pl.colorbar()