NavData
This tutorial shows how to use the NavData class, including how to initialize instances and perform basic operations.
[1]:
import numpy as np
import pandas as pd
import gnss_lib_py as glp
[2]:
# Get data path of example file
glp.make_dir("../data")
!wget https://raw.githubusercontent.com/Stanford-NavLab/gnss_lib_py/main/notebooks/tutorials/data/myreceiver.csv --quiet -nc -O "../data/myreceiver.csv"
data_path = "../data/myreceiver.csv"
Initializing
Create an empty NavData class instance
[3]:
empty_nav_data = glp.NavData()
print(empty_nav_data)
Empty NavData
Rows: []
Index: []
Create a NavData class from a csv file
[4]:
nav_data_csv = glp.NavData(csv_path=data_path)
print(nav_data_csv)
myTimestamp mySatId myPseudorange
0 10 10 270000001
1 10 14 270000007
2 10 7 270000004
3 10 3 270000005
4 11 10 270000002
5 11 14 270000008
6 11 7 270000003
7 11 3 270000004
Create an empty NavData class from a pandas DataFrame
[5]:
# Convert the csv file to a pd.DataFrame for this illustration
pd_df = pd.read_csv(data_path)
# Load pd.DataFrame into NavData using pd.DataFrame instance
nav_data_pd = glp.NavData(pandas_df=pd_df)
print(nav_data_pd)
myTimestamp mySatId myPseudorange
0 10 10 270000001
1 10 14 270000007
2 10 7 270000004
3 10 3 270000005
4 11 10 270000002
5 11 14 270000008
6 11 7 270000003
7 11 3 270000004
Create a NavData class instance from a numpy array
[6]:
np_array = np.eye(4)
nav_data_np = glp.NavData(numpy_array=np_array)
print(nav_data_np)
0 1 2 3
0 1.0 0.0 0.0 0.0
1 0.0 1.0 0.0 0.0
2 0.0 0.0 1.0 0.0
3 0.0 0.0 0.0 1.0
Accessing values
For this example, we will use the csv file that we previously loaded. This file has the following contents:
myTimestamp |
mySatId |
myPseudorange |
|---|---|---|
10 |
G10 |
270000001 |
10 |
G14 |
270000007 |
10 |
G07 |
270000004 |
10 |
G03 |
270000005 |
11 |
G10 |
270000002 |
11 |
G14 |
270000008 |
11 |
G07 |
270000003 |
11 |
G03 |
270000004 |
NavData stores the different types of measurements, like myTimestamp as rows. So, each row contains the variable at different times/measurements. In this case, the myPseudorange row contains values for different timestamps and satellite IDs
Values in rows can be accessed by using the name of the row or the number of the row
[7]:
nav_data_csv['myTimestamp']
[7]:
array([10, 10, 10, 10, 11, 11, 11, 11])
[8]:
nav_data_csv[0]
[8]:
array([10, 10, 10, 10, 11, 11, 11, 11])
By specifying a column number (or slice of columns) along with the row label/number, a sub part of the matrix can be accessed as well
[9]:
nav_data_csv['myPseudorange', :3]
[9]:
array([270000001, 270000007, 270000004])
To access multiple rows using labels, pass the labels as a list of strings or slice of numbers
[10]:
nav_data_csv[['myTimestamp', 'myPseudorange']]
[10]:
array([[1.00000000e+01, 1.00000000e+01, 1.00000000e+01, 1.00000000e+01,
1.10000000e+01, 1.10000000e+01, 1.10000000e+01, 1.10000000e+01],
[2.70000001e+08, 2.70000007e+08, 2.70000004e+08, 2.70000005e+08,
2.70000002e+08, 2.70000008e+08, 2.70000003e+08, 2.70000004e+08]])
However, to ensure compatability with accessing operations, you cannot access string and numeric values jointly. This is to prevent unexpected behaviour that might result on performing mathematical operations with strings and numbers.
If you attempt to access a combination of strings and numbers, the method will return an AssertionError
[11]:
try:
nav_data_csv[0:2]
except AssertionError as err:
print(err)
Setting values
You can update values for existing rows by indexing those rows and assigning an array
[12]:
nav_data_csv['myPseudorange'] = 10*np.arange(8)
nav_data_csv['myPseudorange']
[12]:
array([ 0, 10, 20, 30, 40, 50, 60, 70])
You can also set individual values by accessing the specific rows and columns that you want to reassign
[13]:
nav_data_csv['myPseudorange', 2] = 111
nav_data_csv['myPseudorange']
[13]:
array([ 0, 10, 111, 30, 40, 50, 60, 70])
Setting new row
To set numeric values for a new row, access the row with the label name and assign the value to that row.
[14]:
nav_data_csv['new_row'] = np.arange(8)
nav_data_csv['new_row']
[14]:
array([0, 1, 2, 3, 4, 5, 6, 7])
New string rows can also be created similarly.
Note that while creating rows with string values, you must set the dtype of the row to object
[15]:
nav_data_csv['new_string_row'] = np.array(['string1', 'string1', 'string1', 'string1',
'string2', 'string2', 'string2', 'string2'], dtype=object)
nav_data_csv['new_string_row']
[15]:
array([np.str_('string1'), np.str_('string1'), np.str_('string1'),
np.str_('string1'), np.str_('string2'), np.str_('string2'),
np.str_('string2'), np.str_('string2')], dtype=object)
Find rows, shape and length
You can see which rows are currently in NavData using NavData.rows. The number of columns can be viewed using len(NavData) or NavData.num_cols and the shape of the array can be viewed using NavData.shape.
[16]:
nav_data_csv.rows
[16]:
['myTimestamp', 'mySatId', 'myPseudorange', 'new_row', 'new_string_row']
[17]:
nav_data_csv.shape
[17]:
(5, 8)
[18]:
len(nav_data_csv)
[18]:
8
[19]:
nav_data_csv.num_cols
[19]:
8
Removing rows or columns
To remove rows, use the NavData.remove() method, specifying the rows and columns you want to remove.
[20]:
nav_data_removed = nav_data_csv.remove(rows=['new_row', 'new_string_row'])
print(nav_data_removed.rows)
print(nav_data_removed.shape)
['myTimestamp', 'mySatId', 'myPseudorange']
(3, 8)
[21]:
nav_data_removed = nav_data_csv.remove(cols=[0, 1])
print(nav_data_removed.shape)
(5, 6)
Copy
For NavData.copy(), similar to the remove method, specify the rows and columns you want to copy into a new NavData instance.
Specifying rows, columns or both copies specified rows and columns.
Note that currently, rows and columns must be specified as lists.
[22]:
nav_data_np_copy = nav_data_np.copy(rows=[0,1], cols=list(range(4)))
print('Original NavData array')
print(nav_data_np[:, :])
print('Copied NavData array')
print(nav_data_np_copy[:, :])
Original NavData array
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
Copied NavData array
[[1. 0. 0. 0.]
[0. 1. 0. 0.]]
If you don’t specify any rows or columns, the entire NavData will be copied
[23]:
nav_data_np_copy = nav_data_np.copy()
print('Original NavData array')
print(nav_data_np[:, :])
print('Copied NavData array')
print(nav_data_np_copy[:, :])
Original NavData array
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
Copied NavData array
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
Convert to pd.DataFrame and save to csv
You can use the NavData.to_csv() method to save the data as a csv file and NavData.pandas_df() to get the equivalent pd.DataFrame
[24]:
nav_data_pd.pandas_df()
[24]:
| myTimestamp | mySatId | myPseudorange | |
|---|---|---|---|
| 0 | 10 | 10 | 270000001 |
| 1 | 10 | 14 | 270000007 |
| 2 | 10 | 7 | 270000004 |
| 3 | 10 | 3 | 270000005 |
| 4 | 11 | 10 | 270000002 |
| 5 | 11 | 14 | 270000008 |
| 6 | 11 | 7 | 270000003 |
| 7 | 11 | 3 | 270000004 |
To save, specify the path in NavData.to_csv()
[25]:
# nav_data_pd.to_csv('desired path for csv file')
Looping over columns
You can loop over all columns using in-built looping functions. In this example, we terminate the loop after 3 runs for display clarity
[26]:
for col_idx, nav_data_col in enumerate(nav_data_pd):
print('Current column number', col_idx)
print('Current column')
print(nav_data_col)
if col_idx >= 3:
break
Current column number 0
Current column
myTimestamp mySatId myPseudorange
0 10 10 270000001
Current column number 1
Current column
myTimestamp mySatId myPseudorange
0 10 14 270000007
Current column number 2
Current column
myTimestamp mySatId myPseudorange
0 10 7 270000004
Current column number 3
Current column
myTimestamp mySatId myPseudorange
0 10 3 270000005