def _invert_base(self, fluxthreshold=1.0, positionthreshold=1.0, check_components=True, name='predict_ng', **kwargs): # dirty = invert_ng(self.blockvis, self.model, dopsf=False, normalize=True, **kwargs) from rascil.processing_components.imaging.ng import invert_ng dirty = invert_ng(self.blockvis, self.model, normalize=True, verbosity=self.verbosity, **kwargs) if self.persist: export_image_to_fits( dirty[0], '%s/test_imaging_ng_%s_dirty.fits' % (self.dir, name)) # import matplotlib.pyplot as plt # from rascil.processing_components.image.operations import show_image # npol = dirty[0].shape[1] # for pol in range(npol): # plt.clf() # show_image(dirty[0], pol=pol) # plt.show(block=False) assert numpy.max(numpy.abs(dirty[0].data)), "Image is empty" if check_components: self._checkcomponents(dirty[0], fluxthreshold, positionthreshold)
def _predict_base(self, fluxthreshold=1.0, name='predict_ng', **kwargs): from rascil.processing_components.imaging.ng import predict_ng, invert_ng original_vis = copy_visibility(self.blockvis) vis = predict_ng(self.blockvis, self.model, verbosity=self.verbosity, **kwargs) vis.data['vis'] = vis.data['vis'] - original_vis.data['vis'] dirty = invert_ng(vis, self.model, dopsf=False, normalize=True, verbosity=self.verbosity, **kwargs) # import matplotlib.pyplot as plt # from rascil.processing_components.image.operations import show_image # npol = dirty[0].shape[1] # for pol in range(npol): # plt.clf() # show_image(dirty[0], pol=pol) # plt.show(block=False) if self.persist: export_image_to_fits( dirty[0], '%s/test_imaging_ng_%s_residual.fits' % (self.dir, name)) # assert numpy.max(numpy.abs(dirty[0].data)), "Residual image is empty" maxabs = numpy.max(numpy.abs(dirty[0].data)) assert maxabs < fluxthreshold, "Error %.3f greater than fluxthreshold %.3f " % ( maxabs, fluxthreshold)
def test_deconvolve_and_restore_cube_mmclean_facets(self): self.actualSetUp(add_errors=True) dirty_imagelist = invert_list_rsexecute_workflow(self.vis_list, self.model_imagelist, context='2d', dopsf=False, normalize=True) psf_imagelist = invert_list_rsexecute_workflow(self.vis_list, self.model_imagelist, context='2d', dopsf=True, normalize=True) dirty_imagelist = rsexecute.persist(dirty_imagelist) psf_imagelist = rsexecute.persist(psf_imagelist) dec_imagelist = deconvolve_list_rsexecute_workflow(dirty_imagelist, psf_imagelist, self.model_imagelist, niter=1000, fractional_threshold=0.1, scales=[0, 3, 10], algorithm='mmclean', nmoment=3, nchan=self.freqwin, threshold=0.01, gain=0.7, deconvolve_facets=8, deconvolve_overlap=8, deconvolve_taper='tukey') dec_imagelist = rsexecute.persist(dec_imagelist) residual_imagelist = residual_list_rsexecute_workflow(self.vis_list, model_imagelist=dec_imagelist, context='2d') residual_imagelist = rsexecute.persist(residual_imagelist) restored_list = restore_list_rsexecute_workflow(model_imagelist=dec_imagelist, psf_imagelist=psf_imagelist, residual_imagelist=residual_imagelist, empty=self.model_imagelist) restored = rsexecute.compute(restored_list, sync=True)[0] if self.persist: export_image_to_fits(restored, '%s/test_imaging_%s_overlap_mmclean_restored.fits' % (self.dir, rsexecute.type()))
def test_create_low_test_beam(self): im = create_test_image( canonical=True, cellsize=0.002, frequency=numpy.array([1e8 - 5e7, 1e8, 1e8 + 5e7]), channel_bandwidth=numpy.array([5e7, 5e7, 5e7]), polarisation_frame=PolarisationFrame("stokesIQUV"), phasecentre=self.phasecentre) bm = create_low_test_beam(model=im) if self.persist: export_image_to_fits( bm, '%s/test_test_support_low_beam.fits' % (self.dir)) assert bm.data.shape[0] == 3 assert bm.data.shape[1] == 4 assert bm.data.shape[2] == im.data.shape[2] assert bm.data.shape[3] == im.data.shape[3] # Check to see if the beam scales as expected for i in [30, 40]: assert numpy.max( numpy.abs(bm.data[0, 0, 128, 128 - 2 * i] - bm.data[1, 0, 128, 128 - i])) < 0.02 assert numpy.max( numpy.abs(bm.data[0, 0, 128, 128 - 3 * i] - bm.data[2, 0, 128, 128 - i])) < 0.02 assert numpy.max( numpy.abs(bm.data[0, 0, 128 - 2 * i, 128] - bm.data[1, 0, 128 - i, 128])) < 0.02 assert numpy.max( numpy.abs(bm.data[0, 0, 128 - 3 * i, 128] - bm.data[2, 0, 128 - i, 128])) < 0.02
def test_restored_list_facet(self): self.actualSetUp(zerow=True) centre = self.freqwin // 2 psf_image_list = invert_list_rsexecute_workflow(self.vis_list, self.model_list, context='2d', dopsf=True) residual_image_list = residual_list_rsexecute_workflow(self.vis_list, self.model_list, context='2d') restored_4facets_image_list = restore_list_rsexecute_workflow(self.model_list, psf_image_list, residual_image_list, restore_facets=4, psfwidth=1.0) restored_4facets_image_list = rsexecute.compute(restored_4facets_image_list, sync=True) restored_1facets_image_list = restore_list_rsexecute_workflow(self.model_list, psf_image_list, residual_image_list, restore_facets=1, psfwidth=1.0) restored_1facets_image_list = rsexecute.compute(restored_1facets_image_list, sync=True) if self.persist: export_image_to_fits(restored_4facets_image_list[0], '%s/test_imaging_invert_%s_restored_4facets.fits' % (self.dir, rsexecute.type())) qa = qa_image(restored_4facets_image_list[centre]) assert numpy.abs(qa.data['max'] - 99.43438263927833) < 1e-7, str(qa) assert numpy.abs(qa.data['min'] + 0.6328915148563354) < 1e-7, str(qa) restored_4facets_image_list[centre].data -= restored_1facets_image_list[centre].data if self.persist: export_image_to_fits(restored_4facets_image_list[centre], '%s/test_imaging_invert_%s_restored_4facets_error.fits' % (self.dir, rsexecute.type())) qa = qa_image(restored_4facets_image_list[centre]) assert numpy.abs(qa.data['max']) < 1e-10, str(qa)
def test_create_voltage_patterns_illumination(self): self.createVis(freq=1.4e9) cellsize = 8 * numpy.pi / 180.0 / 280 model = create_image_from_visibility(self.vis, npixel=512, cellsize=cellsize, override_cellsize=False) plt.clf() fig, axs = plt.subplots(5, 5, gridspec_kw={'hspace': 0, 'wspace': 0}) # (r ** 2 + rho * (dx * dy) + diff * (dx ** 2 - dy ** 2)) for irho, rho in enumerate([-0.1, -0.05, 0.0, 0.05, 0.1]): for idiff, diff in enumerate([-0.2, -0.15, -0.1, -0.05, 0.0]): vp = create_vp_generic_numeric(model, pointingcentre=None, diameter=15.0, blockage=0.0, taper='gaussian', edge=0.03162278, padding=2, use_local=True, rho=rho, diff=diff) vp_data = vp.data vp.data = numpy.real(vp_data) if self.persist: export_image_to_fits( vp, "%s/test_voltage_pattern_real_%s_rho%.3f_diff%.3f.fits" % (self.dir, "MID_TAPER", rho, diff)) ax = axs[irho, idiff] ax.imshow(vp.data[0, 0]) #, vmax=0.1, vmin=-0.01) ax.axis('off') plt.show()
def test_create_voltage_patterns_zernike(self): self.createVis(freq=1.4e9) cellsize = 8 * numpy.pi / 180.0 / 280 model = create_image_from_visibility(self.vis, npixel=512, cellsize=cellsize, override_cellsize=False) plt.clf() fig, axs = plt.subplots(7, 7, gridspec_kw={'hspace': 0, 'wspace': 0}) for noll in range(1, 50): zernikes = [{'coeff': 1.0, 'noll': noll}] vp = create_vp_generic_numeric(model, pointingcentre=None, diameter=15.0, blockage=0.0, taper='gaussian', edge=0.03162278, zernikes=zernikes, padding=2, use_local=True) vp_data = vp.data vp.data = numpy.real(vp_data) if self.persist: export_image_to_fits( vp, "%s/test_voltage_pattern_real_%s_NOLL%d.fits" % (self.dir, 'MID_ZERNIKES', noll))
def _predict_base(self, fluxthreshold=1.0, gcf=None, cf=None, name='predict_2d', gcfcf=None, **kwargs): vis = predict_2d(self.vis, self.model, gcfcf=gcfcf, **kwargs) vis.data['vis'] = self.vis.data['vis'] - vis.data['vis'] dirty = invert_2d(vis, self.model, dopsf=False, normalize=True, gcfcf=gcfcf) if self.persist: export_image_to_fits( dirty[0], '%s/test_imaging_%s_residual.fits' % (self.dir, name)) assert numpy.max(numpy.abs(dirty[0].data)), "Residual image is empty" maxabs = numpy.max(numpy.abs(dirty[0].data)) assert maxabs < fluxthreshold, "Error %.3f greater than fluxthreshold %.3f " % ( maxabs, fluxthreshold)
def test_fill_pswf_to_convolutionfunction(self): oversampling = 8 support = 6 gcf, cf = create_pswf_convolutionfunction(self.image, oversampling=oversampling, support=support) assert numpy.max(numpy.abs(cf.data)) > 0.0 if self.persist: export_image_to_fits( gcf, "%s/test_convolutionfunction_pswf_gcf.fits" % self.dir) cf_image = convert_convolutionfunction_to_image(cf) cf_image.data = numpy.real(cf_image.data) if self.persist: export_image_to_fits( cf_image, "%s/test_convolutionfunction_pwsf_cf.fits" % self.dir) peak_location = numpy.unravel_index(numpy.argmax(numpy.abs(cf.data)), cf.shape) assert numpy.abs(cf.data[peak_location] - 0.1871722034219655 + 0j) < 1e-7, cf.data[peak_location] assert peak_location == (0, 0, 0, 4, 4, 3, 3), peak_location u_peak, v_peak = cf.grid_wcs.sub([1, 2]).wcs_pix2world( peak_location[-2], peak_location[-1], 0) assert numpy.abs(u_peak) < 1e-7, u_peak assert numpy.abs(v_peak) < 1e-7, u_peak
def test_calculate_image_frequency_moments_1(self): frequency = numpy.linspace(0.9e8, 1.1e8, 9) cube = create_low_test_image_from_gleam(npixel=512, cellsize=0.0001, frequency=frequency, flux_limit=1.0) log.debug( export_image_to_fits(cube, fitsfile='%s/test_moments_1_cube.fits' % (self.dir))) original_cube = copy_image(cube) moment_cube = calculate_image_frequency_moments(cube, nmoment=1) log.debug( export_image_to_fits( moment_cube, fitsfile='%s/test_moments_1_moment_cube.fits' % (self.dir))) reconstructed_cube = calculate_image_from_frequency_moments( cube, moment_cube) log.debug( export_image_to_fits( reconstructed_cube, fitsfile='%s/test_moments_1_reconstructed_cube.fits' % (self.dir))) error = numpy.std(reconstructed_cube.data - original_cube.data) assert error < 0.2
def test_griddata_invert_aterm_noover(self): self.actualSetUp(zerow=True) make_pb = functools.partial(create_pb_generic, diameter=35.0, blockage=0.0, use_local=False) pb = make_pb(self.model) if self.persist: export_image_to_fits(pb, "%s/test_gridding_aterm_pb.fits" % self.dir) gcf, cf = create_awterm_convolutionfunction(self.model, make_pb=make_pb, nw=1, oversampling=1, support=16, use_aaf=True) griddata = create_griddata_from_image(self.model) griddata, sumwt = grid_visibility_to_griddata(self.vis, griddata=griddata, cf=cf) im = fft_griddata_to_image(griddata, gcf) im = normalize_sumwt(im, sumwt) if self.persist: export_image_to_fits( im, '%s/test_gridding_dirty_aterm_noover.fits' % self.dir) self.check_peaks(im, 97.10594988491549)
def test_create_convolutionfunction(self): cf = create_convolutionfunction_from_image(self.image, nz=1) cf_image = convert_convolutionfunction_to_image(cf) cf_image.data = numpy.real(cf_image.data) if self.persist: export_image_to_fits( cf_image, "%s/test_convolutionfunction_cf.fits" % self.dir)
def test_apply_voltage_pattern(self): vp = create_vp(telescope='MID_FEKO_B2') # vp = scale_and_rotate_image(vp, 30.0 * numpy.pi / 180.0, [1.0, 2.0]) cellsize = vp.wcs.wcs.cdelt[1] * numpy.pi / 180.0 m31image = create_test_image(cellsize=cellsize, frequency=[1.36e9], canonical=True) padded = pad_image(m31image, [1, 1, 1024, 1024]) padded.data = numpy.repeat(padded.data, repeats=4, axis=1) padded.polarisation_frame = PolarisationFrame("stokesIQUV") padded.data[:, 1:, ...] = 0.0 applied = apply_voltage_pattern_to_image(padded, vp) unapplied = apply_voltage_pattern_to_image(applied, vp, inverse=True, min_det=1e-12) if self.persist: applied.data = applied.data.real fitsfile = '{}/test_apply_voltage_pattern_real.fits'.format( self.dir) export_image_to_fits(applied, fitsfile=fitsfile) unapplied.data = unapplied.data.real fitsfile = '{}/test_apply_voltage_pattern_inv_real.fits'.format( self.dir) export_image_to_fits(unapplied, fitsfile=fitsfile) err = numpy.max(numpy.abs(unapplied.data - padded.data)) assert err < 1e-12, err
def test_griddata_invert_wterm(self): self.actualSetUp(zerow=False) gcf, cf = create_awterm_convolutionfunction(self.model, nw=100, wstep=8.0, oversampling=8, support=32, use_aaf=True) cf_image = convert_convolutionfunction_to_image(cf) cf_image.data = numpy.real(cf_image.data) if self.persist: export_image_to_fits(cf_image, "%s/test_gridding_wterm_cf.fits" % self.dir) griddata = create_griddata_from_image(self.model, nw=1) griddata, sumwt = grid_visibility_to_griddata(self.vis, griddata=griddata, cf=cf) im = fft_griddata_to_image(griddata, gcf) im = normalize_sumwt(im, sumwt) if self.persist: export_image_to_fits( im, '%s/test_gridding_dirty_wterm.fits' % self.dir) self.check_peaks(im, 97.13215242859648)
def test_griddata_predict_awterm(self): self.actualSetUp(zerow=False) make_pb = functools.partial(create_pb_generic, diameter=35.0, blockage=0.0, use_local=False) pb = make_pb(self.model) if self.persist: export_image_to_fits(pb, "%s/test_gridding_awterm_pb.fits" % self.dir) gcf, cf = create_awterm_convolutionfunction(self.model, make_pb=make_pb, nw=100, wstep=8.0, oversampling=16, support=32, use_aaf=True) griddata = create_griddata_from_image(self.model, nw=100, wstep=8.0) griddata = fft_image_to_griddata(self.model, griddata, gcf) newvis = degrid_visibility_from_griddata(self.vis, griddata=griddata, cf=cf) qa = qa_visibility(newvis) assert qa.data['rms'] < 120.0, str(qa) self.plot_vis(newvis, 'awterm')
def test_tapering_Gaussian(self): self.actualSetUp() size_required = 0.010 self.componentvis = weight_visibility(self.componentvis, self.model, algoritm='uniform') self.componentvis = taper_visibility_gaussian(self.componentvis, beam=size_required) psf, sumwt = invert_2d(self.componentvis, self.model, dopsf=True) export_image_to_fits( psf, '%s/test_weighting_gaussian_taper_psf.fits' % self.dir) xfr = fft_image(psf) xfr.data = xfr.data.real.astype('float') export_image_to_fits( xfr, '%s/test_weighting_gaussian_taper_xfr.fits' % self.dir) npixel = psf.data.shape[3] sl = slice(npixel // 2 - 7, npixel // 2 + 8) fit = fit_2dgaussian(psf.data[0, 0, sl, sl]) # if fit.x_stddev <= 0.0 or fit.y_stddev <= 0.0: # raise ValueError('Error in fitting to psf') # fit_2dgaussian returns sqrt of variance. We need to convert that to FWHM. # https://en.wikipedia.org/wiki/Full_width_at_half_maximum scale_factor = numpy.sqrt(8 * numpy.log(2.0)) size = numpy.sqrt(fit.x_stddev * fit.y_stddev) * scale_factor # Now we need to convert to radians size *= numpy.pi * self.model.wcs.wcs.cdelt[1] / 180.0 # Very impressive! Desired 0.01 Acheived 0.0100006250829 assert numpy.abs(size - size_required) < 0.01 * size_required, \ "Fit should be %f, actually is %f" % (size_required, size)
def test_invert(self): uvfitsfile = rascil_path("data/vis/ASKAP_example.fits") nchan_ave = 32 nchan = 192 for schan in range(0, nchan, nchan_ave): max_chan = min(nchan, schan + nchan_ave) bv = create_blockvisibility_from_uvfits(uvfitsfile, range(schan, max_chan))[0] vis = convert_blockvisibility_to_visibility(bv) from rascil.processing_components.visibility.operations import convert_visibility_to_stokesI vis = convert_visibility_to_stokesI(vis) model = create_image_from_visibility( vis, npixel=256, polarisation_frame=PolarisationFrame('stokesI')) dirty, sumwt = invert_2d(vis, model, context='2d') assert (numpy.max(numpy.abs(dirty.data))) > 0.0 assert dirty.shape == (nchan_ave, 1, 256, 256) if self.doplot: import matplotlib.pyplot as plt from rascil.processing_components.image.operations import show_image show_image(dirty) plt.show(block=False) if self.persist: export_image_to_fits( dirty, '%s/test_visibility_uvfits_dirty.fits' % self.dir)
def test_invert_psf_block(self): self.actualSetUp(zerow=False, block=True) psf = invert_2d(self.vis, self.model, dopsf=True) error = numpy.max(psf[0].data) - 1.0 assert abs(error) < 1.0e-12, error if self.persist: export_image_to_fits(psf[0], '%s/test_imaging_2d_psf_block.fits' % (self.dir)) assert numpy.max(numpy.abs(psf[0].data)), "Image is empty"
def test_scale_and_rotate(self): vp = create_vp(telescope='MID_FEKO_B2') vp = scale_and_rotate_image(vp, 90.0 * numpy.pi / 180.0) self.persist = True if self.persist: vp.data = vp.data.real fitsfile = '{}/test_vp_rotate_real.fits'.format(self.dir) export_image_to_fits(vp, fitsfile=fitsfile)
def test_insert_skycomponent_dft(self): self.sc = create_skycomponent(direction=self.phasecentre, flux=self.sc.flux, frequency=self.component_frequency, polarisation_frame=PolarisationFrame('stokesI')) self.vis.data['vis'][...] = 0.0 self.vis = predict_skycomponent_visibility(self.vis, self.sc) im, sumwt = invert_2d(self.vis, self.model) export_image_to_fits(im, '%s/test_skycomponent_dft.fits' % self.dir) assert numpy.max(numpy.abs(self.vis.vis.imag)) < 1e-3
def test_fftim(self): self.m31image = create_test_image(cellsize=0.001, frequency=[1e8], canonical=True) m31_fft = fft_image(self.m31image) m31_fft_ifft = fft_image(m31_fft, self.m31image) numpy.testing.assert_array_almost_equal(self.m31image.data, m31_fft_ifft.data.real, 12) m31_fft.data = numpy.abs(m31_fft.data) export_image_to_fits(m31_fft, fitsfile='%s/test_m31_fft.fits' % (self.dir))
def test_create_image_from_array(self): m31model_by_array = create_image_from_array( self.m31image.data, self.m31image.wcs, self.m31image.polarisation_frame) add_image(self.m31image, m31model_by_array) assert m31model_by_array.shape == self.m31image.shape if self.persist: export_image_to_fits(self.m31image, fitsfile='%s/test_model.fits' % (self.dir)) log.debug(qa_image(m31model_by_array, context='test_create_from_image'))
def test_invert_psf_weighting_block_IQUV(self): self.actualSetUp(zerow=False, block=True, image_pol = PolarisationFrame('stokesIQUV')) for weighting in ["natural", "uniform", "robust"]: self.vis = weight_blockvisibility(self.vis, self.model, weighting=weighting, robustness=-1.0) psf = invert_2d(self.vis, self.model, dopsf=True) error = numpy.max(psf[0].data) - 1.0 assert abs(error) < 1.0e-12, error rms = numpy.std(psf[0].data) print(weighting, rms, psf[1]) if self.persist: export_image_to_fits(psf[0], '%s/test_imaging_2d_psf_block_%s_IQUV.fits' % (self.dir, weighting)) assert numpy.max(numpy.abs(psf[0].data)), "Image is empty"
def test_invert_psf_weighting(self): self.actualSetUp(zerow=False) for weighting in ["natural", "uniform", "robust"]: self.vis = weight_visibility(self.vis, self.model, weighting=weighting) psf = invert_2d(self.vis, self.model, dopsf=True) error = numpy.max(psf[0].data) - 1.0 assert abs(error) < 1.0e-12, error rms = numpy.std(psf[0].data) print(weighting, rms, psf[1]) if self.persist: export_image_to_fits(psf[0], '%s/test_imaging_2d_psf_%s.fits' % (self.dir, weighting)) assert numpy.max(numpy.abs(psf[0].data)), "Image is empty"
def test_create_test_image_from_s3_mid(self): im = create_test_image_from_s3(npixel=1024, channel_bandwidth=numpy.array([1e6]), frequency=numpy.array([1e9]), phasecentre=self.phasecentre, flux_limit=2e-3) assert im.data.shape[0] == 1 assert im.data.shape[1] == 1 assert im.data.shape[2] == 1024 assert im.data.shape[3] == 1024 if self.persist: export_image_to_fits( im, '%s/test_test_support_mid_s3.fits' % (self.dir))
def test_griddata_invert_box(self): self.actualSetUp(zerow=True) gcf, cf = create_box_convolutionfunction(self.model) griddata = create_griddata_from_image(self.model) griddata, sumwt = grid_visibility_to_griddata(self.vis, griddata=griddata, cf=cf) im = fft_griddata_to_image(griddata, gcf) im = normalize_sumwt(im, sumwt) if self.persist: export_image_to_fits(im, '%s/test_gridding_dirty_box.fits' % self.dir) self.check_peaks(im, 97.10594988491546, tol=1e-7)
def test_create_primary_beams_RADEC(self): self.createVis() for telescope in ['VLA', 'ASKAP', 'MID', 'LOW']: model = create_image_from_visibility(self.vis, cellsize=self.cellsize, npixel=self.npixel, override_cellsize=False) beam = create_pb(model, telescope=telescope, use_local=False) assert numpy.max(beam.data) > 0.0 if self.persist: export_image_to_fits( beam, "%s/test_primary_beam_RADEC_%s.fits" % (self.dir, telescope))
def test_griddata_invert_pswf_w(self): self.actualSetUp(zerow=False) gcf, cf = create_pswf_convolutionfunction(self.model) griddata = create_griddata_from_image(self.model, self.vis) griddata, sumwt = grid_visibility_to_griddata(self.vis, griddata=griddata, cf=cf) cim = fft_griddata_to_image(griddata, gcf) cim = normalize_sumwt(cim, sumwt) im = convert_polimage_to_stokes(cim) if self.persist: export_image_to_fits( im, '%s/test_gridding_dirty_pswf_w.fits' % self.dir) self.check_peaks(im, 97.13240718331633, tol=1e-7)
def test_griddata_invert_pswf_stokesIQ(self): self.actualSetUp(zerow=True, image_pol=PolarisationFrame("stokesIQ")) gcf, cf = create_pswf_convolutionfunction(self.model) griddata = create_griddata_from_image(self.model, self.vis) griddata, sumwt = grid_visibility_to_griddata(self.vis, griddata=griddata, cf=cf) cim = fft_griddata_to_image(griddata, gcf) cim = normalize_sumwt(cim, sumwt) im = convert_polimage_to_stokes(cim) if self.persist: export_image_to_fits(im, '%s/test_gridding_dirty_pswf.fits' % self.dir) self.check_peaks(im, 97.10594988491545, tol=1e-7)
def test_deconvolve_hogbom(self): self.comp, self.residual = deconvolve_cube(self.dirty, self.psf, niter=10000, gain=0.1, algorithm='hogbom', threshold=0.01) export_image_to_fits( self.residual, "%s/test_deconvolve_hogbom-residual.fits" % (self.dir)) self.cmodel = restore_cube(self.comp, self.psf, self.residual) export_image_to_fits( self.cmodel, "%s/test_deconvolve_hogbom-clean.fits" % (self.dir)) assert numpy.max(self.residual.data) < 1.2