def distanceToSun(self): """ Find the distance between the Sun and the target pointings """ lofar = Observer() lofar.lon = '6.869882' lofar.lat = '52.915129' lofar.elevation = 15.*u.m lofar.date = self.startTime # Create Sun object sun = Sun() sun.compute(lofar) # Create the target object target = FixedBody() target._epoch = '2000' target._ra = self.coordPoint1.ra.radian target._dec = self.coordPoint1.dec.radian target.compute(lofar) print 'INFO: Sun is {:0.2f} degrees away from {}'.format(\ float(separation(target, sun))*180./np.pi, self.namePoint1) target._ra = self.coordPoint2.ra.radian target._dec = self.coordPoint2.dec.radian target.compute(lofar) print 'INFO: Sun is {:0.2f} degrees away from {}'.format(\ float(separation(target, sun))*180./np.pi, self.namePoint2)
def get_object_separation(obs, start_date, time, ra, dec): """ Get separation between the Sun/Moon and the RA/DEC of a pixel. :param obs: pyephem observer :param start_date: date :param time: time axis of TOD :param ra: RA for TOD :param dec: DEC for TOD :return: separation of the TOD positions with the Sun and the Moon """ sun_separation = [] moon_separation = [] for (t, ra, dec) in zip(time, ra, dec): date = start_date + timedelta(hours=t) obs.date = datetime.strftime(date, EPHEM_DATE_FORMAT) sun = ephem.Sun() moon = ephem.Moon(obs) sun.compute(obs) moon.compute(obs) sun_separation.append(ephem.separation(sun, (ra, dec))) moon_separation.append(ephem.separation(moon, (ra, dec))) return np.array(sun_separation), np.array(moon_separation)
def compute_angle(date_local): angle = [0,0,0] m = ephem.Sun() m.compute(ephem.Date(date_local)) m2 = ephem.Pluto() m2.compute(ephem.Date(date_local)) angle[0] = float(repr(ephem.separation((m.hlon,0),(m2.hlon,0)))) angle[1] = abs(float(repr(ephem.separation((0,abs(m2.hlat)),(0,abs(m.a_dec)))))) angle[2] = cmp(m2.hlat*m.a_dec,0) return angle
def query_skycalc(ra, dec, utc, obs_lat_deg, obs_lon_deg, outfile, wmin=650, wmax=750, debug=False): #compute Ephemeris data targ=ephem.Equatorial(ra, dec) ecl=ephem.Ecliptic(targ) obs=ephem.Observer() #obs.date=ephem.julian_date(o.image.midpoint.jd) #This does not work obs.date=utc #This is correct, ephem wants UTC obs.lat=ephem.degrees('{}'.format(obs_lat_deg)) obs.long=ephem.degrees('{}'.format(obs_lon_deg)) #obs.elevation=2450.0 star=ephem.FixedBody() star._ra=ephem.hours(ra) star._dec=ephem.degrees(dec) star.compute(obs) moon=ephem.Moon(obs) sun=ephem.Sun(obs) helio_ecl_lon=np.rad2deg(ecl.lon) #This is a guess, it could be that I've got the signs flipped if helio_ecl_lon >180: helio_ecl_lon=-(360-helio_ecl_lon) ecl_lat=np.rad2deg(ecl.lat) targ_alt=np.rad2deg(star.alt) targ_X=1.0/np.cos(np.deg2rad(90-targ_alt)) moon_alt=np.rad2deg(moon.alt) moon_targ_sep=np.rad2deg(ephem.separation(moon, star)) sum_moon_sep=np.rad2deg(ephem.separation(moon, sun)) month_pair=(obs.date.datetime().month%12)/2 + 1 night_length=(obs.next_rising(sun).datetime()- obs.previous_setting(sun).datetime()) night_elapsed=obs.date.datetime()-obs.previous_setting(sun).datetime() # 1,2, 3 night_third=np.ceil((float(night_elapsed.seconds)/night_length.seconds) * 3.0) try: solar_flux=fluxdata[(obs.date.datetime().strftime('%B'), obs.date.datetime().year)] except KeyError,e: print str(e) raise ValueError('No mean solar flux for observation date')
def gcDAR(): iraf.noao() obs = iraf.noao.observatory # Set up Keck observatory info obs(command="set", obsid="keck") keck = ephem.Observer() keck.long = math.radians(-obs.longitude) keck.lat = math.radians(obs.latitude) keck.elev = obs.altitude keck.pressure = 800.0 keck.temp = 278.0 # Date of Observations: 06maylgs1 keck.date = '2006/05/03 %d:%d:%f' % (obs.timezone+3, 28, 46.33) # Set up the galactic center target sgra = ephem.FixedBody() sgra._ra = ephem.hours("17:45:40") sgra._dec = ephem.degrees("-29:00:10") sgra._epoch = 2000 sgra.compute() pos2 = ephem.FixedBody() pos2._ra = ephem.hours("17:45:40") pos2._dec = ephem.degrees("-29:00:00") pos2._epoch = 2000 pos2.compute() print 'Date of Obs: ', keck.date sgra.compute(keck) pos2.compute(keck) print 'Azimuth of Objects: %s vs. %s' % (sgra.az, pos2.az) for ii in range(15): keck.lat = math.radians(obs.latitude - (ii*2)) sgra.compute(keck) pos2.compute(keck) angAbs = ephem.separation((sgra.ra, sgra.dec), (pos2.ra, pos2.dec)) angAbs *= 206265.0 angRel = ephem.separation((sgra.az, sgra.alt), (pos2.az, pos2.alt)) angRel *= 206265.0 angDiff = angAbs - angRel print 'Sgr A*: %s vs. %s deltaR = %5d (muas)' % \ (sgra.alt, pos2.alt, angDiff*1e6)
def radec_obj_dist(obs, ra, dec, obj): b = ephem.FixedBody() b._ra = np.radians(ra) b._dec = np.radians(dec) b.compute(obs) obj.compute(obs) return np.degrees(ephem.separation(b, obj))
def table(ra,dec,year=year,startday=0,endday=265): """ Produce a table of approximate roll ranges for Swift observation of a target with given position. Parameters: ra, dec : float position in decimal degrees (J2000) year : int (optional) year for the table (default = current year) """ print("Roll angle ranges for swift observation of target at\n RA,Dec=(%.2f,%.2f) year=%i\n"% (ra,dec,year)) ra = ra*dtor dec = dec*dtor print("%3s %7s %7s %7s %7s %7s %7s"%("Day","SunRA","SunDec","SunDist","Roll","MinRoll","MaxRoll")) for i in range(startday,endday+1): now = ICSdateconv("%s-%03d-00:00:00"%(year,i)) sra,sdec = sunradec(now) oroll = optimum_roll(ra,dec,now) sundist = ephem.separation([ra,dec],[sra,sdec]) roll_range = rollcons/numpy.sin(sundist); if sundist/dtor > suncons: #print(f"{i:3d} {sra/dtor:7.3f} {sdec/dtor:7.3f} {sundist/dtor:7.3f} #{oroll/dtor:7.3f} {oroll/dtor-roll_range:7.3f} {oroll/dtor+roll_range:7.3f}") print("%3d %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f"%(i,sra/dtor,sdec/dtor, sundist/dtor,oroll/dtor,oroll/dtor-roll_range,oroll/dtor+roll_range))
def moon_separation(ra, dec, observer = None): ra_rad = ra2float(str(ra))*ephem.degree dec_rad = dec2float(str(dec))*ephem.degree m_ra, m_dec = moon_angle(observer = observer) m_ra = m_ra * ephem.degree m_dec = m_dec * ephem.degree return float(ephem.separation((ra_rad,dec_rad),(m_ra,m_dec))) / ephem.degree
def trend(self): "Returns True if the two bodies are getting closer" a = self.body1.copy() b = self.body2.copy() later = ephem.now() + ephem.hour a.compute(later) b.compute(later) return ephem.separation(a, b) < self.angle
def selectbsc(t, srcs, magrange): ''' Given a list of star sources, select from the list based on hour angle, elevation, and magnitude range provided in magrange as [maglow, maghi] ''' # Pare down the list by selecting stars within +3 and -9 hours of HA. # Pare down further by requiring stars within -30 and +45 degrees in Dec # Finally, find stars with magnitudes between 3.5 and 5 halow = Dec_Angle('-09:00:00','hms').radians hahi = Dec_Angle('03:00:00','hms').radians declow = Dec_Angle('-30:00:00','dms').radians dechi = Dec_Angle('+45:00:00','dms').radians maglow = magrange[0] maghi = magrange[1] # Make a list of good sources (those in the ranges specified) sel = [] # Loop over sources for i,src in enumerate(srcs): # Make sure ha is in range -pi to pi ha = eovsa_ha(src,t) dec = src.dec mag = float(src.mag) good = (ha > halow) & (ha < hahi) & (dec > declow) & (dec < dechi) \ & (mag > maglow) & (mag < maghi) if good: sel.append(i) # These selected stars should be reachable by the antennas, so now check them # for angular separation. nstars = len(sel) # Number of stars so far selected widesep = zeros((nstars,nstars),bool) # Boolean nstars x nstars array for i in range(nstars-1): for j in range(i+1,nstars): # True where pairs of stars are > 20 deg apart widesep[i,j] = ephem.separation(srcs[sel[i]],srcs[sel[j]]) > (21.5*pi/180) widesep[j,i] = widesep[i,j] # Go through asep array row by row and mark stars for deletion with sep < 20 degrees idx = ones((nstars),bool) for i in range(nstars): if idx[i]: # Only look at rows for "True" columns x = widesep[:,i] x[:i+1] = True # Do not delete stars in lower part of array idx = idx & x # This should be a list of remaining good stars ids = array(sel)[idx] print len(ids),'stars selected for date/time starting at:',t.iso print 'Number RA Dec Magnitude' fmt = '{0:<4} {1:>12} {2:>12} {3:>6}' for i in ids: dec = srcs[i].a_dec decstr = str(srcs[i].a_dec).zfill(10) if dec < 0: decstr = '-'+str(srcs[i].a_dec)[1:].zfill(10) print fmt.format(srcs[i].name[2:],str(srcs[i].a_ra),decstr,srcs[i].mag) return ids
def generate_separations(body1, body2): date = ephem.now() body1, body2 = list(body_computer(date, body1, body2)) while True: yield Separation( date, body1, body2, ephem.separation(body1, body2)) date = ephem.Date(date + ephem.hour) body1.compute(date) body2.compute(date)
def pixsep(nside,pix1,pix2): """return the seperation between two healpix pixels in degrees""" src1_loc = hpy.pix2ang(nside,pix1) src2_loc = hpy.pix2ang(nside, pix2) aa = a.scripting.get_null_aa() src1 = a.phs.RadioFixedBody(src1_loc[1],n.pi/2 - src1_loc[0]) src2 = a.phs.RadioFixedBody(src2_loc[1],n.pi/2 - src2_loc[0]) src1.compute(aa) src2.compute(aa) return ephem.separation(src1,src2)
def pointing_plan(tonightsplan, orig_keys, survey_centers, nexttile, filters, obs): time_elapsed = 0 n_exp = 0 for f in filters: if survey_centers['used_tile_{:s}'.format(f)][nexttile] == 1: continue n_exp += 1 survey_centers['used_tile_{:s}'.format(f)][nexttile] = 1 tile_str = ','.join([ str(survey_centers['TILEID'][nexttile]), 'f', survey_centers['RA_STR'][nexttile], survey_centers['DEC_STR'][nexttile], '20' ]) this_tile = ephem.readdb(tile_str) this_tile.compute(obs) # Compute airmass airm = alt2airmass(float(this_tile.alt)) # Compute moon separation moon.compute(obs) moon_dist = ephem.separation( (this_tile.az, this_tile.alt), (moon.az, moon.alt) ) moon_alt = np.degrees(moon.alt) # Add this exposure to tonight's plan for key in orig_keys: tonightsplan[key].append(survey_centers[key][nexttile]) tonightsplan['exp_time'].append(exp_time_filters[f]) tonightsplan['approx_datetime'].append(obs.date) tonightsplan['airmass'].append(airm) ha = survey_centers['RA'][nexttile] - np.degrees(obs.sidereal_time()) tonightsplan['ha'].append(ha/15.) tonightsplan['approx_time'].append(obs.date) tonightsplan['filter'].append(f) tonightsplan['moon_sep'].append(moon_dist) tonightsplan['moon_alt'].append(moon_alt) tonightsplan['lst'].append(np.degrees(obs.sidereal_time())) delta_t = exp_time_filters[f] + overheads time_elapsed += delta_t obs.date = obs.date + delta_t * s_to_days return time_elapsed, n_exp
def current_separations(): stars_list = [ephem.star(name) for name in stars.keys()] planets = [planet() for planet in PLANETS] solar_system = [ephem.Moon()] + planets [body.compute() for body in solar_system + stars_list] print(type(stars_list[0])) angles = [] # Separations between solar system bodies and stars for body in solar_system: for star in stars_list: angles.append( Separation(body, star, ephem.separation(body, star))) # more separations for a, b in itertools.combinations(solar_system, 2): angles.append(Separation(a, b, ephem.separation(a, b))) for sep in sorted(angles, key=operator.attrgetter('angle')): if sep.angle > MAX_ANGLE: break print(sep)
def getAngularSeparation( self, other, location, date ): if isinstance( location, str ): location = getLocation( location ) location.observer.date = date.to( 'utc' ).format( ) self.object.compute( location.observer ) other.object.compute( location.observer ) return RPNMeasurement( mpmathify( ephem.separation( ( self.object.az, self.object.alt ), ( other.object.az, other.object.alt ) ) ), 'radian' )
def compute(self,mylist,delta=0): ''' Compute positions and other values for asteroids in mylist. Do twice (if delta <>0) to compute PA and SPEED ''' dtypes=np.dtype([("KEY","|S7"),("PRECOVERY",np.int16),("TYPE","|S30"),("DATETIME","|S25"),("MJD",np.float64),("EPOCH","|S10"),\ ("RA",np.float64),("DEC",np.float64),("MAG",np.float64),("SPEED",np.float64),("PA",np.float64),("PHASE",np.float64),("EARTH_DIS",np.float64),\ ("SUN_DIS",np.float64),("ELONG",np.float64),("SUN_SEPARATION",np.float64)]) astPos=[] for key, value in mylist.iteritems() : try: obs_date=str(convert_date(value[2])) discover_Date=date_from_designation(key) if discover_Date>=self.here.date: precovery=1 #print key,discover_Date else: precovery=0 (a,type_)=self.loadObject(key) #first compute actual position at datetime a.compute(self.here) ra =a.a_ra*180/(pi) dec =a.a_dec*180/pi #print key,value #print ra,dec phang=self.phase_angle(a.elong,a.earth_distance,a.sun_distance) vmag=self.vmag(a._H,a._G,phang,a.earth_distance,a.sun_distance) sun_separation=ephem.separation(self.sun,a) ldate=self.here.date.datetime().strftime('%Y-%m-%d %H:%M:%S') ddate="{:18.11f}".format(self.here.date+dubliJDoffset-MJDoffset) #then compute for datetime+delta if delta!=0 #to calculate SPEED and PA if delta !=0: self.here.date+=delta a.compute(self.here) ra_ =a.a_ra*180/(pi) dec_ =a.a_dec*180/pi pa=PA(ra,dec,ra_,dec_) sp=speed(delta,ra,dec,ra_,dec_) self.here.date-=delta else: pa=np.nan sp=np.nan astPos.append((key,precovery,type_,ldate,ddate,obs_date,ra,dec,vmag,sp,pa,phang,a.earth_distance,a.sun_distance,a.elong,sun_separation)) except: print key," fail to compute\n",value nrec=len(astPos) Pos=np.asarray(astPos,dtype=dtypes) if len(Pos)>0: self.result_queue.put(Pos) return Pos
def process_plan (target_list, time_string=''): #declare observing sites observatory = ephem.Observer() observatory.lat = observer_latitude observatory.lon = observer_logitude observatory.elev = observer_elevation observatory.pressure = 0 if time_string != '': observatory.date = ephem.Date(time_string)- (observer_timezone * ephem.hour) moon = ephem.Moon() moon.compute(observatory) ###### Reporting Section print "Report for: %s " %(ut_to_local_string(observatory.date)) print "---------------------------------" observatory.horizon = '-18' moon_days = observatory.date - ephem.previous_new_moon(observatory.date) print "Astronomical twilight:\n\tNext ending: %s" %(ut_to_local_string(observatory.next_setting(ephem.Sun(),use_center=True))) print "\tNext beginning: %s" %(ut_to_local_string(observatory.next_rising(ephem.Sun(),use_center=True))) print "Moon age: %3.2f days -- Ilumination: %3.1f%%" % (moon_days, moon.phase) print "\tNext Moon rise: %s" % (ut_to_local_string(observatory.next_rising(moon))) print "\tNext Moon set: %s" % (ut_to_local_string(observatory.next_setting(moon))) observatory.horizon = '0' print "---------------------------------\n" for target in target_list: varstar = plan_to_ephem(target) varstar.compute(observatory) print "Target: %s" %(varstar.name) try: print "Altitude: %3.2f" % (math.degrees(varstar.alt)) print "Azimuth: %3.2f" % (math.degrees(varstar.az)) print "Next rise: %s" % (ut_to_local_string(observatory.next_rising(varstar))) print "Next set: %s" % (ut_to_local_string(observatory.next_setting(varstar))) except ephem.AlwaysUpError: print "Object is circumpolar" except ephem.NeverUpError: print "*** Transit is below horizon ***" transit = observatory.next_transit(varstar) print "Next transit: %s " % (ut_to_local_string(transit)) temp_date = observatory.date observatory.date = transit varstar.compute(observatory) moon.compute(observatory) print "Transit altitude: %3.2f deg" % (math.degrees(varstar.alt)) print "Lunar separation: %s" % (ephem.separation(varstar, moon)) observatory.date = temp_date print "\n"
def calc_moon(self, site, body): """Compute Moon altitude""" moon = ephem.Moon() self.observer.set_date(self.date) moon.compute(site) moon_alt = float(moon.alt) # moon.phase is % of moon that is illuminated moon_pct = moon.moon_phase # calculate distance from target moon_sep = ephem.separation(moon, body) moon_sep = float(moon_sep) return (moon_alt, moon_pct, moon_sep)
def moondeg(self,observer,object,now=None): if type(now)==NoneType: now=self.now() observer.date=now self.moon.compute(observer) object.compute(observer) moondeg=180.0-ephem.separation([self.moon.a_ra,self.moon.a_dec], [object.a_ra,object.a_dec])/self.dtor return moondeg
def calc_moon(self, site, body): """Compute Moon altitude""" site.date = ephem.Date(self.date_utc) moon = ephem.Moon(site) #moon.compute(site) moon_alt = math.degrees(float(moon.alt)) # moon.phase is % of moon that is illuminated moon_pct = moon.moon_phase # calculate distance from target moon_sep = ephem.separation(moon, body) moon_sep = math.degrees(float(moon_sep)) return (moon_alt, moon_pct, moon_sep)
def field_elongation(ra, dec, date): """ For a given field, calculate the solar elongation at the given date. :param ra: field's right ascension. unit="h" format="RAh:RAm:RAs" :param dec: field's declination. degrees :param date: date at which to calculate elongation :return: elongation from the Sun in degrees """ sun = ephem.Sun() sun.compute(date) sep = ephem.separation((ra, dec), sun) retval = 180. - math.degrees(sep) return retval
def find_nearest_star(obj): """ Finds the star that appears closest to the moon for the observer. The star list comes from ephems list of stars of known magnitudes. """ # First calculate the distance for each known star for name, star in stars.stars.items(): star.compute(self.observer) # Get the dict of all separations for object star_sep = {name:ephem.separation(obj,star) for name,star in stars.stars.items()} # Get the star with minimum separation min_star_name = min(star_sep, key = lambda k: star_sep[k]) return stars.star(min_star_name)
def readEphemFile(self, project, filename, min_separation): catfile = open(filename) projobjs = [] for line in catfile: obj = ephem.readdb(line) obj.name = project['id'][6:]+'_'+obj.name obj.compute(ephem.now()) for oldobj in projobjs: if ephem.separation(oldobj, obj)*180./pi < min_separation: oldobj.name = project['id'][6:]+'_multi' obj = None break if obj is not None: projobjs.append(obj) return projobjs
def nearest_stars(): print('\nThe stars within 20° of the Moon:') now = ephem.now() moon = ephem.Moon(now) separations = { name:ephem.separation(moon, compute_star(name)) for name in stars } closest = ( (value, name) for (name, value) in separations.items() if value <= ephem.degrees('20') ) for (value, name) in sorted(closest): print(name, value)
def close_enough(currentposition, finalposition, threshold): #assumes positions are given as pairs [ra,dec] #if close enough return a bool true, else a bool false #express the position as a pair of floats of the ra and dec values currentpos = float(ephem.degrees(currentposition[0])), float(ephem.degrees(currentposition[1])) finalpos = float(ephem.degrees(finalposition[0])), float(ephem.degrees(finalposition[1])) difference = ephem.separation(finalpos, currentpos) #print "the difference in deg is: ", abs(ephem.degrees(difference)) #print "comparing with:", threshold if((ephem.degrees(difference)) < threshold): close = True else: close = False return (close)
def findcal(cal, band='C', qual='P', t=None, dtheta=[20,40]): '''Searches the VLA calibrator database [cal list returned by a call to readvlacaldb()] to find sources matching the band and quality codes provided: band = 'L', 'C', 'X', 'U', 'Q' (default 'C') qual = 'P', 'S', 'X', 'W' (default 'P') If t and dtheta are provided, only sources within an annulus from dtheta[0] to dtheta[1] degrees from the Sun are selected, for the time specified in Time() object t. Default is 20-40 deg. Returns a list of ephem source objects. If t is not provided, the current time is used. In all cases, the first source in the list is the Sun. ''' srclist = [] dtor = pi/180. if t is None: time = Time.now().iso.replace('-','/')[:16] else: time = t.iso.replace('-','/')[:16] aa = eovsa_array() aa.set_ephemtime(time) aa.compute_pressure() sun = ephem.Sun() sun.compute(aa) ## Add sun to source list in first location srclist.append(sun) for i in range(len(cal)): if band in cal[i].band: j = (array(cal[i].band) == band) & (array(cal[i].qual) == qual) if j.any(): flux = str(array(cal[i].flux)[j][0]) name = cal[i].name ra = cal[i].ra[0] dec = cal[i].dec[0] src = ephem.readdb(name+',f,'+ra+','+dec+','+flux+',2000') src.compute(aa) if t is None: # No selection based on distance to Sun, so append srclist.append(src) else: sep = ephem.separation(sun,src) if sep > dtheta[0]*dtor and sep < dtheta[1]*dtor: # This source qualifies so append it to list srclist.append(src) return srclist, aa
def getSunDistance(time, objs, date=today, obs=apex): sundists = [] sun = ephem.Sun() for obj in objs: separation = time.copy() it = np.nditer(time, flags=['f_index']) while not it.finished: h = int(it[0]) m = int((it[0]-h)*60) s = ((it[0]-h)*60-m)*60 obs.date = date + ' ' + '{0}:{1}:{2}'.format(h,m,s) obj.compute(obs) sun.compute(obs) separation[it.index] = ephem.separation(obj, sun)*180./pi it.iternext() sundists.append(separation) return sundists
def close_star_approaches(year=None): if year is None: year = ephem.now().triple()[0] starting_date = ephem.Date(str(year)) stars_list = [ephem.star(name) for name in stars.keys()] # Stars don't move, so just compute them once [star.compute(starting_date) for star in stars_list] planets = [planet() for planet in PLANETS] for day in range(365): date = ephem.Date(starting_date + day) [body.compute(date) for body in planets] for body in planets: for star in stars_list: sep = ephem.separation(body, star) if sep < ephem.degrees('3'): print(date, body.name, star.name, sep)
def find_src_in_cat(src,cat,sep): """ Given a src (src = aipy.amp.RadioFixedObject or lower) and a catalog (cat = aipy.amp.RadioCatalog or lower), find the closest source in cat that falls within sep [deg]. Return: closest source object and seperation (ephem.Angle). If no source found within sep, return None,closest_sep """ last_sep=n.pi closest_src=None for nk,test_src in cat.iteritems(): cursep = ephem.separation(src, test_src) if cursep <= last_sep: last_sep = cursep closest_src = test_src if last_sep<sep * a.img.deg2rad: return closest_src,last_sep else: return None,last_sep
def angles(self): date = ephem.now() bodies = body_computer( date, 'Sun', 'Moon', PLANETS, config.as_list('stars'), config.as_list('asteroids'), config.as_list('comets'), config.as_list('stars', section='separation')) angles = ( Separation(date, a, b, ephem.separation(a, b)) for a, b in itertools.combinations(bodies, 2) ) angles = itertools.filterfalse(lambda x: x.is_two_stars(), angles) angles = filter(lambda x: x.angle < ephem.degrees('20'), angles) return render('angles.html', { 'angles': sorted(angles, key=operator.attrgetter('angle')), })
def check_occultation(b1name, b2name, minsep, closest_date, observer): """Use a more fine-grained time step to check for a lunar occultation. """ # Unfortunately, by the time we get here we only have a name, # not an ephem body. Get the body back: b1 = planets[planets_by_name.index(b1name)] b2 = planets[planets_by_name.index(b2name)] timestep = ephem.hour / 20 # Go from a day earlier to a day later: enddate = closest_date + oneday observer.date = closest_date - oneday while observer.date < enddate: b1.compute(observer) b2.compute(observer) sep = ephem.separation(b1, b2) if sep < minsep: minsep = sep closest_date = observer.date observer.date += timestep return minsep, closest_date
def _separation_angles(katpt_catalogue, target, observer): """Calculate the separation angle between a target. and all the calibrators in the provided catalogue Parameters ---------- katpt_catalogue: katpoint.Catalogue target: ephem.FixedBody observer: ephem.Observer Returns ------- separation_angles: list List of separation angles in radians """ target.compute(observer) separation_angles = [] for calib in katpt_catalogue: calib.body.compute(observer) separation_angles.append(ephem.separation(target, calib.body)) return separation_angles
def magnitude(sat_range, sat_azimuth, sat_altitude, sun_distance, sun_azimuth, sun_altitude): AU = 149597871 # Astronimical Unit (km) STANDARD_MAG = -1.3 # intrinsic brightness of ISS at 1000km # Cannot remember source for this - some suggest it should be lower now (making ISS brighter) # I still find this lines up with how I think it is visually a = sun_distance * AU - ephem.earth_radius # distance sun from observer (Km) b = sat_range / 1000 # distance to ISS from observer (Km) angle_c = ephem.separation((sat_azimuth, sat_altitude), (sun_azimuth, sun_altitude)) c = math.sqrt( math.pow(a, 2) + math.pow(b, 2) - 2 * a * b * math.cos(angle_c)) phase_angle = math.acos( (math.pow(b, 2) + math.pow(c, 2) - math.pow(a, 2)) / (2 * b * c)) # This is the MAGIC equation (Author: Matson, Robert) mag = STANDARD_MAG - 15 + 5 * math.log10( sat_range / 1000) - 2.5 * math.log10( math.sin(phase_angle) + ((math.pi - phase_angle) * math.cos(phase_angle))) return mag
def pointing_crossmatch(pointing, otherpointings, dist_thresh=None): if dist_thresh is None: filtered_pointings = [x for x in otherpointings if ( x.status.name == pointing.status and \ x.instrumentid == int(pointing.instrumentid) and \ x.band.name == pointing.band and \ x.time == pointing.time and \ x.pos_angle == floatNone(pointing.pos_angle) )] for p in filtered_pointings: p_pos = str(geoalchemy2.shape.to_shape(p.position)) if sanatize_pointing(p_pos) == sanatize_pointing( pointing.position): return True else: p_ra, p_dec = sanatize_pointing(pointing.position) filtered_pointings = [x for x in otherpointings if ( x.status.name == pointing.status and \ x.instrumentid == int(pointing.instrumentid) and \ x.band.name == pointing.band )] for p in filtered_pointings: ra, dec == sanatize_pointing( str(geoalchemy2.shape.to_shape(p.position))) sep = 206264.806 * (float( ephem.separation((ra, dec), (p_ra, p_dec)))) if sep < dist_thresh: return True return False
def compute(self): astPos = [[ "KEY", "DATE", "OBS_DATE", "RA", "DEC", "MAG", "PHASE", "EARTH_DIS", "SUN_DIS", "ELONG", "SUN_SEPARATION" ]] for key, value in self.filter_asteroid.iteritems(): try: obs_date = str(convert_date(value[2])) a = self.LoadObject(key) a.compute(self.here) ra = a.a_ra * 180 / (pi) dec = a.a_dec * 180 / pi phang = self.phase_angle(a.elong, a.earth_distance, a.sun_distance) vmag = self.vmag(a._H, a._G, phang, a.earth_distance, a.sun_distance) sun_separation = ephem.separation(self.sun, a) astPos.append((key, str(self.here.date), obs_date, ra, dec, vmag, phang, a.earth_distance, a.sun_distance, a.elong, sun_separation)) except: print key, " fail" return astPos
def factibles(X, obs, actual): "Returns factible points from a list X=[DEC,RA] for the observer. It considers angle distance from the moon and the angle above the horizon." # Parameters dist_moon = 40 * np.pi / 180 above_horizon = 40 * np.pi / 180 #Initialize Moon instance moon = ephem.Moon() moon.compute(obs) #Compute [AZ,ALT] X_obs = np.transpose(np.array(conversion( obs, X[:, 0], X[:, 1]))) #[AZ,ALT] of X for the observer. #One if factible, zero if not I = np.ones(np.size(X, 0)) #Idicates if factible or not. for i in range(0, np.size(I, 0)): if (ephem.separation((X_obs[i, 0], X_obs[i, 1]), (moon.az, moon.alt)) <= dist_moon or X_obs[i, 1] <= above_horizon): #if (X_obs[i,1]<=above_horizon): I[i] = 0 return I
def get_lune(sun, moon): r_sun=sun.size/2 r_moon=moon.size/2 s=math.degrees(ephem.separation((sun.az, sun.alt), (moon.az, moon.alt)))*60*60 ## Calculate the size of the lune (http://mathworld.wolfram.com/Lune.html) in arcsec^2 if s<(r_moon+r_sun): x = (r_sun+r_moon+s)*(r_moon+s-r_sun)*(s+r_sun-r_moon)*(r_sun+r_moon-s) lunedelta=0.25*math.sqrt(abs(x)) else: ### If s>r_moon+r_sun there is no eclipse taking place lunedelta=None percent_eclipse=0 if lunedelta: x = ((r_moon*r_moon)-(r_sun*r_sun)-(s*s)) y = ((r_moon*r_moon)+(s*s)-(r_sun*r_sun)) # Total eclipse if x/(2*r_sun*s) > 1: return 100. else: lune_area=2*lunedelta + r_sun*r_sun*(math.acos(x/(2*r_sun*s))) - r_moon*r_moon*(math.acos(y/(2*r_moon*s))) percent_eclipse=(1-(lune_area/(math.pi*r_sun*r_sun)))*100 # Calculate percentage of sun's disc eclipsed using lune area and sun size return percent_eclipse else: return 0.
def getMoonAngle(jd, target, obs): """Returns the angle between a target and the moon (in radians). :INPUTS: jd : float or 1D numpy array Julian Dates of times target : ephem.star target being observed obs : ephem.Observer observatory with latitude, longitude, and elevation set """ # 2011-09-30 09:56 IJMC: Created from getAirmassAndSunAlt if not hasattr(jd, '__iter__'): jd = [jd] JDwas1D = True else: JDwas1D = False moon = ephem.Moon() njd = len(jd) moonangle = zeros(njd, float) for ii in range(njd): t = jd[ii] obs.date = jd2gd(t) target.compute(obs) moon.compute(obs) moonangle[ii] = ephem.separation(target, moon) if JDwas1D: moonangle = moonangle[0] return moonangle
observer.lon = 0 observer.lat = 0 observer.elevation = -6371000 # center of the earth observer.date = curtimes # minimize refraction: observer.temp = -272 observer.pressure = 0 refbody.compute(observer) nearestdistance = 99999999999999999999999999999 nearestname = '' for body in bodies: try: body.compute(observer) angle = float(repr(ephem.separation(refbody, body))) a = refbody.range b = body.range distance = sqrt(a**2 + b**2 - 2 * a * b * cos(angle)) if distance < nearestdistance: nearestdistance = distance nearestname = body.name except: pass print(nearestdistance, nearestname) nearests.append([nearestdistance, nearestname, curtimes]) curtime += resdelta nearests.sort(key=itemgetter(0), reverse=True) uniquenearest = {}
def separation(self, body1, body2): return ephem.separation(body1, body2)
def logfftdata(flist, plist, longit, decln, rate, srate, pfx, combine): global lastfftlogged global doephem global darkslides global darkcounts global dsinit # # Initialize darkslides to length of plist entries # if (darkslides == None): darkslides = [[-200.0] * len(plist[0])] * COVERAGE decisid = None t = time.gmtime() if (doephem): sid = cur_sidereal(longit, 0)[0] sids = sid.split(",") decisid = float( sids[0]) + float(sids[1]) / 60.0 + float(sids[2]) / 3600.0 else: sid = "??,??,??" if os.path.exists(pfx + "-current_decln.txt"): f = open(pfx + "-current_decln.txt", "r") v = f.readline() v = v.strip("\n") v = float(v) f.close() for i in range(len(decln)): decln[i] = v # # Not time for it yet, buddy # t2 = time.time() if ((t2 - lastfftlogged) < rate): return lastfftlogged = t2 di = 0 # # MUST be 1:1 correspondence between flist and plist # if combine == True and len(plist) == 2: lp1 = linearize(plist[0]) lp2 = linearize(plist[1]) ratio = numpy.sum(lp1) / numpy.sum(lp2) # # If one side is significantly stronger than another, there's a problem # So, we append a message to an "ALERT" file # if (ratio > 2.50 or ratio < (1.0 / 2.5)): f = open(pfx + "-ALERT.txt", "a") f.write("%02d:%02d:%02d: ratio %f\n" % (t.tm_hour, t.tm_min, t.tm_sec, ratio)) f.close() # # We adjust the two sides to be roughly-equal in magnitude # if (ratio < 1.0): lp1 = numpy.multiply(lp1, 1.0 / ratio) else: lp2 = numpy.multiply(lp2, ratio) # # Then compute the linearized average # avg = numpy.add(lp1, lp2) avg = numpy.divide(avg, 2.0) # # Then back into log10 form # newplist = numpy.log10(avg) newplist = numpy.multiply(newplist, 10.0) flist = [flist[0]] plist = [newplist] for x in range(0, len(flist)): # # Construct filename # fn = "%s-%04d%02d%02d-fft-%d.csv" % (pfx, t.tm_year, t.tm_mon, t.tm_mday, x) f = open(fn, "a") # # Determine GMT (UTC) time # gt = "%02d,%02d,%02d" % (t.tm_hour, t.tm_min, t.tm_sec) # # Scale frequency into MHz # fweq = "%g" % (flist[x] / 1.0e6) # # Write header stuff # f.write(gt + "," + sid + "," + fweq + ",") f.write(str(int(srate)) + ",") f.write(str(decln[di]) + ",") if (decisid != None): # # Compute where the Sun currently is # sun = ephem.Sun() sun.compute() # # Figure out our beam pointing--for a transit instrument, it's just # LMST,DEC # beam = ephem.Equatorial(str(decisid), str(decln[di])) # # Suppress dark-slide writing if Sun is too close to our beam # sunbeam = False if (math.degrees( ephem.separation((beam.ra, beam.dec), (sun.ra, sun.dec))) <= 10.0): sunbeam = True # # Compute galactic coordinates of our beam # gp = ephem.Galactic(beam) glat = math.degrees(gp.lat) # # If the galactic latitude of the current observation is outside of # the main galactic plane, we use it as a "cold sky" calibrator # and "dark slide" to remove instrument artifacts. # # We also avoid writing dark-slide data when the Sun is in the beam # # if (sunbeam == False and (glat < -OUTSIDE_GP or glat > OUTSIDE_GP)): # # Form an index into the darkslides array of lists # ndx = int(decln[di]) ndx += int(COVERAGE / 2) # # Pick up the values # vs = darkslides[ndx] # # Initialize # if (dsinit[ndx] == False): dsinit[ndx] = True darkslides[ndx] = copy.deepcopy(plist[x]) # # Add current values in # darkslides[ndx] = numpy.add(darkslides[ndx], plist[x]) darkcounts[ndx] += 1 vs = darkslides[ndx] # # Write out the darkslide file # df = open(pfx + "-darkslide-%02d.csv" % (int(decln[di])), "w") half = len(vs) / 2 half = int(half) full = len(vs) for dx in range(half, full): val = vs[dx] / float(darkcounts[ndx]) df.write("%-6.2f," % val) for dx in range(0, half): val = vs[dx] / float(darkcounts[ndx]) df.write("%-6.2f" % val) if (dx < half - 1): df.write(",") df.write("\n") df.close() # # Reduce occasionally to prevent overflow # if (darkcounts[ndx] >= 20): darkslides[ndx] = numpy.divide(darkslides[ndx], float(darkcounts[ndx])) darkcounts[ndx] = 1 # # Bumpeth the declination index # di += 1 # # Write out the FFT data # half = len(plist[x]) / 2 half = int(half) full = len(plist[x]) y = plist[x] for i in range(half, full): f.write("%-6.2f," % y[i]) for i in range(0, half): f.write("%-6.2f" % y[i]) if (i < half - 1): f.write(",") f.write("\n") f.close()
def data(date): # Necessary lists distances = [] imvis = [] truevis = [] # Check to see if the data has been generated already. # If it has then read it from the file. save = os.path.join(os.path.dirname(__file__), *["data", "eclipse-" + date + ".txt"]) if os.path.isfile(save) and not regen: f = open(save) for line in f: line = line.rstrip().split(",") truevis.append(float(line[0])) imvis.append(float(line[1])) f.close() return (truevis, imvis) # If we're regenerating the data we do it here. directory = os.path.join(os.path.dirname(__file__), *["Images", "Original", "KPNO", date]) images = sorted(os.listdir(directory)) # I need a better way to check this. if ".DS_Store" in images: images.remove(".DS_Store") # Finds the size of the moon in each image. for name in images: print(name) print(date) print(directory) img = image.load_image(name, date, "KPNO") # This basically hacks us to use the center of the earth as our # observation point. camera.elevation = -ephem.earth_radius camera.date = img.formatdate # Calculates the sun and moon positions. moon = ephem.Moon() sun = ephem.Sun() moon.compute(camera) sun.compute(camera) # Finds the angular separation between the sun and the moon. sep = ephem.separation((sun.az, sun.alt), (moon.az, moon.alt)) # Radius of moon orbit to convert angular separation -> distance R = 385000 # For angles this small theta ~ sin(theta), so I dropped the sine # to save computation time. # Angle between moon and earth"s shadow + angle between moon and sun # should ad d to pi, i.e. the earth"s shadow is across from the sun. d = R * (np.pi - sep) size = moon_size(img) imvis.append(size) distances.append(d) print("Processed: " + date + "/" + name) # Calculates the proportion of visible moon for the given distance # between the centers. truevis = eclipse_phase(distances) imvis = np.asarray(imvis) # If the moon is greater than 40,000 pixels then I know that the moon # has merged with the light that comes from the sun and washes out the # horizon. imvis = np.where(imvis < 80000, imvis, float("NaN")) f = open(save, "w") # Writes the data to a file so we can read it later for speed. for i in range(0, len(truevis)): f.write(str(truevis[i]) + "," + str(imvis[i]) + "\n") f.close() return (truevis, imvis)
''' import ephem from datetime import datetime, timedelta curtime = datetime(2018, 7, 27, 15, 0, 0) endtime = datetime(2018, 7, 28, 0, 0, 0) resdelta = timedelta(seconds=60) # resolution moon = ephem.Moon() sun = ephem.Sun() observer = ephem.Observer() observer.elevation = -6371000 # place observer in the center of the Earth observer.pressure = 0 # disable refraction while curtime <= endtime: observer.date = curtime.strftime('%Y/%m/%d %H:%M:%S') # computer the position of the sun and the moon with respect to the observer moon.compute(observer) sun.compute(observer) # calculate separation between the moon and the sun, convert # it from radians to degrees, substract it by 180° sep = abs((float(ephem.separation(moon, sun)) / 0.01745329252) - 180) print(curtime.strftime('%Y/%m/%d %H:%M:%S'), sep) # advance by time interval defined in resdelta curtime += resdelta
def takeImage(site, telescope, imager, exptime, objname, opt='full', frame=(0, 0, 0, 0), filterlam=0): """ Filterlam: options are 780, 823, 860, and 0 (no filter) opt: 'full' or 'sub' if 'sub' then must provide frame=(l,b,r,t) tuple with frame boundaries """ if imager.program == 'maxim': exptypes = { 'DARK': 0, 'BIAS': 0, 'FLAT': 1, } if imager.program == 'theskyX': exptypes = { 'DARK': 3, 'BIAS': 2, 'FLAT': 4, } if objname in exptypes.keys(): exptype = exptypes[objname] else: exptype = 1 # science exposure if str(filterlam) not in imager.filters.keys(): logger.error("Requested filter (" + filterlam + ") not present") return # Take image logger.info("Taking " + str(exptime) + " second image") t0 = datetime.datetime.utcnow() l, b, r, t = frame imager.setFrame(opt, l=l, b=b, r=r, t=t) imager.Expose(exptime, exptype, str(filterlam)) if exptype == 1: # Get status info for headers while exposing/reading out telra = telescope.getRA() teldec = telescope.getDEC() moonpos = site.moonpos() moonra = moonpos[0] moondec = moonpos[1] moonsep = ephem.separation( (telra * math.pi / 180.0, teldec * math.pi / 180.0), moonpos) * 180.0 / math.pi moonphase = site.moonphase() # todo: use moon info or put in header at least # Save the image filename = imager.dataPath + "/" + getIndex( imager.dataPath) + objname + "." + str(filterlam) + ".fits" logger.info('Saving image: ' + filename) imager.saveImage(filename)
def test_github_31(self): position = (4.116325133165859, 0.14032240860186646) self.assertEqual(ephem.separation(position, position), 0.0)
def GetNightlyStrategy(obs, survey_centers, filters, nightfrac=1., minmoonsep=40., optimize_ha=False): """date: UT; if time is not set, the next setting of the sun following start of that date is the start of the plan; awkward when the night starts just before midnight UT, as it does in March in Chile! """ # tonightsplan = OrderedDict() tonightsplan = {} orig_keys = survey_centers.keys() for key in orig_keys: tonightsplan[key] = [] tonightsplan['airmass'] = [] tonightsplan['approx_time'] = [] tonightsplan['approx_datetime'] = [] tonightsplan['moon_sep'] = [] tonightsplan['moon_alt'] = [] tonightsplan['filter'] = [] tonightsplan['exp_time'] = [] tonightsplan['lst'] = [] tonightsplan['ha'] = [] # Get start and end time of night sn = obs.date en = obs.next_rising(ephem.Sun()) lon = (en-sn) * days_to_s * nightfrac # Make sure the Sun isn't up sun.compute(obs) moon.compute(obs) if sun.alt > 0: print 'WARNING: sun is up?!' # Report night start/end times print 'Date: {}'.format(obs.date) print 'Length of night: {} s'.format(lon) print 'Start time of plan (UT): {}'.format(sn) print 'End time of night (UT): {}'.format(en) print 'Plan length: {} hours'.format(lon / 60. / 60.) for f in 'grizY': col = 'used_tile_{:s}'.format(f) survey_centers[col] = ( survey_centers['{:s}_DONE'.format(f.capitalize())].copy()) time_elapsed = 0.0 filterorder = 1 while time_elapsed < lon: start_obsdate = sn + time_elapsed*s_to_days obs.date = start_obsdate if obs.date > en: break sun.compute(obs) moon.compute(obs) # compute derivative of airmass for each exposure airmass = np.zeros((survey_centers['RA'].size, 2), dtype='f8') ha = np.zeros((survey_centers['RA'].size, 2), dtype='f8') moonsep = np.zeros((survey_centers['RA'].size), dtype='f8') for j in range(survey_centers['RA'].size): tile_str = ','.join([ str(survey_centers['TILEID'][j]), 'f', survey_centers['RA_STR'][j], survey_centers['DEC_STR'][j], '20' ]) this_tile = ephem.readdb(tile_str) moon.compute(obs) this_tile.compute(obs) moonsep[j] = ephem.separation((this_tile.az, this_tile.alt), (moon.az, moon.alt))*180./np.pi for k, dt in enumerate((0., s_to_days)): obs.date = start_obsdate + dt this_tile.compute(obs) airmass[j, k] = alt2airmass(float(this_tile.alt)) ha[j, k] = (survey_centers['RA'][j] - np.degrees(obs.sidereal_time()))/15. obs.date = start_obsdate # reset date # Rate of change in airmass^3 (per second) if not optimize_ha: dairmass = airmass[:, 1]**3. - airmass[:, 0]**3. else: dairmass = -(ha[:, 1])*1e-4 # Exclude tiles with terrible airmass exclude = (airmass[:, 0] > 5) | (moonsep < minmoonsep) # Exclude tiles that have been observed before filters_done = np.ones(len(survey_centers['RA']), dtype='bool') for f in filters: filters_done = (filters_done & survey_centers['used_tile_{:s}'.format(f)]) exclude = exclude | filters_done # Bail if there's nothing left to observe if np.all(exclude): print 'Ran out of tiles to observe before night was done!' print 'Minutes left in night: {:5.1f}'.format( (lon-time_elapsed)/60.) break # Determine slew time for each possible exposure if len(tonightsplan['RA']) > 1: slew = slewtime(tonightsplan['RA'][-1], tonightsplan['DEC'][-1], survey_centers['RA'], survey_centers['DEC']) else: slew = 0 # Select tile based on airmass rate of change and slew time nexttile = np.argmax(dairmass - 0.00003*slew - 1.e10*exclude) delta_t, n_exp = pointing_plan( tonightsplan, orig_keys, survey_centers, nexttile, filters[::filterorder], obs ) time_elapsed += delta_t filterorder = -filterorder if len(tonightsplan['RA']) > n_exp: slew = slewtime(tonightsplan['RA'][-1], tonightsplan['DEC'][-1], tonightsplan['RA'][-n_exp-1], tonightsplan['DEC'][-n_exp-1]) time_elapsed += slew if slew > 0: print 'time spent slewing: {:.1f}'.format(slew) numleft = np.sum(exclude == 0) print 'Plan complete, {:d} observations, {:d} remaining.'.format( len(tonightsplan['RA']), numleft) if np.any(np.abs(tonightsplan['ha']) > 5.25): print('************************************************') print('WARNING: some hour angles impossible to observe!') print('************************************************') if not optimize_ha: print('Consider rerunning with optimize_ha!') keys = tonightsplan.keys() return np.rec.fromarrays([tonightsplan[k] for k in keys], names=keys)
def process_gcn(payload, root): if write_event: event_log = open(logfile, 'a+') # Respond only to 'test' events. # VERY IMPORTANT! Replace with the following code # to respond to only real 'observation' events. print("starting process") print(datetime.utcnow()) if write_event: event_log.write("starting process") event_log.write('\n') event_log.write(root.attrib['role']) event_log.write('\n') print(root.attrib['role']) """ Uncomment when we only want to do real observations if root.attrib['role'] != 'observation': return """ # Read all of the VOEvent parameters from the "What" section. params = {elem.attrib['name']: elem.attrib['value'] for elem in root.iterfind('.//Param')} # Respond only to 'CBC' events. Change 'CBC' to "Burst' # to respond to only unmodeled burst events. print(params['Group']) if write_event: event_log.write(params['Group']) event_log.write('\n') if params['Group'] != 'CBC': print('not CBC') return if params['AlertType'] != 'Preliminary': print('not Preliminary') return if 'Pkt_Ser_Num' in params: # Test events send same event twice, only choose first one. check = float(params['Pkt_Ser_Num']) if check > 1.1: return """ COMPLETE TO DEFINE WHICH EVENTS WE ARE LOOKING FOR if 'BNS' in params: check = float(params['BNS']) if check < 50.0: print("not BNS event, skipping") return else: print("not BNS event, skipping") return """ # Print all parameters. for key, value in params.items(): print(key, '=', value) if write_event: event_log.writelines(str(key + '=' + value)) if 'skymap_fits' in params: # Read the HEALPix sky map and the FITS header.i skymap, header = hp.read_map(params['skymap_fits'], h=True, verbose=False) header = dict(header) # Print some values from the FITS header. print('Distance =', header['DISTMEAN'], '+/-', header['DISTSTD']) if write_event: event_log.writelines('Distance =' + str(header['DISTMEAN']) + '+/-' + str(header['DISTSTD'])) event_log.write('\n') # write event information to SQL datadict = {'gracedb_id': [params['GraceID']], 'link': [params['EventPage']], 'dist': [header['DISTMEAN']], 'dist_err': [header['DISTSTD']]} sql_engine = sql.create_engine(connect_string) headers = ['gracedb_id', 'link', 'dist', 'dist_err'] dtypes = {'gracedb_id': 'str', 'link': 'str', 'dist': 'float64', 'dist_err': 'float64'} df = pd.DataFrame.from_dict(datadict) df.to_sql('events', sql_engine, if_exists='append', index=False) # get event ID back query = "select * from events ORDER BY 'ID' DESC" df = pd.read_sql_query(query, sql_engine) event = df['ID'].iloc[-1] credible_levels = find_greedy_credible_levels(skymap) if send_slack: slackmsg = "" for key, value in params.items(): slackmsg = slackmsg + str(key) + '=' + str(value) + '\n' slack_client.chat_postMessage(channel=SLACK_CHANNEL, text=slackmsg) # get df of galaxies from SQL query = "select * from galaxies" galaxies = pd.read_sql_query(query, sql_engine) gal_ipix = getPixel(skymap, galaxies['ra'], galaxies['dec']) """ offset = ephem.Observer() offset.lat = '0.0' offset.long = '180' offset.date = datetime.utcnow() offangle = float(offset.sidereal_time() * 180 / np.pi) """ if plot_map: #ax = plt.axes(projection=ccrs.Mollweide(central_longitude=-1 * offangle)) ax = plt.axes(projection=ccrs.Mollweide()) ax.stock_img() galaxies['credible'] = credible_levels[gal_ipix] banana_galaxies = galaxies[(galaxies.credible <= prob_check)] banana_galaxies.sort_values(by=['credible'], inplace=True) #get list of observatories from SQL query = "select * from observers" observatories = pd.read_sql_query(query, sql_engine) #Find Sun RA/DEC sun = ephem.Sun() #setup pyephem observer telescope = ephem.Observer() telescope.date = datetime.utcnow() #create a copy of galaxy list in case it ends up depleted galaxy_list = copy.deepcopy(banana_galaxies) galaxy_list = galaxy_list.values.tolist() galaxy_depleted = False slackmsg = '' matches = [] slack_count = 0 for x in range(0, len(observatories)): extra_matches = [] # Check if all galaxies have been assigned, if so start assigning duplicates if len(galaxy_list) == 0: galaxy_list = copy.deepcopy(banana_galaxies) galaxy_list = galaxy_list.values.tolist() galaxy_depeleted = True telescope.lat = str(observatories['lat'][x]).strip() telescope.long = str(observatories['lon'][x]).strip() sun.compute(telescope) # if sun is up, observatory can be skipped if check_sun: if sun.alt > max_sun: # print(str(observatories['Code'][x]) + " skipped, Sun is up") continue for i in range(0, len(galaxy_list)): star = ephem.FixedBody() star._ra = ephem.degrees(str(galaxy_list[i][2])) star._dec = ephem.degrees(str(galaxy_list[i][3])) star.compute(telescope) # if the first object is more than 20 degrees below elevation, unlikely any objects will be higher than 45 degrees if check_minalt: if star.alt < min_alt: # print(str(observatories['Code'][x]) + " skipped " + str(star.alt) + " is less than -20 degrees") break # assign galaxy to observer if star.alt > max_alt: matches.append( {'event_id': event, 'obs_ID': observatories['ID'][x], 'galaxy_id': galaxy_list[i][0]}) # print(galaxy_list[i]) listing = WEBSITE_URL+'/observe?key=' + str( observatories['key'][x]) + '&event=' + str(event) + '&obs=' + str( observatories['ID'][x]) + '&gal=' + str(galaxy_list[i][0]) + '&ra=' + str( galaxy_list[i][2]) + '&dec=' + str(galaxy_list[i][3]) + '&fov=' + str(observatories['fov'][x]) print(listing) if write_event: event_log.writelines(listing) event_log.write('\n') #only writing the first 5 urls to slack if send_slack: if slack_count < 5: slack_count += 1 slackmsg = slackmsg + listing + '\n' #find extra galaxies within FOV j = i+1 y = [] print(len(galaxy_list[j:])) if galinfov: for z in range(j,len(galaxy_list)): extra = ephem.FixedBody() extra._ra = ephem.degrees(str(galaxy_list[z][2])) extra._dec = ephem.degrees(str(galaxy_list[z][3])) extra.compute(telescope) sep = float(ephem.separation(star,extra))*180/np.pi if sep < 0.5/2: #if sep < observatories['fov'][x]/2: extra_matches.append({'event_id': event, 'obs_ID': observatories['ID'][x], 'galaxy_id': galaxy_list[z][0]}) print(z,sep,ephem.separation(star,extra)) y.append(z) if len(y)>1: print(y) y.reverse() for k in y: del galaxy_list[k] # print(str(observatories['ID'][x]) + " " + observatories['name'][x].strip()[15:] + " at Lat:" +str(telescope.lat) + ",Lon:" + str(telescope.lon) + " gets galaxy " + str(galaxy_list[i][1]) + ' ra='+str(star.ra) + ' dec=' + str(star.dec) + ' alt='+str(star.alt)) del galaxy_list[i] if plot_map: plt.scatter(telescope.lon * 180 / np.pi, telescope.lat * 180 / np.pi, color='red', transform=ccrs.Geodetic()) break if len(extra_matches) > 0: extra_matches = pd.DataFrame(extra_matches) extra_matches.to_sql('matches_extra', sql_engine, if_exists='append', index=False) matches = pd.DataFrame(matches) matches.to_sql('matches', sql_engine, if_exists='append', index=False) event_log.close() if send_slack: if len(slackmsg) > 0: slack_client.chat_postMessage(channel=SLACK_CHANNEL, text=slackmsg) if galaxy_depleted: text = "All" + str(len(banana_galaxies)) + " galaxies assigned" query = "update events set assigned = " + str(len(banana_galaxies)) + ", possible = " + str( len(banana_galaxies)) + " where ID = " + str(event) else: text = str(len(banana_galaxies) - len(galaxy_list)) + " galaxies assigned out of " + str( len(banana_galaxies)) query = "update events set assigned = " + str( len(banana_galaxies) - len(galaxy_list)) + ", possible = " + str( len(banana_galaxies)) + " where ID = " + str(event) slack_client.chat_postMessage(channel=SLACK_CHANNEL, text=text) sql_engine.execute(query) else: slack_client.chat_postMessage(channel=SLACK_CHANNEL, text="No Galaxies Assigned") if plot_map: ax.add_feature(Nightshade(datetime.utcnow(), alpha=0.2)) plt.title("Map of Observable Sites") plt.savefig("map.png") if send_slack: slack_client.files_upload(channels=SLACK_CHANNEL, file="map.png", title=params['GraceID']) filename = download_file(params['skymap_fits'], cache=True) skyplot([filename, '--annotate', '--geo', '--contour', '50', '90']) plt.savefig("hp.png") if send_slack: slack_client.files_upload(channels=SLACK_CHANNEL, file="hp.png", title=params['GraceID']) return
print(text, end='\r') observer.date = (str(text)) sun = ephem.Sun(observer) sdo = ephem.readtle(lines[0], lines[1], lines[2]) try: sdo.compute(observer) observer.lat = sdo.sublat observer.lon = sdo.sublong observer.elevation = sdo.elevation moon = ephem.Moon(observer) sun = ephem.Sun(observer) moonlon, moonlat, E = equatorial_to_ecliptic( moon.ra, moon.dec, observer) sunlon, sunlat, E = equatorial_to_ecliptic(sun.ra, sun.dec, observer) separation = ephem.separation((sunlon, sunlat), (moonlon, moonlat)) sunsize = int(((sun.radius) * 180 / math.pi) * 1506) moonsize = int(((moon.radius) * 180 / math.pi) * 1506) posangle = position_angle(sunlon, sunlat, moonlon, moonlat) moonyangle = (moonlat - sunlat) moonxangle = (moonlon - sunlon) * math.cos(moonyangle) moonx = int(512 - (moonxangle * 180 / math.pi) * 1506) moony = int(512 - (moonyangle * 180 / math.pi) * 1506) img = vidframe cv2.circle(img, (512, 512), sunsize, (0, 0, 255), 2) cv2.putText(img, 'Sun', (460, 512), font, 2, (0, 0, 255), 2, cv2.LINE_AA) cv2.circle(img, (moonx, moony), moonsize, (255, 0, 0), 2) cv2.putText(img, 'Moon', ((moonx - 74), moony), font, 2, (255, 0, 0), 2, cv2.LINE_AA) cv2.putText(img, str(observer.date), (0, 50), font, 1, (0, 0, 255),
t = ephem.now() s1 = satlist["DIAMOND RED"] s1.compute(t) s2 = satlist["DIAMOND GREEN"] s2.compute(t) s3 = satlist["DIAMOND BLUE"] s3.compute(t) #s4 = satlist["GOMX-4A"] #s4.compute(t) #s5 = satlist["GOMX-4B"] #s5.compute(t) print ("Distance RED<->GREEN") print ("Arc: {:.1f}km".format(ephem.separation(s1, s2) * (s2.elevation + ephem.earth_radius) / 1000)) print ("Chord: {:.1f}km".format(math.sin(ephem.separation(s1, s2)/2)*2*(s2.elevation + ephem.earth_radius) / 1000)) print ("") print ("Distance GREEN<->BLUE") print ("Arc: {:.1f}km".format(ephem.separation(s2, s3) * (s2.elevation + ephem.earth_radius) / 1000)) print ("Chord: {:.1f}km".format(math.sin(ephem.separation(s2, s3)/2)*2*(s2.elevation + ephem.earth_radius) / 1000)) print ("") print ("Distance RED<->BLUE") print ("Arc: {:.1f}km".format(ephem.separation(s1, s3) * (s1.elevation + ephem.earth_radius) / 1000)) print ("Chord: {:.1f}km".format(math.sin(ephem.separation(s1, s3)/2)*2*(s1.elevation + ephem.earth_radius) / 1000)) antenna = ephem.Observer() antenna.lat = '56.769043' antenna.lon = '9.856832' antenna.elevation = 72
import ephem def hpos(body): return body.hlon, body.hlat gatech = ephem.Observer() gatech.lon, gatech.lat = '-84.39733', '33.775867' gatech.date = '1984/5/30 16:22:56' # 12:22:56 EDT sun, moon = ephem.Sun(), ephem.Moon() sun.compute(gatech) moon.compute(gatech) print("%s %s" % (sun.alt, sun.az)) print("%s %s" % (moon.alt, moon.az)) print(ephem.separation((sun.az, sun.alt), (moon.az, moon.alt))) print("%.8f %.8f %.11f" % (sun.size, moon.size, sun.size - moon.size)) gatech.date = '1984/5/31 00:00' # 20:00 EDT sun.compute(gatech) for i in range(8): old_az, old_alt = sun.az, sun.alt gatech.date += ephem.minute * 5. sun.compute(gatech) sep = ephem.separation((old_az, old_alt), (sun.az, sun.alt)) print("%s %s %s" % (gatech.date, sun.alt, sep)) print(gatech.next_setting(sun)) print("%s %s" % (sun.alt, sun.az))
def XML_generator_Mode2(root, date, duration, relativeTime, params=Mode2_default()): "Generates parameters and calls for macros, which will generate commands in the XML-file" from MATS_TIMELINE_macros import IR_night, IR_day "Load parameters from config function" params_default = Mode2_default() "Check if optional params were given" if (params != params_default): params_new = params_default "Loop through parameters given and exchange them for the default ones" for key in params.keys(): params_new[key] = params[key] params = params_new Sun = ephem.Sun(date) MATS = ephem.readtle('MATS', getTLE()[0], getTLE()[1]) "Pre-allocate space" sun_angle = zeros((duration, 1)) R_mean = 6371 pointing_altitude = str(params['pointing_altitude']) #Estimation of the angle between the sun and the FOV position when it enters eclipse MATS_nadir_eclipse_angle = arccos(R_mean / (R_mean + 90)) / pi * 180 + 90 "Loop and calculate the relevant angle of each star to each direction of MATS's FOV" for t in range(duration): current_time = ephem.Date(date + ephem.second * t) MATS.compute(current_time) Sun.compute(current_time) sun_angle[t] = ephem.separation(Sun, MATS) / pi * 180 ############# Initial Mode setup ########################################## if (t == 0): "Check if night or day" if (sun_angle[t] > MATS_nadir_eclipse_angle): current_state = "IR_night" IR_night(root, str(t + relativeTime), pointing_altitude) elif (sun_angle[t] < MATS_nadir_eclipse_angle): current_state = "IR_day" IR_day(root, str(t + relativeTime), pointing_altitude) ############# End of Initial Mode setup ################################### if (t != 0): ####################### SCI-mode Operation planner ################ #Check if night or day if (sun_angle[t] > MATS_nadir_eclipse_angle and current_state != "IR_night"): #Check dusk/dawn boundaries and if NLC is active if ((sun_angle[t] > MATS_nadir_eclipse_angle and sun_angle[t - 1] < MATS_nadir_eclipse_angle) or current_state == "NLC_night"): IR_night(root, str(t + relativeTime), pointing_altitude) current_state = "IR_night" #Check if night or day if (sun_angle[t] < MATS_nadir_eclipse_angle and current_state != "IR_day"): #Check dusk/dawn boundaries and if NLC is active if ((sun_angle[t] < MATS_nadir_eclipse_angle and sun_angle[t - 1] > MATS_nadir_eclipse_angle) or current_state != "NLC_day"): IR_day(root, str(t + relativeTime), pointing_altitude) current_state = "IR_day"
print(ephem.degrees(ephem.degrees('90') - polaris.a_dec)) polaris.compute(epoch='2100') print(polaris.a_dec) thuban = ephem.readdb("Thuban,f|V|A0,14:4:23.3,64:22:33,3.65,2000") thuban.compute() print(thuban.a_dec) print(thuban.a_dec) polaris.compute(epoch='-2800') print(polaris.a_dec) j = ephem.Jupiter() j.compute(epoch=ephem.now()) # so both date and epoch are now print("%s %s" % (j.a_ra, j.a_dec)) j.compute('2003/3/25', epoch='2003/3/25') print("%s %s" % (j.a_ra, j.a_dec)) j1, j2 = ephem.Jupiter(), ephem.Jupiter() j1.compute('2003/3/1') j2.compute('2003/4/1') print(ephem.separation((j1.a_ra, j1.a_dec), (j2.a_ra, j2.a_dec))) # coordinates are both epoch 2000 j1.compute('2003/3/1', '2003/3/1') j2.compute('2003/4/1', '2003/4/1') print(ephem.separation( (j1.a_ra, j1.a_dec), (j2.a_ra, j2.a_dec))) # coordinates are both epoch-of-date
def compute_contacts(self): import ephem import math from operator import itemgetter observer = ephem.Observer() observer.lat = str(self.latitude) observer.lon = str(self.longitude) time = (2017, 8, 21, 15, 40, 00) observer.date = time sun = ephem.Sun() moon = ephem.Moon() results = [] #5 hs = 18000 for x in range (0,18000): QtCore.QCoreApplication.processEvents() observer.date = (ephem.date(ephem.date(time) + x * ephem.second)) sun.compute(observer) moon.compute(observer) r_sun = sun.size/2 r_moon = moon.size/2 s = math.degrees(ephem.separation((sun.az, sun.alt), (moon.az, moon.alt)))*60*60 #Calculate the size of the lune if s <= (r_moon+r_sun): #only under totality. NO lune if r_moon >= (s+r_sun): lunedelta = 'small' else: lunedelta = 0.25 * math.sqrt((r_sun+r_moon+s)*(r_moon+s-r_sun)*(s+r_sun-r_moon)*(r_sun+r_moon-s)) #If s>r_moon+r_sun there is no eclipse taking place else: lunedelta = None if lunedelta: #Only under totality. NO lune if r_moon >= (s + r_sun): lune_area = 0 percent_eclipse = 100 else: lune_area = 2*lunedelta + (r_sun*r_sun * math.acos(( (r_moon*r_moon) - (r_sun*r_sun) - (s*s)) / (2*r_sun*s) )) - (r_moon*r_moon * math.acos(( (r_moon*r_moon) + (s*s) - (r_sun*r_sun)) / (2*r_moon*s))) percent_eclipse = (1-(lune_area/(math.pi*r_sun*r_sun)))*100 else: lune_area = None percent_eclipse = 0 # Append to list of lists: results.append([observer.date.datetime(), s, sun.size,moon.size, lune_area, percent_eclipse]) gen=(x for x in results) #Find Max percentage of eclipse... max_eclipse = max(gen, key=itemgetter(5)) gen=(x for x in results) tc1 = next(x for x in gen if self.check_non_zero(x[5]))[0] self.tc2 = next(x for x in gen if x[5] >= (max_eclipse[5] - 0.0001*max_eclipse[5]))[0] self.tc3 = next(x for x in gen if x[5] < (max_eclipse[5] - 0.0001*max_eclipse[5]))[0] tc4 = next(x for x in gen if x[5] == 0)[0] totality = self.tc3 - self.tc2 mid_eclipse = self.tc2 + (totality)/2 gen=(x for x in results) max_part_eclipse = next(x for x in gen if x[5] == (max_eclipse[5]))[0] if __name__ == '__main__': output = [] gen=(x for x in results) if max_eclipse[5] == 100: output = str("\nMax percent: " + '%.2f' % max_eclipse[5]) + \ str("\nMax eclipse at: " + str(mid_eclipse)) + str("\nDuration of totality: " + str(self.tc3-self.tc2)) + \ str("\n\nFirst contact: " + str(next(x for x in gen if self.check_non_zero(x[5]))[0])) + \ str("\nSecond contact: " + str(self.tc2)) + str("\nThird contact: " + str(self.tc3)) + \ str("\nLast contact: " + str(next(x for x in gen if x[5] == 0)[0]) + "\n") else: output = "\nMax percent: " + '%.2f' % max_eclipse[5] + \ str("\nMax eclipse at: " + str(max_part_eclipse)) + str("\nNo totality\n") self.te.append(output)
# -*- coding: utf-8 -*- """ Created on Tue Jan 7 21:34:36 2020 https://rhodesmill.org/pyephem/tutorial.html#first-steps @author: PC """ import ephem u = ephem.Uranus() u.compute('1781/3/13') print('%s %s %s' % (u.ra, u.dec, u.mag)) print(ephem.constellation(u)) j = ephem.Jupiter('1612/12/28') n = ephem.Neptune('1612/12/28') print("%s %s %s" % (j.ra, j.dec, j.mag)) print("%s %s %s" % (n.ra, n.dec, n.mag)) print(ephem.separation(j, n)) def hpos(body): return body.hlon, body.hlat ma0 = ephem.Mars('1976/05/21') # ma: mars near aphelion ma1 = ephem.Mars('1976/05/22') print(ephem.separation(hpos(ma0), hpos(ma1))) mp0 = ephem.Mars('1975/06/13') # mp: mars near perihelion mp1 = ephem.Mars('1975/06/14') print(ephem.separation(hpos(mp0), hpos(mp1)))
text(0.1, 0.85, srcname, size=8, weight='normal', transform=ax.transAxes) catstr += srcname + '\t' + str(n.max(spec['n_Seq'])) + '\t' catstr += str(i % m1) + '\t' + str( int(i) / int(m1)) + '\t' + str(curfig) VO.data['col'][n.where(VO.data['Seq'] == seq)[0]] = i % m1 + 1 VO.data['row'][n.where( VO.data['Seq'] == seq)[0]] = int(i) / int(m1) + 1 VO.data['fig'][n.where(VO.data['Seq'] == seq)[0]] = curfig if not opts.time is None: src.compute(aa) VO.data['sun_sep'] = ep.separation(src, sun) VO.data['transit'] = aa.next_transit(src).tuple()[3] if (i % m1) and opts.plot: yticks([]) if ((m2 - 1) * m1 > (i % nsub + (m2 * m1 - nsub))) and opts.plot: xticks([]) if opts.plot: draw() print catstr # print VO.data['Seq'],VO.data['logL_cat'] T.append(VO) except (KeyboardInterrupt): sys.exit() T.write('test.vot') print '# sources with no match' for catstr in notfound:
def m31_plotMoonForGC(): """ This will plot distance/illumination of moon for one specified month """ from pyraf import iraf iraf.noao() iraf.noao.obsutil() obs = iraf.noao.observatory # coordinates to Orion source n from Gomez et al. 2005 (J2000) ra = "17:45:40.0" dec = "-29:00:28.0" # Setup Object obj = ephem.FixedBody() obj._ra = ephem.hours(ra) obj._dec = ephem.degrees(dec) obj._epoch = 2000 obj.compute() # Setup dates of observations months = np.array([8, 9]) days = np.array([1]) years = np.zeros(len(days)) + 2010 sym = ['rD', 'bD'] colors = ['r', 'b'] labels = ['Aug', 'Sep'] daysInMonth = np.arange(31) # Setup the observatory info obs(command="set", obsid="keck") keck = ephem.Observer() keck.long = -obs.longitude keck.lat = obs.latitude moondist = np.zeros(len(daysInMonth), dtype=float) moonillum = np.zeros(len(daysInMonth), dtype=float) moon = ephem.Moon() py.clf() for mm in range(len(months)): for dd in daysInMonth: # Set the date and time to midnight keck.date = '%d/%d/%d %d' % (years[0], months[mm], days[0] + dd, obs.timezone) moon.compute(keck) obj.compute(keck) sep = ephem.separation((obj.ra, obj.dec), (moon.ra, moon.dec)) sep *= 180.0 / math.pi moondist[dd] = sep moonillum[dd] = moon.phase print 'Day: %2d Moon Illum: %4.1f Moon Dist: %4.1f' % \ (dd, moonillum[dd], moondist[dd]) py.plot(daysInMonth, moondist, sym[mm], label=labels[mm]) for dd in daysInMonth: py.text(dd + 0.45, moondist[dd] - 2, '%2d' % moonillum[dd], color=colors[mm]) py.plot([0, 31], [30, 30], 'k') py.legend(loc=2, numpoints=1) py.title('Moon distance and % Illumination') py.xlabel('Date (UTC)', fontsize=14) py.ylabel('Moon Distance (degrees)', fontsize=14) py.axis([0, 31, 0, 180]) py.savefig('m31_gc_moondist.ps') py.savefig('m31_gc_moondist.png')
help='Selection criteria for source distance from phase center. [5 degrees]') o.add_option('-v',dest='verb',action='store_true', help='Print more') opts, args = o.parse_args(sys.argv[1:]) opts.sep *= a.img.deg2rad def update_pos(c): date=ephem.J2000 for s in c.keys(): try: ephem.FixedBody.compute(c[s], date) except(TypeError): if opts.juldate is None: del(c[s]) else: ephem.Body.compute(c[s], date) srcs,coff,catalogs = a.scripting.parse_srcs(opts.src,opts.cat) cat = a.src.get_catalog(srcs=srcs,catalogs=catalogs) update_pos(cat) for file in args: data,kwds = a.img.from_fits(file) center = a.phs.RadioFixedBody(kwds['ra']*n.pi/180, kwds['dec']*n.pi/180) ephem.FixedBody.compute(center,ephem.J2000) for name,src in cat.iteritems(): cursep = ephem.separation(src,center) if cursep<opts.sep: if opts.verb: print src.src_name, if opts.verb: print "%2.2f"%(cursep/a.img.deg2rad,), print file continue
def visibility(self, multiple=False, midnight=None, airmassmodel='Pickering2002', **kwargs): """ Calculate ephemeri. *If 'multiple' = False, a single site definition and startdate (and/or values for the days and dt keywords) are expected. If one (or more) of these keywords is not given a value, it is assumed that it should not change its current value. If several astrophysical objects are given, ephemeri will be given for each object at the defined site and times. If 'midnight' is not None, ephemeri are calculated in the middle of each night, for the whole year. *If 'multiple' = True, a list/array of site names and startdates can be given. Note: the length of keywords 'sitename', 'startdate' and 'objects' can be either N or 1 and should be in the same format as previously. In this case, ephemeri are only calculated at the times given in 'startdate', and thus the keywords 'days', 'dt' and 'midnight' are not used. Sites are currently only accessible throught the keyword 'sitename'. The result of this function is an attribute 'vis', a dictionary containing: - MJDs: Modified Julian Dates - dates calendar dates (Format 1) - alts: altitudes - moon_alts: altitudes of the moon - airmass - moon_airmass: airmasses of the moon - moon_separation: separation to moon - during_night: night time / day time (boolean 1-0) - sun_prevrise: time of previous sun rise - sun_nextrise: time of next sun rise - sun_prevset: time of previous sun set - sun_nextset: time of next sun set NOTE: use the 'get_out_objects', 'get_out_objectnames', 'get_out_sites' and 'get_out_sitenames' functions to retrieve the object, name of the object, site and name of the site corresponding to a particular row in each of the arrays 'vis' contains. """ #-- if no values are given for these keywords, this means nothing should change --> None kwargs.setdefault('sitename', None) kwargs.setdefault('startdate', None) kwargs.setdefault('dt', None) kwargs.setdefault('days', None) #-- set optional additional keywords sun = ephem.Sun() moon = ephem.Moon() #moon_theta = 34.1 # minutes if not multiple: #-- set the site, date and objects self.set_site(**kwargs) self.set_date(**kwargs) self.set_objects(**kwargs) #-- set stuff for calculations timestep_minutes = self.dt total_days = self.days if midnight is None: total_minutes = int(total_days * 24 * 60. / timestep_minutes) else: total_minutes = 365 #-- set initial arrays alts = np.zeros((len(self.objects), total_minutes)) rawdates = np.zeros(total_minutes) during_night = np.zeros(total_minutes, int) moon_separation = np.zeros((len(self.objects), total_minutes)) moon_alts = np.zeros(total_minutes) sun_prevrise = np.zeros(total_minutes) sun_prevset = np.zeros(total_minutes) sun_nextrise = np.zeros(total_minutes) sun_nextset = np.zeros(total_minutes) #-- run over all timesteps if midnight is None: for i in range(total_minutes): sun_prevset[i] = float(self.thesite.previous_setting(sun)) sun_prevrise[i] = float(self.thesite.previous_rising(sun)) sun_nextset[i] = float(self.thesite.next_setting(sun)) sun_nextrise[i] = float(self.thesite.next_rising(sun)) rawdates[i] = float(self.thesite.date) #-- compute the moon position moon.compute(self.thesite) moon_alts[i] = float(moon.alt) if (sun_prevrise[i] <= sun_prevset[i]): during_night[i] = 1 for j, star in enumerate(self.objects): star.compute(self.thesite) alts[j, i] = float(star.alt) moon_separation[j, i] = ephem.separation(moon, star) self.thesite.date += ephem.minute * timestep_minutes else: i = 0 while i < 365: sun_nextrise[i] = float(self.thesite.next_rising(sun)) sun_prevset[i] = float(self.thesite.previous_setting(sun)) sun_prevrise[i] = float(self.thesite.previous_rising(sun)) sun_nextset[i] = float(self.thesite.next_setting(sun)) if sun_prevrise[i] <= sun_prevset[ i]: # now we're in a night self.thesite.date = ephem.Date( (sun_nextrise[i] + sun_prevset[i]) / 2.) else: #-- set 4 hours forwards self.thesite.date += ephem.minute * 60 * 4 continue rawdates[i] = float(self.thesite.date) during_night[i] = 1 for j, star in enumerate(self.objects): star.compute(self.thesite) alts[j, i] = float(star.alt) i += 1 #-- set 1 day forwards self.thesite.date += ephem.minute * 60 * 24 alts = alts.ravel() rawdates = np.outer(np.ones(len(self.objects)), rawdates).ravel() during_night = np.outer(np.ones(len(self.objects), int), during_night).ravel() moon_separation = moon_separation.ravel() # moon_alts = np.outer(np.ones(len(self.objects)), moon_alts).ravel() sun_nextrise = np.outer(np.ones(len(self.objects)), sun_nextrise).ravel() sun_prevrise = np.outer(np.ones(len(self.objects)), sun_prevrise).ravel() sun_nextset = np.outer(np.ones(len(self.objects)), sun_nextset).ravel() sun_prevset = np.outer(np.ones(len(self.objects)), sun_prevset).ravel() self._objectIndices = np.outer(np.arange(len(self.objects)), np.ones(total_minutes)).ravel() self._siteIndices = np.zeros_like(alts) self._uniqueSites = [self.thesite] else: startdate = kwargs.get('startdate', None) sitename = kwargs.get('sitename', 'lapalma') objects = kwargs.get('objects', None) if objects is None: objects = self.get_objectnames() # the other option is to iterate over given 'dates' and/or sites and objects if not type(startdate) == np.ndarray: startdate = np.array([startdate]) if not type(sitename) == np.ndarray: sitename = np.array([sitename]) if not type(objects) == np.ndarray: objects = np.array([objects]).ravel() uniqueObjectNames = np.unique(objects) uniqueSiteNames = np.unique(sitename) self.set_objects(uniqueObjectNames) self._objectIndices = np.zeros_like(objects, int) self._siteIndices = np.zeros_like(sitename, int) self._uniqueSites = [] for i in range(len(uniqueObjectNames)): self._objectIndices = np.where(objects == uniqueObjectNames[i], i, self._objectIndices) for i in range(len(uniqueSiteNames)): self._siteIndices = np.where(sitename == uniqueSiteNames[i], i, self._siteIndices) self.set_site(uniqueSiteNames[i]) self._uniqueSites.append(self.thesite) #-- define the iterator it = np.broadcast(startdate, self._siteIndices, self._objectIndices) #-- set initial arrays alts = np.zeros(it.shape[0]) rawdates = np.zeros(it.shape[0]) during_night = np.zeros(it.shape[0], int) moon_separation = np.zeros(it.shape[0]) moon_alts = np.zeros(it.shape[0]) sun_prevrise = np.zeros(it.shape[0]) sun_prevset = np.zeros(it.shape[0]) sun_nextrise = np.zeros(it.shape[0]) sun_nextset = np.zeros(it.shape[0]) #-- run over all elements for i, element in enumerate(it): #-- set the site and date self.thesite = self._uniqueSites[element[1]] self.set_date(startdate=element[0], days=None, dt=None) #-- determine whether the time corresponds to night or day sun_prevset[i] = float(self.thesite.previous_setting(sun)) sun_prevrise[i] = float(self.thesite.previous_rising(sun)) sun_nextset[i] = float(self.thesite.next_setting(sun)) sun_nextrise[i] = float(self.thesite.next_rising(sun)) if (sun_prevrise[i] <= sun_prevset[i]): during_night[i] = 1 rawdates[i] = float(self.thesite.date) #-- compute the moon position moon.compute(self.thesite) moon_alts[i] = float(moon.alt) #-- compute the star's position star = self.objects[element[2]] star.compute(self.thesite) alts[i] = float(star.alt) moon_separation[i] = ephem.separation(moon, star) #-- calculate airmass airmass = obs_airmass.airmass(90 - alts / pi * 180, model=airmassmodel) moon_airmass = obs_airmass.airmass(90 - moon_alts / pi * 180, model=airmassmodel) #-- calculate dates for plotting and output self._plotdates = np.array( [date2num(ephem.Date(h).datetime()) for h in rawdates]) self._sun_prevset = np.array( [date2num(ephem.Date(h).datetime()) for h in sun_prevset]) self._sun_prevrise = np.array( [date2num(ephem.Date(h).datetime()) for h in sun_prevrise]) self._sun_nextset = np.array( [date2num(ephem.Date(h).datetime()) for h in sun_nextset]) self._sun_nextrise = np.array( [date2num(ephem.Date(h).datetime()) for h in sun_nextrise]) dates = np.array([str(ephem.Date(h).datetime()) for h in rawdates]) MJDs = rawdates + 15019.499999 # the zeropoint of ephem is 1899/12/31 12:00:00.0 15019.499585 #-- the output dictionary self.vis = dict(MJDs=MJDs, dates=dates, alts=alts, airmass=airmass, during_night=during_night, moon_alts=moon_alts, moon_airmass=moon_airmass, moon_separation=moon_separation) self.vis.update( dict(sun_prevrise=np.array(num2date(self._sun_prevrise), dtype='|S19'), sun_prevset=np.array(num2date(self._sun_prevset), dtype='|S19'), sun_nextrise=np.array(num2date(self._sun_nextrise), dtype='|S19'), sun_nextset=np.array(num2date(self._sun_nextset), dtype='|S19'))) for i, obj in enumerate(self.objects): keep = (self._objectIndices == i) & (during_night == 1) & ( 0 <= airmass) & (airmass <= 2.5) logger.info( 'Object %s: %s visible during night time (%.1f<airmass<%.1f)' % (obj.name, ~np.any(keep) and 'not' or '', sum(keep) and airmass[keep].min() or np.nan, sum(keep) and airmass[keep].max() or np.nan))
def run(start, end, observer, toolate, output_format): """Find planetary visibility between dates start and end, for an observer whose location has been set, between sunset and "toolate" on each date, where toolate is a GMT hour, e.g. toolate=7 means we'll stop at 0700 GMT or midnight MDT. toolate==None means look for anything between sunset and sunries. """ global visible_planets, saw_conjunction d = start conjunctions = ConjunctionList() if output_format == "csv": print('name,start,end,time,longname,URL,' 'image,image width,image height,image credit') elif output_format == "sql": print("INSERT INTO peecnatu_guides_dev.astronomy(common_name, " "guide_group, visibility, start, end, comments, image, " "image_width, image_height, image_credit) VALUES") else: print("Looking for planetary events between %s and %s:\n" % \ (datestr(d), datestr(end))) def check_if_planet_up(planet, d): """If the planet is up on the given date, do housekeeping to remember that status, then return True if it's up, False otherwise. The date passed in is just a date; we will try different times on that date, including the immediately preceding sunset and a "toolate" hour of the night. """ global crescents, planets_up, visible_planets, saw_conjunction # The moon is easy to see, so allow it half the alt of anything else. if planet.name == "Moon": if planet.alt < min_alt / 2: # moon isn't up return False elif planet.alt < min_alt: # planet is not up return False # Planet is up. if not planets_up[planet.name]: planets_up[planet.name] = d visible_planets.append(planet) if planet.name not in list(crescents.keys()): return True # Is it a crescent? Update its crescent dates. if planet.phase <= crescent_percent: # It's a crescent now if not crescents[planet.name][0]: crescents[planet.name][0] = d else: crescents[planet.name][1] = d return True # Loop over the days in the time range: while d < end: # Set d to mid-day sometime, definitely before sunset midday = list(d.tuple()) midday[3:6] = [12 - timezone, 0, 0] if midday[3] < 0: midday[3] += 12 observer.date = ephem.date(tuple(midday)) sunset = observer.next_setting(sun) # Stop at a fixed hour of the evening? if toolate: latenight = list(observer.date.tuple()) latenight[3:6] = [toolate + 24 - timezone, 0, 0] latenight = ephem.date(tuple(latenight)) if latenight < sunset: latenight += oneday # Stop at sunrise else: observer.date = sunset latenight = observer.next_rising(sun) if verbose: print("\n***", d, "from", sunset, "to", latenight) # We have two lists of planets: planets_up and visible_planets. # planets_up is a dictionary of the time we first saw each planet # in its current apparition. It's global, and used by finish_planet. # visible_planets is a list of planets currently visible. visible_planets = [] for planet in planets: # A planet is observable this evening (not morning) # if its altitude at sunset OR its altitude at late-night # is greater than a visible_threshold observer.date = sunset planet.compute(observer) if verbose: print(observer.date, planet, "alt", planet.alt) if not check_if_planet_up(planet, observer.date): # If it's not up at sunset, try latenight observer.date = latenight if observer.date < sunset: observer.date += oneday planet.compute(observer) if verbose: print(" ", observer.date, planet, "alt", planet.alt) if not check_if_planet_up(planet, observer.date): # Planet is not up. Was it up yesterday? if planets_up[planet.name] and planet.name != "Moon": finish_planet(planet.name, observer.date, observer, output_format) # print() # print(datestr(d), "visible planets:", # ' '.join([p.name for p in visible_planets])) # print("planets_up:", planets_up) # Done with computing visible_planets. # Now look for conjunctions, anything closer than 5 degrees. # Split the difference, use a time halfway between sunset and latenight. saw_conjunction = False observer.date = ephem.date((sunset + latenight) / 2) moon = planets[0] if len(visible_planets) > 1: for p, planet in enumerate(visible_planets): for planet2 in visible_planets[p + 1:]: sep = ephem.separation(planet, planet2) # print(observer.date, "moon -", planet2.name, sep) if sep <= max_sep: # print (datestr(observer.date), planet.name, # planet2.name, sepstr(sep)) if verbose: print("adding sep", planet.name, planet2.name, observer.date, sep) conjunctions.add(planet.name, planet2.name, observer.date, sep) saw_conjunction = True elif planet == moon and sep <= moon_sep: if verbose: print("adding moon sep", planet.name, planet2.name, observer.date, sep) conjunctions.add(planet.name, planet2.name, observer.date, sep) saw_conjunction = True if not saw_conjunction: conjunctions.closeout(observer) # Add a day: d = ephem.date(d + oneday) if saw_conjunction: conjunctions.closeout(observer) for p in visible_planets: if p.name != "Moon": finish_planet(p.name, d, observer, output_format)
def minorplanets(in_datetime, observatory_code, max_objects=None, max_magnitude=None, require_magnitude=True, max_zenithdistance_deg=90.0, min_heliocentric_distance_AU=None, max_heliocentric_distance_AU=None, min_topocentric_distance_AU=None, max_topocentric_distance_AU=None): """ in_datetime - datetime.datetime(), e.g. datetime.datetime.utcnow() observatory_code - the Code of the observatory in http://www.minorplanetcenter.net/iau/lists/ObsCodes.html can be either string or integer. max_objects - default is None, otherwise limits the return to this number of observable objects max_magnitude - default is None, otherwise limits return to objects brighter than or equal to this magnitude (as calculated by PyEphem from the MPC data) (TODO: confirm whether this is V-band, R-band, or other...) require_magnitude - default is True. If False and max_magnitude is None, then return all objects, whether PyEphem can calculate a magnitude or not. max_zenithdistance_deg - default is 90 degrees (horizon) min/max_heliocentric_distance_AU - defaults are None min/max_topocentric_distance_AU - defaults are None """ obs_info = get_latlon_from_observatory_code(observatory_code) obs = ephem.Observer() obs.lat = np.radians(obs_info['latitude']) obs.lon = np.radians(obs_info['longitude']) obs.date = _convert_datetime_to_pyephem_date_string(in_datetime) mpc_filename = _find_cached_file('MPCORB.DAT') if mpc_filename == 'File Not Found': raise Error( "Problem reading MPCORB.DAT file from disk. \n" "Most likely you need to go download a copy from: \n" " http://www.minorplanetcenter.net/iau/MPCORB/MPCORB.DAT") if max_magnitude is not None: require_magnitude = True matching_objects = [] with open(mpc_filename) as f: in_header = True for line in f: if in_header is False and len(line) > 1: if (not require_magnitude) or (require_magnitude and (line[8:13] != ' ')): eph = ephem.readdb( convert_mpcorb_to_xephem(line).splitlines()[1]) eph.compute(obs) if (max_magnitude is None) or (eph.mag <= max_magnitude): if ((max_zenithdistance_deg is None) or (np.degrees(np.pi / 2. - eph.alt) <= max_zenithdistance_deg)): if ((min_heliocentric_distance_AU is None) or (eph.sun_distance >= min_heliocentric_distance_AU)): if ((max_heliocentric_distance_AU is None) or (eph.sun_distance <= max_heliocentric_distance_AU)): if ((min_topocentric_distance_AU is None) or (eph.earth_distance >= min_topocentric_distance_AU)): if ((max_topocentric_distance_AU is None) or (eph.earth_distance <= max_topocentric_distance_AU)): matching_objects.append(eph) else: if line.startswith('-------------------'): in_header = False if max_objects is not None: if len(matching_objects) >= max_objects: break name = [a.name for a in matching_objects] d = {} d['rise_time'] = [ a.rise_time.datetime() if a.rise_time is not None else np.nan for a in matching_objects ] d['transit_time'] = [ a.transit_time.datetime() if a.transit_time is not None else np.nan for a in matching_objects ] d['set_time'] = [ a.set_time.datetime() if a.set_time is not None else np.nan for a in matching_objects ] d['raJ2000_deg'] = [np.degrees(a.a_ra) for a in matching_objects] d['decJ2000_deg'] = [np.degrees(a.a_dec) for a in matching_objects] d['mag'] = [a.mag for a in matching_objects] d['R_AU'] = [a.sun_distance for a in matching_objects] d['delta_AU'] = [a.earth_distance for a in matching_objects] moon = ephem.Moon() moon.compute(obs.date) d['O-E-M_deg'] = [ np.degrees(ephem.separation(moon, a)) for a in matching_objects ] output = DataFrame(d, index=name) output = output[[ 'rise_time', 'transit_time', 'set_time', 'raJ2000_deg', 'decJ2000_deg', 'mag', 'R_AU', 'delta_AU', 'O-E-M_deg' ]] # re-order columns to something sensible return output