Determine apex location for the field line passing through input point.
    
    Employs a two stage method. A broad step (100 km) field line trace spanning 
    Northern/Southern footpoints is used to find the location with the largest 
    geodetic (WGS84) height. A higher resolution trace (.1 km) is then used to 
    get a better fix on this location. Greatest geodetic height is once again 
    selected.
    
    Parameters
    ----------
    glats : list-like of floats (degrees)
        Geodetic (WGS84) latitude
    glons : list-like of floats (degrees)
        Geodetic (WGS84) longitude 
    alts : list-like of floats (km)
        Geodetic (WGS84) altitude, height above surface
    dates : list-like of datetimes
        Date and time for determination of scalars

    Returns
    -------
    (float, float, float, float, float, float)
        ECEF X (km), ECEF Y (km), ECEF Z (km), 
        Geodetic Latitude (degrees), 
        Geodetic Longitude (degrees), 
        Geodetic Altitude (km)

def apex_location_info(glats, glons, alts, dates):
    """Determine apex location for the field line passing through input point.
    
    Employs a two stage method. A broad step (100 km) field line trace spanning 
    Northern/Southern footpoints is used to find the location with the largest 
    geodetic (WGS84) height. A higher resolution trace (.1 km) is then used to 
    get a better fix on this location. Greatest geodetic height is once again 
    selected.
    
    Parameters
    ----------
    glats : list-like of floats (degrees)
        Geodetic (WGS84) latitude
    glons : list-like of floats (degrees)
        Geodetic (WGS84) longitude 
    alts : list-like of floats (km)
        Geodetic (WGS84) altitude, height above surface
    dates : list-like of datetimes
        Date and time for determination of scalars

    Returns
    -------
    (float, float, float, float, float, float)
        ECEF X (km), ECEF Y (km), ECEF Z (km), 
        Geodetic Latitude (degrees), 
        Geodetic Longitude (degrees), 
        Geodetic Altitude (km)
        
    """

    # use input location and convert to ECEF
    ecef_xs, ecef_ys, ecef_zs = geodetic_to_ecef(glats, glons, alts)
    # prepare parameters for field line trace
    step_size = 100.
    max_steps = 1000
    steps = np.arange(max_steps)
    # high resolution trace parameters
    fine_step_size = .01
    fine_max_steps = int(step_size/fine_step_size)+10
    fine_steps = np.arange(fine_max_steps)
    # prepare output
    out_x = []
    out_y = []
    out_z = []

    for ecef_x, ecef_y, ecef_z, glat, glon, alt, date in zip(ecef_xs, ecef_ys, ecef_zs, 
                                                             glats, glons, alts, 
                                                             dates):
        # to get the apex location we need to do a field line trace
        # then find the highest point
        trace = full_field_line(np.array([ecef_x, ecef_y, ecef_z]), date, 0., 
                                steps=steps,
                                step_size=step_size, 
                                max_steps=max_steps)
        # convert all locations to geodetic coordinates
        tlat, tlon, talt = ecef_to_geodetic(trace[:,0], trace[:,1], trace[:,2])        
        # determine location that is highest with respect to the geodetic Earth
        max_idx = np.argmax(talt)
        # repeat using a high resolution trace one big step size each 
        # direction around identified max
        # recurse False ensures only max_steps are taken
        trace = full_field_line(trace[max_idx,:], date, 0., 
                                steps=fine_steps,
                                step_size=fine_step_size, 
                                max_steps=fine_max_steps, 
                                recurse=False)
        # convert all locations to geodetic coordinates
        tlat, tlon, talt = ecef_to_geodetic(trace[:,0], trace[:,1], trace[:,2])
        # determine location that is highest with respect to the geodetic Earth
        max_idx = np.argmax(talt)
        # collect outputs
        out_x.append(trace[max_idx,0])
        out_y.append(trace[max_idx,1])
        out_z.append(trace[max_idx,2])
        
    out_x = np.array(out_x)
    out_y = np.array(out_y)
    out_z = np.array(out_z)
    glat, glon, alt = ecef_to_geodetic(out_x, out_y, out_z)
    
    return out_x, out_y, out_z, glat, glon, alt