Browse Source

Data files moved to importlib. functions.py gone

pull/1/head
Benito Marcote 1 year ago
parent
commit
692c74f423
  1. 16
      README.md
  2. 12
      app.py
  3. 0
      data/__init__.py
  4. 0
      doc/__init__.py
  5. 1
      vlbiplanobs/__init__.py
  6. 128
      vlbiplanobs/functions.py
  7. 8
      vlbiplanobs/graphical_elements.py
  8. 41
      vlbiplanobs/observation.py
  9. 65
      vlbiplanobs/stations.py

16
README.md

@ -45,8 +45,22 @@ import vlbiplanobs
# Two main modules that can also be imported directly
from vlbiplanobs import stations
from vlbiplanobs import observations
from vlbiplanobs import observation
# You can define your source and telescopes before setting the observation:
# You can define the source you want to observe with:
source = observation.Source(coordinates='XXhXXmXXs XXdXXmXXs', name='my_source')
# To can then retrieve the coordinates (as in a astropy.coordinates.angles.Longitude/Latitude object) with:
source.ra
source.dec
# Or retrieve the full astropy.coordinates object as
source.coord
# Then you can set the observation

12
app.py

@ -19,6 +19,7 @@ import os
from os import path
from time import sleep
import itertools
from importlib import resources
from datetime import datetime as dt
import numpy as np
import dash
@ -48,7 +49,6 @@ from astroplan import FixedTarget
from vlbiplanobs import freqsetups as fs
from vlbiplanobs import stations
from vlbiplanobs import functions as fx
from vlbiplanobs import observation
from vlbiplanobs import graphical_elements as ge
# adding the possibility of disabled
@ -57,7 +57,7 @@ from vlbiplanobs.Checkbox import Checkbox
current_directory = path.dirname(path.realpath(__file__))
all_antennas = fx.get_stations_from_configfile(f"{current_directory}/data/stations_catalog.inp")
all_antennas = stations.Stations.get_stations_from_configfile()
sorted_networks = {'EVN': 'EVN: European VLBI Network', 'eMERLIN': 'eMERLIN (out-stations)',
'VLBA': 'VLBA: Very Long Baseline Array',
@ -89,9 +89,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'}
doc_files = {'About this tool': 'doc-contact.md',
'About the antennas': 'doc-antennas.md',
'Technical background': 'doc-estimations.md'}
# Initial values
target_source = observation.Source('10h2m3s +50d40m30s', 'Source')
@ -144,7 +144,7 @@ def get_doc_text():
"""
temp = []
for i,a_topic in enumerate(doc_files):
with open(current_directory + doc_files[a_topic], 'r') as f:
with resources.open_text("doc", doc_files[a_topic]) as f:
# Some files will have references to images/files in the form '{src:filename}'
# We parse this
parsed_text = f.read()

0
data/__init__.py

0
doc/__init__.py

1
vlbiplanobs/__init__.py

@ -1,3 +1,2 @@
from vlbiplanobs import stations
from vlbiplanobs import observation
from vlbiplanobs import functions

128
vlbiplanobs/functions.py

@ -1,128 +0,0 @@
"""Different functions that are required to operate the program
"""
import configparser
from astropy import units as u
from astropy import coordinates as coord
from astropy.io import ascii
from vlbiplanobs import stations
def get_stations_from_configfile(filename='data/stations_catalog.inp'):
"""Retrieves the information concerning all stations available in the 'filename'
file. Creates a Stations object containing the stations and the information on it.
The file must have a format readable by the Python ConfigParser.
Each section will be named with the name of the station, and then it must have
the following keys:
station - full name of the station.
code - codename for the station (typically two letters).
network - main network to which it belongs to.
possible_networks - all networks the station can participate in (including 'network')
country - country where the station is located.
diameter - string with the diameter of the station.
position = x, y, z (in meters). Geoposition of the station.
min_elevation (in degrees) - minimum elevation the station can observe.
real_time = yes/no - if the station can participate in real-time observations (e.g. e-EVN).
SEFD_** - SEFD of the station at the **cm band. If a given band is not present,
it is assumed that the station cannot observe it.
[optional]
img - a path to an image of the station.
link - a url linking to the station page/related information.
"""
config = configparser.ConfigParser()
config.read(filename)
networks = stations.Stations('network', [])
for stationname in config.sections():
temp = [float(i.strip()) for i in config[stationname]['position'].split(',')]
a_loc = coord.EarthLocation(temp[0]*u.m, temp[1]*u.m, temp[2]*u.m)
# Getting the SEFD values for the bands
min_elev = float(config[stationname]['min_elevation'])*u.deg
does_real_time = True if config[stationname]['real_time']=='yes' else False
sefds = {}
for akey in config[stationname].keys():
if 'SEFD_' in akey.upper():
sefds[f"{akey.upper().replace('SEFD_', '').strip()}cm"] = \
float(config[stationname][akey])
new_station = stations.SelectedStation(stationname, config[stationname]['code'],
config[stationname]['network'], a_loc, sefds, min_elev,
config[stationname]['station'], config[stationname]['possible_networks'],
config[stationname]['country'], config[stationname]['diameter'], does_real_time)
networks.add(new_station)
return networks
def stations_with_band(networks, band, output_network_name=None):
"""For a given collection of networks or Stations, returns a Stations object
including all stations that can observe at the given band.
- networks : dict [name_network]: Stations or Stations
- band : str
"""
if output_network_name is None:
output_network_name = f"Stations@{band}"
antennas = stations.Stations(output_network_name, [])
if isinstance(networks, dict):
for network in networks:
for station in networks[network]:
if band in station.bands:
antennas.add(station)
elif isinstance(networks, stations.Stations):
for station in networks:
if band in station.bands:
antennas.add(station)
else:
raise ValueError(f"{networks} expected to be either dict of Stations type.")
return antennas
def print_obs_times(obs, date_format='%d %b %Y'):
"""Given an observation, it returns the time range (starttime-endtime) in a smart
way. If the observation lasts for less than one day it omits the end date:
20 Jan 1971 10:00-20:00UT
It also adds the GST range after that.
Input:
- obs : observation.Observation
It must already have set the .times part with an array of astropy.Time times.
- date_format : str [optional]
Format for the date part (only the date part) of the string to represent
the time range.
Output:
- printed_time : str
A string showing the time-range of the observation.
"""
gsttext = "{:02n}:{:02.2n}-{:02n}:{:02.2n}".format((obs.gstimes[0].hour*60) // 60,
(obs.gstimes[0].hour*60) % 60,
(obs.gstimes[-1].hour*60) // 60,
(obs.gstimes[0].hour*60) % 60)
if obs.times[0].datetime.date() == obs.times[-1].datetime.date():
return "{}\n{}-{} UTC\nGST: {}".format(obs.times[0].datetime.strftime(date_format),
obs.times[0].datetime.strftime('%H:%M'),
obs.times[-1].datetime.strftime('%H:%M'), gsttext)
elif (obs.times[-1] - obs.times[0]) < 24*u.h:
return "{}\n{}-{} UTC (+1d)\nGST: {}".format(
obs.times[0].datetime.strftime(date_format),
obs.times[0].datetime.strftime('%H:%M'),
obs.times[-1].datetime.strftime('%H:%M'), gsttext)
else:
return "{} {} to {} {} UTC\nGST: {}".format(
obs.times[0].datetime.strftime(date_format),
obs.times[0].datetime.strftime('%H:%M'),
obs.times[-1].datetime.strftime(date_format),
obs.times[-1].datetime.strftime('%H:%M'), gsttext)

8
vlbiplanobs/graphical_elements.py

@ -7,8 +7,6 @@ import dash_html_components as html
import dash_bootstrap_components as dbc
import plotly.express as px
from vlbiplanobs import functions
def tooltip(message, idname, trigger='?', placement='right',trigger_is_sup=True, **kwargs):
"""Defines a tooltip (popover) that will be shown in the rendered page.
@ -188,14 +186,14 @@ def summary_card_beam(app, obs):
def summary_card_times(app, obs):
"""Creates a summary card showing the observing times, and the resulting data size.
"""
prtobstimes = functions.print_obs_times(obs)
prtobstimes = obs.print_obs_times()
if '\n' in prtobstimes:
tmp = [html.Span(t) for t in functions.print_obs_times(obs).split('\n')]
tmp = [html.Span(t) for t in obs.print_obs_times().split('\n')]
for i in range(len(tmp)-1):
tmp.insert(2*i+1, html.Br())
temp_msg = [tmp]
else:
temp_msg = [f"{functions.print_obs_times(obs)}."]
temp_msg = [f"{obs.print_obs_times()}."]
temp_msg += [f"The observation lasts for {optimal_units(obs.duration, [u.h, u.min, u.s, u.ms]):.3n}, of which {optimal_units(obs.ontarget_time, [u.h, u.min, u.s, u.ms]):.3n} are on target."]
n_files = int(np.ceil(obs.datasize()/(2.0*u.GB)))

41
vlbiplanobs/observation.py

@ -449,4 +449,45 @@ class Observation(object):
# i += uvdata[bl_name].shape[0]
def print_obs_times(self, date_format='%d %B %Y'):
"""Given an observation, it returns the time range (starttime-endtime) in a smart
way. If the observation lasts for less than one day it omits the end date:
20 Jan 1971 10:00-20:00UT
It also adds the GST range after that.
Input:
- obs : observation.Observation
It must already have set the .times part with an array of astropy.Time times.
- date_format : str [optional]
Format for the date part (only the date part) of the string to represent
the time range.
Output:
- printed_time : str
A string showing the time-range of the observation.
"""
gsttext = "{:02n}:{:02.2n}-{:02n}:{:02.2n}".format((self.gstimes[0].hour*60) // 60,
(self.gstimes[0].hour*60) % 60,
(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),
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(
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(
self.times[0].datetime.strftime(date_format),
self.times[0].datetime.strftime('%H:%M'),
self.times[-1].datetime.strftime(date_format),
self.times[-1].datetime.strftime('%H:%M'), gsttext)

65
vlbiplanobs/stations.py

@ -1,3 +1,5 @@
import configparser
from importlib import resources
import numpy as np
from astropy import units as u
from astropy import coordinates as coord
@ -273,7 +275,70 @@ class Stations(object):
def __contains__(self, item):
return self._stations.__contains__(item)
@staticmethod
def get_stations_from_configfile(filename=None):
"""Retrieves the information concerning all stations available in the 'filename'
file. Creates a Stations object containing the stations and the information on it.
The file must have a format readable by the Python ConfigParser.
Each section will be named with the name of the station, and then it must have
the following keys:
station - full name of the station.
code - codename for the station (typically two letters).
network - main network to which it belongs to.
possible_networks - all networks the station can participate in (including 'network')
country - country where the station is located.
diameter - string with the diameter of the station.
position = x, y, z (in meters). Geoposition of the station.
min_elevation (in degrees) - minimum elevation the station can observe.
real_time = yes/no - if the station can participate in real-time observations (e.g. e-EVN).
SEFD_** - SEFD of the station at the **cm band. If a given band is not present,
it is assumed that the station cannot observe it.
[optional]
img - a path to an image of the station.
link - a url linking to the station page/related information.
"""
config = configparser.ConfigParser()
if filename is None:
with resources.path("data", "stations_catalog.inp") as stations_catalog_path:
config.read(stations_catalog_path)
else:
config.read(filename)
networks = Stations('network', [])
for stationname in config.sections():
temp = [float(i.strip()) for i in config[stationname]['position'].split(',')]
a_loc = coord.EarthLocation(temp[0]*u.m, temp[1]*u.m, temp[2]*u.m)
# Getting the SEFD values for the bands
min_elev = float(config[stationname]['min_elevation'])*u.deg
does_real_time = True if config[stationname]['real_time']=='yes' else False
sefds = {}
for akey in config[stationname].keys():
if 'SEFD_' in akey.upper():
sefds[f"{akey.upper().replace('SEFD_', '').strip()}cm"] = \
float(config[stationname][akey])
new_station = SelectedStation(stationname, config[stationname]['code'],
config[stationname]['network'], a_loc, sefds, min_elev,
config[stationname]['station'], config[stationname]['possible_networks'],
config[stationname]['country'], config[stationname]['diameter'], does_real_time)
networks.add(new_station)
return networks
def stations_with_band(self, band, output_network_name=None):
"""For a given collection of networks or Stations, returns a Stations object
including all stations that can observe at the given band.
- band : str
"""
if output_network_name is None:
output_network_name = f"Stations@{band}"
antennas = stations.Stations(output_network_name, [])
for station in self.stations:
if band in station.bands:
antennas.add(station)
return antennas

Loading…
Cancel
Save