def _watchProgramBegin(self, program): session = model.Session() rsession = RSession() try: program = session.merge(program) self._debuglog.debug('Program %s started' % program) site = self.getSite() log = ObservingLog(time=datetimeFromJD(site.MJD() + 2400000.5, ), tid=program.tid, name=program.name, priority=program.priority, action='ROBOBS: Program Started') rsession.add(log) finally: session.commit() rsession.commit()
def _watchProgramComplete(self, program, status, message=None): session = model.Session() rsession = RSession() try: program = session.merge(program) self._debuglog.debug('Program %s completed with status %s(%s)' % (program, status, message)) site = self.getSite() log = ObservingLog( time=datetimeFromJD(site.MJD() + 2400000.5, ), tid=program.tid, name=program.name, priority=program.priority, action='ROBOBS: Program End with status %s(%s)' % (status, message)) rsession.add(log) rsession.commit() if status == SchedulerStatus.OK and self._current_program is not None: cp = rsession.merge(self._current_program[0]) cp.finished = True rsession.commit() block_config = rsession.merge(self._current_program[1]) sched = schedAlgorithms[block_config.schedalgorith] sched.observed(site.MJD(), self._current_program, site) rsession.commit() rsession.commit() self._current_program = None elif status != SchedulerStatus.OK: self.stop() finally: session.commit() rsession.commit()
def _readout(self, request): self.readoutBegin(request) img = Dispatch("CCDSoft.Image") img.AttachToActiveImager() pix = np.transpose(np.array(img.DataArray)) (mode, binning, top, left, width, height) = self._getReadoutModeInfo(request["binning"], request["window"]) request.headers.append(('GAIN', str(mode.gain), 'Electronic gain in photoelectrons per ADU')) proxy = self._saveImage(request, pix, { "frame_start_time": datetimeFromJD(img.JulianDay), "frame_temperature": self.getTemperature(), "binning_factor": self._binning_factors[binning]}) # [ABORT POINT] if self.abort.isSet(): self.readoutComplete(None, CameraStatus.ABORTED) return None self.readoutComplete(proxy, CameraStatus.OK) return proxy
def checkConditions(self, program, time, program_length=0., external_checker=None): ''' Check if a program can be executed given all restrictions imposed by airmass, moon distance, seeing, cloud cover, etc... [comment] There must be a good way of letting the user rewrite this easily. I can only think about a decorator but I am not sure how to implement it. :param program: :return: True (Program can be executed) | False (Program cannot be executed) ''' site = self.getSite() # 1) check airmass session = RSession() # program = session.merge(prg) target = session.merge(program[3]) # obsblock = session.merge(program[2]) blockpar = session.merge(program[1]) raDec = Position.fromRaDec(target.targetRa, target.targetDec) dateTime = datetimeFromJD(time + 2400000.5) lst = site.LST_inRads(dateTime) # in radians alt = float(site.raDecToAltAz(raDec, lst).alt) airmass = 1. / np.cos(np.pi / 2. - alt * np.pi / 180.) if blockpar.minairmass < airmass < blockpar.maxairmass: self._debuglog.debug('\tairmass:%.3f' % airmass) pass else: self._debuglog.warning( 'Target %s out of airmass range @ %.3f... (%f < %f < %f)' % (target, time, blockpar.minairmass, airmass, blockpar.maxairmass)) return False if program_length > 0.: observation_end = datetimeFromJD((time + program_length / 86.4e3) + 2400000.5).replace(tzinfo=None) # lst = site.LST_inRads(dateTime) # in radians night_end = site.sunrise_twilight_begin(dateTime).replace( tzinfo=None) if observation_end > night_end: self._debuglog.warning( 'Block finish @ %s. Night end is @ %s!' % (observation_end, night_end)) return False else: self._debuglog.debug('Block finish @ %s. Night end is @ %s!' % (observation_end, night_end)) alt = float(site.raDecToAltAz(raDec, lst).alt) airmass = 1. / np.cos(np.pi / 2. - alt * np.pi / 180.) if blockpar.minairmass < airmass < blockpar.maxairmass: self._debuglog.debug('\tairmass:%.3f' % airmass) pass else: self._debuglog.warning( 'Target %s out of airmass range @ %.3f... (%f < %f < %f)' % (target, time, blockpar.minairmass, airmass, blockpar.maxairmass)) # return False # FIXME pass # 2) check moon Brightness moonPos = site.moonpos(dateTime) moonBrightness = site.moonphase(dateTime) * 100. if blockpar.minmoonBright < moonBrightness < blockpar.maxmoonBright: self._debuglog.debug('\tMoon brightness:%.2f' % moonBrightness) pass elif moonPos.alt < 0.: self._debuglog.warning( '\tMoon bellow horizon. Moon brightness:%.2f' % moonBrightness) else: self._debuglog.warning('Wrong Moon Brightness... (%f < %f < %f)' % (blockpar.minmoonBright, moonBrightness, blockpar.maxmoonBright)) return False # 3) check moon distance moonRaDec = site.altAzToRaDec(moonPos, lst) moonDist = raDec.angsep(moonRaDec) if moonDist < blockpar.minmoonDist: self._debuglog.warning( 'Object to close to the moon... ' 'Target@ %s / Moon@ %s (moonDist = %f | minmoonDist = %f)' % (raDec, moonRaDec, moonDist, blockpar.minmoonDist)) return False else: self._debuglog.debug('\tMoon distance:%.3f' % moonDist) # 4) check seeing if self["seeingmonitors"] is not None: seeing = self.getSM().seeing() if seeing > blockpar.maxseeing: self._debuglog.warning( 'Seeing higher than specified... sm = %f | max = %f' % (seeing, blockpar.maxseeing)) return False elif seeing < 0.: self._debuglog.warning('No seeing measurement...') else: self._debuglog.debug('Seeing %.3f' % seeing) # 5) check cloud cover if self["cloudsensors"] is not None: pass if self["weatherstations"] is not None: pass if external_checker is not None: # Todo: add a 3rd option which is a function to check if program is ok from the algorithm itself. pass self._debuglog.debug('Target OK!') return True
def targets(self): ''' After selecting targets, you can generate a list of potential targets to run the scheduler. ''' session = Session() fp1 = open(os.path.join(self.PATH,'Fixed.txt'),'w') fp2 = open(os.path.join(self.PATH,'request.stg'),'w') # Write header fp1.write('''P|Designation | RA | dec |mag. -|------------|hh mm ss.ss|sdd mm ss.s|nn.n ''') config = { 'name' : '', 'user' : '', 'nimages' : 1, 'expt' : 0, 'filter' : '', 'time' : ''} for obstype in [self.stdFlag,self.sciFlag]: targets = session.query(Targets,Program).join((Program,Targets.id==Program.tid)).filter(Targets.type == obstype).order_by(Targets.name) tobs = [] tname = '' FlagFilterClear = True for target,program in targets: p = Position.fromRaDec(target.targetRa,target.targetDec) ra = p.ra.HMS dec = p.dec.DMS # # Write Fixed.txt # objname = '%12s'%(target.name).replace(' ','_') objname = objname.replace(' ','_') fp1.write('%1s %s %02.0f %02.0f %05.2f %+03.0f %02.0f %04.1f %04.1f\n'%( target.type, objname, ra[1], ra[2], ra[3], dec[0]*dec[1], dec[2], dec[3],target.targetMag)) # # Write stg file with observation requests # config['name'] = objname config['user'] = self.stdUser filterExpt = self.stdExpTime if target.type == self.sciFlag: config['user'] = self.sciUser filterExpt = self.sciExpTime config['time'] = '' dt = np.max(filterExpt)*self.nfilters/60./60./24. if target.type ==self.stdFlag: FlagFilterClear = True tname = target.name tstart = datetimeFromJD(program.slewAt + 2400000.5) tend = datetimeFromJD(program.slewAt+dt + 2400000.5) config['time'] = 't>%s t<%s'%(tstart.strftime('%y%m%d-%H:%M'),tend.strftime('%y%m%d-%H:%M')) for i in range(self.nfilters): config['expt'] = filterExpt[i] config['filter'] = self.filters[i] tstart = datetimeFromJD(program.slewAt + 2400000.5) tend = datetimeFromJD(program.slewAt+dt*1.1 + 2400000.5) fp2.write('%(name)12s; %(user)s %(nimages)ii exp=%(expt).2f opt filter=%(filter)s %(time)s\n'%config) fp1.close() fp2.close() return 0
def targets(self): ''' After selecting targets, you can generate a list of potential targets to run the scheduler. ''' import subprocess session = Session() request = os.path.join(self.PATH, 'targets/request.stg') fp1 = open(os.path.join(self.PATH, 'targets/Fixed.txt'), 'w') fp2 = open(request, 'w') # Write header fp1.write('''P|Designation | RA | dec |mag. -|------------|hh mm ss.ss|sdd mm ss.s|nn.n ''') config = { 'name': '', 'user': '', 'nimages': 1, 'expt': 0, 'filter': '', 'time': '' } for obstype in [self.stdFlag, self.sciFlag]: targets = session.query(Targets, Program).join( (Program, Targets.id == Program.tid)).filter( Targets.type == obstype).order_by(Targets.name) tobs = [] tname = '' FlagFilterClear = True for target, program in targets: p = Position.fromRaDec(target.targetRa, target.targetDec) ra = p.ra.HMS dec = p.dec.DMS # # Write Fixed.txt # objname = '%12s' % (target.name).replace(' ', '_') objname = objname.replace(' ', '_') fp1.write( '%1s %s %02.0f %02.0f %05.2f %+03.0f %02.0f %04.1f %04.1f\n' % (target.type, objname, ra[1], ra[2], ra[3], dec[0] * dec[1], dec[2], dec[3], target.targetMag)) # # Write stg file with observation requests # config['name'] = objname config['user'] = self.stdUser filterExpt = self.stdExpTime if target.type == self.sciFlag: config['user'] = self.sciUser filterExpt = self.sciExpTime config['time'] = '' dt = np.max(filterExpt) * self.nfilters / 60. / 60. / 24. if target.type == self.stdFlag: FlagFilterClear = True tname = target.name tstart = datetimeFromJD(program.slewAt + 2400000.5) tend = datetimeFromJD(program.slewAt + dt + 2400000.5) config['time'] = 't>%s t<%s' % (tstart.strftime( '%y%m%d-%H:%M'), tend.strftime('%y%m%d-%H:%M')) for i in range(self.nfilters): config['expt'] = filterExpt[i] config['filter'] = self.filters[i] tstart = datetimeFromJD(program.slewAt + 2400000.5) tend = datetimeFromJD(program.slewAt + dt * 1.1 + 2400000.5) fp2.write( '%(name)12s; %(user)s %(nimages)ii exp=%(expt).2f opt filter=%(filter)s %(time)s\n' % config) fp1.close() fp2.close() # # Calling targets from TAO to generate targets list. # fp1 = open(os.path.join(self.PATH, 'targets/targets.log'), 'w') bin = os.path.expanduser(os.path.join(self.PATH, 'targets/targets')) runTargets = subprocess.Popen([bin, '-s', request], stdout=fp1, stderr=fp1) runTargets.wait() fp1.close() return 0
def selectStandardTargets(self,flag,nstars=3,nairmass=3): ''' Based on configuration parameters, select 'nstars' standard stars to run scheduler on a specified Julian Day. Ideally you will select standard stars before your science targets so not to have a full queue. Usually standard stars are observed more than once a night at different airmasses. The user can control this parameter with nairmass and the script will try to take care of the rest. ''' session = Session() # query project information projQuery = session.query(Projects).filter(Projects.flag == flag) totobstime = 0. # Calculate total observation time for block in projQuery: totobstime += block.exptime totobstime /= 86400.0 # First of all, standard stars can be observed multiple times in sucessive nights. I will mark all # stars as unscheduled. targets = session.query(Targets).filter(Targets.scheduled == True).filter(Targets.type == flag) for target in targets: target.scheduled = False session.commit() # [To be done] Reject objects that are close to the moon # [To be done] Apply all sorts of rejections # Selecting standard stars is not only searching for the higher in that time but select stars than can be observed at 3 # or more (nairmass) different airmasses. It is also important to select stars with different colors (but this will be # taken care in the future). if nairmass*nstars > len(self.obsTimeBins): self.log.warning('Requesting more stars/observations than it will be possible to schedule. Decreasing number of requests to fit in the night.') nstars = len(self.obsTimeBins)/nairmass # Build a grid of desired times for higher airmass observation of each standard star. stdObsTimeBin = np.arange(10,len(self.obsTimeBins)-10,(len(self.obsTimeBins)-10)/nstars) obsStandars = np.zeros(nstars) print stdObsTimeBin # selecting the closest bin without observation stdObsTimeBin,status = self.findSuitableTimeBin(stdObsTimeBin) if status != 0: raise Exception('Could not find suitable time to start observations! Try cleaning queue.') print stdObsTimeBin site = Site() calclst = lambda time: np.sum(np.array([float(tt) / 60.**i for i,tt in enumerate(str(site._getEphem(datetimeFromJD(time)).sidereal_time()).split(':'))])) nightlst = np.array([calclst(obstime) for obstime in self.obsTimeBins]) for i,tbin in enumerate(stdObsTimeBin): # selecting the closest bin without observation closestcleanbin = tbin while self.obsTimeMask[closestcleanbin] > 0.0: closestcleanbin += 1 if i+1 < len(stdObsTimeBin): if closestcleanbin > stdObsTimeBin[i+1]: raise Exception('Could not find suitable place to start observations of standard star. Try cleaning queue.') time = self.obsTimeBins[closestcleanbin] # 1 - Select objects from database that where not scheduled yet (standard stars may be repited) # that fits our observing night #targetSched = False # Will try until a good match is obtained #while( not targetSched ): targets = session.query(Targets).filter(Targets.scheduled == 0).filter(Targets.type == flag) if len(targets[:]) > 0: #ephem = site._getEphem(datetimeFromJD(time)) lst = calclst(time) #np.sum(np.array([float(tt) / 60.**i for i,tt in enumerate(str(ephem.sidereal_time()).split(':'))])) sitelat = np.sum(np.array([float(tt) / 60.**i for i,tt in enumerate(str(site['latitude']).split(':'))])) alt = np.array([_skysub.altit(target.targetDec,lst - target.targetRa,sitelat)[0] for target in targets]) stg = alt.argmax() print('Selecting %s'%(targets[stg])) # Marking target as schedule tst = session.query(Targets).filter(Targets.id == targets[stg].id) # Build airmass table for object objsecz = np.array([_skysub.true_airmass(_skysub.secant_z(_skysub.altit(targets[stg].targetDec,nlst - targets[stg].targetRa,sitelat)[0])) for nlst in nightlst]) # Build desired airmass table #obsairmass = np.linspace(_skysub.true_airmass(_skysub.secant_z(alt[stg])),projQuery[0].maxairmass,nairmass) obsairmass = np.logspace(np.log10(np.min(objsecz[objsecz > 0])),np.log10(projQuery[0].maxairmass),nairmass) np.savetxt('airmass_%04i.dat'%(stg),X=zip(self.obsTimeBins,objsecz)) # Build mask with scheduled airmasses #mask = np.zeros(len(objsecz),dtype=bool) == 1 pltobstime,pltobsairmass = np.array([]),np.array([]) # Try scheduling observations on all airmasses for airmass in obsairmass: # Get times where the object is close to the desired airmass and there are no observations scheduled timeobsmask = np.bitwise_and(self.obsTimeMask < 1.0,np.abs(objsecz - airmass) < self.tolairmass) # Check that there are times available if not timeobsmask.any(): #raise Exception('No time available for scheduling observations of standard star %s at airmass %.3f'%(targets[stg],airmass)) self.log.warning('No time available for scheduling observations of standard star %s at airmass %.3f'%(targets[stg],airmass)) # Start trying to schedule observations indexes = np.arange(len(self.obsTimeMask))[timeobsmask] #np.bitwise_and(self.obsTimeMask, timeobsmask) obsSched = False for index in indexes: print('[%.3f] - Time bin available for observation of standard star at airmass %.3f'%(self.obsTimeBins[index], airmass)) print '- Require %i extra time bins'%(totobstime/self.tbin) if (self.obsTimeMask[index:index+totobstime/self.tbin] < 1.0).all(): print 'Observation fit in this block.' self.obsTimeMask[index:index+totobstime/self.tbin] = 1.0 self.log.info('Requesting observations of %s @airmass=%4.2f @mjd=%.3f...'%(target.name,airmass,self.obsTimeBins[index]-2400000.5)) pltobstime = np.append(pltobstime,self.obsTimeBins[index:index+totobstime/self.tbin]) pltobsairmass = np.append(pltobsairmass, objsecz[index:index+totobstime/self.tbin]) #for nblock,ii in enumerate(range(index,int(index+totobstime/self.tbin),1)): self.addObservation(targets[stg],self.obsTimeBins[index],projQuery) break np.savetxt('obsairmass_%04i.dat'%stg,X = zip(pltobstime,pltobsairmass)) #self.obsTimeMask[index] = 1.0 #for iobsbins in range(index+1,index+int(totobstime/self.tbin)): #print '[%i] - require extra time bin'%(iobsbins) #if self.obsTimeMask[iobsbins] < 1.0: # self.obsTimeMask[iobsbins] = 1.0 #else: # raise Exception('Time bin [%i/%i] not available for observation of standard star at airmass %.3f'%(iobsbins,len(self.obsTimeMask),airmass)) #else: #raise Exception('Time bin not available for observation of standard star at airmass %.3f'%(airmass)) for t in tst: t.scheduled = True session.commit() obsStandars[i] = t.id else: self.log.warning('No suitable standard star for jd:%.3f in database...'%(time)) return 0 return 0 if len(obsStandars[obsStandars >= 0]) < nstars: self.log.warning('Could not find %i suitable standard stars in catalog. Only %i where found.'%(nstars,len(obsStandars[obsStandars >= 0]))) obsStandars = np.zeros(len(self.obsTimeBins))-1 # first selection of observable standards for tbin,time in enumerate(self.obsTimeBins): if self.obsTimeMask[tbin] < 1.0: # 1 - Select objects from database that where not scheduled yet (standard stars may be repited) # that fits our observing night targets = session.query(Targets).filter(Targets.scheduled == 0).filter(Targets.type == flag) if len(targets[:]) > 0: ephem = site._getEphem(datetimeFromJD(time)) lst = np.sum(np.array([float(tt) / 60.**i for i,tt in enumerate(str(ephem.sidereal_time()).split(':'))])) sitelat = np.sum(np.array([float(tt) / 60.**i for i,tt in enumerate(str(site['latitude']).split(':'))])) secz = np.array([_skysub.secant_z(_skysub.altit(target.targetDec,lst - target.targetRa,sitelat)[0]) for target in targets]) stg = secz.argmax() self.log.info('Selecting %s'%(targets[stg])) # Marking target as schedule tst = session.query(Targets).filter(Targets.id == targets[stg].id) for t in tst: t.scheduled = True session.commit() obsStandars[tbin] = t.id else: print('No suitable target for jd:%.3f in database...'%(time)) break else: self.log.info('Bin already filled up with observations. Skipping...') if len(obsStandars[obsStandars >= 0]) < nstars: self.log.warning('Could not find %i suitable standard stars in catalog. Only %i where found.'%(nstars,len(obsStandars[obsStandars >= 0]))) # # Unmarking potential targets as scheduled # for id in obsStandars[obsStandars >= 0]: target = session.query(Targets).filter(Targets.id == id) for t in target: t.scheduled = False session.commit() tbin+=1 # # Preparing a grid of altitudes for each target for each observing window # amGrid = np.zeros(len(obsStandars)*len(obsStandars)).reshape(len(obsStandars),len(obsStandars)) for i in np.arange(len(obsStandars))[obsStandars >= 0]: target = session.query(Targets).filter(Targets.id == obsStandars[i])[0] for j in range(len(obsStandars)): lst = _skysub.lst(self.obsTimeBins[j],self.sitelong) amGrid[i][j] = _skysub.true_airmass(_skysub.secant_z(_skysub.altit(target.targetDec,lst - target.targetRa,self.sitelat)[0])) if amGrid[i][j] < 0: amGrid [i][j] = 99. # # Build a grid mask that specifies the position in time each target should be observed. This means that, when # selecting a single target we ocuppy more than one, non consecutive, position in the night. This grid shows where are these # positions. # obsMask = np.zeros(len(obsStandars)*len(obsStandars),dtype=np.bool).reshape(len(obsStandars),len(obsStandars)) for i in np.arange(len(obsStandars))[obsStandars >= 0]: amObs = np.linspace(amGrid[i].min(),self.stdMaxAirmass,nairmass) # requested aimasses dam = np.mean(np.abs(amGrid[i][amGrid[i]<self.stdMaxAirmass][1:] - amGrid[i][amGrid[i]<self.stdMaxAirmass][:-1])) # how much airmass changes in average for j,am in enumerate(amObs): # Mark positions where target is at specified airmass if j == 0: obsMask[i] = np.bitwise_or(obsMask[i],amGrid[i] == am) else: obsMask[i] = np.bitwise_or(obsMask[i],np.bitwise_and(amGrid[i]>am-dam,amGrid[i]<am+dam)) #print amGrid[i][np.where(obsMask[i])] # # Now it is time to actually select the targets. It will start with the first target and then try the others # until it find enough standard stars, as specified by the user. # # Para cada bin em tempo, varro o bin em massa de ar por coisas observaveis. Se acho um, vejo se posso agendar # os outros bins. Se sim, marco o alvo para observacao, se nao, passo para o proximo. Repito ate completar a # lista de alvos # obsMaskTimeGrid = np.zeros(len(obsStandars),dtype=np.bool) nrequests = 0 reqId = np.zeros(nstars,dtype=np.int)-1 for tbin,time in enumerate(self.obsTimeBins[:-1]): # Evaluates if time slots are all available. If yes, mark orbservation and ocuppy slots. if ( (not obsMaskTimeGrid[obsMask[tbin]].any()) and (len(amGrid[tbin][obsMask[tbin]])>=nairmass) ): obsMaskTimeGrid = np.bitwise_or(obsMaskTimeGrid,obsMask[tbin]) reqId[nrequests] = tbin nrequests += 1 if nrequests >= nstars: break # Finally, requesting observations for id in reqId[reqId >= 0]: target = session.query(Targets).filter(Targets.id == obsStandars[id])[0] secz = amGrid[id][obsMask[id]] seczreq = np.zeros(nairmass,dtype=np.bool) amObs = np.linspace(amGrid[id].min(),self.stdMaxAirmass,nairmass) # requested aimasses for i,obstime in enumerate(self.obsTimeBins[obsMask[id]]): sindex = np.abs(amObs-secz[i]).argmin() if not seczreq[sindex]: self.log.info('Requesting observations of %s @airmass=%4.2f @mjd=%.3f...'%(target.name,secz[i],obstime-2400000.5)) seczreq[sindex] = True target.scheduled = True session.commit() self.addObservation(target,obstime) self.obsTimeMask[obsMask[id]] = 1.0 #print self.obsTimeBins[obsMask[id]] #print #print i return 0 #targets