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
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
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")
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))