Minor Planet Center - Asteroid Orbital Data
200
2009-09-08T10:30:00Z
Complete Asteroid Data from the Minor Planet Center (MPC),
updated once per month. The MPC operates at the Smithsonian Astrophysical
Observatory under the auspices of Division III of the International
Astronomical Union (IAU).
The MPC Orbit database contains orbital elements of minor
planets that have been published in the Minor Planet Circulars,
the Minor Planet Orbit Supplement and the Minor Planet
Electronic Circulars.
Williams, G.; Keys, S.; Rudenko, M.; Galache, J.L.
MPC catalogue distributed by ARI/Zentrum für Astronomie Heidelberg.
http://www.minorplanetcenter.org/
asteroids
surveys
This data was compiled at the Minor Planet Center (MPC). Updated data
files are available at http://www.minorplanetcenter.org/iau/mpc.html
1980CeMec..22...63M
Catalog
execDef.spawnPython("bin/updateData.py")
More information is available at
http://www.minorplanetcenter.net/iau/info/Perturbers.html
The first part of this is a descriptor of the system
used for the perturbing planets according to the follow scheme:
======= ======================================================
(space) Undefined/unknown, assume JPL DE200 positions + masses
d JPL DE200 positions + masses
f JPL DE245 positions + masses
h JPL DE403 positions + masses
j JPL DE405 positions + masses
======= ======================================================
The second part is a two-digit hexadecimal number
to be interpreted bitwise (this was taken literally from the MPC data
and will probably be parsed out at some point). In the meantime,
here is the key to the bits:
+------------+------+-------+-------------------------------+
| Perturber | Bit | Value | |
+============+======+=======+===============================+
| Hygiea | 0 | 1 | |
+------------+------+-------+-------------------------------+
| Earth | 1 | 2 | Bits 1 + 2 must |
+------------+------+-------+ both be set or both be +
| Moon | 2 | 4 | unset! |
+------------+------+-------+-------------------------------+
| Ceres | 3 | 8 | |
+------------+------+-------+-------------------------------+
| Pallas | 4 | 16 | |
+------------+------+-------+-------------------------------+
| Vesta | 5 | 32 | |
+------------+------+-------+-------------------------------+
| Eunomia | 6 | 64 | |
+------------+------+-------+-------------------------------+
Sum the values of the included perturbers and convert to hexadecimal. Since
orbits will always include the major planets Mercury to Neptune there is no
need to include these bodies in the above scheme (other than allowing the earth
and moon to be treated separately).
Some examples of coarse and precise indicators are:
====== ======= ============================================
Coarse Precise Perturbers (Mercury-Neptune+...)
------ ------- --------------------------------------------
M-c 08 Ceres, EM barycenter
M-c 0E Ceres, Earth, Moon
M-p 16 Pallas, Earth, Moon [NOT RECOMMENDED]
M-p 18 Ceres, Pallas, EM barycenter
M-p 1E Ceres, Pallas, Earth, Moon
M-v 38 Ceres, Pallas, Vesta, EM barycenter
M-v 3E Ceres, Pallas, Vesta, Earth, Moon
M-e 78 Ceres, Pallas, Vesta, Euomia, EM barycenter
M-e 7E Ceres, Pallas, Vesta, Euomia, Earth, Moon
M-h 39 Ceres, Pallas, Vesta, Hygiea, EM barycenter
====== ======= ============================================
The default for Minor Planet Center orbits will henceforth be h (DE403), M-v (coarse) and 38 or 3E (precise, depending on whether the object is an earth-approacher or not). Additional perturbers will be added as necessary.
mpcorb_web
createViews
1-7
9-13
15-19
21-25
27-35
38-46
49-57
60-68
71-79
81-91
93-103
106-106
108-116
118-122
124-126
128-136
138-141
143-149
151-160
162-165
167-194
195-202
def unpackDate(val):
century = 18+ord(val[0])-ord('I')
year = int(val[1:3])
try:
month = int(val[3])
except ValueError:
month = 10+ord(val[3])-ord('A')
try:
day = int(val[4])
except ValueError:
day = 10+ord(val[4])-ord('A')
return datetime.datetime(century*100+year, month, day)
@orb_epoch = dateTimeToJYear(unpackDate(@orb_epoch))
import string
majInterpretation = dict((i, c) for c, i in enumerate(
"0123456789"+string.ascii_uppercase+string.ascii_lowercase))
def unpackDesig(val):
year = (18+ord(val[0])-ord('I'))*100+int(val[1:3])
letters = val[3]+val[6]
cycle = majInterpretation[val[4]]*10+int(val[5])
return "%d %s%s"%(
year, letters, cycle or "")
ORD0 = ord('0')
ORDA = ord('A')
ORDa = ord('a')
def fromBase62(s):
"""returns an integer from an MPC-style base-62 number.
"""
val = 0
for c in s:
val *= 62
if c.isdigit():
val += ord(c)-ORD0
elif c.isupper():
val += 10+(ord(c)-ORDA)
elif c.islower():
val += 36+(ord(c)-ORDa)
else:
raise ValueError(f"Invalid char in base-62 '{val}'")
return val
if @designation[0]=='~':
@designation = "{:07d}".format(
620000-fromBase62(@designation[1:]))
elif len(@designation)==5:
# it's a "packed number"
digit = @designation[0]
if digit.isdigit():
tents = int(digit)
elif digit.isupper():
tents = ord(digit)-ord('A')+10
elif digit.islower():
tents = ord(digit)-ord('a')+36
else:
raise ValueError("Invalid packed number char")
@designation = "%07d"%(tents*10000+int(@designation[1:]))
else:
# it's a survey or provisional designation
for surv, abbrev in [
("PLS", "P-L"),
("T1S", "T-1"),
("T2S", "T-2"),
("T3S", "T-3")]:
if @designation.startswith(surv):
@designation = "%s %s"%(@designation[3:], abbrev)
break
else:
@designation = unpackDesig(@designation)
familyCodes = {
0: None,
1: "Atira",
2: "Aten",
3: "Apollo",
4: "Amor",
5: "Object with q < 1.665 AU",
6: "Hungaria",
7: "Phocaea",
8: "Hilda",
9: "Jupiter Trojan",
10: " Distant object",
}
flags = int(@orbit_class, 16)
res = familyCodes.get(flags&0x3f, "PROBLEM -- Please contact"
" the operators")
extras = []
for mask, msg in [
(2048, "Object is NEO"),
(4096, "Object is 1-km (or larger) NEO"),
(8192, "1-opposition object seen at earlier opposition"),
(16384, "Critical list numbered object"),
(32768, "Object is PHA")]:
if flags&mask:
extras.append(msg)
if extras:
res = "%s (%s)"%(res, ", ".join(extras))
@orbit_class = res
try:
if @obs_duration.endswith("days"):
@arc_length = int(@obs_duration.split()[0])
@first_obs = None
else:
@arc_length = None
@first_obs = int(@obs_duration[:4])
except ValueError:
import warnings
warnings.warn("Invalid obs_duration %s in Record %s"%(
@obs_duration, @designation))
@arc_length = @first_obs = None
mat = re.match(r"\\((\\d+)\\)\\s*(.*)", @name)
if mat:
@alt_target_name = "{}#{}".format(mat.group(1), mat.group(2))
else:
@alt_target_name = None
EPN-TAP table for MPC Asteroid Orbital Data
MPC asteroids
The EPN-TAP 2.0 version of the complete asteroid data from the
Minor Planet Center (MPC),
updated once per month. The MPC operates at the Smithsonian Astrophysical
Observatory under the auspices of Division III of the International
Astronomical Union (IAU).
The MPC Orbit database contains orbital elements of minor
planets that have been published in the Minor Planet Circulars,
the Minor Planet Orbit Supplement and the Minor Planet
Electronic Circulars.
//epntap2#table-2_0
original_name, new_name
mag, magnitude
slope, slope_parameter
orb_epoch, orb_epoch
mean_anomaly, mean_anomaly
arg_perihel, arg_perihel
long_asc, long_asc
inclination, inclination
eccentricity, eccentricity
mean_motion, mean_motion
semimaj_ax, semi_major_axis
uncertainty, uncertainty
reference, reference
n_obs, n_obs
n_opp, n_opp
arc_length, arc_length
rms_fit, rms_fit
perturbers, perturbers
computer, computer
orbit_class, orbit_class
first_obs, first_obs
last_obs, last_obs
CREATE VIEW \qName AS (
SELECT \colNames FROM (
SELECT
CAST (designation as text) AS granule_uid,
text 'mpc' AS granule_gid,
cast (designation as text) AS obs_id,
text 'ci' AS dataproduct_type,
text 'phys.angSize.smajAxis;phys.size.smajAxis#src.orbital.eccentricity#src.orbital.node#src.orbital.periastron#src.orbital.meanAnomaly#phys.magAbs' AS measurement_type,
integer '5' AS processing_level,
cast (name as text) AS target_name,
cast (alt_target_name as text) AS alt_target_name,
text 'asteroid' AS target_class,
CAST(NULL AS DOUBLE PRECISION) AS time_min,
CAST(NULL AS DOUBLE PRECISION) AS time_max,
CAST(NULL AS DOUBLE PRECISION) AS time_sampling_step_min,
CAST(NULL AS DOUBLE PRECISION) AS time_sampling_step_max,
CAST(NULL AS DOUBLE PRECISION) AS time_exp_min,
CAST(NULL AS DOUBLE PRECISION) AS time_exp_max,
CAST(NULL AS DOUBLE PRECISION) AS spectral_range_min,
CAST(NULL AS DOUBLE PRECISION) AS spectral_range_max,
CAST(NULL AS DOUBLE PRECISION) AS spectral_sampling_step_min,
CAST(NULL AS DOUBLE PRECISION) AS spectral_sampling_step_max,
CAST(NULL AS DOUBLE PRECISION) AS spectral_resolution_min,
CAST(NULL AS DOUBLE PRECISION) AS spectral_resolution_max,
CAST(NULL AS DOUBLE PRECISION) AS c1min,
CAST(NULL AS DOUBLE PRECISION) AS c1max,
CAST(NULL AS DOUBLE PRECISION) AS c2min,
CAST(NULL AS DOUBLE PRECISION) AS c2max,
CAST(NULL AS DOUBLE PRECISION) as c3min,
CAST(NULL AS DOUBLE PRECISION) as c3max,
CAST(NULL AS DOUBLE PRECISION) as c1_resol_min,
CAST(NULL AS DOUBLE PRECISION) as c1_resol_max,
CAST(NULL AS DOUBLE PRECISION) as c2_resol_min,
CAST(NULL AS DOUBLE PRECISION) as c2_resol_max,
CAST(NULL AS DOUBLE PRECISION) as c3_resol_min,
CAST(NULL AS DOUBLE PRECISION) as c3_resol_max,
CAST('celestial' AS text) AS spatial_frame_type,
CAST(NULL AS DOUBLE PRECISION) as incidence_min,
CAST(NULL AS DOUBLE PRECISION) as incidence_max,
CAST(NULL AS DOUBLE PRECISION) as emergence_min,
CAST(NULL AS DOUBLE PRECISION) as emergence_max,
CAST(NULL AS DOUBLE PRECISION) as phase_min,
CAST(NULL AS DOUBLE PRECISION) as phase_max,
CAST(NULL AS text) AS instrument_host_name,
CAST(NULL AS text) AS instrument_name,
text 'mpc' AS service_title,
make_timestamp(floor(last_obs)::integer, 1,1,0,0,0)
+make_interval(0,0,0,((last_obs-floor(last_obs))*365.25)::integer)
as release_date,
make_timestamp(floor(last_obs)::integer, 1,1,0,0,0)
+make_interval(0,0,0,((last_obs-floor(last_obs))*365.25)::integer)
as creation_date,
make_timestamp(floor(last_obs)::integer, 1,1,0,0,0)
+make_interval(0,0,0,((last_obs-floor(last_obs))*365.25)::integer)
as modification_date,
CAST(NULL AS text) AS spatial_origin,
CAST(NULL AS text) AS time_origin,
CAST(NULL AS text) AS spatial_coordinate_description,
CAST(NULL AS text) AS publisher,
CAST(NULL AS text) AS access_md5,
CAST(NULL AS text) AS target_region,
CAST(NULL AS text) AS time_scale,
CAST(NULL AS text) as thumbnail_url,
CAST(NULL AS text) AS feature_name,
CAST(NULL AS text) AS file_name,
text '1980CeMec..22...63M' AS bib_reference,
CAST(NULL AS text) AS access_format,
CAST(NULL AS text) as access_url,
integer '0' AS access_estsize,
CAST(NULL AS text) as species,
CAST(NULL AS spoly) AS s_region,
mag as magnitude,
slope as slope_parameter,
orb_epoch as orb_epoch,
mean_anomaly as mean_anomaly,
arg_perihel as arg_perihel,
long_asc as long_asc,
inclination as inclination,
eccentricity as eccentricity,
mean_motion as mean_motion,
semimaj_ax as semi_major_axis,
uncertainty as uncertainty,
reference as reference,
n_obs as n_obs,
n_opp as n_opp,
arc_length as arc_length,
rms_fit as rms_fit,
perturbers as perturbers,
computer as computer,
orbit_class as orbit_class,
first_obs as first_obs,
last_obs as last_obs
FROM mpc.mpcorb) as q)
/tap/sync
row = self.getFirstVOTableRow()
self.assertAlmostEqual(row["semi_major_axis"], 3.09, places=1)
self.assertTrue(isinstance(row['creation_date'], datetime.datetime))
self.assertEqual(row["target_name"], '(457) Alleghenia')
pla/form
row = self.getFirstVOTableRow()
self.assertAlmostEqual(row["mag"], 11.1, 0)
self.assertTrue(row["orb_epoch"]>2015)
self.assertTrue(row["last_obs"]>2015)
self.assertEqual(row["arc_length"], None)
self.assertEqual(row["first_obs"], 1900)
/tap/sync
row = self.getFirstVOTableRow()
self.assertEqual(row["target_name"], "(8639) Vonsovsky")
self.assertEqual(row["alt_target_name"], "8639#Vonsovsky")
/tap/sync
self.assertXpath("//v:TIMESYS[@ID=//v:FIELD[@name='time_min']/@ref]",
{"timeorigin": "0", "timescale": "UTC", "refposition": "TOPOCENTER"})
self.assertXpath("//v:TIMESYS[@ID=//v:FIELD[@name='time_max']/@ref]",
{"timeorigin": "0", "timescale": "UTC", "refposition": "TOPOCENTER"})