Trying to write CZML file from a Python dataframe

So, I’ve slapped something together in python to create a list of dictionary of orbit times with respect to the circumference

import pandas as pd
import numpy as np

def calculate_periods(df:pd.DataFrame) -> pd.DataFrame:
  df['orbits'] = np.power((df[['x', 'y', 'z']] - df[['x', 'y', 'z']].shift(1)).prod(axis=1).abs(), 1/3).cumsum() // (2.25 * np.pi * np.power(df_tst[['x', 'y', 'z']].prod(axis=1).abs(), 1/3).mean()) # surface circumference of the earth is about 40075 km, not necessarily orbit circumference
  
  df['t_delta'] = (df['Epoch'] - df['Epoch'].shift(1)).dt.total_seconds()
  
  df_r = df[['t_delta', 'orbits']].groupby(['orbits']).sum()

  df_r['e2'] = df[['e', 'orbits']].groupby(['orbits']).last()
  df_r['e1'] = df_r['e2'].shift(1)
  df_r['e1'].iloc[0] = df['e'].iloc[0]
  # df_r['e1'] = df[['e', 'orbits']].groupby(['orbits']).first()
  
  return df_r[['t_delta', 'e1', 'e2']]

def calculate_lead_times(df:pd.DataFrame) -> list[dict]:
  df_r = calculate_periods(df)

  return df_r.apply(lambda x:{
    "interval":f"{x['e1']}/{x['e2']}",
    "epoch":x['e1'],
    "number":[
      0, x['t_delta'],
      x['t_delta'], 0
    ]
  }, axis=1).tolist()

def calculate_trail_times(df:pd.DataFrame) -> list[dict]:
  df_r = calculate_periods(df)
  
  return df_r.apply(lambda x:{
    "interval":f"{x['e1']}/{x['e2']}",
    "epoch":x['e1'],
    "number":[
      0, 0,
      x['t_delta'], x['t_delta']
    ]
  }, axis=1).tolist()

It starts by (site note, ‘Epoch’ is a datetime object and ‘e’ a string epoch in the format Cesium likes):

  • calculating the orbit length by cumulatively summing the absolute length of vectors between points
  • integer dividing it by the orbit circumference calculated from the mean satellite radius vector which is then used to calculate the “mean orbit circumference”. I know it should be 2 * pi * r but 2 tends to fall a bit short because, calculating using a mean value, and 2.25 gives a bit of overlap.
  • That gives a count of what orbit each point is in.
  • Calculate the change in time ‘t_delta’ in seconds
  • Group the data by orbits and:
    • Sum the ‘t_delta’ values by orbit so you get how long each orbit is in time
    • Get the last string epoch in the orbit.
    • Set the first string epoch by shifting the last string epoch.
    • Set the first element of the string epoch (previously a NaN object) to the first element in the string epochs.
  • Then I return the newly created dataframe in the order I prefer it.
  • The functions calculate_lead_times and calculate_trail_times just reformat the data into dictionaries and return the dictionaries as a list of dictionaries.

The result looks like this:

Edit:
The data from calculate_periods looks like:

orbits t_delta e1 e2
0 5940 2023-07-01T01:39:00Z 2023-07-01T03:18:00Z
1 5940 2023-07-01T03:18:00Z 2023-07-01T04:57:00Z
2 5940 2023-07-01T04:57:00Z 2023-07-01T06:36:00Z