def test_encode_decode(): num_bins = 30 num_beams = 4 vel = EarthVelocity(num_bins, num_beams) # Populate data val = 1.0 for beam in range(vel.element_multiplier): for bin_num in range(vel.num_elements): vel.Velocities[bin_num][beam] = val val += 1.1 vel.Magnitude, vel.Direction = EarthVelocity.generate_vectors( vel.Velocities) result = vel.encode() vel1 = EarthVelocity(num_bins, num_beams) vel1.decode(bytearray(result)) for beam in range(vel1.element_multiplier): for bin_num in range(vel1.num_elements): assert vel.Velocities[bin_num][beam] == pytest.approx( vel1.Velocities[bin_num][beam], 0.1) assert vel.Magnitude[bin_num] == pytest.approx( vel1.Magnitude[bin_num], 0.1) assert vel.Direction[bin_num] == pytest.approx( vel1.Direction[bin_num], 0.1)
def test_avg_mag_dir_nan(): num_bins = 30 num_beams = 4 vel = EarthVelocity(num_bins, num_beams) vel.Magnitude = [np.NaN, np.NaN] vel.Direction = [np.NaN, np.NaN] avg_mag, avg_dir = vel.average_mag_dir() assert avg_mag is None assert avg_dir is None
def test_avg_mag_dir_nan(): num_bins = 30 num_beams = 4 vel = EarthVelocity(num_bins, num_beams) vel.Magnitude = [5.0, 5.0, 5.0, 5.0, np.NaN] vel.Direction = [1.2, 1.2, 1.2, 1.2, np.NaN] avg_mag, avg_dir = vel.average_mag_dir() assert avg_mag == pytest.approx(5, 0.001) assert avg_dir == pytest.approx(1.2, 0.001)
def test_encode_csv_vector_no_gen(): num_bins = 30 num_beams = 4 vel = EarthVelocity(num_bins, num_beams) # Populate data val = 2.0 for beam in range(vel.element_multiplier): for bin_num in range(vel.num_elements): vel.Velocities[bin_num][beam] = val vel.Magnitude, vel.Direction = EarthVelocity.generate_vectors( vel.Velocities) vel.remove_vessel_speed(-1.3, -1.4, 0.3) dt = datetime.datetime.now() # Create CSV lines result = vel.encode_csv(dt, 'A', 1, 1.3, 1.0) # Check the csv data for line in result: if bool(re.search(Ensemble.CSV_MAG, line[0])): assert bool(re.search(str(2.477), line[0])) assert bool(re.search(Ensemble.CSV_MAG, line[0])) elif bool(re.search(Ensemble.CSV_DIR, line[0])): assert bool(re.search(str(49.3987), line[0])) assert bool(re.search(Ensemble.CSV_DIR, line[0])) elif bool(re.search(Ensemble.CSV_EARTH_VEL, line[0])): assert True else: assert False
def test_vectors(): earth = EarthVelocity(3, 4) earth.Velocities.clear() earth.Velocities.append([1.33, 1.45, 0.3, 0.0]) earth.Velocities.append([1.33, 1.45, 0.3, 0.0]) earth.Velocities.append([1.33, 1.45, 0.3, 0.0]) earth.remove_vessel_speed(-1.1, -1.2, -0.1) mag, dir = EarthVelocity.generate_vectors(earth.Velocities) assert 3 == len(mag) assert 3 == len(dir) assert 0.394 == pytest.approx(mag[0], 0.01) assert 42.614 == pytest.approx(dir[0], 0.01) assert 0.394 == pytest.approx(mag[1], 0.01) assert 42.614 == pytest.approx(dir[1], 0.01) assert 0.394 == pytest.approx(mag[2], 0.01) assert 42.614 == pytest.approx(dir[2], 0.01)
def test_encode_csv(): num_bins = 30 num_beams = 4 vel = EarthVelocity(num_bins, num_beams) # Populate data val = 1.0 for beam in range(vel.element_multiplier): for bin_num in range(vel.num_elements): vel.Velocities[bin_num][beam] = val val += 1.1 vel.Magnitude, vel.Direction = EarthVelocity.generate_vectors( vel.Velocities) dt = datetime.datetime.now() # Create CSV lines result = vel.encode_csv(dt, 'A', 1, 1.3, 1.0) # Check the csv data test_value = 1.0 for line in result: if bool(re.search(Ensemble.CSV_EARTH_VEL, line[0])): assert bool(re.search(str(test_value), line[0])) assert bool(re.search(Ensemble.CSV_EARTH_VEL, line[0])) test_value += 1.1
def test_encode_decode(): num_bins = 33 num_beams = 4 ens = Ensemble() ens_ds = EnsembleData() ens_ds.EnsembleNumber = 2668 ens_ds.NumBins = 33 ens_ds.NumBeams = 4 ens_ds.DesiredPingCount = 45 ens_ds.ActualPingCount = 46 ens_ds.SerialNumber = "01H00000000000000000000000999999" ens_ds.SysFirmwareMajor = 2 ens_ds.SysFirmwareMinor = 11 ens_ds.SysFirmwareRevision = 5 ens_ds.SysFirmwareSubsystemCode = "A" ens_ds.SubsystemConfig = 3 ens_ds.Status = 9 ens_ds.Year = 2019 ens_ds.Month = 3 ens_ds.Day = 9 ens_ds.Hour = 12 ens_ds.Minute = 23 ens_ds.Second = 24 ens_ds.HSec = 33 anc = AncillaryData() anc.FirstBinRange = 1.0 # Blank. Depth to the first bin in meters. anc.BinSize = 3.0 # Size of a bin in meters. anc.FirstPingTime = 1.2 # First Ping Time in seconds. anc.LastPingTime = 2.3 # Last Ping Time in seconds. (If averaging pings, this will be the last ping) anc.Heading = 23.5 # Heading in degrees. anc.Pitch = 13.6 # Pitch in degrees. anc.Roll = 11.25 # Roll in degrees. anc.WaterTemp = 25.3 # Water Temperature in fahrenheit anc.SystemTemp = 54.6 # System Temperature in fahrenheit anc.Salinity = 35.0 # Water Salinity set by the user in PPT anc.Pressure = 23.78 # Pressure from pressure sensor in Pascals anc.TransducerDepth = 45.69 # Transducer Depth, used by Pressure sensor in meters anc.SpeedOfSound = 1400.23 # Speed of Sound in m/s. anc.RawMagFieldStrength = 3.0 # Raw magnetic field strength anc.PitchGravityVector = 4.0 # Pitch Gravity Vector anc.RollGravityVector = 5.0 # Roll Gravity Vector anc.VerticalGravityVector = 6.0 # Vertical Gravity Vector amp = Amplitude(num_bins, num_beams) corr = Correlation(num_bins, num_beams) beam_vel = BeamVelocity(num_bins, num_beams) inst_vel = InstrumentVelocity(num_bins, num_beams) earth_vel = EarthVelocity(num_bins, num_beams) gb = GoodBeam(num_bins, num_beams) ge = GoodEarth(num_bins, num_beams) val = 1.0 for beam in range(amp.element_multiplier): for bin_num in range(amp.num_elements): amp.Amplitude[bin_num][beam] = val corr.Correlation[bin_num][beam] = val beam_vel.Velocities[bin_num][beam] = val inst_vel.Velocities[bin_num][beam] = val earth_vel.Velocities[bin_num][beam] = val gb.GoodBeam[bin_num][beam] = 1 * int(beam) ge.GoodEarth[bin_num][beam] = 1 * int(beam) val += 1.1 bt = BottomTrack() bt.FirstPingTime = 12.5 bt.LastPingTime = 12.8 bt.Heading = 152.36 bt.Pitch = 12.6 bt.Roll = 223.1 bt.WaterTemp = 15.23 bt.SystemTemp = 78.58 bt.Salinity = 35.0 bt.Pressure = 23.36 bt.TransducerDepth = 156.2 bt.SpeedOfSound = 1402.36 bt.Status = 9.0 bt.NumBeams = 4.0 bt.ActualPingCount = 23 bt.Range = [1.1, 2.2, 3.3, 4.4] bt.SNR = [1.1, 2.2, 3.3, 4.4] bt.Amplitude = [1.1, 2.2, 3.3, 4.4] bt.Correlation = [1.1, 2.2, 3.3, 4.4] bt.BeamVelocity = [1.1, 2.2, 3.3, 4.4] bt.BeamGood = [1, 2, 3, 4] bt.InstrumentVelocity = [1.1, 2.2, 3.3, 4.4] bt.InstrumentGood = [1, 2, 3, 4] bt.EarthVelocity = [1.1, 2.2, 3.3, 4.4] bt.EarthGood = [1, 2, 3, 4] bt.SNR_PulseCoherent = [1, 2, 3, 4] bt.Amp_PulseCoherent = [1, 2, 3, 4] bt.Vel_PulseCoherent = [1, 2, 3, 4] bt.Noise_PulseCoherent = [1, 2, 3, 4] bt.Corr_PulseCoherent = [1, 2, 3, 4] rt = RangeTracking() rt.NumBeams = 4.0 rt.Range = [1.1, 2.2, 3.3, 4.4] rt.Pings = [1, 2, 3, 4] rt.SNR = [1.1, 2.2, 3.3, 4.4] rt.Amplitude = [1.1, 2.2, 3.3, 4.4] rt.Correlation = [1.1, 2.2, 3.3, 4.4] rt.BeamVelocity = [1.1, 2.2, 3.3, 4.4] rt.InstrumentVelocity = [1.1, 2.2, 3.3, 4.4] rt.EarthVelocity = [1.1, 2.2, 3.3, 4.4] nmea = NmeaData() nmea.add_nmea("$HEHDT,244.39,T*17\n") nmea.add_nmea( "$GPGGA,195949.00,3254.8103248,N,11655.5779629,W,2,08,1.1,222.174,M,-32.602,M,6.0,0138*75\n" ) nmea.add_nmea("$GPVTG,306.20,T,294.73,M,0.13,N,0.24,K,D*2E\n") nmea.add_nmea("$HEHDT,244.36,T*18\n") ss = SystemSetup() ss.BtSamplesPerSecond = 1.0 ss.BtSystemFreqHz = 3.0 ss.BtCPCE = 1.2 ss.BtNCE = 2.3 ss.BtRepeatN = 23.5 ss.WpSamplesPerSecond = 13.6 ss.WpSystemFreqHz = 11.25 ss.WpCPCE = 25.3 ss.WpNCE = 54.6 ss.WpRepeatN = 35.0 ss.WpLagSamples = 23.78 ss.Voltage = 45.69 ss.XmtVoltage = 1400.23 ss.BtBroadband = 3.0 ss.BtLagLength = 4.0 ss.BtNarrowband = 5.0 ss.BtBeamMux = 6.0 ss.WpBroadband = 6.0 ss.WpLagLength = 6.0 ss.WpTransmitBandwidth = 6.0 ss.WpReceiveBandwidth = 6.0 ens.AddAmplitude(amp) ens.AddCorrelation(corr) ens.AddBeamVelocity(beam_vel) ens.AddInstrumentVelocity(inst_vel) ens.AddEarthVelocity(earth_vel) ens.AddGoodBeam(gb) ens.AddGoodEarth(ge) ens.AddAncillaryData(anc) ens.AddEnsembleData(ens_ds) ens.AddBottomTrack(bt) ens.AddRangeTracking(rt) ens.AddSystemSetup(ss) ens.AddNmeaData(nmea) # Encode the ensemble to binar binary_ens = ens.encode() # Use the codec to decode the data ens1 = BinaryCodec.decode_data_sets(binary_ens[:-4]) # Remove the checksum assert ens.EnsembleData.EnsembleNumber == ens1.EnsembleData.EnsembleNumber assert ens.EnsembleData.NumBins == ens1.EnsembleData.NumBins assert ens.EnsembleData.NumBeams == ens1.EnsembleData.NumBeams assert ens.EnsembleData.DesiredPingCount == ens1.EnsembleData.DesiredPingCount assert ens.EnsembleData.ActualPingCount == ens1.EnsembleData.ActualPingCount assert ens.EnsembleData.SerialNumber == ens1.EnsembleData.SerialNumber assert ens.EnsembleData.SysFirmwareMajor == ens1.EnsembleData.SysFirmwareMajor assert ens.EnsembleData.SysFirmwareMinor == ens1.EnsembleData.SysFirmwareMinor assert ens.EnsembleData.SysFirmwareRevision == ens1.EnsembleData.SysFirmwareRevision assert ens.EnsembleData.SysFirmwareSubsystemCode == ens1.EnsembleData.SysFirmwareSubsystemCode assert ens.EnsembleData.SubsystemConfig == ens1.EnsembleData.SubsystemConfig assert ens.EnsembleData.Status == ens1.EnsembleData.Status assert ens.EnsembleData.Year == ens1.EnsembleData.Year assert ens.EnsembleData.Month == ens1.EnsembleData.Month assert ens.EnsembleData.Day == ens1.EnsembleData.Day assert ens.EnsembleData.Hour == ens1.EnsembleData.Hour assert ens.EnsembleData.Minute == ens1.EnsembleData.Minute assert ens.EnsembleData.Second == ens1.EnsembleData.Second assert ens.EnsembleData.HSec == ens1.EnsembleData.HSec assert anc.FirstBinRange == pytest.approx(ens1.AncillaryData.FirstBinRange, 0.1) assert anc.BinSize == pytest.approx(ens1.AncillaryData.BinSize, 0.1) assert anc.FirstPingTime == pytest.approx(ens1.AncillaryData.FirstPingTime, 0.1) assert anc.LastPingTime == pytest.approx(ens1.AncillaryData.LastPingTime, 0.1) assert anc.Heading == pytest.approx(ens1.AncillaryData.Heading, 0.1) assert anc.Pitch == pytest.approx(ens1.AncillaryData.Pitch, 0.1) assert anc.Roll == pytest.approx(ens1.AncillaryData.Roll, 0.1) assert anc.WaterTemp == pytest.approx(ens1.AncillaryData.WaterTemp, 0.1) assert anc.SystemTemp == pytest.approx(ens1.AncillaryData.SystemTemp, 0.1) assert anc.Salinity == pytest.approx(ens1.AncillaryData.Salinity, 0.1) assert anc.Pressure == pytest.approx(ens1.AncillaryData.Pressure, 0.1) assert anc.TransducerDepth == pytest.approx( ens1.AncillaryData.TransducerDepth, 0.1) assert anc.SpeedOfSound == pytest.approx(ens1.AncillaryData.SpeedOfSound, 0.1) assert anc.RawMagFieldStrength == pytest.approx( ens1.AncillaryData.RawMagFieldStrength, 0.1) assert anc.PitchGravityVector == pytest.approx( ens1.AncillaryData.PitchGravityVector, 0.1) assert anc.RollGravityVector == pytest.approx( ens1.AncillaryData.RollGravityVector, 0.1) assert anc.VerticalGravityVector == pytest.approx( ens1.AncillaryData.VerticalGravityVector, 0.1) for beam in range(amp.element_multiplier): for bin_num in range(amp.num_elements): assert amp.Amplitude[bin_num][beam] == pytest.approx( ens1.Amplitude.Amplitude[bin_num][beam], 0.1) for beam in range(corr.element_multiplier): for bin_num in range(corr.num_elements): assert corr.Correlation[bin_num][beam] == pytest.approx( ens1.Correlation.Correlation[bin_num][beam], 0.1) for beam in range(beam_vel.element_multiplier): for bin_num in range(beam_vel.num_elements): assert beam_vel.Velocities[bin_num][beam] == pytest.approx( ens1.Wt.Velocities[bin_num][beam], 0.1) for beam in range(beam_vel.element_multiplier): for bin_num in range(beam_vel.num_elements): assert inst_vel.Velocities[bin_num][beam] == pytest.approx( ens1.InstrumentVelocity.Velocities[bin_num][beam], 0.1) for beam in range(beam_vel.element_multiplier): for bin_num in range(beam_vel.num_elements): assert earth_vel.Velocities[bin_num][beam] == pytest.approx( ens1.EarthVelocity.Velocities[bin_num][beam], 0.1) #for beam in range(gb.element_multiplier): # for bin_num in range(gb.num_elements): # assert gb.GoodBeam[bin_num][beam] == pytest.approx(ens1.GoodBeam.GoodBeam[bin_num][beam], 0.1) for beam in range(ge.element_multiplier): for bin_num in range(ge.num_elements): assert ge.GoodEarth[bin_num][beam] == pytest.approx( ens1.GoodEarth.GoodEarth[bin_num][beam], 0.1) assert bt.FirstPingTime == pytest.approx(ens1.BottomTrack.FirstPingTime) assert bt.LastPingTime == pytest.approx(ens1.BottomTrack.LastPingTime) assert bt.Heading == pytest.approx(ens1.BottomTrack.Heading) assert bt.Pitch == pytest.approx(ens1.BottomTrack.Pitch) assert bt.Roll == pytest.approx(ens1.BottomTrack.Roll) assert bt.WaterTemp == pytest.approx(ens1.BottomTrack.WaterTemp) assert bt.SystemTemp == pytest.approx(ens1.BottomTrack.SystemTemp) assert bt.Salinity == pytest.approx(ens1.BottomTrack.Salinity) assert bt.Pressure == pytest.approx(ens1.BottomTrack.Pressure) assert bt.TransducerDepth == pytest.approx( ens1.BottomTrack.TransducerDepth) assert bt.SpeedOfSound == pytest.approx(ens1.BottomTrack.SpeedOfSound) assert bt.Status == pytest.approx(ens1.BottomTrack.Status) assert bt.NumBeams == pytest.approx(ens1.BottomTrack.NumBeams) assert bt.ActualPingCount == pytest.approx( ens1.BottomTrack.ActualPingCount) assert bt.Range == pytest.approx(ens1.BottomTrack.Range) assert bt.SNR == pytest.approx(ens1.BottomTrack.SNR) assert bt.Amplitude == pytest.approx(ens1.BottomTrack.Amplitude) assert bt.Correlation == pytest.approx(ens1.BottomTrack.Correlation) assert bt.BeamVelocity == pytest.approx(ens1.BottomTrack.Wt) assert bt.BeamGood == pytest.approx(ens1.BottomTrack.BeamGood, 0.1) assert bt.InstrumentVelocity == pytest.approx( ens1.BottomTrack.InstrumentVelocity) assert bt.InstrumentGood == pytest.approx(ens1.BottomTrack.InstrumentGood, 0.1) assert bt.EarthVelocity == pytest.approx(ens1.BottomTrack.EarthVelocity) assert bt.EarthGood == pytest.approx(ens1.BottomTrack.EarthGood, 0.1) assert bt.SNR_PulseCoherent == pytest.approx( ens1.BottomTrack.SNR_PulseCoherent, 0.1) assert bt.Amp_PulseCoherent == pytest.approx( ens1.BottomTrack.Amp_PulseCoherent, 0.1) assert bt.Vel_PulseCoherent == pytest.approx( ens1.BottomTrack.Vel_PulseCoherent, 0.1) assert bt.Noise_PulseCoherent == pytest.approx( ens1.BottomTrack.Noise_PulseCoherent, 0.1) assert bt.Corr_PulseCoherent == pytest.approx( ens1.BottomTrack.Corr_PulseCoherent, 0.1) assert rt.NumBeams == ens1.RangeTracking.NumBeams assert rt.Range == pytest.approx(ens1.RangeTracking.Range) assert rt.SNR == pytest.approx(ens1.RangeTracking.SNR) assert rt.Amplitude == pytest.approx(ens1.RangeTracking.Amplitude) assert rt.Correlation == pytest.approx(ens1.RangeTracking.Correlation) assert rt.BeamVelocity == pytest.approx(ens1.RangeTracking.Wt) assert rt.InstrumentVelocity == pytest.approx( ens1.RangeTracking.InstrumentVelocity) assert rt.EarthVelocity == pytest.approx(ens1.RangeTracking.EarthVelocity) assert nmea.nmea_sentences == ens1.NmeaData.nmea_sentences assert ss.BtSamplesPerSecond == pytest.approx( ens1.SystemSetup.BtSamplesPerSecond, 0.1) assert ss.BtSystemFreqHz == pytest.approx(ens1.SystemSetup.BtSystemFreqHz, 0.1) assert ss.BtCPCE == pytest.approx(ens1.SystemSetup.BtCPCE, 0.1) assert ss.BtNCE == pytest.approx(ens1.SystemSetup.BtNCE, 0.1) assert ss.BtRepeatN == pytest.approx(ens1.SystemSetup.BtRepeatN, 0.1) assert ss.WpSamplesPerSecond == pytest.approx( ens1.SystemSetup.WpSamplesPerSecond, 0.1) assert ss.WpSystemFreqHz == pytest.approx(ens1.SystemSetup.WpSystemFreqHz, 0.1) assert ss.WpCPCE == pytest.approx(ens1.SystemSetup.WpCPCE, 0.1) assert ss.WpNCE == pytest.approx(ens1.SystemSetup.WpNCE, 0.1) assert ss.WpRepeatN == pytest.approx(ens1.SystemSetup.WpRepeatN, 0.1) assert ss.WpLagSamples == pytest.approx(ens1.SystemSetup.WpLagSamples, 0.1) assert ss.Voltage == pytest.approx(ens1.SystemSetup.Voltage, 0.1) assert ss.XmtVoltage == pytest.approx(ens1.SystemSetup.XmtVoltage, 0.1) assert ss.BtBroadband == pytest.approx(ens1.SystemSetup.BtBroadband, 0.1) assert ss.BtLagLength == pytest.approx(ens1.SystemSetup.BtLagLength, 0.1) assert ss.BtNarrowband == pytest.approx(ens1.SystemSetup.BtNarrowband, 0.1) assert ss.BtBeamMux == pytest.approx(ens1.SystemSetup.BtBeamMux, 0.1) assert ss.WpBroadband == pytest.approx(ens1.SystemSetup.WpBroadband, 0.1) assert ss.WpLagLength == pytest.approx(ens1.SystemSetup.WpLagLength, 0.1) assert ss.WpTransmitBandwidth == pytest.approx( ens1.SystemSetup.WpTransmitBandwidth, 0.1) assert ss.WpReceiveBandwidth == pytest.approx( ens1.SystemSetup.WpReceiveBandwidth, 0.1)
def test_encode_csv_no_anc(): num_bins = 33 num_beams = 4 ens = Ensemble() amp = Amplitude(num_bins, num_beams) corr = Correlation(num_bins, num_beams) beam_vel = BeamVelocity(num_bins, num_beams) inst_vel = InstrumentVelocity(num_bins, num_beams) earth_vel = EarthVelocity(num_bins, num_beams) gb = GoodBeam(num_bins, num_beams) ge = GoodEarth(num_bins, num_beams) anc = AncillaryData() ensData = EnsembleData() ss = SystemSetup() bt = BottomTrack() bt.NumBeams = 4 bt.Range = [1.1, 2.2, 3.3, 4.4] bt.SNR = [1.1, 2.2, 3.3, 4.4] bt.Amplitude = [1.1, 2.2, 3.3, 4.4] bt.Correlation = [1.1, 2.2, 3.3, 4.4] bt.BeamVelocity = [1.1, 2.2, 3.3, 4.4] bt.BeamGood = [1, 2, 3, 4] bt.InstrumentVelocity = [1.1, 2.2, 3.3, 4.4] bt.InstrumentGood = [1, 2, 3, 4] bt.EarthVelocity = [1.1, 2.2, 3.3, 4.4] bt.EarthGood = [1, 2, 3, 4] bt.SNR_PulseCoherent = [1, 2, 3, 4] bt.Amp_PulseCoherent = [1, 2, 3, 4] bt.Vel_PulseCoherent = [1, 2, 3, 4] bt.Noise_PulseCoherent = [1, 2, 3, 4] bt.Corr_PulseCoherent = [1, 2, 3, 4] rt = RangeTracking() rt.NumBeams = 4.0 rt.Range = [1.1, 2.2, 3.3, 4.4] rt.Pings = [1, 2, 3, 4] rt.SNR = [1.1, 2.2, 3.3, 4.4] rt.Amplitude = [1.1, 2.2, 3.3, 4.4] rt.Correlation = [1.1, 2.2, 3.3, 4.4] rt.BeamVelocity = [1.1, 2.2, 3.3, 4.4] rt.InstrumentVelocity = [1.1, 2.2, 3.3, 4.4] rt.EarthVelocity = [1.1, 2.2, 3.3, 4.4] ens.AddAmplitude(amp) ens.AddCorrelation(corr) ens.AddBeamVelocity(beam_vel) ens.AddInstrumentVelocity(inst_vel) ens.AddEarthVelocity(earth_vel) ens.AddGoodBeam(gb) ens.AddGoodEarth(ge) ens.AddAncillaryData(anc) ens.AddEnsembleData(ensData) ens.AddBottomTrack(bt) ens.AddRangeTracking(rt) ens.AddSystemSetup(ss) results = ens.encode_csv(is_ancillary_data=False) total_lines = num_bins * num_beams * 7 total_lines += num_bins * 2 # Mag and Direction in EarthVelocity total_lines += 6 + (num_beams * 7) # Bottom Track total_lines += 1 # Ensemble Data #total_lines += 10 # Ancillary Data total_lines += 5 * num_beams # Range Tracking total_lines += 1 # System Settings assert len(results) == total_lines
def decode_data_sets(ens): """ Decode the datasets in the ensemble. Use verify_ens_data if you are using this as a static method to verify the data is correct. :param ens: Ensemble data. Decode the dataset. :return: Return the decoded ensemble. """ #print(ens) packetPointer = Ensemble().HeaderSize type = 0 numElements = 0 elementMultiplier = 0 imag = 0 nameLen = 0 name = "" dataSetSize = 0 ens_len = len(ens) # Create the ensemble ensemble = Ensemble() # Add the raw data to the ensemble #ensemble.AddRawData(ens) try: # Decode the ensemble datasets for x in range(Ensemble().MaxNumDataSets): # Check if we are at the end of the payload if packetPointer >= ens_len - Ensemble.ChecksumSize - Ensemble.HeaderSize: break try: # Get the dataset info ds_type = Ensemble.GetInt32(packetPointer + (Ensemble.BytesInInt32 * 0), Ensemble().BytesInInt32, ens) num_elements = Ensemble.GetInt32(packetPointer + (Ensemble.BytesInInt32 * 1), Ensemble().BytesInInt32, ens) element_multiplier = Ensemble.GetInt32(packetPointer + (Ensemble.BytesInInt32 * 2), Ensemble().BytesInInt32, ens) image = Ensemble.GetInt32(packetPointer + (Ensemble.BytesInInt32 * 3), Ensemble().BytesInInt32, ens) name_len = Ensemble.GetInt32(packetPointer + (Ensemble.BytesInInt32 * 4), Ensemble().BytesInInt32, ens) name = str(ens[packetPointer+(Ensemble.BytesInInt32 * 5):packetPointer+(Ensemble.BytesInInt32 * 5)+8], 'UTF-8') except Exception as e: logging.warning("Bad Ensemble header" + str(e)) break # Calculate the dataset size data_set_size = Ensemble.GetDataSetSize(ds_type, name_len, num_elements, element_multiplier) # Beam Velocity if "E000001" in name: logging.debug(name) bv = BeamVelocity(num_elements, element_multiplier) bv.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddBeamVelocity(bv) # Instrument Velocity if "E000002" in name: logging.debug(name) iv = InstrumentVelocity(num_elements, element_multiplier) iv.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddInstrumentVelocity(iv) # Earth Velocity if "E000003" in name: logging.debug(name) ev = EarthVelocity(num_elements, element_multiplier) ev.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddEarthVelocity(ev) # Amplitude if "E000004" in name: logging.debug(name) amp = Amplitude(num_elements, element_multiplier) amp.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddAmplitude(amp) # Correlation if "E000005" in name: logging.debug(name) corr = Correlation(num_elements, element_multiplier) corr.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddCorrelation(corr) # Good Beam if "E000006" in name: logging.debug(name) gb = GoodBeam(num_elements, element_multiplier) gb.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddGoodBeam(gb) # Good Earth if "E000007" in name: logging.debug(name) ge = GoodEarth(num_elements, element_multiplier) ge.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddGoodEarth(ge) # Ensemble Data if "E000008" in name: logging.debug(name) ed = EnsembleData(num_elements, element_multiplier) ed.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddEnsembleData(ed) # Ancillary Data if "E000009" in name: logging.debug(name) ad = AncillaryData(num_elements, element_multiplier) ad.decode(ens[packetPointer:packetPointer+data_set_size]) ensemble.AddAncillaryData(ad) # Bottom Track if "E000010" in name: logging.debug(name) bt = BottomTrack(num_elements, element_multiplier) bt.decode(ens[packetPointer:packetPointer + data_set_size]) ensemble.AddBottomTrack(bt) # NMEA data if "E000011" in name: logging.debug(name) nd = NmeaData(num_elements, element_multiplier) nd.decode(ens[packetPointer:packetPointer + data_set_size]) ensemble.AddNmeaData(nd) # System Setup if "E000014" in name: logging.debug(name) ss = SystemSetup(num_elements, element_multiplier) ss.decode(ens[packetPointer:packetPointer + data_set_size]) ensemble.AddSystemSetup(ss) # Range Tracking if "E000015" in name: logging.debug(name) rt = RangeTracking(num_elements, element_multiplier) rt.decode(ens[packetPointer:packetPointer + data_set_size]) ensemble.AddRangeTracking(rt) # Move to the next dataset packetPointer += data_set_size except Exception as e: logging.warning("Error decoding the ensemble. " + str(e)) return None return ensemble
def test_velocities(): vels = EarthVelocity(30, 4) # Populate data val = 1.0 for beam in range(vels.element_multiplier): for bin_num in range(vels.num_elements): vels.Velocities[bin_num][beam] = val val += 1.1 result = vels.encode() # Value type assert 0xA == result[0] assert 0x0 == result[1] assert 0x0 == result[2] assert 0x0 == result[3] # Num Elements assert 0x1E == result[4] assert 0x0 == result[5] assert 0x0 == result[6] assert 0x0 == result[7] # Element Multiplier assert 0x4 == result[8] assert 0x0 == result[9] assert 0x0 == result[10] assert 0x0 == result[11] # Imag assert 0x0 == result[12] assert 0x0 == result[13] assert 0x0 == result[14] assert 0x0 == result[15] # Name Length assert 0x8 == result[16] assert 0x0 == result[17] assert 0x0 == result[18] assert 0x0 == result[19] # Name assert ord('E') == result[20] assert ord('0') == result[21] assert ord('0') == result[22] assert ord('0') == result[23] assert ord('0') == result[24] assert ord('0') == result[25] assert ord('3') == result[26] assert ord('\0') == result[27] # Length assert len(result) == 28 + ( (vels.element_multiplier * vels.num_elements) * Ensemble.BytesInFloat) # Beam Velocities data result_val = 1.0 index = 28 # 28 = Header size for beam in range(vels.element_multiplier): for bin_num in range(vels.num_elements): test_val = Ensemble.GetFloat(index, Ensemble().BytesInFloat, bytearray(result)) assert result_val == pytest.approx(test_val, 0.1) result_val += 1.1 index += Ensemble().BytesInFloat
def test_calc_discharge(): ens = Ensemble() ens_data = EnsembleData() ens_data.NumBeams = 4 ens_data.NumBins = 4 ens.AddEnsembleData(ens_data) anc = AncillaryData() anc.BinSize = 1 anc.FirstBinRange = 0.5 ens.AddAncillaryData(anc) vel = EarthVelocity(4, 4) vel.Velocities[0][0] = 1.0 vel.Velocities[0][1] = 1.1 vel.Velocities[0][2] = 0.2 vel.Velocities[0][3] = 0.0 vel.Velocities[1][0] = 1.1 vel.Velocities[1][1] = 1.2 vel.Velocities[1][2] = 0.3 vel.Velocities[1][3] = 0.0 vel.Velocities[2][0] = 1.2 vel.Velocities[2][1] = 1.3 vel.Velocities[2][2] = 0.4 vel.Velocities[2][3] = 0.0 vel.Velocities[3][0] = 1.4 vel.Velocities[3][1] = 1.5 vel.Velocities[3][2] = 0.6 vel.Velocities[3][3] = 0.0 ens.AddEarthVelocity(vel) bt = BottomTrack() bt.NumBeams = 4 bt.Range = [23.5, 24.2, 22.4, 26.1] ens.AddBottomTrack(bt) discharge = CalcDischarge() boat_draft = 0.1 beam_angle = 20 pulse_length = 0.8 pulse_lag = 0.1 bt_east = 0.9 bt_north = 0.9 bt_vert = 0.1 delta_time = 0.15 top_flow_mode = FlowMode.Constants top_pwr_func_exponent = CalcDischarge.ONE_SIXTH_POWER_LAW bottom_flow_mode = FlowMode.PowerFunction result = discharge.calculate_ensemble_flow(ens, boat_draft, beam_angle, pulse_length, pulse_lag, bt_east, bt_north, bt_vert, delta_time, top_flow_mode, top_pwr_func_exponent, bottom_flow_mode) assert result.valid == True assert -0.2284 == pytest.approx(result.bottom_flow, 0.001) assert -0.00135 == pytest.approx(result.top_flow, 0.001) assert -0.054 == pytest.approx(result.measured_flow, 0.001)
def test_write_binary(): num_bins = 33 num_beams = 4 ens = Ensemble() ens_ds = EnsembleData() ens_ds.EnsembleNumber = 2668 ens_ds.NumBins = 33 ens_ds.NumBeams = 4 ens_ds.DesiredPingCount = 45 ens_ds.ActualPingCount = 46 ens_ds.SerialNumber = "01H00000000000000000000000999999" ens_ds.SysFirmwareMajor = 2 ens_ds.SysFirmwareMinor = 11 ens_ds.SysFirmwareRevision = 5 ens_ds.SysFirmwareSubsystemCode = "A" ens_ds.SubsystemConfig = 3 ens_ds.Status = 9 ens_ds.Year = 2019 ens_ds.Month = 3 ens_ds.Day = 9 ens_ds.Hour = 12 ens_ds.Minute = 23 ens_ds.Second = 24 ens_ds.HSec = 33 anc = AncillaryData() anc.FirstBinRange = 1.0 # Blank. Depth to the first bin in meters. anc.BinSize = 3.0 # Size of a bin in meters. anc.FirstPingTime = 1.2 # First Ping Time in seconds. anc.LastPingTime = 2.3 # Last Ping Time in seconds. (If averaging pings, this will be the last ping) anc.Heading = 23.5 # Heading in degrees. anc.Pitch = 13.6 # Pitch in degrees. anc.Roll = 11.25 # Roll in degrees. anc.WaterTemp = 25.3 # Water Temperature in fahrenheit anc.SystemTemp = 54.6 # System Temperature in fahrenheit anc.Salinity = 35.0 # Water Salinity set by the user in PPT anc.Pressure = 23.78 # Pressure from pressure sensor in Pascals anc.TransducerDepth = 45.69 # Transducer Depth, used by Pressure sensor in meters anc.SpeedOfSound = 1400.23 # Speed of Sound in m/s. anc.RawMagFieldStrength = 3.0 # Raw magnetic field strength anc.PitchGravityVector = 4.0 # Pitch Gravity Vector anc.RollGravityVector = 5.0 # Roll Gravity Vector anc.VerticalGravityVector = 6.0 # Vertical Gravity Vector amp = Amplitude(num_bins, num_beams) corr = Correlation(num_bins, num_beams) beam_vel = BeamVelocity(num_bins, num_beams) inst_vel = InstrumentVelocity(num_bins, num_beams) earth_vel = EarthVelocity(num_bins, num_beams) gb = GoodBeam(num_bins, num_beams) ge = GoodEarth(num_bins, num_beams) val = 1.0 for beam in range(amp.element_multiplier): for bin_num in range(amp.num_elements): amp.Amplitude[bin_num][beam] = val corr.Correlation[bin_num][beam] = val beam_vel.Velocities[bin_num][beam] = val inst_vel.Velocities[bin_num][beam] = val earth_vel.Velocities[bin_num][beam] = val gb.GoodBeam[bin_num][beam] = 1 * int(beam) ge.GoodEarth[bin_num][beam] = 1 * int(beam) val += 1.1 bt = BottomTrack() bt.FirstPingTime = 12.5 bt.LastPingTime = 12.8 bt.Heading = 152.36 bt.Pitch = 12.6 bt.Roll = 223.1 bt.WaterTemp = 15.23 bt.SystemTemp = 78.58 bt.Salinity = 35.0 bt.Pressure = 23.36 bt.TransducerDepth = 156.2 bt.SpeedOfSound = 1402.36 bt.Status = 9.0 bt.NumBeams = 4.0 bt.ActualPingCount = 23 bt.Range = [1.1, 2.2, 3.3, 4.4] bt.SNR = [1.1, 2.2, 3.3, 4.4] bt.Amplitude = [1.1, 2.2, 3.3, 4.4] bt.Correlation = [1.1, 2.2, 3.3, 4.4] bt.BeamVelocity = [1.1, 2.2, 3.3, 4.4] bt.BeamGood = [1, 2, 3, 4] bt.InstrumentVelocity = [1.1, 2.2, 3.3, 4.4] bt.InstrumentGood = [1, 2, 3, 4] bt.EarthVelocity = [1.1, 2.2, 3.3, 4.4] bt.EarthGood = [1, 2, 3, 4] bt.SNR_PulseCoherent = [1, 2, 3, 4] bt.Amp_PulseCoherent = [1, 2, 3, 4] bt.Vel_PulseCoherent = [1, 2, 3, 4] bt.Noise_PulseCoherent = [1, 2, 3, 4] bt.Corr_PulseCoherent = [1, 2, 3, 4] rt = RangeTracking() rt.NumBeams = 4.0 rt.Range = [1.1, 2.2, 3.3, 4.4] rt.Pings = [1, 2, 3, 4] rt.SNR = [1.1, 2.2, 3.3, 4.4] rt.Amplitude = [1.1, 2.2, 3.3, 4.4] rt.Correlation = [1.1, 2.2, 3.3, 4.4] rt.BeamVelocity = [1.1, 2.2, 3.3, 4.4] rt.InstrumentVelocity = [1.1, 2.2, 3.3, 4.4] rt.EarthVelocity = [1.1, 2.2, 3.3, 4.4] nmea = NmeaData() nmea.add_nmea("$HEHDT,244.39,T*17\n") nmea.add_nmea( "$GPGGA,195949.00,3254.8103248,N,11655.5779629,W,2,08,1.1,222.174,M,-32.602,M,6.0,0138*75\n" ) nmea.add_nmea("$GPVTG,306.20,T,294.73,M,0.13,N,0.24,K,D*2E\n") nmea.add_nmea("$HEHDT,244.36,T*18\n") ss = SystemSetup() ss.BtSamplesPerSecond = 1.0 ss.BtSystemFreqHz = 3.0 ss.BtCPCE = 1.2 ss.BtNCE = 2.3 ss.BtRepeatN = 23.5 ss.WpSamplesPerSecond = 13.6 ss.WpSystemFreqHz = 11.25 ss.WpCPCE = 25.3 ss.WpNCE = 54.6 ss.WpRepeatN = 35.0 ss.WpLagSamples = 23.78 ss.Voltage = 45.69 ss.XmtVoltage = 1400.23 ss.BtBroadband = 3.0 ss.BtLagLength = 4.0 ss.BtNarrowband = 5.0 ss.BtBeamMux = 6.0 ss.WpBroadband = 6.0 ss.WpLagLength = 6.0 ss.WpTransmitBandwidth = 6.0 ss.WpReceiveBandwidth = 6.0 ens.AddAmplitude(amp) ens.AddCorrelation(corr) ens.AddBeamVelocity(beam_vel) ens.AddInstrumentVelocity(inst_vel) ens.AddEarthVelocity(earth_vel) ens.AddGoodBeam(gb) ens.AddGoodEarth(ge) ens.AddAncillaryData(anc) ens.AddEnsembleData(ens_ds) ens.AddBottomTrack(bt) ens.AddRangeTracking(rt) ens.AddSystemSetup(ss) ens.AddNmeaData(nmea) rti_writer = RtiBinaryWriter("C:\RTI_capture") for ens_count in range(0, 100): bin_data = ens.encode() rti_writer.write(bin_data) ens.EnsembleData.EnsembleNumber += 1 rti_writer.close()
def set_ens(self, ens: Ensemble): """ Get the data out of the ensemble and populate the structure. Lock and unlock when getting the data to ensure when new data is received, it is not being used with old data. :param ens: Latest ensemble. :return: """ # Lock the object self.thread_lock.acquire() if ens.IsEnsembleData: self.x_dt.append(ens.EnsembleData.datetime().isoformat()) else: self.x_dt.append(None) if ens.IsAncillaryData: self.heading.append(ens.AncillaryData.Heading) self.pitch.append(ens.AncillaryData.Pitch) self.roll.append(ens.AncillaryData.Roll) self.temperature.append(ens.AncillaryData.WaterTemp) else: self.heading.append(None) self.pitch.append(None) self.roll.append(None) self.temperature.append(None) if ens.IsEarthVelocity: avg_mag, avg_dir = ens.EarthVelocity.average_mag_dir() self.water_speed.append(avg_mag) self.water_dir.append(avg_dir) else: self.water_speed.append(None) self.water_dir.append(None) if ens.IsNmeaData: self.num_sats.append(ens.NmeaData.GPGGA.num_sats) self.gnss_qual.append(ens.NmeaData.GPGGA.gps_qual) self.gnss_hdop.append(ens.NmeaData.GPGGA.horizontal_dil) self.vtg_speed.append(ens.NmeaData.speed_m_s) else: self.num_sats.append(None) self.gnss_qual.append(None) self.gnss_hdop.append(None) self.vtg_speed.append(None) if ens.IsBottomTrack: # Get the EarthVelocity data bt_e0 = ens.BottomTrack.EarthVelocity[0] bt_e1 = ens.BottomTrack.EarthVelocity[1] bt_e2 = ens.BottomTrack.EarthVelocity[2] # Calculate the Magnitude and direction for the bottom track data bt_mag = EarthVelocity.calculate_magnitude(bt_e0, bt_e1, bt_e2) bt_dir = EarthVelocity.calculate_direction(bt_e0, bt_e1) if not Ensemble.is_bad_velocity(bt_mag): self.boat_speed.append(bt_mag) self.boat_dir.append(bt_dir) else: # Bad Earth Velocity self.boat_speed.append(None) self.boat_dir.append(None) else: # No Bottom Track self.boat_speed.append(None) self.boat_dir.append(None) self.thread_lock.release()
def test_direction(): east = 1.33 north = 1.45 result = EarthVelocity.calculate_direction(east, north) assert 42.52 == pytest.approx(result, 0.01)
def test_magnitude(): east = 1.33 north = 1.45 vert = 0.3 result = EarthVelocity.calculate_magnitude(east, north, vert) assert 1.99 == pytest.approx(result, 0.01)