Ejemplo n.º 1
0
 def test_rejection_line_writing(self):
     """
     Ensure the MPCReader is picking up the
     """
     reader = mpc.MPCReader()
     obs = reader.read(self.fileobj)
     self.assertIsNone(obs[5].comment.mag_uncertainty)
Ejemplo n.º 2
0
 def test_mpc_real_to_ossos(self):
     reader = mpc.MPCReader()
     obs = reader.read(self.fileobj)
     assert isinstance(obs[5].comment, mpc.OSSOSComment)
     self.assertEqual(obs[5].comment.version, "O")
     self.assertEqual(obs[5].provisional_name, "L3XO")
     self.assertAlmostEqual(obs[5].comment.mag, 24.44, places=2)
Ejemplo n.º 3
0
 def test_use_as_reader_set_provisional(self):
     """
     Now we expect MPCReader to return an object that has a read method.
     :return:
     """
     reader = mpc.MPCReader(replace_provisional=True,
                            provisional_name='test')
     obs = reader.read(self.fileobj)
     self.assertEqual(obs[0].provisional_name, 'test')
Ejemplo n.º 4
0
 def test_old_school(self):
     """
     Make sure that we can use the MPCReader directly, in the old school way.
     :return:
     """
     r = mpc.MPCReader(self.fileobj.name,
                       replace_provisional=True).mpc_observations
     self.assertIsInstance(r, numpy.ndarray)
     self.assertIsInstance(r[0], mpc.Observation)
     self.assertEqual(
         r[0].provisional_name, self._default_provisional,
         "got >{}< expected >{}<".format(r[0].provisional_name,
                                         self._default_provisional))
Ejemplo n.º 5
0
def load_observations(xxx_todo_changeme, path, filenames):
    """
    Returns a provisional name based dictionary of observations of the object.
    Each observations is keyed on the date. ie. a dictionary of dictionaries.

    @param path: the directory where filenames are.
    @type path str
    @param filenames: list of files in path.
    @type filenames list
    @rtype  None
    """
    (observations, regex, rename) = xxx_todo_changeme
    for filename in filenames:
        if re.search(regex, filename) is None:
            logging.error("Skipping {}".format(filename))
            continue
        obs = mpc.MPCReader().read(os.path.join(path, filename))
        for ob in obs:
            if "568" not in ob.observatory_code:
                continue
            if not isinstance(ob.comment, mpc.OSSOSComment):
                continue
            if ob.date < Time("2013-01-01 00:00:00"):
                continue
            if rename:
                new_provisional_name = os.path.basename(filename)
                new_provisional_name = new_provisional_name[
                    0:new_provisional_name.find(".")]
                rename_map[ob.provisional_name] = new_provisional_name
            try:
                key1 = ob.comment.frame.split('p')[0]
            except Exception as ex:
                logger.warning(str(ex))
                logger.warning(ob.to_string())
                continue
            key2 = ob.provisional_name
            if key1 not in observations:
                observations[key1] = {}
            if key2 in observations[key1]:
                if observations[key1][key2]:
                    continue
                if not observation.null_observation:
                    logger.error(filename)
                    logger.error(str(observations[key1][key2]))
                    raise ValueError(
                        "conflicting observations for {} in {}".format(
                            key2, key1))
            observations[key1][key2] = ob
Ejemplo n.º 6
0
 def test_correctly_formatted_long_provisional_name(self):
     """
     Make sure we get the provisional name in the correct starting column.
     :return:
     """
     reader = mpc.MPCReader()
     obs = reader.read(self.fileobj)
     self.assertEqual(
         obs[3].provisional_name, self.long_test_name,
         "got >{}< expected >{}<".format(obs[3].provisional_name,
                                         self.long_test_name))
     self.assertEqual(
         str(obs[3])[1:1 + len(self.long_test_name)], self.long_test_name,
         "got >{}< expected >{}<".format(
             self.long_test_name,
             str(obs[3])[1:1 + len(self.long_test_name)]))
Ejemplo n.º 7
0
def main():
    parser = argparse.ArgumentParser(
        description='Parse a directory of TNO .ast files and create links in the postage stamp directory '
                    'that allow retrieval of cutouts of the FITS images associated with the OSSOS detections. '
                    'Cutouts are defined on the WCS RA/DEC of the object position.')

    parser.add_argument("version",
                        help="The OSSOS data release version these stamps should be assigned to.")
    parser.add_argument("--ossin",
                        action="store",
                        default="vos:OSSOS/dbaseclone/ast/",
                        help="The vospace containerNode that clones ossin dbaseclone"
                             "holding the .ast files of astrometry/photometry measurements.")
    parser.add_argument("--blocks", "-b",
                        action="store",
                        default=["o3e", "o3o"],
                        choices=["o3e", "o3o", "O13BL", "Col3N"],
                        help="Prefixes of object designations to include.")
    parser.add_argument("--radius", '-r',
                        action='store',
                        default=0.02,
                        help='Radius (degree) of circle of cutout postage stamp.')
    parser.add_argument("--debug", "-d",
                        action="store_true")
    parser.add_argument("--verbose", "-v",
                        action="store_true")

    args = parser.parse_args()

    username = raw_input("CADC username: "******"CADC password: ")

    if args.debug:
        logging.basicConfig(level=logging.DEBUG)
    elif args.verbose:
        logging.basicConfig(level=logging.INFO)

    for fn in storage.listdir(args.ossin)[10:11]:  #FIXME: TESTING ONLY
        obj = mpc.MPCReader(args.ossin + fn)  # let MPCReader's logic determine the provisional name
        for block in args.blocks:
            if obj.provisional_name.startswith(block):
                obj_dir = '{}/{}/{}'.format(storage.POSTAGE_STAMPS, args.version, obj.provisional_name)
                if not storage.exists(obj_dir, force=True):
                    storage.mkdir(obj_dir)
                # assert storage.exists(obj_dir, force=True)
                cutout(obj, obj_dir, args.radius, username, password)
Ejemplo n.º 8
0
def parse_kbo(kbo_filename,
              camera_filter,
              search_start_date=Time('2013-02-08', scale='utc'),
              search_end_date=Time(
                  datetime.datetime.now().strftime('%Y-%m-%d'), scale='utc')):
    mpc_observations = mpc.MPCReader(kbo_filename).mpc_observations
    orbit = orbfit.Orbfit(mpc_observations)
    sys.stderr.write("Sending query on %s to SSOS\n" % orbit.name)

    query = Query(
        mpc_observations,
        search_start_date=search_start_date,
        search_end_date=search_end_date)  # searches full survey period
    obs_in_filter = parse_ssois_return(query.get(),
                                       camera_filter=camera_filter)

    return orbit, obs_in_filter
Ejemplo n.º 9
0
def cfeps_residuals(version='L7', regenerate=False):
    if version == 'L4':
        header = ['obsnum', 'arclen', 'date', 'ra_resid', 'date2', 'dec_resid']
        data = Table.read(path + 'L4resid.txt',
                          format='ascii',
                          guess=False,
                          delimiter=' ',
                          data_start=0,
                          names=header)
        cfeps_mas = (np.sqrt(data['ra_resid']**2 +
                             data['dec_resid']**2)) * 1000

    else:
        all_resids = []
        if regenerate:
            data_path = '/Users/bannisterm/Dropbox/mpc/'
            for filename in os.listdir(data_path):
                observations = mpc.MPCReader(data_path + filename)
                print(observations.provisional_name)
                orbit = orbfit.Orbfit(observations.mpc_observations)
                try:
                    residuals = orbit.residuals(overall=True)
                    all_resids += residuals
                except Exception as e:
                    print(observations.provisional_name)
                    print(e)
                    continue
            print(all_resids)

            with open('cfeps_resids_{}.dat'.format(version), 'w') as outfile:
                for r in all_resids:
                    outfile.write("{}\n".format(r))

        else:
            assert os.path.exists('cfeps_resids_{}.dat'.format(version))
            with open('cfeps_resids_{}.dat'.format(version), 'r') as infile:
                lines = infile.readlines()
                for line in lines:
                    all_resids.append(float(line))
            print(len(all_resids))

    cfeps_mas = np.array(all_resids)
    print(cfeps_mas)
    print('cfeps', np.median(cfeps_mas))

    return cfeps_mas
Ejemplo n.º 10
0
def ossos_discoveries(no_nt_and_u=True):
    """
    Returns a list of orbfit.Orbfit objects with the observations in the Orbfit.observations field.
    """
    retval = []

    # discovery_files = [n for n in os.listdir(parameters.REAL_KBO_AST_DIR)]# if n.endswith('.mpc') or n.endswith(
    # '.ast')]
    for filename in storage.listdir(parameters.REAL_KBO_AST_DIR):
        # keep out the not-tracked and uncharacterised.
        if no_nt_and_u:
            if not (filename.__contains__('nt') or filename.__contains__('u')):
                print(filename)
                observations = mpc.MPCReader(parameters.REAL_KBO_AST_DIR +
                                             filename)
                orbit = orbfit.Orbfit(observations.mpc_observations)
                retval.append((observations, orbit))

    return retval
Ejemplo n.º 11
0
def load_observations(xxx_todo_changeme, path, filenames):
    """
    Returns a provisional name based dictionary of observations of the object.
    Each observations is keyed on the date. ie. a dictionary of dictionaries.

    :rtype : None
    :param observations: dictionary to store observtions into
    :param path: the directory where filenames are.
    :param filenames: list of files in path.
    """
    (observations, regex, rename) = xxx_todo_changeme
    for filename in filenames:
        if re.search(regex, filename) is None:
            logging.warning("Skipping {}".format(filename))
            continue
        print(os.path.join(path,filename))
        obs = mpc.MPCReader().read(os.path.join(path,filename))
        for ob in obs:
            if rename:
                new_provisional_name = os.path.basename(filename)
                new_provisional_name = new_provisional_name[0:new_provisional_name.find(".")]
                ob.provisional_name = new_provisional_name
                # ob.comment.name = new_provisional_name
            key1 = "{:.5f}".format(ob.date.mjd)
            key2 = ob.provisional_name 
            if key1 not in observations:
                 observations[key1] = {}
            if key2 in observations[key1]:
               if observations[key1][key2]:
                   continue
               if not observation.null_observation:
                   logger.error(filename)
                   logger.error(line)
                   logger.error(str(observations[key1][key2]))
                   raise ValueError("conflicting observations for {} in {}".format(key2, key1))
            observations[key1][key2] = ob
Ejemplo n.º 12
0
    names=names,
    header_start=None)

for tno in tnos['object']:
    if tno.startswith('u'):
        continue
    cl = tnos['cl'][tnos['object'] == tno]
    print(tno, cl[0])

    # Check if the orbfit has already been run. Saves time as this takes a minute or so total
    pfilename = '{}_da'.format(tno)
    if os.access(pfilename, os.R_OK):
        with open(pfilename, 'r') as pf:
            (t, da) = pickle.load(pf)
    else:
        obs = mpc.MPCReader(parameters.REAL_KBO_AST_DIR + tno + '.ast')
        mpc_obs = list(obs.mpc_observations)
        for ob in mpc_obs:
            if ob.discovery:
                t0 = ob.date.jd
                break
        # sort by absolute distance from discovery
        mpc_obs.sort(key=lambda x: math.fabs(x.date.jd - t0))

        # need minimum of 3 observations to start fitting an orbit
        t = []
        da = []
        for idx in range(3, len(mpc_obs) + 1):
            short_arc = mpc_obs[:idx]
            orb = orbfit.Orbfit(short_arc)
            short_arc.sort(key=lambda x: x.date.jd)
Ejemplo n.º 13
0
from ossos.orbfit import Orbfit

date = '2016-10-24T16:00:00'
# lightcurve_targets = '/Users/michele/Dropbox/Telescope proposals/Subaru ' \
#                      'proposal_2015A_lightcurves/lightcurve_targets.txt'
ossinpath = '/Users/bannisterm/Dropbox/OSSOS/measure3/ossin/tmp/'  #'vos:OSSOS/dbaseclone/ast/'  #
outfile = '/Users/bannisterm/Desktop/{}.txt'.format(date)
# '/Users/michele/Dropbox/Telescope proposals/Subaru proposal/lc_pos_20150414.txt'

with open(outfile, 'w') as ofile:
    ofile.write(
        'Target	RA (hrs)	DEC		m_r	delta RA (")	delta DEC (")	Time predicted\n')

# with open(lightcurve_targets, 'r') as infile:
#     lines = infile.readlines()
#     for line in lines:
#         obj, mag = line.split('\t')
for kbo_filename in os.listdir(ossinpath):
    mpc_observations = mpc.MPCReader(ossinpath + kbo_filename).mpc_observations
    orbit = Orbfit(mpc_observations)
    orbit.predict(date=date)

    with open(outfile, 'a') as ofile:
        ofile.write("{:>10s} {:>10s} {:6.2f} {:6.2f} {:>10s}\n".format(
            orbit.name,
            orbit.coordinate.to_string('hmsdms', sep=':'),
            # orbit.coordinate.dec.to_string('hmsdms'),  # need to add mag back in
            orbit.dra,
            orbit.ddec,
            date))
Ejemplo n.º 14
0
    return ax


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("kbo",
                        nargs='*',
                        help="Plot all OSSOS imaging of the given KBO, which can be an OSSOS discovery.")

    args = parser.parse_args()

    # load in the KBO. For now let's assume it's a single OSSOS discovery, generalise later
    # discoveries = parsers.ossos_release_parser(table=True)
    dir = '/Users/bannisterm/Dropbox/OSSOS/measure3/2014B-H/track/'
    fn = dir + args.kbo[0] + '.ast'  # parameters.REAL_KBO_AST_DIR
    obj = mpc.MPCReader(fn)  # let MPCReader's logic determine the provisional name
    # need to determine a plot extent to get the MegaCam coverage
    # and KBOs go westward so earliest to latest is kinda useful
    extents = [max([obs.coordinate.ra.degree for obs in obj.mpc_observations]) + 0.9,
               min([obs.coordinate.ra.degree for obs in obj.mpc_observations]) - 0.9,
               min([obs.coordinate.dec.degree for obs in obj.mpc_observations]),
               max([obs.coordinate.dec.degree for obs in obj.mpc_observations])]
    midpoint = (extents[0] + ((extents[1] - extents[0]) / 2.), extents[2] + ((extents[3] - extents[2]) / 2.))
    print((extents, midpoint))

    handles, labels, ax, fontP = sky_location_plots.basic_skysurvey_plot_setup()
    plt.axis('equal')
    plt.grid(alpha=0.2)
    #
    # fig = aplpy.FITSFigure()
    # fig.set_theme('publication')
Ejemplo n.º 15
0
def ephem_search(mpc_filename, search_date="2014 07 24.0"):
    """
    builds a TSV file in the format of SSOIS by querying for possible observations in CADC/CAOM2.

    This is a fall back program, should only be useful when SSOIS is behind.
    """
    columns = ('Image', 'Ext', 'X', 'Y', 'MJD', 'Filter', 'Exptime',
               'Object_RA', 'Object_Dec', 'Image_target',
               'Telescope/Instrument', 'MetaData', 'Datalink')

    ephem_table = Table(names=columns,
                        dtypes=('S10', 'i4', 'f8', 'f8', 'f8', 'S10', 'f8',
                                'f8', 'f8', 'S20', 'S20', 'S20', 'S50'))

    ephem_table.pprint()

    o = orbfit.Orbfit(mpc.MPCReader(mpc_filename).mpc_observations)
    o.predict(search_date)
    fields = storage.cone_search(o.coordinate.ra.degrees,
                                 o.coordinate.dec.degrees,
                                 dra=0.3,
                                 ddec=0.3,
                                 calibration_level=1)
    mjdates = numpy.unique(fields['mjdate'])

    collectionIDs = []
    for mjdate in mjdates:
        jd = 2400000.5 + mjdate
        o.predict(jd)
        for field in storage.cone_search(o.coordinate.ra.degrees,
                                         o.coordinate.dec.degrees,
                                         dra=30. / 3600.0,
                                         ddec=30. / 3600.0,
                                         mjdate=mjdate,
                                         calibration_level=1):
            collectionIDs.append(field['collectionID'])

    expnums = numpy.unique(numpy.array(collectionIDs))

    for expnum in expnums:
        header = storage.get_astheader(expnum, 22)
        o.predict(header['MJDATE'] + 2400000.5)
        print(o.time.iso, o.coordinate.ra.degrees, o.coordinate.dec.degrees)
        for ccd in range(36):
            header = storage.get_astheader(expnum, ccd)
            w = wcs.WCS(header)
            (x, y) = w.sky2xy(o.coordinate.ra.degrees,
                              o.coordinate.dec.degrees)
            print(ccd, x, y)
            if 0 < x < header['NAXIS1'] and 0 < y < header['NAXIS2']:
                ephem_table.add_row([
                    expnum, ccd + 1, x, y, header['MJDATE'], header['FILTER'],
                    header['EXPTIME'], o.coordinate.ra.degrees,
                    o.coordinate.dec.degrees, header['OBJECT'], 'CFHT/MegaCam',
                    None,
                    "https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/data/pub/CFHT/{}p[{}]"
                    .format(expnum, ccd)
                ])
                break

    ephem_table.pprint()
    ephem_table.write('backdoor.tsv', format='ascii', delimiter='\t')
Ejemplo n.º 16
0
    fig = pyplot.Figure()
    ax1 = pyplot.subplot(221)
    ax2 = pyplot.subplot(222)
    ax3 = pyplot.subplot(223)
    ax4 = pyplot.subplot(224)
    ax1.set_ylabel(r'$\Delta_{mag}$')
    ax1.set_xlabel("jd (days)")
    ax2.set_aspect('equal', adjustable='box')
    ax3.set_ylabel(r'$\Delta_{RA}$')
    ax4.set_ylabel(r'$\Delta_{DEC}$')
    ax3.set_xlabel("JD (days)")
    ax4.set_xlabel("JD (days)")
    ax2.set_xlabel(r'$\Delta_{RA}$')
    ax2.set_ylabel(r'$\Delta_{DEC}$')
    t = numpy.arange(0, numpy.pi * 2.5, 0.1)
    x = 0.05 * numpy.cos(t)
    y = 0.05 * numpy.sin(t)
    ax2.plot(x, y, '-k')

    for mpc_file in sys.argv[1:]:
        mpc_obs = mpc.MPCReader(mpc_file).mpc_observations
        build_summary_plot(mpc_obs)

    ax2.set_xlim(-0.5, 0.5)
    ax2.set_ylim(-0.5, 0.5)
    ax3.set_ylim(-0.5, 0.5)
    ax4.set_ylim(-0.5, 0.5)
    ax1.set_ylim(-0.5, 0.5)

    pyplot.savefig("orbits.pdf")
Ejemplo n.º 17
0
def main():
    parser = argparse.ArgumentParser(
        description='Parse a directory of TNO .ast files and create links in the postage stamp directory '
                    'that allow retrieval of cutouts of the FITS images associated with the OSSOS detections. '
                    'Cutouts are defined on the WCS RA/DEC of the object position.')

    parser.add_argument("version",
                        help="The OSSOS data release version these stamps should be assigned to. e.g. v8")
    parser.add_argument("astdir", help="Directory containing the input .ast files", action="store", default="ast/")
    parser.add_argument("--ossin",
                        action="store",
                        default="vos:OSSOS/0_OSSOSreleases/OSSOS",
                        help="The vospace containerNode that clones ossin dbaseclone"
                             "holding the .ast files of astrometry/photometry measurements.")
    parser.add_argument("--blocks", "-b",
                        action="store",
                        default=['o3e', 'o3o', 'o3l', 'o4h', 'o5p', 'o5m', 'o5s', 'o5t', 'o5c', 'o5d'],
                        choices=["o3e", "o3o", "Col3N", 'o3l', 'o4h', 'o5m', 'o5p', 'o5s', 'o5t', 'o5c', 'o5d'],
                        help="Prefixes of object designations to include.")
    parser.add_argument("--radius", '-r',
                        # FIXME: figure out how to assign this a unit.degree before storage
                        action='store',
                        default=36 * units.arcsec,  # about 200 px square
                        help='Radius (arcsec) of circle of cutout postage stamp.')
    parser.add_argument("--debug", "-d",
                        action="store_true")
    parser.add_argument("--verbose", "-v",
                        action="store_true")
    parser.add_argument("--recheck",
                        default=None,
                        action="store",
                        help="A tuple of TNO IDs to rerun")


    args = parser.parse_args()

    if args.debug:
        logging.basicConfig(level=logging.DEBUG)
    elif args.verbose:
        logging.basicConfig(level=logging.INFO)
    else:
        logging.basicConfig(level=logging.ERROR)


    astdir = args.astdir
    flist = os.listdir(astdir)
    if args.recheck:
        flist = [args.recheck + '.ast']

    for fn in flist:
        if not fn.endswith('.ast'):
            continue
        for block in args.blocks:
            if fn.startswith(block):
                obj_dir = '{}/{}/{}'.format(storage.POSTAGE_STAMPS, args.version, fn.partition('.')
                                                [0]) # obj.provisional_name
                logging.info \
                    ("Processing astrometric files in {}".format(obj_dir))
                storage.mkdir(obj_dir)
                obj = mpc.MPCReader(astdir + fn)
                # assert storage.exists(obj_dir, force=True)
                sys.stderr.write('{} beginning...'.format(obj.provisional_name))
                # if int(obj.provisional_name[3:]) == 49:
                assert isinstance(args.radius, Quantity)
                cutout(obj, obj_dir, args.radius)
                sys.stderr.write \
                    ('{} complete.\n\n'.format(obj.provisional_name))
Ejemplo n.º 18
0
    print("PLOTTING LOCATIONS OF KNOWN KBOs (using {})".format(MPCORB_FILE))
    kbos = mpcread.get_kbos(MPCORB_FILE)
    for kbo in kbos:
        kbo.compute(plot_date)
        if field_polygon.isInside(math.degrees(float(kbo.ra)),
                                  math.degrees(float(kbo.dec))):
            ax.scatter(math.degrees(kbo.ra),
                       math.degrees(kbo.dec),
                       marker='x',
                       s=4,
                       facecolor='r',
                       edgecolor='r',
                       alpha=0.3)

if PLOT_REAL_KBOS:
    reader = mpc.MPCReader()
    print("PLOTTING LOCATIONS OF OSSOS KBOs (using directory {})".format(
        REAL_KBO_AST_DIR))
    for ast in os.listdir(REAL_KBO_AST_DIR):
        if not ast.startswith('u'):
            obs = reader.read(REAL_KBO_AST_DIR + ast)
            try:
                kbo = orbfit.Orbfit(obs)
            except:
                continue
            kbo.predict(ephem.julian_date(ephem.date(plot_date)))
            # if not field_polygon.isInside(float(kbo.coordinate.ra.degrees), float(kbo.coordinate.dec.degrees)):
            #    continue
            if obs[0].mag < 23.6:
                c = 'b'
                if LABEL_FIELDS:
Ejemplo n.º 19
0
def main(mpc_file, cor_file, skip_mags=False):
    """

    :param mpc_file: A file containing the astrometric lines to be updated.
    :param cor_file: The base name for the updated astrometry and diagnostic files.
    :param skip_mags: Should we skip recomputing the magnitude of sources?
    :return: :raise ValueError: If actions on the mpc_obs indicate this is not a valid OSSOS observations
    """
    observations = mpc.MPCReader(mpc_file).mpc_observations

    original_obs = []
    modified_obs = []
    for mpc_in in observations:
        logging.info("orig: {}".format(mpc_in.to_string()))
        mpc_obs = remeasure(mpc_in)

        if skip_mags and not mpc_obs.comment.photometry_note[0] == "Z":
            mpc_mag = remeasure(recompute_mag(mpc_obs))
        else:
            mpc_mag = mpc_obs

        sep = mpc_in.coordinate.separation(mpc_mag.coordinate).degrees * 3600.0
        if sep > TOLERANCE:
            logging.error("Large offset: {} arc-sec".format(sep))
            logging.error("orig: {}".format(mpc_in.to_string()))
            logging.error(" new: {}".format(mpc_mag.to_string()))
        logging.info("modi: {}".format(mpc_mag.to_string()))
        logging.info("")
        original_obs.append(mpc_in)
        modified_obs.append(mpc_mag)

    origin = orbfit.Orbfit(original_obs)
    modified = orbfit.Orbfit(modified_obs)

    orbpt = file(cor_file+".orb", 'w')
    orbpt.write(modified.summarize()+"\n")
    orbpt.write(origin.summarize()+"\n")

    for element in ['a', 'e', 'inc', 'om', 'Node', 'T']:
        oval = getattr(origin, element)
        doval = getattr(origin, "d"+element)
        mval = getattr(modified, element)
        dmval = getattr(modified, "d"+element)
        precision = max(int(-1*math.floor(math.log10(dmval))), int(-1*math.floor(math.log10(doval)))) + 1
        precision = max(0, precision)
        vdigits = 12
        ddigits = 6
        vpadding = " "*int(vdigits-precision)
        dpadding = " "*int(ddigits-precision)

        orbpt.write("{element:>5s}: "
                    "{oval[0]:>{vdigits}.{vdigits}}.{oval[1]:<{precision}.{precision}} {vpadding} +/- "
                    "{doval[0]:>{ddigits}.{ddigits}}.{doval[1]:<{precision}.{precision}} {dpadding} ==> "
                    "{mval[0]:>{vdigits}.{vdigits}}.{mval[1]:<{precision}.{precision}} {vpadding} +/- "
                    "{dmval[0]:>{ddigits}.{ddigits}}.{dmval[1]:<{precision}.{precision}}\n".format(
            element=element,
            dpadding=dpadding,
            vpadding=vpadding,
            vdigits=vdigits,
            ddigits=ddigits,
            oval="{:12.12f}".format(oval).split("."),
            doval="{:12.12f}".format(doval).split("."),
            mval="{:12.12f}".format(mval).split("."),
            dmval="{:12.12f}".format(dmval).split("."),
            precision=precision)
        )

        delta = math.fabs(oval - mval)
        if delta > 3.5 * doval:
            logging.warn("large delta for element {}: {} --> {}".format(element, oval, mval))

    for orb in [orbfit.Orbfit(modified_obs)]:
        residuals = orb.residuals
        dra = []
        ddec = []
        for observation in orb.observations:
            if not observation.null_observation:
                dra.append(observation.ra_residual)
                ddec.append(observation.dec_residual)
                if observation.comment.plate_uncertainty * 5.0 < \
                        ((observation.ra_residual ** 2 + observation.dec_residual ** 2) ** 0.5):
                    logging.warn("LARGE RESIDUAL ON: {}".format(observation.to_string()))
                    logging.warn("Fit residual  unreasonably large.")
        dra = numpy.array(dra)
        ddec = numpy.array(ddec)
        orbpt.write("STD: {} {}\n".format(dra.std(), ddec.std()))

    orbpt.close()

    optr = file(cor_file+".tlf", 'w')
    for idx in range(len(modified_obs)):
        inp = original_obs[idx]
        out = modified_obs[idx]
        if inp != out:
            optr.write(out.to_tnodb()+"\n")
    optr.close()
    return True