Browse Source

Parallelized figs. World Map added. Typo fixed

pull/1/head
Benito Marcote 6 months ago
parent
commit
36f4256e21
  1. 29
      app.py
  2. 28
      vlbiplanobs/graphical_elements.py
  3. 2
      vlbiplanobs/stations.py

29
app.py

@ -19,8 +19,11 @@ import os
from os import path
from time import sleep
import itertools
import functools
from importlib import resources
import multiprocessing as mp
import datetime
# import time
from datetime import datetime as dt
import numpy as np
import dash
@ -96,6 +99,8 @@ app = dash.Dash(__name__, title='EVN Observation Planner', external_scripts=exte
app.config.suppress_callback_exceptions = True # Avoids error messages for id's that haven't been loaded yet
server = app.server
def smap(f):
return f()
def get_doc_text():
"""Reads the doc files and returns it as a Div object.
@ -183,7 +188,6 @@ def update_sensitivity(obs):
with information about the observation.
"""
cards = []
# The time card
cards += ge.summary_card_times(app, obs)
cards += ge.summary_card_frequency(app, obs)
cards += ge.summary_card_antennas(app, obs)
@ -191,7 +195,11 @@ def update_sensitivity(obs):
cards += ge.summary_card_rms(app, obs)
cards += ge.summary_card_fov(app, obs)
return [html.Div(className='card-deck col-12 justify-content-center',
children=cards)]
children=cards),
html.Br(),
html.Div(style={'height': '5rem'}),
html.Div(className='col-12 justify-content-center',
children=ge.summary_card_worldmap(app, obs))]
def arrays_with_band(arrays, a_band):
@ -415,7 +423,6 @@ def intro_choices(clicks_pickband, clicks_picknetwork, clicks_picktimes, clicks_
elif clicks_pickband is not None:
return choice_page('time'), dash.no_update
elif clicks_picktimes is not None:
#TODO: if dates are provided, all date/time/dur must be provided
return choice_page('mode'), dash.no_update
elif clicks_continuum is not None:
return choice_page('final'), False
@ -1203,15 +1210,19 @@ def compute_observation(n_clicks, band, starttime, starthour, duration, source,
dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, \
dash.no_update, dash.no_update, dash.no_update, dash.no_update
# TODO: parallelize all these fig functions
with mp.Pool() as pool:
output_figs = pool.map(smap,
[functools.partial(get_fig_ant_elev, obs),
functools.partial(get_fig_ant_up, obs),
functools.partial(get_fig_uvplane, obs),
functools.partial(get_fig_dirty_map, obs)])
if out_center:
return '', '', False, True, sensitivity_results, get_fig_ant_elev(obs), \
get_fig_ant_up(obs), get_fig_uvplane(obs), get_fig_dirty_map(obs), dash.no_update, \
return '', '', False, True, sensitivity_results, *list(output_figs), dash.no_update, \
'tab-summary', False, False, False
else:
return '', dbc.Alert("Results have been updated.", color='info', dismissable=True), False, True, \
sensitivity_results, get_fig_ant_elev(obs), get_fig_ant_up(obs), get_fig_uvplane(obs), \
get_fig_dirty_map(obs), dash.no_update, \
sensitivity_results, *list(output_figs), dash.no_update, \
dash.no_update, False, False, False
@ -1222,7 +1233,7 @@ def get_fig_ant_elev(obs):
# Some reference lines at low elevations
for ant in data_dict:
data_fig.append({'x': obs.times.datetime, 'y': data_dict[ant].value,
'mode': 'lines', 'hovertemplate': "Elev: %{y:.2n}º (%{x})",
'mode': 'lines', 'hovertemplate': "Elev: %{y:.2n}º<br>%{x}",
'name': obs.stations[ant].name})
data_fig.append({'x': obs.times.datetime, 'y': np.zeros_like(obs.times)+10,

28
vlbiplanobs/graphical_elements.py

@ -129,6 +129,19 @@ def network_card(app, network_acr, network_name, body, network_img=None):
def summary_card_worldmap(app, obs):
"""Generates a world map with the participating stations
"""
ants_up = obs.is_visible()
ant_no_obs = []
for an_ant in ants_up:
if len(ants_up[an_ant][0]) == 0:
ant_no_obs.append(an_ant)
return worldmap_plot([obs.stations[a] for a in obs.stations.codenames \
if a not in ant_no_obs])
def summary_card_antennas(app, obs):
"""Generates the summary card with the information about which
antennas can observe the given source, and the longest/shortest baselines.
@ -152,9 +165,6 @@ def summary_card_antennas(app, obs):
ant_text[-1] = html.Span(".")
else:
ant_text = ["None."]
# TODO: This is the worldmap... I think it does not fit here.
# temp_msg = [ge.worldmap_plot([obs.stations[a] for a in obs.stations.keys() \
# if a not in ant_no_obs])]
temp_msg = []
temp_msg += [[f"{len(ants_up)-len(ant_no_obs)} participating antennas: ", *ant_text]]
if len(ant_no_obs) > 0:
@ -206,7 +216,6 @@ def summary_card_beam(app, obs):
children=[ellipse(bmaj="5rem",
bmin=f"{5*synthbeam['bmin'].to(u.mas)/synthbeam['bmaj'].to(u.mas)}rem",
pa=f"{-synthbeam['pa'].to(u.deg).value+90}deg")])]
# TODO: Check that the rotation is the correct.
temp_msg += [html.Br(), html.P([f"The expected synthesized beam will be approx. {synthbeam['bmaj'].to(synthbeam_units).value:.3n} x {synthbeam['bmin'].to(synthbeam_units):.3n}", html.Sup("2"), \
f", PA = {synthbeam['pa']:.3n}."])]
temp_msg += [html.P("Note that the synthesized beam can significantly change depending "
@ -375,18 +384,19 @@ def baseline_img(app, is_long=True):
def worldmap_plot(antennas):
data = {"lat": [], "lon": [], "color": [], "symbol": [], "mode": "markers",
"name": [], "hovertext": []}
"name": [], "text": [], "hovertemplate": []}
for ant in antennas:
data["lat"].append(ant.location.lat.value)
data["lon"].append(ant.location.lon.value)
data["color"].append('green')
data["symbol"].append(0.1)
data["name"].append(ant.name)
data["hovertext"].append(ant.name)
data["text"].append(f"{ant.name}<br>({ant.country})<br> {ant.diameter}")
data["hovertemplate"].append(f"{ant.name}<br>({ant.country})<br> {ant.diameter}")
fig = px.scatter_geo(data,
lat="lat", lon="lon", color="color", text="hovertext",
hover_name="name")
lat="lat", lon="lon", text="name",
hover_name="text", hover_data=None)
fig.update_layout(autosize=True, hovermode='closest', showlegend=False,
margin={'l': 0, 't': 0, 'b': 0, 'r': 0})
@ -563,7 +573,7 @@ def initial_window_pick_time():
]),
html.Span(style={'height': '5rem'}),
html.Div(className='row justify-content-center', children=[
html.H3('Introduce you target source'),
html.H3('Introduce your target source'),
html.P(["Enter the coordinates or (Simbad-recognized) name of the source you want to observe. ",
html.Br(),
"J2000 coordinates are assumed in both recognized forms: 00:00:00 00:00:00 or "

2
vlbiplanobs/stations.py

@ -403,7 +403,7 @@ class Stations(object):
def codenames(self) -> tuple:
"""Returns a tuple with the `codenames` from all the stations in the network.
"""
return self._codenames
return tuple(self._codenames)
@property

Loading…
Cancel
Save