


def find_passes(duration):
    #instrument function calls
    sat_azel.calls = 0

    # orbital period in seconds
    period = 24.0 * 60.0 * 60.0 / sat._n



    # coarse steps to find the points near (enough) to elevation peaks
    time_coarse = np.arange(0, INTERVAL_SECONDS, period/STEPS_PER_ORBIT)


    el_coarse = np.fromiter((sat_azel(dt)[1] for dt in time_coarse), np.float, time_coarse.size)

    peak_coarse_idx = argrelmax(el_coarse)[0]


    # find all local elevation maxima
    def fneg(dt):
        return -sat_azel(dt)[1]

    def truepeak(t, tol=0.1):
        r = minimize_scalar(
                fneg,
                bracket=(t-period/STEPS_PER_ORBIT, t+period/STEPS_PER_ORBIT),
                tol = tol/t)
        return (r.x, -r.fun)

    peak_true_times = np.zeros((len(peak_coarse_idx),))
    peak_el = np.zeros((len(peak_coarse_idx),))

    for i, dt in enumerate(time_coarse[peak_coarse_idx]):
        t, el = truepeak(dt)
        peak_true_times[i] = t
        peak_el[i] = el

    # select the visible passes
    visible_idx = np.where(peak_el > HORIZON)[0]
    visible_el = peak_el[visible_idx]
    visible_tca = peak_true_times[visible_idx]

    # find AOS events
    def f(t):
        return sat_azel(t)[1]

    def find_aos(t):
        a = (t - period*ORBIT_FRACTION)
        b = t
        return brentq(f, a, b, xtol=TOL)

    def find_los(t):
        a = t
        b = (t + period*ORBIT_FRACTION)
        return brentq(f, a, b, xtol=TOL)

    visible_aos = np.fromiter((find_aos(t) for t in visible_tca), np.float, len(visible_tca))
    visible_los = np.fromiter((find_los(t) for t in visible_tca), np.float, len(visible_tca))
    return (visible_aos, visible_tca, visible_los, visible_el, peak_true_times, peak_el)

(visible_aos, visible_tca, visible_los, visible_el, peak_true_times, peak_el) = find_passes(INTERVAL_SECONDS)

%timeit find_passes(INTERVAL_SECONDS)

print('N passes:', len(visible_tca))
print('N calls:', sat_azel.calls)
print('Avg calls per found pass:', sat_azel.calls / len(visible_tca))

plt.plot(peak_true_times, peak_el, '+')
plt.plot(visible_tca, visible_el, '+r')
plt.plot(visible_aos, np.zeros_like(visible_tca), '.r')
plt.plot(visible_los, np.zeros_like(visible_tca), '.r')

"""
Explanation: Compute sat position relative to GS with STEPS_PER_ORBIT number of time increments for 90 days.
End of explanation
"""


import sys

from satbazaar import db


observer = {
    'name':gs.name,
    'lat':gs.lat,
    'lon':gs.lon,
    'altitude':gs.elevation,
    'min_horizon': 0.0
}

satellite = {
    'name':line0,
    'tle':[line0, line1, line2],
    'norad_cat_id': int(line2.split()[1]),
}

passes = db.compute_passes_ephem([observer, satellite, start, len(visible_tca), INTERVAL_SECONDS/60])
%timeit -r1 -n1 passes = db.compute_passes_ephem([observer, satellite, start, len(visible_tca), INTERVAL_SECONDS/60])

# number of calls from an instrumented pyephem for these conditions
obj_cir_calls = 278228

"""
Explanation: Find time to compute using pyephem.observer.next_pass()
End of explanation
"""


100 * ((sat_azel.calls / 278228) - 1)

1/(sat_azel.calls / 278228)

len(passes)

def td(time):
    return (time - start).total_seconds()


plt.figure(figsize=(20, 6))

plt.interactive(False)
for p in passes:
    aos = td(p.start)
    tca = td(p.tca)
    los = td(p.end)
    el = p.max_el
    plt.plot(aos, 0.0, '+b')
    plt.plot(tca, el, '+b')
    plt.plot(los, 0.0, '+b')

plt.plot(visible_aos, np.zeros_like(visible_aos), 'xr')
plt.plot(visible_los, np.zeros_like(visible_aos), 'xr')
plt.plot(visible_tca, visible_el, 'xr')
plt.show()

"""
Explanation: Speedup factor and percentage reduction.
End of explanation
"""


