def limb_darkening(): """The limb darkening form page. """ # Load default form form = fv.LimbDarkeningForm() # Reload page with stellar data from ExoMAST if form.resolve_submit.data: if form.targname.data.strip() != '': try: # Resolve the target in exoMAST form.targname.data = get_canonical_name(form.targname.data) data, target_url = get_target_data(form.targname.data) # Update the form data form.feh.data = data.get('Fe/H') form.teff.data = data.get('Teff') form.logg.data = data.get('stellar_gravity') form.target_url.data = str(target_url) except: form.target_url.data = '' form.targname.errors = [ "Sorry, could not resolve '{}' in exoMAST.".format( form.targname.data) ] # Send it back to the main page return render_template('limb_darkening.html', form=form) # Reload page with appropriate filter data if form.filter_submit.data: kwargs = {} if form.bandpass.data == 'tophat': kwargs['n_bins'] = 1 kwargs['pixels_per_bin'] = 100 kwargs['wave_min'] = 1 * u.um kwargs['wave_max'] = 2 * u.um # Get the filter bandpass = svo.Filter(form.bandpass.data, **kwargs) # Update the form data form.wave_min.data = bandpass.wave_min.value form.wave_max.data = bandpass.wave_max.value # Send it back to the main page return render_template('limb_darkening.html', form=form) # Update validation values after a model grid is selected if form.modelgrid_submit.data: # Load the modelgrid mg = ModelGrid(form.modeldir.data, resolution=500) teff_rng = mg.Teff_vals.min(), mg.Teff_vals.max() logg_rng = mg.logg_vals.min(), mg.logg_vals.max() feh_rng = mg.FeH_vals.min(), mg.FeH_vals.max() # Update the validation parameters by setting validator attributes setattr(form.teff.validators[1], 'min', teff_rng[0]) setattr(form.teff.validators[1], 'max', teff_rng[1]) setattr( form.teff.validators[1], 'message', 'Effective temperature must be between {} and {}'.format( *teff_rng)) setattr(form.logg.validators[1], 'min', logg_rng[0]) setattr(form.logg.validators[1], 'max', logg_rng[1]) setattr(form.logg.validators[1], 'message', 'Surface gravity must be between {} and {}'.format(*logg_rng)) setattr(form.feh.validators[1], 'min', feh_rng[0]) setattr(form.feh.validators[1], 'max', feh_rng[1]) setattr(form.feh.validators[1], 'message', 'Metallicity must be between {} and {}'.format(*feh_rng)) # Send it back to the main page return render_template('limb_darkening.html', form=form) # Validate form and submit for results if form.validate_on_submit() and form.calculate_submit.data: # Get the stellar parameters star_params = [ float(form.teff.data), float(form.logg.data), float(form.feh.data) ] # Log the form inputs try: log_exoctk.log_form_input(request.form, 'limb_darkening', DB) except: pass # Load the model grid model_grid = ModelGrid(form.modeldir.data, resolution=500) form.modeldir.data = [ j for i, j in form.modeldir.choices if i == form.modeldir.data ][0] # Grism details if '.G' in form.bandpass.data.upper( ) and 'GAIA' not in form.bandpass.data.upper(): kwargs = { 'n_bins': form.n_bins.data, 'pixels_per_bin': form.n_pix.data, 'wl_min': form.wave_min.data * u.um, 'wl_max': form.wave_max.data * u.um } else: kwargs = {} # Make filter object and plot bandpass = svo.Filter(form.bandpass.data, **kwargs) bp_name = bandpass.name bk_plot = bandpass.plot(draw=False) bk_plot.plot_width = 580 bk_plot.plot_height = 280 js_resources = INLINE.render_js() css_resources = INLINE.render_css() filt_script, filt_plot = components(bk_plot) # Trim the grid to nearby grid points to speed up calculation full_rng = [ model_grid.Teff_vals, model_grid.logg_vals, model_grid.FeH_vals ] trim_rng = find_closest(full_rng, star_params, n=1, values=True) # Calculate the coefficients for each profile ld = lf.LDC(model_grid) for prof in form.profiles.data: ld.calculate(*star_params, prof, mu_min=float(form.mu_min.data), bandpass=bandpass) # Draw a figure for each wavelength bin tabs = [] for wav in np.unique(ld.results['wave_eff']): # Plot it TOOLS = 'box_zoom, box_select, crosshair, reset, hover' fig = figure(tools=TOOLS, x_range=Range1d(0, 1), y_range=Range1d(0, 1), plot_width=800, plot_height=400) ld.plot(wave_eff=wav, fig=fig) # Plot formatting fig.legend.location = 'bottom_right' fig.xaxis.axis_label = 'mu' fig.yaxis.axis_label = 'Intensity' tabs.append(Panel(child=fig, title=str(wav))) final = Tabs(tabs=tabs) # Get HTML script, div = components(final) # Store the tables as a string file_as_string = str(ld.results[[ c for c in ld.results.dtype.names if ld.results.dtype[c] != object ]]) # Make a table for each profile with a row for each wavelength bin profile_tables = [] for profile in form.profiles.data: # Make LaTeX for polynomials latex = lf.ld_profile(profile, latex=True) poly = '\({}\)'.format(latex).replace('*', '\cdot').replace('\e', 'e') # Make the table into LaTeX table = filter_table(ld.results, profile=profile) co_cols = [ c for c in ld.results.colnames if (c.startswith('c') or c.startswith('e')) and len(c) == 2 and not np.all([np.isnan(i) for i in table[c]]) ] table = table[['wave_min', 'wave_max'] + co_cols] table.rename_column('wave_min', '\(\lambda_\mbox{min}\hspace{5px}(\mu m)\)') table.rename_column('wave_max', '\(\lambda_\mbox{max}\hspace{5px}(\mu m)\)') # Add the results to the lists html_table = '\n'.join(table.pformat(max_width=500, html=True))\ .replace('<table', '<table id="myTable" class="table table-striped table-hover"') # Add the table title header = '<br></br><strong>{}</strong><br><p>\(I(\mu)/I(\mu=1)\) = {}</p>'.format( profile, poly) html_table = header + html_table profile_tables.append(html_table) return render_template('limb_darkening_results.html', form=form, table=profile_tables, script=script, plot=div, file_as_string=repr(file_as_string), filt_plot=filt_plot, filt_script=filt_script, js=js_resources, css=css_resources) return render_template('limb_darkening.html', form=form)
def limb_darkening(): """Returns the rendered limb darkening form page. Returns ------- ``flask.render_template`` obj The rendered template for the limb-darkening page. """ # Load default form form = fv.LimbDarkeningForm() # Planet properties planet_properties = [ 'transit_duration', 'orbital_period', 'rp_rs', 'a_rs', 'inclination', 'eccentricity', 'omega' ] def empty_fields(form): form.transit_duration.data = form.transit_duration.data or '' form.orbital_period.data = form.orbital_period.data or '' form.rp_rs.data = form.rp_rs.data or '' form.a_rs.data = form.a_rs.data or '' form.inclination.data = form.inclination.data or '' form.eccentricity.data = form.eccentricity.data or '' form.omega.data = form.omega.data or '' return form # Reload page with stellar data from ExoMAST if form.resolve_submit.data: if form.targname.data.strip() != '': try: # Resolve the target in exoMAST form.targname.data = get_canonical_name(form.targname.data) data, target_url = get_target_data(form.targname.data) # Update the star data form.feh.data = data.get('Fe/H') form.teff.data = data.get('Teff') form.logg.data = data.get('stellar_gravity') form.target_url.data = str(target_url) # Update the planet data form.transit_duration.data = data.get('transit_duration') form.orbital_period.data = data.get('orbital_period') form.rp_rs.data = data.get('Rp/Rs') form.a_rs.data = data.get('a/Rs') form.inclination.data = data.get('inclination') form.eccentricity.data = data.get('eccentricity') form.omega.data = data.get('omega') except Exception: form.target_url.data = '' form.targname.errors = [ "Sorry, could not resolve '{}' in exoMAST.".format( form.targname.data) ] # Ensure planet fields are not None form = empty_fields(form) # Send it back to the main page return render_template('limb_darkening.html', form=form) # Reload page with appropriate filter data if form.filter_submit.data: kwargs = {} if form.bandpass.data == 'tophat': kwargs['n_bins'] = 1 kwargs['pixels_per_bin'] = 100 kwargs['wave_min'] = 1 * u.um kwargs['wave_max'] = 2 * u.um # Get the filter bandpass = Throughput(form.bandpass.data, **kwargs) # Update the form data form.wave_min.data = bandpass.wave_min.value form.wave_max.data = bandpass.wave_max.value # Ensure planet fields are not None form = empty_fields(form) # Send it back to the main page return render_template('limb_darkening.html', form=form) # Update validation values after a model grid is selected if form.modelgrid_submit.data: # Load the modelgrid mg = ModelGrid(form.modeldir.data, resolution=500) teff_rng = mg.Teff_vals.min(), mg.Teff_vals.max() logg_rng = mg.logg_vals.min(), mg.logg_vals.max() feh_rng = mg.FeH_vals.min(), mg.FeH_vals.max() # Update the validation parameters by setting validator attributes setattr(form.teff.validators[1], 'min', float(teff_rng[0])) setattr(form.teff.validators[1], 'max', float(teff_rng[1])) setattr( form.teff.validators[1], 'message', 'Effective temperature must be between {} and {}'.format( *teff_rng)) setattr(form.logg.validators[1], 'min', float(logg_rng[0])) setattr(form.logg.validators[1], 'max', float(logg_rng[1])) setattr(form.logg.validators[1], 'message', 'Surface gravity must be between {} and {}'.format(*logg_rng)) setattr(form.feh.validators[1], 'min', float(feh_rng[0])) setattr(form.feh.validators[1], 'max', float(feh_rng[1])) setattr(form.feh.validators[1], 'message', 'Metallicity must be between {} and {}'.format(*feh_rng)) # Ensure planet fields are not None form = empty_fields(form) # Send it back to the main page return render_template('limb_darkening.html', form=form) # Validate form and submit for results if form.validate_on_submit() and form.calculate_submit.data: # Form inputs for logging form_input = dict(request.form) # Get the stellar parameters star_params = [ float(form.teff.data), float(form.logg.data), float(form.feh.data) ] # Load the model grid model_grid = ModelGrid(form.modeldir.data, resolution=500) form.modeldir.data = [ j for i, j in form.modeldir.choices if i == form.modeldir.data ][0] # Grism details kwargs = { 'n_bins': form.n_bins.data, 'wave_min': form.wave_min.data * u.um, 'wave_max': form.wave_max.data * u.um } # Make filter object and plot bandpass = Throughput(form.bandpass.data, **kwargs) bk_plot = bandpass.plot(draw=False) bk_plot.plot_width = 580 bk_plot.plot_height = 280 js_resources = INLINE.render_js() css_resources = INLINE.render_css() filt_script, filt_plot = components(bk_plot) # Trim the grid to nearby grid points to speed up calculation # full_rng = [model_grid.Teff_vals, model_grid.logg_vals, model_grid.FeH_vals] # trim_rng = find_closest(full_rng, star_params, n=1, values=True) # Calculate the coefficients for each profile ld = lf.LDC(model_grid) for prof in form.profiles.data: ld.calculate(*star_params, prof, mu_min=float(form.mu_min.data), bandpass=bandpass) # Check if spam coefficients can be calculated planet_data = { param: getattr(form, param).data for param in planet_properties } planet_data['Rp/Rs'] = planet_data['rp_rs'] planet_data['a/Rs'] = planet_data['a_rs'] spam_calc = all([ val is not None and val != '' for key, val in planet_data.items() ]) if spam_calc: # Make sure non-linear profile is included for spam calculation if all planet parameters are provided if '4-parameter' not in form.profiles.data: ld.calculate(*star_params, '4-parameter', mu_min=float(form.mu_min.data), bandpass=bandpass) # Calculate spam coeffs planet_data = {key: float(val) for key, val in planet_data.items()} ld.spam(planet_data=planet_data) # Draw tabbed figure final = ld.plot_tabs() # Get HTML script, div = components(final) # Store the tables as a string keep_cols = [ 'Teff', 'logg', 'FeH', 'profile', 'filter', 'wave_min', 'wave_eff', 'wave_max', 'c1', 'e1', 'c2', 'e2', 'c3', 'e3', 'c4', 'e4' ] print_table = ld.results[[ col for col in keep_cols if col in ld.results.colnames ]] file_as_string = '\n'.join( print_table.pformat(max_lines=-1, max_width=-1)) # Make a table for each profile with a row for each wavelength bin profile_tables = [] for profile in form.profiles.data: # Make LaTeX for polynomials latex = lf.ld_profile(profile, latex=True) poly = '\({}\)'.format(latex).replace('*', '\cdot').replace('\e', 'e') # Make the table into LaTeX table = filter_table(ld.results, profile=profile) co_cols = [ c for c in ld.results.colnames if (c.startswith('c') or c.startswith('e')) and len(c) == 2 and not np.all([np.isnan(i) for i in table[c]]) ] table = table[['wave_eff', 'wave_min', 'wave_max'] + co_cols] table.rename_column('wave_eff', '\(\lambda_\mbox{eff}\hspace{5px}(\mu m)\)') table.rename_column('wave_min', '\(\lambda_\mbox{min}\hspace{5px}(\mu m)\)') table.rename_column('wave_max', '\(\lambda_\mbox{max}\hspace{5px}(\mu m)\)') # Add the results to the lists html_table = '\n'.join( table.pformat(max_width=-1, max_lines=-1, html=True) ).replace( '<table', '<table id="myTable" class="table table-striped table-hover"') # Add the table title header = '<br></br><strong>{}</strong><br><p>\(I(\mu)/I(\mu=1)\) = {}</p>'.format( profile, poly) html_table = header + html_table profile_tables.append(html_table) # Add the profile to the form inputs form_input[profile] = 'true' # Log the successful form inputs log_exoctk.log_form_input(form_input, 'limb_darkening', DB) # Make a table for each profile with a row for each wavelength bin profile_spam_tables = '' spam_file_as_string = '' if ld.spam_results is not None: # Store SPAM tables as string keep_cols = [ 'Teff', 'logg', 'FeH', 'profile', 'filter', 'wave_min', 'wave_eff', 'wave_max', 'c1', 'c2' ] print_spam_table = ld.spam_results[[ col for col in keep_cols if col in ld.spam_results.colnames ]] spam_file_as_string = '\n'.join( print_spam_table.pformat(max_lines=-1, max_width=-1)) profile_spam_tables = [] for profile in list(np.unique(ld.spam_results['profile'])): # Make LaTeX for polynomials latex = lf.ld_profile(profile, latex=True) poly = '\({}\)'.format(latex).replace('*', '\cdot').replace( '\e', 'e') # Make the table into LaTeX table = filter_table(ld.spam_results, profile=profile) co_cols = [ c for c in ld.spam_results.colnames if c.startswith('c') and c not in ['coeffs', 'color'] ] table = table[['wave_eff', 'wave_min', 'wave_max'] + co_cols] table.rename_column( 'wave_eff', '\(\lambda_\mbox{eff}\hspace{5px}(\mu m)\)') table.rename_column( 'wave_min', '\(\lambda_\mbox{min}\hspace{5px}(\mu m)\)') table.rename_column( 'wave_max', '\(\lambda_\mbox{max}\hspace{5px}(\mu m)\)') # Add the results to the lists html_table = '\n'.join( table.pformat(max_width=-1, max_lines=-1, html=True) ).replace( '<table', '<table id="myTable" class="table table-striped table-hover"' ) # Add the table title header = '<br></br><strong>{}</strong><br><p>\(I(\mu)/I(\mu=1)\) = {}</p>'.format( profile, poly) html_table = header + html_table profile_spam_tables.append(html_table) return render_template('limb_darkening_results.html', form=form, table=profile_tables, spam_table=profile_spam_tables, script=script, plot=div, spam_file_as_string=repr(spam_file_as_string), file_as_string=repr(file_as_string), filt_plot=filt_plot, filt_script=filt_script, js=js_resources, css=css_resources) return render_template('limb_darkening.html', form=form)