コード例 #1
0
def insert_unittest_errors(vt,
                           seed=180555,
                           amp_errors=None,
                           phase_errors=None):
    """Simulate gain errors and apply
    
    :param vt:
    :param seed: Random number seed, set to big integer repeat values from run to run
    :param phase_errors: e.g. {'T': 1.0, 'G': 0.1, 'B': 0.01}
    :param amp_errors: e.g. {'T': 0.0, 'G': 0.01, 'B': 0.01}
    :return:
    """
    numpy.random.seed(seed)
    controls = create_calibration_controls()

    if amp_errors is None:
        amp_errors = {'T': 0.0, 'G': 0.01, 'B': 0.01}

    if phase_errors is None:
        phase_errors = {'T': 1.0, 'G': 0.1, 'B': 0.01}

    for c in "TGB":
        gaintable = \
            create_gaintable_from_blockvisibility(vt, timeslice=controls[c]['timeslice'])
        gaintable = simulate_gaintable(
            gaintable,
            timeslice=controls[c]['timeslice'],
            phase_only=controls[c]['phase_only'],
            crosspol=controls[c]['shape'] == 'matrix',
            phase_error=phase_errors[c],
            amplitude_error=amp_errors[c])
        vt = apply_gaintable(vt,
                             gaintable,
                             inverse=True,
                             timeslice=controls[c]['timeslice'])

    return vt
 def core_solve(self,
                spf,
                dpf,
                phase_error=0.1,
                amplitude_error=0.0,
                leakage=0.0,
                phase_only=True,
                niter=200,
                crosspol=False,
                residual_tol=1e-6,
                f=None,
                vnchan=3,
                timeslice='auto'):
     if f is None:
         f = [100.0, 50.0, -10.0, 40.0]
     self.actualSetup(spf, dpf, f=f, vnchan=vnchan)
     gt = create_gaintable_from_blockvisibility(self.vis,
                                                timeslice=timeslice)
     log.info("Created gain table: %s" % (gaintable_summary(gt)))
     gt = simulate_gaintable(gt,
                             phase_error=phase_error,
                             amplitude_error=amplitude_error,
                             leakage=leakage)
     original = copy_visibility(self.vis)
     vis = apply_gaintable(self.vis, gt)
     gtsol = solve_gaintable(self.vis,
                             original,
                             phase_only=phase_only,
                             niter=niter,
                             crosspol=crosspol,
                             tol=1e-6)
     vis = apply_gaintable(vis, gtsol, inverse=True)
     residual = numpy.max(gtsol.residual)
     assert residual < residual_tol, "%s %s Max residual = %s" % (spf, dpf,
                                                                  residual)
     log.debug(qa_gaintable(gt))
     assert numpy.max(numpy.abs(gtsol.gain - 1.0)) > 0.1
コード例 #3
0
def create_gaintable_from_screen(vis,
                                 sc,
                                 screen,
                                 height=3e5,
                                 vis_slices=None,
                                 scale=1.0,
                                 **kwargs):
    """ Create gaintables from a screen calculated using ARatmospy

    :param vis:
    :param sc: Sky components for which pierce points are needed
    :param screen:
    :param height: Height (in m) of screen above telescope e.g. 3e5
    :param scale: Multiply the screen by this factor
    :return:
    """
    assert isinstance(vis, BlockVisibility)

    station_locations = vis.configuration.xyz

    nant = station_locations.shape[0]
    t2r = numpy.pi / 43200.0
    gaintables = [
        create_gaintable_from_blockvisibility(vis, **kwargs) for i in sc
    ]

    # The time in the Visibility is hour angle in seconds!
    for iha, rows in enumerate(vis_timeslice_iter(vis, vis_slices=vis_slices)):
        v = create_visibility_from_rows(vis, rows)
        ha = numpy.average(v.time)
        number_bad = 0
        number_good = 0

        for icomp, comp in enumerate(sc):
            pp = find_pierce_points(station_locations,
                                    (comp.direction.ra.rad + t2r * ha) * u.rad,
                                    comp.direction.dec,
                                    height=height,
                                    phasecentre=vis.phasecentre)
            scr = numpy.zeros([nant])
            for ant in range(nant):
                pp0 = pp[ant][0:2]
                worldloc = [pp0[0], pp0[1], ha, 1e8]
                try:
                    pixloc = screen.wcs.wcs_world2pix([worldloc],
                                                      0)[0].astype('int')
                    scr[ant] = scale * screen.data[pixloc[3], pixloc[2],
                                                   pixloc[1], pixloc[0]]
                    number_good += 1
                except:
                    number_bad += 1
                    scr[ant] = 0.0

            gaintables[icomp].gain[iha, :, :, :] = numpy.exp(
                1j * scr[:, numpy.newaxis, numpy.newaxis, numpy.newaxis])
            gaintables[icomp].phasecentre = comp.direction

        if number_bad > 0:
            log.warning(
                "create_gaintable_from_screen: %d pierce points are inside the screen image"
                % (number_good))
            log.warning(
                "create_gaintable_from_screen: %d pierce points are outside the screen image"
                % (number_bad))

    return gaintables
コード例 #4
0
    def actualSetup(self,
                    vnchan=1,
                    doiso=True,
                    ntimes=5,
                    flux_limit=2.0,
                    zerow=True,
                    fixed=False):

        nfreqwin = vnchan
        rmax = 300.0
        npixel = 512
        cellsize = 0.001
        frequency = numpy.linspace(0.8e8, 1.2e8, nfreqwin)
        if nfreqwin > 1:
            channel_bandwidth = numpy.array(nfreqwin *
                                            [frequency[1] - frequency[0]])
        else:
            channel_bandwidth = [0.4e8]
        times = numpy.linspace(-numpy.pi / 3.0, numpy.pi / 3.0, ntimes)

        phasecentre = SkyCoord(ra=-60.0 * u.deg,
                               dec=-60.0 * u.deg,
                               frame='icrs',
                               equinox='J2000')

        lowcore = create_named_configuration('LOWBD2', rmax=rmax)

        block_vis = create_blockvisibility(
            lowcore,
            times,
            frequency=frequency,
            channel_bandwidth=channel_bandwidth,
            weight=1.0,
            phasecentre=phasecentre,
            polarisation_frame=PolarisationFrame("stokesI"),
            zerow=zerow)

        block_vis.data['uvw'][..., 2] = 0.0
        self.beam = create_image_from_visibility(
            block_vis,
            npixel=npixel,
            frequency=[numpy.average(frequency)],
            nchan=nfreqwin,
            channel_bandwidth=[numpy.sum(channel_bandwidth)],
            cellsize=cellsize,
            phasecentre=phasecentre)

        self.components = create_low_test_skycomponents_from_gleam(
            flux_limit=flux_limit,
            phasecentre=phasecentre,
            frequency=frequency,
            polarisation_frame=PolarisationFrame('stokesI'),
            radius=npixel * cellsize)
        self.beam = create_low_test_beam(self.beam)
        self.components = apply_beam_to_skycomponent(self.components,
                                                     self.beam,
                                                     flux_limit=flux_limit)

        self.vis = copy_visibility(block_vis, zero=True)
        gt = create_gaintable_from_blockvisibility(block_vis, timeslice='auto')
        for i, sc in enumerate(self.components):
            if sc.flux[0, 0] > 10:
                sc.flux[...] /= 10.0
            component_vis = copy_visibility(block_vis, zero=True)
            gt = simulate_gaintable(gt,
                                    amplitude_error=0.0,
                                    phase_error=0.1,
                                    seed=None)
            component_vis = predict_skycomponent_visibility(component_vis, sc)
            component_vis = apply_gaintable(component_vis, gt)
            self.vis.data['vis'][...] += component_vis.data['vis'][...]

        # Do an isoplanatic selfcal
        self.model_vis = copy_visibility(self.vis, zero=True)
        self.model_vis = predict_skycomponent_visibility(
            self.model_vis, self.components)
        if doiso:
            gt = solve_gaintable(self.vis,
                                 self.model_vis,
                                 phase_only=True,
                                 timeslice='auto')
            self.vis = apply_gaintable(self.vis, gt, inverse=True)

        self.model_vis = convert_blockvisibility_to_visibility(self.model_vis)
        self.model_vis, _, _ = weight_visibility(self.model_vis, self.beam)
        self.dirty_model, sumwt = invert_function(self.model_vis,
                                                  self.beam,
                                                  context='2d')
        export_image_to_fits(self.dirty_model,
                             "%s/test_skymodel-model_dirty.fits" % self.dir)

        lvis = convert_blockvisibility_to_visibility(self.vis)
        lvis, _, _ = weight_visibility(lvis, self.beam)
        dirty, sumwt = invert_function(lvis, self.beam, context='2d')
        if doiso:
            export_image_to_fits(
                dirty, "%s/test_skymodel-initial-iso-residual.fits" % self.dir)
        else:
            export_image_to_fits(
                dirty,
                "%s/test_skymodel-initial-noiso-residual.fits" % self.dir)

        self.skymodels = [
            SkyModel(components=[cm], fixed=fixed) for cm in self.components
        ]
コード例 #5
0
                                 gleam_model,
                                 vis_slices=51,
                                 context='wstack')
#print("np.sum(predicted_vis.data): ", numpy.sum(predicted_vis.data['vis']))
block_vis = convert_visibility_to_blockvisibility(predicted_vis)
#print("np.sum(block_vis.data): ", numpy.sum(block_vis.data['vis']))

#print("nchan npol nants ", block_vis.nchan, block_vis.npol, block_vis.nants)
#print("uvw", block_vis.uvw, numpy.sum(block_vis.uvw))
#print("vis", block_vis.vis, numpy.sum(block_vis.vis))
#print("weight", block_vis.weight, numpy.sum(block_vis.weight))
#print("time", block_vis.time, numpy.sum(block_vis.time))
#print("integration_time", block_vis.integration_time, numpy.sum(block_vis.integration_time))
#print("nvis, size", block_vis.nvis, block_vis.size())

gt = create_gaintable_from_blockvisibility(block_vis)
#print("np.sum(gt.data): ", numpy.sum(gt.data['gain']))
gt = simulate_gaintable(gt, phase_error=1.0)
#print("np.sum(gt.data): ", numpy.sum(gt.data['gain']))
blockvis = apply_gaintable(block_vis, gt)
#print("np.sum(blockvis.data): ", numpy.sum(blockvis.data['vis']))

model = create_image_from_visibility(
    block_vis,
    npixel=npixel,
    frequency=[numpy.average(frequency)],
    nchan=1,
    channel_bandwidth=[numpy.sum(channel_bandwidth)],
    cellsize=cellsize,
    phasecentre=phasecentre)
コード例 #6
0
def create_blockvisibility_iterator(
        config: Configuration,
        times: numpy.array,
        frequency: numpy.array,
        channel_bandwidth,
        phasecentre: SkyCoord,
        weight: float = 1,
        polarisation_frame=PolarisationFrame('stokesI'),
        integration_time=1.0,
        number_integrations=1,
        predict=predict_2d,
        model=None,
        components=None,
        phase_error=0.0,
        amplitude_error=0.0,
        sleep=0.0,
        **kwargs):
    """ Create a sequence of Visibilities and optionally predicting and coalescing

    This is useful mainly for performing large simulations. Do something like::
    
        vis_iter = create_blockvisibility_iterator(config, times, frequency, channel_bandwidth, phasecentre=phasecentre,
                                              weight=1.0, integration_time=30.0, number_integrations=3)

        for i, vis in enumerate(vis_iter):
        if i == 0:
            fullvis = vis
        else:
            fullvis = append_visibility(fullvis, vis)


    :param config: Configuration of antennas
    :param times: hour angles in radians
    :param frequency: frequencies (Hz] Shape [nchan]
    :param weight: weight of a single sample
    :param phasecentre: phasecentre of observation
    :param npol: Number of polarizations
    :param integration_time: Integration time ('auto' or value in s)
    :param number_integrations: Number of integrations to be created at each time.
    :param model: Model image to be inserted
    :param components: Components to be inserted
    :param sleep_time: Time to sleep between yields
    :return: Visibility

    """
    for time in times:
        actualtimes = time + numpy.arange(
            0, number_integrations) * integration_time * numpy.pi / 43200.0
        bvis = create_blockvisibility(config,
                                      actualtimes,
                                      frequency=frequency,
                                      phasecentre=phasecentre,
                                      weight=weight,
                                      polarisation_frame=polarisation_frame,
                                      integration_time=integration_time,
                                      channel_bandwidth=channel_bandwidth)

        if model is not None:
            vis = predict(bvis, model, **kwargs)
            bvis = convert_visibility_to_blockvisibility(vis)

        if components is not None:
            bvis = predict_skycomponent_visibility(bvis, components)

        # Add phase errors
        if phase_error > 0.0 or amplitude_error > 0.0:
            gt = create_gaintable_from_blockvisibility(bvis)
            gt = simulate_gaintable(gt=gt,
                                    phase_error=phase_error,
                                    amplitude_error=amplitude_error)
            bvis = apply_gaintable(bvis, gt)

        import time
        time.sleep(sleep)

        yield bvis
コード例 #7
0
 def corrupt_vis(vis, gt, **kwargs):
     if gt is None:
         gt = create_gaintable_from_blockvisibility(vis, **kwargs)
         gt = simulate_gaintable(gt, **kwargs)
     return apply_gaintable(vis, gt)
コード例 #8
0
def simulate_gaintable_from_voltage_patterns(vis,
                                             sc,
                                             vp_list,
                                             vp_coeffs,
                                             vis_slices=None,
                                             order=3,
                                             use_radec=False,
                                             **kwargs):
    """ Create gaintables for a set of zernikes

    :param vis:
    :param sc: Sky components for which pierce points are needed
    :param vp: List of Voltage patterns in AZELGEO frame
    :param vp_coeffs: Fractional contribution [nants, nvp]
    :param order: order of spline (default is 3)
    :return:
    """

    ntimes, nant = vis.vis.shape[0:2]
    vp_coeffs = numpy.array(vp_coeffs)
    gaintables = [
        create_gaintable_from_blockvisibility(vis, **kwargs) for i in sc
    ]

    if not use_radec:
        assert isinstance(vis, BlockVisibility)
        assert vis.configuration.mount[
            0] == 'azel', "Mount %s not supported yet" % vis.configuration.mount[
                0]

        # The time in the Visibility is hour angle in seconds!
        number_bad = 0
        number_good = 0

        # Cache the splines, one per voltage pattern
        real_splines = list()
        imag_splines = list()
        for ivp, vp in enumerate(vp_list):
            assert vp.wcs.wcs.ctype[0] == 'AZELGEO long', vp.wcs.wcs.ctype[0]
            assert vp.wcs.wcs.ctype[1] == 'AZELGEO lati', vp.wcs.wcs.ctype[1]

            nchan, npol, ny, nx = vp.data.shape
            real_splines.append(
                RectBivariateSpline(range(ny),
                                    range(nx),
                                    vp.data[0, 0, ...].real,
                                    kx=order,
                                    ky=order))
            imag_splines.append(
                RectBivariateSpline(range(ny),
                                    range(nx),
                                    vp.data[0, 0, ...].imag,
                                    kx=order,
                                    ky=order))

        latitude = vis.configuration.location.lat.rad

        r2d = 180.0 / numpy.pi
        s2r = numpy.pi / 43200.0
        # For each hourangle, we need to calculate the location of a component
        # in AZELGEO. With that we can then look up the relevant gain from the
        # voltage pattern
        for iha, rows in enumerate(
                vis_timeslice_iter(vis, vis_slices=vis_slices)):
            v = create_visibility_from_rows(vis, rows)
            ha = numpy.average(v.time)
            har = s2r * ha

            # Calculate the az el for this hourangle and the phasecentre declination
            azimuth_centre, elevation_centre = hadec_to_azel(
                har, vis.phasecentre.dec.rad, latitude)

            for icomp, comp in enumerate(sc):
                antgain = numpy.zeros([nant], dtype='complex')
                # Calculate the location of the component in AZELGEO, then add the pointing offset
                # for each antenna
                hacomp = comp.direction.ra.rad - vis.phasecentre.ra.rad + har
                deccomp = comp.direction.dec.rad
                azimuth_comp, elevation_comp = hadec_to_azel(
                    hacomp, deccomp, latitude)

                for ant in range(nant):
                    for ivp, vp in enumerate(vp_list):
                        nchan, npol, ny, nx = vp.data.shape
                        wcs_azel = vp.wcs.deepcopy()

                        az_comp = azimuth_centre * r2d
                        el_comp = elevation_centre * r2d

                        # We use WCS sensible coordinate handling by labelling the axes misleadingly
                        wcs_azel.wcs.crval[0] = az_comp
                        wcs_azel.wcs.crval[1] = el_comp
                        wcs_azel.wcs.ctype[0] = 'RA---SIN'
                        wcs_azel.wcs.ctype[1] = 'DEC--SIN'

                        worldloc = [
                            azimuth_comp * r2d, elevation_comp * r2d,
                            vp.wcs.wcs.crval[2], vp.wcs.wcs.crval[3]
                        ]
                        try:
                            pixloc = wcs_azel.sub(2).wcs_world2pix(
                                [worldloc[:2]], 1)[0]
                            assert pixloc[0] > 2
                            assert pixloc[0] < nx - 3
                            assert pixloc[1] > 2
                            assert pixloc[1] < ny - 3
                            gain = real_splines[ivp].ev(pixloc[1], pixloc[0]) \
                                   + 1j * imag_splines[ivp](pixloc[1], pixloc[0])
                            antgain[ant] += vp_coeffs[ant, ivp] * gain
                            number_good += 1
                        except:
                            number_bad += 1
                            antgain[ant] = 0.0

                    antgain[ant] = 1.0 / antgain[ant]

                gaintables[icomp].gain[iha, :, :, :] = antgain[:,
                                                               numpy.newaxis,
                                                               numpy.newaxis,
                                                               numpy.newaxis]
                gaintables[icomp].phasecentre = comp.direction
    else:
        assert isinstance(vis, BlockVisibility)
        number_bad = 0
        number_good = 0

        # Cache the splines, one per voltage pattern
        real_splines = list()
        imag_splines = list()
        for ivp, vp in enumerate(vp_list):

            nchan, npol, ny, nx = vp.data.shape
            real_splines.append(
                RectBivariateSpline(range(ny),
                                    range(nx),
                                    vp.data[0, 0, ...].real,
                                    kx=order,
                                    ky=order))
            imag_splines.append(
                RectBivariateSpline(range(ny),
                                    range(nx),
                                    vp.data[0, 0, ...].imag,
                                    kx=order,
                                    ky=order))

        for iha, rows in enumerate(
                vis_timeslice_iter(vis, vis_slices=vis_slices)):

            # The time in the Visibility is hour angle in seconds!
            r2d = 180.0 / numpy.pi
            # For each hourangle, we need to calculate the location of a component
            # in AZELGEO. With that we can then look up the relevant gain from the
            # voltage pattern
            v = create_visibility_from_rows(vis, rows)
            ha = numpy.average(v.time)

            for icomp, comp in enumerate(sc):
                antgain = numpy.zeros([nant], dtype='complex')
                antwt = numpy.zeros([nant])
                ra_comp = comp.direction.ra.rad
                dec_comp = comp.direction.dec.rad
                for ant in range(nant):
                    for ivp, vp in enumerate(vp_list):

                        assert vp.wcs.wcs.ctype[
                            0] == 'RA---SIN', vp.wcs.wcs.ctype[0]
                        assert vp.wcs.wcs.ctype[
                            1] == 'DEC--SIN', vp.wcs.wcs.ctype[1]

                        worldloc = [
                            ra_comp * r2d, dec_comp * r2d, vp.wcs.wcs.crval[2],
                            vp.wcs.wcs.crval[3]
                        ]
                        nchan, npol, ny, nx = vp.data.shape

                        try:
                            pixloc = vp.wcs.sub(2).wcs_world2pix(
                                [worldloc[:2]], 1)[0]
                            assert pixloc[0] > 2
                            assert pixloc[0] < nx - 3
                            assert pixloc[1] > 2
                            assert pixloc[1] < ny - 3
                            gain = real_splines[ivp].ev(pixloc[1], pixloc[0]) \
                                   + 1j * imag_splines[ivp](pixloc[1], pixloc[0])
                            antgain[ant] += vp_coeffs[ant, ivp] * gain
                            antwt[ant] = 1.0
                            number_good += 1
                        except:
                            number_bad += 1
                            antgain[ant] = 1e15
                            antwt[ant] = 0.0

                        antgain[ant] = 1.0 / antgain[ant]

                    gaintables[icomp].gain[
                        iha, :, :, :] = antgain[:, numpy.newaxis,
                                                numpy.newaxis, numpy.newaxis]
                    gaintables[icomp].weight[
                        iha, :, :, :] = antwt[:, numpy.newaxis, numpy.newaxis,
                                              numpy.newaxis]
                    gaintables[icomp].phasecentre = comp.direction

    if number_bad > 0:
        log.warning(
            "simulate_gaintable_from_voltage_patterns: %d points are inside the voltage pattern image"
            % (number_good))
        log.warning(
            "simulate_gaintable_from_voltage_patterns: %d points are outside the voltage pattern image"
            % (number_bad))

    return gaintables
 def create_calskymodel(vis, skymodel):
     gt = create_gaintable_from_blockvisibility(vis, **kwargs)
     return (copy_skymodel(skymodel), copy_gaintable(gt))
コード例 #10
0
def create_gaintable_from_pointingtable(vis,
                                        sc,
                                        pt,
                                        vp,
                                        vis_slices=None,
                                        scale=1.0,
                                        order=3,
                                        **kwargs):
    """ Create gaintables from a pointing table

    :param vis:
    :param sc: Sky components for which pierce points are needed
    :param pt: Pointing table
    :param vp: Voltage pattern
    :param scale: Multiply the screen by this factor
    :param order: order of spline (default is 3)
    :return:
    """
    assert isinstance(vis, BlockVisibility)

    nant = vis.vis.shape[1]
    gaintables = [
        create_gaintable_from_blockvisibility(vis, **kwargs) for i in sc
    ]

    nchan, npol, ny, nx = vp.data.shape

    real_spline = RectBivariateSpline(range(ny),
                                      range(nx),
                                      vp.data[0, 0, ...].real,
                                      kx=order,
                                      ky=order)
    imag_spline = RectBivariateSpline(range(ny),
                                      range(nx),
                                      vp.data[0, 0, ...].imag,
                                      kx=order,
                                      ky=order)

    # The time in the Visibility is hour angle in seconds!
    for iha, rows in enumerate(vis_timeslice_iter(vis, vis_slices=vis_slices)):
        v = create_visibility_from_rows(vis, rows)
        ha = numpy.average(v.time)
        pt_rows = (pt.time == ha)
        pointing_ha = pt.pointing[pt_rows]
        number_bad = 0
        number_good = 0

        r2d = 180.0 / numpy.pi
        for icomp, comp in enumerate(sc):
            antgain = numpy.zeros([nant], dtype='complex')
            for ant in range(nant):
                worldloc = [
                    float(
                        (comp.direction.ra.rad + pointing_ha[0, ant, 0, 0, 0])
                        * r2d),
                    float(
                        (comp.direction.dec.rad + pointing_ha[0, ant, 0, 0, 1])
                        * r2d), vp.wcs.wcs.crval[2], vp.wcs.wcs.crval[3]
                ]
                try:
                    pixloc = vp.wcs.wcs_world2pix([worldloc], 0)[0][0:2]
                    gain = real_spline.ev(
                        pixloc[1],
                        pixloc[0]) + 1j * imag_spline(pixloc[1], pixloc[0])
                    antgain[ant] = 1.0 / (scale * gain)
                    number_good += 1
                except:
                    number_bad += 1
                    antgain[ant] = 0.0

            gaintables[icomp].gain[iha, :, :, :] = antgain[:, numpy.newaxis,
                                                           numpy.newaxis,
                                                           numpy.newaxis]
            gaintables[icomp].phasecentre = comp.direction

        if number_bad > 0:
            log.warning(
                "create_gaintable_from_pointingtable: %d points are inside the voltage pattern image"
                % (number_good))
            log.warning(
                "create_gaintable_from_pointingtable: %d points are outside the voltage pattern image"
                % (number_bad))

    return gaintables
    def ingest_visibility(self,
                          freq=None,
                          chan_width=None,
                          times=None,
                          add_errors=False,
                          block=True,
                          bandpass=False):
        if freq is None:
            freq = [1e8]
        if chan_width is None:
            chan_width = [1e6]
        if times is None:
            times = (numpy.pi / 12.0) * numpy.linspace(-3.0, 3.0, 5)

        lowcore = create_named_configuration('LOWBD2', rmax=750.0)
        frequency = numpy.array(freq)
        channel_bandwidth = numpy.array(chan_width)

        phasecentre = SkyCoord(ra=+180.0 * u.deg,
                               dec=-60.0 * u.deg,
                               frame='icrs',
                               equinox='J2000')
        if block:
            vt = create_blockvisibility(
                lowcore,
                times,
                frequency,
                channel_bandwidth=channel_bandwidth,
                weight=1.0,
                phasecentre=phasecentre,
                polarisation_frame=PolarisationFrame("stokesI"))
        else:
            vt = create_visibility(
                lowcore,
                times,
                frequency,
                channel_bandwidth=channel_bandwidth,
                weight=1.0,
                phasecentre=phasecentre,
                polarisation_frame=PolarisationFrame("stokesI"))
        cellsize = 0.001
        model = create_image_from_visibility(
            vt,
            npixel=self.npixel,
            cellsize=cellsize,
            npol=1,
            frequency=frequency,
            phasecentre=phasecentre,
            polarisation_frame=PolarisationFrame("stokesI"))
        nchan = len(self.frequency)
        flux = numpy.array(nchan * [[100.0]])
        facets = 4

        rpix = model.wcs.wcs.crpix - 1.0
        spacing_pixels = self.npixel // facets
        centers = [-1.5, -0.5, 0.5, 1.5]
        comps = list()
        for iy in centers:
            for ix in centers:
                p = int(round(rpix[0] + ix * spacing_pixels * numpy.sign(model.wcs.wcs.cdelt[0]))), \
                    int(round(rpix[1] + iy * spacing_pixels * numpy.sign(model.wcs.wcs.cdelt[1])))
                sc = pixel_to_skycoord(p[0], p[1], model.wcs, origin=1)
                comp = create_skycomponent(
                    direction=sc,
                    flux=flux,
                    frequency=frequency,
                    polarisation_frame=PolarisationFrame("stokesI"))
                comps.append(comp)
        if block:
            predict_skycomponent_visibility(vt, comps)
        else:
            predict_skycomponent_visibility(vt, comps)
        insert_skycomponent(model, comps)
        self.comps = comps
        self.model = copy_image(model)
        self.empty_model = create_empty_image_like(model)
        export_image_to_fits(
            model, '%s/test_pipeline_functions_model.fits' % (self.dir))

        if add_errors:
            # These will be the same for all calls
            numpy.random.seed(180555)
            gt = create_gaintable_from_blockvisibility(vt)
            gt = simulate_gaintable(gt, phase_error=1.0, amplitude_error=0.0)
            vt = apply_gaintable(vt, gt)

            if bandpass:
                bgt = create_gaintable_from_blockvisibility(vt, timeslice=1e5)
                bgt = simulate_gaintable(bgt,
                                         phase_error=0.01,
                                         amplitude_error=0.01,
                                         smooth_channels=4)
                vt = apply_gaintable(vt, bgt)

        return vt