def __init__(self): self.ims = ImagesQuery() self.disc = DiscoveriesQuery() self.bk = BlockQuery() # pixel scale is symmetric, 0.1850 arcsec/pixel. Dectector is [1:23219,1:19354] pixels. self.field_area = ((0.185 * 23219) / 3600.) * ( (0.185 * 19354) / 3600.) # sq. deg
class SurveyQuery(object): def __init__(self): self.ims = ImagesQuery() self.bk = BlockQuery() # pixel scale is symmetric, 0.1850 arcsec/pixel. Dectector is [1:23219,1:19354] pixels. self.field_area = ((0.184 * 23219) / 3600.) * ( (0.184 * 19354) / 3600.) # sq. deg def fields_observed(self): fields = self.ims.what_fields_have_any_observations() # don't include the wallpaper in the overall count tno_fields = [f for f in fields if not f['fieldId'].__contains__('WP')] num_fields = len(tno_fields) sqdeg_observed = num_fields * self.field_area retval = (sqdeg_observed, num_fields) return retval def fields_processed(self): retval = 3 * 21 * self.field_area # 3 blocks processed at 04-02-2015 return retval def most_recent_observation(self): it = self.ims.images ss = sa.select([it.c.obs_end], order_by=it.c.obs_end) dates = [n[0] for n in self.ims.conn.execute(ss)] return dates[-1] def next_moondark(self): # this is producing an off by one error: fix! mn = ephem.Moon() mp = [] for n in range(0, 29 * 4): mn.compute(ephem.now() + (n / 4.)) mp.append((ephem.now() + (n / 4.), mn.moon_phase)) next_new_moon = ephem.Date(min(mp, key=lambda x: x[1])[0]).datetime() # next_new_moon = pytz.utc.localize(next_new_moon) # it's calculated in UTC # hst = pytz.timezone('HST') retval = next_new_moon # .astimezone(hst) return retval def next_observing_window(self): # we observe if the near-new moon is down, or if the moon is up # but we are within 3 days of new moon. next_nm = self.next_moondark() next_period = (next_nm - datetime.timedelta(3), next_nm + datetime.timedelta(3)) if next_period[0] < datetime.datetime.now() < next_period[1]: retval = 'tonight (hopefully).' else: retval = 'in no more than ' + str( (next_period[0] - datetime.datetime.now()).days) + ' days.' return retval def megacam_schedule(self): # tuples bracket the ends of date ranges that MegaCam is on the telescope schedule = [ (datetime.datetime(2015, 7, 8), datetime.datetime(2015, 7, 21)), ] return schedule def nearest_megacam_run(self): now = datetime.datetime.now() schedule = self.megacam_schedule() nearest_run = [] for run in schedule: if (run[0] - now > datetime.timedelta(0)) or ( run[1] - now > datetime.timedelta(0)): nearest_run = run break if nearest_run[0] <= now <= nearest_run[1]: retval = 'now.' else: if (nearest_run[0] - now).days > 0: retval = "in " + str((nearest_run[0] - now).days) + " days." else: hrs = (nearest_run[0] - now).seconds / 3600. retval = "in " + '%2.1f' % hrs + " hours." return retval def num_discoveries(self): # Characterized discoveries only. status = self.bk.all_blocks()['status'] return sum([ int(n[1]) for n in list(status.values()) if (n is not None and n[1].isdigit()) ]) def mpc_informed(self): # status = self.bk.all_blocks()['blocks'] # Implement more comprehensive info later # return sum([n[1] for n in status.values() if n[1].isdigit()]) return 0
def __init__(self): self.bk = ImagesQuery()
class BlockQuery(object): def __init__(self): self.bk = ImagesQuery() def all_blocks(self): retval = {} bks = retval.get('blocks', []) status = {'E':['complete', '52', '24.05'], 'O':['blinking', '', ''], '13BL':['triplets observed!', '', ''], '13BH':['partial observations','', '']} for block in OSSOS_BLOCKS: bk = [] bk.append(block) bk.append(self.num_block_images(block)) # no. observations if block in status: for val in status[block]: bk.append(val) elif block.__contains__('WP'): # Wallpaper can't have discoveries or efficiency for k in range(1,4): bk.append('-') bks.append(bk) retval['blocks'] = bks return retval def fields_in_block(self, blockID): # REWRITE THIS AS INEFFICIENT # it = self.bk.images # ss = sa.select(it.c.cfht_field, it.c.cfht_field.like('{0}%'.format(blockID)), # group_by=it.c.cfht_field) # ims_query = self.bk.conn.execute(ss) # retval = [r[1] for r in ims_query] all_observed_fields = self.bk.what_fields_have_any_observations() # [dicts] # filter these for the ones that are in this block retval = [] retval2 = [] for obs in all_observed_fields: if obs['fieldId'].startswith(blockID): retval.append(obs) retval2.append(obs['fieldId']) return retval, retval2 # returns a list of dictionaries. Also return just keys? def format_imquery_return(self, ims_query): ret_images = [] for row in ims_query: ret_images.append([row[1], row[2], (row[3])]) ims_query.close() return ret_images def num_block_images(self, blockID): # number of images on all fields that are in the block it = self.bk.images cols = [it.c.cfht_field, sa.func.count(it.c.image_id)] ss = sa.select(cols, it.c.cfht_field.like('{0}%'.format(blockID)), group_by=it.c.cfht_field) ims_query = self.bk.conn.execute(ss) retval = sum([r[1] for r in ims_query]) return retval def central_radec(self, blockID): junk, fieldIds = self.fields_in_block(blockID) ras = [] decs = [] for field in fieldIds: ras.append(ephem.hours(self.bk.field_ra(field))) # str in hours of RA decs.append(ephem.degrees(self.bk.field_dec(field))) # str in deg of Dec # mean ra, mean dec: APPROXIMATING ra = ephem.hours((sum(ras) / len(ras))) dec = ephem.degrees((sum(decs) / len(decs))) retval = (str(ra), str(dec)) return retval def ecliptic_lat_span(self, blockID): junk, fieldIds = self.fields_in_block(blockID) ecs = [] for field in fieldIds: rr = ephem.Equatorial(ephem.hours(self.bk.field_ra(field)), ephem.degrees(self.bk.field_dec(field))) ec = ephem.Ecliptic(rr) ecs.append(ec) ecs.sort(key=lambda x: x.__getattribute__('lat')) retval = (degrees(ecs[0].lat), degrees(ecs[-1].lat)) # eclat is float (deg), min-max return retval def block_discovery_triples(self, blockID): retval, fieldIds = self.fields_in_block(blockID) for field in fieldIds: triplet = self.bk.discovery_triplet(field) if triplet is not None: # yay we have enough observations to have a discovery triplet! retfield = [n for n in retval if n['fieldId'] == field][0] retfield['triplet'] = triplet[1] retfield['worstIQ'] = triplet[2] return retval def block_precoveries(self, blockID): if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = 0 for field in fields: pc = self.bk.num_precoveries(field) if isinstance(pc, int): retval += pc else: retval = '-' return retval def block_nailings(self, blockID): if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = 0 for field in fields: nc = self.bk.num_nailings(field) if isinstance(nc, int): retval += nc else: retval = '-' return retval def block_doubles(self, blockID): if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = 0 for field in fields: doub = self.bk.num_doubles(field) if isinstance(doub, int): retval += doub else: retval = '-' return retval def block_discoveries(self, blockID): # AWAITING IMPLEMENTATION if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = [] return len(retval) else: retval = '-' return retval def block_blinking_status(self, blockID): # 36*21*2 = 1512 (or 1440 if it's a 20-field block.) # combine.py makes a given prefix-field-ccd (type doesn't seem to be included) # real files have either a .measure3.cands.astrom or a .no_candidates file. # fk files have more stuff. And there's a lot more of them, because every ccd gets one. # # sometimes weird stuff gets in there. So check on a field-by-field basis, I think. empty_units, fields = self.fields_in_block(blockID) for field in fields: uris = [os.path.join(storage.MEASURE3, str(field), '.measure3.cands.astrom'), os.path.join(storage.MEASURE3, str(field), '.no_candidates')] for uri in uris: if storage.exists(uri): node = storage.vospace.getNode(uri, force=force).props done = storage.tag_uri('done') # get_tags is built to obtain tags on the dbimages # RIGHT. There can be 'done' tags without there being a corresponding 'reals' file. # this is NOT IDEAL... # vtag vos:OSSOS/measure3/fk_E+3-1_17.measure3.cands.astrom # shows # 'ivo://canfar.uvic.ca/ossos#done': 'michele' # when done, but will show # 'ivo://canfar.uvic.ca/ossos#lock_holder': 'michele' # when someone has it out to blink. # if no ccds blinked, show 'Not started' # if some, show who has locks on those, group by lock_holder # if all ccds show 'done', show 'Completed'. # for the blocks page, just show 'x/36' under 'Blinked.' # has to show that for both fk and real. return None #def get_cands_tags(): def block_processing_status(self, blockID): try: self.bk.get_processing_status(self.block_discovery_triples(blockID)) except: print 'bother' return None
class BlockQuery(object): def __init__(self): self.bk = ImagesQuery() def all_blocks(self): retval = {} bks = retval.get('blocks', []) status = { 'E': ['complete', '52', '24.05'], 'O': ['blinking', '', ''], '13BL': ['triplets observed!', '', ''], '13BH': ['partial observations', '', ''] } for block in OSSOS_BLOCKS: bk = [] bk.append(block) bk.append(self.num_block_images(block)) # no. observations if block in status: for val in status[block]: bk.append(val) elif block.__contains__( 'WP'): # Wallpaper can't have discoveries or efficiency for k in range(1, 4): bk.append('-') bks.append(bk) retval['blocks'] = bks return retval def fields_in_block(self, blockID): # REWRITE THIS AS INEFFICIENT # it = self.bk.images # ss = sa.select(it.c.cfht_field, it.c.cfht_field.like('{0}%'.format(blockID)), # group_by=it.c.cfht_field) # ims_query = self.bk.conn.execute(ss) # retval = [r[1] for r in ims_query] all_observed_fields = self.bk.what_fields_have_any_observations( ) # [dicts] # filter these for the ones that are in this block retval = [] retval2 = [] for obs in all_observed_fields: if obs['fieldId'].startswith(blockID): retval.append(obs) retval2.append(obs['fieldId']) return retval, retval2 # returns a list of dictionaries. Also return just keys? def format_imquery_return(self, ims_query): ret_images = [] for row in ims_query: ret_images.append([row[1], row[2], (row[3])]) ims_query.close() return ret_images def num_block_images(self, blockID): # number of images on all fields that are in the block it = self.bk.images cols = [it.c.cfht_field, sa.func.count(it.c.image_id)] ss = sa.select(cols, it.c.cfht_field.like('{0}%'.format(blockID)), group_by=it.c.cfht_field) ims_query = self.bk.conn.execute(ss) retval = sum([r[1] for r in ims_query]) return retval def central_radec(self, blockID): junk, fieldIds = self.fields_in_block(blockID) ras = [] decs = [] for field in fieldIds: ras.append(ephem.hours( self.bk.field_ra(field))) # str in hours of RA decs.append(ephem.degrees( self.bk.field_dec(field))) # str in deg of Dec # mean ra, mean dec: APPROXIMATING ra = ephem.hours((sum(ras) / len(ras))) dec = ephem.degrees((sum(decs) / len(decs))) retval = (str(ra), str(dec)) return retval def ecliptic_lat_span(self, blockID): junk, fieldIds = self.fields_in_block(blockID) ecs = [] for field in fieldIds: rr = ephem.Equatorial(ephem.hours(self.bk.field_ra(field)), ephem.degrees(self.bk.field_dec(field))) ec = ephem.Ecliptic(rr) ecs.append(ec) ecs.sort(key=lambda x: x.__getattribute__('lat')) retval = (degrees(ecs[0].lat), degrees(ecs[-1].lat) ) # eclat is float (deg), min-max return retval def block_discovery_triples(self, blockID): retval, fieldIds = self.fields_in_block(blockID) for field in fieldIds: triplet = self.bk.discovery_triplet(field) if triplet is not None: # yay we have enough observations to have a discovery triplet! retfield = [n for n in retval if n['fieldId'] == field][0] retfield['triplet'] = triplet[1] retfield['worstIQ'] = triplet[2] return retval def block_precoveries(self, blockID): if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = 0 for field in fields: pc = self.bk.num_precoveries(field) if isinstance(pc, int): retval += pc else: retval = '-' return retval def block_nailings(self, blockID): if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = 0 for field in fields: nc = self.bk.num_nailings(field) if isinstance(nc, int): retval += nc else: retval = '-' return retval def block_doubles(self, blockID): if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = 0 for field in fields: doub = self.bk.num_doubles(field) if isinstance(doub, int): retval += doub else: retval = '-' return retval def block_discoveries(self, blockID): # AWAITING IMPLEMENTATION if not blockID.__contains__('WP'): empty_units, fields = self.fields_in_block(blockID) retval = [] return len(retval) else: retval = '-' return retval def block_blinking_status(self, blockID): # 36*21*2 = 1512 (or 1440 if it's a 20-field block.) # combine.py makes a given prefix-field-ccd (type doesn't seem to be included) # real files have either a .measure3.cands.astrom or a .no_candidates file. # fk files have more stuff. And there's a lot more of them, because every ccd gets one. # # sometimes weird stuff gets in there. So check on a field-by-field basis, I think. empty_units, fields = self.fields_in_block(blockID) for field in fields: uris = [ os.path.join(storage.MEASURE3, str(field), '.measure3.cands.astrom'), os.path.join(storage.MEASURE3, str(field), '.no_candidates') ] for uri in uris: if storage.exists(uri): node = storage.vospace.getNode(uri, force=force).props done = storage.tag_uri('done') # get_tags is built to obtain tags on the dbimages # RIGHT. There can be 'done' tags without there being a corresponding 'reals' file. # this is NOT IDEAL... # vtag vos:OSSOS/measure3/fk_E+3-1_17.measure3.cands.astrom # shows # 'ivo://canfar.uvic.ca/ossos#done': 'michele' # when done, but will show # 'ivo://canfar.uvic.ca/ossos#lock_holder': 'michele' # when someone has it out to blink. # if no ccds blinked, show 'Not started' # if some, show who has locks on those, group by lock_holder # if all ccds show 'done', show 'Completed'. # for the blocks page, just show 'x/36' under 'Blinked.' # has to show that for both fk and real. return None #def get_cands_tags(): def block_processing_status(self, blockID): try: self.bk.get_processing_status( self.block_discovery_triples(blockID)) except: print 'bother' return None
class SurveyQuery(object): def __init__(self): self.ims = ImagesQuery() self.disc = DiscoveriesQuery() self.bk = BlockQuery() # pixel scale is symmetric, 0.1850 arcsec/pixel. Dectector is [1:23219,1:19354] pixels. self.field_area = ((0.185 * 23219) / 3600.) * ( (0.185 * 19354) / 3600.) # sq. deg def fields_observed(self): fields = self.ims.what_fields_have_any_observations() # don't include the wallpaper in the overall count tno_fields = [f for f in fields if not f['fieldId'].__contains__('WP')] num_fields = len(tno_fields) sqdeg_observed = num_fields * self.field_area retval = (sqdeg_observed, num_fields) return retval def fields_processed(self): retval = 42 * self.field_area # FIXME: currently hardwired for field 13AE & 13AO only return retval def most_recent_observation(self): it = self.ims.images ss = sa.select([it.c.obs_end], order_by=it.c.obs_end) dates = [n[0] for n in self.ims.conn.execute(ss)] return dates[-1] def next_moondark(self): # this is producing an off by one error: fix! mn = ephem.Moon() mp = [] for n in range(0, 29 * 4): mn.compute(ephem.now() + (n / 4.)) mp.append((ephem.now() + (n / 4.), mn.moon_phase)) next_new_moon = ephem.Date(min(mp, key=lambda x: x[1])[0]).datetime() # next_new_moon = pytz.utc.localize(next_new_moon) # it's calculated in UTC # hst = pytz.timezone('HST') retval = next_new_moon #.astimezone(hst) return retval def next_observing_window(self): # we observe if the near-new moon is down, or if the moon is up # but we are within 3 days of new moon. next_nm = self.next_moondark() next_period = (next_nm - datetime.timedelta(3), next_nm + datetime.timedelta(3)) if next_period[0] < datetime.datetime.now() < next_period[1]: retval = 'tonight (hopefully).' else: retval = 'in no more than ' + str( (next_period[0] - datetime.datetime.now()).days) + ' days.' return retval def megacam_schedule(self): # tuples bracket the ends of date ranges that MegaCam is on the telescope schedule = [ (datetime.datetime(2014, 1, 27), datetime.datetime(2014, 2, 03)), (datetime.datetime(2014, 2, 21), datetime.datetime(2014, 3, 06)), (datetime.datetime(2014, 3, 24), datetime.datetime(2014, 4, 07)), (datetime.datetime(2014, 4, 24), datetime.datetime(2014, 5, 06)), (datetime.datetime(2014, 5, 20), datetime.datetime(2014, 6, 02)), (datetime.datetime(2014, 6, 20), datetime.datetime(2014, 7, 02)), (datetime.datetime(2014, 7, 17), datetime.datetime(2014, 7, 28)) ] return schedule def nearest_megacam_run(self): now = datetime.datetime.now() schedule = self.megacam_schedule() for run in schedule: if (run[0] - now > datetime.timedelta(0)) or ( run[1] - now > datetime.timedelta(0)): nearest_run = run break if (nearest_run[0] <= now <= nearest_run[1]): retval = 'now.' else: if (nearest_run[0] - now).days > 0: retval = "in " + str((nearest_run[0] - now).days) + " days." else: hrs = (nearest_run[0] - now).seconds / 3600. retval = "in " + '%2.1f' % hrs + " hours." return retval
class SurveyQuery(object): def __init__(self): self.ims = ImagesQuery() self.bk = BlockQuery() # pixel scale is symmetric, 0.1850 arcsec/pixel. Dectector is [1:23219,1:19354] pixels. self.field_area = ((0.184 * 23219) / 3600.) * ((0.184 * 19354) / 3600.) # sq. deg def fields_observed(self): fields = self.ims.what_fields_have_any_observations() # don't include the wallpaper in the overall count tno_fields = [f for f in fields if not f['fieldId'].__contains__('WP')] num_fields = len(tno_fields) sqdeg_observed = num_fields * self.field_area retval = (sqdeg_observed, num_fields) return retval def fields_processed(self): retval = 3 * 21 * self.field_area # 3 blocks processed at 04-02-2015 return retval def most_recent_observation(self): it = self.ims.images ss = sa.select([it.c.obs_end], order_by=it.c.obs_end) dates = [n[0] for n in self.ims.conn.execute(ss)] return dates[-1] def next_moondark(self): # this is producing an off by one error: fix! mn = ephem.Moon() mp = [] for n in range(0, 29 * 4): mn.compute(ephem.now() + (n / 4.)) mp.append((ephem.now() + (n / 4.), mn.moon_phase)) next_new_moon = ephem.Date(min(mp, key=lambda x: x[1])[0]).datetime() # next_new_moon = pytz.utc.localize(next_new_moon) # it's calculated in UTC # hst = pytz.timezone('HST') retval = next_new_moon # .astimezone(hst) return retval def next_observing_window(self): # we observe if the near-new moon is down, or if the moon is up # but we are within 3 days of new moon. next_nm = self.next_moondark() next_period = (next_nm - datetime.timedelta(3), next_nm + datetime.timedelta(3)) if next_period[0] < datetime.datetime.now() < next_period[1]: retval = 'tonight (hopefully).' else: retval = 'in no more than ' + str((next_period[0] - datetime.datetime.now()).days) + ' days.' return retval def megacam_schedule(self): # tuples bracket the ends of date ranges that MegaCam is on the telescope schedule = [(datetime.datetime(2015, 7, 8), datetime.datetime(2015, 7, 21)), ] return schedule def nearest_megacam_run(self): now = datetime.datetime.now() schedule = self.megacam_schedule() nearest_run = [] for run in schedule: if (run[0] - now > datetime.timedelta(0)) or (run[1] - now > datetime.timedelta(0)): nearest_run = run break if nearest_run[0] <= now <= nearest_run[1]: retval = 'now.' else: if (nearest_run[0] - now).days > 0: retval = "in " + str((nearest_run[0] - now).days) + " days." else: hrs = (nearest_run[0] - now).seconds / 3600. retval = "in " + '%2.1f' % hrs + " hours." return retval def num_discoveries(self): # Characterized discoveries only. status = self.bk.all_blocks()['status'] return sum([int(n[1]) for n in status.values() if (n is not None and n[1].isdigit())]) def mpc_informed(self): # status = self.bk.all_blocks()['blocks'] # Implement more comprehensive info later # return sum([n[1] for n in status.values() if n[1].isdigit()]) return 0
def __init__(self): self.ims = ImagesQuery() self.bk = BlockQuery() # pixel scale is symmetric, 0.1850 arcsec/pixel. Dectector is [1:23219,1:19354] pixels. self.field_area = ((0.184 * 23219) / 3600.) * ((0.184 * 19354) / 3600.) # sq. deg
class SurveyQuery(object): def __init__(self): self.ims = ImagesQuery() self.disc = DiscoveriesQuery() self.bk = BlockQuery() # pixel scale is symmetric, 0.1850 arcsec/pixel. Dectector is [1:23219,1:19354] pixels. self.field_area = ((0.185 * 23219) / 3600.0) * ((0.185 * 19354) / 3600.0) # sq. deg def fields_observed(self): fields = self.ims.what_fields_have_any_observations() # don't include the wallpaper in the overall count tno_fields = [f for f in fields if not f["fieldId"].__contains__("WP")] num_fields = len(tno_fields) sqdeg_observed = num_fields * self.field_area retval = (sqdeg_observed, num_fields) return retval def fields_processed(self): retval = 42 * self.field_area # FIXME: currently hardwired for field 13AE & 13AO only return retval def most_recent_observation(self): it = self.ims.images ss = sa.select([it.c.obs_end], order_by=it.c.obs_end) dates = [n[0] for n in self.ims.conn.execute(ss)] return dates[-1] def next_moondark(self): # this is producing an off by one error: fix! mn = ephem.Moon() mp = [] for n in range(0, 29 * 4): mn.compute(ephem.now() + (n / 4.0)) mp.append((ephem.now() + (n / 4.0), mn.moon_phase)) next_new_moon = ephem.Date(min(mp, key=lambda x: x[1])[0]).datetime() # next_new_moon = pytz.utc.localize(next_new_moon) # it's calculated in UTC # hst = pytz.timezone('HST') retval = next_new_moon # .astimezone(hst) return retval def next_observing_window(self): # we observe if the near-new moon is down, or if the moon is up # but we are within 3 days of new moon. next_nm = self.next_moondark() next_period = (next_nm - datetime.timedelta(3), next_nm + datetime.timedelta(3)) if next_period[0] < datetime.datetime.now() < next_period[1]: retval = "tonight (hopefully)." else: retval = "in no more than " + str((next_period[0] - datetime.datetime.now()).days) + " days." return retval def megacam_schedule(self): # tuples bracket the ends of date ranges that MegaCam is on the telescope schedule = [ (datetime.datetime(2014, 1, 27), datetime.datetime(2014, 2, 03)), (datetime.datetime(2014, 2, 21), datetime.datetime(2014, 3, 06)), (datetime.datetime(2014, 3, 24), datetime.datetime(2014, 4, 07)), (datetime.datetime(2014, 4, 24), datetime.datetime(2014, 5, 06)), (datetime.datetime(2014, 5, 20), datetime.datetime(2014, 6, 02)), (datetime.datetime(2014, 6, 20), datetime.datetime(2014, 7, 02)), (datetime.datetime(2014, 7, 17), datetime.datetime(2014, 7, 28)), ] return schedule def nearest_megacam_run(self): now = datetime.datetime.now() schedule = self.megacam_schedule() for run in schedule: if (run[0] - now > datetime.timedelta(0)) or (run[1] - now > datetime.timedelta(0)): nearest_run = run break if nearest_run[0] <= now <= nearest_run[1]: retval = "now." else: if (nearest_run[0] - now).days > 0: retval = "in " + str((nearest_run[0] - now).days) + " days." else: hrs = (nearest_run[0] - now).seconds / 3600.0 retval = "in " + "%2.1f" % hrs + " hours." return retval
def __init__(self): self.ims = ImagesQuery() self.disc = DiscoveriesQuery() self.bk = BlockQuery()
class SurveyQuery(object): def __init__(self): self.ims = ImagesQuery() self.disc = DiscoveriesQuery() self.bk = BlockQuery() def survey_proportion_complete(self): retval = [] # UPDATE THIS return retval def fields_observed(self): fields = self.ims.what_fields_have_any_observations() # don't include the wallpaper in the overall count tno_fields = [f for f in fields if not f['fieldId'].__contains__('WP')] num_fields = len(tno_fields) # pixel scale is symmetric, 0.1850 arcsec/pixel. Dectector is [1:23219,1:19354] pixels. field_area = ((0.185*23219)/3600.) * ((0.185*19354)/3600.) # sq. deg sqdeg_observed = num_fields * field_area retval = (sqdeg_observed, num_fields) return retval def fields_observed_to_completion(self): retval = [] # UPDATE THIS return retval def fields_processed(self): retval = [] return retval def survey_efficiency(self): retval = [] return retval def most_recent_observation(self): it = self.ims.images ss = sa.select([it.c.obs_end], order_by=it.c.obs_end) dates = [n[0] for n in self.ims.conn.execute(ss)] return dates[-1] def next_moondark(self): # this is producing an off by one error: fix! mn = ephem.Moon() mp = [] for n in range(0,29*4): mn.compute(ephem.now()+(n/4.)) mp.append((ephem.now()+(n/4.), mn.moon_phase)) next_new_moon = ephem.Date(min(mp, key=lambda x:x[1])[0]).datetime() # next_new_moon = pytz.utc.localize(next_new_moon) # it's calculated in UTC # hst = pytz.timezone('HST') retval = next_new_moon #.astimezone(hst) return retval def next_observing_window(self): # we observe if the near-new moon is down, or if the moon is up # but we are within 3 days of new moon. next_nm = self.next_moondark() next_period = (next_nm-datetime.timedelta(3), next_nm+datetime.timedelta(3)) if next_period[0] < datetime.datetime.now() < next_period[1]: retval = 'tonight (hopefully).' else: retval = 'in no more than ' + str((next_period[0]-datetime.datetime.now()).days) + ' days.' return retval def megacam_schedule(self): # tuples bracket the ends of date ranges that MegaCam is on the telescope schedule = [(datetime.datetime(2013,7,29), datetime.datetime(2013,8,11)), (datetime.datetime(2013,8,29), datetime.datetime(2013,9,10)), (datetime.datetime(2013,9,27), datetime.datetime(2013,10,8)), (datetime.datetime(2013,10,28), datetime.datetime(2013,11,7)), (datetime.datetime(2013,11,27), datetime.datetime(2013,12,5)), (datetime.datetime(2013,12,27), datetime.datetime(2014,1,6)), (datetime.datetime(2014,1,22), datetime.datetime(2014,1,31)) ] return schedule def nearest_megacam_run(self): now = datetime.datetime.now() schedule = self.megacam_schedule() for run in schedule: if (run[0]-now > datetime.timedelta(0)) or (run[1]-now > datetime.timedelta(0)): nearest_run = run break if (nearest_run[0] <= now <= nearest_run[1]): retval = 'now.' else: if (nearest_run[0]-now).days > 0: retval = "in "+ str((nearest_run[0]-now).days) + " days." else: hrs = (nearest_run[0]-now).seconds/3600. retval = "in "+ '%2.1f' % hrs + " hours." return retval