Basic Usage

Most operations in rocks can be executed both via the command line and the python interface. The former is useful for quick data exploration, the latter for a scripted data analysis. The available functions can generally be divided into identification, data exploration, and data analysis.

Identification

rocks allows to quickly resolve the identity of asteroids, returning the current official designation and, if applicable, the number. It recognizes aliases such as previously used provisional designations.

The $ rocks id [identifier] command allows for quick name resolution via the command line. You can pass any valid asteroid identifier. Note that whitespace and capitalization are irrelevant.

$ rocks id 221
(221) Eos

$ rocks id Schwartz
(13820) Schwartz

$ rocks id "1902 UG"
(19) Fortuna

$ rocks id 2012fg3
(nan) 2012 FG3

$ rocks id J65B00A
(1727) Mette

The rocks.id() function identifies one or many asteroids based on user-provided identifiers It is quite straight-forward: providing a single identifier (or a list of many) returns a tuple containing the (asteroid name, asteroid number) (or a list of tuples).

>>> import rocks
>>> rocks.id(11334)
('Rio de Janeiro', 11334)
>>> rocks.id(["SCHWARTZ", "J95X00A", "47", 3.])
[('Schwartz', 13820), ('1995 XA', 24850), ('Aglaja', 47), ('Juno', 3)]

Hint

Note the alphabetical order: first returned is the name, then the number.

The command line offers more functionality related to identification of asteroids:

Using the plural ids returns the list of aliases under which the asteroid may be listed as well.

$ rocks ids aschera                                                                                     master
  (214) Aschera, aka
  ['1880 DB', '1903 SE', '1947 BP', '1948 JE', '1949 QG2', '1949 SX1',
   '1950 XH', '1953 OO', '2000214', 'I80D00B', 'J03S00E', 'J47B00P',
   'J48J00E', 'J49Q02G', 'J49S01X', 'J50X00H', 'J53O00O']

All these aliases are automatically resolved to (214) Aschera by rocks using quaero.

Use $ rocks who to get the citations associated to each named asteroid.

$ rocks who zappafrank
(3834) Zappafrank
   Named in memory of Frank Zappa (1940-1993), rock musician and composer [...]

If the fzf tool is installed, executing the identification commands id|ids|who without passing and identifier will launch an interactive search through all asteroids in the asteroid name-number index. In the example below, asteroid (3834) Zappafrank is selected interactively from all 1,218,250 recognised asteroid names:

$ rocks who

  (225250)  Georgfranziska
  (16127)   Farzan-Kashani
  (520)     Franziska
  (3183)    Franzkaiser
> (3834)    Zappafrank

> frank za  < 5/1218250

Furthermore, rocks provides a hint for unidentified names with close matches in the asteroid name-number index.

$ rocks id barkajdetolli
rocks: Could not find match for id Barkajdetolli.

Could this be the rock you're looking for?
  (4524) Barklajdetolli

Hint

Whitespace and capitalization are irrelevant for successful identification of the passed identifier.

Data Exploration

The quick look-up of asteroid parameter values is most convenient via the command line. The most general use case is to provide an asteroid parameter and identifier to echo the value from the ssoCard.

$ rocks diameter pallas
514.1 +- 3.906 km
>>> import rocks
>>> pallas = rocks.Rock('pallas')
>>> pallas.diameter.value
514.1
>>> pallas.diameter.error
3.906
>>> pallas.diameter.unit
'km'

Important

All data that you look up is cached on your computer to increase the execution speed repeated queries. Remember to run $ rocks status to update or remove the cached data regularly (e.g. once a month) as there may be new observations available.

The parameter names follow the structure of the ssoCard. The different levels are connected via dots, e.g. parameters.physical.albedo. For convenience, parameters.physical and parameters.dynamical does not have to be specified. For even more convenience, there are shortcuts defined for some parameters to reduce the amount of typing, such as proper_elements.proper_semi_major_axis -> ap, orbital_elements.orbital_period -> P.

$ rocks parameters.dynamical.orbital_elements.semi_major_axis ceres
2.76661907 +- 0.00000010 au

$ rocks orbital_elements.semi_major_axis ceres
2.76661907 +- 0.00000010 au

$ rocks a ceres
2.76661907 +- 0.00000010 au

A complete list is given in the appendix.[1]

Warning

Some parameter names (e.g. class) are protected python keywords and can therefore not be used to refer to the asteroid parameter. These names carry a _-suffix instead when using the python interface:

>>> import rocks
>>> rocks.Rock(1).taxonomy.class_.value
'C'

The complete list of parameters which require the suffix is given in the appendix. It contains all parameters for which the following evaluates to True:

>>> import keyword
>>> keyword.iskeyword('class')
True

Another Warning

Some parameter names in the ssoCard are invalid variable names in python, such as the name of colors (e.g. c-o). In general, characters such as -, /, ., are replaced by _ in parameter names (e.g. c_o).

Both the best-estimates stored in the ssoCard and the literature compilation of the parameters stored in the datacloud are available for look-up. In general, best-estimates are returned if the parameter is specified in singular form (e.g. albedo) while all available data is returned for the plural form (e.g. albedos).

$ rocks taxonomy aschera
E
$ rocks taxonomies aschera
+---+--------+---------+--------+-----------+-----------+-----------------+
|    class_ | complex | method | waverange | scheme    | shortbib        |
+---+--------+---------+--------+-----------+-----------+-----------------+
| 1 | E      | E       | Phot   | VIS       | Tholen    | Tholen+1989     |
| 2 | Xc     | X       | Spec   | VIS       | Bus       | Bus&Binzel+2002 |
| 3 | B      | B       | Spec   | VIS       | Bus       | Lazzaro+2004    |
| 4 | B      | B       | Spec   | VIS       | Tholen    | Lazzaro+2004    |
| 5 | Cgh    | Ch      | Spec   | VISNIR    | Bus-DeMeo | DeMeo+2009      |
| 6 | B      | B       | Spec   | VISNIR    | Bus       | deLeon+2012     |
| 7 | C      | C       | Spec   | VISNIR    | Bus-DeMeo | deLeon+2012     |
| 8 | B      | B       | Spec   | VISNIR    | Tholen    | deLeon+2012     |
| 9 | E      | E       | Spec   | VISNIR    | Mahlke    | Mahlke+2022     |
+---+--------+---------+--------+-----------+-----------+-----------------+

An overview of the available parameters is given in the appendix. Alternatively, you can run $ rocks parameters to echo the template form of the ssoCard in JSON format.

To echo the complete ssoCard of an asteroid, use the $ rocks info command.

Data Analysis

To build an analysis around the asteroid data compiled in SsODNet, rocks provides a python interface built around the Rock class. Each Rock object represents an asteroid. They are created by passing an identifier, which is then resolved and the data corresponding to the asteroid is retrieved.

>>> import rocks
>>> ceres = rocks.Rock(1)
>>> ceres
Rock(number=1, name='Ceres')
>>> vesta = rocks.Rock("1807 FA")
>>> vesta
Rock(number=4, name='Vesta')

Hint

Creating a large number of Rock objects can take a while if the requested data is not cached on the computer. Using the rocks.rocks() function drastically speeds up the process by first requesting all required data asynchronously from the SsODNet servers. See this tutorial.

All ssoCard parameters are then available via the dot notation. The same shortcuts as explained above are implemented.

>>> ceres.parameters.physical.taxonomy.class_.value
'C'
>>> ceres.taxonomy.class_.value
'C'
>>> ceres.a.value
2.3615126

Hint

Errors in the ssoCard are given as upper and lower value. They are accessed as described above:

>>> ceres.diameter.error.min_
0.4
>>> ceres.diameter.error.max_
-0.4

To get the mean of the upper and lower error, you can use the error_ attribute instead:

>>> ceres.diameter.error_
0.4

Access of datacloud tables

datacloud catalogues of an asteroid are not loaded by default when creating a Rock instance, as each table requires an additional remote query. Tables are explicitly requested using the datacloud argument. Single tables can be requested by passing the table name to the datacloud.

>>> ceres = rocks.Rock(1, datacloud='masses')

Multiple tables are retrieved by passing a list of table names.

>>> ceres = rocks.Rock(1, datacloud=['taxonomies', 'masses'])
>>> ceres.taxonomies.class_
['G', 'C', 'C', 'C', 'C', 'G', 'C']
>>> ceres.taxonomies.shortbib
['Tholen+1989', 'Bus&Binzel+2002', 'Lazzaro+2004', 'Lazzaro+2004',
 'DeMeo+2009', 'Fornasier+2014', 'Fornasier+2014']

Once ingested into the Rock object, each catalogue is essentially a pandas.DataFrame, making operations such as accessing the catalogue values identical to the standard pandas operations.

>>> vesta = rocks.Rock(4, datacloud="diamalbedo")
>>> for _, entry in vesta.diameters.iterrows():
        print(f"{entry.diameter:.1f}km, observed via {entry.method} by {entry.shortbib}")

507.3km, observed via TE-IM by Drummond+1998
530.0km, observed via STM by Morrison+2007
510.0km, observed via TE-IM by Drummond+2008
468.3km, observed via STM by Tedesco+2001
520.4km, observed via STM by Ryan+2010
515.9km, observed via NEATM by Ryan+2010
521.7km, observed via NEATM by Usui+2011
525.4km, observed via SPACE by Russell+2012
562.6km, observed via NEATM by Alí-Lagoa+2018
505.4km, observed via OCC by Herald+2019
522.0km, observed via OCC by Herald+2019

Some observations in the catalogues might be preferred to others. For example, a taxonomical classification using a visible-near-infrared spectrum is more reliable than one based on visible colours. rocks includes opinionated selections of preferred observations based on the observation methods, just as the ssoCard does. Catalogues have preferred attributes, which are lists containing True if the corresponding observation is preferred, and False otherwise.

>>> ceres = rocks.Rock(1, datacloud='masses')
>>> len(ceres.masses.mass)  # 20 observations of Ceres' mass in database
20
>>> for i, obs in ceres.masses.iterrows():  # datacloud catalogues are pandas DataFrames
>>>   mean_error = (obs.err_mass_up + abs(obs.err_mass_do wn)) / 2
>>>   print(f"[{'X' if obs.preferred else ' '}] {obs.mass} +- {mean_error} [{obs.shortbib}, Method: {obs.method}]")
[ ] 8.27e+20 +- 3.78e+19 [Kuzmanoski+1996, Method: DEFLECT]
[ ] 8.73e+20 +- 7.96e+18 [Hilton+1999, Method: DEFLECT]
[ ] 9.04e+20 +- 1.39e+19 [Kova+2012, Method: DEFLECT]
[ ] 9.19e+20 +- 1.41e+19 [Sitarski+1995, Method: DEFLECT]
[ ] 9.29e+20 +- 1.79e+19 [Carpino+1996, Method: DEFLECT]
[ ] 9.29e+20 +- 3.68e+18 [Fienga+2013, Method: EPHEM]
[ ] 9.29e+20 +- 3.84e+18 [Fienga+2014, Method: EPHEM]
[ ] 9.31e+20 +- 6.46e+18 [Konopliv+2011, Method: EPHEM]
[ ] 9.32e+20 +- 9.32e+19 [Folkner+2009, Method: EPHEM]
[ ] 9.3483e+20 +- 5.967e+19 [Goffin1991, Method: DEFLECT]
[ ] 9.35e+20 +- 5.57e+18 [Konopliv+2006, Method: DEFLECT]
[ ] 9.35e+20 +- 5.97e+19 [Goffin+2001, Method: DEFLECT]
[ ] 9.35e+20 +- 7.96e+18 [Michalak+2000, Method: DEFLECT]
[ ] 9.38348e+20 +- 2.28689e+18 [Fienga+2019, Method: EPHEM]
[X] 9.384e+20 +- 1e+17 [Russell+2016, Method: SPACE]
[ ] 9.38e+20 +- 2.21e+18 [Viswanathan+2017, Method: EPHEM]
[ ] 9.394e+20 +- 1.312e+18 [Baer+2017, Method: EPHEM]
[ ] 9.39e+20 +- 1.57e+18 [Pitjeva+2013, Method: EPHEM]
[ ] 9.39e+20 +- 2.31e+18 [Fienga+2020, Method: EPHEM]
[ ] 9.39e+20 +- 5.97e+18 [Pitjeva+2010, Method: EPHEM]
[ ] 9.40797e+20 +- 0.0 [Folkner+2014, Method: EPHEM]
[ ] 9.41e+20 +- 5.69e+18 [Kuchynka+2013, Method: EPHEM]
[ ] 9.42e+20 +- 2.65e+18 [Zielenbach+2011, Method: DEFLECT]
[ ] 9.42e+20 +- 2.68e+18 [Zielenbach+2011, Method: DEFLECT]
[ ] 9.42e+20 +- 5.17e+18 [Kova+2007, Method: DEFLECT]
[ ] 9.44e+20 +- 5.97e+17 [Goffin+2014, Method: DEFLECT]
[ ] 9.45e+20 +- 3.98e+18 [Pitjeva+2004, Method: DEFLECT]
[ ] 9.45e+20 +- 4.18e+18 [Pitjeva+2005, Method: EPHEM]
[ ] 9.45e+20 +- 5.97e+18 [Baer+2008a, Method: DEFLECT]
[ ] 9.46366e+20 +- 5.5692e+18 [Fienga+2011, Method: EPHEM]
[ ] 9.46e+20 +- 1.43e+18 [Baer+2011, Method: DEFLECT]
[ ] 9.46e+20 +- 7.96e+17 [Fienga+2008, Method: EPHEM]
[ ] 9.47e+20 +- 4.57e+18 [Viateau+1998, Method: DEFLECT]
[ ] 9.4e+20 +- 3.1e+18 [Zielenbach+2011, Method: DEFLECT]
[ ] 9.52e+20 +- 4.63e+18 [Zielenbach+2011, Method: DEFLECT]
[ ] 9.52e+20 +- 7.76e+18 [Viateau+1997b, Method: DEFLECT]
[ ] 9.54e+20 +- 1.69e+19 [Sitarski+1992, Method: DEFLECT]
[ ] 9.55e+20 +- 4.38e+19 [Williams+1992, Method: DEFLECT]
[ ] 9.57e+20 +- 1.99e+18 [Pitjeva+2001, Method: DEFLECT]
[ ] 9.94e+20 +- 3.98e+19 [Viateau+1995, Method: DEFLECT]

Note

As the diamalbedo catalogue contains both diameters and albedos, it contains the preferred_diameter and preferred_albedo attributes.

rocks offers an easy way to compute the weighted averages of the preferred property measurements, see for example: what’s the weighted average albedo of (6) Hebe?

Access of ssoBFT

The ssoBFT contains all best-estimate parameters of all known minor bodies in SsODNet. It aggregates 591 of about 1,200,000 objects. For quick execution times, rocks stores the parquet version (~600MB) of the ssoBFT in the cache directory when it is first requested via the rocks.load_bft() function. The returned table is a pandas DataFrame and enables quick sample selection via minor body parameters.

>>> import rocks
>>> bft = rocks.load_bft()
>>> family_eos = bft[bft['family.family_name'] == 'Eos']
>>> family_eos['albedo.value'].mean()
0.12367009372337404

To get the advantages of the Rock class, you can pass any subset of the ssoBFT to rocks.rocks. To get all asteroids in the family of (121) Hermione:

>>> family_hermione = bft[bft['family.family_name'] == 'hermione']  # pd.DataFrame
>>> family_hermione = rocks.rocks(family_hermione)  # list of Rock instances
>>> family_hermione
[Rock(number=121, name='Hermione'),
 Rock(number=168, name='Sibylla'),
 Rock(number=2634, name='James Bradley'),
 Rock(number=4003, name='Schumann'),
 ...
]

Or all asteroids in the Vesta family larger than 5km in diameter and with a taxonomic classification:

>>> subset_vesta = bft[(bft['family.family_name'] == 'Vesta') & (bft['diameter.value'] > 5) & (~pd.isna(bft['taxonomy.class']))]
>>> subset_vesta = rocks.rocks(subset_vesta)  # list of 82 Rocks

The valid column names for the selection are given on the ssoBFT API page.

Column Selection

The BFT is a large, sparse table containing many columns that you might not need routinely. On some machines, loading the entire table may further exceed the memory size and lead to crashes.

To reduce its size in memory and the time to load it, rocks by default only loads a subset of the available columns. You can define your own subset of columns by setting rocks.bft.COLUMNS to the list of the desired columns

>>> rocks.bft.COLUMNS = ['sso_number', 'diameter.value', 'mass.value', 'taxonomy.class', 'family.family_status']
>>> rocks.load_bft()  # loads rocks.bft.COLUMNS by default

Alternatively, you can directly pass the list to the columns keyword argument:

>>> rocks.load_bft(columns=['sso_number', 'diameter.value', 'mass.value', 'taxonomy.class', 'family.family_status'])

You can request the full table using the full keyword argument (though it’s not recommended):

>>> bft = rocks.load_bft(full=True)

Footnotes