Skip to content

Commit e24a030

Browse files
committed
Added python files
1 parent 688231c commit e24a030

10 files changed

+3688
-0
lines changed

RFE6GEN_CalibrationData.py

Lines changed: 515 additions & 0 deletions
Large diffs are not rendered by default.

RFEAmplitudeTableData.py

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
#pylint: disable=trailing-whitespace, line-too-long, bad-whitespace, invalid-name, R0204, C0200
2+
#pylint: disable=superfluous-parens, missing-docstring, broad-except
3+
#pylint: disable=too-many-lines, too-many-instance-attributes, too-many-statements, too-many-nested-blocks
4+
#pylint: disable=too-many-branches, too-many-public-methods, too-many-locals, too-many-arguments
5+
6+
#============================================================================
7+
#RF Explorer Python Libraries - A Spectrum Analyzer for everyone!
8+
#Copyright © 2010-16 Ariel Rocholl, www.rf-explorer.com
9+
#
10+
#This application is free software; you can redistribute it and/or
11+
#modify it under the terms of the GNU Lesser General Public
12+
#License as published by the Free Software Foundation; either
13+
#version 3.0 of the License, or (at your option) any later version.
14+
#
15+
#This software is distributed in the hope that it will be useful,
16+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18+
#General Public License for more details.
19+
#
20+
#You should have received a copy of the GNU General Public
21+
#License along with this library; if not, write to the Free Software
22+
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23+
#=============================================================================
24+
25+
class RFEAmplitudeTableData:
26+
"""Class support a single collection of calibration amplitude values, of 1 MHz steps
27+
Positive values will be used to externally add to the measurement, that means imply correcting attenuation
28+
whereas negative values will be to externally substract to the measurement, implying correcting gain.
29+
"""
30+
CONST_MAX_ENTRY_DATA = 6101
31+
CONST_MIN_ENTRY_DATA = 0
32+
CONST_INVALID_DATA = -1E10
33+
CONST_DEFAULT_COMPRESSION = -10.0
34+
CONST_DEFAULT_AMPLITUDE_CORRECTION = 0.0
35+
36+
def __init__(self):
37+
self.m_arrAmplitudeCalibrationDataDB = [0.0] * self.CONST_MAX_ENTRY_DATA
38+
self.m_arrCompressionDataDBM = [0.0] * self.CONST_MAX_ENTRY_DATA
39+
self.m_bHasCompressionData = False
40+
self.lm_bHasCalibrationData = False
41+
self.m_sCalibrationID = ""
42+
self.Clear()
43+
44+
@property
45+
def CalibrationID(self):
46+
"""Calibration ID is usually a filename to name the calibration in use
47+
future versions may support different IDs than a filename
48+
"""
49+
return self.m_sCalibrationID
50+
51+
@property
52+
def HasCompressionData(self):
53+
"""Returns true if data stored include compression amplitude for overload check
54+
"""
55+
return self.m_bHasCompressionData
56+
57+
@property
58+
def HasCalibrationData(self):
59+
"""Will return true if there is loaded valid calibration data
60+
"""
61+
return self.m_bHasCalibrationData
62+
63+
@classmethod
64+
def FileHeaderVersioned(cls):
65+
"""File header version to control an unknown format
66+
67+
Returns:
68+
String File header version
69+
"""
70+
return "--RFEAT01"
71+
72+
def Clear(self):
73+
"""Initialize all collection of calibration amplitude values
74+
"""
75+
self.m_sCalibrationID = ""
76+
self.m_bHasCalibrationData = False
77+
for nInd in range(len(self.m_arrAmplitudeCalibrationDataDB)):
78+
self.m_arrAmplitudeCalibrationDataDB[nInd] = self.CONST_INVALID_DATA
79+
self.m_arrCompressionDataDBM[nInd] = self.CONST_INVALID_DATA
80+
81+
def GetAmplitudeCalibration(self, nIndexMHz):
82+
"""Amplitude correction data for each MHZ entry
83+
84+
Parameters:
85+
nIndexMHz -- Frequency reference in MHZ to get correction data from
86+
Returns:
87+
Float Correction amplitude value in dB
88+
"""
89+
if ((nIndexMHz < self.CONST_MAX_ENTRY_DATA) and (self.m_arrAmplitudeCalibrationDataDB) and (range(self.m_arrAmplitudeCalibrationDataDB) > nIndexMHz) and (self.m_arrAmplitudeCalibrationDataDB[nIndexMHz] != self.CONST_INVALID_DATA)):
90+
return self.m_arrAmplitudeCalibrationDataDB[nIndexMHz]
91+
else:
92+
return self.CONST_DEFAULT_AMPLITUDE_CORRECTION
93+
94+
def GetCompressionAmplitude(self, nIndexMHz):
95+
"""Amplitude compression data for each MHZ entry
96+
97+
Parameters:
98+
nIndexMHz -- Frequency reference in MHZ to get compression amplitude data from
99+
Returns:
100+
Float Compression amplitude value in dB
101+
"""
102+
if ((nIndexMHz < self.CONST_MAX_ENTRY_DATA) and (self.m_arrCompressionDataDBM) and (range(self.m_arrCompressionDataDBM) > nIndexMHz) and (self.m_arrAmplitudeCalibrationDataDB[nIndexMHz] != self.CONST_INVALID_DATA)):
103+
return self.m_arrCompressionDataDBM[nIndexMHz]
104+
else:
105+
return self.CONST_DEFAULT_COMPRESSION
106+
107+
def NormalizeDataIterating(self, arrAmplitudeData):
108+
"""Utility function to be used by both arrays, when needed
109+
110+
Parameters:
111+
arrAmplitudeData -- Collection of amplitude calibration data
112+
Returns:
113+
List Collection of amplitude calibration data
114+
"""
115+
fAmplitude1 = fAmplitude2 = self.CONST_INVALID_DATA #the two amplitude values to iterate in order to adjust intermediate values
116+
nAmplitude1Ind = nAmplitude2Ind = -1 #Index used to know the position of the two amplitudes
117+
118+
for nInd in range(len(arrAmplitudeData)):
119+
fVal = arrAmplitudeData[nInd]
120+
121+
if (fAmplitude1 == self.CONST_INVALID_DATA):
122+
if (fVal != self.CONST_INVALID_DATA):
123+
fAmplitude1 = fVal
124+
nAmplitude1Ind = nInd
125+
else:
126+
#use self._DEFAULT_AMPLITUDE_CORRECTION if nothing else is found
127+
#valid yet
128+
arrAmplitudeData[nInd] = self.CONST_DEFAULT_AMPLITUDE_CORRECTION
129+
elif (fAmplitude2 == self.CONST_INVALID_DATA):
130+
if (fVal != self.CONST_INVALID_DATA):
131+
fAmplitude2 = fVal
132+
nAmplitude2Ind = nInd
133+
134+
if ((nAmplitude2Ind - nAmplitude1Ind) > 1):
135+
#if more than one step is between the two, iterate to
136+
#add an incremental delta
137+
fDelta = (fAmplitude2 - fAmplitude1) / (nAmplitude2Ind - nAmplitude1Ind)
138+
nSteps = 1
139+
nInd2 = nAmplitude1Ind + 1
140+
while (nInd2 < nAmplitude2Ind):
141+
arrAmplitudeData[nInd2] = fAmplitude1 + nSteps * fDelta
142+
nInd2 += 1
143+
nSteps += 1
144+
145+
fAmplitude1 = fAmplitude2
146+
nAmplitude1Ind = nAmplitude2Ind
147+
fAmplitude2 = self.CONST_INVALID_DATA
148+
nAmplitude2Ind = 0
149+
else:
150+
#Use last valid value from now on, it should be overwritten
151+
#and updated later, but if that was
152+
#the last sample, then this will be good for the remaining
153+
#of the samples
154+
arrAmplitudeData[nInd] = fAmplitude1
155+
156+
return arrAmplitudeData
157+
158+
def NormalizeAmplitudeCalibrationDataIterating(self):
159+
""" It will iterate to all values and will fill in anything that is not initialized with a valid value
160+
As oposed to NormalizeDataCopy, it will look for valid values and will fill it in with intermediate
161+
calculated values in between these two. If no valid value is found among two (i.e. last value or first value)
162+
then it is filled in using NormalizedDataCopy.
163+
"""
164+
self.m_arrAmplitudeCalibrationDataDB = self.NormalizeDataIterating(self.m_arrAmplitudeCalibrationDataDB)
165+
166+
def NormalizeCompressionData(self):
167+
""" This function will make sure the compression data has start/end points even if not specified in the file
168+
"""
169+
if (self.m_arrCompressionDataDBM[self.CONST_MIN_ENTRY_DATA] == self.CONST_INVALID_DATA):
170+
self.m_arrCompressionDataDBM[self.CONST_MIN_ENTRY_DATA] = self.CONST_DEFAULT_COMPRESSION
171+
if (self.m_arrCompressionDataDBM[self.CONST_MAX_ENTRY_DATA - 1] == self.CONST_INVALID_DATA):
172+
self.m_arrCompressionDataDBM[self.CONST_MAX_ENTRY_DATA - 1] = self.CONST_DEFAULT_COMPRESSION
173+
174+
def NormalizeDataCopy(self):
175+
"""It will iterate to all values and will fill in anything that is not initialized with a valid value
176+
It uses a copy method, not an incremental method (i.e. it will pick the first valid value and
177+
go copying the same value over and over till it find another valid one. See NormalizeDataPredict for alternative
178+
"""
179+
fLastAmplitude = self.CONST_DEFAULT_AMPLITUDE_CORRECTION
180+
for nInd in range(len(self.m_arrAmplitudeCalibrationDataDB)):
181+
fVal = self.m_arrAmplitudeCalibrationDataDB[nInd]
182+
if (fVal == self.CONST_INVALID_DATA):
183+
self.m_arrAmplitudeCalibrationDataDB[nInd] = fLastAmplitude
184+
else:
185+
fLastAmplitude = fVal
186+
187+
def LoadFile(self, sFilename):
188+
"""Load a file with amplitude and optionally compression data
189+
190+
Parameters:
191+
sFilename -- Full path of the filename
192+
Returns:
193+
Boolean True if everything ok, False if data was invalid
194+
"""
195+
bOk = True
196+
try:
197+
with open(sFilename, 'r') as objReader:
198+
sHeader = objReader.readline()[:-1] #[-1] is to delete '\n' at the end
199+
if (sHeader != self.FileHeaderVersioned()):
200+
#unknown format
201+
return False
202+
203+
self.Clear()
204+
while(bOk):
205+
#Read line, trim and replace all consecutive blanks with a single tab
206+
sLine = objReader.readline().strip(' ')
207+
sLine = sLine.replace('\t', ' ')[:-1]
208+
while (" " in sLine):
209+
sLine = sLine.replace(" ", " ")
210+
211+
if (sLine[:2] != "--"):
212+
arrStrings = sLine.split(' ')
213+
if (len(arrStrings) >= 2):
214+
nMHZ = int(arrStrings[0])
215+
self.m_arrAmplitudeCalibrationDataDB[nMHZ] = float(arrStrings[1])
216+
if (len(arrStrings) >= 3):
217+
#this is a file that includes compression data
218+
self.m_arrCompressionDataDBM[nMHZ] = float(arrStrings[2])
219+
self.m_bHasCompressionData = True
220+
else:
221+
bOk = False
222+
223+
if (bOk):
224+
#update calibration file name
225+
sFile = sFilename.split('\\')
226+
if (len(sFile) > 0):
227+
self.m_sCalibrationID = sFile[len(sFile) - 1].ToUpper().Replace(".RFA", "")
228+
229+
#fill in all gaps
230+
self.NormalizeAmplitudeCalibrationDataIterating()
231+
self.NormalizeCompressionData()
232+
else:
233+
self.Clear()
234+
except Exception as obEx:
235+
print("Error in RFEAmplitudeTableData - LoadFile(): " + str(obEx))
236+
bOk = False
237+
238+
return bOk
239+

0 commit comments

Comments
 (0)