예제 #1
0
def test_comet():
    text = (b'    CJ95O010  1997 03 29.6333  0.916241  0.994928  130.6448'
            b'  283.3593   88.9908  20200224  -2.0  4.0  C/1995 O1 (Hale-Bopp)'
            b'                                    MPC106342\n')

    ts = load.timescale()
    t = ts.utc(2020, 5, 31)
    eph = load('de421.bsp')
    e = eph['earth'].at(t)

    for loader in mpc.load_comets_dataframe, mpc.load_comets_dataframe_slow:
        df = loader(BytesIO(text))
        row = df.iloc[0]
        k = mpc.comet_orbit(row, ts, GM_SUN)
        p = e.observe(eph['sun'] + k)
        ra, dec, distance = p.radec()

        # The file authorities/mpc-hale-bopp in the repository is the
        # source of these angles.  TODO: can we tighten this bound and
        # drive it to fractions of an arcsecond?

        ra_want = Angle(hours=(23, 59, 16.6))
        dec_want = Angle(degrees=(-84, 46, 58))
        assert abs(ra_want.arcseconds() - ra.arcseconds()) < 2.0
        assert abs(dec_want.arcseconds() - dec.arcseconds()) < 0.2
        assert abs(distance.au - 43.266) < 0.0005

        assert k.target == 'C/1995 O1 (Hale-Bopp)'
예제 #2
0
def comet_info(comet_id):
    """View a comet info."""
    comet = _find_comet(comet_id)
    if comet is None:
        abort(404)

    form = CometFindChartForm()

    ts = load.timescale(builtin=True)
    eph = load('de421.bsp')
    sun, earth = eph['sun'], eph['earth']

    c = sun + mpc.comet_orbit(comet, ts, GM_SUN)

    if not form.date_from.data or not form.date_to.data:
        today = datetime.today()
        form.date_from.data = today
        form.date_to.data = today + timedelta(days=7)

    if (form.date_from.data is None) or (form.date_to.data is None) or form.date_from.data >= form.date_to.data:
        t = ts.now()
        comet_ra_ang, comet_dec_ang, distance = earth.at(t).observe(c).radec()
        trajectory_b64 = None
    else:
        d1 = date(form.date_from.data.year, form.date_from.data.month, form.date_from.data.day)
        d2 = date(form.date_to.data.year, form.date_to.data.month, form.date_to.data.day)
        t = ts.now()
        comet_ra_ang, comet_dec_ang, distance = earth.at(t).observe(c).radec()
        if d1 != d2:
            time_delta = d2 - d1
            if time_delta.days > 365:
                d2 = d1 + timedelta(days=365)
            dt = get_trajectory_time_delta(d1, d2)
            trajectory = []
            while d1 <= d2:
                t = ts.utc(d1.year, d1.month, d1.day)
                ra, dec, distance = earth.at(t).observe(c).radec()
                trajectory.append((ra.radians, dec.radians, d1.strftime('%d.%m.')))
                d1 += dt
            t = ts.utc(d1.year, d1.month, d1.day)
            trajectory_json = json.dumps(trajectory)
            trajectory_b64 = base64.b64encode(trajectory_json.encode('utf-8'))
        else:
            trajectory_b64 = None

    comet_ra = comet_ra_ang.radians
    comet_dec = comet_dec_ang.radians

    if not common_ra_dec_fsz_from_request(form):
        form.ra.data = comet_ra
        form.dec.data = comet_dec

    chart_control = common_prepare_chart_data(form)

    return render_template('main/solarsystem/comet_info.html', fchart_form=form, type='info', comet=comet, comet_ra=comet_ra, comet_dec=comet_dec,
                           chart_control=chart_control, trajectory=trajectory_b64)
예제 #3
0
 def comet(self, designation: str) -> CelestialObject:
     """Look up a comet by its designation, e.g. 1P/Halley"""
     # NB: mpc.comet_orbit returns an orbit centered on the Sun, so we need to offset it!
     row = self._comets.loc[designation]
     return makeObject(
         type=ObjectType.COMET,
         name=designation[designation.find("/") + 1:],
         position=self.sun.position +
         mpc.comet_orbit(row, self.timescale, GM_SUN),
         dataFrame=row,
     )
예제 #4
0
def get_mpc_positions(designation):
    row = comets.loc[designation]
    coords = list()
    comet = planets['sun'] + mpc.comet_orbit(row, ts, GM_SUN)
    now = ts.now()
    x, y, z = comet.at(
        ts.utc(now.utc.year, now.utc.month,
               range(now.utc.day - 30, now.utc.day + 30))).ecliptic_xyz().km
    for xc, yc, zc in zip(x, y, z):
        coords.append([xc, yc, zc])
    return f2i(coords)
예제 #5
0
def calc_comet(comet_df, obstime, earthcoords, numdays=0, alt_table=False):
    # Generating a position.
    cometvec = sun + mpc.comet_orbit(comet_df, ts, GM_SUN)

    cometpos = earth.at(obstime).observe(cometvec)
    ra, dec, distance = cometpos.radec()
    print("RA", ra, "   DEC", dec, "   Distance", distance)

    if earthcoords:
        if len(earthcoords) > 2:
            elev = earthcoords[2]
        else:
            elev = 0
        obstopos = Topos(latitude_degrees=earthcoords[0],
                         longitude_degrees=earthcoords[1],
                         elevation_m=elev)
        print("\nObserver at", obstopos.latitude, "N  ", obstopos.longitude,
              "E  ", "Elevation", obstopos.elevation.m, "m")
        obsvec = earth + obstopos

        alt, az, distance = \
            obsvec.at(obstime).observe(cometvec).apparent().altaz()
        print("Altitude", alt, "     Azumuth", az, distance)

        alm_twilights = almanac.dark_twilight_day(eph, obstopos)
        # dawn, dusk = find_twilights(obstime, alm_twilights)
        # print(WHICH_TWILIGHT, ": Dawn", svt2str(dawn), "Dusk", svt2str(dusk))

        if numdays:
            print("\nRises and sets over", numdays, "days:")
            datetime1 = obstime.utc_datetime() - timedelta(hours=2)
            t0 = ts.utc(datetime1)
            t1 = ts.utc(datetime1 + timedelta(days=numdays))

            alm = almanac.risings_and_settings(eph, cometvec, obstopos)
            t, y = almanac.find_discrete(t0, t1, alm)

            print_rises_sets(obsvec, cometvec, alm, t0, t1)

        if alt_table:
            print()
            oneday = timedelta(days=1)
            while True:
                print_alt_table(obstime, cometvec, obsvec, alm_twilights)
                numdays -= 1
                if numdays <= 0:
                    break
                # Add a day: there doesn't seem to be a way to do this
                # while staying within skyview's Time object.
                obstime = ts.utc(obstime.utc_datetime() + oneday)
예제 #6
0
def get_comet(name, timestamp):
    # https://rhodesmill.org/skyfield/example-plots.html#drawing-a-finder-chart-for-comet-neowise
    # https://astroquery.readthedocs.io/en/latest/mpc/mpc.html

    # name = "C/2020 F3 (NEOWISE)"
    # https://www.minorplanetcenter.net/iau/info/CometOrbitFormat.html
    with load.open(mpc.COMET_URL) as f:
        comets = mpc.load_comets_dataframe(f)

    comets = (comets.sort_values('reference')
              .groupby('designation', as_index=False).last()
              .set_index('designation', drop=False))

    row = comets.loc[name]
    print(row)
    ts = load.timescale()
    eph = load('de421.bsp')
    sun, earth = eph['sun'], eph['earth']

    comet = sun + mpc.comet_orbit(row, ts, GM_SUN)

    t = ts.utc(timestamp.year, timestamp.month, timestamp.day, timestamp.hour, timestamp.minute)
    ra, dec, distance = earth.at(t).observe(comet).radec()

    result = {}
    result['name'] = name
    result['designation'] = row['designation']
    result['timestamp'] = str(timestamp)
    result['ra'] = str(ra)
    result['dec'] = str(dec)
    result['ra_decimal'] = str(ra.hours * 15)
    result['dec_decimal'] = str(dec.degrees)
    result['distance'] = str(distance)
    result['magnitude_g'] = row['magnitude_g']
    result['magnitude_k'] = row['magnitude_k']
    result['visual_magnitude'] = row['magnitude_k']
    result['row'] = row
    return result,comet
예제 #7
0
def test_comet_with_eccentricity_of_exactly_one():
    ts = load.timescale()
    t = ts.utc(2020, 8, 13)
    planets = load('de421.bsp')
    earth, sun = planets['earth'], planets['sun']

    data = (b'    CK15A020  2015 08  1.8353  5.341055  1.000000  208.8369  '
            b'258.5042  109.1696            10.5  4.0  C/2015 A2 (PANSTARRS)'
            b'                                    MPC 93587')

    with BytesIO(data) as f:
        df = mpc.load_comets_dataframe(f)

    df = df[df['designation'] == 'C/2015 A2 (PANSTARRS)']
    comet = mpc.comet_orbit(df.iloc[0], ts, GM_SUN)
    ra, dec, distance = earth.at(t).observe(sun + comet).radec()

    # These are exactly the RA and declination from the Minor Planet
    # Center for this comet!  (The RA seconds returned by Skyfield
    # actually say "46.45s", which would round up to 46.5, but what's a
    # tenth of an arcsecond among friends?)
    assert str(ra).startswith('18h 46m 46.4')
    assert str(dec).startswith("-72deg 05' 33.")
예제 #8
0
def _create_comet_brighness_file(all_comets, fname):
    global creation_running
    ts = load.timescale(builtin=True)
    eph = load('de421.bsp')
    sun, earth = eph['sun'], eph['earth']
    mags = []
    t = ts.now()
    with open(fname, 'w') as f:
        for index, row in all_comets.iterrows():
            m = 22.0
            try:
                comet = sun + mpc.comet_orbit(row, ts, GM_SUN)
                dist_earth = earth.at(t).observe(comet).distance().au
                dist_sun = sun.at(t).observe(comet).distance().au
                if dist_earth < 10.0:
                    m = row['magnitude_g'] + 5.0*np.log10(dist_earth) + 2.5*row['magnitude_k']*np.log10(dist_sun)
                    print('Comet: {} de={} ds={} m={} g={}'.format(row['designation'], dist_earth, dist_sun, m, row['magnitude_k']), flush=True)
            except Exception:
                pass
            f.write(row['comet_id'] + ' ' + str(m) + '\n')
            mags.append(m)

    all_comets['mag'] = mags
    creation_running = False
예제 #9
0
t = t_comet[len(t_comet) // 2]  # middle date

# An ephemeris from the JPL provides Sun and Earth positions.

eph = load('de421.bsp')
sun = eph['sun']
earth = eph['earth']

# The Minor Planet Center data file provides the comet orbit.

with load.open(mpc.COMET_URL) as f:
    comets = mpc.load_comets_dataframe(f)

comets = comets.set_index('designation', drop=False)
row = comets.loc['C/2020 F3 (NEOWISE)']
comet = sun + mpc.comet_orbit(row, ts, GM_SUN)

# The Hipparcos mission provides our star catalog.

with load.open(hipparcos.URL) as f:
    stars = hipparcos.load_dataframe(f)

# And the constellation outlines come from Stellarium.  We make a list
# of the stars at which each edge stars, and the star at which each edge
# ends.

url = ('https://raw.githubusercontent.com/Stellarium/stellarium/master'
       '/skycultures/western_SnT/constellationship.fab')

with load.open(url) as f:
    constellations = stellarium.parse_constellations(f)
예제 #10
0
ts = load.timescale()
ephem = load('de421.bsp')
cet = timezone('CET')

sun, moon, earth = ephem['sun'], ephem['moon'], ephem['earth']

amsterdam = Topos('52.3679 N', '4.8984 E')
amstercentric = earth + amsterdam

t0 = ts.now()
t1 = ts.tt_jd(t0.tt + 1)
nu = t0.utc_datetime().astimezone(cet).time().strftime('%H:%M')

mindist=1.5
from skyfield.constants import GM_SUN_Pitjeva_2005_km3_s2 as GM_SUN
with load.open(mpc.COMET_URL,reload=True) as f:
    comets = mpc.load_comets_dataframe(f)
print('Found ',len(comets), ' comets')
comets = (comets.sort_values('reference')
          .groupby('designation', as_index=False).last()
          .set_index('designation', drop=False))
f = open('cometlist.txt', 'w')
for (c, cometdata) in comets.iterrows():
    comet = sun + mpc.comet_orbit(cometdata, ts, GM_SUN)
    ra, dec, distance = sun.at(t0).observe(comet).radec()
    print(c,' is at ',distance.au,'au')
    if (distance.au < mindist):
       f.write(c+"\n")
f.close()
예제 #11
0
def comet_visibility(start_dt,
                     comet_name,
                     lat,
                     lng,
                     tzname='UTC',
                     minutes_coarse=60,
                     minutes_fine=1,
                     days=1,
                     min_comet_alt=0,
                     max_sun_alt=-12):
    '''
    find periods where the comet is above the specified horizon and the Sun is sufficiently below the horizon

    :param start_dt: timezone aware datetime to begin search
    :param comet_name: string containing the comet name, must match up with the MPC database
    :param lat: string with a float followed by N or S (e.g. 35.22 N), no negative numbers
    :param lng: string with a float followed by E or W (e.g. 78.01 W), no negative numbers
    :param tzname: string containing the timzone name
    :param days: integer with the length of the search window in days
    :param min_comet_alt: minimum altitude the comet is visible, defaults to 0 but could be set to match treeline
    :param max_sun_alt: maximum Sun altitide, defaults to -12 (nautical twilight) which works for low altitude comets less than magnitude 2
           subtract 1-1.5 for that maximum altitude for every additional increase of 1 in magnitude.
    :return: a dataframe containing each minute during the specified time period the comet is observable
    '''
    rediskey = f"cv:{start_dt.isoformat()}:{days}:{lat}:{lng}".replace(
        ' ', "_")
    start_utc = start_dt.astimezone(UTC) - datetime.timedelta(hours=4)
    try:
        cached_dict = pickle.loads(rconn.get(rediskey))
        print("from cv cache")
        return cached_dict
    except Exception as e:
        pass

    try:
        localtz = start_dt.tzinfo
    except:
        localtz = 'UTC'

    # get comet ephemris and observer's location in space
    comet = sun + mpc.comet_orbit(comets.loc[comet_name], ts, GM_SUN)
    obs = earth + Topos(lat, lng)

    # course grained look at visiblity, use Sun at horizon to ensure we dont miss any opporunities
    times_coarse = ts.utc(start_utc.year, start_utc.month, start_utc.day,
                          start_utc.hour,
                          range(0, 60 * 24 * days, minutes_coarse))
    _, instances = run_calculations(comet, 0, 0, obs, minutes_coarse,
                                    times_coarse)

    # rerun observations with a finer grain (defaults to 1 minute intervals) and passed Sun altitude
    instances_fine = []
    for instance in instances:
        new_start = instance['begin']['time']
        window = range(
            new_start.minute - minutes_coarse,
            round(instance['duration'].total_seconds() / 60) + minutes_coarse)
        times_fine = ts.utc(new_start.year, new_start.month, new_start.day,
                            new_start.hour, window)
        _, local_instances_fine = run_calculations(comet, max_sun_alt,
                                                   min_comet_alt, obs,
                                                   minutes_fine, times_fine)
        instances_fine += local_instances_fine
    daily_instances = dict()
    for instance in instances_fine:
        for x in ['begin', 'end']:
            instance[x]['tz'] = localtz
            instance[x]['time_local'] = instance[x]['time'].astimezone(localtz)
        datestr = instance['begin']['time_local'].strftime('%a %b %-d')
        if datestr not in daily_instances.keys():
            daily_instances[datestr] = []
        daily_instances[datestr].append(instance)

    pickled_object = pickle.dumps(daily_instances)
    rconn.set(rediskey, pickled_object)

    # rconn.lset("rediskey", daily_instances)

    return (daily_instances)
예제 #12
0
def get_mpc_current_position(designation):
    row = comets.loc[designation]
    coords = list()
    comet = planets['sun'] + mpc.comet_orbit(row, ts, GM_SUN)
    x, y, z = comet.at(ts.now()).ecliptic_xyz().km
    return [x, y, z]
예제 #13
0
def create_starmap(command, observation_id):

    # The comet is plotted on several dates `t_comet`.  But the stars only
    # need to be drawn once, so we take the middle comet date as the single
    # time `t` we use for everything else.

    ts = load.timescale()
    t_comet = ts.utc(2020, 8, range(1, 10))
    t = t_comet[len(t_comet) // 2]  # middle date

    # An ephemeris from the JPL provides Sun and Earth positions.

    eph = load('de421.bsp')
    sun = eph['sun']
    earth = eph['earth']

    # The Minor Planet Center data file provides the comet orbit.

    with load.open(mpc.COMET_URL) as f:
        comets = mpc.load_comets_dataframe(f)

    comets = (comets.sort_values('reference')
              .groupby('designation', as_index=False).last()
              .set_index('designation', drop=False))

    row = comets.loc['C/2020 F3 (NEOWISE)']
    comet = sun + mpc.comet_orbit(row, ts, GM_SUN)

    # The Hipparcos mission provides our star catalog.

    # with load.open(hipparcos.URL) as f:
    with load.open(settings.MY_HIPPARCOS_URL) as f:
        stars = hipparcos.load_dataframe(f)

    # And the constellation outlines come from Stellarium.  We make a list
    # of the stars at which each edge stars, and the star at which each edge
    # ends.

    url = ('https://raw.githubusercontent.com/Stellarium/stellarium/master'
           '/skycultures/western_SnT/constellationship.fab')

    with load.open(url) as f:
        constellations = stellarium.parse_constellations(f)

    edges = [edge for name, edges in constellations for edge in edges]
    edges_star1 = [star1 for star1, star2 in edges]
    edges_star2 = [star2 for star1, star2 in edges]

    # We will center the chart on the comet's middle position.

    center = earth.at(t).observe(comet)
    projection = build_stereographic_projection(center)
    field_of_view_degrees = 30.0
    limiting_magnitude = 8.0

    # Now that we have constructed our projection, compute the x and y
    # coordinates that each star and the comet will have on the plot.

    star_positions = earth.at(t).observe(Star.from_dataframe(stars))
    stars['x'], stars['y'] = projection(star_positions)

    comet_x, comet_y = projection(earth.at(t_comet).observe(comet))

    # Create a True/False mask marking the stars bright enough to be
    # included in our plot.  And go ahead and compute how large their
    # markers will be on the plot.

    bright_stars = (stars.magnitude <= limiting_magnitude)
    magnitude = stars['magnitude'][bright_stars]
    marker_size = (0.5 + limiting_magnitude - magnitude) ** 2.0

    # The constellation lines will each begin at the x,y of one star and end
    # at the x,y of another.  We have to "rollaxis" the resulting coordinate
    # array into the shape that matplotlib expects.

    xy1 = stars[['x', 'y']].loc[edges_star1].values
    xy2 = stars[['x', 'y']].loc[edges_star2].values
    lines_xy = np.rollaxis(np.array([xy1, xy2]), 1)

    # Time to build the figure!

    fig, ax = plt.subplots(figsize=[9, 9])

    # Draw the constellation lines.

    ax.add_collection(LineCollection(lines_xy, colors='#00f2'))

    # Draw the stars.

    ax.scatter(stars['x'][bright_stars], stars['y'][bright_stars],
               s=marker_size, color='k')

    # Draw the comet positions, and label them with dates.

    comet_color = '#f00'
    offset = 0.002

    ax.plot(comet_x, comet_y, '+', c=comet_color, zorder=3)

    for xi, yi, tstr in zip(comet_x, comet_y, t_comet.utc_strftime('%m/%d')):
        tstr = tstr.lstrip('0')
        text = ax.text(xi + offset, yi - offset, tstr, color=comet_color,
                       ha='left', va='top', fontsize=9, weight='bold', zorder=-1)
        text.set_alpha(0.5)

    # Finally, title the plot and set some final parameters.

    angle = np.pi - field_of_view_degrees / 360.0 * np.pi
    limit = np.sin(angle) / (1.0 - np.cos(angle))

    ax.set_xlim(-limit, limit)
    ax.set_ylim(-limit, limit)
    ax.xaxis.set_visible(False)
    ax.yaxis.set_visible(False)
    ax.set_aspect(1.0)
    ax.set_title('Comet NEOWISE {} through {}'.format(
        t_comet[0].utc_strftime('%Y %B %d'),
        t_comet[-1].utc_strftime('%Y %B %d'),
    ))

    # Save.
    filename = 'starmap.png'
    path = os.path.join(settings.MEDIA_ROOT, filename)

    fig.savefig(path, bbox_inches='tight')

    image_url = os.path.join(settings.MEDIA_URL, filename)
    return image_url