def fits_osiris_allclose(a, b): """Assert that two OSIRIS fits files are close.""" a = fits.open(a) b = fits.open(b) try: del a[0].header['COMMENT'] del b[0].header['COMMENT'] report = StringIO() diff = FITSDiff( a, b, ignore_keywords=["COMMENT"], ignore_comments=["SIMPLE"], ignore_fields=[], ignore_blanks=True, ignore_blank_cards=True, tolerance=1e-5) diff.report(fileobj=report) assert diff.identical, report.getvalue() finally: a.close() b.close()
def fits_osiris_allclose(a, b): """Assert that two OSIRIS fits files are close.""" a = fits.open(a) b = fits.open(b) try: del a[0].header['COMMENT'] del b[0].header['COMMENT'] report = StringIO() diff = FITSDiff(a, b, ignore_keywords=["COMMENT"], ignore_comments=["SIMPLE"], ignore_fields=[], ignore_blanks=True, ignore_blank_cards=True, tolerance=1e-5) diff.report(fileobj=report) assert diff.identical, report.getvalue() finally: a.close() b.close()
def exotransmit_portal(): """ Run Exo-Transmit taking inputs from the HTML form and plot the results """ if exotransmit_dir is None: return render_template( 'tor_error.html', tor_err= "There seems to be no directory in place for exo-transmit...") # Grab the inputs arguments from the URL args = flask.request.args # Get all the form arguments in the url with defaults eos, tp, g, R_p, R_s, P, Rayleigh, invalid = _param_validation(args) if invalid: return flask.render_template('exotransmit_validation.html', invalid=invalid) if args: x, y = exotransmit_run(eos, tp, g, R_p, R_s, P, Rayleigh) else: x, y = np.loadtxt(os.path.join(exotransmit_dir, 'Spectra/default.dat'), skiprows=2, unpack=True) tab = at.Table(data=[x / 1e-6, y / 100]) fh = StringIO() tab.write(fh, format='ascii.no_header') table_string = fh.getvalue() fig = figure(plot_width=1100, plot_height=400, responsive=False) fig.line(x / 1e-6, y / 100, color='Black', line_width=0.5) fig.xaxis.axis_label = 'Wavelength (um)' fig.yaxis.axis_label = 'Transit Depth' js_resources = INLINE.render_js() css_resources = INLINE.render_css() script, div = components(fig) html = flask.render_template( 'exotransmit_portal.html', plot_script=script, plot_div=div, js_resources=js_resources, css_resources=css_resources, eos_files=os.listdir(os.path.join(exotransmit_dir, 'EOS')), tp_files=os.listdir(os.path.join(exotransmit_dir, 'T_P')), tp=tp, eos=eos, g=g, R_p=R_p, R_s=R_s, P=P, Rayleigh=Rayleigh, table_string=table_string) return encode_utf8(html)
def contam_visibility(): """The contamination and visibility form page""" # Load default form form = fv.ContamVisForm() form.calculate_contam_submit.disabled = False if request.method == 'GET': # http://0.0.0.0:5000/contam_visibility?ra=24.354208334287005&dec=-45.677930555343636&target=WASP-18%20b target_name = request.args.get('target') form.targname.data = target_name ra = request.args.get('ra') form.ra.data = ra dec = request.args.get('dec') form.dec.data = dec return render_template('contam_visibility.html', form=form) # Reload page with stellar data from ExoMAST if form.resolve_submit.data: if form.targname.data.strip() != '': # Resolve the target in exoMAST try: form.targname.data = get_canonical_name(form.targname.data) data, url = get_target_data(form.targname.data) # Update the coordinates ra_deg = data.get('RA') dec_deg = data.get('DEC') # Set the form values form.ra.data = ra_deg form.dec.data = dec_deg form.target_url.data = 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('contam_visibility.html', form=form) # Reload page with appropriate mode data if form.mode_submit.data: # Update the button if form.inst.data != 'NIRISS': form.calculate_contam_submit.disabled = True else: form.calculate_contam_submit.disabled = False # Send it back to the main page return render_template('contam_visibility.html', form=form) if form.validate_on_submit() and (form.calculate_submit.data or form.calculate_contam_submit.data): try: # Log the form inputs try: log_exoctk.log_form_input(request.form, 'contam_visibility', DB) except: pass # Make plot title = form.targname.data or ', '.join( [form.ra.data, form.dec.data]) pG, pB, dates, vis_plot, table = vpa.using_gtvt( str(form.ra.data), str(form.dec.data), form.inst.data.split(' ')[0]) # Make output table vers = '0.3' today = datetime.datetime.now() fh = StringIO() fh.write('# Hi! This is your Visibility output file for... \n') fh.write('# Target: {} \n'.format(form.targname.data)) fh.write('# Instrument: {} \n'.format(form.inst.data)) fh.write('# \n') fh.write( '# This file was generated using ExoCTK v{} on {} \n'.format( vers, today)) fh.write('# Visit our GitHub: https://github.com/ExoCTK/exoctk \n') fh.write('# \n') table.write(fh, format='csv', delimiter=',') visib_table = fh.getvalue() # Format x axis day0 = datetime.date(2019, 6, 1) dtm = datetime.timedelta(days=367) #vis_plot.x_range = Range1d(day0, day0 + dtm) # TODO: Fix this so bad PAs are included pB = [] # Make plot TOOLS = 'crosshair, reset, hover, save' fig = figure(tools=TOOLS, plot_width=800, plot_height=400, x_axis_type='datetime', title=title) fh = StringIO() table.write(fh, format='ascii') visib_table = fh.getvalue() # Format x axis day0 = datetime.date(2019, 6, 1) dtm = datetime.timedelta(days=367) # Get scripts vis_js = INLINE.render_js() vis_css = INLINE.render_css() vis_script, vis_div = components(vis_plot) # Contamination plot too if form.calculate_contam_submit.data: # First convert ra and dec to HH:MM:SS ra_deg, dec_deg = float(form.ra.data), float(form.dec.data) sc = SkyCoord(ra_deg, dec_deg, unit='deg') ra_dec = sc.to_string('hmsdms') ra_hms, dec_dms = ra_dec.split(' ')[0], ra_dec.split(' ')[1] # Make field simulation contam_cube = fs.sossFieldSim(ra_hms, dec_dms, binComp=form.companion.data) contam_plot = cf.contam( contam_cube, title, paRange=[int(form.pa_min.data), int(form.pa_max.data)], badPA=pB, fig='bokeh') # Get scripts contam_js = INLINE.render_js() contam_css = INLINE.render_css() contam_script, contam_div = components(contam_plot) else: contam_script = contam_div = contam_js = contam_css = '' return render_template('contam_visibility_results.html', form=form, vis_plot=vis_div, vis_table=visib_table, vis_script=vis_script, vis_js=vis_js, vis_css=vis_css, contam_plot=contam_div, contam_script=contam_script, contam_js=contam_js, contam_css=contam_css) except IOError: #Exception as e: err = 'The following error occurred: ' + str(e) return render_template('groups_integrations_error.html', err=err) return render_template('contam_visibility.html', form=form)
def contam_visibility(): """The contamination and visibility form page""" # Load default form form = fv.ContamVisForm() form.calculate_contam_submit.disabled = False if request.method == 'GET': # http://0.0.0.0:5000/contam_visibility?ra=24.354208334287005&dec=-45.677930555343636&target=WASP-18%20b target_name = request.args.get('target') form.targname.data = target_name ra = request.args.get('ra') form.ra.data = ra dec = request.args.get('dec') form.dec.data = dec return render_template('contam_visibility.html', form=form) # Reload page with stellar data from ExoMAST if form.resolve_submit.data: if form.targname.data.strip() != '': # Resolve the target in exoMAST try: form.targname.data = get_canonical_name(form.targname.data) data, url = get_target_data(form.targname.data) # Update the coordinates ra_deg = data.get('RA') dec_deg = data.get('DEC') # Set the form values form.ra.data = ra_deg form.dec.data = dec_deg form.target_url.data = url except Exception: 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('contam_visibility.html', form=form) # Reload page with appropriate mode data if form.mode_submit.data: # Update the button if (form.inst.data == 'MIRI') or (form.inst.data == 'NIRSpec'): form.calculate_contam_submit.disabled = True else: form.calculate_contam_submit.disabled = False # Send it back to the main page return render_template('contam_visibility.html', form=form) if form.validate_on_submit() and (form.calculate_submit.data or form.calculate_contam_submit.data): try: # Log the form inputs try: log_exoctk.log_form_input(request.form, 'contam_visibility', DB) except Exception: pass # Make plot title = form.targname.data or ', '.join( [str(form.ra.data), str(form.dec.data)]) pG, pB, dates, vis_plot, table, badPAs = vpa.using_gtvt( str(form.ra.data), str(form.dec.data), form.inst.data.split(' ')[0], targetName=str(title)) # Make output table fh = StringIO() table.write(fh, format='csv', delimiter=',') visib_table = fh.getvalue() # Get scripts vis_js = INLINE.render_js() vis_css = INLINE.render_css() vis_script, vis_div = components(vis_plot) # Contamination plot too if form.calculate_contam_submit.data: # First convert ra and dec to HH:MM:SS ra_deg, dec_deg = float(form.ra.data), float(form.dec.data) sc = SkyCoord(ra_deg, dec_deg, unit='deg') ra_dec = sc.to_string('hmsdms') ra_hms, dec_dms = ra_dec.split(' ')[0], ra_dec.split(' ')[1] # Make field simulation contam_cube = fs.fieldSim(ra_hms, dec_dms, form.inst.data, binComp=form.companion.data) contam_plot = cf.contam( contam_cube, form.inst.data, targetName=str(title), paRange=[int(form.pa_min.data), int(form.pa_max.data)], badPAs=badPAs, fig='bokeh') # Get scripts contam_js = INLINE.render_js() contam_css = INLINE.render_css() contam_script, contam_div = components(contam_plot) else: contam_script = contam_div = contam_js = contam_css = '' return render_template('contam_visibility_results.html', form=form, vis_plot=vis_div, vis_table=visib_table, vis_script=vis_script, vis_js=vis_js, vis_css=vis_css, contam_plot=contam_div, contam_script=contam_script, contam_js=contam_js, contam_css=contam_css) except Exception as e: err = 'The following error occurred: ' + str(e) return render_template('groups_integrations_error.html', err=err) return render_template('contam_visibility.html', form=form)
def fortney(): """ Pull up Forntey Grid plot the results and download """ # Grab the inputs arguments from the URL args = flask.request.args temp, chem, cloud, pmass, m_unit, reference_radius, r_unit, rstar, rstar_unit = _param_fort_validation(args) # get sqlite database try: db = create_engine('sqlite:///' + FORTGRID_DIR) header = pd.read_sql_table('header', db) except: raise Exception('Fortney Grid File Path is incorrect, or not initialized') if args: rstar = float(rstar) rstar = (rstar * u.Unit(rstar_unit)).to(u.km) reference_radius = float(reference_radius) rplan = (reference_radius * u.Unit(r_unit)).to(u.km) # clouds if cloud.find('flat') != -1: flat = int(cloud[4:]) ray = 0 elif cloud.find('ray') != -1: ray = int(cloud[3:]) flat = 0 elif int(cloud) == 0: flat = 0 ray = 0 else: flat = 0 ray = 0 print('No cloud parameter not specified, default no clouds added') # chemistry if chem == 'noTiO': noTiO = True if chem == 'eqchem': noTiO = False # grid does not allow clouds for cases with TiO flat = 0 ray = 0 fort_grav = 25.0 * u.m / u.s**2 temp = float(temp) df = header.loc[(header.gravity == fort_grav) & (header.temp == temp) & (header.noTiO == noTiO) & (header.ray == ray) & (header.flat == flat)] wave_planet = np.array(pd.read_sql_table(df['name'].values[0], db)['wavelength'])[::-1] r_lambda = np.array(pd.read_sql_table(df['name'].values[0], db)['radius']) * u.km # All fortney models have fixed 1.25 radii z_lambda = r_lambda - (1.25 * u.R_jup).to(u.km) # Scale with planetary mass pmass = float(pmass) mass = (pmass * u.Unit(m_unit)).to(u.kg) # Convert radius to m for gravity units gravity = constants.G * (mass) / (rplan.to(u.m))**2.0 # Scale lambbda (this technically ignores the fact that scaleheight # is altitude dependent) therefore, it will not be valide for very # very low gravities z_lambda = z_lambda * fort_grav / gravity # Create new wavelength dependent R based on scaled ravity r_lambda = z_lambda + rplan # Finally compute (rp/r*)^2 flux_planet = np.array(r_lambda**2 / rstar**2) x = wave_planet y = flux_planet[::-1] else: df = pd.read_sql_table('t1000g25_noTiO', db) x, y = df['wavelength'], df['radius']**2.0 / 7e5**2.0 tab = at.Table(data=[x, y]) fh = StringIO() tab.write(fh, format='ascii.no_header') table_string = fh.getvalue() fig = figure(plot_width=1100, plot_height=400) fig.line(x, 1e6 * (y - np.mean(y)), color='Black', line_width=0.5) fig.xaxis.axis_label = 'Wavelength (um)' fig.yaxis.axis_label = 'Rel. Transit Depth (ppm)' js_resources = INLINE.render_js() css_resources = INLINE.render_css() script, div = components(fig) html = flask.render_template('fortney.html', plot_script=script, plot_div=div, js_resources=js_resources, css_resources=css_resources, temp=list(map(str, header.temp.unique())), table_string=table_string ) return encode_utf8(html)
def fortney_grid(args, write_plot=False, write_table=False): """ Function to grab a Fortney Grid model, plot it, and make a table. Parameters ---------- args : dict Dictionary of arguments for the Fortney Grid. Must include : temp chem cloud pmass m_unit reference_radius r_unit rstar rstar_unit write_plot : bool, optional Whether or not to save the bokeh plot, defaults to False. write_table : bool, optional Whether or not to save the ascii table, defaults to False. Returns ------- fig : bokeh object The unsaved bokeh plot. fh : ascii table object The unsaved ascii table. temp_out : list of str of int The list of temperatures in the model grid. """ # Check for Fortney Grid database print( os.path.join(get_env_variables()['exoctk_data'], 'fortney/fortney_models.db')) try: db = create_engine('sqlite:///' + os.path.join( get_env_variables()['exoctk_data'], 'fortney/fortney_models.db')) header = pd.read_sql_table('header', db) except: raise Exception( 'Fortney Grid File Path is incorrect, or not initialized') if args: rstar = float(args['rstar']) rstar = (rstar * u.Unit(args['rstar_unit'])).to(u.km) reference_radius = float(args['reference_radius']) rplan = (reference_radius * u.Unit(args['r_unit'])).to(u.km) temp = float(args['temp']) # clouds cloud = args['cloud'] if cloud.find('flat') != -1: flat = int(cloud[4:]) ray = 0 elif cloud.find('ray') != -1: ray = int(cloud[3:]) flat = 0 elif int(cloud) == 0: flat = 0 ray = 0 else: flat = 0 ray = 0 print('No cloud parameter not specified, default no clouds added') # chemistry chem = args['chem'] if chem == 'noTiO': noTiO = True if chem == 'eqchem': noTiO = False # grid does not allow clouds for cases with TiO flat = 0 ray = 0 fort_grav = 25.0 * u.m / u.s**2 df = header.loc[(header.gravity == fort_grav) & (header.temp == temp) & (header.noTiO == noTiO) & (header.ray == ray) & (header.flat == flat)] wave_planet = np.array( pd.read_sql_table(df['name'].values[0], db)['wavelength'])[::-1] r_lambda = np.array( pd.read_sql_table(df['name'].values[0], db)['radius']) * u.km # All fortney models have fixed 1.25 radii z_lambda = r_lambda - (1.25 * u.R_jup).to(u.km) # Scale with planetary mass pmass = float(args['pmass']) mass = (pmass * u.Unit(args['m_unit'])).to(u.kg) # Convert radius to m for gravity units gravity = constants.G * (mass) / (rplan.to(u.m))**2.0 # Scale lambbda (this technically ignores the fact that scaleheight # is altitude dependent) therefore, it will not be valide for very # very low gravities z_lambda = z_lambda * fort_grav / gravity # Create new wavelength dependent R based on scaled ravity r_lambda = z_lambda + rplan # Finally compute (rp/r*)^2 flux_planet = np.array(r_lambda**2 / rstar**2) x = wave_planet y = flux_planet[::-1] else: df = pd.read_sql_table('t1000g25_noTiO', db) x, y = df['wavelength'], df['radius']**2.0 / 7e5**2.0 tab = at.Table(data=[x, y]) fh = StringIO() tab.write(fh, format='ascii.no_header') if write_table: tab.write('fortney.dat', format='ascii.no_header') fig = figure(plot_width=1100, plot_height=400) fig.line(x, 1e6 * (y - np.mean(y)), color='Black', line_width=0.5) fig.xaxis.axis_label = 'Wavelength (um)' fig.yaxis.axis_label = 'Rel. Transit Depth (ppm)' if write_plot: output_file('fortney.html') save(fig) # Return temperature list for the fortney grid page temp_out = list(map(str, header.temp.unique())) return fig, fh, temp_out
def generic_grid(input_args, write_plot=False, write_table=False): """ Build a plot and table from the generic grid results. Parameters ---------- input_args : dict A dictionary of the form output from the generic grid form. If manual input must include : r_star : The radius of the star. r_planet : The radius of the planet. gravity : The gravity. temperature : The temperature. condensation : local or rainout metallicity c_o : carbon/oxygen ratio haze cloud write_plot : bool, optional Whether to write the plot out. Defaults to False. write_table : bool, optional Whether to write the table out. Defaults to Fals. Returns ------- plot : bokeh object Unsaved bokeh plot. table : ascii table object Unsaved ascii table. closest_match : dict A dictionary with the parameters/model name of the closest match in the grid. error_message : str An error message, or lack therof. """ # Find path to the database. database_path = os.path.join(get_env_variables()['exoctk_data'], 'generic/generic_grid_db.hdf5') # Build rescaled model solution, inputs, closest_match, error_message = rescale_generic_grid( input_args, database_path) # Build file out tab = at.Table(data=[solution['wv'], solution['spectra']]) fh = StringIO() tab.write(fh, format='ascii.no_header') if write_table: tab.write('generic.dat') # Plot fig = figure(title='Rescaled Generic Grid Transmission Spectra'.upper(), plot_width=1100, plot_height=400) fig.x_range.start = 0.3 fig.x_range.end = 5 fig.line(solution['wv'], solution['spectra'], color='Black', line_width=1) fig.xaxis.axis_label = 'Wavelength (um)' fig.yaxis.axis_label = 'Transit Depth (Rp/R*)^2' if write_plot: output_file('generic.html') save(fig) return fig, fh, closest_match, error_message