Beispiel #1
0
    def test_properMotionErrorSkyAvg(self):
        """
    Verify that the function works for reasonable combinations of array and scalar input parameters.
    """
        sigalphastar, sigdelta = astrom.properMotionErrorSkyAvg(15.0, 3.0)
        self.assertTrue(sigalphastar > 0.0)
        self.assertTrue(sigdelta > 0.0)

        gmags = linspace(6, 20, 100)
        vmini = linspace(-1, 4, 100)
        sigalphastar, sigdelta = astrom.properMotionErrorSkyAvg(gmags, vmini)
        for error in sigalphastar:
            self.assertTrue(error > 0.0)
        for error in sigdelta:
            self.assertTrue(error > 0.0)
        sigalphastar, sigdelta = astrom.properMotionErrorSkyAvg(gmags, -1.0)
        for error in sigalphastar:
            self.assertTrue(error > 0.0)
        for error in sigdelta:
            self.assertTrue(error > 0.0)
        sigalphastar, sigdelta = astrom.properMotionErrorSkyAvg(15.0, vmini)
        for error in sigalphastar:
            self.assertTrue(error > 0.0)
        for error in sigdelta:
            self.assertTrue(error > 0.0)
Beispiel #2
0
 def test_properMotionErrorSkyAveExtended(self):
     """
   Check that errors are correctly scaled for a mission extension.
   """
     sigmualphastar, sigmudelta = astrom.properMotionErrorSkyAvg(15.0, 3.0)
     for e in range(6):
         sigmualphastarext, sigmudeltaext = astrom.properMotionErrorSkyAvg(
             15.0, 3.0, extension=e)
         assert_almost_equal(sigmualphastarext / sigmualphastar,
                             power((5.0 + e) / 5.0, -1.5),
                             decimal=8)
         assert_almost_equal(sigmudeltaext / sigmudelta,
                             power((5.0 + e) / 5.0, -1.5),
                             decimal=8)
Beispiel #3
0
def gaia_proper_motion_error(d, fe_h=-1.5):
    """ Compute the sky-averaged proper motion error for an
        RR Lyrae at the given distance.

        Parameters:
        -----------
        d : quantity_like
            The distance as an Astropy Quantity object.
        fe_h : numeric
            The metallicity.
    """

    Vmag = distance_modulus(d) + M_V(fe_h)
    G = V_to_G(Vmag, V_minus_I)
    err = properMotionErrorSkyAvg(G, V_minus_I)
    err = 0.5*(err[0] + err[1])
    return err*u.microarcsecond/u.yr
Beispiel #4
0
def gaia_proper_motion_error(d, fe_h=-1.5):
    """ Compute the sky-averaged proper motion error for an
        RR Lyrae at the given distance.

        Parameters:
        -----------
        d : quantity_like
            The distance as an Astropy Quantity object.
        fe_h : numeric
            The metallicity.
    """

    Vmag = distance_modulus(d) + M_V(fe_h)
    G = V_to_G(Vmag, V_minus_I)
    err = properMotionErrorSkyAvg(G, V_minus_I)
    err = 0.5 * (err[0] + err[1])
    return err * u.microarcsecond / u.yr
Beispiel #5
0
def gaia_proper_motion_error(d, fe_h=-1.5):
    """ Compute the sky-averaged proper motion error for an
        RR Lyrae at the given distance.

        Parameters:
        -----------
        d : quantity_like
            The distance as an Astropy Quantity object.
        fe_h : numeric
            The metallicity.
    """

    if not PYGAIA:
        raise ImportError("pygaia is required to use this function.\n"
                          "pip install pygaia")

    Vmag = distance_modulus(d) + M_V(fe_h)
    G = V_to_G(Vmag, V_minus_I)
    err = properMotionErrorSkyAvg(G, V_minus_I)
    err = 0.5*(err[0] + err[1])
    return err*u.microarcsecond/u.yr
def makePlot(args):
  """
  Make the plot with proper motion performance predictions. The predictions are for the TOTAL proper
  motion under the assumption of equal components mu_alpha* and mu_delta.

  :argument args: command line arguments
  """
  gmag=np.linspace(5.7,20.0,101)

  vminiB1V=vminiFromSpt('B1V')
  vminiG2V=vminiFromSpt('G2V')
  vminiM6V=vminiFromSpt('M6V')
  
  vmagB1V=gmag-gminvFromVmini(vminiB1V)
  vmagG2V=gmag-gminvFromVmini(vminiG2V)
  vmagM6V=gmag-gminvFromVmini(vminiM6V)

  sigmualphaB1V, sigmudeltaB1V = properMotionErrorSkyAvg(gmag,vminiB1V)
  sigmuB1V = np.sqrt(0.5*sigmualphaB1V**2+0.5*sigmudeltaB1V**2)
  sigmualphaB1V, sigmudeltaB1V = properMotionMinError(gmag,vminiB1V)
  sigmuB1Vmin = np.sqrt(0.5*sigmualphaB1V**2+0.5*sigmudeltaB1V**2)
  sigmualphaB1V, sigmudeltaB1V = properMotionMaxError(gmag,vminiB1V)
  sigmuB1Vmax = np.sqrt(0.5*sigmualphaB1V**2+0.5*sigmudeltaB1V**2)
  
  sigmualphaG2V, sigmudeltaG2V = properMotionErrorSkyAvg(gmag,vminiG2V)
  sigmuG2V = np.sqrt(0.5*sigmualphaG2V**2+0.5*sigmudeltaG2V**2)
  sigmualphaG2V, sigmudeltaG2V = properMotionMinError(gmag,vminiG2V)
  sigmuG2Vmin = np.sqrt(0.5*sigmualphaG2V**2+0.5*sigmudeltaG2V**2)
  sigmualphaG2V, sigmudeltaG2V = properMotionMaxError(gmag,vminiG2V)
  sigmuG2Vmax = np.sqrt(0.5*sigmualphaG2V**2+0.5*sigmudeltaG2V**2)
  
  sigmualphaM6V, sigmudeltaM6V = properMotionErrorSkyAvg(gmag,vminiM6V)
  sigmuM6V = np.sqrt(0.5*sigmualphaM6V**2+0.5*sigmudeltaM6V**2)
  sigmualphaM6V, sigmudeltaM6V = properMotionMinError(gmag,vminiM6V)
  sigmuM6Vmin = np.sqrt(0.5*sigmualphaM6V**2+0.5*sigmudeltaM6V**2)
  sigmualphaM6V, sigmudeltaM6V = properMotionMaxError(gmag,vminiM6V)
  sigmuM6Vmax = np.sqrt(0.5*sigmualphaM6V**2+0.5*sigmudeltaM6V**2)
  
  fig=plt.figure(figsize=(10,6.5))
  
  if (args['gmagAbscissa']):
    plt.semilogy(gmag, sigmuB1V, 'b', label='B1V')
    plt.semilogy(gmag, sigmuG2V, 'g', label='G2V')
    plt.semilogy(gmag, sigmuM6V, 'r', label='M6V')
    plt.xlim((5,20))
    plt.ylim((1,500))
    plt.legend(loc=4)
  else:
    ax=fig.add_subplot(111)
    plt.semilogy(vmagB1V, sigmuB1V, 'b', label='B1V')
    #plt.semilogy(vmagG2V, sigmuG2V, 'g', label='G2V')
    plt.semilogy(vmagM6V, sigmuM6V, 'r', label='M6V')
    plt.fill_between(vmagB1V, sigmuB1Vmin, sigmuB1Vmax, color='b', alpha=0.3)
    plt.fill_between(vmagM6V, sigmuM6Vmin, sigmuM6Vmax, color='r', alpha=0.3)
    plt.xlim((5,22.5))
    plt.ylim((1,500))
    plt.text(17.5,100,'B1V',color='b')
    plt.text(18,10,'M6V',color='r')
    plt.text(7,11,'calibration noise floor', size=12, bbox=dict(boxstyle="round,pad=0.3",
                       ec=(0.0, 0.0, 0.0),
                       fc=(1.0, 1.0, 1.0),
                       ))
    plt.text(14.75,50,'photon noise', rotation=45, size=12, bbox=dict(boxstyle="round,pad=0.3",
                       ec=(0.0, 0.0, 0.0),
                       fc=(1.0, 1.0, 1.0),
                       ))
    ax.annotate('non-uniformity\nover the sky', xy=(21.5, 80),  xycoords='data',
                  xytext=(21.5,30), textcoords='data', ha='center', size='12',
                  bbox=dict(boxstyle="round,pad=0.3",ec=(0,0,0),fc=(1,1,1)),
                  arrowprops=dict(facecolor='black', shrink=0.15, width=1,
                    headwidth=6),
                  horizontalalignment='right', verticalalignment='top',
                  )
    ax.annotate('', xy=(21.5, 170),  xycoords='data',
                  xytext=(21.5,380), textcoords='data', ha='center', size='12',
                  arrowprops=dict(facecolor='black', shrink=0.15, width=1,
                    headwidth=6),
                  horizontalalignment='right', verticalalignment='bottom',
                  )
  
  plt.xticks(np.arange(6,24,2))
  ax = plt.gca().yaxis 
  ax.set_major_formatter(matplotlib.ticker.ScalarFormatter())
  plt.ticklabel_format(axis='y',style='plain')
  plt.grid(which='both')
  plt.xlabel('$V$ [mag]')
  plt.ylabel('End-of-mission $\\sigma_\\mu$ [$\mu$as/yr]')
  
  basename = 'ProperMotionErrors'
  if (args['pdfOutput']):
    plt.savefig(basename+'.pdf')
  elif (args['pngOutput']):
    plt.savefig(basename+'.png')
  else:
    plt.show()
def makePlot(args):
    """
  Make the plot with proper motion performance predictions. The predictions are for the TOTAL proper
  motion under the assumption of equal components mu_alpha* and mu_delta.

  :argument args: command line arguments
  """
    gmag = np.linspace(5.7, 20.0, 101)

    vminiB1V = vminiFromSpt('B1V')
    vminiG2V = vminiFromSpt('G2V')
    vminiM6V = vminiFromSpt('M6V')

    vmagB1V = gmag - gminvFromVmini(vminiB1V)
    vmagG2V = gmag - gminvFromVmini(vminiG2V)
    vmagM6V = gmag - gminvFromVmini(vminiM6V)

    sigmualphaB1V, sigmudeltaB1V = properMotionErrorSkyAvg(gmag, vminiB1V)
    sigmuB1V = np.sqrt(0.5 * sigmualphaB1V**2 + 0.5 * sigmudeltaB1V**2)
    sigmualphaB1V, sigmudeltaB1V = properMotionMinError(gmag, vminiB1V)
    sigmuB1Vmin = np.sqrt(0.5 * sigmualphaB1V**2 + 0.5 * sigmudeltaB1V**2)
    sigmualphaB1V, sigmudeltaB1V = properMotionMaxError(gmag, vminiB1V)
    sigmuB1Vmax = np.sqrt(0.5 * sigmualphaB1V**2 + 0.5 * sigmudeltaB1V**2)

    sigmualphaG2V, sigmudeltaG2V = properMotionErrorSkyAvg(gmag, vminiG2V)
    sigmuG2V = np.sqrt(0.5 * sigmualphaG2V**2 + 0.5 * sigmudeltaG2V**2)
    sigmualphaG2V, sigmudeltaG2V = properMotionMinError(gmag, vminiG2V)
    sigmuG2Vmin = np.sqrt(0.5 * sigmualphaG2V**2 + 0.5 * sigmudeltaG2V**2)
    sigmualphaG2V, sigmudeltaG2V = properMotionMaxError(gmag, vminiG2V)
    sigmuG2Vmax = np.sqrt(0.5 * sigmualphaG2V**2 + 0.5 * sigmudeltaG2V**2)

    sigmualphaM6V, sigmudeltaM6V = properMotionErrorSkyAvg(gmag, vminiM6V)
    sigmuM6V = np.sqrt(0.5 * sigmualphaM6V**2 + 0.5 * sigmudeltaM6V**2)
    sigmualphaM6V, sigmudeltaM6V = properMotionMinError(gmag, vminiM6V)
    sigmuM6Vmin = np.sqrt(0.5 * sigmualphaM6V**2 + 0.5 * sigmudeltaM6V**2)
    sigmualphaM6V, sigmudeltaM6V = properMotionMaxError(gmag, vminiM6V)
    sigmuM6Vmax = np.sqrt(0.5 * sigmualphaM6V**2 + 0.5 * sigmudeltaM6V**2)

    fig = plt.figure(figsize=(10, 6.5))

    if (args['gmagAbscissa']):
        plt.semilogy(gmag, sigmuB1V, 'b', label='B1V')
        plt.semilogy(gmag, sigmuG2V, 'g', label='G2V')
        plt.semilogy(gmag, sigmuM6V, 'r', label='M6V')
        plt.xlim((5, 20))
        plt.ylim((1, 500))
        plt.legend(loc=4)
    else:
        ax = fig.add_subplot(111)
        plt.semilogy(vmagB1V, sigmuB1V, 'b', label='B1V')
        #plt.semilogy(vmagG2V, sigmuG2V, 'g', label='G2V')
        plt.semilogy(vmagM6V, sigmuM6V, 'r', label='M6V')
        plt.fill_between(vmagB1V,
                         sigmuB1Vmin,
                         sigmuB1Vmax,
                         color='b',
                         alpha=0.3)
        plt.fill_between(vmagM6V,
                         sigmuM6Vmin,
                         sigmuM6Vmax,
                         color='r',
                         alpha=0.3)
        plt.xlim((5, 22.5))
        plt.ylim((1, 500))
        plt.text(17.5, 100, 'B1V', color='b')
        plt.text(18, 10, 'M6V', color='r')
        plt.text(7,
                 11,
                 'calibration noise floor',
                 size=12,
                 bbox=dict(
                     boxstyle="round,pad=0.3",
                     ec=(0.0, 0.0, 0.0),
                     fc=(1.0, 1.0, 1.0),
                 ))
        plt.text(14.75,
                 50,
                 'photon noise',
                 rotation=45,
                 size=12,
                 bbox=dict(
                     boxstyle="round,pad=0.3",
                     ec=(0.0, 0.0, 0.0),
                     fc=(1.0, 1.0, 1.0),
                 ))
        ax.annotate(
            'non-uniformity\nover the sky',
            xy=(21.5, 80),
            xycoords='data',
            xytext=(21.5, 30),
            textcoords='data',
            ha='center',
            size='12',
            bbox=dict(boxstyle="round,pad=0.3", ec=(0, 0, 0), fc=(1, 1, 1)),
            arrowprops=dict(facecolor='black',
                            shrink=0.15,
                            width=1,
                            headwidth=6),
            horizontalalignment='right',
            verticalalignment='top',
        )
        ax.annotate(
            '',
            xy=(21.5, 170),
            xycoords='data',
            xytext=(21.5, 380),
            textcoords='data',
            ha='center',
            size='12',
            arrowprops=dict(facecolor='black',
                            shrink=0.15,
                            width=1,
                            headwidth=6),
            horizontalalignment='right',
            verticalalignment='bottom',
        )

    plt.xticks(np.arange(6, 24, 2))
    ax = plt.gca().yaxis
    ax.set_major_formatter(matplotlib.ticker.ScalarFormatter())
    plt.ticklabel_format(axis='y', style='plain')
    plt.grid(which='both')
    plt.xlabel('$V$ [mag]')
    plt.ylabel('End-of-mission $\\sigma_\\mu$ [$\mu$as/yr]')

    basename = 'ProperMotionErrors'
    if (args['pdfOutput']):
        plt.savefig(basename + '.pdf')
    elif (args['pngOutput']):
        plt.savefig(basename + '.png')
    else:
        plt.show()
def main(argv):
    parser = argparse.ArgumentParser(
        description=
        "This Script downloads a besancon model including include_kinematics using the astroquery interface. Gaia DR2 parallax and proper motion sky-averaged uncertainties are derived using pygaia. Random errors corresponding to Gaia DR2 expectations can be added to the parallaxes and distances of the model output."
    )
    parser.add_argument('email', help='Your valid email address.')
    parser.add_argument('--ra_deg',
                        type=float,
                        default=10.,
                        help='RA in degrees')
    parser.add_argument('--dec_deg',
                        type=float,
                        default=0.,
                        help='Dec in degrees')
    parser.add_argument('--field_size_squaredegree',
                        type=float,
                        default=0.05,
                        help='Field size in squaredegrees.')
    parser.add_argument('--data_dir',
                        type=str,
                        default='',
                        help='Path to directory for table saving')
    parser.add_argument('--overwrite',
                        type=bool,
                        default=False,
                        help='Overwrite download from besancon server.')
    parser.add_argument(
        '--add_random_gaia_errors',
        type=bool,
        default=False,
        help=
        'Add random errors to parallax and PM assuming Gaia DR2 performances.')
    parser.add_argument(
        '--random_seed',
        type=int,
        default=None,
        help='numpy random seed for error simulation. Allows for repeatability.'
    )
    # parser.add_argument('--argument_dict', type=, default=None,
    #                     help='Dictionary of arguments passed to Besancon.query. See Besancon.query documentation for allowed values and format.')
    parser.add_argument(
        '--vmag_upper_limit',
        type=float,
        default=None,
        help='V mag upper limit passed to Besancon.query. Default is 18')

    args = parser.parse_args(argv)

    email = args.email

    # central pointing and field size
    ra_deg = args.ra_deg
    dec_deg = args.dec_deg
    field_size_squaredegree = args.field_size_squaredegree

    data_dir = args.data_dir
    overwrite = args.overwrite
    random_seed = args.random_seed
    add_random_gaia_errors = args.add_random_gaia_errors
    # argument_dict = args.argument_dict
    # vmag_limits = args.vmag_limits
    vmag_upper_limit = args.vmag_upper_limit

    galactic_latitude_deg = None
    galactic_longitude_deg = None

    if (galactic_latitude_deg is None) and (galactic_longitude_deg is None):
        equatorial_coordinates = SkyCoord(ra=ra_deg * u.deg,
                                          dec=dec_deg * u.deg)
        galactic_longitude_deg = equatorial_coordinates.galactic.l.value
        galactic_latitude_deg = equatorial_coordinates.galactic.b.value

    include_kinematics = True
    pm_in_lb = False  # flag to obtain proper motions in galactic coordinates instead of equatorial

    # include_kinematics options
    kwd = {}
    if (include_kinematics):
        kwd['cinem'] = 1
        kwd['sc'] = [
            [0, 0, 0]
        ] * 15  # changed default *9 to *15 to allow for kinematics to be downloaded
        # note: if you leave klee at zero you get no kinematics
        if (pm_in_lb):
            kwd['klee'] = 2  #l/b
        else:
            kwd['klee'] = 1  #ra/dec

    # merge two dictionaries of arguments
    # if argument_dict is not None:
    #     kwd = {**kwd, **argument_dict}
    # if vmag_limits is not None:
    #     kwd['mag_limits'] = {'V': vmag_limits}

    # execute the query and save into astropy table on disk
    table_file = os.path.join(
        data_dir, 'besancon_table_{:3.2f}_{:3.2f}_{:3.2f}.csv'.format(
            galactic_longitude_deg, galactic_latitude_deg,
            field_size_squaredegree))

    if (not os.path.isfile(table_file)) | (overwrite):
        if vmag_upper_limit is not None:
            # print(vmag_upper_limit)
            mag_limits = {'V': (10, vmag_upper_limit)}
            besancon_model = Besancon.query(glon=galactic_longitude_deg,
                                            glat=galactic_latitude_deg,
                                            email=email,
                                            retrieve_file=False,
                                            area=field_size_squaredegree,
                                            mag_limits=mag_limits,
                                            **kwd)
            # print('Faintest V magnitude = {}'.format(np.max(besancon_model['V'])))
        else:
            besancon_model = Besancon.query(glon=galactic_longitude_deg,
                                            glat=galactic_latitude_deg,
                                            email=email,
                                            retrieve_file=False,
                                            area=field_size_squaredegree,
                                            **kwd)
        besancon_model.write(table_file,
                             format='ascii.fixed_width',
                             delimiter=',',
                             bookend=False)
    else:
        besancon_model = Table.read(table_file,
                                    format='ascii.basic',
                                    delimiter=',')

    dr2_table_file = table_file.replace('besancon_', 'besancon_gaia_dr2_')

    # compute Gaia magnitude and color
    besancon_model['G-V'] = transformations.gminvFromVmini(
        besancon_model['V-I'])
    besancon_model['Gmag'] = besancon_model['G-V'] + besancon_model['V']
    besancon_model['BP-RP'] = vminusi_to_gaiacolor(besancon_model['V-I'])
    besancon_model['BP'], besancon_model['RP'] = get_gaia_bp_and_rp(
        besancon_model['V'], besancon_model['V-I'])
    # print(besancon_model['BP']-besancon_model['RP'] - besancon_model['BP-RP'])

    # compute expected DR2 errors, parallaxErrorSkyAvg is in microarcsec
    dr2_offset = -(60. - 22.) / 12.
    besancon_model['properMotionErrorSkyAvg_dr2_ra_maspyr'], besancon_model[
        'properMotionErrorSkyAvg_dr2_dec_maspyr'] = np.array(
            properMotionErrorSkyAvg(besancon_model['Gmag'].data,
                                    besancon_model['V-I'].data,
                                    extension=dr2_offset)) / 1000.
    besancon_model['parallaxErrorSkyAvg_dr2_mas'] = np.array(
        parallaxErrorSkyAvg(besancon_model['Gmag'],
                            besancon_model['V-I'],
                            extension=dr2_offset)) / 1000.

    besancon_model['parallax_mas'] = 1. / besancon_model[
        'Dist']  # 'Dist' is in kpc

    # coordinates are constant and equal to the central pointing in the standard output
    galactic_coords = SkyCoord('galactic',
                               l=besancon_model['l'],
                               b=besancon_model['b'],
                               unit='deg')
    besancon_model['ra_deg'] = galactic_coords.icrs.ra.value
    besancon_model['dec_deg'] = galactic_coords.icrs.dec.value

    if pm_in_lb is False:
        # mux,muy are in arcsec/century
        besancon_model['pm_ra*_maspyr'] = besancon_model['mux'] * 1000 / 100.
        besancon_model['pm_dec_maspyr'] = besancon_model['muy'] * 1000 / 100.

    if add_random_gaia_errors:
        # add random errors to parallax and PM assuming Gaia DR2 performances
        if random_seed is not None:
            np.random.seed(random_seed)
        besancon_model['parallax_mas'] += (
            np.random.normal(0., 1, len(besancon_model)) *
            besancon_model['parallaxErrorSkyAvg_dr2_mas'])
        if random_seed is not None:
            np.random.seed(random_seed + 1)
        besancon_model['pm_ra*_maspyr'] += (
            np.random.normal(0., 1, len(besancon_model)) *
            besancon_model['properMotionErrorSkyAvg_dr2_ra_maspyr'])
        if random_seed is not None:
            np.random.seed(random_seed + 2)
        besancon_model['pm_dec_maspyr'] += (
            np.random.normal(0., 1, len(besancon_model)) *
            besancon_model['properMotionErrorSkyAvg_dr2_dec_maspyr'])

    besancon_model.meta = {}
    besancon_model.write(dr2_table_file,
                         format='ascii.fixed_width',
                         delimiter=',',
                         bookend=False)
    print('Besancon model and Gaia DR2 performance simulation written to {}'.
          format(dr2_table_file))