Browse Source

Added documentation

tags/v1.0
Benito Marcote 1 year ago
parent
commit
184898187b
10 changed files with 257 additions and 25 deletions
  1. +75
    -20
      app.py
  2. BIN
      assets/eq-datarate.png
  3. BIN
      assets/eq-noise.png
  4. +106
    -4
      assets/style.css
  5. +22
    -0
      doc/doc-antennas.md
  6. +17
    -0
      doc/doc-contact.md
  7. +24
    -0
      doc/doc-estimations.md
  8. +13
    -1
      doc/documentation.md
  9. BIN
      doc/noise.png
  10. BIN
      src/__pycache__/functions.cpython-36.pyc

+ 75
- 20
app.py View File

@@ -56,7 +56,7 @@ current_directory = path.dirname(path.realpath(__file__))
# iers.Conf.iers_auto_url.set('ftp://cddis.gsfc.nasa.gov/pub/products/iers/finals2000A.all')

all_antennas = fx.get_stations_from_file(f"{current_directory}/data/station_location.txt")
sorted_networks = {'EVN': 'EVN: European VLBI Network', 'eMERLIN': 'eMERLIN',
sorted_networks = {'EVN': 'EVN: European VLBI Network', 'eMERLIN': 'eMERLIN (out-stations)',
'VLBA': 'VLBA: Very Long Baseline Array',
'LBA': 'LBA: Australian Long Baseline Array',
'KVN': 'Korean VLBI Network',
@@ -84,6 +84,9 @@ for a_array in default_arrays:
for a_station in default_arrays[a_array]:
assert a_station in all_antennas.keys()

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

# Initial values
target_source = observation.Source('1h2m3s +50d40m30s', 'Source')
@@ -97,12 +100,14 @@ selected_band = '18cm'
# external_stylesheets = ["https://bmarcote.github.io/temp/style.css"]
external_stylesheets = []
# n_timestamps = 70 # Number of points (timestamps) for the whole observations.
# external_scripts = ["https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js", \
# "https://polyfill.io/v3/polyfill.min.js?features=es6"]
# "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"]





# app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# app = dash.Dash(__name__, external_scripts=external_scripts)
app = dash.Dash(__name__)


@@ -124,19 +129,68 @@ def tooltip(message, idname, trigger='?', placement='right', **kwargs):
**kwargs)]


def create_accordion_card(title, text, id, is_open=True):
"""Given a title (header) and a text (which can be either text, a dcc/html object),
it will return a dbc.Card object which is one input for an accordion.
"""
card_header = dbc.CardHeader(html.H2(dbc.Button(title, color='link',
id=f"group-{id}-toggle", className='')), className='accordion-header')
card_body = dbc.Collapse(dbc.CardBody(text), id=f"collapse-{id}", is_open=is_open,
className='accordion-collapse')
return dbc.Card([card_header, card_body], className='accordion-card')


def get_doc_text():
"""Reads the doc files and returns it as a Div object.
"""
temp = []
for i,a_topic in enumerate(doc_files):
with open(current_directory + doc_files[a_topic], 'r') as f:
# Some files will have references to images/files in the form '{src:filename}'
# We parse this
parsed_text = f.read()
while '{src:' in parsed_text:
i0 = parsed_text.index('{src:')
i1 = i0 + parsed_text[i0:].index('}')
filename = parsed_text[i0+5:i1]
parsed_text = parsed_text.replace( parsed_text[i0:i1+1], app.get_asset_url(filename) )

temp += [create_accordion_card(a_topic, dcc.Markdown(parsed_text), id=str(i))]

return html.Div(temp, className='col-12 accordion')


@app.callback([Output(f"collapse-{i}", "is_open") for i in range(len(doc_files))],
[Input(f"group-{i}-toggle", "n_clicks") for i in range(len(doc_files))],
[State(f"collapse-{i}", "is_open") for i in range(len(doc_files))])
def toggle_accordion(*args):
defaults = list(args[len(doc_files):])
ctx = dash.callback_context
if not ctx.triggered:
return [dash.no_update]*len(doc_files)
else:
button_id = ctx.triggered[0]["prop_id"].split(".")[0]

for i in range(len(doc_files)):
if (button_id == f"group-{i}-toggle") and (args[i] is not None):
defaults[i] = not defaults[i]

return defaults



##################### This is the webpage layout
app.layout = html.Div([
html.Script("""
$(document).ready(function() {
$('[data-toggle="popover"]').popover({
placement : 'bottom',
title : '<div style="text-align:center; color:red; text-decoration:underline; font-size:14px;"> Muah ha ha</div>', //this is the top title bar of the popover. add some basic css
html: 'true',
content : '<div id="popOverBox"><img src="http://www.hd-report.com/wp-content/uploads/2008/08/mr-evil.jpg" width="251" height="201" /></div>' //this is the content of the html box. add the image here or anything you want really.
});
});
"""),
# html.Script("""
# $(document).ready(function() {
# $('[data-toggle="popover"]').popover({
# placement : 'bottom',
# title : '<div style="text-align:center; color:red; text-decoration:underline; font-size:14px;"> Muah ha ha</div>', //this is the top title bar of the popover. add some basic css
# html: 'true',
# content : '<div id="popOverBox"><img src="http://www.hd-report.com/wp-content/uploads/2008/08/mr-evil.jpg" width="251" height="201" /></div>' //this is the content of the html box. add the image here or anything you want really.
# });
# });
# """),
html.Div(id='banner', className='navbar-brand d-flex p-3 shadow-sm', children=[
html.A(className='d-inline-block mr-md-auto', href="https://www.evlbi.org", children=[
html.Img(height='70px', src=app.get_asset_url("logo_evn.png"),
@@ -327,11 +381,11 @@ app.layout = html.Div([
html.Br(),
html.Div([
dcc.Graph(id='fig-elev-time')
]),
],className='tex2jax_ignore'),
# Antenna VS time (who can observe)
html.Div([
dcc.Graph(id='fig-ant-time')
])
],className='tex2jax_ignore')
])])
]),
dcc.Tab(label='Imaging', className='custom-tab',
@@ -349,10 +403,9 @@ app.layout = html.Div([
selected_className='custom-tab--selected', children=[
# Documentation
html.Div(className='row justify-content-center', children=[
html.Div(className='col-md-8', children=[
dcc.Markdown(children="""The Help/doc.
All explanations and technical details will go here.""")
])])
html.Div([html.Br(), html.Br()]),
html.Div(className='col-md-8', children=get_doc_text())
])
])
])
])
@@ -513,6 +566,8 @@ def update_sensitivity(obs):





@app.callback(Output('onsourcetime-label', 'children'),
[Input('onsourcetime', 'value')])
def update_onsourcetime_label(onsourcetime):
@@ -738,7 +793,7 @@ def get_fig_ant_up(obs):
'name': obs.stations[ant].name})

return {'data': data_fig,
'layout': {'title': 'Source visible (>10 deg) during the observation',
'layout': {'title': 'Source visible during the observation',
'xaxis': {'title': 'Time (UTC)', 'showgrid': False,
'ticks': 'inside', 'showline': True, 'mirror': "all",
'hovermode': 'closest', 'color': 'black'},


BIN
assets/eq-datarate.png View File

Before After
Width: 838  |  Height: 74  |  Size: 18 KiB

BIN
assets/eq-noise.png View File

Before After
Width: 1684  |  Height: 192  |  Size: 37 KiB

+ 106
- 4
assets/style.css View File

@@ -145,7 +145,7 @@ sup {
}

a {
color: #FF304F;
color: #a01d26;
text-decoration: none;
background-color:transparent
}
@@ -3290,7 +3290,6 @@ input[type=checkbox]:disabled:after {
width: 135pt;
}


.card {
min-width: 19rem;
max-width: 19rem;
@@ -3406,7 +3405,7 @@ input[type=checkbox]:disabled:after {
word-spacing: normal;
word-wrap: normal;
white-space: normal;
opacity: 0;
opacity: 1 !important;
line-break: auto;
}

@@ -3431,7 +3430,7 @@ input[type=checkbox]:disabled:after {
position: absolute;
width: 0;
height: 0;
border-color: #a01d26;
border-color: #a01d26 !important;
border-style: solid;
color: #a01d26 !important;
}
@@ -3472,6 +3471,109 @@ input[type=checkbox]:disabled:after {
color: #F0959B !important;
}

}
.accordion {
background-color: white;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
text-color: #a01d26;
border: none;
transition: 0.4s;
}

.accordion-card.card {
background-color: white !important;
/* color: #a01d26; */
/* cursor: pointer; */
/* padding: 18px; */
width: 100% !important;
/* text-align: left; */
/* text-color: #a01d26; */
/* border: none; */
/* outline: none; */
min-width: 100%;
max-width: 100%;
/* border: 1px solid #CCCCCC; */
border-left: 5px solid #a01d26;
margin: 40px;
transition: 0.4s;
}

.btn.btn-link {
color: #a01d26;
}


.accordion>.card .card-header {
background-color: white !important;
/* color: white; */
/* cursor: pointer; */
/* padding: 18px; */
width: 100%;
text-align: left;
/* color: #a01d26; */
/* outline: none; */
transition: 0.4s;
margin-bottom: 1;
border-bottom: 0px !important;
}

.accordion-header h2 .btn {
text-color: #a01d26;
font-weight: 500;
line-height:1.2;
font-size: 1.75rem;
}

/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
/* .active, .accordion:hover { */
/* background-color: #ccc; */
/* } */

/* Style the accordion panel. Note: hidden by default */
.accordion-collapse.collapse {
background-color: white;
border-bottom: 1px solid #CCCCCC;
/* display: none; */
/* overflow: hidden; */
}



img[alt=equation] {
/* width: 50%; */
height: 2.5rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1rem;
margin-bottom: 1rem;
}

img[alt=equation2] {
/* width: 50%; */
height: 1.5rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1rem;
margin-bottom: 1rem;
}

/* .accordion button:after { */
/* content: '\02795'; /* Unicode character for "plus" sign (+) */ */
/* font-size: 13px; */
/* color: #777; */
/* float: right; */
/* margin-left: 5px; */
/* } */
/* */
/* .active:after { */
/* content: "\2796"; /* Unicode character for "minus" sign (-) */ */
/* } */

/* FOR TEXT INPUTS I SHOULD ADD AN OFFSET SHADOW (REFACTORING UI TRICKS):
box-shadow: inset 0 2px 4px 0 hsla(0 0% 0& 0.08);


+ 22
- 0
doc/doc-antennas.md View File

@@ -0,0 +1,22 @@



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.


#### 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, respectivelya), 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.

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










+ 17
- 0
doc/doc-contact.md View File

@@ -0,0 +1,17 @@


This tool has been developed and is maintained at the [Joint Institute for VLBI ERIC (JIVE)](https://www.jive.eu) by Benito Marcote. The code and documentation is publicly available at [GitHub](https://github.com/bmarcote/vlbi_calculator) under GNU GPL v3.0.

Note that the full program can also be used without launching a server. We provide all tools to allow its interactive use without a graphical interface or to be easily integrated in any Python program.

Do not hesitate to provide feedback either at the [GitHub repository](https://github.com/bmarcote/vlbi_calculator/issues) or by [contacting the author](mailto:marcote@jive.eu).











+ 24
- 0
doc/doc-estimations.md View File

@@ -0,0 +1,24 @@



#### Datarate

VLBI observations are typically limited by the datarate: the amount of data that a station can transfer/record simultaneously. For simplification, this tool will always assume that all antennas record at the same speed. Whereas this is in general true, in multiple observations a few antennas can be limited to lower datarates. While this is fully supported in the SFXC correlator, the final effect is that those stations would show a fewer bandwidth, and thus the expected thermal rms noise may be slightly larger than expected.

The datarate for a given station is determined as
![equation2]({src:eq-datarate.png})
where _&#916;&#957;_ is the total observed bandwidth, _Np_ is the number of recorded polarizations (one or two), _N<sub>b</sub>_ is the number of bits used to sample the data (VLBI observations typically record at 2-bit sampling), and the last 2 is related to the Nyquist sampling.



#### Thermal noise level

This tool assumes the nominal System Equivalent Flux Densities (SEFDs) for each antenna. The SEFD is define as the flux density of a radio source that doubles the system temperature and thus allows a direct conversion between the amplitudes recorded at each antenna and the real flux density of the emission recorded. The SEFD values for EVN antennas can be seen at [the EVN Status Table](http://old.evlbi.org/user_guide/EVNstatus.txt).

The thermal noise for a given observation can be estimated (following e.g. [Wrobel & Walker 1999](https://ui.adsabs.harvard.edu/abs/1999ASPC..180..171W/abstract)) by
![equation]({src:eq-noise.png})
where _&#414;_ is the system efficiency (typically 0.7 in VLBI, 2-bit, observations), _&#916;&#957;_ is the total bandwidth, _Np_ is the number of polarizations recorded at each antenna (one or two), _&#916;t_ is the total on-source integration time, and _SEFD_ is the SEFD for the _k_ station, where it is considered that there are _N_ antennas in total. Note that this tool takes into account that a given baseline (formed by the _i,j_ antennas) can observe for a limited amount of time, not necessarily the full observing time.

We remark that nominal SEFD values are considered. This implies that no gain-curve corrections are applied. This can have a significant effect when observing at low elevations, specially at higher frequencies. The SEFDs at 3 mm assume typical weather conditions and a mean elevation of 30 degrees. We also do not take into account expected losses due to external factors like radio frequency interferences (RFI; that can be significant at low frequencies). Therefore, the final rms noise level may result to be slightly larger than the thermal noise level.



+ 13
- 1
doc/documentation.md View File

@@ -1,7 +1,19 @@



## General Comments




# About this tool






# Contact






BIN
doc/noise.png View File

Before After
Width: 1602  |  Height: 222  |  Size: 37 KiB

BIN
src/__pycache__/functions.cpython-36.pyc View File


Loading…
Cancel
Save