def expscript_for_json(j, status=None): ss = [] if 'approx_datetime' in j: # Expected start time of this script, in "date -u +%s" units -- seconds since unixepoch = 1970-01-01 00:00:00 unixepoch = 25567.5 tj = ephem.Date(str(j['approx_datetime'])) ss = ['# Exposure scheduled for: %s UT\n' % j['approx_datetime'], 'dt=$(($(date -u +%%s) - %i))' % (int((tj - unixepoch) * 86400))] #ss.append('echo DT: $dt\n') ss.append('if [ $dt -gt 3600 ]; then\n' + ' echo; echo "WARNING: This exposure is happening more than an hour late!";\n' + ' echo "Scheduled time: %s UT";\n' % j['approx_datetime'] + ' echo; tput bel; sleep 0.25; tput bel; sleep 0.25; tput bel;\n' + 'fi\n' + 'if [ $dt -lt -3600 ]; then\n' + ' echo; echo "WARNING: This exposure is happening more than an hour early!";\n' + ' echo "Scheduled time: %s UT";\n' % j['approx_datetime'] + ' echo; tput bel; sleep 0.25; tput bel; sleep 0.25; tput bel;\n' + 'fi\n') #ADM force exit if observation is more than 4 hours late ss.append('if [ $dt -gt 14400 ]; then\n' + ' echo; echo "ERROR: This exposure is happening more than 4 hours late!";\n' + ' echo "Scheduled time: %s UT";\n' % j['approx_datetime'] + ' echo "YOU SHOULD RERUN mosbot.py TO CREATE A NEW tonight.sh FILE!";\n' + ' touch quit\n' + ' exit 1\n' + 'fi\n') ra = j['RA'] dec = j['dec'] ss.append(jnox_moveto(ra, dec)) # exposure time et = (j['expTime']) # filter filter_name = str(j['filter']) tilename = str(j['object']) if status is None: ra = ra2hms(ra) dec = dec2dms(dec) status = "Tile %s, RA %s, Dec %s" % (tilename, ra, dec) ss.append(jnox_exposure(et, filter_name, tilename, status)) return '\n'.join(ss) + '\n'
def expscript_for_json(j, status=None): ss = ('# Exposure scheduled for: %s UT\n' % j['approx_datetime']) # Expected start time of this script, in "date -u +%s" units -- seconds since unixepoch = 1970-01-01 00:00:00 unixepoch = 25567.5 tj = ephem.Date(str(j['approx_datetime'])) ss = ['dt=$(($(date -u +%%s) - %i))' % (int((tj - unixepoch) * 86400))] #ss.append('echo DT: $dt\n') ss.append('if [ $dt -gt 3600 ]; then\n' + ' echo; echo "WARNING: This exposure is happening more than an hour late!";\n' + ' echo "Scheduled time: %s UT";\n' % j['approx_datetime'] + ' echo; tput bel; sleep 0.25; tput bel; sleep 0.25; tput bel;\n' + 'fi\n' + 'if [ $dt -lt -3600 ]; then\n' + ' echo; echo "WARNING: This exposure is happening more than an hour early!";\n' + ' echo "Scheduled time: %s UT";\n' % j['approx_datetime'] + ' echo; tput bel; sleep 0.25; tput bel; sleep 0.25; tput bel;\n' + 'fi\n') ra = j['RA'] dec = j['dec'] ss.append(jnox_moveto(ra, dec)) # exposure time et = (j['expTime']) # filter filter_name = str(j['filter']) tilename = str(j['object']) if status is None: ra = ra2hms(ra) dec = dec2dms(dec) status = "Tile %s, RA %s, Dec %s" % (tilename, ra, dec) ss.append(jnox_exposure(et, filter_name, tilename, status)) return '\n'.join(ss) + '\n'
def update_for_image(self, M, forcepass=None, now=None): # M: measurements for the image that's we're going to use to update # exposure times. # now: for testing purposes only; defaults to ephem.now() # filename patterns for the exposure and slew scripts expscriptpat = os.path.join(self.scriptdir, self.expscriptpattern) slewscriptpat = os.path.join(self.scriptdir, self.slewscriptpattern) if M is not None: # Choose the pass, based on... trans = M['transparency'] seeing = M['seeing'] skybright = M['skybright'] # eg, nominal = 20, sky = 19, brighter is 1 mag brighter than nom. meas_band = M['band'] nomsky = self.nom.sky(meas_band) brighter = nomsky - skybright print('Transparency: %6.02f' % trans) print('Seeing : %6.02f' % seeing) print('Sky : %6.02f' % skybright) print('Nominal sky : %6.02f' % nomsky) print('Sky over nom: %6.02f (positive means brighter than nominal)' % brighter) nextpass = choose_pass(trans, seeing, skybright, nomsky, forcedir=self.scriptdir) elif forcepass is not None: nextpass = forcepass else: nextpass = self.opt.passnum print() print('Selected pass:'******'%s: reading sequence number from %s' % (str(ephem.now()), self.seqnumpath)) f = open(self.seqnumpath, 'r') s = f.read() f.close() seqnum = int(s) else: # Tonight.sh may not have started yet -- pretend that # we're currently taking seqnum=0, so the next one to be # planned is seqnum=1. seqnum = 0 print('%s: sequence number: %i' % (str(now), seqnum)) # 'iplan': the tile index we will use for exposure # 'seqnum' iplan = None if self.opt.sequence: iplan = seqnum + self.sequence_offset # Check whether the next tile will be observed more than an hour # later than its scheduled time -- if so, skip a block of tiles. if iplan < len(J): j = J[iplan] tstart = ephem.Date(str(j['approx_datetime'])) if now > (tstart + 3600./86400.): print('The next tile will be observed more than an hour late. Skipping a block of observations...') for i,j in enumerate(J[iplan:]): tstart = ephem.Date(str(j['approx_datetime'])) if tstart <= now: continue print('Found tile', j['object'], 'which starts at', str(tstart)) print('Skipping', i, 'tiles') self.sequence_offset += i iplan += i break elif self.opt.cut_before_now: # The usual case -- find the next tile scheduled for after now. for i,j in enumerate(J): tstart = ephem.Date(str(j['approx_datetime'])) if tstart <= now: continue print('Found tile', j['object'], 'which starts at', str(tstart)) iplan = i break if iplan is None: print('Could not find a JSON observation in pass', nextpass, 'with approx_datetime after now =', str(now), '-- latest one', str(tstart)) return False else: # For when we want to observe every tile in the plan: # 'seqnum' is the exposure currently running; # seqnum is 1-indexed, so that's the index we want for iplan. iplan = seqnum # Set observing conditions for computing exposure time self.obs.date = now # Planned exposures: P = fits_table() P.type = [] P.tilename = [] P.filter = [] P.exptime = [] P.ra = [] P.dec = [] P.passnumber = [] lasttile = None lastdate = None iahead = 0 for ii,jplan in enumerate(J[iplan:]): from astrometry.util.starutil_numpy import degrees_between if iahead >= self.Nahead: break tilename = str(jplan['object']) nextseq = seqnum + 1 + iahead if self.n_exposures > 0 and nextseq > self.n_exposures: print('Planned tile is beyond the exposure number in ', 'tonight.sh -- RESTART MOSBOT') return False print('Considering planning tile %s for exp %i'%(tilename,nextseq)) # Check all planned tiles before this one for a duplicate tile. dup = False for s in range(nextseq-1, 0, -1): if tilename == self.planned_tiles[s]: dup = True print('Wanted to plan tile %s (pass %i element %i) for exp %i' % (tilename, nextpass, iplan+ii, nextseq), 'but it was already planned for exp %i' % s) break if dup: continue self.planned_tiles[nextseq] = tilename iahead += 1 # Find this tile in the tiles table. tile = get_tile_from_name(tilename, self.tiles) ebv = tile.ebv_med nextband = str(jplan['filter'])[0] print('Selected tile:', tile.tileid, nextband) rastr = ra2hms (jplan['RA' ]) decstr = dec2dms(jplan['dec']) ephemstr = str('%s,f,%s,%s,20' % (tilename, rastr, decstr)) etile = ephem.readdb(ephemstr) etile.compute(self.obs) airmass = get_airmass(float(etile.alt)) print('Airmass of planned tile:', airmass) print('Time of observation:', self.obs.date) # HACK -- try setting the date to the planned datetime from the plan file. #self.obs.date = ephem.Date(str(jplan['approx_datetime'])) lst = np.rad2deg(float(self.obs.sidereal_time())) ha = lst - jplan['RA'] if ha < -180: ha += 360. print('LST:', lst, 'Tile RA:', jplan['RA'], 'Dec', jplan['dec']) print('HA of planned tile:', ha) readout_during_move = True # Check for large slew slew = 0. if lasttile is None: # Look up the tile we previously planned prevname = self.planned_tiles.get(nextseq - 1, None) Jall = self.J1 + self.J2 + self.J3 I, = np.nonzero([str(j['object']) == prevname for j in Jall]) if len(I) == 0: print('Could not find previous tile "%s"' % prevname) else: jprev = Jall[I[0]] lasttile = jprev lastdate = ephem.Date(str(jprev['approx_datetime'])) if lasttile is not None: slew = degrees_between(lasttile['RA'], lasttile['dec'], jplan['RA'], jplan['dec']) print('Slew: %.1f degrees' % slew) # Compute HA for previous tile thedate = self.obs.date self.obs.date = lastdate last_lst = np.rad2deg(float(self.obs.sidereal_time())) self.obs.date = thedate last_ha = last_lst - lasttile['RA'] if last_ha < -180: last_ha += 360. print('Last tile LST:', last_lst, 'Tile RA:', lasttile['RA'], 'Dec', lasttile['dec']) print('Last HA:', last_ha) fuzz = 3. maybe_flip = maybe_ha_flip(ha, last_ha, fuzz) print('Over-the-pole flip possible:', maybe_flip) if maybe_flip: readout_during_move = False if iahead == 1 and slew > 10.: # Beep the terminal -- OA has to okay it (?) print() print() print('Large slew from current exposure to next: ' + 'RA,Dec %.1f, %.1f to %.1f, %.1f ==> %.1f degrees' % (jprev['RA'], jprev['dec'], jplan['RA'], jplan['dec'], slew)) print() print() os.system('tput bel; sleep 0.2; ' * 5) if slew > 35: # We risk a timeout -- modify the "slewread" # script we write out so that we read out before # commanding the telescope to move. print('Large slew from current exposure to next: reading out before moving the telescope') readout_during_move = False lasttile = jplan lastdate = self.obs.date if M is not None: if M['band'] == nextband: nextsky = skybright else: # Guess that the sky is as much brighter than canonical # in the next band as it is in this one! nextsky = ((skybright - nomsky) + self.nom.sky(nextband)) fid = self.nom.fiducial_exptime(nextband) expfactor = exposure_factor(fid, self.nom, airmass, ebv, seeing, nextsky, trans) print('Exposure factor:', expfactor) expfactor_orig = expfactor # Adjust for previous exposures? if self.opt.adjust: debug=True adjfactor,others = self.adjust_for_previous( tile, nextband, fid, debug=debug, get_others=True) # Don't adjust exposure times down, only up. adjfactor = max(adjfactor, 1.0) expfactor *= adjfactor else: adjfactor = 0. others = [] exptime = expfactor * fid.exptime ### HACK -- safety factor! print('Exposure time:', exptime) exptime *= 1.1 print('Exposure time with safety factor:', exptime) exptime_unclipped = exptime exptime = np.clip(exptime, fid.exptime_min, fid.exptime_max) print('Clipped exptime', exptime) exptime_satclipped = 0. if nextband == 'z': # Compute cap on exposure time to avoid saturation / # loss of dynamic range. t_sat = self.nom.saturation_time(nextband, nextsky) if exptime > t_sat: exptime_satclipped = t_sat exptime = t_sat print('Reduced exposure time to avoid z-band saturation:', '%.1f' % exptime) exptime = int(np.ceil(exptime)) print('Changing exptime from', jplan['expTime'], 'to', exptime) jplan['expTime'] = exptime # Update the computed exposure-time database. if self.opt.db: try: # NOTE, these kwargs MUST match the names in models.py self.update_exptime_db( nextseq, others, tileid=tile.tileid, passnumber=nextpass, band=nextband, airmass=airmass, ebv=ebv, meas_band=meas_band, zeropoint=M['zp'], transparency=trans, seeing=seeing, sky=skybright, expfactor=expfactor_orig, adjfactor=adjfactor, exptime_unclipped=exptime_unclipped, exptime_satclipped=exptime_satclipped, exptime=exptime) except: print('Failed to update computed-exptime database.') import traceback traceback.print_exc() # carry on print('Predict tile will be observed at', str(self.obs.date), 'vs approx_datetime', jplan.get('approx_datetime',None)) status = ('Exp %i: Tile %s, Pass %i, RA %s, Dec %s' % (nextseq, tilename, nextpass, rastr, decstr)) print('%s: updating exposure %i to tile %s' % (str(ephem.now()), nextseq, tilename)) expscriptfn = expscriptpat % (nextseq) exptmpfn = expscriptfn + '.tmp' f = open(exptmpfn, 'w') f.write(('# Exp %i Tile: %s, set at Seq %i, %s\n' % (nextseq, tilename, seqnum, str(ephem.now()))) + expscript_for_json(jplan, status=status)) f.close() slewscriptfn = slewscriptpat % (nextseq) slewtmpfn = slewscriptfn + '.tmp' f = open(slewtmpfn, 'w') f.write(slewscript_for_json(jplan, readout_during_move=readout_during_move)) f.close() os.rename(exptmpfn, expscriptfn) print('Wrote', expscriptfn) os.rename(slewtmpfn, slewscriptfn) print('Wrote', slewscriptfn) exptime = jplan['expTime'] self.obs.date += (exptime + self.nom.overhead) / 86400. print('%s: updated exposure %i to tile %s' % (str(ephem.now()), nextseq, tilename)) P.tilename.append(tilename) P.filter.append(nextband) P.exptime.append(exptime) P.ra.append(jplan['RA']) P.dec.append(jplan['dec']) P.passnumber.append(nextpass) P.type.append('P') if iahead < self.Nahead: # We ran out of tiles. # Overwrite the default planned exposures with blanks to avoid # running the defaults (eg, at end of night). seqstart = seqnum + 1 + iahead seqend = self.n_exposures print('Overwriting remaining exposure scripts (%i to %i inclusive) with blanks.' % (seqstart, seqend)) for nextseq in range(seqstart, seqend+1): print('Blanking out exposure %i' % nextseq) fn = self.expscriptpattern % nextseq path = os.path.join(self.scriptdir, fn) f = open(path, 'w') f.write('\n') f.close() fn = self.slewscriptpattern % nextseq path = os.path.join(self.scriptdir, fn) f = open(path, 'w') f.write('\n') f.close() for i,J in enumerate([self.J1,self.J2,self.J3]): passnum = i+1 for j in J: tstart = ephem.Date(str(j['approx_datetime'])) if self.opt.cut_before_now and tstart < now: continue P.tilename.append(str(j['object'])) filt = str(j['filter'])[0] P.filter.append(filt) P.exptime.append(j['expTime']) P.ra.append(j['RA']) P.dec.append(j['dec']) P.passnumber.append(passnum) P.type.append('%i' % passnum) P.to_np_arrays() fn = 'mosbot-plan.fits' tmpfn = fn + '.tmp' P.writeto(tmpfn) os.rename(tmpfn, fn) print('Wrote', fn) return True
def write_initial_script(self, J, passnum, exptime, scriptfn, seqnumfn): quitfile = 'quit' # 775 chmod = (stat.S_IXUSR | stat.S_IWUSR | stat.S_IRUSR | stat.S_IXGRP | stat.S_IWGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH) def log(s): datecmd = 'date -u +"%Y-%m-%d %H:%M:%S"' #return 'echo "mosbot $(%s): %s"' % (datecmd, s) return 'echo "$(%s): %s" >> mosbot.log' % (datecmd, s) # Delete 'quit' file if it exists. quitfn = os.path.join(self.scriptdir, quitfile) if os.path.exists(quitfn): print('Removing file', quitfn) os.remove(quitfn) # Write "read.sh" for quitting gracefully without slew path = os.path.join(self.scriptdir, 'read.sh') f = open(path, 'w') f.write(jnox_readout() + '\n' + jnox_end_exposure()) f.close() os.chmod(path, chmod) # Start writing the "tonight.sh" script. script = [] # tonight.sh initial NOCS commands script.append(jnox_preamble(scriptfn)) script.append(log('###############')) script.append(log('Starting script')) script.append(log('###############')) if self.opt.set_filter: # tonight.sh setting the filter once at the start of the night! j = J[0] f = str(j['filter']) script.append(jnox_filter(f)) # Write top-level script and shell scripts for default plan. for i,j in enumerate(J): # The sequence number start at 1 seq = i + 1 # tonight.sh: start exposure script.append('\n### Exposure %i ###\n' % seq) script.append('echo "%i" > %s' % (seq, seqnumfn)) if seq > 1: script.append('# Check for file "%s"; read out and quit if it exists' % quitfile) script.append('if [ -f %s ]; then\n . read.sh; rm %s; exit 0;\nfi' % (quitfile,quitfile)) # tonight.sh: slew to field while reading out previous exposure # Write slewread-##.sh script fn = self.slewscriptpattern % seq path = os.path.join(self.scriptdir, fn) f = open(path, 'w') f.write(slewscript_for_json(j)) f.close() os.chmod(path, chmod) print('Wrote', path) script.append('. %s' % fn) # Another check for 'quit' file; no need to run "read.sh" here. script.append('if [ -f %s ]; then\n rm %s; exit 0;\nfi' % (quitfile,quitfile)) script.append(log('Starting exposure %i' % seq)) expfn = self.expscriptpattern % seq script.append(log('Tile: $(grep "Tile:" %s)' % expfn)) tilename = str(j['object']) self.planned_tiles[seq] = tilename if exptime is not None: j['expTime'] = exptime # Write expose-##.sh default exposure script fn = self.expscriptpattern % seq path = os.path.join(self.scriptdir, fn) f = open(path, 'w') s = ('# Exp %i: Tile: %s, Pass: %i; default\n' % (seq, tilename, passnum)) ra = ra2hms (j['RA' ]) dec = dec2dms(j['dec']) status = ('Exp %i: Tile %s, Pass %i, RA %s, Dec %s' % (seq, tilename, passnum, ra, dec)) s += expscript_for_json(j, status=status) f.write(s) f.close() os.chmod(path, chmod) print('Wrote', path) script.append('. %s' % fn) # Read out the last one! script.append('. read.sh') script = '\n'.join(script) + '\n' f = open(scriptfn, 'w') f.write(script) f.close() os.chmod(scriptfn, chmod) print('Wrote', scriptfn)
def process_file(self, fn): ext = self.opt.ext expscriptpat = os.path.join(self.scriptdir, self.expscriptpattern) slewscriptpat = os.path.join(self.scriptdir, self.slewscriptpattern) print('%s: found new image %s' % (str(ephem.now()), fn)) nopass1path = os.path.join(self.scriptdir, 'nopass1') dopass1 = not os.path.exists(nopass1path) if not dopass1: print('Not considering Pass 1 because file exists:', nopass1path) nopass2path = os.path.join(self.scriptdir, 'nopass2') dopass2 = not os.path.exists(nopass2path) if not dopass2: print('Not considering Pass 2 because file exists:', nopass2path) # Read primary FITS header phdr = fitsio.read_header(fn) expnum = phdr.get('EXPNUM', 0) obstype = phdr.get('OBSTYPE','').strip() print('obstype:', obstype) if obstype in ['zero', 'focus', 'dome flat']: print('Skipping obstype =', obstype) return False elif obstype == '': print('Empty OBSTYPE in header:', fn) return False exptime = phdr.get('EXPTIME') if exptime == 0: print('Exposure time EXPTIME in header =', exptime) return False filt = str(phdr['FILTER']) filt = filt.strip() filt = filt.split()[0] if filt == 'solid': print('Solid (block) filter.') return False # Measure the new image kwa = {} if ext is not None: kwa.update(ext=ext) ps = None M = measure_raw(fn, ps=ps, **kwa) # Sanity checks ok = (M['nmatched'] >= 20) and (M.get('zp',None) is not None) if not ok: print('Failed sanity checks in our measurement of', fn, '-- not updating anything') # FIXME -- we could fall back to pass 3 here. return False # Choose the pass trans = M['transparency'] seeing = M['seeing'] skybright = M['skybright'] # eg, nominal = 20, sky = 19, brighter is 1 mag brighter than nom. nomsky = self.nom.sky(M['band']) brighter = nomsky - skybright print('Transparency: %6.02f' % trans) print('Seeing : %6.02f' % seeing) print('Sky : %6.02f' % skybright) print('Nominal sky : %6.02f' % nomsky) print('Sky over nom: %6.02f (positive means brighter than nom)' % brighter) transcut = 0.9 seeingcut = 1.25 brightcut = 0.25 transok = trans > transcut seeingok = seeing < seeingcut brightok = brighter < brightcut pass1ok = transok and seeingok and brightok pass2ok = transok or seeingok nextpass = 3 if pass1ok and dopass1: nextpass = 1 elif pass2ok and dopass2: nextpass = 2 print('Transparency cut: %s (%6.2f vs %6.2f)' % (('pass' if transok else 'fail'), trans, transcut)) print('Seeing cut: %s (%6.2f vs %6.2f)' % (('pass' if seeingok else 'fail'), seeing, seeingcut)) print('Brightness cut: %s (%6.2f vs %6.2f)' % (('pass' if brightok else 'fail'), skybright, nomsky+brightcut)) print('Pass 1 = transparency AND seeing AND brightness: %s' % pass1ok) if pass1ok and not dopass1: print('Pass 1 forbidden by observer!') print('Pass 2 = transparency OR seeing : %s' % pass2ok) if pass2ok and not dopass2: print('Pass 2 forbidden by observer!') print('Selected pass:'******'UTC now is', str(now)) for i,j in enumerate(J): tstart = ephem.Date(str(j['approx_datetime'])) if tstart > now: print('Found tile', j['object'], 'which starts at', str(tstart)) iplan = i break if iplan is None: print('Could not find a JSON observation in pass', nextpass, 'with approx_datetime after now =', str(now), '-- latest one', str(tstart)) return False # Read the current sequence number print('%s: reading sequence number' % (str(ephem.now()))) f = open(self.seqnumpath, 'r') s = f.read() f.close() seqnum = int(s) print('%s: sequence number: %i' % (str(ephem.now()), seqnum)) # How many exposures ahead should we write? Nahead = 10 # Set observing conditions for computing exposure time self.obs.date = now P = fits_table() P.type = [] P.tilename = [] #P.tileid = [] P.filter = [] P.exptime = [] P.ra = [] P.dec = [] P.passnumber = [] iahead = 0 for ii,jplan in enumerate(J[iplan:]): if iahead >= Nahead: break tilename = str(jplan['object']) nextseq = seqnum + 1 + iahead print('Considering planning tile %s for exp %i' % (tilename, nextseq)) # Check all planned tiles before this one for a duplicate tile. dup = False for s in range(nextseq-1, 0, -1): t = self.planned_tiles[s] if t == tilename: dup = True print('Wanted to plan tile %s (pass %i element %i) for exp %i' % (tilename, nextpass, iplan+ii, nextseq), 'but it was already planned for exp %i' % s) break if dup: continue self.planned_tiles[nextseq] = tilename iahead += 1 # Find this tile in the tiles table. tile = get_tile_from_name(tilename, self.tiles) ebv = tile.ebv_med nextband = str(jplan['filter'])[0] print('Selected tile:', tile.tileid, nextband) rastr = ra2hms (jplan['RA' ]) decstr = dec2dms(jplan['dec']) ephemstr = str('%s,f,%s,%s,20' % (tilename, rastr, decstr)) etile = ephem.readdb(ephemstr) etile.compute(self.obs) airmass = get_airmass(float(etile.alt)) print('Airmass of planned tile:', airmass) if M['band'] == nextband: nextsky = skybright else: # Guess that the sky is as much brighter than canonical # in the next band as it is in this one! nextsky = ((skybright - nomsky) + self.nom.sky(nextband)) fid = self.nom.fiducial_exptime(nextband) expfactor = exposure_factor(fid, self.nom, airmass, ebv, seeing, nextsky, trans) print('Exposure factor:', expfactor) exptime = expfactor * fid.exptime ### HACK -- safety factor! print('Exposure time:', exptime) exptime *= 1.1 exptime = int(np.ceil(exptime)) print('Exposure time with safety factor:', exptime) exptime = np.clip(exptime, fid.exptime_min, fid.exptime_max) print('Clipped exptime', exptime) if nextband == 'z': # Compute cap on exposure time to avoid saturation / # loss of dynamic range. t_sat = self.nom.saturation_time(nextband, nextsky) if exptime > t_sat: exptime = t_sat print('Reduced exposure time to avoid z-band saturation: %.1f' % exptime) exptime = int(exptime) print('Changing exptime from', jplan['expTime'], 'to', exptime) jplan['expTime'] = exptime status = ('Exp %i: Tile %s, Pass %i, RA %s, Dec %s' % (nextseq, tilename, nextpass, rastr, decstr)) print('%s: updating exposure %i to tile %s' % (str(ephem.now()), nextseq, tilename)) expscriptfn = expscriptpat % (nextseq) exptmpfn = expscriptfn + '.tmp' f = open(exptmpfn, 'w') f.write(('# Exp %i Tile: %s, set at Seq %i, %s\n' % (nextseq, tilename, seqnum, str(ephem.now()))) + expscript_for_json(jplan, status=status)) f.close() slewscriptfn = slewscriptpat % (nextseq) slewtmpfn = slewscriptfn + '.tmp' f = open(slewtmpfn, 'w') f.write(slewscript_for_json(jplan)) f.close() os.rename(exptmpfn, expscriptfn) print('Wrote', expscriptfn) os.rename(slewtmpfn, slewscriptfn) print('Wrote', slewscriptfn) self.obs.date += (exptime + self.nom.overhead) / 86400. print('%s: updated exposure %i to tile %s' % (str(ephem.now()), nextseq, tilename)) P.tilename.append(tilename) #P.tileid.append(tile.tileid) P.filter.append(nextband) P.exptime.append(exptime) P.ra.append(jplan['RA']) P.dec.append(jplan['dec']) P.passnumber.append(nextpass) P.type.append('P') for i,J in enumerate([self.J1,self.J2,self.J3]): passnum = i+1 for j in J: tstart = ephem.Date(str(j['approx_datetime'])) if tstart < now: continue P.tilename.append(str(j['object'])) filt = str(j['filter'])[0] P.filter.append(filt) P.exptime.append(j['expTime']) P.ra.append(j['RA']) P.dec.append(j['dec']) P.passnumber.append(passnum) P.type.append('%i' % passnum) P.to_np_arrays() fn = 'mosbot-plan.fits' tmpfn = fn + '.tmp' P.writeto(tmpfn) os.rename(tmpfn, fn) print('Wrote', fn) return True
def write_initial_script(self, J, passnum, exptime, scriptfn, seqnumfn): quitfile = 'quit' # 775 chmod = (stat.S_IXUSR | stat.S_IWUSR | stat.S_IRUSR | stat.S_IXGRP | stat.S_IWGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH) def log(s): datecmd = 'date -u +"%Y-%m-%d %H:%M:%S"' #return 'echo "mosbot $(%s): %s"' % (datecmd, s) return 'echo "$(%s): %s" >> mosbot.log' % (datecmd, s) # Write "read.sh" for quitting gracefully without slew path = os.path.join(self.scriptdir, 'read.sh') f = open(path, 'w') f.write(jnox_readout() + '\n' + jnox_end_exposure()) f.close() os.chmod(path, chmod) script = [] script.append(jnox_preamble(scriptfn)) script.append(log('###############')) script.append(log('Starting script')) script.append(log('###############')) j = J[0] f = str(j['filter']) script.append(jnox_filter(f)) # Write top-level script and shell scripts for default plan. for i,j in enumerate(J): # We make the sequence numbers start at 1, just to make things # difficult for ourselves. seq = i + 1 if seq > 1: script.append('# Check for file "%s"; read out and quit if it exists' % quitfile) script.append('if [ -f %s ]; then\n . read.sh; rm %s; exit 0;\nfi' % (quitfile,quitfile)) # Write slewread-##.sh script fn = self.slewscriptpattern % seq path = os.path.join(self.scriptdir, fn) f = open(path, 'w') f.write(slewscript_for_json(j)) f.close() os.chmod(path, chmod) print('Wrote', path) script.append('. %s' % fn) script.append('\n### Exposure %i ###\n' % seq) script.append('echo "%i" > %s' % (seq, seqnumfn)) script.append(log('Starting exposure %i' % seq)) expfn = self.expscriptpattern % seq script.append(log('Tile: $(grep "Tile:" %s)' % expfn)) tilename = str(j['object']) self.planned_tiles[seq] = tilename if exptime is not None: j['expTime'] = exptime # Write expose-##.sh fn = self.expscriptpattern % seq path = os.path.join(self.scriptdir, fn) f = open(path, 'w') s = ('# Exp %i: Tile: %s, Pass: %i; default\n' % (seq, tilename, passnum)) ra = ra2hms (j['RA' ]) dec = dec2dms(j['dec']) status = ('Exp %i: Tile %s, Pass %i, RA %s, Dec %s' % (seq, tilename, passnum, ra, dec)) s += expscript_for_json(j, status=status) f.write(s) f.close() os.chmod(path, chmod) print('Wrote', path) script.append('. %s' % fn) # Read out the last one! script.append('. read.sh') script = '\n'.join(script) + '\n' f = open(scriptfn, 'w') f.write(script) f.close() os.chmod(scriptfn, chmod) print('Wrote', scriptfn)
obs = ephem_observer() J = json.loads(open('pass1.json').read()) print(len(J), 'tiles in pass 1 plan') #A = json.loads(open('pass1_byhand_v2.json').read()) nexti = 0 newJ = [] for j in J: print() obs.date = ephem.Date(str(j['approx_datetime'])) rastr = ra2hms (j['RA' ]) decstr = dec2dms(j['dec']) ephemstr = str('%s,f,%s,%s,20' % (j['object'], rastr, decstr)) #print(ephemstr) etile = ephem.readdb(ephemstr) etile.compute(obs) print('Tile', j['object'], 'at', j['approx_datetime'], 'RA,Dec', j['RA'],j['dec']) airmass = get_airmass(float(etile.alt)) print('Airmass:', airmass) lst = obs.sidereal_time() print('LST', lst) lsthr = np.rad2deg(float(obs.sidereal_time())) / 15. # print('lst', lst)