Example #1
0
def fit_mfl(args, curves_o, bnames, fitter, name, path, t_diff, tlim,
            is_fit_sigmas):
    distance = args.distance  # pc
    z = args.redshift
    # Set distance and redshift
    if not args.distance and z > 0:
        distance = ps.cosmology_D_by_z(z) * 1e6

    # light curves
    mdl = ps.Stella(name, path=path)
    if args.is_curve_tt:  # tt
        print(
            "The curves [UBVRI+bol] was taken from tt-file {}. ".format(name) +
            "IMPORTANT: distance: 10 pc, z=0, E(B-V) = 0")
        curves_m = mdl.get_tt().read_curves()
        excluded = [bn for bn in curves_m.BandNames if bn not in bnames]
        for bn in excluded:
            curves_m.pop(bn)
    else:
        curves_m = mdl.curves(bnames,
                              z=z,
                              distance=distance,
                              ebv=args.color_excess,
                              t_beg=tlim[0],
                              t_end=tlim[1],
                              t_diff=t_diff)

    fit_result, res, dum = fitter.best_curves(curves_m,
                                              curves_o,
                                              dt0=0.,
                                              is_fit_sigmas=is_fit_sigmas)

    return curves_m, fit_result, res
Example #2
0
def fit_mfl_vel(args,
                curves_o,
                vels_o,
                bnames,
                fitter,
                name,
                path,
                t_diff,
                tlim,
                Vnorm=1e8,
                A=0.):
    distance = args.distance  # pc
    z = args.redshift
    # Set distance and redshift
    if not args.distance and z > 0:
        distance = ps.cosmology_D_by_z(z) * 1e6

    tss_m = ps.SetTimeSeries("Models")
    tss_o = ps.SetTimeSeries("Obs")
    curves_m = None

    # light curves
    if curves_o is not None:
        mdl = ps.Stella(name, path=path)
        if args.is_curve_tt:  # tt
            print("The curves [UBVRI+bol] was taken from tt-file {}. ".format(
                name) + "IMPORTANT: distance: 10 pc, z=0, E(B-V) = 0")
            curves_m = mdl.get_tt().read_curves()
            excluded = [bn for bn in curves_m.BandNames if bn not in bnames]
            for bn in excluded:
                curves_m.pop(bn)
        else:
            curves_m = mdl.curves(bnames,
                                  z=z,
                                  distance=distance,
                                  ebv=args.color_excess,
                                  t_beg=tlim[0],
                                  t_end=tlim[1],
                                  t_diff=t_diff)

        for lc in curves_m:
            tss_m.add(lc)
            # tss_m[lc.Band.Name] = lc

        for lc in curves_o:
            l, tshift, mshift = lc.clone()
            tss_o.add(l)
            # tss_o[lc.Band.Name], tshift, mshift = lc.shifted()
            # tshifts[lc.Band.Name] = tshift

    vel_m = None
    # compute model velocities
    try:
        tbl = ps.vel.compute_vel_swd(name, path)
        # tbl = velocity.compute_vel_res_tt(name, path)
        vel_m = ps.vel.VelocityCurve('Vel', tbl['time'], tbl['vel'] / Vnorm)
        if vel_m is None:
            raise ValueError('Problem with vel_m.')
    except ValueError as ext:
        print(ext)

    # velocity
    if curves_m is not None:
        # To increase the weight of Velocities with fitting
        for i in range(curves_m.Length):
            for vel_o in vels_o:
                key = 'Vel{:d}{}'.format(i, vel_o.Name)
                tss_m.add(vel_m.copy(name=key))
                tss_o.add(vel_o.copy(name=key))
                # tss_o[key] = vel_o
                # tss_m[key] = vel_m
    else:
        # tss_m.add(vel_m.copy(name='Vel'))
        for i, vel_o in enumerate(vels_o):
            key = 'Vel{:d}{}'.format(i, vel_o.Name)
            tss_m.add(vel_m.copy(name=key))
            tss_o.add(vel_o.copy(name=key))
        # tss_o.add(vels_o.copy(name='Vel'))
        # tss_m['Vel'] = vel_m
        # tss_o['Vel'] = vels_o

    # fit
    res = fitter.fit_tss(tss_m, tss_o, A=A)

    return curves_m, res, vel_m
Example #3
0
def main():
    import os
    import sys

    model_ext = '.ph'
    n_best = 15
    ps.Band.load_settings()
    is_set_model = False
    parser = get_parser()
    args, unknownargs = parser.parse_known_args()

    path = os.getcwd()
    if args.path:
        path = os.path.expanduser(args.path)
        # print(f'-p: {path}')

    # Set model names
    names = []
    if args.input:
        for arg in args.input:
            names.extend(arg2names(arg=arg, path=path, ext=model_ext))
            is_set_model = True
        names = list(set(names))  # with unique values

    if len(names) == 0 and not is_set_model:  # run for all files in the path
        names = ps.path.get_model_names(path, model_ext)

    if len(names) == 0:
        print(f'PATH: {path}')
        print(f'-i: {args.input}')
        print(
            'I do not know the models for fitting. Please use the key -i MODEL or -i *R500* '
        )
        parser.print_help()
        sys.exit(2)

    # Set band names
    bnames = []
    if args.bnames:
        for bname in args.bnames.split('-'):
            if not ps.band.is_exist(bname):
                print('No such band: ' + bname)
                parser.print_help()
                sys.exit(2)
            bnames.append(bname)

    # Get observations
    observations = ps.cb.observations(args)
    if observations is None:
        print('No obs data. Use key: -c: ')
        parser.print_help()
        sys.exit(2)

    # curves
    curves_o = merge_obs(observations, ps.SetLightCurve)
    vels_o = merge_obs(observations, ps.vel.SetVelocityCurve)

    # set bands  as observed
    if curves_o is not None and len(bnames) == 0:
        bnames = [bn for bn in curves_o.BandNames if ps.band.is_exist(bn)]

    # Set distance and redshift
    is_sigma = args.is_fit_sigmas
    z = args.redshift
    t_diff = args.t_diff
    if args.distance is not None:
        print("Fit magnitudes on z={0:F} at distance={1:E}".format(
            z, args.distance))
        if z > 0:
            print("  Cosmology D(z)={0:E} Mpc".format(ps.cosmology_D_by_z(z)))
    else:
        distance = 10  # pc
        if z > 0:
            distance = ps.cosmology_D_by_z(z) * 1e6
            print("Fit magnitudes on z={0:F} with cosmology D(z)={1:E} pc".
                  format(z, distance))
        args.distance = distance
    if is_sigma:
        print("Fit magnitudes with model uncertainties.")

    print("Color excess E(B-V) ={:f}".format(args.color_excess))

    # Time limits for models
    tlim = (0, float('inf'))

    if args.tlim:
        tlim = list(map(float, args.tlim.replace('\\', '').split(':')))
    print('Time limits for models: {}'.format(':'.join(map(str, tlim))))

    # The fit engine
    fitter = engines(args.engine)
    fitter.is_info = args.is_not_quiet  # fitter = FitMPFit(is_debug=args.is_not_quiet)
    # fitter.is_debug = args.is_not_quiet

    if args.is_not_quiet:
        fitter.print_parameters()

    # The filter results by tshift
    if args.dtshift:
        dtshift = ps.str2interval(args.dtshift,
                                  llim=float("-inf"),
                                  rlim=float('inf'))
    else:
        dtshift = (float("-inf"), float("inf"))

    # tshift = 0.
    res_models = {}
    vels_m = {}
    res_chi = {}
    if len(names) == 1:
        name = names[0]
        if args.is_not_quiet:
            if tlim is not None:
                print("Fitting for model %s %s for %s moments" %
                      (path, name, tlim))
            else:
                print("Fitting for model %s %s, tweight= %f" %
                      (path, name, args.tweight))
        # curves_m = lcf.curves_compute(name, path, bnames, z=args.redshift, distance=args.distance,
        #                               t_beg=tlim[0], t_end=tlim[1], t_diff=t_diff)
        # res = fitter.fit_curves(curves_o, curves_m)
        if vels_o is None:
            curves_m, res, res_full = fit_mfl(args, curves_o, bnames, fitter,
                                              name, path, t_diff, tlim,
                                              is_sigma)
        else:
            curves_m, res, vel_m = fit_mfl_vel(args,
                                               curves_o,
                                               vels_o,
                                               bnames,
                                               fitter,
                                               name,
                                               path,
                                               t_diff,
                                               tlim,
                                               is_sigma,
                                               A=args.tweight)
            vels_m[name] = vel_m

        print("{}: time shift  = {:.2f}+/-{:.4f} Measure: {:.4f} {}".format(
            name, res.tshift, res.tsigma, res.measure, res.comm))
        # best_tshift = res.tshift
        res_models[name] = curves_m
        res_chi[name] = res
        res_sorted = res_chi
    elif len(names) > 1:
        if args.nodes > 1:
            print("Run parallel fitting: nodes={}, models  {}".format(
                args.nodes, len(names)))
            with futures.ProcessPoolExecutor(
                    max_workers=args.nodes) as executor:
                if vels_o is None:
                    future_to_name = {
                        executor.submit(fit_mfl, args, curves_o, bnames,
                                        fitter, n, path, t_diff, tlim,
                                        is_sigma): n
                        for n in names
                    }
                else:
                    future_to_name = {
                        executor.submit(fit_mfl_vel, args, curves_o, vels_o,
                                        bnames, fitter, n, path, t_diff, tlim,
                                        is_sigma): n
                        for n in names
                    }

                i = 0
                for future in futures.as_completed(future_to_name):
                    i += 1
                    name = future_to_name[future]
                    try:
                        data = future.result()
                    except Exception as exc:
                        print('%r generated an exception: %s' % (name, exc))
                    else:
                        res_models[name], res, vels_m[name] = data
                        res_chi[name] = res
                        print("[{}/{}] {:30s} -> {}".format(
                            i, len(names), name, res.comm))
        else:
            i = 0
            for name in names:
                i += 1
                txt = "Fitting [{}] for model {:30s}  [{}/{}]".format(
                    fitter.Name, name, i, len(names))
                if args.is_not_quiet:
                    print(txt)
                else:
                    sys.stdout.write(u"\u001b[1000D" + txt)
                    sys.stdout.flush()

                if vels_o is None:
                    curves_m, res, res_full = fit_mfl(args, curves_o, bnames,
                                                      fitter, name, path,
                                                      t_diff, tlim, is_sigma)
                else:
                    curves_m, res, vel_m = fit_mfl_vel(args,
                                                       curves_o,
                                                       vels_o,
                                                       bnames,
                                                       fitter,
                                                       name,
                                                       path,
                                                       t_diff,
                                                       tlim,
                                                       is_sigma,
                                                       A=args.tweight)
                    vels_m[name] = vel_m
                res_models[name] = curves_m
                res_chi[name] = res

        # select with dtshift
        res_chi_sel = {}
        for k, v in res_chi.items():
            if dtshift[0] < v.tshift < dtshift[1]:
                res_chi_sel[k] = v
        res_chi = res_chi_sel
        # sort with measure
        res_sorted = OrderedDict(
            sorted(res_chi.items(), key=lambda kv: kv[1].measure))
    else:
        print("No any data about models. Path: {}".format(path))
        parser.print_help()
        sys.exit(2)

    # print results
    print("\n Results (tshift in range:{:.2f} -- {:.2f}".format(
        dtshift[0], dtshift[1]))
    print("{:40s} ||{:18s}|| {:10}".format('Model', 'dt+-t_err', 'Measure'))
    for k, v in res_sorted.items():
        print("{:40s} || {:7.2f}+/-{:7.4f} || {:.4f} || {}".format(
            k, v.tshift, v.tsigma, v.measure, v.comm))

    if len(res_sorted) >= n_best:
        # plot chi squared
        plot_squared_grid(res_sorted, path, is_not_quiet=args.is_not_quiet)
        plot_chi_par(res_sorted, path)

        # plot only Nbest modeles
        # while len(res_sorted) > Nbest:
        #     res_sorted.popitem()

        # plot_squared_3d(None, res_sorted, path, p=('R', 'M', 'E'), is_polar=True)

    best_mdl, res = ps.first(res_sorted.items())
    # res = first(res_sorted.values())[0]
    print("Best fit model:")
    print("{}: time shift  = {:.2f}+/-{:.4f} Measure: {:.4f}".format(
        best_mdl, res.tshift, res.tsigma, res.measure))
    print("{}: ".format(best_mdl), res.comm)

    # shift observational data
    # curves_o.set_tshift(best_tshift)

    # plot only NbestPlot modeles
    while len(res_sorted) > args.plotnbest:
        res_sorted.popitem()

    if vels_o is not None and vels_o.Length > 0:
        # vel_o.tshift = best_tshift
        fig = plot_curves_vel(curves_o, vels_o, res_models, res_sorted, vels_m)
    else:
        fig = plot_curves(curves_o, res_models, res_sorted, xlim=tlim)

    if args.save_file is not None:
        fsave = args.save_file
        if len(os.path.dirname(fsave)) == 0:
            fsave = os.path.expanduser("~/{}".format(fsave))
        if not fsave.endswith('.pdf'):
            fsave += '.pdf'
        print("Save plot to {0}".format(fsave))
        fig.savefig(fsave, bbox_inches='tight')
    else:
        from matplotlib import pyplot as plt
        # plt.subplots_adjust(left=0.07, right=0.96, top=0.97, bottom=0.06)
        plt.ion()
        plt.show()
        plt.pause(0.0001)
        print('')
        input("===> Hit <return> to quit")
Example #4
0
def main(name=None, model_ext='.ph'):
    import sys
    import os
    import getopt
    import fnmatch

    is_quiet = False
    is_save_mags = False
    is_save_plot = False
    is_plot_time_points = False
    is_extinction = False
    is_curve_old = False
    is_curve_tt = False
    is_axes_right = False
    is_grid = False

    vel_mode = None
    view_opts = ('single', 'grid', 'gridl', 'gridm')
    opt_grid = view_opts[0]
    t_diff = 1.01
    linestyles = ['-']

    label = None
    fsave = None
    fname = None
    # path = ''
    path = os.getcwd()
    z = 0.
    e = 0.
    magnification = 1.
    distance = None  # 10.  # pc
    callback = None
    xlim = None
    ylim = None
    xtype = 'lin'
    # bshift = None
    bshift = None

    ps.band.Band.load_settings()

    try:
        opts, args = getopt.getopt(sys.argv[1:],
                                   "hqtb:c:d:e:g:i:l:o:m:p:v:s:w:x:y:z:",
                                   ['dt=', 'curve-old', 'curve-tt'])
    except getopt.GetoptError as err:
        print(str(err))  # will print something like "option -a not recognized"
        usage()
        sys.exit(2)

    if len(args) > 0:
        path, name = os.path.split(str(args[0]))
        path = os.path.expanduser(path)
        name = name.replace('.ph', '')
    elif len(opts) == 0:
        usage()
        sys.exit(2)

    bnames = ['U', 'B', 'V', 'R']
    # bands = ['U', 'B', 'V', 'R', "I", 'UVM2', "UVW1", "UVW2", 'g', "r", "i"]

    for opt, arg in opts:
        if opt == '-e':
            e = float(arg)
            is_extinction = True
            continue
        if opt == '-b':
            bnames = []
            bshift = {}
            for b in str(arg).split('-'):
                # extract band shift
                if ':' in b:
                    bname, shift = b.split(':')
                    if '_' in shift:
                        bshift[bname] = -float(shift.replace('_', ''))
                    else:
                        bshift[bname] = float(shift)
                else:
                    bname = b
                if not ps.band.is_exist(bname):
                    print('No such band: ' + bname)
                    sys.exit(2)
                bnames.append(bname)
            continue
        if opt == '-c':
            c = ps.cb.lc_wrapper(str(arg))
            if callback is not None:
                c = ps.cb.CallBackArray((callback, c))
            callback = c
            continue
        if opt == '--dt':
            t_diff = float(arg)
            continue
        if opt == '-q':
            is_quiet = True
            continue
        if opt == '-g':
            opt_grid = str.strip(arg).lower()
            if opt_grid not in view_opts:
                print('No such view option: {0}. Can be '.format(
                    opt_grid, '|'.join(view_opts)))
                sys.exit(2)
            continue
        if opt == '-s':
            is_save_plot = True
            fsave = str.strip(arg)
            continue
        if opt == '--curve-old':
            is_curve_old = True
            continue
        if opt == '--curve-tt':
            is_curve_tt = True
            continue
        if opt == '-w':
            is_save_mags = True
            if arg != '1':
                fname = arg.strip()
            continue
        if opt == '-t':
            is_plot_time_points = True
            continue
        if opt == '-v':
            vel_mode = arg.strip()
            continue
        if opt == '-m':
            magnification = float(arg)
            continue
        if opt == '-z':
            z = float(arg)
            continue
        if opt == '-d':
            distance = float(arg)
            continue
        if opt == '-l':
            label = str.strip(arg)
            continue
        if opt == '-x':
            if 'log' in arg:
                xtype = 'log'
                s12 = arg.replace(xtype, '')
                s12 = s12.rstrip(':')
            else:
                s12 = arg
            # print(f's12= {s12}')
            xlim = ps.str2interval(s12, llim=0, rlim=float('inf'))
            continue
        if opt == '-y':
            ylim = ps.str2interval(arg, llim=-10, rlim=-22)
            continue
        if opt == '-p':
            path = os.path.expanduser(str(arg))
            if not (os.path.isdir(path) and os.path.exists(path)):
                print("No such directory: " + path)
                sys.exit(2)
            continue
        elif opt == '-h':
            usage()
            sys.exit(2)

    # Set model names
    names = []
    is_set_model = False
    if name is None:
        for opt, arg in opts:
            if opt == '-i':
                nm = os.path.splitext(os.path.basename(str(arg)))[0]
                if os.path.exists(os.path.join(path, nm + model_ext)):
                    names.append(nm)
                else:
                    files = [
                        f for f in os.listdir(path)
                        if os.path.isfile(os.path.join(path, f))
                        and fnmatch.fnmatch(f, arg)
                    ]
                    for f in files:
                        nm = os.path.splitext(os.path.basename(f))[0]
                        names.append(nm)
                    names = list(set(names))
                    print('Input {} models: {}'.format(len(names),
                                                       ' '.join(names)))
                is_set_model = True
    else:
        print(name)
        names.append(name)
        is_set_model = True

    if len(names) == 0 and not is_set_model:  # run for all files in the path
        names = ps.path.get_model_names(path, model_ext)

    # Set distance and redshift
    if distance is None:
        if z > 0:
            distance = ps.cosmology_D_by_z(z) * 1e6
            print(
                "Plot magnitudes on z={0:F} with D(z)={1:E} pc (cosmological)".
                format(z, distance))
        else:
            distance = 10  # pc
    else:
        print("Plot magnitudes on z={0:F} at distance={1:E}".format(
            z, distance))
        if z > 0:
            print("  Cosmology D(z)={0:E} Mpc".format(ps.cosmology_D_by_z(z)))

    # Run models
    if len(names) > 0:
        models_mags = {}  # dict((k, None) for k in names)
        models_vels = {}  # dict((k, None) for k in names)
        for i, name in enumerate(names):
            mdl = ps.Stella(name, path=path)

            if is_curve_tt:  # tt
                print(
                    "The curves [UBVRI+bol] was taken from tt-file. IMPORTANT: distance: 10 pc, z=0, E(B-V) = 0"
                )
                curves = mdl.get_tt().read_curves()
            elif is_curve_old:  # old
                print("Use old proc for Stella magnitudes")
                curves = ps.lcf.curves_compute(name,
                                               path,
                                               bnames,
                                               z=z,
                                               distance=distance,
                                               magnification=magnification,
                                               t_diff=t_diff)
                if is_extinction:
                    curves = ps.lcf.curves_reddening(curves, ebv=e, z=z)
            else:
                curves = mdl.curves(bnames,
                                    z=z,
                                    distance=distance,
                                    ebv=e,
                                    magnification=magnification,
                                    t_diff=t_diff)

            models_mags[name] = curves

            if vel_mode is not None:
                if vel_mode == 'swd':
                    vels = ps.vel.compute_vel_swd(name, path, z=z)
                elif vel_mode.startswith('ttres'):
                    vels = ps.vel.compute_vel_res_tt(name,
                                                     path,
                                                     z=z,
                                                     is_info=False,
                                                     is_new_std='old'
                                                     not in vel_mode.lower())
                else:
                    raise ValueError(
                        'This mode [{}] for velocity is not supported'.format(
                            vel_mode))

                if vels is None:
                    sys.exit("Error: no data for: %s in %s" % (name, path))
                models_vels[name] = vels
                print("[%d/%d] Done mags & velocity for %s" %
                      (i + 1, len(names), name))
            else:
                models_vels = None
                print("[%d/%d] Done mags for %s" % (i + 1, len(names), name))

        if label is None:
            if callback is not None:
                label = "ts=%s z=%4.2f D=%6.2e mu=%3.1f ebv=%4.2f" % (
                    callback.arg_totext(0), z, distance, magnification, e)
            else:
                label = "z=%4.2f D=%6.2e mu=%3.1f ebv=%4.2f" % (
                    z, distance, magnification, e)

        # save curves to files
        if is_save_mags:
            for curves in models_mags.values():
                if fname is None:
                    fname = os.path.join(path, curves.Name)
                    if z > 0.:
                        fname = '{}_Z{:.2g}'.format(fname, z)
                    if distance > 10.:
                        fname = '{}_D{:.2e}'.format(fname, distance)
                    if e > 0:
                        fname = '{}_E{:0.2g}'.format(fname, e)
                    fname = '{}{}'.format(fname, '.ubv')
                if ps.lcf.curves_save(curves, fname):
                    print("Magnitudes of {} have been saved to {}".format(
                        curves.Name, fname))
                else:
                    print("Error with Magnitudes saved to {}".format(
                        curves.Name, fname))
        # plot
        elif not is_quiet:
            if opt_grid in view_opts[1:]:
                sep = opt_grid[:-1]
                if sep == 'd':
                    sep = 'l'  # line separator
                fig = plot_grid(models_mags,
                                bnames,
                                call=callback,
                                xlim=xlim,
                                xtype=xtype,
                                ylim=ylim,
                                title=label,
                                sep=sep,
                                is_grid=False)
            else:
                # linestyles = ['--', '-.', '-', ':']
                fig = plot_all(models_vels,
                               models_mags,
                               bnames,
                               d=distance,
                               call=callback,
                               xlim=xlim,
                               xtype=xtype,
                               ylim=ylim,
                               is_time_points=is_plot_time_points,
                               title=label,
                               bshift=bshift,
                               is_axes_right=is_axes_right,
                               is_grid=is_grid,
                               legloc=1,
                               fontsize=14,
                               lines=linestyles)
                # lcp.setFigMarkersBW(fig)
                # lcp.setFigLinesBW(fig)

            if is_save_plot:
                if len(fsave) == 0:
                    if vel_mode is not None:
                        fsave = "ubv_vel_%s" % name
                    else:
                        fsave = "ubv_%s" % name

                if is_extinction and e > 0:
                    fsave = "%s_e0%2d" % (fsave, int(e * 100)
                                          )  # bad formula for name

                fsave = os.path.expanduser(fsave)
                fsave = os.path.splitext(fsave)[0] + '.pdf'

                print("Save plot to %s " % os.path.abspath(fsave))
                fig.savefig(fsave, bbox_inches='tight', format='pdf')
            else:
                import matplotlib.pyplot as plt
                # plt.ion()
                plt.show()
                # plt.pause(0.0001)
                # print('')
                # input("===> Hit <return> to quit")

    else:
        print(
            "There are no such models in the directory: %s with extension: %s "
            % (path, model_ext))