Example #1
0
    def __init__(self, *args, **kwargs):
        """
        Takes a set of input observations and fits the orbital elements. These can then be used to
        compute the position and error ellipse for the object on an arbitrary date.
        Requires: observatories.dat and binEphem.423.
        
        keyword arguments:
        obsfile -- file containing observation data, either in MPC format or as
                   JD HH:MM:SS.SS +DD:MM:SS.SS ERROR OBSCODE  or as
                   YYYY MM DD.DDDDD HH:MM:SS.SS +DD:MM:SS.SS ERROR OBSCODE
                   where the error is the astrometric error on each measurement in arcsec (default 0.2)
                   and OBSCODE is the observatory code in observatories.dat
                   The number of digits in each field is unrestricted, but ra and dec must not contain spaces.
        The following options should be used only if obsfile is None. Then they must all be used. If obsfile
        is supplied then these arguments are ignored.
        dates -- list of observation dates, either in JD or YYYY MM DD.DDDDD format
        ra -- list of RA in HH:MM:SS.SS format.
        dec -- list of DEC in +DD:MM:SS.SS format
        obscode -- list of observatory codes
        err -- measurement error in arcsec
        
        Methods:
           get_elements() -- returns aei orbital elements and their errors
           get_elements_abg() -- returns abg orbital elements and their errors
           barycentric_distance() -- barycentric distance and error
           perihelion() -- perihelion and error
           aphelion() -- aphelion and error
           cov_pq() -- covariance matrix for perihelion, aphelion
           plotEllipse() -- generates an error ellipse for a given covariance matrix
           predict_pos() -- predicted ra, dec, and error ellipse on a given date
           ellipticalBody() -- returns an EllipticalBody object with these orbital parameters, suitable for use by pyEphem
        """

        if 'file' in kwargs.keys():  # observations supplied in a file
            obsfile = kwargs['file']
            with open(obsfile, 'r') as fobs:
                self.nobs = 0  # determine the number of observations
                for line in fobs:
                    if line[0] != '#':
                        self.nobs += 1
                fobs.seek(0)  # rewind to the beginning
                self.obsarray = orbfit.OBSERVATION_ARRAY(
                    self.nobs)  # create empty array of observations
                iobs = 0
                for line in fobs:
                    if line[0] != '#':
                        thisobs = orbfit.OBSERVATION()
                        orbfit.scan_observation(line, thisobs)
                        orbfit.add_to_obsarray(self.obsarray, iobs, thisobs)
                        iobs += 1
                if 'err' in kwargs.keys(
                ):  # change: obserr need not be constant
                    obserr = kwargs['err']
        elif len(args):  # observations supplied in a Catalog object
            self.nobs = len(args[0])
            self.obsarray = orbfit.OBSERVATION_ARRAY(self.nobs)
            for iobs, pt in enumerate(args[0]):
                thisobs = orbfit.OBSERVATION()
                if pt.err is None:
                    pt.err = 0.15  # This is to avoid silent crash.
                if pt.obscode is None: pt.obscode = 807  # Ditto.
                obsline = str(ephem.julian_date(pt.date)) + ' ' + str(
                    pt.ra) + ' ' + str(pt.dec) + ' ' + str(pt.err) + ' ' + str(
                        pt.obscode)
                orbfit.scan_observation(obsline, thisobs)
                orbfit.add_to_obsarray(self.obsarray, iobs, thisobs)
        else:  # observations specified in input lists
            required_keys = ['dates', 'ra', 'dec', 'obscode']
            for k in required_keys:
                if k not in kwargs.keys():
                    raise KeyError('keyword ' + k + ' is missing')
            obsdate = kwargs['dates']
            ra = kwargs['ra']
            dec = kwargs['dec']
            obscode = kwargs['obscode']
            self.nobs = len(obsdate)
            if 'err' in kwargs.keys():  # change: obserr need not be constant
                obserr = kwargs['err']
                if not np.iterable(obserr):
                    obserr = [obserr for i in range(self.nobs)]
            else:
                obserr = [0.15 for i in range(self.nobs)
                          ]  # obervation astrometric error defaults to 0.15"
            assert self.nobs == len(ra) and self.nobs == len(
                dec) and self.nobs == len(obscode) and self.nobs == len(obserr)
            self.obsarray = orbfit.OBSERVATION_ARRAY(
                self.nobs)  # create empty array of observations
            for iobs in range(self.nobs):  # fill the OBSERVATION_ARRAY
                thisobs = orbfit.OBSERVATION()
                obsline = str(ephem.julian_date(obsdate[iobs])) + ' ' + str(
                    ra[iobs]) + ' ' + str(dec[iobs]) + ' ' + str(
                        obserr[iobs]) + ' ' + str(obscode[iobs])
                orbfit.scan_observation(obsline, thisobs)
                orbfit.add_to_obsarray(self.obsarray, iobs, thisobs)

        # At this point we have filled obsarray with the observations. Now fit the orbit.


#        orbfit.set_ephem_file('/Users/gerdes/TNO/pyOrbfit/binEphem.430')      # pick up the correct ephemeris and observatories file.
#        orbfit.set_observatory_file('/Users/gerdes/TNO/pyOrbfit/observatories.dat')   # Will need to handle pathnames more elegantly.

        self.orbit_abg = orbfit.PBASIS()
        self.orbit_xyz = orbfit.XVBASIS()
        self.orbit_aei = orbfit.ORBIT()
        self.cov_abg = orbfit.dmatrix(
            1, 6, 1, 6
        )  # need to make this one globally visible since it's needed by predict_pos()
        cov_xyz = orbfit.dmatrix(1, 6, 1, 6)
        cov_aei = orbfit.dmatrix(1, 6, 1, 6)
        derivs = orbfit.dmatrix(1, 6, 1, 6)
        # fittype is 6 if normal fit, 5 if energy constraint was used.
        self.fittype, self.chisq, self.ndof = orbfit.fit_observations(
            self.obsarray, self.nobs, self.orbit_abg, self.cov_abg,
            None)  # abg orbit elements
        #   Transform the orbit basis and get the deriv. matrix
        orbfit.pbasis_to_bary(self.orbit_abg, self.orbit_xyz, derivs)
        orbfit.orbitElements(self.orbit_xyz,
                             self.orbit_aei)  # aei orbit elements
        #        self.orbit_xyz.jd0 = orbfit.cvar.jd0     # time zeropoint
        # covariance matrices
        orbfit.covar_map(self.cov_abg, derivs, cov_xyz, 6,
                         6)  # map the covariance matrix to xyz basis
        orbfit.aei_derivs(
            self.orbit_xyz,
            derivs)  # Get partial derivative matrix from xyz to aei
        orbfit.covar_map(cov_xyz, derivs, cov_aei, 6,
                         6)  # map covariance matrix from xyz to aei
        # This is a hack to create matrices python can actually use. We have trouble wrapping double pointers.
        c = orbfit.doubleArray(36)
        orbfit.flatten_cov(self.cov_abg, 6, c)
        self.covar_abg = np.array([c[i] for i in range(36)
                                   ]).reshape(6, 6)  # a bona-fide numpy array.
        c = orbfit.doubleArray(
            36)  # It's necessary to reallocate the space in memory
        orbfit.flatten_cov(cov_xyz, 6, c)
        self.covar_xyz = np.array([c[i] for i in range(36)]).reshape(6, 6)
        c = orbfit.doubleArray(36)
        orbfit.flatten_cov(cov_aei, 6, c)
        self.covar_aei = np.array([c[i] for i in range(36)]).reshape(6, 6)
        self.elements, self.elements_errs = self.get_elements()
        self.jd0 = orbfit.cvar.jd0
        self.lat0 = orbfit.cvar.lat0
        self.lon0 = orbfit.cvar.lon0
        self.xBary = orbfit.cvar.xBary
        self.yBary = orbfit.cvar.yBary
        self.zBary = orbfit.cvar.zBary
Example #2
0
    def __init__(self, *args, **kwargs):
        """
        Takes a set of input observations and fits the orbital elements. These can then be used to
        compute the position and error ellipse for the object on an arbitrary date.
        Requires: observatories.dat and binEphem.423.
        
        keyword arguments:
        obsfile -- file containing observation data, either in MPC format or as
                   JD HH:MM:SS.SS +DD:MM:SS.SS ERROR OBSCODE  or as
                   YYYY MM DD.DDDDD HH:MM:SS.SS +DD:MM:SS.SS ERROR OBSCODE
                   where the error is the astrometric error on each measurement in arcsec (default 0.2)
                   and OBSCODE is the observatory code in observatories.dat
                   The number of digits in each field is unrestricted, but ra and dec must not contain spaces.
        The following options should be used only if obsfile is None. Then they must all be used. If obsfile
        is supplied then these arguments are ignored.
        dates -- list of observation dates, either in JD or YYYY MM DD.DDDDD format
        ra -- list of RA in HH:MM:SS.SS format.
        dec -- list of DEC in +DD:MM:SS.SS format
        obscode -- list of observatory codes
        err -- measurement error in arcsec
        
        Methods:
           get_elements() -- returns aei orbital elements and their errors
           get_elements_abg() -- returns abg orbital elements and their errors
           barycentric_distance() -- barycentric distance and error
           perihelion() -- perihelion and error
           aphelion() -- aphelion and error
           cov_pq() -- covariance matrix for perihelion, aphelion
           plotEllipse() -- generates an error ellipse for a given covariance matrix
           predict_pos() -- predicted ra, dec, and error ellipse on a given date
           ellipticalBody() -- returns an EllipticalBody object with these orbital parameters, suitable for use by pyEphem
        """

        if "file" in kwargs.keys():  # observations supplied in a file
            obsfile = kwargs["file"]
            with open(obsfile, "r") as fobs:
                self.nobs = 0  # determine the number of observations
                for line in fobs:
                    if line[0] != "#":
                        self.nobs += 1
                fobs.seek(0)  # rewind to the beginning
                self.obsarray = orbfit.OBSERVATION_ARRAY(self.nobs)  # create empty array of observations
                iobs = 0
                for line in fobs:
                    if line[0] != "#":
                        thisobs = orbfit.OBSERVATION()
                        orbfit.scan_observation(line, thisobs)
                        orbfit.add_to_obsarray(self.obsarray, iobs, thisobs)
                        iobs += 1
        elif len(args):  # observations supplied in a Catalog object
            self.nobs = len(args[0])
            self.obsarray = orbfit.OBSERVATION_ARRAY(self.nobs)
            for iobs, pt in enumerate(args[0]):
                thisobs = orbfit.OBSERVATION()
                if pt.err is None:
                    pt.err = 0.15  # This is to avoid silent crash.
                if pt.obscode is None:
                    pt.obscode = 807  # Ditto.
                obsline = (
                    str(ephem.julian_date(pt.date))
                    + " "
                    + str(pt.ra)
                    + " "
                    + str(pt.dec)
                    + " "
                    + str(pt.err)
                    + " "
                    + str(pt.obscode)
                )
                orbfit.scan_observation(obsline, thisobs)
                orbfit.add_to_obsarray(self.obsarray, iobs, thisobs)
        else:  # observations specified in input lists
            required_keys = ["dates", "ra", "dec", "obscode"]
            for k in required_keys:
                if k not in kwargs.keys():
                    raise KeyError("keyword " + k + " is missing")
            obsdate = kwargs["dates"]
            ra = kwargs["ra"]
            dec = kwargs["dec"]
            obscode = kwargs["obscode"]
            self.nobs = len(obsdate)
            if "err" in kwargs.keys():  # change: obserr need not be constant
                obserr = kwargs["err"]
                if not np.iterable(obserr):
                    obserr = [obserr for i in range(self.nobs)]
            else:
                obserr = [0.15 for i in range(self.nobs)]  # obervation astrometric error defaults to 0.15"
            assert (
                self.nobs == len(ra)
                and self.nobs == len(dec)
                and self.nobs == len(obscode)
                and self.nobs == len(obserr)
            )
            self.obsarray = orbfit.OBSERVATION_ARRAY(self.nobs)  # create empty array of observations
            for iobs in range(self.nobs):  # fill the OBSERVATION_ARRAY
                thisobs = orbfit.OBSERVATION()
                obsline = (
                    str(ephem.julian_date(obsdate[iobs]))
                    + " "
                    + str(ra[iobs])
                    + " "
                    + str(dec[iobs])
                    + " "
                    + str(obserr[iobs])
                    + " "
                    + str(obscode[iobs])
                )
                orbfit.scan_observation(obsline, thisobs)
                orbfit.add_to_obsarray(self.obsarray, iobs, thisobs)

        # At this point we have filled obsarray with the observations. Now fit the orbit.

        #        orbfit.set_ephem_file('/Users/gerdes/TNO/pyOrbfit/binEphem.430')      # pick up the correct ephemeris and observatories file.
        #        orbfit.set_observatory_file('/Users/gerdes/TNO/pyOrbfit/observatories.dat')   # Will need to handle pathnames more elegantly.

        self.orbit_abg = orbfit.PBASIS()
        self.orbit_xyz = orbfit.XVBASIS()
        self.orbit_aei = orbfit.ORBIT()
        self.cov_abg = orbfit.dmatrix(
            1, 6, 1, 6
        )  # need to make this one globally visible since it's needed by predict_pos()
        cov_xyz = orbfit.dmatrix(1, 6, 1, 6)
        cov_aei = orbfit.dmatrix(1, 6, 1, 6)
        derivs = orbfit.dmatrix(1, 6, 1, 6)
        # fittype is 6 if normal fit, 5 if energy constraint was used.
        self.fittype, self.chisq, self.ndof = orbfit.fit_observations(
            self.obsarray, self.nobs, self.orbit_abg, self.cov_abg, None
        )  # abg orbit elements
        #   Transform the orbit basis and get the deriv. matrix
        orbfit.pbasis_to_bary(self.orbit_abg, self.orbit_xyz, derivs)
        orbfit.orbitElements(self.orbit_xyz, self.orbit_aei)  # aei orbit elements
        #        self.orbit_xyz.jd0 = orbfit.cvar.jd0     # time zeropoint
        # covariance matrices
        orbfit.covar_map(self.cov_abg, derivs, cov_xyz, 6, 6)  # map the covariance matrix to xyz basis
        orbfit.aei_derivs(self.orbit_xyz, derivs)  # Get partial derivative matrix from xyz to aei
        orbfit.covar_map(cov_xyz, derivs, cov_aei, 6, 6)  # map covariance matrix from xyz to aei
        # This is a hack to create matrices python can actually use. We have trouble wrapping double pointers.
        c = orbfit.doubleArray(36)
        orbfit.flatten_cov(self.cov_abg, 6, c)
        self.covar_abg = np.array([c[i] for i in range(36)]).reshape(6, 6)  # a bona-fide numpy array.
        c = orbfit.doubleArray(36)  # It's necessary to reallocate the space in memory
        orbfit.flatten_cov(cov_xyz, 6, c)
        self.covar_xyz = np.array([c[i] for i in range(36)]).reshape(6, 6)
        c = orbfit.doubleArray(36)
        orbfit.flatten_cov(cov_aei, 6, c)
        self.covar_aei = np.array([c[i] for i in range(36)]).reshape(6, 6)
        self.elements, self.elements_errs = self.get_elements()
        self.jd0 = orbfit.cvar.jd0
        self.lat0 = orbfit.cvar.lat0
        self.lon0 = orbfit.cvar.lon0
        self.xBary = orbfit.cvar.xBary
        self.yBary = orbfit.cvar.yBary
        self.zBary = orbfit.cvar.zBary
def orbfit_abg(abgfile):
    with open(abgfile) as f:
        lines = [line for line in f if line[0] != '#']
        elem_abg = [float(e) for e in lines[0].split()]
        cov_arr = np.array([[float(de) for de in lines[i].split()]
                            for i in range(1, 7)],
                           dtype=np.float64)
        last = lines[7].split()
        lat0 = float(last[0])
        lon0 = float(last[1])
        xBary = float(last[2])
        yBary = float(last[3])
        zBary = float(last[4])
        jd0 = float(last[5])
        abginfo = {
            'elem': elem_abg,
            'cov': cov_arr,
            'lat0': lat0,
            'lon0': lon0,
            'xBary': xBary,
            'yBary': yBary,
            'zBary': zBary,
            'jd0': jd0
        }
        jd0 = abginfo['jd0']  # zeropoint of time scale
        # Create space for various useful matrices
        cov_abg = orbfit.dmatrix(1, 6, 1, 6)
        p_in = orbfit.PBASIS()
        orbit_xyz = orbfit.XVBASIS()
        orbit_aei = orbfit.ORBIT()
        p_in.a = abginfo['elem'][0]
        p_in.adot = abginfo['elem'][1]
        p_in.b = abginfo['elem'][2]
        p_in.bdot = abginfo['elem'][3]
        p_in.g = abginfo['elem'][4]
        p_in.gdot = abginfo['elem'][5]
        # Here follows kludginess to put the covariance matrix into C double pointers
        c = orbfit.doubleArray(36)
        cc = abginfo['cov'].reshape(36, order='F')
        for i in range(len(cc)):
            c[i] = cc[i]
        orbfit.unflatten_cov(c, 6, cov_abg)
        abginfo['pbasis'] = p_in
        abginfo['cov_abg'] = cov_abg
        cov_xyz = orbfit.dmatrix(1, 6, 1, 6)
        cov_aei = orbfit.dmatrix(1, 6, 1, 6)
        derivs = orbfit.dmatrix(1, 6, 1, 6)
        #   Transform the orbit basis and get the deriv. matrix
        orbfit.cvar.jd0 = abginfo['jd0']
        orbfit.cvar.xBary = abginfo['xBary']
        orbfit.cvar.yBary = abginfo['yBary']
        orbfit.cvar.zBary = abginfo['zBary']
        orbfit.cvar.lon0 = abginfo['lon0'] * np.pi / 180
        orbfit.cvar.lat0 = abginfo['lat0'] * np.pi / 180
        #CHANGE HERE
        orbfit.pbasis_to_bary(p_in, orbit_xyz, derivs)
        orbfit.orbitElements(orbit_xyz, orbit_aei)  # aei orbit elements

        abginfo['orbit_aei'] = orbit_aei
        abginfo['cov_aei'] = cov_aei
        abginfo['elems_aei'] = {
            'a': orbit_aei.a,
            'e': orbit_aei.e,
            'i': orbit_aei.i,
            'lan': orbit_aei.lan,
            'aop': orbit_aei.aop,
            'top': orbit_aei.T
        }
    return abginfo
Example #4
0
def orbfit_abg(abgfile):
    with open(abgfile) as f:
        lines = [line for line in f if line[0] != "#"]
        elem_abg = [float(e) for e in lines[0].split()]
        cov_arr = np.array([[float(de) for de in lines[i].split()] for i in range(1, 7)], dtype=np.float64)
        last = lines[7].split()
        lat0 = float(last[0])
        lon0 = float(last[1])
        xBary = float(last[2])
        yBary = float(last[3])
        zBary = float(last[4])
        jd0 = float(last[5])
        abginfo = {
            "elem": elem_abg,
            "cov": cov_arr,
            "lat0": lat0,
            "lon0": lon0,
            "xBary": xBary,
            "yBary": yBary,
            "zBary": zBary,
            "jd0": jd0,
        }
        jd0 = abginfo["jd0"]  # zeropoint of time scale
        # Create space for various useful matrices
        cov_abg = orbfit.dmatrix(1, 6, 1, 6)
        p_in = orbfit.PBASIS()
        orbit_xyz = orbfit.XVBASIS()
        orbit_aei = orbfit.ORBIT()
        p_in.a = abginfo["elem"][0]
        p_in.adot = abginfo["elem"][1]
        p_in.b = abginfo["elem"][2]
        p_in.bdot = abginfo["elem"][3]
        p_in.g = abginfo["elem"][4]
        p_in.gdot = abginfo["elem"][5]
        # Here follows kludginess to put the covariance matrix into C double pointers
        c = orbfit.doubleArray(36)
        cc = abginfo["cov"].reshape(36, order="F")
        for i in range(len(cc)):
            c[i] = cc[i]
        orbfit.unflatten_cov(c, 6, cov_abg)
        abginfo["pbasis"] = p_in
        abginfo["cov_abg"] = cov_abg
        cov_xyz = orbfit.dmatrix(1, 6, 1, 6)
        cov_aei = orbfit.dmatrix(1, 6, 1, 6)
        derivs = orbfit.dmatrix(1, 6, 1, 6)
        #   Transform the orbit basis and get the deriv. matrix
        orbfit.cvar.jd0 = abginfo["jd0"]
        orbfit.cvar.xBary = abginfo["xBary"]
        orbfit.cvar.yBary = abginfo["yBary"]
        orbfit.cvar.zBary = abginfo["zBary"]
        orbfit.cvar.lon0 = abginfo["lon0"] * np.pi / 180
        orbfit.cvar.lat0 = abginfo["lat0"] * np.pi / 180
        orbfit.pbasis_to_bary(p_in, orbit_xyz, derivs)
        orbfit.orbitElements(orbit_xyz, orbit_aei)  # aei orbit elements
        abginfo["orbit_aei"] = orbit_aei
        abginfo["cov_aei"] = cov_aei
        abginfo["elems_aei"] = {
            "a": orbit_aei.a,
            "e": orbit_aei.e,
            "i": orbit_aei.i,
            "lan": orbit_aei.lan,
            "aop": orbit_aei.aop,
            "top": orbit_aei.T,
        }
    return abginfo