# Path: cubical/tools/logger.py
# def logToFile(filename, append=False):
# def getLogFilename():
#     def __init__(self, logger, level, color=None, bold=None):
#     def write(self, message, level_override=None, print_once=None):
#     def print(self, *args):
#     def __init__(self, logger, verbose=None, log_verbose=None):
#     def verbosity(self, set_verb=None):
#     def log_verbosity(self, set_verb=None):
#     def __call__(self, level, color=None):
#     def warn(self, msg, color=None, print_once=None):
#     def error(self, msg, color="red", print_once=None):
#     def info(self, msg, color=None, print_once=None):
#     def critical(self, msg, color=None, print_once=None):
#     def debug(self, msg, color=None, print_once=None):
#     def exception(self, msg, color=None, print_once=None):
#     def print(self, *args):
#     def write(self, message, level=logging.INFO, verbosity=0, print_once=None, color=None):
# def enableMemoryLogging(level=1):
# def set_subprocess_label(label):
# def get_subprocess_label():
# def _sigusr1_handler(signum, frame):
# def _sigusr2_handler(signum, frame):
#     def setMemoryLogging(level):
#     def filter(self, event):
#     def __init__(self, fmt, datefmt, strip=True):
#     def label(self, record):
#     def format(self, record):
# def init(app_name):
# def getLogger(name, verbose=None, log_verbose=None):
# def setBoring(boring=True):
# def setGlobalVerbosity(verbosity):
# def setGlobalLogVerbosity(verbosity):
# def setSilent(Lname):
# def setLoud(Lname):
# class _DefaultWriter(object):
# class LoggerWrapper(object):
# class LogFilter(logging.Filter):
# class ColorStrippingFormatter(logging.Formatter):
# GB = float(1024 ** 3)
#                 KEYS = _log_memory_types[memlevel]
# 
# Path: cubical/solver.py
# GD = None 
# SOLVERS = { 'so': SolveOnly,
#             'sc': SolveAndCorrect,
#             'sr': SolveAndCorrectResiduals,
#             'ss': SolveAndSubtract,
#             'ac': CorrectOnly,
#             'ar': CorrectResiduals,
#             'as': SubtractOnly
#             }
#     def profile(func): return func
# def _solve_gains(gm, stats, madmax, obser_arr, model_arr, flags_arr, sol_opts, label="", compute_residuals=None):
#     def get_flagging_stats():
#     def update_stats(flags, statfields):
#     def compute_chisq(statfield=None, full=True):
#     def __init__(self, obser_arr, model_arr, flags_arr, weight_arr, freq_slice):
#     def weighted_obser(self):
#     def weighted_model(self):
#     def corrupt_weighted_model(self):
#     def corrupt_residual(self, imod=0, idir=slice(None)):
#     def corrupt_model(self, imod=0, idir=slice(None)):
#     def __get__(self, cls, owner):
#     def __init__(self, vdm, gm, soldict, sol_opts, label, metadata):
#     def is_model_required(cls):
#     def outputs_full_corrected_residuals(cls):
#     def run(self):
#     def finalize(self, corr_vis):
#     def run(self):
#     def run(self):
#     def run(self, correct=False):
#     def outputs_full_corrected_residuals(self):
#     def is_model_required(cls):
#     def run(self):
#     def run(self):
#     def outputs_full_corrected_residuals(self):
# def run_solver(solver_type, itile, chunk_key, sol_opts, debug_opts):
# class _VisDataManager(object):
# class classproperty(property):
# class SolverMachine(object):
# class SolveOnly(SolverMachine):
# class SolveAndCorrect(SolveOnly):
# class SolveAndSubtract(SolveOnly):
# class SolveAndCorrectResiduals(SolveAndSubtract):
# class CorrectOnly(SolverMachine):
# class SubtractOnly(SolverMachine):
# class CorrectResiduals(SubtractOnly):


from builtins import range
from cubical.tools import logger
from cubical import solver
import multiprocessing, os, sys, traceback
import concurrent.futures as cf
import re
import numba
import cubical.kernels
            import cubical.kernels
        # (Montblanc is finicky about affinities apparently, so we don't do it before)
        _init_worker(main=True)

        for itile, tile in enumerate(tile_list):
            # wait for I/O job on current tile to finish
            print("waiting for I/O on {}".format(tile.label), file=log(0))
            # have a timeout so that if a child process dies, we at least find out
            done = False
            while not done:
                reap_children()
                done, not_done = cf.wait([io_futures[itile]], timeout=10)

            # check if result was successful
            if not io_futures[itile].result():
                raise RuntimeError("I/O job on {} failed".format(tile.label))
            del io_futures[itile]

            # immediately schedule I/O job to save previous/load next tile
            load_next = itile + 1 if itile < len(tile_list) - 1 else None
            save_prev = itile - 1 if itile else None
            if load_next is not None or save_prev is not None:
                io_futures[itile + 1] = io_executor.submit(_io_handler, load=load_next,
                                                           save=save_prev, load_model=load_model)

            # submit solver jobs
            solver_futures = {}

            print("submitting solver jobs for {}".format(tile.label), file=log(0))

            for key in tile.get_chunk_keys():

# Path: cubical/tools/logger.py
# def logToFile(filename, append=False):
# def getLogFilename():
#     def __init__(self, logger, level, color=None, bold=None):
#     def write(self, message, level_override=None, print_once=None):
#     def print(self, *args):
#     def __init__(self, logger, verbose=None, log_verbose=None):
#     def verbosity(self, set_verb=None):
#     def log_verbosity(self, set_verb=None):
#     def __call__(self, level, color=None):
#     def warn(self, msg, color=None, print_once=None):
#     def error(self, msg, color="red", print_once=None):
#     def info(self, msg, color=None, print_once=None):
#     def critical(self, msg, color=None, print_once=None):
#     def debug(self, msg, color=None, print_once=None):
#     def exception(self, msg, color=None, print_once=None):
#     def print(self, *args):
#     def write(self, message, level=logging.INFO, verbosity=0, print_once=None, color=None):
# def enableMemoryLogging(level=1):
# def set_subprocess_label(label):
# def get_subprocess_label():
# def _sigusr1_handler(signum, frame):
# def _sigusr2_handler(signum, frame):
#     def setMemoryLogging(level):
#     def filter(self, event):
#     def __init__(self, fmt, datefmt, strip=True):
#     def label(self, record):
#     def format(self, record):
# def init(app_name):
# def getLogger(name, verbose=None, log_verbose=None):
# def setBoring(boring=True):
# def setGlobalVerbosity(verbosity):
# def setGlobalLogVerbosity(verbosity):
# def setSilent(Lname):
# def setLoud(Lname):
# class _DefaultWriter(object):
# class LoggerWrapper(object):
# class LogFilter(logging.Filter):
# class ColorStrippingFormatter(logging.Formatter):
# GB = float(1024 ** 3)
#                 KEYS = _log_memory_types[memlevel]
# 
# Path: cubical/solver.py
# GD = None 
# SOLVERS = { 'so': SolveOnly,
#             'sc': SolveAndCorrect,
#             'sr': SolveAndCorrectResiduals,
#             'ss': SolveAndSubtract,
#             'ac': CorrectOnly,
#             'ar': CorrectResiduals,
#             'as': SubtractOnly
#             }
#     def profile(func): return func
# def _solve_gains(gm, stats, madmax, obser_arr, model_arr, flags_arr, sol_opts, label="", compute_residuals=None):
#     def get_flagging_stats():
#     def update_stats(flags, statfields):
#     def compute_chisq(statfield=None, full=True):
#     def __init__(self, obser_arr, model_arr, flags_arr, weight_arr, freq_slice):
#     def weighted_obser(self):
#     def weighted_model(self):
#     def corrupt_weighted_model(self):
#     def corrupt_residual(self, imod=0, idir=slice(None)):
#     def corrupt_model(self, imod=0, idir=slice(None)):
#     def __get__(self, cls, owner):
#     def __init__(self, vdm, gm, soldict, sol_opts, label, metadata):
#     def is_model_required(cls):
#     def outputs_full_corrected_residuals(cls):
#     def run(self):
#     def finalize(self, corr_vis):
#     def run(self):
#     def run(self):
#     def run(self, correct=False):
#     def outputs_full_corrected_residuals(self):
#     def is_model_required(cls):
#     def run(self):
#     def run(self):
#     def outputs_full_corrected_residuals(self):
# def run_solver(solver_type, itile, chunk_key, sol_opts, debug_opts):
# class _VisDataManager(object):
# class classproperty(property):
# class SolverMachine(object):
# class SolveOnly(SolverMachine):
# class SolveAndCorrect(SolveOnly):
# class SolveAndSubtract(SolveOnly):
# class SolveAndCorrectResiduals(SolveAndSubtract):
# class CorrectOnly(SolverMachine):
# class SubtractOnly(SolverMachine):
# class CorrectResiduals(SubtractOnly):


# Path: cubical/workers.py
from builtins import range
from cubical.tools import logger
from cubical import solver
import multiprocessing, os, sys, traceback
import concurrent.futures as cf
import re
import numba
import cubical.kernels
            import cubical.kernels

        # (Montblanc is finicky about affinities apparently, so we don't do it before)
        _init_worker(main=True)

        for itile, tile in enumerate(tile_list):
            # wait for I/O job on current tile to finish
            print("waiting for I/O on {}".format(tile.label), file=log(0))
            # have a timeout so that if a child process dies, we at least find out
            done = False
            while not done:
                reap_children()
                done, not_done = cf.wait([io_futures[itile]], timeout=10)

            # check if result was successful
            if not io_futures[itile].result():
                raise RuntimeError("I/O job on {} failed".format(tile.label))
            del io_futures[itile]

            # immediately schedule I/O job to save previous/load next tile
            load_next = itile + 1 if itile < len(tile_list) - 1 else None
            save_prev = itile - 1 if itile else None
            if load_next is not None or save_prev is not None:
                io_futures[itile + 1] = io_executor.submit(_io_handler, load=load_next,
                                                           save=save_prev, load_model=load_model)

            # submit solver jobs
            solver_futures = {}

            print("submitting solver jobs for {}".format(tile.label), file=log(0))

            for key in tile.get_chunk_keys():

                solver_futures[executor.submit(solver.run_solver, solver_type, itile, key, solver_opts, debug_opts)] = key