コード例 #1
0
    def predict_pos(self, date, obscode=807):
        """
        Computes ra, dec, and error ellipse at the date(s) and observatory specified.
        Date is an ephem.date object.
        Returns a corresponding dictionary with keywords
            'ra' -- ra in ICRS coords, returned as an ephem.Angle object
            'dec' -- dec in ICRS coords, ditto
            'err' -- error ellipse (see below)
            'elong' -- solar elongation in degrees
            'opp' -- opposition angle in degrees
        where the error ellipse, indexed by 'err', is itself a dictionary with keywords:
            'a'  -- semimajor axis in arcsec
            'b'  -- semiminor axis in arcsec
            'PA' -- position angle in degrees, north through east
        
        """
        p_in = self.orbit_abg
        jd0 = orbfit.cvar.jd0  # zeropoint of time scale
        # Create space for various useful matrices
        sigxy = orbfit.dmatrix(1, 2, 1, 2)
        derivs = orbfit.dmatrix(1, 2, 1, 2)
        covecl = orbfit.dmatrix(1, 2, 1, 2)
        coveq = orbfit.dmatrix(1, 2, 1, 2)

        # Fill the OBSERVATION structure
        futobs = orbfit.OBSERVATION()
        futobs.obscode = obscode
        futobs.obstime = (ephem.julian_date(date) - jd0) * orbfit.DAY
        futobs.xe = -999  # force evaluation of earth3D
        dx = orbfit.dvector(1, 6)
        dy = orbfit.dvector(1, 6)
        # Sometimes hangs in next line... why?
        thetax, thetay = orbfit.kbo2d(p_in, futobs, dx, dy)
        # Predicted position, in abg basis:
        orbfit.predict_posn(p_in, self.cov_abg, futobs, sigxy)
        solar_elongation = orbfit.elongation(
            futobs) / orbfit.DTOR  # solar elongation in degrees
        opposition_angle = orbfit.opposition_angle(
            futobs) / orbfit.DTOR  # opposition angle in degrees
        lat_ec, lon_ec = orbfit.proj_to_ec(
            futobs.thetax, futobs.thetay, orbfit.cvar.lat0, orbfit.cvar.lon0,
            derivs)  # project to ecliptic coords
        orbfit.covar_map(sigxy, derivs, covecl, 2, 2)  # map the covariance
        ra_eq, dec_eq = orbfit.ec_to_eq(
            lat_ec, lon_ec, derivs)  # transform to ICRS to compute ra, dec
        if ra_eq < 0: ra_eq += 2 * np.pi  # convert angle to (0,2pi) range
        orbfit.covar_map(covecl, derivs, coveq, 2, 2)  # map the covariance

        # Compute ICRS error ellipse
        c = orbfit.doubleArray(4)  # stoopid workaround for double pointers...
        orbfit.flatten_cov(coveq, 2, c)
        covar_eq = np.array([c[i] for i in range(4)]).reshape(2, 2)
        xx = covar_eq[0][0] * np.cos(dec_eq)**2
        xy = covar_eq[0][1] * np.cos(dec_eq)
        yy = covar_eq[1][1]
        pos_angle = 0.5 * np.arctan2(2. * xy, (xx - yy)) * 180. / np.pi
        pos_angle = 90 - pos_angle  # convert to astronomy convention of measuring position angle North through East
        bovasqrd = (xx + yy - np.sqrt((xx - yy)**2 +
                                      (2 * xy)**2)) / (xx + yy +
                                                       np.sqrt((xx - yy)**2 +
                                                               (2 * xy)**2))
        det = xx * yy - xy * xy
        a = (det / bovasqrd)**(
            1 / 4
        ) / orbfit.ARCSEC  # semimajor, minor axes of error ellipse, in arcsec
        b = (det * bovasqrd)**(1 / 4) / orbfit.ARCSEC
        err_ellipse = dict(a=a, b=b, PA=pos_angle)  # store as a dictionary

        pos = dict(ra=ephem.hours(ra_eq),
                   dec=ephem.degrees(dec_eq),
                   err=err_ellipse,
                   elong=solar_elongation,
                   opp=opposition_angle)
        return pos
コード例 #2
0
def predict_from_abg(abginfo, date, obscode=807):

    p_in = abginfo['pbasis']
    cov_abg = abginfo['cov_abg']
    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
    sigxy = orbfit.dmatrix(1, 2, 1, 2)
    derivs = orbfit.dmatrix(1, 2, 1, 2)
    covecl = orbfit.dmatrix(1, 2, 1, 2)
    coveq = orbfit.dmatrix(1, 2, 1, 2)
    # Fill the OBSERVATION structure
    futobs = orbfit.OBSERVATION()
    futobs.obscode = obscode
    futobs.obstime = (ephem.julian_date(date) - orbfit.cvar.jd0) * orbfit.DAY
    futobs.xe = -999  # force evaluation of earth3D

    dx = orbfit.dvector(1, 6)
    dy = orbfit.dvector(1, 6)

    thetax, thetay = orbfit.kbo2d(p_in, futobs, dx, dy)

    # Predicted position, in abg basis:
    orbfit.predict_posn(p_in, cov_abg, futobs, sigxy)
    solar_elongation = orbfit.elongation(
        futobs) / orbfit.DTOR  # solar elongation in degrees
    opposition_angle = orbfit.opposition_angle(
        futobs) / orbfit.DTOR  # opposition angle in degrees
    lat_ec, lon_ec = orbfit.proj_to_ec(futobs.thetax, futobs.thetay,
                                       orbfit.cvar.lat0, orbfit.cvar.lon0,
                                       derivs)  # project to ecliptic coords
    orbfit.covar_map(sigxy, derivs, covecl, 2, 2)  # map the covariance
    ra_eq, dec_eq = orbfit.ec_to_eq(
        lat_ec, lon_ec, derivs)  # transform to ICRS to compute ra, dec
    eq = ephem.Equatorial(ephem.Ecliptic(lat_ec, lon_ec))
    ra_eq2 = eq.ra * 180 / np.pi
    dec_eq2 = eq.dec * 180 / np.pi
    if ra_eq < 0: ra_eq += 2 * np.pi  # convert angle to (0,2pi) range
    #        print ra_eq*180/np.pi, dec_eq*180/np.pi, ra_eq2, dec_eq2, ra_eq*180/np.pi-ra_eq2, dec_eq*180/np.pi-dec_eq2
    orbfit.covar_map(covecl, derivs, coveq, 2, 2)  # map the covariance
    #        print ephem.hours(ra_eq), ephem.degrees(dec_eq)
    # Compute ICRS error ellipse
    c2d = orbfit.doubleArray(4)  # stoopid workaround for double pointers...
    orbfit.flatten_cov(coveq, 2, c2d)
    covar_eq = np.array([c2d[i] for i in range(4)]).reshape(2, 2)
    xx = covar_eq[0][0] * np.cos(dec_eq)**2
    xy = covar_eq[0][1] * np.cos(dec_eq)
    yy = covar_eq[1][1]
    pos_angle = 0.5 * np.arctan2(2. * xy, (xx - yy)) * 180. / np.pi
    pos_angle = 90 - pos_angle  # convert to astronomy convention of measuring position angle North through East
    bovasqrd = (xx + yy - np.sqrt((xx - yy)**2 +
                                  (2 * xy)**2)) / (xx + yy +
                                                   np.sqrt((xx - yy)**2 +
                                                           (2 * xy)**2))
    det = xx * yy - xy * xy
    a = (det / bovasqrd)**(
        1 /
        4) / orbfit.ARCSEC  # semimajor, minor axes of error ellipse, in arcsec
    b = (det * bovasqrd)**(1 / 4) / orbfit.ARCSEC
    err_ellipse = dict(a=a, b=b, PA=pos_angle)  # store as a dictionary

    pos = dict(ra=ephem.hours(ra_eq),
               dec=ephem.degrees(dec_eq),
               err=err_ellipse,
               elong=solar_elongation,
               opp=opposition_angle)
    return pos
コード例 #3
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
コード例 #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
        #CHANGE HERE
        orbfit.pbasis_to_helio(p_in, orbit_xyz, derivs)
        orbfit.orbitElements_helio(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
コード例 #5
0
ファイル: Orbit.py プロジェクト: dwgerdes/pyOrbfit
    def predict_pos(self, date, obscode=807):
        """
        Computes ra, dec, and error ellipse at the date(s) and observatory specified.
        Date is an ephem.date object.
        Returns a corresponding dictionary with keywords
            'ra' -- ra in ICRS coords, returned as an ephem.Angle object
            'dec' -- dec in ICRS coords, ditto
            'err' -- error ellipse (see below)
            'elong' -- solar elongation in degrees
            'opp' -- opposition angle in degrees
        where the error ellipse, indexed by 'err', is itself a dictionary with keywords:
            'a'  -- semimajor axis in arcsec
            'b'  -- semiminor axis in arcsec
            'PA' -- position angle in degrees, north through east
        
        """
        p_in = self.orbit_abg
        jd0 = orbfit.cvar.jd0  # zeropoint of time scale
        # Create space for various useful matrices
        sigxy = orbfit.dmatrix(1, 2, 1, 2)
        derivs = orbfit.dmatrix(1, 2, 1, 2)
        covecl = orbfit.dmatrix(1, 2, 1, 2)
        coveq = orbfit.dmatrix(1, 2, 1, 2)

        # Fill the OBSERVATION structure
        futobs = orbfit.OBSERVATION()
        futobs.obscode = obscode
        futobs.obstime = (ephem.julian_date(date) - jd0) * orbfit.DAY
        futobs.xe = -999  # force evaluation of earth3D
        dx = orbfit.dvector(1, 6)
        dy = orbfit.dvector(1, 6)
        thetax, thetay = orbfit.kbo2d(p_in, futobs, dx, dy)

        # Predicted position, in abg basis:
        orbfit.predict_posn(p_in, self.cov_abg, futobs, sigxy)
        solar_elongation = orbfit.elongation(futobs) / orbfit.DTOR  # solar elongation in degrees
        opposition_angle = orbfit.opposition_angle(futobs) / orbfit.DTOR  # opposition angle in degrees
        lat_ec, lon_ec = orbfit.proj_to_ec(
            futobs.thetax, futobs.thetay, orbfit.cvar.lat0, orbfit.cvar.lon0, derivs
        )  # project to ecliptic coords
        orbfit.covar_map(sigxy, derivs, covecl, 2, 2)  # map the covariance
        ra_eq, dec_eq = orbfit.ec_to_eq(lat_ec, lon_ec, derivs)  # transform to ICRS to compute ra, dec
        if ra_eq < 0:
            ra_eq += 2 * np.pi  # convert angle to (0,2pi) range
        orbfit.covar_map(covecl, derivs, coveq, 2, 2)  # map the covariance

        # Compute ICRS error ellipse
        c = orbfit.doubleArray(4)  # stoopid workaround for double pointers...
        orbfit.flatten_cov(coveq, 2, c)
        covar_eq = np.array([c[i] for i in range(4)]).reshape(2, 2)
        xx = covar_eq[0][0] * np.cos(dec_eq) ** 2
        xy = covar_eq[0][1] * np.cos(dec_eq)
        yy = covar_eq[1][1]
        pos_angle = 0.5 * np.arctan2(2.0 * xy, (xx - yy)) * 180.0 / np.pi
        pos_angle = 90 - pos_angle  # convert to astronomy convention of measuring position angle North through East
        bovasqrd = (xx + yy - np.sqrt((xx - yy) ** 2 + (2 * xy) ** 2)) / (
            xx + yy + np.sqrt((xx - yy) ** 2 + (2 * xy) ** 2)
        )
        det = xx * yy - xy * xy
        a = (det / bovasqrd) ** (1 / 4) / orbfit.ARCSEC  # semimajor, minor axes of error ellipse, in arcsec
        b = (det * bovasqrd) ** (1 / 4) / orbfit.ARCSEC
        err_ellipse = dict(a=a, b=b, PA=pos_angle)  # store as a dictionary

        pos = dict(
            ra=ephem.hours(ra_eq),
            dec=ephem.degrees(dec_eq),
            err=err_ellipse,
            elong=solar_elongation,
            opp=opposition_angle,
        )
        return pos
コード例 #6
0
ファイル: Orbit.py プロジェクト: dwgerdes/pyOrbfit
    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
コード例 #7
0
ファイル: orbfit_tools.py プロジェクト: dwgerdes/tnofind
def predict_from_abg(abginfo, date, obscode=807):

    p_in = abginfo["pbasis"]
    cov_abg = abginfo["cov_abg"]
    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
    sigxy = orbfit.dmatrix(1, 2, 1, 2)
    derivs = orbfit.dmatrix(1, 2, 1, 2)
    covecl = orbfit.dmatrix(1, 2, 1, 2)
    coveq = orbfit.dmatrix(1, 2, 1, 2)
    # Fill the OBSERVATION structure
    futobs = orbfit.OBSERVATION()
    futobs.obscode = obscode
    futobs.obstime = (ephem.julian_date(date) - orbfit.cvar.jd0) * orbfit.DAY
    futobs.xe = -999  # force evaluation of earth3D

    dx = orbfit.dvector(1, 6)
    dy = orbfit.dvector(1, 6)

    thetax, thetay = orbfit.kbo2d(p_in, futobs, dx, dy)

    # Predicted position, in abg basis:
    orbfit.predict_posn(p_in, cov_abg, futobs, sigxy)
    solar_elongation = orbfit.elongation(futobs) / orbfit.DTOR  # solar elongation in degrees
    opposition_angle = orbfit.opposition_angle(futobs) / orbfit.DTOR  # opposition angle in degrees
    lat_ec, lon_ec = orbfit.proj_to_ec(
        futobs.thetax, futobs.thetay, orbfit.cvar.lat0, orbfit.cvar.lon0, derivs
    )  # project to ecliptic coords
    orbfit.covar_map(sigxy, derivs, covecl, 2, 2)  # map the covariance
    ra_eq, dec_eq = orbfit.ec_to_eq(lat_ec, lon_ec, derivs)  # transform to ICRS to compute ra, dec
    eq = ephem.Equatorial(ephem.Ecliptic(lat_ec, lon_ec))
    ra_eq2 = eq.ra * 180 / np.pi
    dec_eq2 = eq.dec * 180 / np.pi
    if ra_eq < 0:
        ra_eq += 2 * np.pi  # convert angle to (0,2pi) range
    #        print ra_eq*180/np.pi, dec_eq*180/np.pi, ra_eq2, dec_eq2, ra_eq*180/np.pi-ra_eq2, dec_eq*180/np.pi-dec_eq2
    orbfit.covar_map(covecl, derivs, coveq, 2, 2)  # map the covariance
    #        print ephem.hours(ra_eq), ephem.degrees(dec_eq)
    # Compute ICRS error ellipse
    c2d = orbfit.doubleArray(4)  # stoopid workaround for double pointers...
    orbfit.flatten_cov(coveq, 2, c2d)
    covar_eq = np.array([c2d[i] for i in range(4)]).reshape(2, 2)
    xx = covar_eq[0][0] * np.cos(dec_eq) ** 2
    xy = covar_eq[0][1] * np.cos(dec_eq)
    yy = covar_eq[1][1]
    pos_angle = 0.5 * np.arctan2(2.0 * xy, (xx - yy)) * 180.0 / np.pi
    pos_angle = 90 - pos_angle  # convert to astronomy convention of measuring position angle North through East
    bovasqrd = (xx + yy - np.sqrt((xx - yy) ** 2 + (2 * xy) ** 2)) / (xx + yy + np.sqrt((xx - yy) ** 2 + (2 * xy) ** 2))
    det = xx * yy - xy * xy
    a = (det / bovasqrd) ** (1 / 4) / orbfit.ARCSEC  # semimajor, minor axes of error ellipse, in arcsec
    b = (det * bovasqrd) ** (1 / 4) / orbfit.ARCSEC
    err_ellipse = dict(a=a, b=b, PA=pos_angle)  # store as a dictionary

    pos = dict(
        ra=ephem.hours(ra_eq), dec=ephem.degrees(dec_eq), err=err_ellipse, elong=solar_elongation, opp=opposition_angle
    )
    return pos
コード例 #8
0
ファイル: orbfit_tools.py プロジェクト: dwgerdes/tnofind
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