Example #1
0
def _define_forest(ns, parent=None, **kw):
    if not mssel.msname:
        raise RuntimeError("MS not set")
    if run_purr:
        Timba.TDL.GUI.purr(mssel.msname + ".purrlog", [mssel.msname, '.'])
    # create Purr pipe
    global purrpipe
    purrpipe = Purr.Pipe.Pipe(mssel.msname)

    # setup contexts from MS
    mssel.setup_observation_context(ns, prefer_baseline_uvw=True)
    array = Meow.Context.array

    # make spigot nodes for data
    if do_solve or do_output not in [CORRUPTED_MODEL]:
        mssel.enable_input_column(True)
        spigots = spigots0 = outputs = array.spigots(
            corr=mssel.get_corr_index())
        if enable_inspectors:
            meqmaker.make_per_ifr_bookmarks(spigots, "Input visibilities")
        # add IFR-based errors, if any
        spigots = meqmaker.apply_visibility_processing(ns, spigots)
    else:
        mssel.enable_input_column(False)
        spigots = spigots0 = None

    # make spigot nodes for model
    corrupt_uvdata = model_spigots = None
    if read_ms_model:
        mssel.enable_model_column(True)
        model_spigots = array.spigots(column="PREDICT",
                                      corr=mssel.get_corr_index())
        if enable_inspectors:
            meqmaker.make_per_ifr_bookmarks(model_spigots,
                                            "UV-model visibilities")
        # if calibrating on (input-corrupt model), make corrupt model
        if do_solve and cal_type == CAL.DIFF:
            corrupt_uvdata = meqmaker.corrupt_uv_data(ns, model_spigots)

    # if needed, then make a predict tree using the MeqMaker
    if do_solve or do_output != CORRECTED_DATA:
        if model_spigots and not corrupt_uvdata:
            uvdata = model_spigots
        else:
            uvdata = None
        predict = meqmaker.make_predict_tree(ns, uvdata=uvdata)
    else:
        predict = None
    output_title = "Uncorrected residuals"

    # make nodes to compute residuals
    if do_output in [CORRECTED_RESIDUALS, RESIDUALS]:
        residuals = ns.residuals
        for p, q in array.ifrs():
            if corrupt_uvdata:
                residuals(p, q) << Meq.Subtract(spigots(
                    p, q), corrupt_uvdata(p, q), predict(p, q))
            else:
                residuals(p, q) << spigots(p, q) - predict(p, q)
        if enable_inspectors:
            meqmaker.make_per_ifr_bookmarks(residuals, "Uncorrected residuals")
        outputs = residuals

    # and now we may need to correct the outputs
    if do_output in [CORRECTED_DATA, CORRECTED_RESIDUALS]:
        if do_correct_sky:
            srcs = meqmaker.get_source_list(ns)
            if do_correct_sky is FIRST_SOURCE:
                sky_correct = srcs and srcs[0]
            else:
                srcs = [
                    src for src in srcs
                    if fnmatch.fnmatchcase(src.name, do_correct_sky)
                ]
                sky_correct = srcs and srcs[0]
        else:
            sky_correct = None
        outputs = meqmaker.correct_uv_data(ns,
                                           outputs,
                                           sky_correct=sky_correct,
                                           flag_jones=flag_jones)
        output_title = "Corrected data" if do_output is CORRECTED_DATA else "Corrected residuals"
    elif do_output == CORRUPTED_MODEL:
        outputs = predict
        output_title = "Predict"
    elif do_output == CORRUPTED_MODEL_ADD:
        outputs = ns.output
        for p, q in array.ifrs():
            outputs(p, q) << spigots(p, q) + predict(p, q)
        output_title = "Data+predict"

    # make flaggers
    if flag_enable and do_output in [
            CORRECTED_DATA, RESIDUALS, CORRECTED_RESIDUALS
    ]:
        flaggers = []
        if flag_res is not None or flag_mean_res is not None:
            for p, q in array.ifrs():
                ns.absres(p, q) << Meq.Abs(outputs(p, q))
        # make flagger for residuals
        if flag_res is not None:
            for p, q in array.ifrs():
                ns.flagres(p, q) << Meq.ZeroFlagger(
                    ns.absres(p, q) - flag_res,
                    oper='gt',
                    flag_bit=Meow.MSUtils.FLAGMASK_OUTPUT)
            flaggers.append(ns.flagres)
            # ...and an inspector for them
            if enable_inspectors:
                meqmaker.make_per_ifr_bookmarks(ns.flagres,
                                                "Residual amplitude flags")
        # make flagger for mean residuals
        if flag_mean_res is not None:
            ns.meanabsres << Meq.Mean(
                *[ns.absres(p, q) for p, q in array.ifrs()])
            ns.flagmeanres << Meq.ZeroFlagger(
                ns.meanabsres - flag_mean_res,
                oper='gt',
                flag_bit=Meow.MSUtils.FLAGMASK_OUTPUT)
            Meow.Bookmarks.Page("Mean residual amplitude flags").add(
                ns.flagmeanres, viewer="Result Plotter")
            flaggers.append(lambda p, q: ns.flagmeanres)

        # merge flags into output
        if flaggers:
            if enable_inspectors:
                meqmaker.make_per_ifr_bookmarks(outputs,
                                                output_title + " (unflagged)")
            for p, q in array.ifrs():
                ns.flagged(p, q) << Meq.MergeFlags(
                    outputs(p, q), *[f(p, q) for f in flaggers])
            outputs = ns.flagged

    if enable_inspectors:
        meqmaker.make_per_ifr_bookmarks(outputs, output_title)
        abs_outputs = outputs('abs')
        for p, q in array.ifrs():
            abs_outputs(p, q) << Meq.Abs(outputs(p, q))
        meqmaker.make_per_ifr_bookmarks(abs_outputs,
                                        output_title + " (mean amplitudes)")

    # make solve trees
    if do_solve:
        # parse ifr specification
        solve_ifrs = array.subset(calibrate_ifrs, strict=False).ifrs()
        if not solve_ifrs:
            raise RuntimeError(
                "No interferometers selected for calibration. Check your ifr specification (under calibration options)."
            )
        # inputs to the solver are based on calibration type
        if corrupt_uvdata:
            [
                ns.diff(p, q) << spigots(p, q) - corrupt_uvdata(p, q)
                for p, q in solve_ifrs
            ]
            rhs = ns.diff
        else:
            rhs = spigots
        lhs = predict
        weights = modulo = None
        # if calibrating visibilities, feed them to condeq directly, else take ampl/phase
        if cal_what == CAL.VIS:
            pass
        elif cal_what == CAL.AMPL:
            [
                x('ampl', p, q) << Meq.Abs(x(p, q)) for p, q in ifrs
                for x in [rhs, lhs]
            ]
            lhs = lhs('ampl')
            rhs = rhs('ampl')
        elif cal_what == CAL.LOGAMPL:
            [
                x('logampl', p, q) << Meq.Log(Meq.Abs(x(p, q)))
                for p, q in ifrs for x in [rhs, lhs]
            ]
            lhs = lhs('logampl')
            rhs = rhs('logampl')
        elif cal_what == CAL.PHASE:
            [
                x('phase', p, q) << Meq.Arg(x(p, q)) for p, q in ifrs
                for x in [rhs, lhs]
            ]
            [rhs('ampl', p, q) << Meq.Abs(rhs(p, q)) for p, q in ifrs]
            lhs = lhs('phase')
            rhs = rhs('phase')
            weights = rhs('ampl')
            modulo = 2 * math.pi
        else:
            raise ValueError("unknown cal_what setting: " + str(cal_what))
        # make a solve tree
        solve_tree = StdTrees.SolveTree(ns,
                                        lhs,
                                        solve_ifrs=solve_ifrs,
                                        weights=weights,
                                        modulo=modulo)
        # the output of the sequencer is either the residuals or the spigots,
        # according to what has been set above
        outputs = solve_tree.sequencers(inputs=rhs, outputs=outputs)

    post = ((enable_inspectors and meqmaker.get_inspectors()) or [])
    StdTrees.make_sinks(ns,
                        outputs,
                        spigots=spigots0,
                        post=post,
                        corr_index=mssel.get_corr_index())

    if not do_solve:
        name = "Generate " + output_title.lower()
        comment = "Generated " + output_title.lower()
        if name:
            # make a TDL job to run the tree
            def run_tree(mqs, parent, wait=False, **kw):
                global tile_size
                purrpipe.title("Calibrating").comment(comment)
                return mqs.execute(Meow.Context.vdm.name,
                                   mssel.create_io_request(tile_size),
                                   wait=wait)

            TDLRuntimeMenu(
                name,
                TDLOption(
                    'tile_size',
                    "Tile size, in timeslots", [10, 60, 120, 240],
                    more=int,
                    doc=
                    """Input data is sliced by time, and processed in chunks (tiles) of
                  the indicated size. Larger tiles are faster, but use more memory."""
                ), TDLJob(run_tree, name, job_id='generate_visibilities'))

    # very important -- insert meqmaker's runtime options properly
    # this should come last, since runtime options may be built up during compilation.
    TDLRuntimeOptions(*meqmaker.runtime_options(nest=False))
    # insert solvejobs
    if do_solve:
        TDLRuntimeOptions(*ParmGroup.get_solvejob_options())
    # finally, setup imaging options
    imsel = mssel.imaging_selector(npix=512,
                                   arcmin=meqmaker.estimate_image_size())
    TDLRuntimeMenu("Make an image from this MS", *imsel.option_list())

    # and close meqmaker -- this exports annotations, etc
    meqmaker.close()
Example #2
0
def _define_forest(ns, parent=None, **kw):
    if run_purr:
        Timba.TDL.GUI.purr(mssel.msname + ".purrlog", [mssel.msname, '.'])
    # create Purr pipe
    global purrpipe
    purrpipe = Purr.Pipe.Pipe(mssel.msname)

    # get antennas from MS
    ANTENNAS = mssel.get_antenna_set(list(range(1, 15)))
    array = Meow.IfrArray(ns, ANTENNAS, mirror_uvw=False)
    stas = array.stations()
    # get phase centre from MS, setup observation
    observation = Meow.Observation(ns,
                                   phase_centre=mssel.get_phase_dir(),
                                   linear=mssel.is_linear_pol(),
                                   circular=mssel.is_circular_pol())
    Meow.Context.set(array, observation)
    # get active correlations from MS
    Meow.Context.active_correlations = mssel.get_correlations()

    # make spigot nodes
    spigots = spigots0 = outputs = array.spigots(corr=mssel.get_corr_index())

    # ...and an inspector for them
    StdTrees.vis_inspector(ns.inspector('input'),
                           spigots,
                           bookmark="Inspect input visibilities")
    inspectors = [ns.inspector('input')]
    Bookmarks.make_node_folder("Input visibilities by baseline",
                               [spigots(p, q) for p, q in array.ifrs()],
                               sorted=True,
                               ncol=2,
                               nrow=2)

    inspect_ifrs = array.ifrs()
    if do_solve:
        # filter solvable baselines by baseline length
        solve_ifrs = []
        antpos = mssel.ms_antenna_positions
        if (min_baseline or max_baseline) and antpos is not None:
            for (ip, p), (iq, q) in array.ifr_index():
                baseline = math.sqrt(
                    ((antpos[ip, :] - antpos[iq, :])**2).sum())
                if (not min_baseline or baseline > min_baseline) and \
                   (not max_baseline or baseline < max_baseline):
                    solve_ifrs.append((p, q))
        else:
            solve_ifrs = array.ifrs()
        inspect_ifrs = solve_ifrs

    # make a predict tree using the MeqMaker
    if do_solve or do_subtract:
        predict = meqmaker.make_predict_tree(ns)
        # make a ParmGroup and solve jobs for source parameters, if we have any
        if do_solve:
            parms = {}
            for src in meqmaker.get_source_list(ns):
                parms.update([(p.name, p) for p in src.get_solvables()])
            if parms:
                pg_src = ParmGroup.ParmGroup("source",
                                             list(parms.values()),
                                             table_name="sources.fmep",
                                             individual=True,
                                             bookmark=True)
                # now make a solvejobs for the source
                ParmGroup.SolveJob("cal_source", "Calibrate source model",
                                   pg_src)

    # make nodes to compute residuals
    if do_subtract:
        residuals = ns.residuals
        for p, q in array.ifrs():
            residuals(p, q) << spigots(p, q) - predict(p, q)
        outputs = residuals

    # and now we may need to correct the outputs
    if do_correct:
        if do_correct_sky:
            srcs = meqmaker.get_source_list(ns)
            sky_correct = srcs and srcs[0]
        else:
            sky_correct = None
        outputs = meqmaker.correct_uv_data(ns,
                                           outputs,
                                           sky_correct=sky_correct,
                                           inspect_ifrs=inspect_ifrs)

    # make solve trees
    if do_solve:
        # inputs to the solver are based on calibration type
        # if calibrating visibilities, feed them to condeq directly
        if cal_type == CAL.VIS:
            observed = spigots
            model = predict
        # else take ampl/phase component
        else:
            model = ns.model
            observed = ns.observed
            if cal_type == CAL.AMPL:
                for p, q in array.ifrs():
                    observed(p, q) << Meq.Abs(spigots(p, q))
                    model(p, q) << Meq.Abs(predict(p, q))
            elif cal_type == CAL.LOGAMPL:
                for p, q in array.ifrs():
                    observed(p, q) << Meq.Log(Meq.Abs(spigots(p, q)))
                    model(p, q) << Meq.Log(Meq.Abs(predict(p, q)))
            elif cal_type == CAL.PHASE:
                for p, q in array.ifrs():
                    observed(p, q) << 0
                    model(p, q) << Meq.Abs(predict(p, q)) * Meq.FMod(
                        Meq.Arg(spigots(p, q)) - Meq.Arg(predict(p, q)),
                        2 * math.pi)
            else:
                raise ValueError("unknown cal_type setting: " + str(cal_type))
        # make a solve tree
        solve_tree = StdTrees.SolveTree(ns, model, solve_ifrs=solve_ifrs)
        # the output of the sequencer is either the residuals or the spigots,
        # according to what has been set above
        outputs = solve_tree.sequencers(inputs=observed, outputs=outputs)

    # make sinks and vdm.
    # The list of inspectors must be supplied here
    inspectors += meqmaker.get_inspectors() or []
    StdTrees.make_sinks(ns, outputs, spigots=spigots0, post=inspectors)
    Bookmarks.make_node_folder("Corrected/residual visibilities by baseline",
                               [outputs(p, q) for p, q in array.ifrs()],
                               sorted=True,
                               ncol=2,
                               nrow=2)

    if not do_solve:
        if do_subtract:
            name = "Generate residuals"
            comment = "Generated residual visibilities."
        elif do_correct:
            name = "Generate corrected data"
            comment = "Generated corrected visibilities."
        else:
            name = None
        if name:
            # make a TDL job to runsthe tree
            def run_tree(mqs, parent, **kw):
                global tile_size
                purrpipe.title("Calibrating").comment(comment)
                mqs.execute(Meow.Context.vdm.name,
                            mssel.create_io_request(tile_size),
                            wait=False)

            TDLRuntimeMenu(
                name,
                TDLOption(
                    'tile_size',
                    "Tile size, in timeslots", [10, 60, 120, 240],
                    more=int,
                    doc=
                    """Input data is sliced by time, and processed in chunks (tiles) of
                  the indicated size. Larger tiles are faster, but use more memory."""
                ), TDLRuntimeJob(run_tree, name))

    # very important -- insert meqmaker's runtime options properly
    # this should come last, since runtime options may be built up during compilation.
    TDLRuntimeOptions(*meqmaker.runtime_options(nest=False))
    # insert solvejobs
    if do_solve:
        TDLRuntimeOptions(*ParmGroup.get_solvejob_options())
    # finally, setup imaging options
    imsel = mssel.imaging_selector(npix=512,
                                   arcmin=meqmaker.estimate_image_size())
    TDLRuntimeMenu("Make an image from this MS", *imsel.option_list())

    # and close meqmaker -- this exports annotations, etc
    meqmaker.close()
Example #3
0
def _define_forest(ns, parent=None, **kw):
    if not mssel.msname:
        raise RuntimeError('MS name not set')

    mssel.setup_observation_context(ns)
    array = Context.array

    # Data and model input

    if do_solve or output_type.need_data:
        mssel.enable_input_column(True)
        spigots = array.spigots(corr=mssel.get_corr_index())
        meqmaker.make_per_ifr_bookmarks(spigots, 'Input visibilities')
    else:
        mssel.enable_input_column(False)
        spigots = None

    if do_solve or output_type.need_model:
        predict = meqmaker.make_predict_tree(ns, uvdata=None)
    else:
        predict = None

    # Data output

    outputs = output_type.apply(ns, meqmaker, array.ifrs(), spigots, predict)

    # Flagging

    if flag_enable and output_type.flag_data:
        flaggers = []

        if flag_res is not None or flag_mean_res is not None:
            for p, q in array.ifrs():
                ns.absres(p, q) << Meq.Abs(outputs(p, q))

        if flag_res is not None:
            for p, q in array.ifrs():
                ns.flagres(p, q) << Meq.ZeroFlagger(
                    ns.absres(p, q) - flag_res,
                    oper='gt',
                    flag_bit=MSUtils.FLAGMASK_OUTPUT)
            flaggers.append(ns.flagres)
            meqmaker.make_per_ifr_bookmarks(ns.flagres,
                                            'Residual amplitude flags')

        if flag_mean_res is not None:
            ns.meanabsres << Meq.Mean(
                *[ns.absres(p, q) for p, q in array.ifrs()])
            ns.flagmeanres << Meq.ZeroFlagger(ns.meanabsres - flag_mean_res,
                                              oper='gt',
                                              flag_bit=MSUtils.FLAGMASK_OUTPUT)
            Bookmarks.Page('Mean residual amplitude flags').add(
                ns.flagmeanres, viewer='Result Plotter')
            flaggers.append(lambda p, q: ns.flagmeanres)

        if flaggers:
            meqmaker.make_per_ifr_bookmarks(outputs,
                                            output_type.desc + ' (unflagged)')
            for p, q in array.ifrs():
                ns.flagged(p, q) << Meq.MergeFlags(
                    outputs(p, q), *[f(p, q) for f in flaggers])
            outputs = ns.flagged

    meqmaker.make_per_ifr_bookmarks(outputs, output_type.desc)

    # Solve trees

    if do_solve:
        # parse ifr specification
        solve_ifrs = array.subset(calibrate_ifrs, strict=False).ifrs()

        if not solve_ifrs:
            raise RuntimeError(
                'No interferometers selected for calibration. '
                'Check your ifr specification (under calibration options).')

        lhs, rhs, weights, modulo = cal_quant.apply(solve_ifrs, predict,
                                                    spigots)
        solve_tree = StdTrees.SolveTree(ns,
                                        lhs,
                                        solve_ifrs=solve_ifrs,
                                        weights=weights,
                                        modulo=modulo)
        outputs = solve_tree.sequencers(inputs=rhs, outputs=outputs)

    StdTrees.make_sinks(ns,
                        outputs,
                        spigots=spigots,
                        post=meqmaker.get_inspectors() or [],
                        corr_index=mssel.get_corr_index())

    if not do_solve:
        name = 'Generate ' + output_type.desc.lower()
        comment = 'Generated ' + output_type.desc.lower()

        def run_tree(mqs, parent, wait=False, **kw):
            return mqs.execute(Context.vdm.name,
                               mssel.create_io_request(tile_size),
                               wait=wait)

        doc = """Input data are sliced by time, and processed in chunks (tiles) of
the indicated size. Larger tiles are faster, but use more memory."""

        TDLRuntimeMenu(
            name,
            TDLOption('tile_size',
                      'Tile size, in timeslots', [10, 60, 120, 240],
                      more=int,
                      doc=doc),
            TDLJob(run_tree, name, job_id='generate_visibilities'))

    # very important -- insert meqmaker's runtime options properly
    # this should come last, since runtime options may be built up
    # during compilation.

    TDLRuntimeOptions(*meqmaker.runtime_options(nest=False))

    if do_solve:
        TDLRuntimeOptions(*ParmGroup.get_solvejob_options())

    imsel = mssel.imaging_selector(npix=512,
                                   arcmin=meqmaker.estimate_image_size())
    TDLRuntimeMenu('Make an image', *imsel.option_list())
    meqmaker.close()