Example #1
0
 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
Example #2
0
 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"])
Example #3
0
    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