def test_get_obs_array_phase():
    """Test FWHM calculation."""
    for obsid, expect_ans in [(1117101752, 'P1'),
                              (1252177744, 'P2C'),
                              (1247832024, 'P2E'),
                              (1188439520, 'OTH')]:
        ans = get_obs_array_phase(obsid)
        if ans != expect_ans:
            raise AssertionError()
Пример #2
0
def find_pulsars_in_fov(obsid,
                        psrbeg,
                        psrend,
                        fwhm=None,
                        search_radius=0.02,
                        meta_data=None,
                        full_meta=None,
                        no_known_pulsars=False,
                        no_search_cands=False):
    """
    Find all pulsars in the field of view and return all the pointings sorted into vdif and normal lists:

    Parameters:
    -----------
    obsid: int
        The observation ID
    psrbeg: int
        The begining of the observation you are processing in GPS time
    psrend: int
        The end of the observation you are processing in GPS time

    fwhm: float
        OPTIONAL - The FWHM of the beam in degrees.
        Default None: Value will be estimated
    search_radius: float
        OPTIONAL - The radius to search (create beams within) in degrees to account for ionosphere.
        Default: 0.02 degrees
    meta_data: list
        OPTIONAL - Comon observation metadata in the format from vcstools.metadb_utils.get_common_obs_metadata
        Default None: Will perform the metadata call
    full_meta: dict
        OPTIONAL - Full observation metadata in the format from vcstools.metadb_utils.getmeta
        Default None: Will perform the metadata call
    no_known_pulsars: bool
        OPTIONAL - Will return no known pulsars
        Default: False
    no_search_cands: bool
        OPTIONAL - Will return no search candidates
        Default: False

    Returns:
    --------
    list of lists:
           [pulsar_name_list,
            pulsar_pointing_list,
            vdif_name_list,
            vdif_pointing_list,
            sp_name_list,
            sp_pointing_list]
    """
    if not meta_data or not full_meta:
        meta_data, full_meta = get_common_obs_metadata(obsid, return_all=True)
    channels = meta_data[-1]

    if fwhm is None:
        # Estimate FWHM
        oap = get_obs_array_phase(obsid)
        centrefreq = 1.28 * float(min(channels) + max(channels)) / 2.
        fwhm = calc_ta_fwhm(centrefreq, array_phase=oap)

    # Find all pulsars in beam at at least 0.3 and 0.1 of zenith normlaized power
    names_ra_dec = np.array(grab_source_alog(max_dm=250))
    pow_dict, _ = find_pulsars_power(obsid,
                                     powers=[0.3, 0.1],
                                     names_ra_dec=names_ra_dec)
    obs_psrs = pow_dict[0.3][obsid]
    # Find pulsars with power between 0.3 and 0.1 and calculate their SN
    psrs_list_03 = [x[0] for x in obs_psrs]
    psrs_list_01 = [x[0] for x in pow_dict[0.1][obsid]]
    psrs_03_01 = psrs_list_01
    for psr in psrs_list_03:
        if psr in psrs_list_01:
            psrs_03_01.remove(psr)
    sn_dict_01 = snfu.multi_psr_snfe(psrs_03_01,
                                     obsid,
                                     beg=psrbeg,
                                     end=psrend,
                                     min_z_power=0.1,
                                     obs_metadata=meta_data,
                                     full_meta=full_meta)
    # Include all bright pulsars in beam at at least 0.1 of zenith normalized power
    for psr in psrs_03_01:
        sn, sn_err, _, _ = sn_dict_01[psr]
        if sn is not None and sn_err is not None:
            if sn - sn_err >= 10.:
                for psr_list in pow_dict[0.1][obsid]:
                    if psr in psr_list:
                        obs_psrs.append(psr_list)

    #get all the pulsars periods
    pulsar_list = []
    for o in obs_psrs:
        pulsar_list.append(o[0])
    period_query = psrqpy.QueryATNF(params=["PSRJ", "P0"],
                                    psrs=pulsar_list,
                                    loadfromdb=data_load.ATNF_LOC).pandas

    # Sort all the sources into 3 categories, pulsars which is for slow pulsars, vdif
    # for fast pulsars that require vdif and sp for singple pulse searches (FRBs,
    # RRATs and pulsars without ATNF periods)
    pulsar_pointing_list = []
    pulsar_name_list = []
    vdif_pointing_list = []
    vdif_name_list = []
    pulsar_search_pointing_list = []
    pulsar_search_name_list = []
    sp_pointing_list = []
    sp_name_list = []

    for pi, pulsar_line in enumerate(obs_psrs):
        vdif_check = False
        sp_check = False

        PSRJ = pulsar_line[0]
        if not (len(PSRJ) < 11 or PSRJ[-1] == 'A' or PSRJ[-2:] == 'aa'):
            continue

        for line in names_ra_dec:
            if PSRJ == line[0]:
                temp = [line]

        temp = format_ra_dec(temp, ra_col=1, dec_col=2)
        jname, raj, decj = temp[0]
        #get pulsar period
        period = period_query[period_query['PSRJ'] ==
                              PSRJ].reset_index()["P0"][0]

        if math.isnan(period):
            logger.warn("Period not found in ephermeris for {0} so assuming "
                        "it's an RRAT".format(jname))
            sp_check = True
            period = 0.
        elif float(period) < .05:
            vdif_check = True
        period = float(period) * 1000.
        logger.debug(
            "{0:12} RA: {1} Dec: {2} Period: {3:8.2f} (ms) Begin {4} End {5}".
            format(PSRJ, raj, decj, period, psrbeg, psrend))

        jname_temp_list = []
        if PSRJ[-1] == 'A' or PSRJ[-2:] == 'aa':
            #Got to find all the pulsar J names with other letters
            vdif_check = True
            for pulsar_l in obs_psrs:
                pulsar_name = pulsar_l[0]
                if pulsar_name.startswith(PSRJ[:-2]):
                    jname_temp_list.append(pulsar_name)
        else:
            jname_temp_list.append(jname)

        # grid the pointings to fill 2 arcminute raduis to account for ionosphere shift
        pointing_list_list = get_pointings_required(raj, decj, fwhm,
                                                    search_radius)

        # sort the pointings into the right groups
        for prd in pointing_list_list:
            if vdif_check:
                vdif_name_list.append(jname_temp_list)
                vdif_pointing_list.append("{0}_{1}".format(prd[0], prd[1]))
            elif sp_check:
                sp_name_list.append(jname_temp_list)
                sp_pointing_list.append("{0}_{1}".format(prd[0], prd[1]))
            else:
                pulsar_name_list.append(jname_temp_list)
                pulsar_pointing_list.append("{0}_{1}".format(prd[0], prd[1]))

    #Get the rest of the singple pulse search canidates
    #-----------------------------------------------------------------------------------------------------------
    temp = get_sources_in_fov(obsid, 'RRATs', fwhm)
    sp_name_list = sp_name_list + temp[0]
    sp_pointing_list = sp_pointing_list + temp[1]

    # Find all of the FRB candidates
    #-----------------------------------------------------------------------------------------------------------
    temp = get_sources_in_fov(obsid, 'FRB', fwhm)
    sp_name_list = sp_name_list + temp[0]
    sp_pointing_list = sp_pointing_list + temp[1]

    # Find all of the Fermi candidates
    #-----------------------------------------------------------------------------------------------------------
    fermi_list = get_sources_in_fov(obsid, 'Fermi', fwhm)
    logger.info(f"{obsid} Fermi candidates: {fermi_list}")
    pulsar_search_name_list = pulsar_search_name_list + fermi_list[0]
    pulsar_search_pointing_list = pulsar_search_pointing_list + fermi_list[1]

    # Find all of the points of interest candidates
    #-----------------------------------------------------------------------------------------------
    poi_list = get_sources_in_fov(obsid, 'POI', fwhm)
    logger.info(f"{obsid} Points of interest: {poi_list}")
    pulsar_search_name_list = pulsar_search_name_list + poi_list[0]
    pulsar_search_pointing_list = pulsar_search_pointing_list + poi_list[1]

    # Sometimes we get redundant RRATs that are found in RRAT and ANTF catalogues so they need to be removed
    sp_name_list = list(dict.fromkeys([":".join(s) for s in sp_name_list]))
    sp_pointing_list = list(dict.fromkeys(sp_pointing_list))

    # Changing the format of the names list to make it easier to format
    pulsar_name_list = [":".join(s) for s in pulsar_name_list]
    vdif_name_list = [":".join(s) for s in vdif_name_list]
    pulsar_search_name_list = [":".join(s) for s in pulsar_search_name_list]

    if no_known_pulsars:
        # Return empty list for all known pulsar categories
        pulsar_name_list = []
        pulsar_pointing_list = []
        vdif_name_list = []
        vdif_pointing_list = []

    if no_search_cands:
        # Return empty list for all search candidate categories
        pulsar_search_name_list = []
        pulsar_search_pointing_list = []
        sp_name_list = []
        sp_pointing_list = []

    return [
        pulsar_name_list, pulsar_pointing_list, vdif_name_list,
        vdif_pointing_list, pulsar_search_name_list,
        pulsar_search_pointing_list, sp_name_list, sp_pointing_list
    ]
Пример #3
0
        print(parser.print_help())
        sys.exit(1)

    # Handle defaults
    if args.out_name is None:
        if args.multibeam_file:
            args.out_name = args.multibeam_file.split(".")[0]
        if args.bestprof_files:
            args.out_name = args.bestprof_files[0].split(".")[0]
    # Work out max baseline (diameter) in meters
    if args.telescope == "ASKAP":
        max_baseline = 12.
    elif args.telescope == "MWA":
        from vcstools.metadb_utils import get_obs_array_phase
        obsid = args.out_name = args.bestprof_files[0].split("_")[0]
        array_phase = get_obs_array_phase(obsid)
        if array_phase == 'P1':
            # True max_baseline is 2800 but due to the minimal amount of long baselines
            # the following is more realisitic
            max_baseline = 2000.
        if array_phase == 'P2C':
            # True max_baseline is 700.
            max_baseline = 327.
        elif array_phase == 'P2E':
            max_baseline = 4818.

    # Parse input files
    if args.multibeam_file:
        # Load multi_beam_global file
        col_name  = ['beam', 'xpos', 'ypos', 'flux', 'ferr', 'freq', 'sefd']
        dtype     = {'beam': 'string', 'xpos': 'f8', 'ypos': 'f8', 'flux': 'f4',
Пример #4
0
def launch_pabeam_sim(obsid,
                      pointing,
                      begin,
                      duration,
                      source_name="noname",
                      metafits_file=None,
                      flagged_tiles=None,
                      delays=None,
                      efficiency=1,
                      vcstools_version='master',
                      args=None,
                      common_metadata=None,
                      output_dir=None):
    """Submit a job to run the pabeam code to estimate the system equivelent
    flux density and a dependent job to resume the submit_to_databse.py code if `args` is given.

    Parameters
    ----------
    obsid : `int`
        The MWA observation ID.
    pointing : `str`
        The pointing of the simulation in the format HH:MM:SS.SS_DD:MM:SS.SS.
    begin : `int`
        The begining of the simulation in GPS time.
    duration : `int`
        The duration of the simulation in seconds (used to calculate the end of the simulation).
    source_name : `str`, optional
        The name of the source to be used to label output files. |br| Default: "noname".
    metafits_file : `str`, optional
        The location of the metafits file. If none given will assume the default location.
    flagged_tiles : `list`, optional
        A list of the flagged tiles. If none given will assume no tiles were flagged.
    efficiency : `float`, optional
        Frequency and pointing dependent array efficiency. |br| Default: 1.
    vcstools_version : `str`, optional
        VCSTools version to load in the job.
    args : `dict`, optional
        The argument parse dictionary from submit_to_database.py. 
        If supplied will launch a dependedn job with submit_to_databse.py to complete the script.
    common_metadata : `list`, optional
        The list of common metadata generated from :py:meth:`vcstools.metadb_utils.get_common_obs_metadata`.
    output_dir : `str`
        The output directory of the simulation results. By default will put it in the VCS directory under <obsid>/sefd_simulations.
    
    Examples
    --------
    A simple example:

    >>>launch_pabeam_sim(1206977296, "12:49:12_+27:12:00", 1206977300, 600, source_name="SEFD_test", output_dir=".")
    """
    # Load computer dependant config file
    comp_config = load_config_file()

    # Ensure metafits file is there
    data_dir = "{}{}".format(comp_config['base_data_dir'], obsid)
    ensure_metafits(data_dir, obsid, "{0}_metafits_ppds.fits".format(obsid))

    # Perform metadata calls
    if common_metadata is None:
        common_metadata = get_common_obs_metadata(obsid)
    # Get frequencies
    centre_freq = common_metadata[5] * 10e5
    low_freq = common_metadata[6][0] * 1.28 * 10e5
    high_freq = common_metadata[6][-1] * 1.28 * 10e5
    sim_freqs = [str(low_freq), str(centre_freq), str(high_freq)]

    # Calculate required pixel res and cores/mem
    array_phase = get_obs_array_phase(obsid)
    fwhm = calc_ta_fwhm(high_freq / 10e5, array_phase=array_phase)  #degrees
    phi_res = theta_res = fwhm / 3
    if phi_res < 0.015:
        # Going any smaller causes memory errors
        phi_res = theta_res = 0.015
    npixels = 360. // phi_res + 90. // theta_res
    cores_required = npixels * len(sim_freqs) // 600
    nodes_required = cores_required // 24 + 1

    # Make directories
    batch_dir = "{}/batch".format(data_dir)
    if output_dir is None:
        sefd_dir = "{}/sefd_simulations".format(data_dir)
    else:
        sefd_dir = output_dir
    if not os.path.exists(batch_dir):
        mdir(batch_dir, "Batch", gid=comp_config['gid'])
    if not os.path.exists(sefd_dir):
        mdir(sefd_dir, "SEFD", gid=comp_config['gid'])

    # Parse defaults
    if metafits_file is None:
        metafits_file = "{0}{1}/{1}_metafits_ppds.fits".format(
            comp_config['base_data_dir'], obsid)

    # Get delays if none given
    if delays is None:
        delays = get_common_obs_metadata(obsid)[4][0]
        print(delays)
        print(' '.join(np.array(delays, dtype=str)))

    # Set up pabeam command
    command = 'srun --export=all -u -n {} pabeam.py'.format(
        int(nodes_required * 24))
    command += ' -o {}'.format(obsid)
    command += ' -b {}'.format(begin)
    command += ' -d {}'.format(int(duration))
    command += ' -s {}'.format(
        int(duration // 4 - 1))  # force 4 time steps to get reasonable std
    command += ' -e {}'.format(efficiency)
    command += ' --metafits {}'.format(metafits_file)
    command += ' -p {}'.format(pointing)
    command += ' --grid_res {:.3f} {:.3f}'.format(theta_res, phi_res)
    command += ' --delays {}'.format(' '.join(np.array(delays, dtype=str)))
    command += ' --out_dir {}'.format(sefd_dir)
    command += ' --out_name {}'.format(source_name)
    command += ' --freq {}'.format(" ".join(sim_freqs))
    if flagged_tiles is not None:
        logger.debug("flagged_tiles: {}".format(flagged_tiles))
        command += ' --flagged_tiles {}'.format(' '.join(flagged_tiles))

    # Set up and launch job
    batch_file_name = 'pabeam_{}_{}_{}'.format(obsid, source_name, pointing)
    job_id = submit_slurm(batch_file_name, [command],
                          batch_dir=batch_dir,
                          slurm_kwargs={
                              "time": datetime.timedelta(seconds=10 * 60 * 60),
                              "nodes": int(nodes_required)
                          },
                          module_list=['hyperbeam-python'],
                          queue='cpuq',
                          cpu_threads=24,
                          mem=12288,
                          vcstools_version=vcstools_version)

    if args:
        # Set up dependant submit_to_database.py job
        submit_args = vars(args)
        # Add sefd_file argument
        submit_args['sefd_file'] = "{}/{}*stats".format(sefd_dir, source_name)
        command_str = "submit_to_database.py"
        for key, val in submit_args.items():
            if val:
                if val == True:
                    command_str += " --{}".format(key)
                else:
                    command_str += " --{} {}".format(key, val)

        batch_file_name = 'submit_to_database_{}_{}_{}'.format(
            obsid, source_name, pointing)
        job_id_dependant = submit_slurm(
            batch_file_name, [command_str],
            batch_dir=batch_dir,
            slurm_kwargs={"time": datetime.timedelta(seconds=1 * 60 * 60)},
            queue='cpuq',
            vcstools_version=vcstools_version,
            depend=[job_id])
        return job_id, job_id_dependant
Пример #5
0
        help=
        'Manualy give the declination FWHM in degrees instead of it estimating it from the array phase and frequency'
    )
    args = parser.parse_args()

    # Set up plots
    fig = plt.figure()
    plt.rc("font", size=8)
    fig.add_subplot(111)
    ax = plt.axes()
    ax.axis('equal')

    # Get the fwhm of the observation
    meta_data = get_common_obs_metadata(args.obsid)
    channels = meta_data[-1]
    oap = get_obs_array_phase(args.obsid)
    if oap == "OTH":
        #Assume it's phase 2 extended array
        oap = "P2E"
    centrefreq = 1.28 * float(min(channels) + max(channels)) / 2.
    fwhm = calc_ta_fwhm(centrefreq, array_phase=oap)
    print("Observation ID: {}".format(args.obsid))
    print("FWHM: {} deg".format(fwhm))

    detections = []
    if args.bestprof_dir:
        for bestprof_file in glob.glob("{}/*bestprof".format(
                args.bestprof_dir)):
            with open(bestprof_file, "r") as bestprof:
                lines = bestprof.readlines()
                ra, dec = lines[0].split("=")[-1].split("_")[1:3]