def load_moments_data(results_dir):
    """Load the full-Stokes images into memory.
    
    Args:
    results_dir (str): directory to save results.
    
    Returns:
    image_temp: ARL image data.
    weights: array of weights per channel (1/sigma**2).
    """
    try:
        if os.path.isdir(results_dir):
            try:
                # Load the channel 0 data as an image template:
                image_temp = import_image_from_fits(
                    '%s/imaging_clean_WStack-%s.fits' % (results_dir, 0))
                # Fill image_temp with the multi-frequency data:
                image_temp.data = np.concatenate(([
                    import_image_from_fits('%s/imaging_clean_WStack-%s.fits' %
                                           (results_dir, channel)).data
                    for channel in range(0, 40)
                ]))
                # Calculate the weights, in the form [channel, stokes, npix, npix]:
                # Initially using std for weights, should consider more robust options.
                weights = np.array([
                    1.0 / (np.std(image_temp.data[channel, 0, :, :])**2)
                    for channel in range(0, 40)
                ])
            except:
                print("Unexpected error:", sys.exc_info()[0])
                raise
    except:
        print("Input directory does not exist:", sys.exc_info()[0])
        raise
    return image_temp, weights
Beispiel #2
0
def create_test_image(
    canonical=True,
    cellsize=None,
    frequency=None,
    channel_bandwidth=None,
    phasecentre=None,
    polarisation_frame=PolarisationFrame("stokesI")) -> Image:
    """Create a useful test image

    This is the test image M31 widely used in ALMA and other simulations. It is actually part of an Halpha region in
    M31.

    :param canonical: Make the image into a 4 dimensional image
    :param cellsize:
    :param frequency: Frequency (array) in Hz
    :param channel_bandwidth: Channel bandwidth (array) in Hz
    :param phasecentre: Phase centre of image (SkyCoord)
    :param polarisation_frame: Polarisation frame
    :return: Image
    """
    if frequency is None:
        frequency = [1e8]
    im = import_image_from_fits(arl_path("data/models/M31.MOD"))
    if canonical:

        if polarisation_frame is None:
            im.polarisation_frame = PolarisationFrame("stokesI")
        elif isinstance(polarisation_frame, PolarisationFrame):
            im.polarisation_frame = polarisation_frame
        else:
            raise ValueError("polarisation_frame is not valid")

        im = replicate_image(im,
                             frequency=frequency,
                             polarisation_frame=im.polarisation_frame)
        if cellsize is not None:
            im.wcs.wcs.cdelt[0] = -180.0 * cellsize / numpy.pi
            im.wcs.wcs.cdelt[1] = +180.0 * cellsize / numpy.pi
        if frequency is not None:
            im.wcs.wcs.crval[3] = frequency[0]
        if channel_bandwidth is not None:
            im.wcs.wcs.cdelt[3] = channel_bandwidth[0]
        else:
            if len(frequency) > 1:
                im.wcs.wcs.cdelt[3] = frequency[1] - frequency[0]
            else:
                im.wcs.wcs.cdelt[3] = 0.001 * frequency[0]
        im.wcs.wcs.radesys = 'ICRS'
        im.wcs.wcs.equinox = 2000.00

    if phasecentre is not None:
        im.wcs.wcs.crval[0] = phasecentre.ra.deg
        im.wcs.wcs.crval[1] = phasecentre.dec.deg
        # WCS is 1 relative
        im.wcs.wcs.crpix[0] = im.data.shape[3] // 2 + 1
        im.wcs.wcs.crpix[1] = im.data.shape[2] // 2 + 1

    return im
Beispiel #3
0
def create_low_test_beam(model: Image) -> Image:
    """Create a test power beam for LOW using an image from OSKAR

    :param model: Template image
    :return: Image
    """

    beam = import_image_from_fits(arl_path('data/models/SKA1_LOW_beam.fits'))

    # Scale the image cellsize to account for the different in frequencies. Eventually we will want to
    # use a frequency cube
    log.info("create_low_test_beam: primary beam is defined at %.3f MHz" %
             (beam.wcs.wcs.crval[2] * 1e-6))

    nchan, npol, ny, nx = model.shape

    # We need to interpolate each frequency channel separately. The beam is assumed to just scale with
    # frequency.

    reprojected_beam = create_empty_image_like(model)

    for chan in range(nchan):

        model2dwcs = model.wcs.sub(2).deepcopy()
        model2dshape = [model.shape[2], model.shape[3]]
        beam2dwcs = beam.wcs.sub(2).deepcopy()

        # The frequency axis is the second to last in the beam
        frequency = model.wcs.sub(['spectral']).wcs_pix2world([chan], 0)[0]
        fscale = beam.wcs.wcs.crval[2] / frequency

        beam2dwcs.wcs.cdelt = fscale * beam.wcs.sub(2).wcs.cdelt
        beam2dwcs.wcs.crpix = beam.wcs.sub(2).wcs.crpix
        beam2dwcs.wcs.crval = model.wcs.sub(2).wcs.crval
        beam2dwcs.wcs.ctype = model.wcs.sub(2).wcs.ctype
        model2dwcs.wcs.crpix = [
            model.shape[2] // 2 + 1, model.shape[3] // 2 + 1
        ]

        beam2d = create_image_from_array(beam.data[0, 0, :, :], beam2dwcs,
                                         model.polarisation_frame)
        reprojected_beam2d, footprint = reproject_image(beam2d,
                                                        model2dwcs,
                                                        shape=model2dshape)
        assert numpy.max(
            footprint.data) > 0.0, "No overlap between beam and model"

        reprojected_beam2d.data *= reprojected_beam2d.data
        reprojected_beam2d.data[footprint.data <= 0.0] = 0.0
        for pol in range(npol):
            reprojected_beam.data[chan,
                                  pol, :, :] = reprojected_beam2d.data[:, :]

    return reprojected_beam
def moments_save_to_disk(moments_im,
                         stokes_type='q',
                         results_dir='./results_dir',
                         outname='mean'):
    """Save the Faraday moments images to disk.
    
    Args:
    rmsynth (numpy array): array of complex numbers from RM Synthesis.
    cellsize (float): advised cellsize in Faraday space.
    maxrm_est (float): maximum observable RM (50 percent sensitivity).
    rmtype (str): the component of the complex numbers to process and save.
    results_dir (str): directory to save results.
    outname (str): outname for saved file.
    
    Returns:
    None
    """
    # Read in the first channel image, and appropriate it as the new moments image:
    im_moments = import_image_from_fits('%s/imaging_clean_WStack-%s.fits' %
                                        (results_dir, 0))
    # Place the data into the open image:
    im_moments.data = moments_im
    try:
        if stokes_type == 'p':
            stokes_val = 0.0
        elif stokes_type == 'q':
            stokes_val = 2.0
        elif stokes_type == 'u':
            stokes_val = 3.0
    except:
        print("Unknown value for stokes_type:", sys.exc_info()[0])
        raise

    # This line also adjusts the listed Stokes parameter (use 0.0=? for P):
    im_moments.wcs.wcs.crval = [
        im_moments.wcs.wcs.crval[0], im_moments.wcs.wcs.crval[1], stokes_val,
        im_moments.wcs.wcs.crval[3]
    ]
    # Output the file to disk:
    export_image_to_fits(im_moments,
                         '%s/%s_%s.fits' % (results_dir, outname, stokes_type))
    return