BLTRheaderIO.py
404 lines
| 16.2 KiB
| text/x-python
|
PythonLexer
|
r965 | ''' | ||
$Author: murco $ | ||||
$Id: JROHeaderIO.py 151 2012-10-31 19:00:51Z murco $ | ||||
''' | ||||
import sys | ||||
import numpy | ||||
import copy | ||||
import datetime | ||||
|
r1167 | |||
|
r965 | |||
SPEED_OF_LIGHT = 299792458 | ||||
SPEED_OF_LIGHT = 3e8 | ||||
|
r1383 | FILE_STRUCTURE = numpy.dtype([ # HEADER 48bytes | ||
('FileMgcNumber', '<u4'), # 0x23020100 | ||||
('nFDTdataRecors', '<u4'), # No Of FDT data records in this file (0 or more) | ||||
('RadarUnitId', '<u4'), | ||||
('SiteName', '<s32'), # Null terminated | ||||
|
r965 | ]) | ||
|
r1383 | RECORD_STRUCTURE = numpy.dtype([ # RECORD HEADER 180+20N bytes | ||
('RecMgcNumber', '<u4'), # 0x23030001 | ||||
('RecCounter', '<u4'), # Record counter(0,1, ...) | ||||
('Off2StartNxtRec', '<u4'), # Offset to start of next record form start of this record | ||||
('Off2StartData', '<u4'), # Offset to start of data from start of this record | ||||
('EpTimeStamp', '<i4'), # Epoch time stamp of start of acquisition (seconds) | ||||
('msCompTimeStamp', '<u4'), # Millisecond component of time stamp (0,...,999) | ||||
('ExpTagName', '<s32'), # Experiment tag name (null terminated) | ||||
('ExpComment', '<s32'), # Experiment comment (null terminated) | ||||
('SiteLatDegrees', '<f4'), # Site latitude (from GPS) in degrees (positive implies North) | ||||
('SiteLongDegrees', '<f4'), # Site longitude (from GPS) in degrees (positive implies East) | ||||
('RTCgpsStatus', '<u4'), # RTC GPS engine status (0=SEEK, 1=LOCK, 2=NOT FITTED, 3=UNAVAILABLE) | ||||
('TransmitFrec', '<u4'), # Transmit frequency (Hz) | ||||
('ReceiveFrec', '<u4'), # Receive frequency | ||||
('FirstOsciFrec', '<u4'), # First local oscillator frequency (Hz) | ||||
('Polarisation', '<u4'), # (0="O", 1="E", 2="linear 1", 3="linear2") | ||||
('ReceiverFiltSett', '<u4'), # Receiver filter settings (0,1,2,3) | ||||
('nModesInUse', '<u4'), # Number of modes in use (1 or 2) | ||||
('DualModeIndex', '<u4'), # Dual Mode index number for these data (0 or 1) | ||||
('DualModeRange', '<u4'), # Dual Mode range correction for these data (m) | ||||
('nDigChannels', '<u4'), # Number of digital channels acquired (2*N) | ||||
('SampResolution', '<u4'), # Sampling resolution (meters) | ||||
('nRangeGatesSamp', '<u4'), # Number of range gates sampled | ||||
('StartRangeSamp', '<u4'), # Start range of sampling (meters) | ||||
('PRFhz', '<u4'), # PRF (Hz) | ||||
('Integrations', '<u4'), # Integrations | ||||
('nDataPointsTrsf', '<u4'), # Number of data points transformed | ||||
('nReceiveBeams', '<u4'), # Number of receive beams stored in file (1 or N) | ||||
('nSpectAverages', '<u4'), # Number of spectral averages | ||||
('FFTwindowingInd', '<u4'), # FFT windowing index (0 = no window) | ||||
('BeamAngleAzim', '<f4'), # Beam steer angle (azimuth) in degrees (clockwise from true North) | ||||
('BeamAngleZen', '<f4'), # Beam steer angle (zenith) in degrees (0=> vertical) | ||||
('AntennaCoord', '<f24'), # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs | ||||
('RecPhaseCalibr', '<f12'), # Receiver phase calibration (degrees) - N values | ||||
('RecAmpCalibr', '<f12'), # Receiver amplitude calibration (ratio relative to receiver one) - N values | ||||
('ReceiverGaindB', '<u12'), # Receiver gains in dB - N values | ||||
|
r965 | ]) | ||
class Header(object): | ||||
def __init__(self): | ||||
raise NotImplementedError | ||||
def read(self): | ||||
raise NotImplementedError | ||||
def write(self): | ||||
raise NotImplementedError | ||||
def printInfo(self): | ||||
message = "#"*50 + "\n" | ||||
message += self.__class__.__name__.upper() + "\n" | ||||
message += "#"*50 + "\n" | ||||
|
r1167 | keyList = list(self.__dict__.keys()) | ||
|
r965 | keyList.sort() | ||
for key in keyList: | ||||
|
r1383 | message += "%s = %s" % (key, self.__dict__[key]) + "\n" | ||
|
r965 | |||
if "size" not in keyList: | ||||
attr = getattr(self, "size") | ||||
if attr: | ||||
|
r1383 | message += "%s = %s" % ("size", attr) + "\n" | ||
|
r965 | |||
|
r1167 | print(message) | ||
|
r965 | |||
class FileHeader(Header): | ||||
|
r1383 | FileMgcNumber = None | ||
nFDTdataRecors = None # No Of FDT data records in this file (0 or more) | ||||
RadarUnitId = None | ||||
SiteName = None | ||||
|
r965 | |||
|
r1383 | # __LOCALTIME = None | ||
|
r965 | |||
def __init__(self, useLocalTime=True): | ||||
|
r1383 | self.FileMgcNumber = 0 # 0x23020100 | ||
self.nFDTdataRecors = 0 # No Of FDT data records in this file (0 or more) | ||||
self.RadarUnitId = 0 | ||||
self.SiteName = "" | ||||
|
r965 | self.size = 48 | ||
|
r1383 | # self.useLocalTime = useLocalTime | ||
|
r965 | |||
def read(self, fp): | ||||
try: | ||||
|
r1383 | header = numpy.fromfile(fp, FILE_STRUCTURE, 1) | ||
|
r965 | ''' numpy.fromfile(file, dtype, count, sep='') | ||
file : file or str | ||||
Open file object or filename. | ||||
dtype : data-type | ||||
Data type of the returned array. For binary files, it is used to determine | ||||
the size and byte-order of the items in the file. | ||||
count : int | ||||
Number of items to read. -1 means all items (i.e., the complete file). | ||||
sep : str | ||||
Separator between items if file is a text file. Empty (“”) separator means | ||||
the file should be treated as binary. Spaces (” ”) in the separator match zero | ||||
or more whitespace characters. A separator consisting only of spaces must match | ||||
at least one whitespace. | ||||
''' | ||||
|
r1167 | except Exception as e: | ||
print("FileHeader: ") | ||||
print(eBasicHeader) | ||||
|
r965 | return 0 | ||
|
r1383 | self.FileMgcNumber = byte(header['FileMgcNumber'][0]) | ||
self.nFDTdataRecors = int(header['nFDTdataRecors'][0]) # No Of FDT data records in this file (0 or more) | ||||
self.RadarUnitId = int(header['RadarUnitId'][0]) | ||||
self.SiteName = char(header['SiteName'][0]) | ||||
|
r965 | |||
|
r1383 | if self.size < 48: | ||
|
r965 | return 0 | ||
return 1 | ||||
def write(self, fp): | ||||
headerTuple = (self.FileMgcNumber, | ||||
self.nFDTdataRecors, | ||||
self.RadarUnitId, | ||||
self.SiteName, | ||||
self.size) | ||||
header = numpy.array(headerTuple, FILE_STRUCTURE) | ||||
# numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0) | ||||
header.tofile(fp) | ||||
''' ndarray.tofile(fid, sep, format) Write array to a file as text or binary (default). | ||||
fid : file or str | ||||
An open file object, or a string containing a filename. | ||||
sep : str | ||||
Separator between array items for text output. If “” (empty), a binary file is written, | ||||
equivalent to file.write(a.tobytes()). | ||||
format : str | ||||
Format string for text file output. Each entry in the array is formatted to text by | ||||
first converting it to the closest Python type, and then using “format” % item. | ||||
''' | ||||
return 1 | ||||
class RecordHeader(Header): | ||||
|
r1383 | RecMgcNumber = None # 0x23030001 | ||
RecCounter = None | ||||
Off2StartNxtRec = None | ||||
EpTimeStamp = None | ||||
msCompTimeStamp = None | ||||
ExpTagName = None | ||||
ExpComment = None | ||||
SiteLatDegrees = None | ||||
SiteLongDegrees = None | ||||
RTCgpsStatus = None | ||||
TransmitFrec = None | ||||
ReceiveFrec = None | ||||
FirstOsciFrec = None | ||||
Polarisation = None | ||||
ReceiverFiltSett = None | ||||
nModesInUse = None | ||||
DualModeIndex = None | ||||
DualModeRange = None | ||||
nDigChannels = None | ||||
SampResolution = None | ||||
nRangeGatesSamp = None | ||||
StartRangeSamp = None | ||||
PRFhz = None | ||||
Integrations = None | ||||
nDataPointsTrsf = None | ||||
nReceiveBeams = None | ||||
nSpectAverages = None | ||||
FFTwindowingInd = None | ||||
BeamAngleAzim = None | ||||
BeamAngleZen = None | ||||
AntennaCoord = None | ||||
RecPhaseCalibr = None | ||||
RecAmpCalibr = None | ||||
ReceiverGaindB = None | ||||
|
r965 | |||
'''size = None | ||||
nSamples = None | ||||
nProfiles = None | ||||
nChannels = None | ||||
adcResolution = None | ||||
pciDioBusWidth = None''' | ||||
|
r1383 | def __init__(self, RecMgcNumber=None, RecCounter=0, Off2StartNxtRec=0, | ||
EpTimeStamp=0, msCompTimeStamp=0, ExpTagName=None, | ||||
ExpComment=None, SiteLatDegrees=0, SiteLongDegrees=0, | ||||
RTCgpsStatus=0, TransmitFrec=0, ReceiveFrec=0, | ||||
FirstOsciFrec=0, Polarisation=0, ReceiverFiltSett=0, | ||||
nModesInUse=0, DualModeIndex=0, DualModeRange=0, | ||||
nDigChannels=0, SampResolution=0, nRangeGatesSamp=0, | ||||
StartRangeSamp=0, PRFhz=0, Integrations=0, | ||||
nDataPointsTrsf=0, nReceiveBeams=0, nSpectAverages=0, | ||||
FFTwindowingInd=0, BeamAngleAzim=0, BeamAngleZen=0, | ||||
AntennaCoord=0, RecPhaseCalibr=0, RecAmpCalibr=0, | ||||
ReceiverGaindB=0): | ||||
|
r965 | |||
|
r1383 | self.RecMgcNumber = RecMgcNumber # 0x23030001 | ||
|
r965 | self.RecCounter = RecCounter | ||
self.Off2StartNxtRec = Off2StartNxtRec | ||||
self.EpTimeStamp = EpTimeStamp | ||||
self.msCompTimeStamp = msCompTimeStamp | ||||
self.ExpTagName = ExpTagName | ||||
self.ExpComment = ExpComment | ||||
self.SiteLatDegrees = SiteLatDegrees | ||||
self.SiteLongDegrees = SiteLongDegrees | ||||
self.RTCgpsStatus = RTCgpsStatus | ||||
self.TransmitFrec = TransmitFrec | ||||
self.ReceiveFrec = ReceiveFrec | ||||
self.FirstOsciFrec = FirstOsciFrec | ||||
self.Polarisation = Polarisation | ||||
self.ReceiverFiltSett = ReceiverFiltSett | ||||
self.nModesInUse = nModesInUse | ||||
self.DualModeIndex = DualModeIndex | ||||
self.DualModeRange = DualModeRange | ||||
self.nDigChannels = nDigChannels | ||||
self.SampResolution = SampResolution | ||||
self.nRangeGatesSamp = nRangeGatesSamp | ||||
self.StartRangeSamp = StartRangeSamp | ||||
self.PRFhz = PRFhz | ||||
self.Integrations = Integrations | ||||
self.nDataPointsTrsf = nDataPointsTrsf | ||||
self.nReceiveBeams = nReceiveBeams | ||||
self.nSpectAverages = nSpectAverages | ||||
self.FFTwindowingInd = FFTwindowingInd | ||||
self.BeamAngleAzim = BeamAngleAzim | ||||
self.BeamAngleZen = BeamAngleZen | ||||
self.AntennaCoord = AntennaCoord | ||||
self.RecPhaseCalibr = RecPhaseCalibr | ||||
self.RecAmpCalibr = RecAmpCalibr | ||||
self.ReceiverGaindB = ReceiverGaindB | ||||
def read(self, fp): | ||||
|
r1383 | startFp = fp.tell() # The method tell() returns the current position of the file read/write pointer within the file. | ||
|
r965 | |||
try: | ||||
|
r1383 | header = numpy.fromfile(fp, RECORD_STRUCTURE, 1) | ||
|
r1167 | except Exception as e: | ||
print("System Header: " + e) | ||||
|
r965 | return 0 | ||
|
r1383 | self.RecMgcNumber = header['RecMgcNumber'][0] # 0x23030001 | ||
|
r965 | self.RecCounter = header['RecCounter'][0] | ||
self.Off2StartNxtRec = header['Off2StartNxtRec'][0] | ||||
self.EpTimeStamp = header['EpTimeStamp'][0] | ||||
self.msCompTimeStamp = header['msCompTimeStamp'][0] | ||||
self.ExpTagName = header['ExpTagName'][0] | ||||
self.ExpComment = header['ExpComment'][0] | ||||
self.SiteLatDegrees = header['SiteLatDegrees'][0] | ||||
self.SiteLongDegrees = header['SiteLongDegrees'][0] | ||||
self.RTCgpsStatus = header['RTCgpsStatus'][0] | ||||
self.TransmitFrec = header['TransmitFrec'][0] | ||||
self.ReceiveFrec = header['ReceiveFrec'][0] | ||||
self.FirstOsciFrec = header['FirstOsciFrec'][0] | ||||
self.Polarisation = header['Polarisation'][0] | ||||
self.ReceiverFiltSett = header['ReceiverFiltSett'][0] | ||||
self.nModesInUse = header['nModesInUse'][0] | ||||
self.DualModeIndex = header['DualModeIndex'][0] | ||||
self.DualModeRange = header['DualModeRange'][0] | ||||
self.nDigChannels = header['nDigChannels'][0] | ||||
self.SampResolution = header['SampResolution'][0] | ||||
self.nRangeGatesSamp = header['nRangeGatesSamp'][0] | ||||
self.StartRangeSamp = header['StartRangeSamp'][0] | ||||
self.PRFhz = header['PRFhz'][0] | ||||
self.Integrations = header['Integrations'][0] | ||||
self.nDataPointsTrsf = header['nDataPointsTrsf'][0] | ||||
self.nReceiveBeams = header['nReceiveBeams'][0] | ||||
self.nSpectAverages = header['nSpectAverages'][0] | ||||
self.FFTwindowingInd = header['FFTwindowingInd'][0] | ||||
self.BeamAngleAzim = header['BeamAngleAzim'][0] | ||||
self.BeamAngleZen = header['BeamAngleZen'][0] | ||||
self.AntennaCoord = header['AntennaCoord'][0] | ||||
self.RecPhaseCalibr = header['RecPhaseCalibr'][0] | ||||
self.RecAmpCalibr = header['RecAmpCalibr'][0] | ||||
self.ReceiverGaindB = header['ReceiverGaindB'][0] | ||||
|
r1383 | Self.size = 180 + 20 * 3 | ||
|
r965 | |||
endFp = self.size + startFp | ||||
if fp.tell() > endFp: | ||||
|
r1383 | sys.stderr.write("Warning %s: Size value read from System Header is lower than it has to be\n" % fp.name) | ||
|
r965 | return 0 | ||
if fp.tell() < endFp: | ||||
|
r1383 | sys.stderr.write("Warning %s: Size value read from System Header size is greater than it has to be\n" % fp.name) | ||
|
r965 | return 0 | ||
return 1 | ||||
def write(self, fp): | ||||
headerTuple = (self.RecMgcNumber, | ||||
|
r1383 | self.RecCounter, | ||
self.Off2StartNxtRec, | ||||
self.EpTimeStamp, | ||||
self.msCompTimeStamp, | ||||
self.ExpTagName, | ||||
self.ExpComment, | ||||
self.SiteLatDegrees, | ||||
self.SiteLongDegrees, | ||||
self.RTCgpsStatus, | ||||
self.TransmitFrec, | ||||
self.ReceiveFrec, | ||||
self.FirstOsciFrec, | ||||
self.Polarisation, | ||||
self.ReceiverFiltSett, | ||||
self.nModesInUse, | ||||
self.DualModeIndex, | ||||
self.DualModeRange, | ||||
|
r965 | self.nDigChannels, | ||
|
r1383 | self.SampResolution, | ||
self.nRangeGatesSamp, | ||||
self.StartRangeSamp, | ||||
self.PRFhz, | ||||
self.Integrations, | ||||
self.nDataPointsTrsf, | ||||
self.nReceiveBeams, | ||||
self.nSpectAverages, | ||||
self.FFTwindowingInd, | ||||
self.BeamAngleAzim, | ||||
self.BeamAngleZen, | ||||
self.AntennaCoord, | ||||
self.RecPhaseCalibr, | ||||
self.RecAmpCalibr, | ||||
|
r965 | self.ReceiverGaindB) | ||
# self.size,self.nSamples, | ||||
# self.nProfiles, | ||||
# self.nChannels, | ||||
# self.adcResolution, | ||||
# self.pciDioBusWidth | ||||
|
r1383 | header = numpy.array(headerTuple, RECORD_STRUCTURE) | ||
|
r965 | header.tofile(fp) | ||
return 1 | ||||
def get_dtype_index(numpy_dtype): | ||||
index = None | ||||
for i in range(len(NUMPY_DTYPE_LIST)): | ||||
if numpy_dtype == NUMPY_DTYPE_LIST[i]: | ||||
index = i | ||||
break | ||||
return index | ||||
def get_numpy_dtype(index): | ||||
|
r1383 | # dtype4 = numpy.dtype([('real','<f4'),('imag','<f4')]) | ||
|
r965 | |||
return NUMPY_DTYPE_LIST[index] | ||||
def get_dtype_width(index): | ||||
|
r1383 | return DTYPE_WIDTH[index] | ||