Browse Source

Text and graphical small tweaks

tags/v2.0.2
Benito Marcote 8 months ago
parent
commit
c64976c03e
5 changed files with 52 additions and 44 deletions
  1. +29
    -26
      app.py
  2. +6
    -0
      assets/style.css
  3. +3
    -3
      doc/doc-antennas.md
  4. +8
    -9
      vlbiplanobs/graphical_elements.py
  5. +6
    -6
      vlbiplanobs/observation.py

+ 29
- 26
app.py View File

@@ -92,7 +92,7 @@ for a_array in default_arrays:
for a_station in default_arrays[a_array]:
assert a_station in all_antennas.codenames

doc_files = {'About this tool': 'doc-contact.md',
doc_files = {'About the EVN Observation Planner': 'doc-contact.md',
'About the antennas': 'doc-antennas.md',
'Technical background': 'doc-estimations.md'}

@@ -198,9 +198,9 @@ def update_sensitivity(obs):
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)
cards += ge.summary_card_beam(app, obs)
cards += ge.summary_card_frequency(app, 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)]
@@ -258,16 +258,16 @@ app.layout = html.Div([
html.Div(className='row justify-content-center',
children=html.Div(className='col-sm-6 justify-content-center',
children=[html.Div(className='justify-content-center',
children=[html.P(["This tool allows you to plan observations with the ",
children=[html.P(["Welcome to the EVN Observation Planner!", html.Br(),
"This tool allows you to plan observations with the ",
html.A(href="https://www.evlbi.org", children="European VLBI Network"),
" (EVN) and other Very Long Baseline Interferometry (VLBI) networks. "
"This tool allows you to determine when you can schedule the observation "
"of a given source (e.g. when it is visible in the sky "
"for the different antennas), and estimating the outcome of the observation "
"(e.g. reached resolution or sensitivity)."]),
"The EVN Observation Planner helps you to determine when your source "
"can be observed by the different antennas, and provides the expected "
"outcome of these observation, like the expected sensitivity or resolution."]),

html.P(["First, ", html.B("pick the band (wavelength or frequency)"),
" at which you want to observe. "
html.P([html.B("Pick the observing band first"),
" to be able to continue. "
"Note that you will still be able to change your selection afterwards "
"in case you want to compare different bands."])
], style={'text:align': 'justify !important'}),
@@ -401,9 +401,10 @@ def update_onsourcetime_label(n_clicks, a_wavelength):
html.Div(className='form-group', children=[
html.Label('Source (name or coordinates)'),
*ge.tooltip(idname='popover-target',
message="Right Ascension and Declination of the source " \
"J2000 coordinates are assumed. Both, 00:00:00 00:00:00 and " \
"00h00m00s 00d00m00s syntaxes are allowed."),
message="Source name or coordinates. " \
"You may see an error if the given name is not properly resolved. "
"J2000 coordinates are assumed in both forms: 00:00:00 00:00:00 or " \
"00h00m00s 00d00m00s."),
# dcc.Input(id='source', value='12:29:06.7 +02:03:08.6', type='text',
dcc.Input(id='source', value=None, type='text',
className='form-control', placeholder="hh:mm:ss dd:mm:ss",
@@ -443,8 +444,8 @@ def update_onsourcetime_label(n_clicks, a_wavelength):
html.Div(className='form-group', children=[
html.Label('Number of subbands'),
*ge.tooltip(idname='popover-subbands',
message="Number of subbands the total observed bandwidth "
"will be split during correlation."),
message="Number of subbands to split the total observed bandwidth "
" during correlation (IFs in AIPS)."),
dcc.Dropdown(id='subbands', placeholder="Select no. subbands...",
options=[{'label': fs.subbands[sb], 'value': sb} \
for sb in fs.subbands], value=8, persistence=True),
@@ -481,15 +482,17 @@ def update_onsourcetime_label(n_clicks, a_wavelength):
]),
html.Div(className='col-9', children=[
html.Div(id='first-advise', className='col-sm-9', children=[
html.P(["This is the ", html.B("EVN Observation Planner"),
". Once you have selected the "
"band (frequency/wavelength) at which you want to observe, "
"you can customize your observation setup (left options and "
"select required antennas). Finally, "
"run ", html.B("'compute observation'"),
". You will get a detailed "
"summary of the planned observation (like when the source "
"is visible, expected rms noise level, etc.) in the different "
html.P(["Here you can set up your observation.", html.Br(),
"Please select which network (or networks) you want to use in your "
"observations, or select a customized array of antennas. "
"On the left you can set the basic information from your observations: "
"times of the observations and target source to observe. ", html.Br(),
"Optionally, you can customize the configuration and correlation parameters "
"under 'advance setup'. Otherwise, default values based on your selection "
"will be used.", html.Br(),
"Once you are ready, press the big red ", html.B("'compute observation'"),
" button. You will get a detailed "
"summary of the planned observation and expected outcomes in the different "
"tabs."]),
html.P(["Note that only antennas that can observe at the selected band "
"will be clickable."])
@@ -499,10 +502,10 @@ def update_onsourcetime_label(n_clicks, a_wavelength):
html.Label('Select default VLBI Network(s)',
style={'color': '#a01d26'}),
*ge.tooltip(idname='popover-network', message="Automatically selects "
"the default antennas for the selected VLBI network(s)."),
"the default participating antennas for the selected VLBI network(s)."),
dcc.Dropdown(id='array', options=[{'label': n, 'value': n} \
for n in default_arrays if n != 'e-EVN'], value=[],
multi=True),
persistence=True, multi=True),
]),
html.Div(className='col-sm-3', children=[
html.Button('Compute Observation', id='antenna-selection-button',
@@ -587,7 +590,7 @@ def update_onsourcetime_label(n_clicks, a_wavelength):
html.P("""The following plot shows when the source may be observed
for the different antennas, assuming a minimum elevation of 10 degrees
for most antennas (except e.g. Arecibo). Note that some antennas may
have additional constraints por some particular azimuth or elevation
have additional constraints for particular azimuth or elevation
angles that are not considered here.
""")
]),


+ 6
- 0
assets/style.css View File

@@ -3754,6 +3754,12 @@ img[alt=equation2] {
margin-bottom: 0px;
}

.card.card-antenna .card-text {
margin-bottom: 0.5rem;
position: absolute;
bottom: 0.5rem;
}

.popover-link {
color: #a01d26;
}


+ 3
- 3
doc/doc-antennas.md View File

@@ -3,14 +3,14 @@

This tool has been written with a main focus on observations with the [European VLBI Network](https://www.evlbi.org) (EVN). This implies that some stations, which can also belong to other networks, are placed under the EVN group to avoid duplicates. The network selection would select them when required in any case.

Note that through EVN proposals any user can also apply for the participation of other networks like the VLBA, KVN, or eMERLIN. See [the documentation at the EVN webpage](https://www.evlbi.org/using-evn) for more information.
Note that through EVN proposals any user can also apply for the participation of other networks like the VLBA, KVN, or eMERLIN. See [the documentation at the EVN webpage](https://www.evlbi.org/using-evn) for more information. Arrangement of observations where multiple networks are participating is also possible by submitting their respective proposals and coorinating the different time allocation committees (TACs). In any case, the EVN Observation Planner can be used for planning any VLBI observation.


#### Connected interferometers

Connected interferometers as the Karl G. Jansky VLA, the Australian Telescope Compact Array (ATCA), the Giant Metrewave Radio Telescope (GMRT), or the Atacama Large Millimeter/submillimeter Array (ALMA) can operate with a single antenna or phasing up the entire array.

Right now we only provide the two options for the VLA (VLA 1, or VLA 27, respectively), for further information [see the VLA in VLBI reference at the NRAO site](https://science.nrao.edu/facilities/vla/docs/manuals/obsguide/modes/vlbi). For the rest of connected interferometers this tool assumes that the entire array is being used.
Right now we only provide the two options for the VLA (VLA 1, or VLA 27, respectively; for further information [see the VLA in VLBI reference at the NRAO site](https://science.nrao.edu/facilities/vla/docs/manuals/obsguide/modes/vlbi)). For the rest of connected interferometers this tool assumes that the entire (phased-up) array is being used.

In the case of ALMA we consider the participation of all 37 telescopes that can be available for VLBI use.

@@ -18,7 +18,7 @@ In the case of ALMA we consider the participation of all 37 telescopes that can

#### Brief summary from all antennas

A brief summary of all antennas can be shown in the following. Note that all images have been obtained from [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page).
A brief summary of all antennas is shown in the following. Note that all images have been obtained from [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page).





+ 8
- 9
vlbiplanobs/graphical_elements.py View File

@@ -81,10 +81,9 @@ def antenna_card(app, station):
html.Span(station.diameter, style={'float': 'right'}),
], className='card-subtitle'),
# html.P(f"🇦 Participates in {station.all_networks}.\n"
dcc.Markdown(f"Listed for the {s(station.all_networks)}.\n" if \
station.all_networks != '' else '', className='card-text'),
dcc.Markdown("Can observe at "
f"{', '.join([i.replace('cm', '') for i in station.bands])} cm.",
dcc.Markdown([f"Listed for the {s(station.all_networks)}.\n" if \
station.all_networks != '' else '', "Can observe at "
f"{', '.join([i.replace('cm', '') for i in station.bands])} cm."],
className='card-text')
])
], className='card-antenna')
@@ -249,14 +248,14 @@ def summary_card_fov(app, obs):
smearing_ratio = smearing_ratio if smearing_ratio <= 1.0 else 1/smearing_ratio

temp_msg = [html.Div(className='row', style={'height': '1rem'}),
html.Div(className='row justify-content-center',
html.Div(className='row justify-content-center align-self-center',
children=[ellipse(bmaj="5rem", bmin="5rem", pa="0deg"),
ellipse(bmaj=f"2rem", bmin=f"2rem", pa="0deg", color="#F0959B",
z_index=3, position='absolute', margin_top='7%'),
z_index=3, position='absolute', className='align-self-center'),
ellipse(bmaj=f"{2*smearing_ratio}rem",
bmin=f"{2*smearing_ratio}rem",
pa="0deg", color="white", z_index=4, position='absolute',
margin_top=f'{8+2*bw_smearing/tm_smearing}%')])]
className='align-self-center')])]
temp_msg += [f"The Field of View would be limited by time smearing to {optimal_units(tm_smearing, [u.arcmin, u.arcsec]):.3n} and by frequency smearing to {optimal_units(bw_smearing, [u.arcmin, u.arcsec]):.3n} (considering a 10% loss)."]
temp_msg += [f"Considering the shortest baseline in the array, "
"you will filter out emission on angular scales larger than "
@@ -290,7 +289,7 @@ def summary_card_rms(app, obs):
# Some small graphical elements


def ellipse(bmaj, bmin, pa, color='#a01d26', z_index=1, position='relative', margin_top=''):
def ellipse(bmaj, bmin, pa, color='#a01d26', z_index=1, position='relative', margin_top='', className=''):
"""Returns a html.Div element that draws an ellipse with a semimajor axis bmaj,
semiminor axis bmin, and position angle (as defined in radio astronomy) pa.
bmaj,bmin, pa must be strings recognized by HTML/CSS.
@@ -298,7 +297,7 @@ def ellipse(bmaj, bmin, pa, color='#a01d26', z_index=1, position='relative', mar
return html.Div(children=[], style={'width': bmaj, 'height': bmin,
'border-radius': '50%', 'background': color, 'position': position,
'transform': f"rotate({pa})", 'z-index': z_index,
'vertical-align': 'middle', 'margin-top': margin_top})
'vertical-align': 'middle', 'margin-top': margin_top}, className=className)


def baseline_img(app, is_long=True):


+ 6
- 6
vlbiplanobs/observation.py View File

@@ -761,15 +761,15 @@ class Observation(object):
"""Returns the time range (starttime-to-endtime) of the observation in a smart way.
If the observation lasts for less than one day it omits the end date:
20 January 1971 10:00-20:00 UTC
GST: 05:00-15:00
GST range: 05:00-15:00

If the observation ends the day after, then it returns:
20 January 1971 10:00-20:00 UTC (+1d)
GST: 05:00-15:00
GST range: 05:00-15:00

If the observation is longer, then it returns
20 January 1971 10:00 to 24 January 1971 20:00 UTC
GST: 05:00-15:00
GST range: 05:00-15:00

Input:
- date_format : str [OPTIONAL]
@@ -784,16 +784,16 @@ class Observation(object):
(self.gstimes[-1].hour*60) // 60,
(self.gstimes[0].hour*60) % 60)
if self.times[0].datetime.date() == self.times[-1].datetime.date():
return "{}\n{}-{} UTC\nGST: {}".format(self.times[0].datetime.strftime(date_format),
return "{} {}-{} UTC\nGST range: {}".format(self.times[0].datetime.strftime(date_format),
self.times[0].datetime.strftime('%H:%M'),
self.times[-1].datetime.strftime('%H:%M'), gsttext)
elif (self.times[-1] - self.times[0]) < 24*u.h:
return "{}\n{}-{} UTC (+1d)\nGST: {}".format(
return "{} {}-{} UTC (+1d)\nGST range: {}".format(
self.times[0].datetime.strftime(date_format),
self.times[0].datetime.strftime('%H:%M'),
self.times[-1].datetime.strftime('%H:%M'), gsttext)
else:
return "{} {} to {} {} UTC\nGST: {}".format(
return "{} {} to {} {} UTC\nGST range: {}".format(
self.times[0].datetime.strftime(date_format),
self.times[0].datetime.strftime('%H:%M'),
self.times[-1].datetime.strftime(date_format),


Loading…
Cancel
Save