# Path: mlat/geodesy.py
# WGS84_A = 6378137.0
# WGS84_F = 1.0/298.257223563
# WGS84_B = WGS84_A * (1 - WGS84_F)
# WGS84_ECC_SQ = 1 - WGS84_B * WGS84_B / (WGS84_A * WGS84_A)
# WGS84_ECC = math.sqrt(WGS84_ECC_SQ)
# SPHERICAL_R = 6371e3
#     N = WGS84_A / math.sqrt(1 - WGS84_ECC_SQ * math.sin(lat)**2)
# def llh2ecef(llh):
# def ecef2llh(ecef):
# def greatcircle(p0, p1):
# def ecef_distance(p0, p1):
# 
# Path: mlat/profile.py
# def trackcpu(f, **kwargs):
# def dump_cpu_profiles(tofile=None):
# def trackcpu(f, name=None, **kwargs):
#     def cpu_measurement_wrapper(*args, **kwargs):
# def dump_cpu_profiles(tofile=sys.stderr):
# 
# Path: mlat/server/clocknorm.py
# class _Predictor(object):
#     def __init__(self, predict, variance):
# def _identity_predict(x):
# def _make_predictors(clocktracker, station0, station1):
# def _label_heights(g, node, heights):
# def _tallest_branch(g, node, heights, ignore=None):
# def _convert_timestamps(g, timestamp_map, predictor_map, node, results, conversion_chain, variance):
# def normalize(clocktracker, timestamp_map):
# 
# Path: mlat/server/solver.py
# def _residuals(x_guess, pseudorange_data, altitude, altitude_error):
# def solve(measurements, altitude, altitude_error, initial_guess):
# 
# Path: mlat/server/config.py
# MIN_NUC = 6
# MAX_RANGE = 500e3
# MAX_INTERMESSAGE_RANGE = 10e3
# MAX_ALT = 50000 * constants.FTOM
# MLAT_DELAY = 2.5
# SOLVER_MAXFEV = 50


import json
import asyncio
import logging
import operator
import numpy
import modes.message
from contextlib import closing
from mlat import geodesy, constants, profile
from mlat.server import clocknorm, solver, config
                    if user:
                        s.add(user)
            except FileNotFoundError:
                pass

            glogger.info("Read {n} blacklist entries".format(n=len(s)))

        self.blacklist = s

    def reopen_pseudoranges(self):
        if self.pseudorange_file:
            self.pseudorange_file.close()
            self.pseudorange_file = None

        self.pseudorange_file = open(self.pseudorange_filename, 'a')

    @profile.trackcpu
    def receiver_mlat(self, receiver, timestamp, message, utc):
        # use message as key
        group = self.pending.get(message)
        if not group:
            group = self.pending[message] = MessageGroup(message, utc)
            group.handle = asyncio.get_event_loop().call_later(
                config.MLAT_DELAY,
                self._resolve,
                group)

        group.copies.append((receiver, timestamp, utc))
        group.first_seen = min(group.first_seen, utc)


# Path: mlat/geodesy.py
# WGS84_A = 6378137.0
# WGS84_F = 1.0/298.257223563
# WGS84_B = WGS84_A * (1 - WGS84_F)
# WGS84_ECC_SQ = 1 - WGS84_B * WGS84_B / (WGS84_A * WGS84_A)
# WGS84_ECC = math.sqrt(WGS84_ECC_SQ)
# SPHERICAL_R = 6371e3
#     N = WGS84_A / math.sqrt(1 - WGS84_ECC_SQ * math.sin(lat)**2)
# def llh2ecef(llh):
# def ecef2llh(ecef):
# def greatcircle(p0, p1):
# def ecef_distance(p0, p1):
# 
# Path: mlat/profile.py
# def trackcpu(f, **kwargs):
# def dump_cpu_profiles(tofile=None):
# def trackcpu(f, name=None, **kwargs):
#     def cpu_measurement_wrapper(*args, **kwargs):
# def dump_cpu_profiles(tofile=sys.stderr):
# 
# Path: mlat/server/clocknorm.py
# class _Predictor(object):
#     def __init__(self, predict, variance):
# def _identity_predict(x):
# def _make_predictors(clocktracker, station0, station1):
# def _label_heights(g, node, heights):
# def _tallest_branch(g, node, heights, ignore=None):
# def _convert_timestamps(g, timestamp_map, predictor_map, node, results, conversion_chain, variance):
# def normalize(clocktracker, timestamp_map):
# 
# Path: mlat/server/solver.py
# def _residuals(x_guess, pseudorange_data, altitude, altitude_error):
# def solve(measurements, altitude, altitude_error, initial_guess):
# 
# Path: mlat/server/config.py
# MIN_NUC = 6
# MAX_RANGE = 500e3
# MAX_INTERMESSAGE_RANGE = 10e3
# MAX_ALT = 50000 * constants.FTOM
# MLAT_DELAY = 2.5
# SOLVER_MAXFEV = 50


# Path: mlat/server/mlattrack.py
import json
import asyncio
import logging
import operator
import numpy
import modes.message
from contextlib import closing
from mlat import geodesy, constants, profile
from mlat.server import clocknorm, solver, config

                    if user:
                        s.add(user)
            except FileNotFoundError:
                pass

            glogger.info("Read {n} blacklist entries".format(n=len(s)))

        self.blacklist = s

    def reopen_pseudoranges(self):
        if self.pseudorange_file:
            self.pseudorange_file.close()
            self.pseudorange_file = None

        self.pseudorange_file = open(self.pseudorange_filename, 'a')

    @profile.trackcpu
    def receiver_mlat(self, receiver, timestamp, message, utc):
        # use message as key
        group = self.pending.get(message)
        if not group:
            group = self.pending[message] = MessageGroup(message, utc)
            group.handle = asyncio.get_event_loop().call_later(
                config.MLAT_DELAY,
                self._resolve,
                group)

        group.copies.append((receiver, timestamp, utc))
        group.first_seen = min(group.first_seen, utc)


    @profile.trackcpu