Ejemplo n.º 1
0
    def __init__(self, dataset: katdal.DataSet,
                 common: CommonStats, target: katpoint.Target) -> None:
        self.common = common
        self.target = target
        # Status string for each channel
        self.status: List[str] = ['masked'] * common.channels
        for channel in common.output_channels:
            self.status[channel] = 'failed'
        # Peak per channel (NaN where missing)
        self.peak: u.Quantity = [math.nan] * common.channels * (u.Jy / u.beam)
        # Total flux density per (polarization, channel) (NaN where missing)
        self.totals: u.Quantity = {
            pol: [math.nan] * common.channels * u.Jy
            for pol in 'IQUV'
        }
        # Noise per channel (NaN where missing)
        self.noise: u.Quantity = [math.nan] * common.channels * (u.Jy / u.beam)
        # Estimate noise from weights (NaN where missing)
        self.weights_noise: u.Quantity = [math.nan] * common.channels * (u.Jy / u.beam)
        # Increase in noise due to imaging weights
        self.normalized_noise = [math.nan] * common.channels
        self.plots: Dict[str, str] = {}     # Divs to insert for plots returned by make_plots
        self.uv_coverage = ''
        self.frequency_range = bokeh.models.Range1d(
            self.common.frequencies[0].to_value(FREQUENCY_PLOT_UNIT),
            self.common.frequencies[-1].to_value(FREQUENCY_PLOT_UNIT),
            bounds='auto'
        )
        self.channel_range = bokeh.models.Range1d(0, self.common.channels - 1, bounds='auto')
        self.time_on_target = katsdpimager.metadata.time_on_target(dataset, target)
        self.model_natural_noise: Optional[u.Quantity] = None
        if self.common.sefd is not None and len(self.common.antennas) > 1:
            n = len(self.common.antennas)
            # Correlator efficiency is already folded in to self.common.sefd
            denom = math.sqrt(2 * n * (n - 1) * self.time_on_target * self.common.channel_width)
            self.model_natural_noise = self.common.sefd / denom / u.beam

        mask = katsdpimager.metadata.target_mask(dataset, target)
        self.timestamps = dataset.timestamps[mask]
        self.time_range = bokeh.models.Range1d(
            datetime.fromtimestamp(self.timestamps[0] - 0.5 * dataset.dump_period, timezone.utc),
            datetime.fromtimestamp(self.timestamps[-1] + 0.5 * dataset.dump_period, timezone.utc)
        )
        # Find contiguous time intervals on target
        delta = np.diff(mask, prepend=0, append=0)
        starts = np.nonzero(delta == 1)[0]
        ends = np.nonzero(delta == -1)[0] - 1
        self.time_intervals = list(zip(dataset.timestamps[starts] - 0.5 * dataset.dump_period,
                                       dataset.timestamps[ends] + 0.5 * dataset.dump_period))

        self.array_ant = dataset.sensor['Antennas/array/antenna'][0]
        self.ants = dataset.ants
        self.elevation = target.azel(timestamp=self.timestamps, antenna=self.array_ant)[1] << u.rad
        self.parallactic_angle = target.parallactic_angle(
            timestamp=self.timestamps, antenna=self.array_ant) << u.rad
def check_target(OVST, target, tmstmp=None, check=True):
    '''
    :param tar:         str or object of class Target
                        if string: searches for the target in catalogue
    :param antennas:    list
                        list of antenna objects of class Antenna
    :param catalogue:   Catalogue
    :param tmstmp:      Timestamp
    :return:            list with position tuples
                        [(az1, el1), (az2, el2), ...]
    '''
    antennas = OVST.active_antennas
    catalogue = OVST.Catalogue

    azel = []
    if isinstance(target, Target):
        target = target
    elif isinstance(
            target, str
    ) and ',' in target:  # Check if target has format: e.g. 'azel, 30, 60'
        target = Target(target)
    elif isinstance(target, str):
        target = catalogue[target]
        if not target:
            raise ValueError("Target not in Catalogue")

    if isinstance(tmstmp, str):
        if tmstmp and len(tmstmp) == 5:
            tmstmp += ':00'
        if tmstmp and len(tmstmp) == 8:
            tmstmp = str(datetime.now().date()) + ' ' + tmstmp

    if isinstance(tmstmp, (int, float)):
        tmstmp = Timestamp(tmstmp)

    if not tmstmp:
        tmstmp = Timestamp()

    for antenna in antennas:
        ae = target.azel(timestamp=tmstmp, antenna=antenna)
        azel.append([rad2deg(ae[0]), rad2deg(ae[1])])

    az = [item[0] for item in azel]
    el = [item[1] for item in azel]
    if check:
        if all((OVST.az_limit[1] - 2 < i < OVST.az_limit[0] + 2
                for i in az)) or all(i < OVST.el_limit[0] for i in el):
            raise LookupError(
                'target cannot get focused at % s (target at azimuth %.2f and elevation %.2f).\n '
                'Allowed limits: az not in range of 150-173 and elevation > 25'
                % (tmstmp.local()[11:19], azel[0][0], azel[0][1]))

    return azel  # format: [(az1, el1), (az2, el2), ...]
Ejemplo n.º 3
0
class TestVirtualSensors:
    def setup(self):
        self.target = Target('PKS1934-638, radec, 19:39, -63:42')
        self.antennas = [
            Antenna('m000, -30:42:39.8, 21:26:38.0, 1086.6, 13.5, '
                    '-8.264 -207.29 8.5965'),
            Antenna('m063, -30:42:39.8, 21:26:38.0, 1086.6, 13.5, '
                    '-3419.5845 -1840.48 16.3825')
        ]
        corrprods = [('m000h', 'm000h'), ('m000v', 'm000v'),
                     ('m063h', 'm063h'), ('m063v', 'm063v'),
                     ('m000h', 'm063h'), ('m000v', 'm063v')]
        subarray = Subarray(self.antennas, corrprods)
        spw = SpectralWindow(centre_freq=1284e6,
                             channel_width=0,
                             num_chans=16,
                             sideband=1,
                             bandwidth=856e6)
        # Pick a time when the source is up as that seems more realistic
        self.timestamps = 1234667890.0 + 1.0 * np.arange(10)
        self.dataset = MinimalDataSet(self.target, subarray, spw,
                                      self.timestamps)
        self.array_ant = self.dataset.sensor.get('Antennas/array/antenna')[0]

    def test_timestamps(self):
        mjd = Timestamp(self.timestamps[0]).to_mjd()
        assert_equal(self.dataset.mjd[0], mjd)
        lst = self.array_ant.local_sidereal_time(self.timestamps)
        # Convert LST from radians (katpoint) to hours (katdal)
        assert_array_equal(self.dataset.lst, lst * (12 / np.pi))

    def test_pointing(self):
        az, el = self.target.azel(self.timestamps, self.antennas[1])
        assert_array_equal(self.dataset.az[:, 1], rad2deg(az))
        assert_array_equal(self.dataset.el[:, 1], rad2deg(el))
        ra, dec = self.target.radec(self.timestamps, self.antennas[0])
        assert_array_almost_equal(self.dataset.ra[:, 0],
                                  rad2deg(ra),
                                  decimal=5)
        assert_array_almost_equal(self.dataset.dec[:, 0],
                                  rad2deg(dec),
                                  decimal=5)
        angle = self.target.parallactic_angle(self.timestamps,
                                              self.antennas[0])
        # TODO: Check why this is so poor... see SR-1882 for progress on this
        assert_array_almost_equal(self.dataset.parangle[:, 0],
                                  rad2deg(angle),
                                  decimal=0)
        x, y = self.target.sphere_to_plane(az, el, self.timestamps,
                                           self.antennas[1])
        assert_array_equal(self.dataset.target_x[:, 1], rad2deg(x))
        assert_array_equal(self.dataset.target_y[:, 1], rad2deg(y))

    def test_uvw(self):
        u0, v0, w0 = self.target.uvw(self.antennas[0], self.timestamps,
                                     self.array_ant)
        u1, v1, w1 = self.target.uvw(self.antennas[1], self.timestamps,
                                     self.array_ant)
        u = u0 - u1
        v = v0 - v1
        w = w0 - w1
        assert_array_equal(self.dataset.u[:, 4], u)
        assert_array_equal(self.dataset.v[:, 4], v)
        assert_array_equal(self.dataset.w[:, 4], w)
        # Check that both H and V polarisations have the same (u, v, w)
        assert_array_equal(self.dataset.u[:, 5], u)
        assert_array_equal(self.dataset.v[:, 5], v)
        assert_array_equal(self.dataset.w[:, 5], w)