예제 #1
0
 def interpolate_per_source (self,lm_list,dl,dm,grid,vbs,thetaphi=False,rotate=None,masklist=None):
   # Loops over all source coordinates in the lm tensor, interpolates beams for them, and returns the resulting vellsets.
   # lm is a list of [[l0,m0],[l1,m1],...] source coordinates
   # This is the "fail-safe" method, as it interpolates per-source, and therefore allows for the source lm arrays to have different
   # time/frequency dependencies per source.
   vellsets = [];
   for isrc,(l,m) in enumerate(lm_list):
     # apply pointing offsets, if any
     if dl is not None:
       # unite shapes just in case, since l/m and dl/dm may have time/freq axes
       l,dl,m,dm = unite_multiple_shapes(l,dl,m,dm);
     # if mask is set, make sure it has the same shape
     mask = masklist[isrc] if masklist is not None else None;
     if mask is not None:
       l,m,mask = unite_multiple_shapes(l,m,mask);
     grid['l'],grid['m'] = l,m;
     # loop over all 2x2 matrices (we may have several, they all need to be added)
     E = [None]*4;
     for vbmat in vbs:
       for i,vb in enumerate(vbmat):
         beam = vb.interpolate(freqaxis=self._freqaxis,lm=self.interpol_lm,thetaphi=thetaphi,rotate=rotate,mask=mask,**grid);
         if E[i] is None:
           E[i] = meq.complex_vells(beam.shape);
         E[i][...] += beam[...];
     # make vellsets
     for ej in E:
       vellsets.append(meq.vellset(ej));
   return vellsets;
예제 #2
0
 def interpolate_per_source(self,
                            lm_list,
                            dl,
                            dm,
                            grid,
                            vbs,
                            thetaphi=False,
                            rotate=None,
                            masklist=None):
     # Loops over all source coordinates in the lm tensor, interpolates beams for them, and returns the resulting vellsets.
     # lm is a list of [[l0,m0],[l1,m1],...] source coordinates
     # This is the "fail-safe" method, as it interpolates per-source, and therefore allows for the source lm arrays to have different
     # time/frequency dependencies per source.
     vellsets = []
     for isrc, (l, m) in enumerate(lm_list):
         # apply pointing offsets, if any
         if dl is not None:
             # unite shapes just in case, since l/m and dl/dm may have time/freq axes
             l, dl, m, dm = unite_multiple_shapes(l, dl, m, dm)
         # if mask is set, make sure it has the same shape
         mask = masklist[isrc] if masklist is not None else None
         if mask is not None:
             l, m, mask = unite_multiple_shapes(l, m, mask)
         grid['l'], grid['m'] = l, m
         # loop over all 2x2 matrices (we may have several, they all need to be added)
         E = [None] * 4
         for vbmat in vbs:
             for i, vb in enumerate(vbmat):
                 beam = vb.interpolate(freqaxis=self._freqaxis,
                                       lm=self.interpol_lm,
                                       thetaphi=thetaphi,
                                       rotate=rotate,
                                       mask=mask,
                                       **grid)
                 if E[i] is None:
                     E[i] = meq.complex_vells(beam.shape)
                 E[i][...] += beam[...]
         # make vellsets
         for ej in E:
             vellsets.append(meq.vellset(ej))
     return vellsets
예제 #3
0
 def get_result(self, request, radec, radec0, dlm=None, azel=None, pa=None):
     # get list of VoltageBeams
     vbs = self.init_voltage_beams()
     # now, figure out the radec and time/freq grid
     # radec may be a 2/3-vector or an Nx2/3 tensor
     dims = getattr(radec, 'dims', [len(radec.vellsets)])
     if len(dims) == 2 and dims[1] == 2:
         radec_list = [(radec.vellsets[i].value,
                        radec.vellsets[i + 1].value)
                       for i in range(0, len(radec.vellsets), dims[1])]
         tensor = True
     elif len(dims) == 1 and dims[0] == 2:
         radec_list = [(radec.vellsets[0].value, radec.vellsets[1].value)]
         tensor = False
     else:
         raise TypeError, "expecting a 2-vector or an Nx2 matrix for child 0 (radec)"
     nsrc = len(radec_list)
     # radec0 is a 2-vector
     if len(radec0.vellsets) != 2:
         raise TypeError, "expecting a 2-vector for child 1 (radec0)"
     ra0, dec0 = radec0.vellsets[0].value, radec0.vellsets[1].value
     # get offsets and rotations
     masklist = rotate = None
     # pointing offsets are optional -- apply them in here
     if dlm is not None and len(dlm.vellsets) == 2:
         dl, dm = dlm.vellsets[0].value, dlm.vellsets[1].value
         ra0, dl, dec0, dm = unite_multiple_shapes(ra0, dl, dec0, dm)
         ra0, dec0 = self.lm_to_radec(dl, dm, ra0, dec0)
     # az/el is optional. If specified, then horizon masking is enabled
     if azel is not None and len(azel.vellsets) > 1:
         if len(azel.vellsets) != nsrc * 2:
             raise TypeError, "expecting a Nx2 matrix for child 3 (azel)"
         masklist = [
             azel.vellsets[i].value < 0 for i in range(1, nsrc * 2, 2)
         ]
     # PA is optional. If specified, then this is the rotation angle for interpolation
     if pa is not None:
         if len(pa.vellsets) != 1:
             raise TypeError, "expecting a single value for child 4 (pa)"
         rotate = pa.vellsets[0].value
     thetaphi_list = []
     # precompute these -- may be functions of time if time-variable pointing is in effect
     sind0, cosd0 = numpy.sin(dec0), numpy.cos(dec0)
     # now go over all coordinates
     for ra, dec in radec_list:
         # This is based on the formula in Tigger/Coordinates.py, except we flip the sign of phi (by swapping ra0 and ra around),
         # since rotation is meant to go N through W here
         dra = numpy.subtract(*unite_shapes(ra, ra0))
         cosra, sinra = numpy.cos(dra), numpy.sin(dra)
         sind0x, sind, cosd0x, cosd, cosra, sinra = unite_multiple_shapes(
             sind0, numpy.sin(dec), cosd0, numpy.cos(dec), cosra, sinra)
         theta = numpy.arccos(sind0x * sind + cosd0x * cosd * cosra)
         phi = numpy.arctan2(-cosd * sinra,
                             -cosd * sind0x * cosra + sind * cosd0x)
         thetaphi_list.append((theta, phi))
     dprint(2, "theta/phi", thetaphi_list)
     # setup grid dict that will be passed to VoltageBeam.interpolate
     grid = dict()
     for axis in 'time', 'freq':
         values = _cells_grid(radec, axis)
         if values is None:
             values = _cells_grid(request, axis)
         if values is not None:
             if numpy.isscalar(values) or values.ndim == 0:
                 values = [float(values)]
             grid[axis] = values
     # accumulate per-source EJones tensor
     vellsets = self.interpolate_batch(thetaphi_list,
                                       None,
                                       None,
                                       grid,
                                       vbs,
                                       thetaphi=True,
                                       rotate=rotate,
                                       masklist=masklist)
     # create result object
     cells = request.cells
     result = meq.result(vellsets[0], cells=cells)
     result.vellsets[1:] = vellsets[1:]
     result.dims = (len(radec_list), 2, 2) if tensor else (2, 2)
     return result
예제 #4
0
    def interpolate_batch(self,
                          lm_list,
                          dl,
                          dm,
                          grid,
                          vbs,
                          thetaphi=False,
                          rotate=None,
                          masklist=None):
        # A faster version of interpolate_per_source(), which assumes that all lm's (as well as the masks, if given)
        # have the same shape, and stacks them into a single array for a single interpolation call.
        # If there's a shape mismatch, it'll fall back to interpolate_per_source
        # 'maskarr', if given, should be an list of per-source mask arrays
        nsrc = len(lm_list)
        maskcube = None
        for isrc, (l, m) in enumerate(lm_list):
            mask = masklist[isrc] if masklist is not None else None
            # apply pointing offsets, if any
            if dl is not None:
                # unite shapes just in case, since l/m and dl/dm may have time/freq axes
                l, dl, m, dm = unite_multiple_shapes(l, dl, m, dm)
                l, m = l - dl, m - dm
            # unite l,m shapes just in case, and transform
            l, m, mask = unite_multiple_shapes(l, m, mask)
            if not isrc:
                lm_shape = l.shape
                cubeshape = [nsrc] + list(lm_shape)
                lcube = numpy.zeros(cubeshape, float)
                mcube = numpy.zeros(cubeshape, float)
                if masklist is not None:
                    maskcube = numpy.zeros(cubeshape, bool)
            else:
                if l.shape != lm_shape:
                    dprint(
                        1,
                        "l/m shapes unequal at source %d, falling back to per-source interpolation"
                        % isrc)
                    return self.interpolate_per_source(lm_list,
                                                       dl,
                                                       dm,
                                                       grid,
                                                       vbs,
                                                       thetaphi=thetaphi,
                                                       rotate=rotate,
                                                       masklist=masklist)
            lcube[isrc, ...] = l
            mcube[isrc, ...] = m
            if mask is not None:
                maskcube[isrc, ...] = mask


#        if mask.any():
#          dprint(2,"source %d has %d slots masked"%(isrc,mask.sum()));
# if 'rotate' is specified, it needs to be promoted to the same cube shape, and ravelled
        if rotate is not None:
            lcube, mcube, maskcube, rotate = unite_multiple_shapes(
                lcube, mcube, maskcube,
                rotate.reshape([1] + list(rotate.shape)))
            cubeshape = list(lcube.shape)
            rotate = rotate.ravel()
        # ok, we've stacked things into lm cubes, interpolate
        grid['l'], grid['m'] = lcube.ravel(), mcube.ravel()
        # loop over all 2x2 matrices (we may have several, they all need to be added)
        E = [None] * 4
        for vbmat in vbs:
            for i, vb in enumerate(vbmat):
                beam = vb.interpolate(freqaxis=self._freqaxis,
                                      extra_axes=1,
                                      thetaphi=thetaphi,
                                      rotate=rotate,
                                      **grid)
                if E[i] is None:
                    E[i] = beam
                else:
                    E[i] += beam
        # The l/m cubes have a shape of [nsrcs,lm_shape].
        # These are raveled for interpolation, so the resulting Es have a shape of [nsrcs*num_lm_points,num_freq]
        # Reshape them properly. Note that there's an extra "source" axis at the front, so the frequency axis
        # is off by 1.
        if len(cubeshape) <= self._freqaxis + 1:
            cubeshape = list(cubeshape) + [1] * (self._freqaxis -
                                                 len(cubeshape) + 2)
        cubeshape[self._freqaxis + 1] = len(grid['freq'])
        E = [ej.reshape(cubeshape) for ej in E]
        # apply mask cube, if we had one
        if maskcube is not None:
            # the E planes now have the same shape as the maskcube, but with an extra frequency axis. Promote the maskcube
            # accordingly
            me = unite_multiple_shapes(maskcube, *E)
            maskcube = me[0]
            E = me[1:]
            dprint(2, "maskcube sum", maskcube.sum())
            for ej in E:
                ej[maskcube] = 0
        # now tease the E's apart plane by plane
        # make vellsets
        vellsets = []
        for isrc in range(nsrc):
            for ej in E:
                dprint(
                    2, "source %d has %d null gains" %
                    (isrc, (ej[isrc, ...] == 0).sum()))
                ejplane = ej[isrc, ...]
                value = meq.complex_vells(ejplane.shape, ejplane)
                vellsets.append(meq.vellset(value))
        return vellsets
예제 #5
0
 def get_result (self,request,radec,radec0,dlm=None,azel=None,pa=None):
   # get list of VoltageBeams
   vbs = self.init_voltage_beams();
   # now, figure out the radec and time/freq grid
   # radec may be a 2/3-vector or an Nx2/3 tensor
   dims = getattr(radec,'dims',[len(radec.vellsets)]);
   if len(dims) == 2 and dims[1] == 2:
     radec_list = [ (radec.vellsets[i].value,radec.vellsets[i+1].value) for i in range(0,len(radec.vellsets),dims[1]) ];
     tensor = True;
   elif len(dims) == 1 and dims[0] == 2:
     radec_list = [ (radec.vellsets[0].value,radec.vellsets[1].value) ];
     tensor = False;
   else:
     raise TypeError,"expecting a 2-vector or an Nx2 matrix for child 0 (radec)";
   nsrc = len(radec_list);
   # radec0 is a 2-vector
   if len(radec0.vellsets) != 2:
     raise TypeError,"expecting a 2-vector for child 1 (radec0)";
   ra0,dec0 = radec0.vellsets[0].value,radec0.vellsets[1].value;
   # get offsets and rotations
   masklist = rotate = None;
   # pointing offsets are optional -- apply them in here
   if dlm is not None and len(dlm.vellsets) == 2:
     dl,dm = dlm.vellsets[0].value,dlm.vellsets[1].value;
     ra0,dl,dec0,dm = unite_multiple_shapes(ra0,dl,dec0,dm);
     ra0,dec0 = self.lm_to_radec(dl,dm,ra0,dec0); 
   # az/el is optional. If specified, then horizon masking is enabled
   if azel is not None and len(azel.vellsets) > 1:
     if len(azel.vellsets) != nsrc*2:
       raise TypeError,"expecting a Nx2 matrix for child 3 (azel)";
     masklist = [ azel.vellsets[i].value<0 for i in range(1,nsrc*2,2) ];
   # PA is optional. If specified, then this is the rotation angle for interpolation
   if pa is not None:
     if len(pa.vellsets) != 1:
       raise TypeError,"expecting a single value for child 4 (pa)";
     rotate = pa.vellsets[0].value;
   thetaphi_list = [];
   # precompute these -- may be functions of time if time-variable pointing is in effect
   sind0,cosd0 = numpy.sin(dec0),numpy.cos(dec0);
   # now go over all coordinates
   for ra,dec in radec_list:
     # This is based on the formula in Tigger/Coordinates.py, except we flip the sign of phi (by swapping ra0 and ra around),
     # since rotation is meant to go N through W here
     dra = numpy.subtract(*unite_shapes(ra,ra0));
     cosra,sinra = numpy.cos(dra),numpy.sin(dra);
     sind0x,sind,cosd0x,cosd,cosra,sinra = unite_multiple_shapes(sind0,numpy.sin(dec),cosd0,numpy.cos(dec),cosra,sinra);
     theta = numpy.arccos(sind0x*sind + cosd0x*cosd*cosra);
     phi = numpy.arctan2(-cosd*sinra,-cosd*sind0x*cosra+sind*cosd0x);
     thetaphi_list.append((theta,phi));
   dprint(2,"theta/phi",thetaphi_list);
   # setup grid dict that will be passed to VoltageBeam.interpolate
   grid = dict();
   for axis in 'time','freq':
     values = _cells_grid(radec,axis);
     if values is None:
       values = _cells_grid(request,axis);
     if values is not None:
       if numpy.isscalar(values) or values.ndim == 0:
         values = [float(values)];
       grid[axis] = values;
   # accumulate per-source EJones tensor
   vellsets = self.interpolate_batch(thetaphi_list,None,None,grid,vbs,thetaphi=True,rotate=rotate,masklist=masklist);
   # create result object
   cells = request.cells;
   result = meq.result(vellsets[0],cells=cells);
   result.vellsets[1:] = vellsets[1:];
   result.dims = (len(radec_list),2,2) if tensor else (2,2);
   return result;
예제 #6
0
  def interpolate_batch (self,lm_list,dl,dm,grid,vbs,thetaphi=False,rotate=None,masklist=None):
    # A faster version of interpolate_per_source(), which assumes that all lm's (as well as the masks, if given) 
    # have the same shape, and stacks them into a single array for a single interpolation call.
    # If there's a shape mismatch, it'll fall back to interpolate_per_source
    # 'maskarr', if given, should be an list of per-source mask arrays 
    nsrc = len(lm_list);
    maskcube = None;
    for isrc,(l,m) in enumerate(lm_list):
      mask = masklist[isrc] if masklist is not None else None;
      # apply pointing offsets, if any
      if dl is not None:
        # unite shapes just in case, since l/m and dl/dm may have time/freq axes
        l,dl,m,dm = unite_multiple_shapes(l,dl,m,dm);
        l,m = l-dl,m-dm;
      # unite l,m shapes just in case, and transform
      l,m,mask = unite_multiple_shapes(l,m,mask);
      if not isrc:
        lm_shape = l.shape;
        cubeshape = [nsrc]+list(lm_shape);
        lcube = numpy.zeros(cubeshape,float);
        mcube = numpy.zeros(cubeshape,float);
        if masklist is not None:
          maskcube = numpy.zeros(cubeshape,bool);
      else:
        if l.shape != lm_shape:
          dprint(1,"l/m shapes unequal at source %d, falling back to per-source interpolation"%isrc);
          return self.interpolate_per_source(lm_list,dl,dm,grid,vbs,thetaphi=thetaphi,rotate=rotate,masklist=masklist);
      lcube[isrc,...] = l;
      mcube[isrc,...] = m;
      if mask is not None:
        maskcube[isrc,...] = mask;
#        if mask.any():
#          dprint(2,"source %d has %d slots masked"%(isrc,mask.sum()));
    # if 'rotate' is specified, it needs to be promoted to the same cube shape, and ravelled
    if rotate is not None:
      lcube,mcube,maskcube,rotate = unite_multiple_shapes(lcube,mcube,maskcube,rotate.reshape([1]+list(rotate.shape)));
      cubeshape = list(lcube.shape);
      rotate = rotate.ravel();
    # ok, we've stacked things into lm cubes, interpolate
    grid['l'],grid['m'] = lcube.ravel(),mcube.ravel();
    # loop over all 2x2 matrices (we may have several, they all need to be added)
    E = [None]*4;
    for vbmat in vbs:
      for i,vb in enumerate(vbmat):
        beam = vb.interpolate(freqaxis=self._freqaxis,extra_axes=1,thetaphi=thetaphi,rotate=rotate,**grid);
        if E[i] is None:
          E[i] = beam;
        else:
          E[i] += beam;
    # The l/m cubes have a shape of [nsrcs,lm_shape].
    # These are raveled for interpolation, so the resulting Es have a shape of [nsrcs*num_lm_points,num_freq]
    # Reshape them properly. Note that there's an extra "source" axis at the front, so the frequency axis
    # is off by 1.
    if len(cubeshape) <= self._freqaxis+1:
      cubeshape = list(cubeshape) + [1]*(self._freqaxis - len(cubeshape) + 2);
    cubeshape[self._freqaxis+1] = len(grid['freq']);
    E = [ ej.reshape(cubeshape) for ej in E ];
    # apply mask cube, if we had one
    if maskcube is not None:
      # the E planes now have the same shape as the maskcube, but with an extra frequency axis. Promote the maskcube
      # accordingly
      me = unite_multiple_shapes(maskcube,*E);
      maskcube = me[0];
      E = me[1:];
      dprint(2,"maskcube sum",maskcube.sum());
      for ej in E:
        ej[maskcube] = 0;
    # now tease the E's apart plane by plane
    # make vellsets
    vellsets = [];
    for isrc in range(nsrc):
      for ej in E:
        dprint(2,"source %d has %d null gains"%(isrc,(ej[isrc,...]==0).sum()));
        ejplane = ej[isrc,...];
        value = meq.complex_vells(ejplane.shape,ejplane);
        vellsets.append(meq.vellset(value));
    return vellsets;