예제 #1
0
def fake_data(stddev, RpRs, aRs, per, inc, midtrantime, gamma1, gamma2, ecc,
              argper):

    #Define Times (in days) centered at mid-transit time.
    expTime = 45. / (3600 * 24.
                     )  #Set to be 1-minute, somewhat typical for observing.
    Nimages = 200.  #Needs to be long enough to cover entire transit w/ some baseline.
    times = np.arange(start=midtrantime - expTime * Nimages / 2.,
                      stop=midtrantime + expTime * Nimages / 2.,
                      step=expTime)

    #Creates Gaussian Distributed Data using numpy.random.normal function based on standard dev.

    #Commented out stuff - talk to Brett about input parameters for model.
    #modelParams = [RpRs,aRs,per,inc,gamma1,gamma2,ecc,argper,midtrantime]
    #fake_data = oscaar.occultquad(times,modelParams) + np.random(scale=stddev,size=np.size(times))

    #Uses alternate input parameters setup for occultquad.
    modelParams = [
        RpRs, aRs, per, inc, gamma1, gamma2, ecc, argper, midtrantime
    ]
    perfect_data = oscaar.occultquad(times, modelParams)
    random_dist = np.random.normal(scale=stddev, size=np.size(times))
    fk_data = perfect_data + random_dist

    return times, fk_data
예제 #2
0
def fake_data(stddev,RpRs,aRs,per,inc,midtrantime,gamma1,gamma2,ecc,argper):
    '''Takes in orbital and planetary parameters and simulates data using random gaussian fluctations.
    
    Parameters include,
    stddev - standard deviation of fake data.
    RpRs   - fractional planetary to stellar radius
    aRs    - semi-major axis/stellar radii
    per    - orbital period (days)
    inc    - inclination of orbital plane (degrees)
    midtrantime - mid-transit time (JD)
    gamma1 - linear limb-darkening coeff.
    gamma2 - quadrtic limb-darkening coeff
    argper - argument of pericenter
    '''
    
    #Define Times (in days) centered at mid-transit time. 
    expTime = 45./(3600*24.) #Set to be 45 sec., somewhat typical for observing.
    Nimages = 200. #Needs to be long enough to cover entire transit w/ some baseline. 
    times = np.arange(start=midtrantime-expTime*Nimages/2.,
                      stop=midtrantime+expTime*Nimages/2.,
                      step=expTime)

    #Creates Gaussian Distributed Data using numpy.random.normal function based on standard dev.
    
    #Uses alternate input parameters setup for occultquad.
    modelParams=[RpRs,aRs,per,inc,gamma1,gamma2,ecc,argper,midtrantime]
    perfect_data = oscaar.occultquad(times,modelParams)
    random_dist = np.random.normal(scale=stddev,size=np.size(times))
    fk_data = perfect_data + random_dist
    
    return times,fk_data
예제 #3
0
 def occultquadForTransiter(t,p,ap,i,t0,gamma1=fit[4],gamma2=fit[5],P=perGuess,e=eccGuess,longPericenter=0.0):
     b=ap*np.cos(i)
     if b > 1.0 or i > 90.0 or gamma1 < 0.0 or gamma1 > 1.0:
         return np.zeros(len(t))
     elif gamma2 < 0.0 or gamma2 > 1.0 or i < 75.0:
         return np.zeros(len(t))
     else:
         modelParams = [p,ap,P,i,gamma1,gamma2,e,longPericenter,t0]
         return oscaar.occultquad(t,modelParams)        
def fitfunc(p,t=t,P=P,gamma1=gamma1,gamma2=gamma2,e=e,longPericenter=longPericenter):
    '''Fixed parameters: P, gamma1, gamma2, e, longPericenter
       Constraints: 0<=inclination<=90, but to prevent the leastsq algorithm from getting penalized
       for inclinations near 90, allow it to vary over range (0,180), and if a value is submitted > 90,
       then subtract it from 180 to return a value on 0=<i<90'''
    if p[2] >= 0 and p[2] <= 180:
    	if p[2] > 90: p[2] = 180 - p[2] ## 90 - (p[2] - 90)
        #occultquad(t,p[0],p[1],P,p[2],gamma1,gamma2,e,longPericenter,p[3],n,F)
        modelParams = [p[0],p[1],P,p[2],gamma1,gamma2,e,longPericenter,p[3]]
        F = oscaar.occultquad(times,modelParams)
        return F
예제 #5
0
 def occultquadForTransiter(t,
                            p,
                            ap,
                            i,
                            t0,
                            gamma1=0.0,
                            gamma2=0.0,
                            P=perGuess,
                            e=eccGuess,
                            longPericenter=0.0):
     modelParams = [p, ap, P, i, gamma1, gamma2, e, longPericenter, t0]
     return oscaar.occultquad(t, modelParams)
예제 #6
0
def fitfunc(p,
            t=t,
            P=P,
            gamma1=gamma1,
            gamma2=gamma2,
            e=e,
            longPericenter=longPericenter):
    '''Fixed parameters: P, gamma1, gamma2, e, longPericenter
       Constraints: 0<=inclination<=90, but to prevent the leastsq algorithm from getting penalized
       for inclinations near 90, allow it to vary over range (0,180), and if a value is submitted > 90,
       then subtract it from 180 to return a value on 0=<i<90'''
    if p[2] >= 0 and p[2] <= 180:
        if p[2] > 90: p[2] = 180 - p[2]  ## 90 - (p[2] - 90)
        #occultquad(t,p[0],p[1],P,p[2],gamma1,gamma2,e,longPericenter,p[3],n,F)
        modelParams = [
            p[0], p[1], P, p[2], gamma1, gamma2, e, longPericenter, p[3]
        ]
        F = oscaar.occultquad(times, modelParams)
        return F
예제 #7
0
 def occultquadForTransiter(t,p,ap,i,t0,gamma1=gamma1,gamma2=gamma2,P=perGuess,e=eccGuess,longPericenter=0.0):
     '''Defines oscaar.occultquad differently to be compatible w/ optimize.curve_fit
     
     If a parameter goes outside physical boundries then it returns
     an array of zeros, such that the chi squared value is extremely high.
     
     Constraints:
     Limb-darkening Coeff's -- 0.0 < gamma < 1.0
     Inclination < 90 degrees
     Impact Parameter < 1 (assumes no grazing transits)
     '''
     
     b=ap*np.cos(i)
     if b > 1.0 or i > 90.0 or gamma1 < 0.0 or gamma1 > 1.0:
         return np.zeros(len(t))
     elif gamma2 < 0.0 or gamma2 > 1.0:
         return np.zeros(len(t))
     else:
         modelParams = [p,ap,P,i,gamma1,gamma2,e,longPericenter,t0]
         return oscaar.occultquad(t,modelParams)
예제 #8
0
def fake_data(stddev,RpRs,aRs,per,inc,midtrantime,gamma1,gamma2,ecc,argper):
    
    #Define Times (in days) centered at mid-transit time. 
    expTime = 45./(3600*24.) #Set to be 1-minute, somewhat typical for observing.
    Nimages = 200. #Needs to be long enough to cover entire transit w/ some baseline. 
    times = np.arange(start=midtrantime-expTime*Nimages/2.,
                      stop=midtrantime+expTime*Nimages/2.,
                      step=expTime)

    #Creates Gaussian Distributed Data using numpy.random.normal function based on standard dev. 
    
    #Commented out stuff - talk to Brett about input parameters for model.
    #modelParams = [RpRs,aRs,per,inc,gamma1,gamma2,ecc,argper,midtrantime]
    #fake_data = oscaar.occultquad(times,modelParams) + np.random(scale=stddev,size=np.size(times))
    
    #Uses alternate input parameters setup for occultquad.
    modelParams=[RpRs,aRs,per,inc,gamma1,gamma2,ecc,argper,midtrantime]
    perfect_data = oscaar.occultquad(times,modelParams)
    random_dist = np.random.normal(scale=stddev,size=np.size(times))
    fk_data = perfect_data + random_dist
    
    return times,fk_data
예제 #9
0
from matplotlib import pyplot as plt
from scipy import optimize
import oscaar

## If you've run sampleMCMC.py before and want to load the results of that
## run, set loadvals = True. To run a fresh chain, set loadvals = False.
loadvals = False

if loadvals == False:
    ##############################
    # Generate sample transit light curve with random Gaussian noise
    x = np.arange(0.1, 0.4, 2e-3)
    noiseFactor = 5.0e-3  ## Set how much noise is added
    modelParams = [0.11, 4.1, 2.2, 83.1, 0.23, 0.3, 0.0, 0.0,
                   0.25]  ## Set simulated planet's parameters
    y = oscaar.occultquad(
        x, modelParams) + np.random.normal(0, 1, x.shape) * noiseFactor
    sigma_y = np.zeros_like(x) + noiseFactor
    Npoints = len(x)

    plt.errorbar(x, y, yerr=sigma_y)  ## Plot the simulated light curve
    plt.show()

    ##############################
    # Fit with MCMC
    Nsteps = int(
        0.75e6)  ## Number of MCMC "links in the chain" / number of steps
    saveInterval = 1e3  ## interval between MCMC links that get saved for uncertainty estimation
    inputParams = np.array([0.12, 3.9, 83.0, 0.26],
                           dtype=np.float64)  ## Initial fit parameters

    ## Parameters: [Rp/Rs, a/Rs, inclination, mid-transit time]
예제 #10
0
import numpy as np
from matplotlib import pyplot as plt
from scipy import optimize
import oscaar

## If you've run sampleMCMC.py before and want to load the results of that
## run, set loadvals = True. To run a fresh chain, set loadvals = False.
loadvals = False 

if loadvals == False:
    ##############################
    # Generate sample transit light curve with random Gaussian noise
    x = np.arange(0.1,0.4,2e-3)
    noiseFactor = 5.0e-3      ## Set how much noise is added
    modelParams = [0.11,4.1,2.2,83.1,0.23,0.3,0.0,0.0,0.25] ## Set simulated planet's parameters
    y = oscaar.occultquad(x,modelParams) + np.random.normal(0,1,x.shape)*noiseFactor
    sigma_y = np.zeros_like(x) + noiseFactor
    Npoints = len(x)

    plt.errorbar(x,y,yerr=sigma_y)     ## Plot the simulated light curve
    plt.show()

    ##############################
    # Fit with MCMC
    Nsteps = int(0.75e6)     ## Number of MCMC "links in the chain" / number of steps
    saveInterval = 1e3      ## interval between MCMC links that get saved for uncertainty estimation
    inputParams = np.array([0.12,3.9,83.0,0.26],dtype=np.float64)	## Initial fit parameters
    ## Parameters: [Rp/Rs, a/Rs, inclination, mid-transit time]

    def occult4params(t,params):
        '''Allow 4 parameters to vary freely, keep the others fixed at the values assigned below'''
예제 #11
0
def main():
    #################################################################
    ## Tweak these parameters, if you like!
    NdataImages = 200        ## Number of data images to generate
    NdarkImages = 3          ## Number of dark frames to generate
    NflatImages = 3          ## Number of flat fields to generate
    flatFieldCounts = 20000  ## Approx counts per pixel in flat field
    imageDimensionX = 120    ## Pixel dimensions of each image
    imageDimensionY = 40
    starDimensions = 4       ## Pixel dimensions of the stars
    skyBackground = 500      ## Background counts from sky brightness
    darkBackground = 100     ## Background counts from detector
    targetFluxOOT = 10000    ## Flux (in counts) from each pixel of the unocculted target star (out-of-transit)
    relativeFluxCompA = 0.85 ## Flux from comp A relative to target
    relativeFluxCompB = 0.95 ## Flux from comp B relative to target
    plotModel = False        ## Plot the injected transit light curve
    createMasterFlatNow = True  ## Use oscaar to create a master flat from the freshly generated flat frames
    ## Isn't it nice to control the signal to noise?
    #################################################################
    
    ## Delete `images` directory, if there is one, and
    ##      make a fresh one.
    if len(glob(os.path.join(os.path.dirname(__file__),'images'))) > 0: rmtree(os.path.join(os.path.dirname(__file__),'images'))
    mkdir(os.path.join(os.path.dirname(__file__),'images'))
    
    ## Pixel positions of the stars (x,y)
    targetX = [20-starDimensions/2,20+starDimensions/2]
    compAX = [60-starDimensions/2,60+starDimensions/2]
    compBX = [100-starDimensions/2,100+starDimensions/2]
    starsY = [imageDimensionY/2-starDimensions/2,imageDimensionY/2+starDimensions/2]
    
    ## Set ingress/egress times, transiting system parameters 
    ## In GD: Ingress = 2013-05-15;10:06:30; egress = 2013-05-15;11:02:35
    jd0 = 2456427.88890 
    exposureTime = 45/(60*60*24.) ## Convert s -> hr
    times = np.arange(jd0,jd0+exposureTime*NdataImages,exposureTime)
    # [p,ap,P,i,gamma1,gamma2,e,longPericenter,t0]
    modelParams = [ 0.1179, 14.71, 1.580400, 90.0, 0.23, \
                    0.30, 0.00, 0.0, np.mean(times,dtype=np.float64)]
    np.savetxt(os.path.join(os.path.dirname(__file__),'modelParams.txt'),modelParams)
    modelLightCurve = oscaar.occultquad(times,modelParams)
    if plotModel: 
    	fig = plt.figure()
    	ax1 = fig.add_subplot(111)
    	def format_coord(x, y):
    		'''Function to also give data value on mouse over with imshow.'''
    		return 'JD=%1.6f, Flux=%1.6f' % (x, y)
    	ax1.set_xlabel('Time (JD)')
    	ax1.set_ylabel('Relative Flux')
    	ax1.set_title('Injected Light Curve')
    	ax1.plot(times,modelLightCurve)
    	ax1.format_coord = format_coord
    	plt.show()
    
    ## For producing random arrays, initialize reference arrays with the proper shapes
    imageShapedMatrix = np.zeros([imageDimensionY,imageDimensionX])
    starShapedMatrix = np.zeros([starDimensions,starDimensions])
    
    ## Simulate dark frames with shot noise
    for i in range(NdarkImages):
        darkFrame = darkBackground + np.random.normal(imageShapedMatrix,np.sqrt(darkBackground))
        darkFrame = np.require(darkFrame,dtype=int)   ## Require integer counts
        pyfits.writeto(os.path.join(os.path.dirname(__file__),'images/simulatedImg-'+str(i).zfill(3)+'d.fits'),darkFrame)
    
    ## Simulate ideal flat frames (perfectly flat)
    for i in range(NflatImages):
        ## Flats will be completely flat -- ie, we're pretending that we have a 
        ##      perfect optical path with no spatial flux variations.
        flatField = np.zeros([imageDimensionY,imageDimensionX]) +  flatFieldCounts
        flatField = np.require(flatField,dtype=int)## Require integer counts
        pyfits.writeto(os.path.join(os.path.dirname(__file__),'images/simulatedImg-'+str(i).zfill(3)+'f.fits'),flatField)
    
    
    ## Create master flat now using oscaar's standard flat maker
    if createMasterFlatNow:
        flatPaths = glob(os.path.join(os.path.dirname(__file__),'images/simulatedImg-???f.fits'))
        flatDarkPaths = glob(os.path.join(os.path.dirname(__file__),'images/simulatedImg-???d.fits'))   ## Use the same darks
        masterFlatSavePath = os.path.join(os.path.dirname(__file__),'images/masterFlat.fits')   ## Where to save the master
        oscaar.standardFlatMaker(flatPaths,flatDarkPaths,masterFlatSavePath,plots=False)
    
    
    ## Create data images
    for i in range(NdataImages):
        ## Produce image with sky and dark background with simulated photon noise for each source
        simulatedImage = darkBackground + skyBackground +\
            np.random.normal(imageShapedMatrix,np.sqrt(darkBackground)) +\
            np.random.normal(imageShapedMatrix,np.sqrt(skyBackground))
        
        ## Create two box-shaped stars with simulated photon noise
        targetBrightness = targetFluxOOT*modelLightCurve[i]  ## Scale brightness with the light curve
        target = targetBrightness + np.random.normal(starShapedMatrix,np.sqrt(targetBrightness))
        
        compBrightnessA = targetFluxOOT*relativeFluxCompA
        compBrightnessB = targetFluxOOT*relativeFluxCompB
        compA = compBrightnessA + np.random.normal(starShapedMatrix,np.sqrt(compBrightnessA))
        compB = compBrightnessB + np.random.normal(starShapedMatrix,np.sqrt(compBrightnessB))
        
        ## Add stars onto the simulated image with some position jitter
        randomPositionJitterX = np.sign(np.random.uniform(-1,1))	## +/- 1 pixel stellar centroid position jitter
        randomPositionJitterY = np.sign(np.random.uniform(-1,1))	## +/- 1 pixel stellar centroid position jitter
        simulatedImage[starsY[0]+randomPositionJitterY:starsY[1]+randomPositionJitterY,targetX[0]+randomPositionJitterX:targetX[1]+randomPositionJitterX] += target
        simulatedImage[starsY[0]+randomPositionJitterY:starsY[1]+randomPositionJitterY,compAX[0]+randomPositionJitterX:compAX[1]+randomPositionJitterX] += compA
        simulatedImage[starsY[0]+randomPositionJitterY:starsY[1]+randomPositionJitterY,compBX[0]+randomPositionJitterX:compBX[1]+randomPositionJitterX] += compB
    
        ## Force counts to integers, save.
        simulatedImage = np.require(simulatedImage,dtype=int)   ## Require integer counts before save
    
        header = pyfits.Header()
        header.append(('JD',times[i],'Simulated Time (Julian Date)'))
        pyfits.writeto(os.path.join(os.path.dirname(__file__),'images/simulatedImg-'+str(i).zfill(3)+'r.fits'),simulatedImage,header=header)
예제 #12
0
lib_path = os.path.abspath('../../Code/')
sys.path.append(lib_path)
import oscaar

## Define system parameters for planet HAT-P-7 b. 
## Citation: Morris et al. 2013 (http://arxiv.org/abs/1301.4503)
RpOverRs = 0.07759				## R_p/R_s = ratio of planetary radius to stellar radius
aOverRs = 4.0					## a/R_s = ratio of semimajor axis to stellar radius
period = 2.204737				## Period [days]
inclination = 83.111			## Inclination [degrees]
gamma1 = 0.3525					## Linear limb-darkening coefficient
gamma2 = 0.168					## Quadratic limb-darkening coefficient
eccentricity = 0.0				## Eccentricity
longPericenter = 0.0			## Longitude of pericenter
epoch = 2454954.357463			## Mid transit time [Julian date]

## Generate times at which to calculate the flux
durationOfObservation = 6./24	## Elapsed time [days]
times = np.arange(epoch-durationOfObservation/2,epoch+durationOfObservation/2,1e-5)

modelParams = [RpOverRs,aOverRs,period,inclination,gamma1,gamma2,eccentricity,longPericenter,epoch]

## Generate light curve
flux = oscaar.occultquad(times,modelParams)

## Plot light curve
plt.plot(times,flux,linewidth=2)
plt.title('Transit light curve for HAT-P-7 b')
plt.ylabel('Relative Flux')
plt.xlabel('Time (JD)')
plt.show()
예제 #13
0
 def occultquadForTransiter(t,p,ap,i,t0,gamma1=0.0,gamma2=0.0,P=perGuess,e=eccGuess,longPericenter=0.0):
     modelParams = [p,ap,P,i,gamma1,gamma2,e,longPericenter,t0]
     return oscaar.occultquad(t,modelParams)
예제 #14
0
 def occult4params(t, params):
     '''Allow 4 parameters to vary freely, keep the others fixed at the values assigned below'''
     p, ap, i, t0 = params
     return oscaar.occultquad(t, [p, ap, 2.2, i, 0.23, 0.3, 0.0, 0.0, t0])
예제 #15
0
## Define system parameters for planet HAT-P-7 b.
## Citation: Morris et al. 2013 (http://arxiv.org/abs/1301.4503)
RpOverRs = 0.07759  ## R_p/R_s = ratio of planetary radius to stellar radius
aOverRs = 4.0  ## a/R_s = ratio of semimajor axis to stellar radius
period = 2.204737  ## Period [days]
inclination = 83.111  ## Inclination [degrees]
gamma1 = 0.3525  ## Linear limb-darkening coefficient
gamma2 = 0.168  ## Quadratic limb-darkening coefficient
eccentricity = 0.0  ## Eccentricity
longPericenter = 0.0  ## Longitude of pericenter
epoch = 2454954.357463  ## Mid transit time [Julian date]

## Generate times at which to calculate the flux
durationOfObservation = 6. / 24  ## Elapsed time [days]
times = np.arange(epoch - durationOfObservation / 2,
                  epoch + durationOfObservation / 2, 1e-5)

modelParams = [
    RpOverRs, aOverRs, period, inclination, gamma1, gamma2, eccentricity,
    longPericenter, epoch
]

## Generate light curve
flux = oscaar.occultquad(times, modelParams)

## Plot light curve
plt.plot(times, flux, linewidth=2)
plt.title('Transit light curve for HAT-P-7 b')
plt.ylabel('Relative Flux')
plt.xlabel('Time (JD)')
plt.show()
예제 #16
0
 def occult4params(t,params):
     '''Allow 4 parameters to vary freely, keep the others fixed at the values assigned below'''
     p,ap,i,t0 = params
     return oscaar.occultquad(t,[p,ap,2.2,i,0.23,0.3,0.0,0.0,t0])
예제 #17
0
def main():
    #################################################################
    ## Tweak these parameters, if you like!
    NdataImages = 200  ## Number of data images to generate
    NdarkImages = 3  ## Number of dark frames to generate
    NflatImages = 3  ## Number of flat fields to generate
    flatFieldCounts = 20000  ## Approx counts per pixel in flat field
    imageDimensionX = 120  ## Pixel dimensions of each image
    imageDimensionY = 40
    starDimensions = 4  ## Pixel dimensions of the stars
    skyBackground = 500  ## Background counts from sky brightness
    darkBackground = 100  ## Background counts from detector
    targetFluxOOT = 10000  ## Flux (in counts) from each pixel of the unocculted target star (out-of-transit)
    relativeFluxCompA = 0.85  ## Flux from comp A relative to target
    relativeFluxCompB = 0.95  ## Flux from comp B relative to target
    plotModel = False  ## Plot the injected transit light curve
    createMasterFlatNow = True  ## Use oscaar to create a master flat from the freshly generated flat frames
    ## Isn't it nice to control the signal to noise?
    #################################################################

    ## Delete `images` directory, if there is one, and
    ##      make a fresh one.
    if len(glob(os.path.join(os.path.dirname(__file__), 'images'))) > 0:
        rmtree(os.path.join(os.path.dirname(__file__), 'images'))
    mkdir(os.path.join(os.path.dirname(__file__), 'images'))

    ## Pixel positions of the stars (x,y)
    targetX = [20 - starDimensions / 2, 20 + starDimensions / 2]
    compAX = [60 - starDimensions / 2, 60 + starDimensions / 2]
    compBX = [100 - starDimensions / 2, 100 + starDimensions / 2]
    starsY = [
        imageDimensionY / 2 - starDimensions / 2,
        imageDimensionY / 2 + starDimensions / 2
    ]

    ## Set ingress/egress times, transiting system parameters
    ## In GD: Ingress = 2013-05-15;10:06:30; egress = 2013-05-15;11:02:35
    jd0 = 2456427.88890
    exposureTime = 45 / (60 * 60 * 24.)  ## Convert s -> hr
    times = np.arange(jd0, jd0 + exposureTime * NdataImages, exposureTime)
    # [p,ap,P,i,gamma1,gamma2,e,longPericenter,t0]
    modelParams = [ 0.1179, 14.71, 1.580400, 90.0, 0.23, \
                    0.30, 0.00, 0.0, np.mean(times,dtype=np.float64)]
    np.savetxt(os.path.join(os.path.dirname(__file__), 'modelParams.txt'),
               modelParams)
    modelLightCurve = oscaar.occultquad(times, modelParams)
    if plotModel:
        fig = plt.figure()
        ax1 = fig.add_subplot(111)

        def format_coord(x, y):
            '''Function to also give data value on mouse over with imshow.'''
            return 'JD=%1.6f, Flux=%1.6f' % (x, y)

        ax1.set_xlabel('Time (JD)')
        ax1.set_ylabel('Relative Flux')
        ax1.set_title('Injected Light Curve')
        ax1.plot(times, modelLightCurve)
        ax1.format_coord = format_coord
        plt.show()

    ## For producing random arrays, initialize reference arrays with the proper shapes
    imageShapedMatrix = np.zeros([imageDimensionY, imageDimensionX])
    starShapedMatrix = np.zeros([starDimensions, starDimensions])

    ## Simulate dark frames with shot noise
    for i in range(NdarkImages):
        darkFrame = darkBackground + np.random.normal(imageShapedMatrix,
                                                      np.sqrt(darkBackground))
        darkFrame = np.require(darkFrame, dtype=int)  ## Require integer counts
        pyfits.writeto(
            os.path.join(os.path.dirname(__file__),
                         'images/simulatedImg-' + str(i).zfill(3) + 'd.fits'),
            darkFrame)

    ## Simulate ideal flat frames (perfectly flat)
    for i in range(NflatImages):
        ## Flats will be completely flat -- ie, we're pretending that we have a
        ##      perfect optical path with no spatial flux variations.
        flatField = np.zeros([imageDimensionY, imageDimensionX
                              ]) + flatFieldCounts
        flatField = np.require(flatField, dtype=int)  ## Require integer counts
        pyfits.writeto(
            os.path.join(os.path.dirname(__file__),
                         'images/simulatedImg-' + str(i).zfill(3) + 'f.fits'),
            flatField)

    ## Create master flat now using oscaar's standard flat maker
    if createMasterFlatNow:
        flatPaths = glob(
            os.path.join(os.path.dirname(__file__),
                         'images/simulatedImg-???f.fits'))
        flatDarkPaths = glob(
            os.path.join(
                os.path.dirname(__file__),
                'images/simulatedImg-???d.fits'))  ## Use the same darks
        masterFlatSavePath = os.path.join(
            os.path.dirname(__file__),
            'images/masterFlat.fits')  ## Where to save the master
        oscaar.standardFlatMaker(flatPaths,
                                 flatDarkPaths,
                                 masterFlatSavePath,
                                 plots=False)

    ## Create data images
    for i in range(NdataImages):
        ## Produce image with sky and dark background with simulated photon noise for each source
        simulatedImage = darkBackground + skyBackground +\
            np.random.normal(imageShapedMatrix,np.sqrt(darkBackground)) +\
            np.random.normal(imageShapedMatrix,np.sqrt(skyBackground))

        ## Create two box-shaped stars with simulated photon noise
        targetBrightness = targetFluxOOT * modelLightCurve[
            i]  ## Scale brightness with the light curve
        target = targetBrightness + np.random.normal(starShapedMatrix,
                                                     np.sqrt(targetBrightness))

        compBrightnessA = targetFluxOOT * relativeFluxCompA
        compBrightnessB = targetFluxOOT * relativeFluxCompB
        compA = compBrightnessA + np.random.normal(starShapedMatrix,
                                                   np.sqrt(compBrightnessA))
        compB = compBrightnessB + np.random.normal(starShapedMatrix,
                                                   np.sqrt(compBrightnessB))

        ## Add stars onto the simulated image with some position jitter
        randomPositionJitterX = np.sign(np.random.uniform(
            -1, 1))  ## +/- 1 pixel stellar centroid position jitter
        randomPositionJitterY = np.sign(np.random.uniform(
            -1, 1))  ## +/- 1 pixel stellar centroid position jitter
        simulatedImage[starsY[0] + randomPositionJitterY:starsY[1] +
                       randomPositionJitterY,
                       targetX[0] + randomPositionJitterX:targetX[1] +
                       randomPositionJitterX] += target
        simulatedImage[starsY[0] + randomPositionJitterY:starsY[1] +
                       randomPositionJitterY,
                       compAX[0] + randomPositionJitterX:compAX[1] +
                       randomPositionJitterX] += compA
        simulatedImage[starsY[0] + randomPositionJitterY:starsY[1] +
                       randomPositionJitterY,
                       compBX[0] + randomPositionJitterX:compBX[1] +
                       randomPositionJitterX] += compB

        ## Force counts to integers, save.
        simulatedImage = np.require(
            simulatedImage, dtype=int)  ## Require integer counts before save

        header = pyfits.Header()
        header.append(('JD', times[i], 'Simulated Time (Julian Date)'))
        pyfits.writeto(os.path.join(
            os.path.dirname(__file__),
            'images/simulatedImg-' + str(i).zfill(3) + 'r.fits'),
                       simulatedImage,
                       header=header)