def __init__(self, coeffs=[1,1,1,1,2,1], revisit_wait=91.25, **specs): SurveySimulation.__init__(self, **specs) TL = self.TargetList #verify that coefficients input is iterable 6x1 if not(isinstance(coeffs,(list,tuple,np.ndarray))) or (len(coeffs) != 6): raise TypeError("coeffs must be a 6 element iterable") #Add to outspec self._outspec['coeffs'] = coeffs self._outspec['revisit_wait'] = revisit_wait # normalize coefficients coeffs = np.array(coeffs) coeffs = coeffs/np.linalg.norm(coeffs, ord=1) self.coeffs = coeffs self.revisit_wait = revisit_wait*u.d self.earth_candidates = [] # list of detected earth-like planets aroung promoted stars self.no_dets = np.ones(self.TargetList.nStars, dtype=bool) self.known_stars, self.known_rocky = self.find_known_plans() TL.comp0[self.known_rocky] = 1.0
def __init__(self, **specs): SurveySimulation.__init__(self, **specs) OS = self.OpticalSystem SU = self.SimulatedUniverse allModes = OS.observingModes num_char_modes = len(list(filter(lambda mode: 'spec' in mode['inst']['name'], allModes))) self.fullSpectra = np.zeros((num_char_modes, SU.nPlans), dtype=int) self.partialSpectra = np.zeros((num_char_modes, SU.nPlans), dtype=int)
def __init__(self, occHIPs=[], **specs): SurveySimulation.__init__(self, **specs) self._outspec['occHIPs'] = occHIPs if occHIPs != []: occHIPs_path = os.path.join(EXOSIMS.__path__[0],'Scripts',occHIPs) assert os.path.isfile(occHIPs_path), "%s is not a file."%occHIPs_path HIPsfile = open(occHIPs_path, 'r').read() self.occHIPs = HIPsfile.split(',') if len(self.occHIPs) <= 1: self.occHIPs = HIPsfile.split('\n') else: self.occHIPs = occHIPs
def __init__(self, coeffs=[1,0,0,0], **specs): SurveySimulation.__init__(self, **specs) #verify that coefficients input is iterable 6x1 if not(isinstance(coeffs,(list,tuple,np.ndarray))) or (len(coeffs) != 4): raise TypeError("coeffs must be a 3 element iterable") #normalize coefficients coeffs = np.array(coeffs) coeffs = coeffs/np.linalg.norm(coeffs) self.coeffs = coeffs
def __init__(self, coeffs=[1, 1, 2, 1], revisit_wait=91.25, **specs): SurveySimulation.__init__(self, **specs) #verify that coefficients input is iterable 4x1 if not (isinstance(coeffs, (list, tuple, np.ndarray))) or (len(coeffs) != 4): raise TypeError("coeffs must be a 4 element iterable") #Add to outspec self._outspec['coeffs'] = coeffs self._outspec['revisit_wait'] = revisit_wait # normalize coefficients coeffs = np.array(coeffs) coeffs = coeffs / np.linalg.norm(coeffs) self.coeffs = coeffs self.revisit_wait = revisit_wait * u.d self.no_dets = np.ones(self.TargetList.nStars, dtype=bool)
def __init__(self, coeffs=[1,1,2,1], revisit_wait=91.25, **specs): SurveySimulation.__init__(self, **specs) #verify that coefficients input is iterable 4x1 if not(isinstance(coeffs,(list,tuple,np.ndarray))) or (len(coeffs) != 4): raise TypeError("coeffs must be a 4 element iterable") #Add to outspec self._outspec['coeffs'] = coeffs self._outspec['revisit_wait'] = revisit_wait # normalize coefficients coeffs = np.array(coeffs) coeffs = coeffs/np.linalg.norm(coeffs) self.coeffs = coeffs self.revisit_wait = revisit_wait*u.d self.no_dets = np.ones(self.TargetList.nStars, dtype=bool)
def __init__(self, **specs): # call prototype constructor SurveySimulation.__init__(self, **specs) TL = self.TargetList SU = self.SimulatedUniverse # reinitialize working angles and delta magnitudes used for integration self.WAint = np.zeros(TL.nStars)*u.arcsec self.dMagint = np.zeros(TL.nStars) # calculate estimates of shortest WAint and largest dMagint for each target for sInd in range(TL.nStars): pInds = np.where(SU.plan2star == sInd)[0] self.WAint[sInd] = np.arctan(np.min(SU.a[pInds])/TL.dist[sInd]).to('arcsec') phis = np.array([np.pi/2]*pInds.size) dMags = deltaMag(SU.p[pInds], SU.Rp[pInds], SU.a[pInds], phis) self.dMagint[sInd] = np.min(dMags) # populate outspec with arrays self._outspec['WAint'] = self.WAint.value self._outspec['dMagint'] = self.dMagint
def __init__(self, cacheOptTimes=False, staticOptTimes=False, **specs): #initialize the prototype survey SurveySimulation.__init__(self, **specs) assert isinstance(staticOptTimes, bool), 'staticOptTimes must be boolean.' self.staticOptTimes = staticOptTimes self._outspec['staticOptTimes'] = self.staticOptTimes assert isinstance(cacheOptTimes, bool), 'cacheOptTimes must be boolean.' self._outspec['cacheOptTimes'] = cacheOptTimes #some global defs self.detmode = filter(lambda mode: mode['detectionMode'] == True, self.OpticalSystem.observingModes)[0] self.ohTimeTot = self.Observatory.settlingTime + self.detmode['syst']['ohTime'] self.maxTime = self.TimeKeeping.missionLife*self.TimeKeeping.missionPortion self.constraints = {'type':'ineq', 'fun': lambda x: self.maxTime.to(u.d).value - np.sum(x[x*u.d > 0.1*u.s]) - np.sum(x*u.d > 0.1*u.s).astype(float)*self.ohTimeTot.to(u.d).value, 'jac':lambda x: np.ones(len(x))*-1.} self.t0 = None if cacheOptTimes: #Generate cache Name######################################################################## cachefname = self.cachefname + 't0' if os.path.isfile(cachefname): self.vprint("Loading cached t0 from %s"%cachefname) with open(cachefname, 'rb') as f: self.t0 = pickle.load(f) sInds = np.arange(self.TargetList.nStars) fZ = np.array([self.ZodiacalLight.fZ0.value]*len(sInds))*self.ZodiacalLight.fZ0.unit self.scomp0 = -self.objfun(self.t0.to(u.d).value,sInds,fZ) if self.t0 is None: #find nominal background counts for all targets in list _, Cbs, Csps = self.OpticalSystem.Cp_Cb_Csp(self.TargetList, range(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, 25.0, self.WAint, self.detmode) #find baseline solution with dMagLim-based integration times self.vprint('Finding baseline fixed-time optimal target set.') t0 = self.OpticalSystem.calc_intTime(self.TargetList, range(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, self.dMagint, self.WAint, self.detmode) comp0 = self.Completeness.comp_per_intTime(t0, self.TargetList, range(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, self.WAint, self.detmode, C_b=Cbs, C_sp=Csps) solver = pywraplp.Solver('SolveIntegerProblem',pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) xs = [ solver.IntVar(0.0,1.0, 'x'+str(j)) for j in range(len(comp0)) ] #constraint is x_i*t_i < maxtime constraint = solver.Constraint(-solver.infinity(),self.maxTime.to(u.day).value) for j,x in enumerate(xs): constraint.SetCoefficient(x, t0[j].to(u.day).value + self.ohTimeTot.to(u.day).value) #objective is max x_i*comp_i objective = solver.Objective() for j,x in enumerate(xs): objective.SetCoefficient(x, comp0[j]) objective.SetMaximization() cpres = solver.Solve() x0 = np.array([x.solution_value() for x in xs]) self.scomp0 = np.sum(comp0*x0) self.t0 = t0 #now find the optimal eps baseline and use whichever gives you the highest starting completeness self.vprint('Finding baseline fixed-eps optimal target set.') def totCompfeps(eps): compstars,tstars,x = self.inttimesfeps(eps, Cbs.to('1/d').value, Csps.to('1/d').value) return -np.sum(compstars*x) epsres = minimize_scalar(totCompfeps,method='bounded',bounds = [0,1],options = {'disp':True}) comp_epsmax,t_epsmax,x_epsmax = self.inttimesfeps(epsres['x'],Cbs.to('1/d').value, Csps.to('1/d').value) if np.sum(comp_epsmax*x_epsmax) > self.scomp0: x0 = x_epsmax self.scomp0 = np.sum(comp_epsmax*x_epsmax) self.t0 = t_epsmax*u.day #now optimize the solution self.vprint('Optimizing baseline integration times.') sInds = np.arange(self.TargetList.nStars) fZ = np.array([self.ZodiacalLight.fZ0.value]*len(sInds))*self.ZodiacalLight.fZ0.unit bounds = [(0,self.maxTime.to(u.d).value) for i in range(len(sInds))] initguess = x0*self.t0.to(u.d).value ires = minimize(self.objfun, initguess, jac=self.objfun_deriv, args=(sInds,fZ), constraints=self.constraints, method='SLSQP', bounds=bounds, options={'maxiter':100,'ftol':1e-4}) assert ires['success'], "Initial time optimization failed." self.t0 = ires['x']*u.d self.scomp0 = -ires['fun'] if cacheOptTimes: with open(cachefname,'wb') as f: pickle.dump(self.t0, f) self.vprint("Saved cached optimized t0 to %s"%cachefname)
def __init__(self, **specs): SurveySimulation.__init__(self, **specs) # bring inherited class objects to top level of Survey Simulation SU = self.SimulatedUniverse OS = SU.OpticalSystem ZL = SU.ZodiacalLight self.Completeness = SU.Completeness TL = SU.TargetList Obs = self.Observatory TK = self.TimeKeeping self.starVisits = np.zeros(TL.nStars, dtype=int) self.starRevisit = np.array([]) detMode = filter(lambda mode: mode['detectionMode'] == True, OS.observingModes)[0] spectroModes = filter(lambda mode: 'spec' in mode['inst']['name'], OS.observingModes) self.mode = detMode #Create and start Schedule self.schedule = np.arange( TL.nStars) #self.schedule is meant to be editable self.schedule_startSaved = np.arange( TL.nStars) #preserves initial list of targets dMagLim = self.Completeness.dMagLim self.dmag_startSaved = np.linspace(1, dMagLim, num=1500, endpoint=True) sInds = self.schedule_startSaved dmag = self.dmag_startSaved WA = OS.WA0 startTime = np.zeros( sInds.shape[0]) * u.d + self.TimeKeeping.currentTimeAbs tovisit = np.zeros(sInds.shape[0], dtype=bool) #Generate fZ #ZL.fZ_startSaved = self.generate_fZ(sInds)#Sept 21, 2017 execution time 0.725 sec #Estimate Yearly fZmin########################################### tmpfZ = np.asarray(ZL.fZ_startSaved) fZ_matrix = tmpfZ[ sInds, :] #Apply previous filters to fZ_startSaved[sInds, 1000] #Find minimum fZ of each star fZmin = np.zeros(sInds.shape[0]) fZminInds = np.zeros(sInds.shape[0]) for i in xrange(len(sInds)): fZmin[i] = min(fZ_matrix[i, :]) fZminInds[i] = np.argmin(fZ_matrix[i, :]) ################################################################# #CACHE Cb Cp Csp################################################Sept 20, 2017 execution time 10.108 sec #fZ = np.zeros(sInds.shape[0]) + 0./u.arcsec**2 #fEZ = 0./u.arcsec**2# #fZ = np.zeros(sInds.shape[0]) + ZL.fZ0 fZ = fZmin / u.arcsec**2 # fEZ = ZL.fEZ0 mode = self.mode #resolve this mode is passed into next_target allModes = self.OpticalSystem.observingModes det_mode = filter(lambda mode: mode['detectionMode'] == True, allModes)[0] #dmag = self.dmag_startSaved Cp = np.zeros([sInds.shape[0], dmag.shape[0]]) Cb = np.zeros(sInds.shape[0]) Csp = np.zeros(sInds.shape[0]) for i in xrange(dmag.shape[0]): Cp[:, i], Cb[:], Csp[:] = OS.Cp_Cb_Csp(TL, sInds, fZ, fEZ, dmag[i], WA, det_mode) self.Cb = Cb[:] / u.s #Cb[:,0]/u.s#note all Cb are the same for different dmags. They are just star dependent self.Csp = Csp[:] / u.s #Csp[:,0]/u.s#note all Csp are the same for different dmags. They are just star dependent #self.Cp = Cp[:,:] #This one is dependent upon dmag and each star ################################################################ #Solve Initial Integration Times############################################### def CbyTfunc(t_dets, self, TL, sInds, fZ, fEZ, WA, mode, Cb, Csp): CbyT = -self.Completeness.comp_per_intTime(t_dets * u.d, TL, sInds, fZ, fEZ, WA, mode, Cb, Csp) / t_dets * u.d return CbyT.value maxCbyTtime = np.zeros( sInds.shape[0]) #This contains the time maxCbyT occurs at maxCbyT = np.zeros(sInds.shape[0]) #this contains the value of maxCbyT dir_path = os.path.dirname(os.path.realpath( __file__)) #find current directory of survey Simualtion fname = '/cachedMaxCbyTtime.csv' #Check File Length fileLength = 0 numcommas = 0 try: with open(dir_path + fname, 'rb') as f: reader = csv.reader(f) your_list = list(reader) fileLength = len(your_list) numcommas = len(your_list[0]) f.close() except: fileLength = 0 numcommas = 0 if ( not os.path.isfile(dir_path + fname) or not (fileLength != sInds.shape[0] or numcommas != sInds.shape[0]) ): #If the file does not exist or is not the proper size, Recalculate for i in xrange(sInds.shape[0]): x0 = 0.01 maxCbyTtime[i] = fmin(CbyTfunc, x0, xtol=1e-8, args=(self, TL, sInds[i], fZ[i], fEZ, WA, mode, self.Cb[i], self.Csp[i]), disp=False) t_dets = maxCbyTtime #Sept 27, Execution time 101 seconds for 651 stars #Save maxCbyT to File###################################### try: #Here we delete the previous fZ file timeNow = datetime.datetime.now() timeString = str(timeNow.year) + '_' + str( timeNow.month) + '_' + str(timeNow.day) + '_' + str( timeNow.hour) + '_' + str(timeNow.minute) + '_' fnameNew = '/' + timeString + 'moved_maxCbyTtime.csv' os.rename(dir_path + fname, dir_path + fnameNew) except OSError: pass with open(dir_path + fname, "wb") as fo: wr = csv.writer(fo, quoting=csv.QUOTE_ALL) wr.writerow(maxCbyTtime) #Write the fZ to file fo.close() #Load maxCbyTtime for Each Star From File###### Sept 28, 2017 execution time is 0.00057 sec maxCbyTtimeList = list() with open(dir_path + fname, 'rb') as f: reader = csv.reader(f) your_list = list(reader) f.close() for i in range(len(your_list)): tmp = np.asarray(your_list[i]).astype(np.float) maxCbyTtimeList.append(tmp) maxCbyTtime = np.asarray(maxCbyTtimeList, dtype=np.float64) t_dets = maxCbyTtime[0][sInds] ############################################################################# #Distribute Excess Mission Time################################################Sept 28, 2017 execution time 19.0 sec missionLength = ( TK.missionFinishAbs - TK.currentTimeAbs ).value * 12 / 12 #TK.missionLife.to(u.day).value#mission length in days overheadTime = self.Observatory.settlingTime.value + self.OpticalSystem.observingModes[ 0]['syst']['ohTime'].value #OH time in days while ( (sum(t_dets) + sInds.shape[0] * overheadTime) > missionLength ): #the sum of star observation times is still larger than the mission length sInds, t_dets, sacrificedStarTime, fZ = self.sacrificeStarCbyT( sInds, t_dets, fZ, fEZ, WA, overheadTime) if (sum(t_dets + sInds.shape[0] * overheadTime) > missionLength): #There is some excess time sacrificedStarTime = missionLength - ( sum(t_dets) + sInds.shape[0] * overheadTime ) #The amount of time the list is under the total mission Time t_dets = self.distributedt(sInds, t_dets, sacrificedStarTime, fZ, fEZ, WA) ############################################################################### #STARK AYO LOOP################################################################ savedSumComp00 = np.zeros(sInds.shape[0]) firstIteration = 1 #checks if this is the first iteration. numits = 0 #ensure an infinite loop does not occur. Should be depricated lastIterationSumComp = -10000000 #this is some ludacrisly negative number to ensure sumcomp runs. All sumcomps should be positive while numits < 100000 and sInds is not None: numits = numits + 1 #we increment numits each loop iteration #Sacrifice Lowest Performing Star################################################Sept 28, 2017 execution time 0.0744 0.032 at smallest list size sInds, t_dets, sacrificedStarTime, fZ = self.sacrificeStarCbyT( sInds, t_dets, fZ, fEZ, WA, overheadTime) #Distribute Sacrificed Time to new star observations############################# Sept 28, 2017 execution time 0.715, 0.64 at smallest (depends on # stars) t_dets = self.distributedt(sInds, t_dets, sacrificedStarTime, fZ, fEZ, WA) #AYO Termination Conditions###############################Sept 28, 2017 execution time 0.033 sec Comp00 = self.Completeness.comp_per_intTime( t_dets * u.d, TL, sInds, fZ, fEZ, WA, mode, self.Cb, self.Csp) #change this to an assert if 1 >= len(sInds): #if this is the last ement in the list #print('sInds maximally sorted (This probably indicates an error)') #print(saltyburrito) break savedSumComp00[numits - 1] = sum(Comp00) # # #If the total sum of completeness at this moment is less than the last sum, then exit if ( sum(Comp00) < lastIterationSumComp ): #If sacrificing the additional target reduced performance, then Define Output of AYO Process CbyT = self.Completeness.comp_per_intTime( t_dets * u.d, self.TargetList, sInds, fZ, fEZ, WA, self.mode, self.Cb, self.Csp ) / t_dets #takes 5 seconds to do 1 time for all stars sortIndex = np.argsort(CbyT, axis=-1)[::-1] #This is the static optimal schedule self.schedule = sInds[sortIndex] self.t_dets = t_dets[sortIndex] self.CbyT = CbyT[sortIndex] self.fZ = fZ[sortIndex] self.Comp00 = Comp00[sortIndex] break else: #else set lastIterationSumComp to current sum Comp00 lastIterationSumComp = sum(Comp00) print( str(numits) + ' SumComp ' + str(sum(Comp00)) + ' Sum(t_dets) ' + str(sum(t_dets)) + ' sInds ' + str(sInds.shape[0] * float(1)) + ' TimeConservation ' + str(sum(t_dets) + sInds.shape[0] * float(1)) ) # + ' Avg C/T ' + str(np.average(CbyT)))
def __init__(self, **specs): SurveySimulation.__init__(self, **specs)
def __init__(self, cacheOptTimes=False, staticOptTimes=False, **specs): SurveySimulation.__init__(self, **specs) assert isinstance(staticOptTimes, bool), 'staticOptTimes must be boolean.' self.staticOptTimes = staticOptTimes self._outspec['staticOptTimes'] = self.staticOptTimes assert isinstance(cacheOptTimes, bool), 'cacheOptTimes must be boolean.' self._outspec['cacheOptTimes'] = cacheOptTimes # bring inherited class objects to top level of Survey Simulation OS = self.OpticalSystem ZL = self.ZodiacalLight TL = self.TargetList Obs = self.Observatory TK = self.TimeKeeping #Create and start Schedule self.schedule = np.arange(TL.nStars)#self.schedule is meant to be editable self.schedule_startSaved = np.arange(TL.nStars)#preserves initial list of targets dMagLim = self.Completeness.dMagLim self.dmag_startSaved = np.linspace(1, dMagLim, num=1500,endpoint=True) sInds = self.schedule_startSaved.copy() dmag = self.dmag_startSaved WA = OS.WA0 startTime = np.zeros(sInds.shape[0])*u.d + TK.currentTimeAbs #Generate fZ #no longer necessary because called by calcfZmin #Estimate Yearly fZmin########################################### self.fZmin, self.abdTimefZmin = ZL.calcfZmin(sInds, Obs, TL, TK, self.mode, self.cachefname) #Estimate Yearly fZmax########################################### self.fZmax, self.abdTimefZmax = ZL.calcfZmax(sInds, Obs, TL, TK, self.mode, self.cachefname) ################################################################# #CACHE Cb Cp Csp################################################Sept 20, 2017 execution time 10.108 sec #WE DO NOT NEED TO CALCULATE OVER EVERY DMAG Cp = np.zeros([sInds.shape[0],dmag.shape[0]]) Cb = np.zeros(sInds.shape[0]) Csp = np.zeros(sInds.shape[0]) for i in xrange(dmag.shape[0]): Cp[:,i], Cb[:], Csp[:] = OS.Cp_Cb_Csp(TL, sInds, self.fZmin, ZL.fEZ0, dmag[i], WA, self.mode) self.Cb = Cb[:]/u.s#Cb[:,0]/u.s#note all Cb are the same for different dmags. They are just star dependent self.Csp = Csp[:]/u.s#Csp[:,0]/u.s#note all Csp are the same for different dmags. They are just star dependent #self.Cp = Cp[:,:] #This one is dependent upon dmag and each star ################################################################ #Load cached Observation Times cachefname = self.cachefname + 'starkcache' # Generate cache Name if cacheOptTimes and os.path.isfile(cachefname):#Checks if flag to load cached optimal times exists self.vprint("Loading starkcache from %s"%cachefname) try: with open(cachefname, "rb") as ff: tmpDat = pickle.load(ff) except UnicodeDecodeError: with open(cachefname, "rb") as ff: tmpDat = pickle.load(ff,encoding='latin1') self.schedule = tmpDat[0,:].astype(int) self.t_dets = tmpDat[1,:] self.CbyT = tmpDat[2,:] self.Comp00 = tmpDat[3,:] else:#create cachedOptTimes self.altruisticYieldOptimization(sInds)
def __init__(self, cacheOptTimes=False, staticOptTimes=False, **specs): SurveySimulation.__init__(self, **specs) assert isinstance(staticOptTimes, bool), 'staticOptTimes must be boolean.' self.staticOptTimes = staticOptTimes self._outspec['staticOptTimes'] = self.staticOptTimes assert isinstance(cacheOptTimes, bool), 'cacheOptTimes must be boolean.' self._outspec['cacheOptTimes'] = cacheOptTimes # bring inherited class objects to top level of Survey Simulation SU = self.SimulatedUniverse OS = self.OpticalSystem ZL = self.ZodiacalLight #self.Completeness = SU.Completeness TL = self.TargetList Obs = self.Observatory TK = self.TimeKeeping #Create and start Schedule self.schedule = np.arange(TL.nStars)#self.schedule is meant to be editable self.schedule_startSaved = np.arange(TL.nStars)#preserves initial list of targets dMagLim = self.Completeness.dMagLim self.dmag_startSaved = np.linspace(1, dMagLim, num=1500,endpoint=True) sInds = self.schedule_startSaved.copy() dmag = self.dmag_startSaved WA = OS.WA0 startTime = np.zeros(sInds.shape[0])*u.d + TK.currentTimeAbs #Generate fZ #no longer necessary because called by calcfZmin #Estimate Yearly fZmin########################################### self.fZmin, self.abdTimefZmin = ZL.calcfZmin(sInds, Obs, TL, TK, self.mode, self.cachefname) #Estimate Yearly fZmax########################################### self.fZmax, self.abdTimefZmax = ZL.calcfZmax(sInds, Obs, TL, TK, self.mode, self.cachefname) ################################################################# #CACHE Cb Cp Csp################################################Sept 20, 2017 execution time 10.108 sec #WE DO NOT NEED TO CALCULATE OVER EVERY DMAG Cp = np.zeros([sInds.shape[0],dmag.shape[0]]) Cb = np.zeros(sInds.shape[0]) Csp = np.zeros(sInds.shape[0]) for i in xrange(dmag.shape[0]): Cp[:,i], Cb[:], Csp[:] = OS.Cp_Cb_Csp(TL, sInds, self.fZmin, ZL.fEZ0, dmag[i], WA, self.mode) self.Cb = Cb[:]/u.s#Cb[:,0]/u.s#note all Cb are the same for different dmags. They are just star dependent self.Csp = Csp[:]/u.s#Csp[:,0]/u.s#note all Csp are the same for different dmags. They are just star dependent #self.Cp = Cp[:,:] #This one is dependent upon dmag and each star ################################################################ #Load cached Observation Times cachefname = self.cachefname + 'starkcache' # Generate cache Name if cacheOptTimes and os.path.isfile(cachefname):#Checks if flag to load cached optimal times exists self.vprint("Loading starkcache from %s"%cachefname) with open(cachefname, 'rb') as f:#load from cache tmpDat = pickle.load(f) self.schedule = tmpDat[0,:].astype(int) self.t_dets = tmpDat[1,:] self.CbyT = tmpDat[2,:] self.Comp00 = tmpDat[3,:] sInds = np.arange(self.TargetList.nStars) else:#create cachedOptTimes #Calculate Initial Integration Times########################################### maxCbyTtime = self.calcTinit(sInds, TL, self.fZmin, ZL.fEZ0, WA, self.mode) t_dets = maxCbyTtime#[sInds] #t_dets has length TL.nStars #Sacrifice Stars and then Distribute Excess Mission Time################################################Sept 28, 2017 execution time 19.0 sec overheadTime = Obs.settlingTime.value + OS.observingModes[0]['syst']['ohTime'].value#OH time in days while((sum(t_dets) + sInds.shape[0]*overheadTime) > (TK.missionLife*TK.missionPortion).to('day').value):#the sum of star observation times is still larger than the mission length sInds, t_dets, sacrificedStarTime= self.sacrificeStarCbyT(sInds, t_dets, self.fZmin[sInds], ZL.fEZ0, WA, overheadTime) self.vprint('Started with ' + str(TL.nStars) + ' sacrificed down to ' + str(sInds.shape[0])) if(sum(t_dets + sInds.shape[0]*overheadTime) > (TK.missionLife*TK.missionPortion).to('day').value):#There is some excess time sacrificedStarTime = (TK.missionLife*TK.missionPortion).to('day').value - (sum(t_dets) + sInds.shape[0]*overheadTime)#The amount of time the list is under the total mission Time t_dets = self.distributedt(sInds, t_dets, sacrificedStarTime, self.fZmin[sInds], ZL.fEZ0, WA) ############################################################################### #STARK AYO LOOP################################################################ numits = 0#ensure an infinite loop does not occur. Should be depricated lastIterationSumComp = -10000000 #this is some ludacrisly negative number to ensure sumcomp runs. All sumcomps should be positive while numits < 100000 and sInds is not None: numits = numits+1#we increment numits each loop iteration #Sacrifice Lowest Performing Star################################################Sept 28, 2017 execution time 0.0744 0.032 at smallest list size sInds, t_dets, sacrificedStarTime = self.sacrificeStarCbyT(sInds, t_dets, self.fZmin[sInds], ZL.fEZ0, WA, overheadTime) #Distribute Sacrificed Time to new star observations############################# Sept 28, 2017 execution time 0.715, 0.64 at smallest (depends on # stars) t_dets = self.distributedt(sInds, t_dets, sacrificedStarTime, self.fZmin[sInds], ZL.fEZ0, WA) #AYO Termination Conditions###############################Sept 28, 2017 execution time 0.033 sec Comp00 = self.Completeness.comp_per_intTime(t_dets*u.d, TL, sInds, self.fZmin[sInds], ZL.fEZ0, WA, self.mode, self.Cb[sInds], self.Csp[sInds]) #change this to an assert if 1 >= len(sInds):#if this is the last ement in the list break #If the total sum of completeness at this moment is less than the last sum, then exit if(sum(Comp00) < lastIterationSumComp):#If sacrificing the additional target reduced performance, then Define Output of AYO Process CbyT = self.Completeness.comp_per_intTime(t_dets*u.d, self.TargetList, sInds, self.fZmin[sInds], ZL.fEZ0, WA, self.mode, self.Cb[sInds], self.Csp[sInds])/t_dets#takes 5 seconds to do 1 time for all stars sortIndex = np.argsort(CbyT,axis=-1)[::-1] #This is the static optimal schedule self.schedule = sInds[sortIndex] self.t_dets = t_dets[sortIndex] self.CbyT = CbyT[sortIndex] #self.fZ = fZ[sortIndex] self.Comp00 = Comp00[sortIndex] cachefname = self.cachefname + 'starkcache' # Generate cache Name tmpDat = np.zeros([4,self.schedule.shape[0]]) tmpDat[0,:] = self.schedule tmpDat[1,:] = self.t_dets tmpDat[2,:] = self.CbyT tmpDat[3,:] = self.Comp00 self.vprint("Saving starkcache to %s"%cachefname) with open(cachefname, 'wb') as f:#save to cache pickle.dump(tmpDat,f) break else:#else set lastIterationSumComp to current sum Comp00 lastIterationSumComp = sum(Comp00) self.vprint("%d SumComp %.2f Sum(t_dets) %.2f sInds %d Time Conservation %.2f" \ %(numits, sum(Comp00), sum(t_dets), sInds.shape[0], sum(t_dets)+sInds.shape[0]*overheadTime))
def __init__(self, cacheOptTimes=False, **specs): SurveySimulation.__init__(self, **specs) assert isinstance(cacheOptTimes, bool), 'cacheOptTimes must be boolean.' self._outspec['cacheOptTimes'] = cacheOptTimes #Load cached Observation Times self.starkt0 = None if cacheOptTimes: #Checks if flag exists cachefname = '' #declares cachefname mods = [ 'PlanetPopulation', 'PlanetPhysicalModel', 'Completeness', 'TargetList', 'OpticalSystem' ] #modules to look at for mod in mods: cachefname += self.modules[mod].__module__.split(".")[ -1] #add module name to end of cachefname? cachefname += hashlib.md5( str(self.TargetList.Name) + str(self.TargetList.tint0.to(u.d).value)).hexdigest( ) #turn cachefname into hashlib cachefname = os.path.join( os.path.split(inspect.getfile(self.__class__))[0], cachefname + os.extsep + 'starkt0') #'t0')#join into filepath and fname if os.path.isfile(cachefname): #check if file exists self.vprint("Loading cached t0 from %s" % cachefname) with open(cachefname, 'rb') as f: #load from cache self.starkt0 = pickle.load(f) sInds = np.arange(self.TargetList.nStars) # bring inherited class objects to top level of Survey Simulation SU = self.SimulatedUniverse OS = SU.OpticalSystem ZL = SU.ZodiacalLight self.Completeness = SU.Completeness TL = SU.TargetList Obs = self.Observatory TK = self.TimeKeeping self.starVisits = np.zeros(TL.nStars, dtype=int) self.starRevisit = np.array([]) detMode = filter(lambda mode: mode['detectionMode'] == True, OS.observingModes)[0] spectroModes = filter(lambda mode: 'spec' in mode['inst']['name'], OS.observingModes) self.mode = detMode #Create and start Schedule self.schedule = np.arange( TL.nStars) #self.schedule is meant to be editable self.schedule_startSaved = np.arange( TL.nStars) #preserves initial list of targets dMagLim = self.Completeness.dMagLim self.dmag_startSaved = np.linspace(1, dMagLim, num=1500, endpoint=True) sInds = self.schedule_startSaved dmag = self.dmag_startSaved WA = OS.WA0 startTime = np.zeros( sInds.shape[0]) * u.d + self.TimeKeeping.currentTimeAbs tovisit = np.zeros(sInds.shape[0], dtype=bool) #Generate fZ self.fZ_startSaved = self.generate_fZ(sInds) # #Estimate Yearly fZmin########################################### fZmin, fZminInds = self.calcfZmin(sInds, self.fZ_startSaved) #Estimate Yearly fZmin########################################### # tmpfZ = np.asarray(self.fZ_startSaved) # fZ_matrix = tmpfZ[sInds,:]#Apply previous filters to fZ_startSaved[sInds, 1000] # #Find minimum fZ of each star # fZmin = np.zeros(sInds.shape[0]) # fZminInds = np.zeros(sInds.shape[0]) # for i in xrange(len(sInds)): # fZmin[i] = min(fZ_matrix[i,:]) # fZminInds[i] = np.argmin(fZ_matrix[i,:]) ################################################################# #CACHE Cb Cp Csp################################################Sept 20, 2017 execution time 10.108 sec fZ = fZmin / u.arcsec**2 # fEZ = ZL.fEZ0 mode = self.mode #resolve this mode is passed into next_target allModes = self.OpticalSystem.observingModes det_mode = filter(lambda mode: mode['detectionMode'] == True, allModes)[0] Cp = np.zeros([sInds.shape[0], dmag.shape[0]]) Cb = np.zeros(sInds.shape[0]) Csp = np.zeros(sInds.shape[0]) for i in xrange(dmag.shape[0]): Cp[:, i], Cb[:], Csp[:] = OS.Cp_Cb_Csp(TL, sInds, fZ, fEZ, dmag[i], WA, det_mode) self.Cb = Cb[:] / u.s #Cb[:,0]/u.s#note all Cb are the same for different dmags. They are just star dependent self.Csp = Csp[:] / u.s #Csp[:,0]/u.s#note all Csp are the same for different dmags. They are just star dependent #self.Cp = Cp[:,:] #This one is dependent upon dmag and each star ################################################################ #Calculate Initial Integration Times########################################### maxCbyTtime = self.calcTinit(sInds, TL, fZ, fEZ, WA, mode, self.Cb, self.Csp) t_dets = maxCbyTtime[sInds] #Sacrifice Stars and then Distribute Excess Mission Time################################################Sept 28, 2017 execution time 19.0 sec missionLength = ( TK.missionLife.to(u.d) * TK.missionPortion ).value * 12 / 12 #TK.missionLife.to(u.day).value#mission length in days overheadTime = self.Observatory.settlingTime.value + self.OpticalSystem.observingModes[ 0]['syst']['ohTime'].value #OH time in days while ( (sum(t_dets) + sInds.shape[0] * overheadTime) > missionLength ): #the sum of star observation times is still larger than the mission length sInds, t_dets, sacrificedStarTime, fZ = self.sacrificeStarCbyT( sInds, t_dets, fZ, fEZ, WA, overheadTime) if (sum(t_dets + sInds.shape[0] * overheadTime) > missionLength): #There is some excess time sacrificedStarTime = missionLength - ( sum(t_dets) + sInds.shape[0] * overheadTime ) #The amount of time the list is under the total mission Time t_dets = self.distributedt(sInds, t_dets, sacrificedStarTime, fZ, fEZ, WA) ############################################################################### #STARK AYO LOOP################################################################ savedSumComp00 = np.zeros(sInds.shape[0]) firstIteration = 1 #checks if this is the first iteration. numits = 0 #ensure an infinite loop does not occur. Should be depricated lastIterationSumComp = -10000000 #this is some ludacrisly negative number to ensure sumcomp runs. All sumcomps should be positive while numits < 100000 and sInds is not None: numits = numits + 1 #we increment numits each loop iteration #Sacrifice Lowest Performing Star################################################Sept 28, 2017 execution time 0.0744 0.032 at smallest list size sInds, t_dets, sacrificedStarTime, fZ = self.sacrificeStarCbyT( sInds, t_dets, fZ, fEZ, WA, overheadTime) #Distribute Sacrificed Time to new star observations############################# Sept 28, 2017 execution time 0.715, 0.64 at smallest (depends on # stars) t_dets = self.distributedt(sInds, t_dets, sacrificedStarTime, fZ, fEZ, WA) #AYO Termination Conditions###############################Sept 28, 2017 execution time 0.033 sec Comp00 = self.Completeness.comp_per_intTime( t_dets * u.d, TL, sInds, fZ, fEZ, WA, mode, self.Cb, self.Csp) #change this to an assert if 1 >= len(sInds): #if this is the last ement in the list break savedSumComp00[numits - 1] = sum(Comp00) #If the total sum of completeness at this moment is less than the last sum, then exit if ( sum(Comp00) < lastIterationSumComp ): #If sacrificing the additional target reduced performance, then Define Output of AYO Process CbyT = self.Completeness.comp_per_intTime( t_dets * u.d, self.TargetList, sInds, fZ, fEZ, WA, self.mode, self.Cb, self.Csp ) / t_dets #takes 5 seconds to do 1 time for all stars sortIndex = np.argsort(CbyT, axis=-1)[::-1] #This is the static optimal schedule self.schedule = sInds[sortIndex] self.t_dets = t_dets[sortIndex] self.CbyT = CbyT[sortIndex] self.fZ = fZ[sortIndex] self.Comp00 = Comp00[sortIndex] break else: #else set lastIterationSumComp to current sum Comp00 lastIterationSumComp = sum(Comp00) self.vprint( str(numits) + ' SumComp ' + str(sum(Comp00)) + ' Sum(t_dets) ' + str(sum(t_dets)) + ' sInds ' + str(sInds.shape[0] * float(1)) + ' TimeConservation ' + str(sum(t_dets) + sInds.shape[0] * float(1)) ) # + ' Avg C/T ' + str(np.average(CbyT)))
def __init__(self, cacheOptTimes=False, staticOptTimes=False, **specs): SurveySimulation.__init__(self, **specs) assert isinstance(staticOptTimes, bool), 'staticOptTimes must be boolean.' self.staticOptTimes = staticOptTimes self._outspec['staticOptTimes'] = self.staticOptTimes assert isinstance(cacheOptTimes, bool), 'cacheOptTimes must be boolean.' self._outspec['cacheOptTimes'] = cacheOptTimes # bring inherited class objects to top level of Survey Simulation OS = self.OpticalSystem ZL = self.ZodiacalLight TL = self.TargetList Obs = self.Observatory TK = self.TimeKeeping #Create and start Schedule self.schedule = np.arange( TL.nStars) #self.schedule is meant to be editable self.schedule_startSaved = np.arange( TL.nStars) #preserves initial list of targets dMagLim = self.Completeness.dMagLim self.dmag_startSaved = np.linspace(1, dMagLim, num=1500, endpoint=True) sInds = self.schedule_startSaved.copy() dmag = self.dmag_startSaved WA = OS.WA0 startTime = np.zeros(sInds.shape[0]) * u.d + TK.currentTimeAbs #Generate fZ #no longer necessary because called by calcfZmin #Estimate Yearly fZmin########################################### self.fZmin, self.abdTimefZmin = ZL.calcfZmin(sInds, Obs, TL, TK, self.mode, self.cachefname) #Estimate Yearly fZmax########################################### self.fZmax, self.abdTimefZmax = ZL.calcfZmax(sInds, Obs, TL, TK, self.mode, self.cachefname) ################################################################# #CACHE Cb Cp Csp################################################Sept 20, 2017 execution time 10.108 sec #WE DO NOT NEED TO CALCULATE OVER EVERY DMAG Cp = np.zeros([sInds.shape[0], dmag.shape[0]]) Cb = np.zeros(sInds.shape[0]) Csp = np.zeros(sInds.shape[0]) for i in xrange(dmag.shape[0]): Cp[:, i], Cb[:], Csp[:] = OS.Cp_Cb_Csp(TL, sInds, self.fZmin, ZL.fEZ0, dmag[i], WA, self.mode) self.Cb = Cb[:] / u.s #Cb[:,0]/u.s#note all Cb are the same for different dmags. They are just star dependent self.Csp = Csp[:] / u.s #Csp[:,0]/u.s#note all Csp are the same for different dmags. They are just star dependent #self.Cp = Cp[:,:] #This one is dependent upon dmag and each star ################################################################ #Load cached Observation Times cachefname = self.cachefname + 'starkcache' # Generate cache Name if cacheOptTimes and os.path.isfile( cachefname ): #Checks if flag to load cached optimal times exists self.vprint("Loading starkcache from %s" % cachefname) with open(cachefname, 'rb') as f: #load from cache tmpDat = pickle.load(f) self.schedule = tmpDat[0, :].astype(int) self.t_dets = tmpDat[1, :] self.CbyT = tmpDat[2, :] self.Comp00 = tmpDat[3, :] else: #create cachedOptTimes self.altruisticYieldOptimization(sInds)
def __init__(self, cacheOptTimes=False, staticOptTimes=False, selectionMetric='maxC', Izod='current', maxiter=60, ftol=1e-3, **specs): #fZminObs=False, #initialize the prototype survey SurveySimulation.__init__(self, **specs) #Calculate fZmax self.valfZmax, self.absTimefZmax = self.ZodiacalLight.calcfZmax(np.arange(self.TargetList.nStars), self.Observatory, self.TargetList, self.TimeKeeping, list(filter(lambda mode: mode['detectionMode'] == True, self.OpticalSystem.observingModes))[0], self.cachefname) assert isinstance(staticOptTimes, bool), 'staticOptTimes must be boolean.' self.staticOptTimes = staticOptTimes self._outspec['staticOptTimes'] = self.staticOptTimes assert isinstance(cacheOptTimes, bool), 'cacheOptTimes must be boolean.' self._outspec['cacheOptTimes'] = cacheOptTimes assert selectionMetric in ['maxC','Izod-Izodmin','Izod-Izodmax', '(Izod-Izodmin)/(Izodmax-Izodmin)', '(Izod-Izodmin)/(Izodmax-Izodmin)/CIzod', #(Izod-Izodmin)/(Izodmax-Izodmin)/CIzodmin is simply this but with Izod='fZmin' 'TauIzod/CIzod', #TauIzodmin/CIzodmin is simply this but with Izod='fZmin' 'random', 'priorityObs'], 'selectionMetric not valid input' # Informs what selection metric to use self.selectionMetric = selectionMetric self._outspec['selectionMetric'] = self.selectionMetric assert Izod in ['fZmin','fZ0','fZmax','current'], 'Izod not valid input' # Informs what Izod to optimize integration times for [fZmin, fZmin+45d, fZ0, fZmax, current] self.Izod = Izod self._outspec['Izod'] = self.Izod assert isinstance(maxiter, int), 'maxiter is not an int' # maximum number of iterations to optimize integration times for assert maxiter >= 1, 'maxiter must be positive real' self.maxiter = maxiter self._outspec['maxiter'] = self.maxiter assert isinstance(ftol, float), 'ftol must be boolean' # tolerance to place on optimization assert ftol > 0, 'ftol must be positive real' self.ftol = ftol self._outspec['ftol'] = self.ftol #some global defs self.detmode = list(filter(lambda mode: mode['detectionMode'] == True, self.OpticalSystem.observingModes))[0] self.ohTimeTot = self.Observatory.settlingTime + self.detmode['syst']['ohTime'] # total overhead time per observation self.maxTime = self.TimeKeeping.missionLife*self.TimeKeeping.missionPortion # total mission time self.constraints = {'type':'ineq', 'fun': lambda x: self.maxTime.to(u.d).value - np.sum(x[x*u.d > 0.1*u.s]) - #maxTime less sum of intTimes np.sum(x*u.d > 0.1*u.s).astype(float)*self.ohTimeTot.to(u.d).value, # sum of True -> goes to 1 x OHTime 'jac':lambda x: np.ones(len(x))*-1.} self.t0 = None if cacheOptTimes: #Generate cache Name######################################################################## cachefname = self.cachefname + 't0' if os.path.isfile(cachefname): self.vprint("Loading cached t0 from %s"%cachefname) with open(cachefname, 'rb') as f: self.t0 = pickle.load(f) sInds = np.arange(self.TargetList.nStars) fZ = np.array([self.ZodiacalLight.fZ0.value]*len(sInds))*self.ZodiacalLight.fZ0.unit self.scomp0 = -self.objfun(self.t0.to('day').value,sInds,fZ) if self.t0 is None: #1. find nominal background counts for all targets in list dMagint = 25.0 # this works fine for WFIRST _, Cbs, Csps = self.OpticalSystem.Cp_Cb_Csp(self.TargetList, np.arange(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, dMagint, self.WAint, self.detmode) #find baseline solution with dMagLim-based integration times #3. self.vprint('Finding baseline fixed-time optimal target set.') t0 = self.OpticalSystem.calc_intTime(self.TargetList, np.arange(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, self.dMagint, self.WAint, self.detmode) #4. comp0 = self.Completeness.comp_per_intTime(t0, self.TargetList, np.arange(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, self.WAint, self.detmode, C_b=Cbs, C_sp=Csps) #### 5. Formulating MIP to filter out stars we can't or don't want to reasonably observe solver = pywraplp.Solver('SolveIntegerProblem',pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) # create solver instance xs = [ solver.IntVar(0.0,1.0, 'x'+str(j)) for j in np.arange(len(comp0)) ] # define x_i variables for each star either 0 or 1 #constraint is x_i*t_i < maxtime constraint = solver.Constraint(-solver.infinity(),self.maxTime.to(u.day).value) for j,x in enumerate(xs): constraint.SetCoefficient(x, t0[j].to('day').value + self.ohTimeTot.to(u.day).value) # this forms x_i*(t_0i+OH) for all i #objective is max x_i*comp_i objective = solver.Objective() for j,x in enumerate(xs): objective.SetCoefficient(x, comp0[j]) objective.SetMaximization() #solver.EnableOutput()# this line enables output of the CBC MIXED INTEGER PROGRAM (Was hard to find don't delete) solver.SetTimeLimit(5*60*1000)#time limit for solver in milliseconds cpres = solver.Solve() # actually solve MIP x0 = np.array([x.solution_value() for x in xs]) # convert output solutions self.scomp0 = np.sum(comp0*x0) # calculate sum Comp from MIP self.t0 = t0 # assign calculated t0 #Observation num x0=0 @ dMagint=25 is 1501 #Observation num x0=0 @ dMagint=30 is 1501... #now find the optimal eps baseline and use whichever gives you the highest starting completeness self.vprint('Finding baseline fixed-eps optimal target set.') def totCompfeps(eps): compstars,tstars,x = self.inttimesfeps(eps, Cbs.to('1/d').value, Csps.to('1/d').value) return -np.sum(compstars*x) #Note: There is no way to seed an initial solution to minimize scalar #0 and 1 are supposed to be the bounds on epsres. I could define upper bound to be 0.01, However defining the bounds to be 5 lets the solver converge epsres = minimize_scalar(totCompfeps,method='bounded',bounds=[0,7], options={'disp': 3, 'xatol':self.ftol, 'maxiter': self.maxiter}) #adding ftol for initial seed. could be different ftol #https://docs.scipy.org/doc/scipy/reference/optimize.minimize_scalar-bounded.html#optimize-minimize-scalar-bounded comp_epsmax,t_epsmax,x_epsmax = self.inttimesfeps(epsres['x'],Cbs.to('1/d').value, Csps.to('1/d').value) if np.sum(comp_epsmax*x_epsmax) > self.scomp0: x0 = x_epsmax self.scomp0 = np.sum(comp_epsmax*x_epsmax) self.t0 = t_epsmax*x_epsmax*u.day ##### Optimize the baseline solution self.vprint('Optimizing baseline integration times.') sInds = np.arange(self.TargetList.nStars) if self.Izod == 'fZ0': # Use fZ0 to calculate integration times fZ = np.array([self.ZodiacalLight.fZ0.value]*len(sInds))*self.ZodiacalLight.fZ0.unit elif self.Izod == 'fZmin': # Use fZmin to calculate integration times fZ = self.valfZmin elif self.Izod == 'fZmax': # Use fZmax to calculate integration times fZ = self.valfZmax elif self.Izod == 'current': # Use current fZ to calculate integration times fZ = self.ZodiacalLight.fZ(self.Observatory, self.TargetList, sInds, self.TimeKeeping.currentTimeAbs.copy()+np.zeros(self.TargetList.nStars)*u.d, self.detmode) maxIntTimeOBendTime, maxIntTimeExoplanetObsTime, maxIntTimeMissionLife = self.TimeKeeping.get_ObsDetectionMaxIntTime(self.Observatory, self.detmode, self.TimeKeeping.currentTimeNorm.copy()) maxIntTime = min(maxIntTimeOBendTime, maxIntTimeExoplanetObsTime, maxIntTimeMissionLife) # Maximum intTime allowed bounds = [(0,maxIntTime.to(u.d).value) for i in np.arange(len(sInds))] initguess = x0*self.t0.to(u.d).value self.save_initguess = initguess #While we use all sInds as input, theoretically, this can be solved faster if we use the following lines: #sInds = np.asarray([sInd for sInd in sInds if np.bool(x0[sInd])]) #bounds = [(0,maxIntTime.to(u.d).value) for i in np.arange(len(sInds))] #and use initguess[sInds], fZ[sInds], and self.t0[sInds]. #There was no noticable performance improvement ires = minimize(self.objfun, initguess, jac=self.objfun_deriv, args=(sInds,fZ), constraints=self.constraints, method='SLSQP', bounds=bounds, options={'maxiter':self.maxiter, 'ftol':self.ftol, 'disp': True}) #original method assert ires['success'], "Initial time optimization failed." self.t0 = ires['x']*u.d self.scomp0 = -ires['fun'] if cacheOptTimes: with open(cachefname,'wb') as f: pickle.dump(self.t0, f) self.vprint("Saved cached optimized t0 to %s"%cachefname) #Redefine filter inds self.intTimeFilterInds = np.where((self.t0 > 0.)*(self.t0 <= self.OpticalSystem.intCutoff) > 0.)[0] # These indices are acceptable for use simulating
def __init__(self, cacheOptTimes=False, staticOptTimes=False, selectionMetric='maxC', Izod='current', maxiter=60, ftol=1e-3, **specs): #fZminObs=False, #initialize the prototype survey SurveySimulation.__init__(self, **specs) #Calculate fZmax self.valfZmax, self.absTimefZmax = self.ZodiacalLight.calcfZmax( np.arange(self.TargetList.nStars), self.Observatory, self.TargetList, self.TimeKeeping, list( filter(lambda mode: mode['detectionMode'] == True, self.OpticalSystem.observingModes))[0], self.cachefname) assert isinstance(staticOptTimes, bool), 'staticOptTimes must be boolean.' self.staticOptTimes = staticOptTimes self._outspec['staticOptTimes'] = self.staticOptTimes assert isinstance(cacheOptTimes, bool), 'cacheOptTimes must be boolean.' self._outspec['cacheOptTimes'] = cacheOptTimes assert selectionMetric in [ 'maxC', 'Izod-Izodmin', 'Izod-Izodmax', '(Izod-Izodmin)/(Izodmax-Izodmin)', '(Izod-Izodmin)/(Izodmax-Izodmin)/CIzod', #(Izod-Izodmin)/(Izodmax-Izodmin)/CIzodmin is simply this but with Izod='fZmin' 'TauIzod/CIzod', #TauIzodmin/CIzodmin is simply this but with Izod='fZmin' 'random', 'priorityObs' ], 'selectionMetric not valid input' # Informs what selection metric to use self.selectionMetric = selectionMetric self._outspec['selectionMetric'] = self.selectionMetric assert Izod in [ 'fZmin', 'fZ0', 'fZmax', 'current' ], 'Izod not valid input' # Informs what Izod to optimize integration times for [fZmin, fZmin+45d, fZ0, fZmax, current] self.Izod = Izod self._outspec['Izod'] = self.Izod assert isinstance( maxiter, int ), 'maxiter is not an int' # maximum number of iterations to optimize integration times for assert maxiter >= 1, 'maxiter must be positive real' self.maxiter = maxiter self._outspec['maxiter'] = self.maxiter assert isinstance( ftol, float ), 'ftol must be boolean' # tolerance to place on optimization assert ftol > 0, 'ftol must be positive real' self.ftol = ftol self._outspec['ftol'] = self.ftol #some global defs self.detmode = list( filter(lambda mode: mode['detectionMode'] == True, self.OpticalSystem.observingModes))[0] self.ohTimeTot = self.Observatory.settlingTime + self.detmode['syst'][ 'ohTime'] # total overhead time per observation self.maxTime = self.TimeKeeping.missionLife * self.TimeKeeping.missionPortion # total mission time self.constraints = { 'type': 'ineq', 'fun': lambda x: self.maxTime.to(u.d).value - np.sum(x[ x * u.d > 0.1 * u.s]) - #maxTime less sum of intTimes np.sum(x * u.d > 0.1 * u.s).astype(float) * self.ohTimeTot.to(u.d). value, # sum of True -> goes to 1 x OHTime 'jac': lambda x: np.ones(len(x)) * -1. } self.t0 = None if cacheOptTimes: #Generate cache Name######################################################################## cachefname = self.cachefname + 't0' if os.path.isfile(cachefname): self.vprint("Loading cached t0 from %s" % cachefname) with open(cachefname, 'rb') as f: self.t0 = pickle.load(f) sInds = np.arange(self.TargetList.nStars) fZ = np.array([self.ZodiacalLight.fZ0.value] * len(sInds)) * self.ZodiacalLight.fZ0.unit self.scomp0 = -self.objfun(self.t0.to('day').value, sInds, fZ) if self.t0 is None: #1. find nominal background counts for all targets in list dMagint = 25.0 # this works fine for WFIRST _, Cbs, Csps = self.OpticalSystem.Cp_Cb_Csp( self.TargetList, np.arange(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, dMagint, self.WAint, self.detmode, TK=self.TimeKeeping) #find baseline solution with dMagLim-based integration times #3. self.vprint('Finding baseline fixed-time optimal target set.') t0 = self.OpticalSystem.calc_intTime(self.TargetList, np.arange( self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, self.dMagint, self.WAint, self.detmode, TK=self.TimeKeeping) #4. comp0 = self.Completeness.comp_per_intTime( t0, self.TargetList, np.arange(self.TargetList.nStars), self.ZodiacalLight.fZ0, self.ZodiacalLight.fEZ0, self.WAint, self.detmode, C_b=Cbs, C_sp=Csps, TK=self.TimeKeeping) #### 5. Formulating MIP to filter out stars we can't or don't want to reasonably observe solver = pywraplp.Solver( 'SolveIntegerProblem', pywraplp.Solver. CBC_MIXED_INTEGER_PROGRAMMING) # create solver instance xs = [ solver.IntVar(0.0, 1.0, 'x' + str(j)) for j in np.arange(len(comp0)) ] # define x_i variables for each star either 0 or 1 #constraint is x_i*t_i < maxtime constraint = solver.Constraint(-solver.infinity(), self.maxTime.to(u.day).value) for j, x in enumerate(xs): constraint.SetCoefficient( x, t0[j].to('day').value + self.ohTimeTot.to( u.day).value) # this forms x_i*(t_0i+OH) for all i #objective is max x_i*comp_i objective = solver.Objective() for j, x in enumerate(xs): objective.SetCoefficient(x, comp0[j]) objective.SetMaximization() #solver.EnableOutput()# this line enables output of the CBC MIXED INTEGER PROGRAM (Was hard to find don't delete) solver.SetTimeLimit(5 * 60 * 1000) #time limit for solver in milliseconds cpres = solver.Solve() # actually solve MIP x0 = np.array([x.solution_value() for x in xs]) # convert output solutions self.scomp0 = np.sum(comp0 * x0) # calculate sum Comp from MIP self.t0 = t0 # assign calculated t0 #Observation num x0=0 @ dMagint=25 is 1501 #Observation num x0=0 @ dMagint=30 is 1501... #now find the optimal eps baseline and use whichever gives you the highest starting completeness self.vprint('Finding baseline fixed-eps optimal target set.') def totCompfeps(eps): compstars, tstars, x = self.inttimesfeps( eps, Cbs.to('1/d').value, Csps.to('1/d').value) return -np.sum(compstars * x) #Note: There is no way to seed an initial solution to minimize scalar #0 and 1 are supposed to be the bounds on epsres. I could define upper bound to be 0.01, However defining the bounds to be 5 lets the solver converge epsres = minimize_scalar( totCompfeps, method='bounded', bounds=[0, 7], options={ 'disp': 3, 'xatol': self.ftol, 'maxiter': self.maxiter }) #adding ftol for initial seed. could be different ftol #https://docs.scipy.org/doc/scipy/reference/optimize.minimize_scalar-bounded.html#optimize-minimize-scalar-bounded comp_epsmax, t_epsmax, x_epsmax = self.inttimesfeps( epsres['x'], Cbs.to('1/d').value, Csps.to('1/d').value) if np.sum(comp_epsmax * x_epsmax) > self.scomp0: x0 = x_epsmax self.scomp0 = np.sum(comp_epsmax * x_epsmax) self.t0 = t_epsmax * x_epsmax * u.day ##### Optimize the baseline solution self.vprint('Optimizing baseline integration times.') sInds = np.arange(self.TargetList.nStars) if self.Izod == 'fZ0': # Use fZ0 to calculate integration times fZ = np.array([self.ZodiacalLight.fZ0.value] * len(sInds)) * self.ZodiacalLight.fZ0.unit elif self.Izod == 'fZmin': # Use fZmin to calculate integration times fZ = self.valfZmin elif self.Izod == 'fZmax': # Use fZmax to calculate integration times fZ = self.valfZmax elif self.Izod == 'current': # Use current fZ to calculate integration times fZ = self.ZodiacalLight.fZ( self.Observatory, self.TargetList, sInds, self.TimeKeeping.currentTimeAbs.copy() + np.zeros(self.TargetList.nStars) * u.d, self.detmode) maxIntTimeOBendTime, maxIntTimeExoplanetObsTime, maxIntTimeMissionLife = self.TimeKeeping.get_ObsDetectionMaxIntTime( self.Observatory, self.detmode, self.TimeKeeping.currentTimeNorm.copy()) maxIntTime = min(maxIntTimeOBendTime, maxIntTimeExoplanetObsTime, maxIntTimeMissionLife) # Maximum intTime allowed bounds = [(0, maxIntTime.to(u.d).value) for i in np.arange(len(sInds))] initguess = x0 * self.t0.to(u.d).value self.save_initguess = initguess #While we use all sInds as input, theoretically, this can be solved faster if we use the following lines: #sInds = np.asarray([sInd for sInd in sInds if np.bool(x0[sInd])]) #bounds = [(0,maxIntTime.to(u.d).value) for i in np.arange(len(sInds))] #and use initguess[sInds], fZ[sInds], and self.t0[sInds]. #There was no noticable performance improvement ires = minimize(self.objfun, initguess, jac=self.objfun_deriv, args=(sInds, fZ), constraints=self.constraints, method='SLSQP', bounds=bounds, options={ 'maxiter': self.maxiter, 'ftol': self.ftol, 'disp': True }) #original method assert ires['success'], "Initial time optimization failed." self.t0 = ires['x'] * u.d self.scomp0 = -ires['fun'] if cacheOptTimes: with open(cachefname, 'wb') as f: pickle.dump(self.t0, f) self.vprint("Saved cached optimized t0 to %s" % cachefname) #Redefine filter inds self.intTimeFilterInds = np.where( (self.t0 > 0.) * (self.t0 <= self.OpticalSystem.intCutoff) > 0.)[ 0] # These indices are acceptable for use simulating