def compute_jones (self,nodes,sources,stations=None,tags=None,label='',**kw): stations = stations or Context.array.stations(); # set up qualifier labels depending on polarization definition if Context.observation.circular(): x,y,X,Y = 'r','l','R','L'; else: x,y,X,Y = 'x','y','X','Y'; xx,xy,yx,yy = x+x,x+y,y+x,y+y; axx,axy,ayx,ayy = [ q+":a" for q in xx,xy,yx,yy ]; pxx,pxy,pyx,pyy = [ q+":p" for q in xx,xy,yx,yy ]; ampl_def = phase_def = None; parms_phase = []; parms_ampl = []; subgroups_phase = []; subgroups_ampl = []; for src in sources: sg = src.name if self.independent_solve else ''; # (re)create parm definitions. if ampl_def is None or self.independent_solve: ampl_def = Meq.Parm(self.init_ampl,tags=tags+"solvable diag ampl",solve_group=sg); phase_def = Meq.Parm(self.init_phase,tags=tags+"solvable diag phase",solve_group=sg); sga = []; sgp = []; # now loop to create nodes for p in stations: jj = nodes(src,p); jj << Meq.Matrix22( Meq.Polar(jj(axx) << ampl_def,jj(pxx) << phase_def),0,0, Meq.Polar(jj(ayy) << ampl_def,jj(pyy) << phase_def)); sga += [jj(axx),jj(ayy)]; sgp += [jj(pxx),jj(pyy)]; parms_ampl += [jj(axx),jj(ayy)]; parms_phase += [jj(pxx),jj(pyy)]; # add subgroups for this source subgroups_ampl.append(ParmGroup.Subgroup(src.name,sga)); subgroups_phase.append(ParmGroup.Subgroup(src.name,sgp)); # make parmgroups for phases and gains self.pg_phase = ParmGroup.ParmGroup(label+"_phase", parms_phase, subgroups = subgroups_phase, table_name="%s_phase.fmep"%label,bookmark=4); self.pg_ampl = ParmGroup.ParmGroup(label+"_ampl", parms_ampl, subgroups = subgroups_ampl, table_name="%s_ampl.fmep"%label,bookmark=4); ParmGroup.SolveJob("cal_"+label+"_phase","Calibrate %s phases"%label,self.pg_phase); ParmGroup.SolveJob("cal_"+label+"_ampl","Calibrate %s amplitudes"%label,self.pg_ampl); return nodes;
def compute_jones(self, jones, sources, stations=None, tags=None, label='', **kw): stations = stations or Context.array.stations() is_complex = self.matrix_type != "real" # set up qualifier labels depending on polarization definition if Context.observation.circular(): x, y, X, Y = 'r', 'l', 'R', 'L' else: x, y, X, Y = 'x', 'y', 'X', 'Y' xx, xy, yx, yy = x + x, x + y, y + x, y + y rxx, rxy, ryx, ryy = [q + ":r" for q in (xx, xy, yx, yy)] ixx, ixy, iyx, iyy = [q + ":i" for q in (xx, xy, yx, yy)] # prepare parm definitions for real and imag parts of diagonal and off-diagonal elements tags = NodeTags(tags) + "solvable" diag_pdefs = offdiag_pdefs = None # loop over sources parms_diag = [] parms_offdiag = [] subgroups_diag = [] subgroups_offdiag = [] # Define a function to put together a matrix element, depending on whether we're in real or complex mode. # This is also responsible for appending parms to the appropriate parm and subgroup lists. # Note that for the purely-real case we still create parms called 'J:xx:r' (and not 'J:xx' directly), # this is to keep MEP tables mutually-compatible naming wise. if self.matrix_type == "real": def make_element(jj, parmdef, *parmlists): parm = jj('r') << parmdef[0] for plist in parmlists: plist.append(parm) return jj << Meq.Identity(parm) else: def make_element(jj, parmdef, *parmlists): parms = [jj('r') << parmdef[0], jj('i') << parmdef[1]] for plist in parmlists: plist += parms return jj << Meq.ToComplex(*parms) for src in sources: sg = src.name if self.independent_solve else '' # (re)create parm definitions. if diag_pdefs is None or self.independent_solve: diag_pdefs = (Meq.Parm(complex(self.init_diag).real, tags=tags + "diag real", solve_group=sg), Meq.Parm(complex(self.init_diag).imag, tags=tags + "diag imag", solve_group=sg)) offdiag_pdfefs = (Meq.Parm(complex(self.init_offdiag).imag, tags=tags + "offdiag real", solve_group=sg), Meq.Parm(complex(self.init_offdiag).imag, tags=tags + "offdiag imag", solve_group=sg)) # now loop to create nodes sgdiag = [] sgoff = [] for p in stations: jj = jones(src, p) jj << Meq.Matrix22( make_element(jj(xx), diag_pdefs, parms_diag, sgdiag), make_element(jj(xy), offdiag_pdefs, parms_offdiag, sgoff) if self._offdiag else 0, make_element(jj(yx), offdiag_pdefs, parms_offdiag, sgoff) if self._offdiag else 0, make_element(jj(yy), diag_pdefs, parms_diag, sgdiag)) # add subgroup for this source subgroups_diag.append(ParmGroup.Subgroup(src.name, sgdiag)) subgroups_offdiag.append(ParmGroup.Subgroup(src.name, sgoff)) # re-sort by name from past.builtins import cmp from functools import cmp_to_key subgroups_diag.sort(key=cmp_to_key(lambda a, b: cmp(a.name, b.name))) subgroups_offdiag.sort( key=cmp_to_key(lambda a, b: cmp(a.name, b.name))) # make parmgroups for diagonal and off-diagonal terms self.pg_diag = ParmGroup.ParmGroup(label + "_diag", parms_diag, subgroups=subgroups_diag, table_name="%s_diag.fmep" % label, bookmark=False) if self._offdiag: self.pg_offdiag = ParmGroup.ParmGroup( label + "_offdiag", parms_offdiag, subgroups=subgroups_offdiag, table_name="%s_offdiag.fmep" % label, bookmark=False) # make bookmarks Bookmarks.make_node_folder("%s diagonal terms" % label, [ jones(src, p, zz) for src in sources for p in stations for zz in ["xx", "yy"] ], sorted=True) if self._offdiag: Bookmarks.make_node_folder("%s off-diagonal terms" % label, [ jones(src, p, zz) for src in sources for p in stations for zz in ["xy", "yx"] ], sorted=True) # make solvejobs ParmGroup.SolveJob("cal_" + label + "_diag", "Calibrate %s diagonal terms" % label, self.pg_diag) if self._offdiag: ParmGroup.SolveJob("cal_" + label + "_offdiag", "Calibrate %s off-diagonal terms" % label, self.pg_offdiag) 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);