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
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
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