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
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
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
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)
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
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)
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
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]
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'''
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)
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()
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)
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])
## 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()
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])
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)