21 from numpy
import sin, cos, sqrt, arcsin, power, deg2rad, isnan
25 log = logging.getLogger(__name__)
29 """! ChannelSpec: Specify a data channel with a formatted string"""
33 Split string into source, channel, and optionally array index
34 components. Values are validated to the extent possible without device
35 and source specific information
36 @param s String in format 'source:channel[:index]'
41 raise ValueError(
"Invalid channel specification")
44 self.
sourcesource = int(parts[0], base=0)
47 self.
channelchannel = int(parts[1], base=0)
50 self.
indexindex = int(parts[2], base=0)
52 self.
indexindex =
None
55 raise ValueError(
"Invalid channel specification (bad source)")
58 raise ValueError(
"Invalid channel specification (bad channel)")
60 if not self.
indexindex
is None and self.
indexindex < 0:
61 raise ValueError(
"Invalid channel specification (bad index)")
65 Extract value from `state` corresponding to this Spec.
66 @param state Dataframe containing StateFile data
67 @returns floating point value, or NaN if not found
70 val = state.loc[(self.
sourcesource, self.
channelchannel)].Value
71 if self.
indexindex
is None:
74 return float(val.split(
"/")[self.
indexindex - 1])
79 """! @returns Correctly formatted string"""
80 if self.
indexindex
is None:
81 return f
"0x{self.source:02x}:0x{self.channel:02x}"
83 return f
"0x{self.source:02x}:0x{self.channel:02x}:0x{self.index:02x}"
86 """! @returns Parseable representation"""
87 return f
"ChannelSpec('{self.__str__():s}')"
92 LocatorSpec: String representation of location monitoring settings
97 Split string into components defining location warning settings.
98 Values are validated to the extent possible without device
99 and source specific information
100 String is a set of comma separated values in this order:
101 - Latitude ChannelSpec()
102 - Longitude ChannelSpec()
104 - Reference Longitude
105 - Warning threshold distance (m)
107 @param s String in required format.
110 if len(parts) < 5
or len(parts) > 6:
111 raise ValueError(
"Invalid locator specification")
132 self.
namename = f
"{self.latChan}/{self.lonChan}"
137 Haversine distance formula, from Wikipedia
138 @param lat1 Latitude 1 (decimal degrees)
139 @param lon1 Longitude 1 (decimal degrees)
140 @param lat2 Latitude 2 (decimal degrees)
141 @param lon2 Latitude 2 (decimal degrees)
142 @returns Distance from 1 -> 2 in metres
144 hdLat = (deg2rad(lat2) - deg2rad(lat1)) / 2
145 hdLon = (deg2rad(lon2) - deg2rad(lon1)) / 2
153 power(sin(hdLat), 2) + cos(lat1) * cos(lat2) * power(sin(hdLon), 2)
160 Check whether locator is within warning threshold or not, based on the
163 In returned tuple, `alert` is True if position is unknown or further from
164 the reference position than the warning threshold distance. The distance
165 from the reference point in metres is returned along with the current
166 position in decimal degrees.
168 @param s State dataframe
169 @returns Tuple of form (alert, distance, (lat, lon))
171 curLat = self.
latChanlatChan.getValue(s)
172 curLon = self.
lonChanlonChan.getValue(s)
174 if isnan(curLat)
or isnan(curLon):
175 log.warning(f
"{self.name} has invalid coordinates")
176 return (
True, float(
"nan"), (curLat, curLon))
180 return (
True, d, (curLat, curLon))
181 return (
False, d, (curLat, curLon))
184 """! @returns Correctly formatted string"""
185 return f
"{self.latChan},{self.lonChan},{self.refLat},{self.refLon},{self.threshold},{self.name}"
188 """! @returns Parseable representation"""
189 return f
"LocatorSpec('{self.__str__():s}')"
194 LimitSpec: String representation of channel limit specification
199 Split string into components defining channel and warning limits.
200 Values are validated to the extent possible without device
201 and source specific information
202 String is a set of comma separated values in this order:
204 - Low value threshold
205 - High value threshold
207 @param s String in required format.
210 if len(parts) < 3
or len(parts) > 4:
212 f
"Invalid limit specification ({parts}: {len(parts)} parts)"
228 self.
namename = f
"{self.channel}"
232 Check whether channel is within warning threshold or not, based on the
235 Returns true if value is unknown or outside limits
237 @param s State dataframe
243 log.warning(f
"{self.name} has invalid value")
246 return (value < self.
lowLimlowLim)
or (value > self.
highLimhighLim)
249 """! @returns Channel getValue result"""
253 """! @returns Correctly formatted string"""
254 return f
"{self.channel},{self.lowLim},{self.highLim},{self.name}"
257 """! @returns Parseable representation"""
258 return f
"LocatorSpec('{self.__str__():s}')"
ChannelSpec: Specify a data channel with a formatted string.
def __init__(self, s)
Split string into source, channel, and optionally array index components.
index
Selected array index (optional)
def getValue(self, state)
Extract value from state corresponding to this Spec.
source
Selected source ID.
channel
Selected channel ID.
LimitSpec: String representation of channel limit specification.
channel
ChannelSpec() identifying source of latitude data.
name
Name for this locator (used in reporting)
def check(self, s)
Check whether channel is within warning threshold or not, based on the data in s
def __init__(self, s)
Split string into components defining channel and warning limits.
LocatorSpec: String representation of location monitoring settings.
latChan
ChannelSpec() identifying source of latitude data.
def __init__(self, s)
Split string into components defining location warning settings.
def check(self, s)
Check whether locator is within warning threshold or not, based on the data in s
def haversine(lat1, lon1, lat2, lon2)
Haversine distance formula, from Wikipedia.
refLon
Reference longitude (decimal degrees)
name
Name for this locator (used in reporting)
lonChan
ChannelSpec() identifying source of longitude data.
refLat
Reference latitude (decimal degrees)
threshold
Warning Distance (m)