diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a9851a135a5f82c62c0110b5d802d191a95a2fe0..7cfd5468d9f8430570aeea7bb77a6e4c52b0495e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -14,6 +14,7 @@ set(_py_files constants.py visualizer.py query.py + station_coordinates.py ) @@ -25,6 +26,7 @@ set(resource_files python_install(${_py_files} DESTINATION lofar/lta/sip) + install(FILES ${resource_files} DESTINATION ${PYTHON_INSTALL_DIR}/lofar/lta/sip COMPONENT ${lower_package_name}) diff --git a/lib/siplib.py b/lib/siplib.py index bb3c6238a14a19117ee2d5379f838ddb6b04f66c..4f89a4fe91f5552972e9b43c0cc4afe903d9d9fc 100644 --- a/lib/siplib.py +++ b/lib/siplib.py @@ -28,6 +28,7 @@ from . import ltasip import pyxb from . import constants +from . import station_coordinates import os import uuid import xml.dom.minidom @@ -38,8 +39,6 @@ import logging logger = logging.getLogger(__name__) VERSION = "SIPlib 0.4" -d = os.path.dirname(os.path.realpath(__file__)) -STATION_CONFIG_PATH = d+'/station_coordinates.conf' ltasip.Namespace.setPrefix('sip') # todo: create docstrings for everything. @@ -144,30 +143,28 @@ class Station(): __afield1=None __afield2=None - with open(STATION_CONFIG_PATH, 'r') as f: - for line in f.readlines(): - if line.strip(): - field_coords = eval("dict("+line+")") # literal_eval does not accept dict definition via constructor. Make sure config file is not writable to prevent code execution! - for type in antennafieldtypes: - if field_coords["name"] == name+"_"+type: - __afield=AntennafieldXYZ( - type=type, + station_coords = station_coordinates.parse_station_coordinates() + for atype in antennafieldtypes: + if name+"_"+atype in station_coords.keys(): + field_coords = station_coords[name+"_"+atype] + __afield=AntennafieldXYZ( + type=atype, coordinate_system=field_coords["coordinate_system"], coordinate_unit=constants.LENGTHUNIT_M, # Does this make sense? I have to give a lenght unit accoridng to the XSD, but ICRF should be decimal degrees?! coordinate_x=field_coords["x"], coordinate_y=field_coords["y"], coordinate_z=field_coords["z"]) - if not __afield1: - __afield1=__afield - elif not __afield2: - __afield2=__afield + if not __afield1: + __afield1=__afield + elif not __afield2: + __afield2=__afield if not __afield1: - raise Exception("no matching coordinates found for station:", name,"and fields",str(antennafieldtypes)) + raise Exception("no matching coordinates found for station:", name, "and fields", str(antennafieldtypes)) - if name.startswith( 'CS' ): + if name.startswith('CS'): sttype = "Core" - elif name.startswith( "RS" ): + elif name.startswith("RS"): sttype = "Remote" else: sttype = "International" diff --git a/lib/station_coordinates.conf b/lib/station_coordinates.conf index 07e488f9a72ccf960c6e6f30c9bc39823e3c7613..741cd1395f2a6a362e70335b7c97d0ac383eb746 100644 --- a/lib/station_coordinates.conf +++ b/lib/station_coordinates.conf @@ -154,3 +154,9 @@ coordinate_system='ITRF2005', x='3850973.9872', y='1439061.04111', z='4860478.99 coordinate_system='ITRF2005', x='3850980.8812', y='1438994.87911', z='4860498.993' , name='PL611_HBA' coordinate_system='ITRF2005', x='3551478.64311', y='1334128.4928', z='5110179.160' , name='PL612_LBA' coordinate_system='ITRF2005', x='3551481.8171', y='1334203.5728', z='5110157.410' , name='PL612_HBA' + +coordinate_system='ITRF2005', x='3801633.528060000', y='-529021.899396000', z='5076997.185' , name='IE613_LBA' +coordinate_system='ITRF2005', x='3801691.943300000', y='-528983.966429000', z='5076957.924' , name='IE613_HBA' + +coordinate_system='ITRF2005', x='3183318.032280000', y='1276777.654760000', z='5359435.077' , name='LV614_LBA' +coordinate_system='ITRF2005', x='3183249.285620000', y='1276801.742170000', z='5359469.949' , name='LV614_HBA' \ No newline at end of file diff --git a/lib/station_coordinates.py b/lib/station_coordinates.py new file mode 100644 index 0000000000000000000000000000000000000000..f2952a203d2af5ee5578342eac1af1706c41662c --- /dev/null +++ b/lib/station_coordinates.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +# This module provides functions for easy creation of a Lofar LTA SIP document. +# It builds upon a Pyxb-generated API from the schema definition, which is very clever but hard to use, since +# the arguments in class constructors and functions definitions are not verbose and there is no intuitive way +# to determine the mandatory and optional elements to create a valid SIP document. This module is designed to +# provide easy-to-use functions that bridges this shortcoming of the Pyxb API. +# +# Usage: Import module. Create an instance of Sip. +# Add elements through the Sip.add_X functions. Many require instances of other classes of the module. +# call getprettyxml() and e.g. save to disk. +# +# Note on validation: From construction through every addition, the SIP should remain valid (or throw an error +# that clearly points out where e.g. a given value does not meet the restrictions of the SIP schema. +# +# Note on code structure: This has to be seen as a compromise between elegant and maintainable code with well- +# structured inheritance close to the schema definition on the one hand, and something more straightforward to use, +# with flatter hierarchies on the other hand. +# +# Note on parameter maps: The ...Map objects are helper objects to create dictionaries for the commonly used +# constructor arguments of several other objects. This could alternatively also be implemented via inheritance from +# a supertype, and indeed is solved like this in the pyxb code. However, this then requires the use of an argument +# list pointer, which hides the list of required and optional arguments from the user. Alternatively, all arguments +# have to be mapped in all constructors repeatedly, creating lots of boilerplate code. This is the nicest approach +# I could think of that keeps the whole thing reasonably maintainable AND usable. + +import os +d = os.path.dirname(os.path.realpath(__file__)) +STATION_CONFIG_PATH = d+'/station_coordinates.conf' + + +def parse_station_coordinates() -> dict: + """ + :return: a dict mapping station field name, e.g. "CS002_LBA", to a dict containing ITRF coordinates + """ + station_coordinates = {} + with open(STATION_CONFIG_PATH, 'r') as f: + for line in f.readlines(): + if line.strip(): + field_coords = eval("dict(" + line + ")") # literal_eval does not accept dict definition via constructor. Make sure config file is not writable to prevent code execution! + station_coordinates[field_coords.pop("name")] = field_coords + return station_coordinates + +