def determine_diagonality(cls, options): """Returns true if the machine class, given the options, represents a diagonal gain""" from cubical.main import UserInputError diagonal = True for term_opts in options['chain']: jones_class = machine_types.get_machine_class(term_opts['type']) if jones_class is None: raise UserInputError("unknown Jones class '{}'".format( term_opts['type'])) diagonal = diagonal and jones_class.determine_diagonality( term_opts) return diagonal
def init_solutions(self): from cubical.main import UserInputError for opts in self.chain_options: label = opts["label"] jones_class = machine_types.get_machine_class(opts['type']) if jones_class is None: raise UserInputError("unknown Jones class '{}'".format( opts['type'])) if not issubclass(jones_class, Complex2x2Gains) and not issubclass(jones_class, ComplexW2x2Gains) and \ opts['solvable']: raise UserInputError( "only complex-2x2 or robust-2x2 terms can be made solvable in a Jones chain" ) self._init_solutions( label, self.make_filename(opts["xfer-from"], label) or self.make_filename(opts["load-from"], label), bool(opts["xfer-from"]), self.solvable and opts["solvable"] and self.make_filename(opts["save-to"], label), jones_class.exportable_solutions(), dd_term=opts["dd-term"])
def __init__(self, label, data_arr, ndir, nmod, times, frequencies, chunk_label, jones_options): """ Initialises a chain of complex 2x2 gain machines. Args: label (str): Label identifying the Jones term. data_arr (np.ndarray): Shape (n_mod, n_tim, n_fre, n_ant, n_ant, n_cor, n_cor) array containing observed visibilities. ndir (int): Number of directions. nmod (nmod): Number of models. times (np.ndarray): Times for the data being processed. frequencies (np.ndarray): Frequencies for the data being processsed. jones_options (dict): Dictionary of options pertaining to the chain. """ from cubical.main import UserInputError # This instantiates the number of complex 2x2 elements in our chain. Each element is a # gain machine in its own right - the purpose of this machine is to manage these machines # and do the relevant fiddling between parameter updates. When combining DD terms with # DI terms, we need to be initialise the DI terms using only one direction - we do this with # slicing rather than summation as it is slightly faster. self.jones_terms = [] self.num_left_di_terms = 0 # how many DI terms are there at the left of the chain seen_dd_term = False for iterm, term_opts in enumerate(jones_options['chain']): jones_class = machine_types.get_machine_class(term_opts['type']) if jones_class is None: raise UserInputError("unknown Jones class '{}'".format( term_opts['type'])) if not issubclass(jones_class, Complex2x2Gains) and not issubclass( jones_class, ComplexW2x2Gains) and term_opts['solvable']: raise UserInputError( "only complex-2x2 or robust-2x2 terms can be made solvable in a Jones chain" ) term = jones_class(term_opts["label"], data_arr, ndir, nmod, times, frequencies, chunk_label, term_opts) self.jones_terms.append(term) if term.dd_term: seen_dd_term = True elif not seen_dd_term: self.num_left_di_terms = iterm MasterMachine.__init__(self, label, data_arr, ndir, nmod, times, frequencies, chunk_label, jones_options) self.chain = cubical.kernels.import_kernel("chain") # kernel used for compute_residuals and such self.kernel = Complex2x2Gains.get_full_kernel( jones_options, diag_gains=self.is_diagonal) self.n_dir, self.n_mod = ndir, nmod _, self.n_tim, self.n_fre, self.n_ant, self.n_ant, self.n_cor, self.n_cor = data_arr.shape self.n_terms = len(self.jones_terms) # make list of number of iterations per solvable term # If not specified, just use the maxiter setting of each term # note that this list is updated as we converge, so make a copy term_iters = jones_options['sol']['term-iters'] if not term_iters: self.term_iters = [ term.maxiter for term in self.jones_terms if term.solvable ] elif type(term_iters) is int: self.term_iters = [term_iters] elif isinstance(term_iters, (list, tuple)): self.term_iters = list(term_iters) else: raise UserInputError( "invalid term-iters={} setting".format(term_iters)) self.solvable = bool(self.term_iters) and any( [term.solvable for term in self.jones_terms]) # setup first solvable term in chain self.active_index = None # this list accumulates the per-term convergence status strings self._convergence_states = [] # True when the last active term has had its convergence status queried self._convergence_states_finalized = False self.cached_model_arr = self._r = self._m = None