Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 87 additions & 18 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,87 @@
astrodbkit>=2.2
astropy>=5.2.0,<6
bokeh==3.0.2
flask>=3.0,<4
flask-cors>=4.0,<5
flask-wtf>=1.2,<2
markdown2>=2.4,<3
multiprocess>=0.70,<1
numpy>=1.24,<2
pandas>=2.0,<2.1
pysqlite3>=0.5,<1
pytest>=8.0,<9
requests>=2.31,<3
specutils>=1.12,<2
sqlalchemy>=2.0,<3
tqdm>=4.66,<5
werkzeug>=3.0,<4
wtforms>=3.1,<4
antiorm==1.2.1
asdf==4.1.0
asdf-astropy==0.7.0
asdf_coordinates_schemas==0.3.0
asdf_standard==1.1.1
asdf_transform_schemas==0.5.0
asdf_wcs_schemas==0.4.0
astrodbkit==2.2
astropy==5.3.4
astroquery==0.4.9.post1
attrs==25.1.0
backports.tarfile==1.2.0
beautifulsoup4==4.13.3
blinker==1.9.0
bokeh==3.7.3
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
contourpy==1.3.1
cryptography==44.0.0
db==0.1.1
db-sqlite3==0.0.1
dill==0.3.9
distlib==0.3.9
distro==1.9.0
filelock==3.16.1
Flask==3.1.0
Flask-Cors==4.0.2
Flask-WTF==1.2.2
greenlet==3.1.1
gwcs==0.21.0
html5lib==1.1
idna==3.10
importlib_metadata==8.6.1
iniconfig==2.0.0
iniparse==0.5
itsdangerous==2.2.0
jaraco.classes==3.4.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jeepney==0.8.0
Jinja2==3.1.5
jmespath==1.0.1
keyring==25.6.0
markdown2==2.5.3
MarkupSafe==3.0.2
more-itertools==10.6.0
multiprocess==0.70.17
narwhals==1.41.0
ndcube==2.3.0
numpy==1.26.4
packaging==24.2
pandas==2.0.3
pathlib2==2.3.7.post1
pillow==11.1.0
platformdirs==4.3.6
pluggy==1.5.0
pycparser==2.22
pyerfa==2.0.1.5
PyMySQL==1.1.1
pyOpenSSL==24.3.0
pysqlite3==0.5.4
pytest==8.3.4
python-dateutil==2.9.0.post0
pytz==2024.2
pyvo==1.6
PyYAML==6.0.2
requests==2.32.3
scipy==1.15.1
SecretStorage==3.3.3
semantic-version==2.10.0
six==1.17.0
soupsieve==2.6
specutils==1.19.0
SQLAlchemy==2.0.38
tornado==6.4.2
tqdm==4.67.1
typing_extensions==4.12.2
tzdata==2025.1
urllib3==2.3.0
virtualenv==20.28.0
webencodings==0.5.1
Werkzeug==3.1.3
WTForms==3.2.1
xyzservices==2025.1.0
zipp==3.21.0
57 changes: 40 additions & 17 deletions simple_app/app_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ def search():
if (query := form.search.data) is None: # content in main searchbar
query = ''

curdoc().template_variables['query'] = query # add query to bokeh curdoc
curdoc().template_variables['ref_query'] = ref_query # add query to bokeh curdoc
session['query'] = query # add query to bokeh curdoc
session['ref_query'] = ref_query # add query to bokeh curdoc
db = SimpleDB(db_file) # open database

# object search function
Expand Down Expand Up @@ -96,7 +96,7 @@ def coordinate_query():
if (query := form.query.data) is None:
query = ''

curdoc().template_variables['query'] = query
session['query'] = query
db = SimpleDB(db_file)

# parse query into ra, dec, radius
Expand Down Expand Up @@ -127,7 +127,7 @@ def full_text_search():
query = ''
limmaxrows = True

curdoc().template_variables['query'] = query
session['query'] = query
db = SimpleDB(db_file)

# search through the tables using the given query
Expand Down Expand Up @@ -160,14 +160,14 @@ def raw_query():
if (query := form.sqlfield.data) is None:
query = ''

curdoc().template_variables['query'] = query
session['query'] = query

# attempt to query the database
try:
results: Optional[pd.DataFrame] = db.sql_query(query, fmt='pandas')

# catch any broken queries (should not activate as will be caught by validation)
except (ResourceClosedError, OperationalError, IndexError, SqliteWarning, BadSQLError):
except (ResourceClosedError, OperationalError, IndexError, SqliteWarning, BadSQLError, ProgrammingError):
results = pd.DataFrame()

results = reference_handle(results, db_file, True)
Expand All @@ -188,7 +188,7 @@ def solo_result(query: str):
query: str
The query -- full match to a main ID
"""
curdoc().template_variables['query'] = query
session['query'] = query
db = SimpleDB(db_file)

# search database for given object
Expand All @@ -199,6 +199,7 @@ def solo_result(query: str):
except KeyError:
abort(404, f'"{query}" does match any result in SIMPLE!')
return

everything = Inventory(resultdict, db_file)

# create camd and spectra plots
Expand Down Expand Up @@ -283,7 +284,7 @@ def create_file_for_download(key: str):
key: str
The dataframe string
"""
query = curdoc().template_variables['query']
query: str = session.get('query')
db = SimpleDB(db_file)

# search for a given object and a given key
Expand All @@ -305,7 +306,7 @@ def create_files_for_solo_download():
"""
Creates and downloads all dataframes from solo results
"""
query = curdoc().template_variables['query']
query = session.get('query')
db = SimpleDB(db_file)

# search for a given object
Expand All @@ -328,7 +329,7 @@ def create_spectra_files_for_download():
"""
Downloads the spectra files and zips together
"""
query = curdoc().template_variables['query']
query = session.get('query')
db = SimpleDB(db_file)

# search for a given object and specifically its spectra
Expand All @@ -346,13 +347,35 @@ def create_spectra_files_for_download():
abort(400, 'Could not download fits')


@app_simple.route('/write_multi_spectra', methods=['GET'])
def create_multi_spectra_files_for_download():
"""
Downloads the spectra files and zips together
"""
query = session.get('query')
db = SimpleDB(db_file)

# search for the spectra within a given free search
resultdict: Dict[str, pd.DataFrame] = db.search_string(query, fmt='pandas', verbose=False)
spectra_df: pd.DataFrame = resultdict['Spectra']

# write all spectra for object to zipped file
zipped = write_spec_files(spectra_df.access_url.values)
if zipped is not None:
response = Response(zipped, mimetype='application/zip')
response = control_response(response, app_type='zip')
return response

abort(400, 'Could not download fits')


@app_simple.route('/write_filt', methods=['GET'])
def create_file_for_filtered_download():
"""
Creates and downloads the shown dataframe when in filtered search
"""
query = curdoc().template_variables['query']
refquery = curdoc().template_variables['ref_query']
query = session.get('query')
refquery = session.get('ref_query')
db = SimpleDB(db_file)

# search for a given object and a full text search at the same time
Expand All @@ -375,7 +398,7 @@ def create_file_for_coordinate_download():
"""
Creates and downloads the shown dataframe when in coordinate search
"""
query = curdoc().template_variables['query']
query = session.get('query')
db = SimpleDB(db_file)

# query the database for given coordinates and parse those coordinates
Expand All @@ -401,12 +424,12 @@ def create_file_for_full_download(key: str):
key: str
The dataframe string
"""
query = curdoc().template_variables['query']
query = session.get('query')
db = SimpleDB(db_file)

# search database with a free-text search and specific table
resultdict: Dict[str, pd.DataFrame] = db.search_string(query, fmt='pandas', verbose=False)

print(query, key, resultdict.keys())
# write to csv
if key in resultdict:
results: pd.DataFrame = resultdict[key]
Expand All @@ -422,7 +445,7 @@ def create_files_for_multi_download():
"""
Creates and downloads all dataframes from full results
"""
query = curdoc().template_variables['query']
query = session.get('query')
db = SimpleDB(db_file)

# search with full-text search
Expand All @@ -439,7 +462,7 @@ def create_file_for_sql_download():
"""
Creates and downloads the shown dataframe when in sql query
"""
query = curdoc().template_variables['query']
query = session.get('query')
db = SimpleDB(db_file)

# query database via sql
Expand Down
32 changes: 20 additions & 12 deletions simple_app/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,14 @@ def sky_plot() -> figure:
_p_sky = figure(title='Sky Plot', outer_height=500,
active_scroll='wheel_zoom', active_drag='box_zoom',
tools='pan,wheel_zoom,box_zoom,box_select,reset',
sizing_mode='stretch_width', x_range=[-180, 180], y_range=[-90, 90])
sizing_mode='stretch_width', x_range=Range1d(-180, 180), y_range=Range1d(-90, 90))

# background for skyplot
_p_sky.ellipse(x=0, y=0, width=360, height=180, color='#444444', name='background')

# scatter plot for sky plot
circle = _p_sky.circle(source=full_cds, x='ra_projected', y='dec_projected',
size=6, name='circle', color='ghostwhite')
circle = _p_sky.scatter(marker='circle', source=full_cds, x='ra_projected', y='dec_projected',
size=6, name='circle', color='ghostwhite')

# bokeh tools for sky plot
this_hover = HoverTool(renderers=[circle, ], tooltips=tooltips)
Expand All @@ -367,7 +367,8 @@ def colour_colour_plot() -> Tuple[figure, Toggle, Toggle, Select, Select]:
_p_colour_colour = bokeh_formatter(_p_colour_colour)

# scatter plot for colour-colour
full_plot = _p_colour_colour.circle(x=x_full_name, y=y_full_name, source=full_cds, size=6, color=cmap)
full_plot = _p_colour_colour.scatter(marker='circle', x=x_full_name, y=y_full_name, source=full_cds, size=6,
color=cmap)

# colour bar for colour-colour plot
cbar = ColorBar(color_mapper=cmap['transform'], label_standoff=12,
Expand Down Expand Up @@ -395,6 +396,8 @@ def colour_colour_plot() -> Tuple[figure, Toggle, Toggle, Select, Select]:
args={'full_plot': full_plot, 'full_data': full_cds.data,
'y_button': _button_y_flip, 'y_axis': _p_colour_colour.yaxis[0],
'y_range': _p_colour_colour.y_range}))
_p_colour_colour.js_on_event('reset', CustomJS(args=dict(dropdown_x=_dropdown_x, dropdown_y=_dropdown_y),
code=js_callbacks.reset_dropdown))
return _p_colour_colour, _button_x_flip, _button_y_flip, _dropdown_x, _dropdown_y

def colour_absolute_magnitude_diagram() -> Tuple[figure, Toggle, Toggle, Select, Select]:
Expand All @@ -413,7 +416,8 @@ def colour_absolute_magnitude_diagram() -> Tuple[figure, Toggle, Toggle, Select,
_p_camd = bokeh_formatter(_p_camd)

# scatter plot for camd
full_mag_plot = _p_camd.circle(x=x_full_name, y=y_full_name, source=full_cds, size=6, color=cmap)
full_mag_plot = _p_camd.scatter(marker='circle', x=x_full_name, y=y_full_name, source=full_cds, size=6,
color=cmap)

# colour bar for camd
cbar = ColorBar(color_mapper=cmap['transform'], label_standoff=12,
Expand All @@ -439,6 +443,8 @@ def colour_absolute_magnitude_diagram() -> Tuple[figure, Toggle, Toggle, Select,
args={'full_plot': full_mag_plot,
'full_data': full_cds.data, 'y_button': _button_mag_y_flip,
'y_axis': _p_camd.yaxis[0], 'y_range': _p_camd.y_range}))
_p_camd.js_on_event('reset', CustomJS(args=dict(dropdown_x=_dropdown_mag_x, dropdown_y=_dropdown_mag_y),
code=js_callbacks.reset_dropdown))
return _p_camd, _button_mag_x_flip, _button_mag_y_flip, _dropdown_mag_x, _dropdown_mag_y

# gather all necessary data including parallaxes, spectral types and bands
Expand Down Expand Up @@ -491,8 +497,8 @@ def colour_absolute_magnitude_diagram() -> Tuple[figure, Toggle, Toggle, Select,
absmagnames = absmagnames[~np.isin(absmagnames, bad_cols)]
absmag_shown_name = [name_simplifier(mag) for mag in absmagnames]
dropdown_menu_mag = [*zip(absmagnames, absmag_shown_name)]
y_full_name = absmagnames[0]
y_shown_name = absmag_shown_name[0]
y_full_name = absmagnames[1]
y_shown_name = absmag_shown_name[1]

# camd plot
p_camd, button_mag_x_flip, button_mag_y_flip, dropdown_mag_x, dropdown_mag_y = colour_absolute_magnitude_diagram()
Expand Down Expand Up @@ -650,13 +656,13 @@ def camd_plot(query: str, everything: Inventory, all_bands: np.ndarray, all_resu

# scatter plot for given object
this_cds = ColumnDataSource(data=this_photometry)
this_plot = p.square(x=x_full_name, y=y_full_name, source=this_cds,
color=cmap, size=20) # plot for this object
this_plot = p.scatter(marker='square', x=x_full_name, y=y_full_name, source=this_cds,
color=cmap, size=20) # plot for this object

# scatter plot for all data
cds_full = ColumnDataSource(data=all_results_full) # bokeh cds object
full_plot = p.circle(x=x_full_name, y=y_full_name, source=cds_full,
color=cmap, alpha=0.5, size=6) # plot all objects
full_plot = p.scatter(marker='circle', x=x_full_name, y=y_full_name, source=cds_full,
color=cmap, alpha=0.5, size=6) # plot all objects
full_plot.level = 'underlay' # put full plot underneath this plot

# colour bar
Expand All @@ -683,6 +689,8 @@ def camd_plot(query: str, everything: Inventory, all_bands: np.ndarray, all_resu
args={'full_plot': full_plot, 'this_plot': this_plot,
'full_data': cds_full.data, 'y_button': button_y_flip,
'y_axis': p.yaxis[0], 'y_range': p.y_range}))
p.js_on_event('reset', CustomJS(args=dict(dropdown_x=dropdown_x, dropdown_y=dropdown_y),
code=js_callbacks.reset_dropdown))

# creating bokeh layout and html
plots = column(p, row(dropdown_x,
Expand All @@ -705,6 +713,6 @@ def main_plots():


if __name__ == '__main__':
ARGS, DB_FILE, PHOTOMETRIC_FILTERS, ALL_RESULTS, ALL_RESULTS_FULL, VERSION_STR,\
ARGS, DB_FILE, PHOTOMETRIC_FILTERS, ALL_RESULTS, ALL_RESULTS_FULL, VERSION_STR, \
ALL_PHOTO, ALL_BANDS, ALL_PLX, ALL_SPTS = main_utils()
NIGHTSKYTHEME, JSCALLBACKS = main_plots()
11 changes: 11 additions & 0 deletions simple_app/simple_callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,15 @@ function reset_slider (spectra_slide) {
spectra_slide.value = [0.81, 0.82];
spectra_slide.change.emit();

}

function reset_dropdown(dropdown_x, dropdown_y) {

// resetting the dropdown columns when reset button pressed
dropdown_x.value = dropdown_x.options[0][0];
dropdown_y.value = dropdown_y.options[1][0];

dropdown_x.change.emit();
dropdown_y.change.emit();

}
Loading