<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Using NEOS package
With the new poliastro version (0.7.0), a new package is included
Step1:  NeoWS module
This module make requests to NASA NEO Webservice, so you'll need an internet connection to run the next examples.
The simplest neows function is orbit_from_name(), which return an Orbit object given a name
Step2:  You can also search by IAU number or SPK-ID (there is a faster neows.orbit_from_spk_id() function in that case, although)
Step3:  Since neows relies on Small-Body Database browser to get the SPK-ID given a body name, you can use the wildcards from that browser
Step4:  <div class="alert alert-info">Note that epoch is provided by the Web Service itself, so if you need orbit on another epoch, you have to propagate it
Step5:  Given that we are using NASA APIs, there is a maximum number of requests. If you want to make many requests, it is recommended getting a NASA API key. You can use your API key adding the api_key parameter to the function
Step6:  DASTCOM5 module
This module can also be used to get NEOs orbit, in the same way that neows, but it have some advantages (and some disadvantages).
It relies on DASTCOM5 database, a NASA/JPL maintained asteroid and comet database. This database has to be downloaded at least once in order to use this module. According to its README, it is updated typically a couple times per day, but 
 potentially as frequently as once per hour, so you can download it whenever you want the more recently discovered bodies. This also means that, after downloading the file, you can use the database offline.
The file is a ~230 MB zip that you can manually download and unzip in ~/.poliastro or, more easily, you can use
Python
dastcom5.download_dastcom5()
The main DASTCOM5 advantage over NeoWs is that you can use it to search not only NEOs, but any asteroid or comet. The easiest function is orbit_from_name()
Step7:  Keep in mind that this function returns a list of orbits matching your string. This is made on purpose given that there are comets which have several records in the database (one for each orbit determination in history) what allow plots like this one
Step8:  While neows can only be used to get Orbit objects, dastcom5 can also provide asteroid and comet complete database.
Once you have this, you can get specific data about one or more bodies. The complete databases are ndarrays, so if you want to know the entire list of available parameters, you can look at the dtype, and they are also explained in
documentation API Reference
Step9:  <div class="alert alert-info">Asteroid and comet parameters are not exactly the same (although they are very close)
Step10:  The number of Atira NEOs we use using this method is
Step11:  Which is consistent with the stats published by CNEOS
Now we're gonna plot all of their orbits, with corresponding labels, just because we love plots 
Step12:  We only need to get the 16 orbits from these 16 ndarrays.
There are two ways
Step13:  If we needed also the names of each asteroid, we could do
Step14:  <div class="alert alert-info">We knew beforehand that there are no `Atira` comets, only asteroids (comet orbits are usually more eccentric), but we could use the same method with `com_db` if we wanted.</div>
Finally, another interesting function in dastcom5 is entire_db(), which is really similar to ast_db and com_db, but it returns a Pandas dataframe instead of a numpy ndarray. The dataframe has asteroids and comets in it, but in order to achieve that (and a more manageable dataframe), a lot of parameters were removed, and others were renamed
Step15:  Also, in this function, DASTCOM5 data (specially strings) is ready to use (decoded and improved strings, etc)
Step16:  Panda offers many functionalities, and can also be used in the same way as the ast_db and comet_db functions
Step17:  What? I said they can be used in the same way!
Dont worry 
Step18:  So, rewriting our condition
<ASSISTANT_TASK:>
Python Code:
import matplotlib.pyplot as plt
plt.ion()
from astropy import time
from poliastro.twobody.orbit import Orbit
from poliastro.bodies import Earth
from poliastro.plotting import OrbitPlotter
Explanation: Using NEOS package
With the new poliastro version (0.7.0), a new package is included: NEOs package.
The docstrings of this package states the following:
Functions related to NEOs and different NASA APIs. All of them are coded as part of SOCIS 2017 proposal.
So, first of all, an important question:
What are NEOs?
NEO stands for near-Earth object. The Center for NEO Studies (CNEOS) defines NEOs as comets and asteroids that have been nudged by the gravitational attraction of nearby planets into orbits that allow them to enter the Earth’s neighborhood.
And what does "near" exactly mean? In terms of orbital elements, asteroids and comets can be considered NEOs if their perihelion (orbit point which is nearest to the Sun) is less than 1.3 au = 1.945 * 10<sup>8</sup> km from the Sun.
End of explanation
from poliastro.neos import neows
eros = neows.orbit_from_name('Eros')
frame = OrbitPlotter()
frame.plot(eros, label='Eros');
Explanation: NeoWS module
This module make requests to NASA NEO Webservice, so you'll need an internet connection to run the next examples.
The simplest neows function is orbit_from_name(), which return an Orbit object given a name:
End of explanation
ganymed = neows.orbit_from_name('1036') # Ganymed IAU number
amor = neows.orbit_from_name('2001221') # Amor SPK-ID
eros = neows.orbit_from_spk_id('2000433') # Eros SPK-ID
frame = OrbitPlotter()
frame.plot(ganymed, label='Ganymed')
frame.plot(amor, label='Amor')
frame.plot(eros, label='Eros');
Explanation: You can also search by IAU number or SPK-ID (there is a faster neows.orbit_from_spk_id() function in that case, although):
End of explanation
neows.orbit_from_name('*alley')
Explanation: Since neows relies on Small-Body Database browser to get the SPK-ID given a body name, you can use the wildcards from that browser: * and ?.
<div class="alert alert-info">Keep it in mind that `orbit_from_name()` can only return one Orbit, so if several objects are found with that name, it will raise an error with the different bodies.</div>
End of explanation
eros.epoch.iso
epoch = time.Time(2458000.0, scale='tdb', format='jd')
eros_november = eros.propagate(epoch)
eros_november.epoch.iso
Explanation: <div class="alert alert-info">Note that epoch is provided by the Web Service itself, so if you need orbit on another epoch, you have to propagate it:</div>
End of explanation
neows.orbit_from_name('Toutatis', api_key='DEMO_KEY')
Explanation: Given that we are using NASA APIs, there is a maximum number of requests. If you want to make many requests, it is recommended getting a NASA API key. You can use your API key adding the api_key parameter to the function:
End of explanation
from poliastro.neos import dastcom5
atira = dastcom5.orbit_from_name('atira')[0] # NEO
wikipedia = dastcom5.orbit_from_name('wikipedia')[0] # Asteroid, but not NEO.
frame = OrbitPlotter()
frame.plot(atira, label='Atira (NEO)')
frame.plot(wikipedia, label='Wikipedia (asteroid)');
Explanation: DASTCOM5 module
This module can also be used to get NEOs orbit, in the same way that neows, but it have some advantages (and some disadvantages).
It relies on DASTCOM5 database, a NASA/JPL maintained asteroid and comet database. This database has to be downloaded at least once in order to use this module. According to its README, it is updated typically a couple times per day, but 
 potentially as frequently as once per hour, so you can download it whenever you want the more recently discovered bodies. This also means that, after downloading the file, you can use the database offline.
The file is a ~230 MB zip that you can manually download and unzip in ~/.poliastro or, more easily, you can use
Python
dastcom5.download_dastcom5()
The main DASTCOM5 advantage over NeoWs is that you can use it to search not only NEOs, but any asteroid or comet. The easiest function is orbit_from_name():
End of explanation
halleys = dastcom5.orbit_from_name('1P')
frame = OrbitPlotter()
frame.plot(halleys[0], label='Halley')
frame.plot(halleys[5], label='Halley')
frame.plot(halleys[10], label='Halley')
frame.plot(halleys[20], label='Halley')
frame.plot(halleys[-1], label='Halley');
Explanation: Keep in mind that this function returns a list of orbits matching your string. This is made on purpose given that there are comets which have several records in the database (one for each orbit determination in history) what allow plots like this one:
End of explanation
ast_db = dastcom5.asteroid_db()
comet_db = dastcom5.comet_db()
ast_db.dtype.names[:20] # They are more than 100, but that would be too much lines in this notebook :P
Explanation: While neows can only be used to get Orbit objects, dastcom5 can also provide asteroid and comet complete database.
Once you have this, you can get specific data about one or more bodies. The complete databases are ndarrays, so if you want to know the entire list of available parameters, you can look at the dtype, and they are also explained in
documentation API Reference:
End of explanation
aphelion_condition = 2 * ast_db['A'] - ast_db['QR'] < 0.983
axis_condition = ast_db['A'] < 1.3 
atiras = ast_db[aphelion_condition & axis_condition]
Explanation: <div class="alert alert-info">Asteroid and comet parameters are not exactly the same (although they are very close):</div>
With these ndarrays you can classify asteroids and comets, sort them, get all their parameters, and whatever comes to your mind.
For example, NEOs can be grouped in several ways. One of the NEOs group is called Atiras, and is formed by NEOs whose orbits are contained entirely with the orbit of the Earth. They are a really little group, and we can try to plot all of these NEOs using asteroid_db():
Talking in orbital terms, Atiras have an aphelion distance, Q &lt; 0.983 au and a semi-major axis, a &lt; 1.0 au.
Visiting documentation API Reference, you can see that DASTCOM5 provides semi-major axis, but doesn't provide aphelion distance. You can get aphelion distance easily knowing perihelion distance (q, QR in DASTCOM5) and semi-major axis Q = 2*a - q, but there are probably many other ways.
End of explanation
len(atiras)
Explanation: The number of Atira NEOs we use using this method is:
End of explanation
from poliastro.twobody.orbit import Orbit
from poliastro.bodies import Earth
earth = Orbit.from_body_ephem(Earth)
Explanation: Which is consistent with the stats published by CNEOS
Now we're gonna plot all of their orbits, with corresponding labels, just because we love plots :)
End of explanation
frame = OrbitPlotter()
frame.plot(earth, label='Earth')
for record in atiras['NO']:
    ss = dastcom5.orbit_from_record(record).to_icrs()
    frame.plot(ss, color="#666666")
Explanation: We only need to get the 16 orbits from these 16 ndarrays.
There are two ways:
Gather all their orbital elements manually and use the Orbit.from_classical() function.
Use the NO property (logical record number in DASTCOM5 database) and the dastcom5.orbit_from_record() function.
The second one seems easier and it is related to the current notebook, so we are going to use that one:
We are going to use ASTNAM property of DASTCOM5 database:
End of explanation
frame = OrbitPlotter()
frame.plot(earth, label='Earth')
for i in range(len(atiras)):
    record = atiras['NO'][i]
    label = atiras['ASTNAM'][i].decode().strip() # DASTCOM5 strings are binary
    ss = dastcom5.orbit_from_record(record).to_icrs()
    frame.plot(ss, label=label)
Explanation: If we needed also the names of each asteroid, we could do:
End of explanation
db = dastcom5.entire_db()
db.columns
Explanation: <div class="alert alert-info">We knew beforehand that there are no `Atira` comets, only asteroids (comet orbits are usually more eccentric), but we could use the same method with `com_db` if we wanted.</div>
Finally, another interesting function in dastcom5 is entire_db(), which is really similar to ast_db and com_db, but it returns a Pandas dataframe instead of a numpy ndarray. The dataframe has asteroids and comets in it, but in order to achieve that (and a more manageable dataframe), a lot of parameters were removed, and others were renamed:
End of explanation
db[db.NAME == 'Halley'] # As you can see, Halley is the name of an asteroid too, did you know that?
Explanation: Also, in this function, DASTCOM5 data (specially strings) is ready to use (decoded and improved strings, etc):
End of explanation
aphelion_condition = (2 * db['A'] - db['QR']) < 0.983
axis_condition = db['A'] < 1.3 
atiras = db[aphelion_condition & axis_condition]
len(atiras)
Explanation: Panda offers many functionalities, and can also be used in the same way as the ast_db and comet_db functions:
End of explanation
len(atiras[atiras.A < 0])
Explanation: What? I said they can be used in the same way!
Dont worry :) If you want to know what's happening here, the only difference is that we are now working with comets too, and some comets have a negative semi-major axis!
End of explanation
axis_condition = (db['A'] < 1.3) & (db['A'] > 0)
atiras = db[aphelion_condition & axis_condition]
len(atiras)
Explanation: So, rewriting our condition:
End of explanation
<END_TASK>