def compute_jones (Jones,sources,stations=None,inspectors=[],**kw):
  """Creates the Z Jones for ionospheric phase, given TECs (per source, 
  per station).""";
  stations = stations or Context.array.stations;
  ns = Jones.Subscope();
  piercings = iono_geometry.compute_piercings(ns,sources,stations);
  za_cos = iono_geometry.compute_za_cosines(ns,sources,stations);
  tecs = iono_model(ns,piercings,za_cos,sources,stations);
  # make inspector for TECs
  inspectors.append(
    Jones.scope.inspector('TEC') << StdTrees.define_inspector(tecs,sources,stations,
                                                   label='tec',freqavg=False)
  );
  if diff_mode:
    absJones = Jones('abs');
    iono_geometry.compute_zeta_jones_from_tecs(absJones,tecs,sources,stations);
    for src in sources:
      for p in stations:
        Jones(src,p) << absJones(src,p)/absJones(sources[0],p);
  else:
    iono_geometry.compute_zeta_jones_from_tecs(Jones,tecs,sources,stations);
  
  # make inspector for ionospheric phases
  Zphase = ns.Zphase;
  for src in sources:
    for p in stations:
      Zphase(src,p) << Meq.Arg(Jones(src,p));
  inspectors += [
    Jones.scope.inspector('iono_phase') << \
        StdTrees.define_inspector(Zphase,sources,stations,label='z'),
    Jones.scope.inspector('iono_piercings') << \
        StdTrees.define_inspector(ns.dxy,sources,stations,label='dxy'),
  ]
  return Jones;
Esempio n. 2
0
def compute_jones(Jones, sources, stations=None, inspectors=[], **kw):
    """Creates the Z Jones for ionospheric phase, given TECs (per source, 
  per station)."""
    stations = stations or Context.array.stations
    ns = Jones.Subscope()
    piercings = iono_geometry.compute_piercings(ns, sources, stations)
    za_cos = iono_geometry.compute_za_cosines(ns, sources, stations)
    tecs = iono_model(ns, piercings, za_cos, sources, stations)
    # make inspector for TECs
    inspectors.append(
        Jones.scope.inspector('TEC') << StdTrees.define_inspector(
            tecs, sources, stations, label='tec', freqavg=False))
    if diff_mode:
        absJones = Jones('abs')
        iono_geometry.compute_zeta_jones_from_tecs(absJones, tecs, sources,
                                                   stations)
        for src in sources:
            for p in stations:
                Jones(src, p) << absJones(src, p) / absJones(sources[0], p)
    else:
        iono_geometry.compute_zeta_jones_from_tecs(Jones, tecs, sources,
                                                   stations)

    # make inspector for ionospheric phases
    Zphase = ns.Zphase
    for src in sources:
        for p in stations:
            Zphase(src, p) << Meq.Arg(Jones(src, p))
    inspectors += [
      Jones.scope.inspector('iono_phase') << \
          StdTrees.define_inspector(Zphase,sources,stations,label='z'),
      Jones.scope.inspector('iono_piercings') << \
          StdTrees.define_inspector(ns.dxy,sources,stations,label='dxy'),
    ]
    return Jones
Esempio n. 3
0
def compute_jones (Jones,sources,stations=None,pointing_offsets=None,inspectors=[],label='E',**kw):
  stations = stations or Context.array.stations;
  ns = Jones.Subscope();

  # make the gridded beam pattern node
  beam = ns.beam;
  make_beam_nodes(beam);
  # declare an inspector node for the Jons matrix -- will be defined below
  insp = Jones.scope.inspector(label);
  inspectors += [ insp ];

  # if sky rotation is in effect, make rotation matrices
  if sky_rotation:
    for p in stations:
      pa = ns.pa(p) << Meq.ParAngle(radec=Context.observation.radec0(),xyz=Context.array.xyz(p));
      ca = ns.cos_pa(p) << Meq.Cos(pa);
      sa = ns.sin_pa(p) << Meq.Sin(pa);
      ns.parot(p) << Meq.Matrix22(ca,-sa,sa,ca);

  # loop over sources
  for src in sources:
    # If sky rotation and/or pointing offsets are in effect, we have a per-station beam.
    # Otherwise the beam is the same for all stations.
    if sky_rotation or pointing_offsets:
      for p in stations:
        lm = src.direction.lm();
        # apply rotation to put sources into the antenna frame
        if sky_rotation:
          lm = ns.lmrot(src,p) << Meq.MatrixMultiply(ns.parot(p),src.direction.lm());
        # apply offset (so pointing offsets are interpreted in the azel frame, if rotating)
        if pointing_offsets:
          lm = ns.lmoff(src,p) << lm + pointing_offsets(p);
        # now make the resampler/compounder combo. dep_mask=0xFF is a little cache-defeating magic
        # (becaise I'm too lazy to fiure out the proper symdep to put in)
        res = Jones("res",src,p) << Meq.Resampler(ns.beam,dep_mask=0xFF);
        Jones(src,p) << Meq.Compounder(lm,res,common_axes=[hiid('l'),hiid('m')]);
    else:
      # compute E for a given source. Use Resampler (though this is not really adequate!)
      res = Jones("res",src) << Meq.Resampler(ns.beam,dep_mask=0xFF);
      Jones(src) << Meq.Compounder(src.direction.lm(),res,common_axes=[hiid('l'),hiid('m')]);
      for p in stations:
        Jones(src,p) << Meq.Identity(Jones(src))

  # add a bookmark for the beam pattern
  Meow.Bookmarks.Page("%s-Jones beam pattern"%label).add(beam,viewer="Result Plotter");

  # define an inspector
  if sky_rotation or pointing_offsets:
    # Jones inspector is per-source, per-station
    insp << StdTrees.define_inspector(Jones,sources,stations,label=label);
  else:
    # Jones inspector is per-source
    insp << StdTrees.define_inspector(Jones,sources,label=label);


  return Jones;
Esempio n. 4
0
def compute_jones(Jones,
                  sources,
                  stations=None,
                  pointing_offsets=None,
                  inspectors=[],
                  label='E',
                  **kw):
    stations = stations or Context.array.stations
    ns = Jones.Subscope()

    # declare an inspector node for the Jones matrix -- will be defined below
    insp = Jones.scope.inspector(label)
    inspectors += [insp]

    radec0 = Context.observation.phase_centre.radec(
    ) if interpol_coord is COORD_THETAPHI else None

    # loop over sources
    for src in sources:
        xy = src.direction.radec(
        ) if interpol_coord is COORD_THETAPHI else src.direction.lm()
        # If sky rotation and/or horizon masking and/or pointing offsets are in effect, we have a per-station beam.
        # Otherwise the beam is the same for all stations.
        if sky_rotation or pointing_offsets or horizon_masking:
            for p in stations:
                azel = src.direction.azel(
                    Context.array.xyz(p)) if horizon_masking else None
                pa = Context.observation.phase_centre.pa(
                    Context.array.xyz(p)) if sky_rotation else None
                # apply offset in the node (so pointing offsets are interpreted in the azel frame, if rotating)
                make_beam_node(Jones(src, p),
                               filename_pattern,
                               xy,
                               radec0=radec0,
                               dlm=pointing_offsets and pointing_offsets(p),
                               azel=azel,
                               pa=pa)
        else:
            make_beam_node(Jones(src), filename_pattern, xy, radec0=radec0)
            for p in stations:
                Jones(src, p) << Meq.Identity(Jones(src))

    # define an inspector
    if sky_rotation or pointing_offsets or horizon_masking:
        # Jones inspector is per-source, per-station
        insp << StdTrees.define_inspector(
            Jones, sources, stations, label=label)
    else:
        # Jones inspector is per-source
        insp << StdTrees.define_inspector(Jones, sources, label=label)

    return Jones
Esempio n. 5
0
def compute_jones(Jones,
                  sources,
                  stations=None,
                  pointing_offsets=None,
                  inspectors=[],
                  label='E',
                  **kw):
    stations = stations or Context.array.stations
    ns = Jones.Subscope()

    # declare an inspector node for the Jones matrix -- will be defined below
    insp = Jones.scope.inspector(label)
    inspectors += [insp]

    # loop over sources
    for src in sources:
        # If sky rotation and/or pointing offsets are in effect, we have a per-station beam.
        # Otherwise the beam is the same for all stations.
        if sky_rotation or pointing_offsets:
            for p in stations:
                lm = src.direction.lm()
                # apply rotation to put sources into the antenna frame
                if sky_rotation:
                    xyz = Context.array.xyz(p)
                    pa_rot = Context.observation.phase_centre.pa_rot(xyz)
                    lm = ns.lmrot(src, p) << Meq.MatrixMultiply(
                        pa_rot, src.direction.lm())
                # apply offset in the node (so pointing offsets are interpreted in the azel frame, if rotating)
                make_beam_node(Jones(src, p), filename_pattern, lm,
                               pointing_offsets and pointing_offsets(p))
        else:
            make_beam_node(Jones(src), filename_pattern, src.direction.lm())
            for p in stations:
                Jones(src, p) << Meq.Identity(Jones(src))

    # define an inspector
    if sky_rotation or pointing_offsets:
        # Jones inspector is per-source, per-station
        insp << StdTrees.define_inspector(
            Jones, sources, stations, label=label)
    else:
        # Jones inspector is per-source
        insp << StdTrees.define_inspector(Jones, sources, label=label)

    return Jones
Esempio n. 6
0
def compute_jones (Jones,sources,stations=None,pointing_offsets=None,inspectors=[],label='E',**kw):
  stations = stations or Context.array.stations;
  ns = Jones.Subscope();

  # declare an inspector node for the Jones matrix -- will be defined below
  insp = Jones.scope.inspector(label);
  inspectors += [ insp ];

  # loop over sources
  for src in sources:
    # If sky rotation and/or pointing offsets are in effect, we have a per-station beam.
    # Otherwise the beam is the same for all stations.
    if sky_rotation or pointing_offsets:
      for p in stations:
        lm = src.direction.lm();
        # apply rotation to put sources into the antenna frame
        if sky_rotation:
          xyz = Context.array.xyz(p);
          pa_rot = Context.observation.phase_centre.pa_rot(xyz);
          lm = ns.lmrot(src,p) <<  Meq.MatrixMultiply(pa_rot,src.direction.lm());
        # apply offset in the node (so pointing offsets are interpreted in the azel frame, if rotating)
        make_beam_node(Jones(src,p),filename_pattern,lm,pointing_offsets and pointing_offsets(p));
    else:
      make_beam_node(Jones(src),filename_pattern,src.direction.lm());
      for p in stations:
        Jones(src,p) << Meq.Identity(Jones(src));

  # define an inspector
  if sky_rotation or pointing_offsets:
    # Jones inspector is per-source, per-station
    insp << StdTrees.define_inspector(Jones,sources,stations,label=label);
  else:
    # Jones inspector is per-source
    insp << StdTrees.define_inspector(Jones,sources,label=label);

  return Jones;
def compute_jones (Jones,sources,stations=None,pointing_offsets=None,inspectors=[],label='E',**kw):
  stations = stations or Context.array.stations;
  ns = Jones.Subscope();

  # declare an inspector node for the Jones matrix -- will be defined below
  insp = Jones.scope.inspector(label);
  inspectors += [ insp ];

  radec0 = Context.observation.phase_centre.radec() if interpol_coord is COORD_THETAPHI else None;

  # loop over sources
  for src in sources:
    xy = src.direction.radec() if interpol_coord is COORD_THETAPHI else src.direction.lm();
    # If sky rotation and/or horizon masking and/or pointing offsets are in effect, we have a per-station beam.
    # Otherwise the beam is the same for all stations.
    if sky_rotation or pointing_offsets or horizon_masking:
      for p in stations:
        azel = src.direction.azel(Context.array.xyz(p)) if horizon_masking else None;
        pa = Context.observation.phase_centre.pa(Context.array.xyz(p)) if sky_rotation else None;
        # apply offset in the node (so pointing offsets are interpreted in the azel frame, if rotating)
        make_beam_node(Jones(src,p),filename_pattern,xy,radec0=radec0,
                       dlm=pointing_offsets and pointing_offsets(p),azel=azel,pa=pa);
    else:
      make_beam_node(Jones(src),filename_pattern,xy,radec0=radec0);
      for p in stations:
        Jones(src,p) << Meq.Identity(Jones(src));

  # define an inspector
  if sky_rotation or pointing_offsets or horizon_masking:
    # Jones inspector is per-source, per-station
    insp << StdTrees.define_inspector(Jones,sources,stations,label=label);
  else:
    # Jones inspector is per-source
    insp << StdTrees.define_inspector(Jones,sources,label=label);

  return Jones;
Esempio n. 8
0
def compute_jones (Jones,sources,stations=None,inspectors=[],label='L',**kw):
  """Creates the dipole projection matrix.""";
  stations = stations or Context.array.stations;
  ns = Jones.Subscope();
  insp = Jones.scope.inspector(label);
  for src in sources:
    for p in stations:
      Jones(src,p) << proj_matrix(src,Context.array.xyz(p));
  insp << StdTrees.define_inspector(Jones,sources,stations,label=label);

  # add inspectors
  StdTrees.inspector(Jones.scope.inspector(label,'AzEl') ,[src.direction.azel() for src in sources],bookmark=False);
  inspectors += [ insp,Jones.scope.inspector(label,'AzEl') ];

  return Jones;
  def compute_jones (self,Jones,sources,stations=None,inspectors=[],**kw):
    """Computes beam gain for a list of sources.
    The output node, will be qualified with either a source only, or a source/station pair
    """;
    stations = stations or Context.array.stations();
    ns = Jones.Subscope();

    # init solvables etc.
    self.init_parameters(ns,sources,stations,inspectors);

    # this dict will hold LM tuples (or nodes) for each source.
    lmsrc = {};
    # see if sources have a "beam_lm" attribute, use that for beam offsets
    for src in sources:
      lm = src.get_attr("beam_lm",None) or src.get_attr("_lm_ncp",None);
      if lm:
        src.set_attr(self.label+'r',math.sqrt(lm[0]**2+lm[1]**2)/math.pi*(180*60));
        lmsrc[src.name] = ns.lm(src) << Meq.Constant(value=Timba.array.array(lm));
      # else try to use static lm coordinates
      else:
        # else try to use static lm coordinates
        lmnst = src.direction.lmn_static();
        if lmnst:
          lm = lmnst[0:2];
          src.set_attr(self.label+'r',math.sqrt(lm[0]**2+lm[1]**2)/math.pi*(180*60));
          lmsrc[src.name] = ns.lm(src) << Meq.Constant(value=Timba.array.array(lm));
        # else use lmn node
        else:
          lmsrc[src.name] = src.direction.lm();

    if self.per_station:
      for src in sources:
        for p in stations:
          self.make_beam_nodes(Jones(src,p),self.beamshape(p),lmsrc[src.name],self.ell(p),self.dlm(p));
    else:
      p0 = stations[0];
      for src in sources:
        self.make_beam_nodes(Jones(src,p0),self.beamshape(p0),lmsrc[src.name],self.ell(p0),self.dlm(p0));
        for p in stations[1:]:
          Jones(src,p) << Meq.Identity(Jones(src,p0));

    # make inspectors
    inspectors.append(ns.inspector << StdTrees.define_inspector(
              Jones,sources,stations,label=self.label));

    return Jones;
Esempio n. 10
0
def compute_jones(Jones,
                  sources,
                  stations=None,
                  inspectors=[],
                  meqmaker=None,
                  label='R',
                  **kw):
    """Creates the Z Jones for ionospheric phase, given TECs (per source, 
  per station)."""
    stations = stations or Context.array.stations
    ns = Jones.Subscope()

    parmdef = Meq.Parm(0, tags="pos_offset")
    parms = []
    uvw = Context.array.uvw()
    # now loop over sources
    for isrc, src in enumerate(sources):
        parms += [ns.dl(src) << parmdef,
                  ns.dm(src) << parmdef]
        dlmn = ns.dlmn(src) << Meq.Composer(ns.dl(src), ns.dm(src), 0)
        for p in stations:
            Jones(src, p) << Meq.VisPhaseShift(lmn=dlmn, uvw=uvw(p))
    # make bookmarks
    srcnames = [src.name for src in sources]
    meqmaker.make_bookmark_set(Jones, [(src, p) for src in srcnames
                                       for p in stations],
                               "%s: inspector plot" % label,
                               "%s: by source-station" % label,
                               freqmean=True)
    inspectors.append(ns.inspector(label,'dlmn') << \
        StdTrees.define_inspector(ns.dlmn,srcnames,label=label))

    # make parmgroups and solvejobs
    global pg
    pg = ParmGroup.ParmGroup(label,
                             parms,
                             table_name="%s.fmep" % label,
                             bookmark=False)

    # make solvejobs
    ParmGroup.SolveJob("cal_" + label,
                       "Calibrate %s (position shifts)" % label, pg)

    return Jones
Esempio n. 11
0
def compute_jones(Jones,
                  sources,
                  stations=None,
                  pointing_offsets=None,
                  inspectors=[],
                  label='E',
                  **kw):
    stations = stations or Context.array.stations
    ns = Jones.Subscope()
    JE = Jones("elem")

    per_station = sky_rotation or pointing_offsets

    # read offsets file
    if read_offsets_file:
        offsets = list(map(float,
                           open(offsets_file).read().split()))
        if len(offsets) < (beam_number + 1) * 2:
            raise ValueError("beam number %d not found in offsets file" %
                             beam_number)
        l_offset, m_offset = offsets[beam_number * 2:(beam_number + 1) * 2]
        if invert_l:
            l_offset = -l_offset
    else:
        l_offset, m_offset = 0, 0

    # loop over sources to create per-element beamgains
    for src in sources:
        # If sky rotation and/or pointing offsets are in effect, we have a per-station beam.
        # Otherwise the beam is the same for all stations.
        if per_station:
            for p in stations:
                lm = src.direction.lm()
                # apply rotation to put sources into the antenna frame
                if sky_rotation:
                    xyz = Context.array.xyz(p)
                    pa_rot = Context.observation.phase_centre.pa_rot(xyz)
                    lm = ns.lmrot(src, p) << Meq.MatrixMultiply(
                        pa_rot, src.direction.lm())
                # apply offset (so pointing offsets are interpreted in the azel frame, if rotating)
                if pointing_offsets:
                    lm = ns.lmoff(src, p) << lm + pointing_offsets(p)
                # now make the beam node
                make_beam_node(JE(src, p), filename_pattern, l_offset,
                               m_offset, lm)
        else:
            make_beam_node(JE(src), filename_pattern, l_offset, m_offset,
                           src.direction.lm())

    # now load weights
    wx = pickle.load(open(weight_filename_x, "rb"))
    wy = pickle.load(open(weight_filename_y, "rb"))
    if wx.shape[1] != num_elements or wy.shape[1] != num_elements:
        raise ValueError(
            """weights files contain weights for %d (X) and %d (Y) complex
                      elements, %d expected""" %
            (wx.shape[1], wy.shape[1], num_elements))
    if beam_number > wx.shape[0] or beam_number > wy.shape[0]:
        raise ValueError("beam number %d not found in weights files" %
                         beam_number)

    # w0:x and w0:y are the nominal weight vectors
    ns.w0('x') << Meq.Constant(value=wx[beam_number, :])
    ns.w0('y') << Meq.Constant(value=wy[beam_number, :])

    if sim_element_errors:
        # create perturbed weights
        a0 = 10**(min_ampl_var / 20) - 1
        a1 = 10**(max_ampl_var / 20) - 1
        for p in stations:
            for xy in 'x', 'y':
                werr = ns.werr(xy, p)
                # amplitude and phase period and offset
                for ap in 'ampl', 'phase':
                    p0 = werr("period", ap) << Meq.Constant(value=[
                        random.uniform(min_period_var * 3600, max_period_var *
                                       3600) / (2 * math.pi)
                        for i in range(num_elements)
                    ])
                    if start_phased_up:
                        werr("sin", ap) << Meq.Sin(Meq.Time() / p0)
                    else:
                        t0 = werr("offset", ap) << Meq.Constant(value=[
                            random.uniform(0, 2 * math.pi)
                            for i in range(num_elements)
                        ])
                        werr("sin", ap) << Meq.Sin((Meq.Time() / p0) + t0)

                # amplitude excursion
                e0 = werr("maxampl") << Meq.Constant(value=[
                    random.uniform(a0, a1) for i in range(num_elements)
                ])
                ep = werr("maxphase") << Meq.Constant(value=[
                    random.uniform(min_phase_var * DEG, max_phase_var * DEG)
                    for i in range(num_elements)
                ])
                # weight errors
                werr << Meq.Polar(1 + e0 * werr("sin", "ampl"),
                                  ep * werr("sin", "phase"))
                ns.weight(xy, p) << ns.w0(xy) * werr

    # compute matrix norms based on nominal matrices
    if per_station:
        quallist = [[src, p] for src in sources for p in stations]
    else:
        quallist = [[src] for src in sources]
    for qq in quallist:
        ex0 = Jones(*(qq + ["x0"])) << Meq.MatrixMultiply(JE(*qq), ns.w0("x"))
        ey0 = Jones(*(qq + ["y0"])) << Meq.MatrixMultiply(JE(*qq), ns.w0("y"))
        J0 = Jones(*(qq + ["nominal"])) << Meq.Composer(ex0, ey0, dims=[2, 2])
        if do_normalize or (qq[0] is sources[0] and do_correct):
            make_norm(J0, Jones(*(qq + ["norm"])))

    if do_normalize:
        # norm towards source is average per-station norm
        if per_station:
            for src in sources:
                Jones(src, "norm") << Meq.Add(
                    *[Jones(src, p, "norm") for p in stations]) / len(stations)
                #average must be float
    elif do_correct:
        if per_station:
            for src in sources:
                Jones(sources[0], "norm") << Meq.Add(
                    *[Jones(sources[0], p, "norm")
                      for p in stations]) / len(stations)
                #average must be float
        for src in sources[1:]:
            Jones(src, "norm") << Meq.Identity(Jones(sources[0], "norm"))
    else:
        for src in sources:
            Jones(src, "norm") << 1

    # put these together into Jones matrices
    for src in sources:
        # jesrc/JJ will eventually point to the unqualified element beam node
        # of the unqualified jones node. Depending on whether we're per-station or
        # not, this is qualified with src,p or just src.
        jesrc = JE(src)
        jnorm = Jones(src, "norm")
        JJ = Jones(src)

        if sim_element_errors:
            for p in stations:
                if per_station:
                    jesrc = JE(src, p)
                    JJ = JJ(p)
                # jesrc returns a (2,N) matrix of element gains towards this source.
                # Multiply this by the weights to get the "x" and "y" beams
                ex = Jones(src, p, "x") << Meq.MatrixMultiply(
                    jesrc, ns.weight("x", p))
                ey = Jones(src, p, "y") << Meq.MatrixMultiply(
                    jesrc, ns.weight("y", p))
                if do_correct:
                    J0 = Jones(
                        src, p,
                        "ref") << Meq.Composer(ex, ey, dims=[2, 2]) / jnorm
                    if src is sources[0]:
                        Jones(src, p) << Meq.Constant(value=[1, 0, 0, 1],
                                                      dims=[2, 2])
                        Jones(src, p, "inv") << Meq.MatrixInvert22(J0)
                    else:
                        Jones(src, p) << Meq.MatrixMultiply(
                            Jones(sources[0], p, "inv"), J0)
                else:
                    Jones(src, p) << Meq.Composer(ex, ey, dims=[2, 2]) / jnorm
        # no element errors, use nominal beam
        else:
            if per_station:
                for p in stations:
                    if do_correct:
                        J0 = Jones(src, p,
                                   "ref") << Jones(src, p, "nominal") / jnorm
                        if src is sources[0]:
                            Jones(src, p) << Meq.Constant(value=[1, 0, 0, 1],
                                                          dims=[2, 2])
                            Jones(src, p, "inv") << Meq.MatrixInvert22(J0)
                        else:
                            Jones(src, p) << Meq.MatrixMultiply(
                                Jones(sources[0], p, "inv"), J0)
                    else:
                        Jones(src, p) << Jones(src, p, "nominal") / jnorm
            else:
                if do_correct:
                    J0 = Jones(src, "ref") << Jones(src, "nominal") / jnorm
                    if src is sources[0]:
                        Jones(src) << Meq.Constant(value=[1, 0, 0, 1],
                                                   dims=[2, 2])
                        Jones(src, "inv") << Meq.MatrixInvert22(J0)
                    else:
                        Jones(src) << Meq.MatrixMultiply(
                            Jones(sources[0], "inv"), J0)
                else:
                    Jones(src) << Jones(src, "nominal") / jnorm
                for p in stations:
                    Jones(src, p) << Meq.Identity(Jones(src))

    # declare an inspector node for the Jones matrix -- will be defined below
    insp = Jones.scope.inspector(label)

    # define inspectors
    insp << StdTrees.define_inspector(Jones, sources, stations, label=label)
    inspectors += [insp]
    if sim_element_errors:
        insp1 = insp("werr") << StdTrees.define_inspector(
            ns.werr, ("x", "y"), stations, label="%s weight drifts" % label)
        insp2 = insp("weights") << StdTrees.define_inspector(
            ns.weight, ("x", "y"), stations, label="%s weights" % label)

        inspectors += [insp1, insp2]

    return Jones
def compute_jones (Jones,sources,stations=None,inspectors=[],meqmaker=None,label='R',**kw):
  """Creates the Z Jones for ionospheric phase, given TECs (per source, 
  per station).""";
  stations = stations or Context.array.stations;
  ns = Jones.Subscope();
  
  # get reference source
  if ref_source:
    # treat as index first
    dir0 = None;
    try:
      dir0 = sources[int(ref_source)].direction; 
    except:
      pass;
    # else treat as name, find in list
    if not dir0:
      for src0 in sources:
        if src0.name == ref_source:
          dir0 = src0.direction;
          break;
    # else treat as direction string
    if not dir0:
      ff = list(ref_source.split());
      if len(ff) < 2 or len(ff) > 3:
        raise RuntimeError,"invalid reference dir '%s' specified for %s-Jones"%(ref_source,label);
      global dm;
      if not dm:
        raise RuntimeError,"pyrap measures module not available, cannot use direction strings for %s-Jones"%label;
      if len(ff) == 2:
        ff =  [ 'J2000' ] +ff;
      # treat as direction measure
      try:
        dmdir = dm.direction(*ff);
      except:
        raise RuntimeError,"invalid reference dir '%s' specified for %s-Jones"%(ref_source,label);
      # convert to J2000 and make direction object
      dmdir = dm.measure(dmdir,'J2000');
      ra,dec = dm.getvalue(dmdir)[0].get_value(),dm.getvalue(dmdir)[1].get_value();
      dir0 = Meow.Direction(ns,"refdir",ra,dec,static=True);
  else:
    dir0 = Context.observation.phase_centre;
 
  # make refraction scale node
  scale = ns.scale(0) << Meq.Parm(0,tags="refraction");

  xyz0 = Context.array.xyz0();
  if coord_approx:
    # get PA, and assume it's the same over the whole field
    pa = ns.pa0 << Meq.ParAngle(dir0.radec(),xyz0);
    # second column of the Rot(-PA) matrix. Multiply this by del to get a rotation of (0,del) into the lm plane.
    # The third component (0) is for convenience, as it immediately gives us dl,dm,dn, since we assume dn~0
    rot_pa = ns.rotpa0 << Meq.Composer(Meq.Sin(pa),Meq.Cos(pa),0);

  # el0: elevation of field centre
  el0 = dir0.el();
  if do_extinction:
    ns.inv_ext0 << Meq.Sin(el0);  # inverse of extinction towards el0
  # station UVWs
  uvw = Context.array.uvw();
  # now loop over sources
  for isrc,src in enumerate(sources):
    # reference direction: no refraction at all
    if src.direction is dir0:
      for p in stations:
        Jones(src,p) << 1;
      continue;
    # dEl is source elevation minus el0
    # ddEl = scale*dEl: amount by which source refracts (negative means field is compressed)
    el = src.direction.el()
    ns.dEl(src) << el - el0;
    ddel = ns.ddEl(src) << ns.dEl(src)*scale;
    # get el1: refracted elevation angle
    if not coord_approx or do_extinction:
      el1 = ns.el1(src) << el + ddel;
    # compute extinction component
    if do_extinction:
      # compute inverse of extinction towards the refracted direction el1
      iext = ns.inv_ext(src) << Meq.Sin(el1);  # 
      # and differential extinction is then ext1/ext0
      ext = ns.dext(src) << ns.inv_ext0/iext;
    # Compute dlmn offset in lm plane.
    if coord_approx:
      # Approximate mode: ddel is added to elevation, so to get the lm offset, we need
      # to apply Rot(PA) to the column vector (0,ddel), and then take the sine of the result.
      dlmn = ns.dlmn(src) << Meq.Sin(ddel*rot_pa);
    else:
      ns.azel1(src) << Meq.Composer(src.direction.az(),el1);
      ns.radec1(src) << Meq.RADec(ns.azel1(src),xyz0);
      ns.lmn1(src) << Meq.LMN(Context.observation.radec0(),ns.radec1(src));
      dlmn = ns.dlmn(src) << ns.lmn1(src) - src.lmn();
    # get per-station phases
    for p in stations:
      if do_extinction:
        Jones(src,p) << ext*(ns.phase(src,p) << Meq.VisPhaseShift(lmn=dlmn,uvw=uvw(p)));
      else:
        Jones(src,p) << Meq.VisPhaseShift(lmn=dlmn,uvw=uvw(p));
  # make bookmarks
  srcnames = [ src.name for src in sources ];
  meqmaker.make_bookmark_set(Jones,[ (src,p) for src in srcnames for p in stations ],
      "%s: inspector plot"%label,"%s: by source-station"%label,freqmean=True);
  inspectors.append(ns.inspector(label,'scale') << \
      StdTrees.define_inspector(ns.scale,[0],label=label));
  inspectors.append(ns.inspector(label,'delta-el') << \
      StdTrees.define_inspector(ns.ddEl,srcnames,label=label));
  inspectors.append(ns.inspector(label,'delta-el') << \
      StdTrees.define_inspector(ns.ddEl,srcnames,label=label));
  inspectors.append(ns.inspector(label,'dlmn') << \
      StdTrees.define_inspector(ns.dlmn,srcnames,label=label));
  if do_extinction:
    inspectors.append(ns.inspector(label,'inv-ext') << \
        StdTrees.define_inspector(ns.inv_ext,srcnames,label=label));
    inspectors.append(ns.inspector(label,'diff-ext') << \
        StdTrees.define_inspector(ns.dext,srcnames,label=label));

  # make parmgroups and solvejobs
  global pg;
  pg  = ParmGroup.ParmGroup(label,[scale],table_name="%s.fmep"%label,bookmark=False);

  # make solvejobs
  ParmGroup.SolveJob("cal_"+label,"Calibrate %s (differential refraction)"%label,pg);

  return Jones;
Esempio n. 13
0
def compute_jones (Jones,sources,stations=None,pointing_offsets=None,inspectors=[],label='E',**kw):
  stations = stations or Context.array.stations;
  ns = Jones.Subscope();
  JE = Jones("elem");

  per_station = sky_rotation or pointing_offsets;

  # read offsets file
  if read_offsets_file:
    offsets = map(float,open(offsets_file).read().split());
    if len(offsets) < (beam_number+1)*2:
      raise ValueError,"beam number %d not found in offsets file"%beam_number;
    l_offset,m_offset = offsets[beam_number*2:(beam_number+1)*2];
    if invert_l:
      l_offset = -l_offset;
  else:
    l_offset,m_offset = 0,0;

  # loop over sources to create per-element beamgains
  for src in sources:
    # If sky rotation and/or pointing offsets are in effect, we have a per-station beam.
    # Otherwise the beam is the same for all stations.
    if per_station:
      for p in stations:
        lm = src.direction.lm();
        # apply rotation to put sources into the antenna frame
        if sky_rotation:
          xyz = Context.array.xyz(p);
          pa_rot = Context.observation.phase_centre.pa_rot(xyz);
          lm = ns.lmrot(src,p) <<  Meq.MatrixMultiply(pa_rot,src.direction.lm());
        # apply offset (so pointing offsets are interpreted in the azel frame, if rotating)
        if pointing_offsets:
          lm = ns.lmoff(src,p) << lm + pointing_offsets(p);
        # now make the beam node
        make_beam_node(JE(src,p),filename_pattern,l_offset,m_offset,lm);
    else:
      make_beam_node(JE(src),filename_pattern,l_offset,m_offset,src.direction.lm());


  # now load weights
  wx = cPickle.load(open(weight_filename_x));
  wy = cPickle.load(open(weight_filename_y));
  if wx.shape[1] != num_elements or wy.shape[1] != num_elements:
    raise ValueError,"""weights files contain weights for %d (X) and %d (Y) complex
                      elements, %d expected"""%(wx.shape[1],wy.shape[1],num_elements);
  if beam_number > wx.shape[0] or beam_number > wy.shape[0]:
    raise ValueError,"beam number %d not found in weights files"%beam_number;

  # w0:x and w0:y are the nominal weight vectors
  ns.w0('x') << Meq.Constant(value=wx[beam_number,:]);
  ns.w0('y') << Meq.Constant(value=wy[beam_number,:]);

  if sim_element_errors:
    # create perturbed weights
    a0 = 10**(min_ampl_var/20)-1;
    a1 = 10**(max_ampl_var/20)-1;
    for p in stations:
      for xy in 'x','y':
        werr = ns.werr(xy,p);
        # amplitude and phase period and offset
        for ap in 'ampl','phase':
          p0 = werr("period",ap) << Meq.Constant(value=[random.uniform(min_period_var*3600,max_period_var*3600)/(2*math.pi) for i in range(num_elements)]);
          if start_phased_up:
            werr("sin",ap) << Meq.Sin(Meq.Time()/p0);
          else:
            t0 = werr("offset",ap) << Meq.Constant(value=[random.uniform(0,2*math.pi) for i in range(num_elements)]);
            werr("sin",ap) << Meq.Sin((Meq.Time()/p0)+t0);
          
        # amplitude excursion
        e0 = werr("maxampl") << Meq.Constant(value=[random.uniform(a0,a1) for i in range(num_elements)]);
        ep = werr("maxphase") << Meq.Constant(value=[random.uniform(min_phase_var*DEG,max_phase_var*DEG) for i in range(num_elements)]);
        # weight errors
        werr << Meq.Polar(1+e0*werr("sin","ampl"),ep*werr("sin","phase"));
        ns.weight(xy,p) << ns.w0(xy)*werr;

  # compute matrix norms based on nominal matrices
  if per_station:
    quallist = [ [src,p] for src in sources for p in stations ];
  else:
    quallist = [ [src] for src in sources ];
  for qq in quallist:
    ex0 = Jones(*(qq+["x0"])) << Meq.MatrixMultiply(JE(*qq),ns.w0("x"));
    ey0 = Jones(*(qq+["y0"])) << Meq.MatrixMultiply(JE(*qq),ns.w0("y"));
    J0 = Jones(*(qq+["nominal"])) << Meq.Composer(ex0,ey0,dims=[2,2]);
    if do_normalize or (qq[0] is sources[0] and do_correct):
      make_norm(J0,Jones(*(qq+["norm"])));

  if do_normalize:
    # norm towards source is average per-station norm
    if per_station:
      for src in sources:
        Jones(src,"norm") << Meq.Add(*[Jones(src,p,"norm") for p in stations])/len(stations);
  elif do_correct:
    if per_station:
      for src in sources:
        Jones(sources[0],"norm") << Meq.Add(*[Jones(sources[0],p,"norm") for p in stations])/len(stations);
    for src in sources[1:]:
      Jones(src,"norm") << Meq.Identity(Jones(sources[0],"norm"));
  else:
    for src in sources:
      Jones(src,"norm") << 1;

  # put these together into Jones matrices
  for src in sources:
    # jesrc/JJ will eventually point to the unqualified element beam node
    # of the unqualified jones node. Depending on whether we're per-station or
    # not, this is qualified with src,p or just src.
    jesrc = JE(src);
    jnorm = Jones(src,"norm");
    JJ = Jones(src);

    if sim_element_errors:
      for p in stations:
        if per_station:
          jesrc = JE(src,p);
          JJ = JJ(p);
        # jesrc returns a (2,N) matrix of element gains towards this source.
        # Multiply this by the weights to get the "x" and "y" beams
        ex = Jones(src,p,"x") << Meq.MatrixMultiply(jesrc,ns.weight("x",p));
        ey = Jones(src,p,"y") << Meq.MatrixMultiply(jesrc,ns.weight("y",p));
        if do_correct:
          J0 = Jones(src,p,"ref") << Meq.Composer(ex,ey,dims=[2,2])/jnorm;
          if src is sources[0]:
            Jones(src,p) << Meq.Constant(value=[1,0,0,1],dims=[2,2]);
            Jones(src,p,"inv") << Meq.MatrixInvert22(J0);
          else:
            Jones(src,p) << Meq.MatrixMultiply(Jones(sources[0],p,"inv"),J0);
        else:
          Jones(src,p) << Meq.Composer(ex,ey,dims=[2,2])/jnorm;
    # no element errors, use nominal beam
    else:
      if per_station:
        for p in stations:
          if do_correct:
            J0 = Jones(src,p,"ref") << Jones(src,p,"nominal")/jnorm;
            if src is sources[0]:
              Jones(src,p) << Meq.Constant(value=[1,0,0,1],dims=[2,2]);
              Jones(src,p,"inv") << Meq.MatrixInvert22(J0);
            else:
              Jones(src,p) << Meq.MatrixMultiply(Jones(sources[0],p,"inv"),J0);
          else:
            Jones(src,p) << Jones(src,p,"nominal")/jnorm;
      else:
        if do_correct:
          J0 = Jones(src,"ref") << Jones(src,"nominal")/jnorm;
          if src is sources[0]:
            Jones(src) << Meq.Constant(value=[1,0,0,1],dims=[2,2]);
            Jones(src,"inv") << Meq.MatrixInvert22(J0);
          else:
            Jones(src) << Meq.MatrixMultiply(Jones(sources[0],"inv"),J0);
        else:
          Jones(src) << Jones(src,"nominal")/jnorm;
        for p in stations:
          Jones(src,p) << Meq.Identity(Jones(src));


  # declare an inspector node for the Jones matrix -- will be defined below
  insp = Jones.scope.inspector(label);

  # define inspectors
  insp << StdTrees.define_inspector(Jones,sources,stations,label=label);
  inspectors += [ insp ];
  if sim_element_errors:
    insp1 = insp("werr") << StdTrees.define_inspector(ns.werr,("x","y"),stations,label="%s weight drifts"%label);
    insp2 = insp("weights") << StdTrees.define_inspector(ns.weight,("x","y"),stations,label="%s weights"%label);

    inspectors += [ insp1,insp2 ];

  return Jones;
def compute_jones(Jones,
                  sources,
                  stations=None,
                  inspectors=[],
                  meqmaker=None,
                  label='R',
                  **kw):
    """Creates the Z Jones for ionospheric phase, given TECs (per source, 
  per station)."""
    stations = stations or Context.array.stations
    ns = Jones.Subscope()

    # get reference source
    if ref_source:
        # treat as index first
        dir0 = None
        try:
            dir0 = sources[int(ref_source)].direction
        except:
            pass
        # else treat as name, find in list
        if not dir0:
            for src0 in sources:
                if src0.name == ref_source:
                    dir0 = src0.direction
                    break
        # else treat as direction string
        if not dir0:
            ff = list(ref_source.split())
            if len(ff) < 2 or len(ff) > 3:
                raise RuntimeError(
                    "invalid reference dir '%s' specified for %s-Jones" %
                    (ref_source, label))
            global dm
            if not dm:
                raise RuntimeError(
                    "pyrap measures module not available, cannot use direction strings for %s-Jones"
                    % label)
            if len(ff) == 2:
                ff = ['J2000'] + ff
            # treat as direction measure
            try:
                dmdir = dm.direction(*ff)
            except:
                raise RuntimeError(
                    "invalid reference dir '%s' specified for %s-Jones" %
                    (ref_source, label))
            # convert to J2000 and make direction object
            dmdir = dm.measure(dmdir, 'J2000')
            ra, dec = dm.getvalue(dmdir)[0].get_value(), dm.getvalue(
                dmdir)[1].get_value()
            dir0 = Meow.Direction(ns, "refdir", ra, dec, static=True)
    else:
        dir0 = Context.observation.phase_centre

    # make refraction scale node
    scale = ns.scale(0) << Meq.Parm(0, tags="refraction")

    xyz0 = Context.array.xyz0()
    if coord_approx:
        # get PA, and assume it's the same over the whole field
        pa = ns.pa0 << Meq.ParAngle(dir0.radec(), xyz0)
        # second column of the Rot(-PA) matrix. Multiply this by del to get a rotation of (0,del) into the lm plane.
        # The third component (0) is for convenience, as it immediately gives us dl,dm,dn, since we assume dn~0
        rot_pa = ns.rotpa0 << Meq.Composer(Meq.Sin(pa), Meq.Cos(pa), 0)

    # el0: elevation of field centre
    el0 = dir0.el()
    if do_extinction:
        ns.inv_ext0 << Meq.Sin(el0)
        # inverse of extinction towards el0
    # station UVWs
    uvw = Context.array.uvw()
    # now loop over sources
    for isrc, src in enumerate(sources):
        # reference direction: no refraction at all
        if src.direction is dir0:
            for p in stations:
                Jones(src, p) << 1
            continue
        # dEl is source elevation minus el0
        # ddEl = scale*dEl: amount by which source refracts (negative means field is compressed)
        el = src.direction.el()
        ns.dEl(src) << el - el0
        ddel = ns.ddEl(src) << ns.dEl(src) * scale
        # get el1: refracted elevation angle
        if not coord_approx or do_extinction:
            el1 = ns.el1(src) << el + ddel
        # compute extinction component
        if do_extinction:
            # compute inverse of extinction towards the refracted direction el1
            iext = ns.inv_ext(src) << Meq.Sin(el1)
            #
            # and differential extinction is then ext1/ext0
            ext = ns.dext(src) << ns.inv_ext0 / iext
        # Compute dlmn offset in lm plane.
        if coord_approx:
            # Approximate mode: ddel is added to elevation, so to get the lm offset, we need
            # to apply Rot(PA) to the column vector (0,ddel), and then take the sine of the result.
            dlmn = ns.dlmn(src) << Meq.Sin(ddel * rot_pa)
        else:
            ns.azel1(src) << Meq.Composer(src.direction.az(), el1)
            ns.radec1(src) << Meq.RADec(ns.azel1(src), xyz0)
            ns.lmn1(src) << Meq.LMN(Context.observation.radec0(),
                                    ns.radec1(src))
            dlmn = ns.dlmn(src) << ns.lmn1(src) - src.lmn()
        # get per-station phases
        for p in stations:
            if do_extinction:
                Jones(src, p) << ext * (ns.phase(src, p) << Meq.VisPhaseShift(
                    lmn=dlmn, uvw=uvw(p)))
            else:
                Jones(src, p) << Meq.VisPhaseShift(lmn=dlmn, uvw=uvw(p))
    # make bookmarks
    srcnames = [src.name for src in sources]
    meqmaker.make_bookmark_set(Jones, [(src, p) for src in srcnames
                                       for p in stations],
                               "%s: inspector plot" % label,
                               "%s: by source-station" % label,
                               freqmean=True)
    inspectors.append(ns.inspector(label,'scale') << \
        StdTrees.define_inspector(ns.scale,[0],label=label))
    inspectors.append(ns.inspector(label,'delta-el') << \
        StdTrees.define_inspector(ns.ddEl,srcnames,label=label))
    inspectors.append(ns.inspector(label,'delta-el') << \
        StdTrees.define_inspector(ns.ddEl,srcnames,label=label))
    inspectors.append(ns.inspector(label,'dlmn') << \
        StdTrees.define_inspector(ns.dlmn,srcnames,label=label))
    if do_extinction:
        inspectors.append(ns.inspector(label,'inv-ext') << \
            StdTrees.define_inspector(ns.inv_ext,srcnames,label=label))
        inspectors.append(ns.inspector(label,'diff-ext') << \
            StdTrees.define_inspector(ns.dext,srcnames,label=label))

    # make parmgroups and solvejobs
    global pg
    pg = ParmGroup.ParmGroup(label, [scale],
                             table_name="%s.fmep" % label,
                             bookmark=False)

    # make solvejobs
    ParmGroup.SolveJob("cal_" + label,
                       "Calibrate %s (differential refraction)" % label, pg)

    return Jones
  def init_parameters (self,ns,sources,stations,inspectors=[]):
    if self.beamshape is not None:
      return;
    # create solvables if enabled
    parms = [];
    parmgroups = [];
    parmdef_scale = Meq.Parm(self.bf*1e-9,tags="beam solvable");
    parmdef_ell = Meq.Parm(self.ellipticity,tags="beam solvable");
    self.per_station = False;

    # solvable beam scale
    if self.solve_scale is PER_STATION:
      self.beamshape = ns.beamshape;
      for p in stations:
        parms.append(beamshape(p) << parmdef_scale);
      inspectors.append(ns.inspector("scale") << 
            StdTrees.define_inspector(ns.beamshape,stations,label=self.label));
      self.per_station = True;
    elif self.solve_scale is PER_ARRAY:
      parms.append(ns.beamshape << parmdef_scale);
      self.beamshape = lambda p:ns.beamshape;
    else:
      ns.beamshape ** (self.bf*1e-9);
      self.beamshape = lambda p:ns.beamshape;
    
    # solvable ellipticities
    if self.solve_ell is PER_STATION:
      self.ell = ns.ell;
      for p in stations:
        ell_xy = ns.ell_xy(p) << parmdef_ell;
        parms.append(ell_xy);
        self.ell(p) << Meq.Composer(ell_xy,-ell_xy);
      inspectors.append(ns.inspector("ellipticity") << 
            StdTrees.define_inspector(ns.ell_xy,stations,label=self.label));
      self.per_station = True;
    elif self.solve_ell is PER_ARRAY:
      ell_xy = ns.ell_xy << parmdef_ell;
      parms.append(ell_xy);
      ns.ell << Meq.Composer(ell_xy,-ell_xy);
      self.ell = lambda p:ns.ell;
    elif self.ellipticity != 0:
      ns.ell ** Meq.Constant([self.ellipticity,-self.ellipticity]);
      self.ell = lambda p:ns.ell;
    else:
      self.ell = lambda p:None;
      
    # make parm group, if any solvables have been created
    if parms:
      parmgroups.append(ParmGroup.Subgroup("beam shape",list(parms)));
      
    # solvable pointings
    if self.solve_pointings:
      self.dlm = ns.dlm;
      parmdef_0 = Meq.Parm(0,tags="beam solvable");
      pparms = [];
      for p in stations:
        dl = ns.dl(p) << parmdef_0;
        dm = ns.dm(p) << parmdef_0;
        ns.dlm(p) << Meq.Composer(dl,dm);
        pparms += [dl,dm];
      parmgroups.append(ParmGroup.Subgroup("pointing offsets",pparms));
      parms += pparms;
      inspectors.append(ns.inspector('dlm') << 
              StdTrees.define_inspector(ns.dlm,stations,label=self.label));
      self.per_station = True;
    else:
      ns.dlm_null ** Meq.Constant([0,0]);
      self.dlm = lambda p:ns.dlm_null;

    # add solve jobs
    self.solvable = bool(parms);
    if self.solvable:
      self.pg_beam = ParmGroup.ParmGroup(self.label,parms,subgroups=parmgroups,table_name="%s.fmep"%self.label,bookmark=True);
      ParmGroup.SolveJob("cal_"+self.label,"Calibrate beam parameters",self.pg_beam);