Browse Source

Data files moved to importlib. functions.py gone

tags/v1.0
Benito Marcote 6 months ago
parent
commit
692c74f423
9 changed files with 130 additions and 141 deletions
  1. +15
    -1
      README.md
  2. +6
    -6
      app.py
  3. +0
    -0
      data/__init__.py
  4. +0
    -0
      doc/__init__.py
  5. +0
    -1
      vlbiplanobs/__init__.py
  6. +0
    -128
      vlbiplanobs/functions.py
  7. +3
    -5
      vlbiplanobs/graphical_elements.py
  8. +41
    -0
      vlbiplanobs/observation.py
  9. +65
    -0
      vlbiplanobs/stations.py

+ 15
- 1
README.md View File

@@ -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





+ 6
- 6
app.py View File

@@ -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
- 0
data/__init__.py View File


+ 0
- 0
doc/__init__.py View File


+ 0
- 1
vlbiplanobs/__init__.py View File

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

+ 0
- 128
vlbiplanobs/functions.py View File

@@ -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)














+ 3
- 5
vlbiplanobs/graphical_elements.py View File

@@ -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
- 0
vlbiplanobs/observation.py View File

@@ -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
- 0
vlbiplanobs/stations.py View File

@@ -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