Ejemplo n.º 1
0
            /// <summary>
            /// Convert the PD0 Bottom Track data type to the RTI Bottom Track data set.
            /// </summary>
            /// <param name="bt">PD0 Bottom Track.</param>
            /// <param name="xform">Coordinate Transform.</param>
            /// <param name="vl">Variable Leader.</param>
            public void DecodePd0Ensemble(Pd0BottomTrack bt, PD0.CoordinateTransforms xform, Pd0VariableLeader vl)
            {
                // Get the time to seconds
                TimeSpan ts = new TimeSpan((int)vl.RtcY2kDay, (int)vl.RtcY2kHour, (int)vl.RtcY2kMinute, (int)vl.RtcY2kSecond);

                FirstPingTime = (float)ts.TotalSeconds;
                LastPingTime = FirstPingTime;
                Heading = vl.Heading;
                Pitch = vl.Pitch;
                Roll = vl.Roll;
                WaterTemp = vl.Temperature;
                SystemTemp = 0.0f;
                Salinity = vl.Salinity;
                Pressure = vl.Pressure / 0.0001f;
                TransducerDepth = vl.DepthOfTransducer / 10.0f;
                SpeedOfSound = 0.0f;
                Status = new Status(0);
                NumBeams = DataSet.Ensemble.DEFAULT_NUM_BEAMS_BEAM;
                ActualPingCount = bt.BtPingsPerEnsemble;

                #region Range

                // Range
                Range[0] = bt.GetRangeBeam3() / 100.0f;
                Range[1] = bt.GetRangeBeam2() / 100.0f;
                Range[2] = bt.GetRangeBeam0() / 100.0f;
                Range[3] = bt.GetRangeBeam1() / 100.0f;

                #endregion

                #region SNR

                // SNR
                // PD0 Beam 2, RTI Beam 0
                if (bt.BtAmplitudeBeam2 < PD0.BAD_AMPLITUDE)
                {
                    SNR[0] = bt.BtAmplitudeBeam2 / 2.0f;
                }
                else
                {
                    SNR[0] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 3, RTI Beam 1
                if (bt.BtAmplitudeBeam3 < PD0.BAD_AMPLITUDE)
                {
                    SNR[1] = bt.BtAmplitudeBeam3 / 2.0f;
                }
                else
                {
                    SNR[1] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 1, RTI Beam 2
                if (bt.BtAmplitudeBeam1 < PD0.BAD_AMPLITUDE)
                {
                    SNR[2] = bt.BtAmplitudeBeam1 / 2.0f;
                }
                else
                {
                    SNR[2] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 0, RTI Beam 3
                if (bt.BtAmplitudeBeam0 < PD0.BAD_AMPLITUDE)
                {
                    SNR[3] = bt.BtAmplitudeBeam0 / 2.0f;
                }
                else
                {
                    SNR[3] = DataSet.Ensemble.BAD_VELOCITY;
                }

                #endregion

                #region Amplitude

                // Amplitude
                // PD0 Beam 2, RTI Beam 0
                if (bt.BtRssiBeam2 < PD0.BAD_AMPLITUDE)
                {
                    Amplitude[0] = bt.BtRssiBeam2 / 2.0f;
                }
                else
                {
                    Amplitude[0] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 3, RTI Beam 1
                if (bt.BtRssiBeam3 < PD0.BAD_AMPLITUDE)
                {
                    Amplitude[1] = bt.BtRssiBeam3 / 2.0f;
                }
                else
                {
                    Amplitude[1] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 1, RTI Beam 2
                if (bt.BtRssiBeam1 < PD0.BAD_AMPLITUDE)
                {
                    Amplitude[2] = bt.BtRssiBeam1 / 2.0f;
                }
                else
                {
                    Amplitude[2] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 0, RTI Beam 3
                if (bt.BtRssiBeam0 < PD0.BAD_AMPLITUDE)
                {
                    Amplitude[3] = bt.BtRssiBeam0 / 2.0f;
                }
                else
                {
                    Amplitude[3] = DataSet.Ensemble.BAD_VELOCITY;
                }

                #endregion

                #region Correlation

                // Correlation
                // PD0 Beam 2, RTI Beam 0
                if (bt.BtCorrelationMagnitudeBeam2 < PD0.BAD_CORRELATION)
                {
                    Correlation[0] = bt.BtCorrelationMagnitudeBeam2 / 255.0f;
                }
                else
                {
                    Correlation[0] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 3, RTI Beam 1
                if (bt.BtCorrelationMagnitudeBeam3 < PD0.BAD_CORRELATION)
                {
                    Correlation[1] = bt.BtCorrelationMagnitudeBeam3 / 255.0f;
                }
                else
                {
                    Correlation[1] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 1, RTI Beam 2
                if (bt.BtCorrelationMagnitudeBeam1 < PD0.BAD_CORRELATION)
                {
                    Correlation[2] = bt.BtCorrelationMagnitudeBeam1 / 255.0f;
                }
                else
                {
                    Correlation[2] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 0, RTI Beam 3
                if (bt.BtCorrelationMagnitudeBeam0 < PD0.BAD_CORRELATION)
                {
                    Correlation[3] = bt.BtCorrelationMagnitudeBeam0 / 255.0f;
                }
                else
                {
                    Correlation[3] = DataSet.Ensemble.BAD_VELOCITY;
                }

                #endregion

                #region Velocity

                // Velocity
                switch(xform)
                {
                    // Beam Coordinate Transform
                    case PD0.CoordinateTransforms.Coord_Beam:

                        // PD0 Beam 2, RTI Beam 0
                        if(bt.BtVelocityBeam2 != PD0.BAD_VELOCITY)
                        {
                            BeamVelocity[0] = bt.BtVelocityBeam2 / 1000.0f;
                        }
                        else
                        {
                            BeamVelocity[0] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // PD0 Beam 3, RTI Beam 1
                        if(bt.BtVelocityBeam3 != PD0.BAD_VELOCITY)
                        {
                            BeamVelocity[1] = bt.BtVelocityBeam3 / 1000.0f;
                        }
                        else
                        {
                            BeamVelocity[1] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // PD0 Beam 1, RTI Beam 2
                        if(bt.BtVelocityBeam1 != PD0.BAD_VELOCITY)
                        {
                            BeamVelocity[2] = bt.BtVelocityBeam1 / 1000.0f;
                        }
                        else
                        {
                            BeamVelocity[2] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // PD0 Beam 0, RTI Beam 3
                        if(bt.BtVelocityBeam0 != PD0.BAD_VELOCITY)
                        {
                            BeamVelocity[3] = bt.BtVelocityBeam0 / 1000.0f;
                        }
                        else
                        {
                            BeamVelocity[3] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        break;

                    // Instrument Coordinate Transform
                    case PD0.CoordinateTransforms.Coord_Instrument:

                        // PD0 Beam 1, RTI Beam 0
                        if(bt.BtVelocityBeam1 != PD0.BAD_VELOCITY)
                        {
                            InstrumentVelocity[0] = bt.BtVelocityBeam1 / 1000.0f;
                        }
                        else
                        {
                            InstrumentVelocity[0] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // PD0 Beam 0, RTI Beam 1
                        if(bt.BtVelocityBeam0 != PD0.BAD_VELOCITY)
                        {
                            InstrumentVelocity[1] = bt.BtVelocityBeam0 / 1000.0f;
                        }
                        else
                        {
                            InstrumentVelocity[1] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // PD0 Beam -2, RTI Beam 2
                        if(bt.BtVelocityBeam2 != PD0.BAD_VELOCITY)
                        {
                            InstrumentVelocity[2] = (bt.BtVelocityBeam2 * -1) / 1000.0f;
                        }
                        else
                        {
                            InstrumentVelocity[2] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // PD0 Beam 3, RTI Beam 3
                        if(bt.BtVelocityBeam3 != PD0.BAD_VELOCITY)
                        {
                            InstrumentVelocity[3] = bt.BtVelocityBeam3 / 1000.0f;
                        }
                        else
                        {
                            InstrumentVelocity[3] = DataSet.Ensemble.BAD_VELOCITY;
                        }
                        break;

                    // Earth Coordinate Transform
                    case PD0.CoordinateTransforms.Coord_Earth:

                        // Beam 0
                        if(bt.BtVelocityBeam0 != PD0.BAD_VELOCITY)
                        {
                            EarthVelocity[0] = bt.BtVelocityBeam0 / 1000.0f;
                        }
                        else
                        {
                            EarthVelocity[0] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // Beam 1
                        if(bt.BtVelocityBeam1 != PD0.BAD_VELOCITY)
                        {
                            EarthVelocity[1] = bt.BtVelocityBeam1 / 1000.0f;
                        }
                        else
                        {
                            EarthVelocity[1] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // Beam 2
                        if(bt.BtVelocityBeam2 != PD0.BAD_VELOCITY)
                        {
                            EarthVelocity[2] = bt.BtVelocityBeam2 / 1000.0f;
                        }
                        else
                        {
                            EarthVelocity[2] = DataSet.Ensemble.BAD_VELOCITY;
                        }

                        // Beam 3
                        if(bt.BtVelocityBeam3 != PD0.BAD_VELOCITY)
                        {
                            EarthVelocity[3] = bt.BtVelocityBeam3 / 1000.0f;
                        }
                        else
                        {
                            EarthVelocity[3] = DataSet.Ensemble.BAD_VELOCITY;
                        }
                        break;
                }

                #endregion

                #region Good Earth

                // PD0 Beam 2, RTI Beam 0
                if (bt.BtPercentGoodBeam2 != PD0.BAD_PERCENT_GOOD)
                {
                    EarthGood[0] = (bt.BtPercentGoodBeam2 / 100.0f) * bt.BtPingsPerEnsemble;
                }
                else
                {
                    EarthGood[0] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 3, RTI Beam 1
                if (bt.BtPercentGoodBeam3 != PD0.BAD_PERCENT_GOOD)
                {
                    EarthGood[1] = (bt.BtPercentGoodBeam3 / 100.0f) * bt.BtPingsPerEnsemble;
                }
                else
                {
                    EarthGood[1] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 1, RTI Beam 2
                if (bt.BtPercentGoodBeam1 != PD0.BAD_PERCENT_GOOD)
                {
                    EarthGood[2] = (bt.BtPercentGoodBeam1 / 100.0f) * bt.BtPingsPerEnsemble;
                }
                else
                {
                    EarthGood[2] = DataSet.Ensemble.BAD_VELOCITY;
                }

                // PD0 Beam 0, RTI Beam 3
                if (bt.BtPercentGoodBeam0 != PD0.BAD_PERCENT_GOOD)
                {
                    EarthGood[3] = (bt.BtPercentGoodBeam0 / 100.0f) * bt.BtPingsPerEnsemble;
                }
                else
                {
                    EarthGood[3] = DataSet.Ensemble.BAD_VELOCITY;
                }

                #endregion
            }
Ejemplo n.º 2
0
        public void TestEncodeVelCorrEchoPgBt()
        {
            PD0 pd0 = new PD0();

            pd0.FixedLeader.NumberOfCells = 5;

            Pd0Velocity vel = new Pd0Velocity(5);

            vel.Velocities[0, 0] = 32;
            vel.Velocities[0, 1] = -32;
            pd0.AddDataType(vel);

            Pd0Correlation corr = new Pd0Correlation(5);

            corr.Correlation[0, 0] = 32;
            corr.Correlation[0, 1] = 255;
            pd0.AddDataType(corr);

            Pd0EchoIntensity ei = new Pd0EchoIntensity(5);

            ei.EchoIntensity[0, 0] = 32;
            ei.EchoIntensity[0, 1] = 255;
            pd0.AddDataType(ei);

            Pd0PercentGood pg = new Pd0PercentGood(5);

            pg.PercentGood[0, 0] = 32;
            pg.PercentGood[0, 1] = 255;
            pd0.AddDataType(pg);

            Pd0BottomTrack bt = new Pd0BottomTrack();

            bt.BtPingsPerEnsemble     = 20;
            bt.BtDelayBeforeReacquire = 20;
            bt.BtAmplitudeBeam0       = 255;
            pd0.AddDataType(bt);

            byte[] encode = pd0.Encode();

            int flOffset   = pd0.Header.GetFixedLeader().Offset;
            int velOffset  = pd0.Header.GetVelocity().Offset;
            int corrOffset = pd0.Header.GetCorrelation().Offset;
            int eiOffset   = pd0.Header.GetEchoIntensity().Offset;
            int pgOffset   = pd0.Header.GetPercentGood().Offset;
            int btOffset   = pd0.Header.GetBottomTrack().Offset;

            Assert.AreEqual(0, encode[flOffset], "Fixed Leader ID LSB is incorrect");
            Assert.AreEqual(0, encode[flOffset + 1], "Fixed Leader ID MSB is incorrect");
            Assert.AreEqual(5, encode[flOffset + 9], "Number of depth cells is incorrect");

            Assert.AreEqual(32, MathHelper.LsbMsbShort(encode[velOffset + 2], encode[velOffset + 3]), "Velocity Bin 0, Beam 0 is incorrect.");
            Assert.AreEqual(-32, MathHelper.LsbMsbShort(encode[velOffset + 4], encode[velOffset + 5]), "Velocity Bin 0, Beam 1 is incorrect.");

            Assert.AreEqual(32, encode[corrOffset + 2], "Correlation Bin 0, Beam 0 is incorrect.");
            Assert.AreEqual(255, encode[corrOffset + 3], "Correlation Bin 0, Beam 1 is incorrect.");

            Assert.AreEqual(32, encode[eiOffset + 2], "Echo Intensity Bin 0, Beam 0 is incorrect.");
            Assert.AreEqual(255, encode[eiOffset + 3], "Echo Intensity Bin 0, Beam 1 is incorrect.");

            Assert.AreEqual(32, encode[pgOffset + 2], "Percent Good Bin 0, Beam 0 is incorrect.");
            Assert.AreEqual(255, encode[pgOffset + 3], "Percent Good Bin 0, Beam 1 is incorrect.");

            Assert.AreEqual(20, MathHelper.LsbMsbUShort(encode[btOffset + 2], encode[btOffset + 3]), "Bottom Track Pings per Ensemble is incorrect.");
            Assert.AreEqual(20, MathHelper.LsbMsbUShort(encode[btOffset + 4], encode[btOffset + 5]), "Bottom Track Delay Before Reacquire is incorrect.");
            Assert.AreEqual(255, encode[btOffset + 36], "Bottom Track Amplitude Beam 0 is incorrect.");

            Assert.IsTrue(pd0.IsBottomTrackExist, "IsBottomTrackExist is incorrect.");
            Assert.IsTrue(pd0.IsCorrelationExist, "IsCorrelationExist is incorrect.");
            Assert.IsTrue(pd0.IsEchoIntensityExist, "IsEchoIntensityExist is incorrect.");
            Assert.IsTrue(pd0.IsPercentGoodExist, "IsPercentGoodExist is incorrect.");
        }
Ejemplo n.º 3
0
            /// <summary>
            /// Convert the PD0 Bottom Track data type to the RTI Bottom Track data set.
            /// </summary>
            /// <param name="bt">PD0 Bottom Track.</param>
            /// <param name="xform">Coordinate Transform.</param>
            /// <param name="vl">Variable Leader.</param>
            public void DecodePd0Ensemble(Pd0BottomTrack bt, PD0.CoordinateTransforms xform, Pd0VariableLeader vl)
            {
                #region Velocity Data

                this.WaterMassDepthLayer = ((bt.BtRefLayerNear + bt.BtRefLayerFar) / 2.0f) / 10.0f;  // Divide by 10 to convert DM to M

                // Set velocities and check for bad velocities
                if (bt.BtRefLayerVelocityBeam0 == PD0.BAD_VELOCITY)
                {
                    this.VelocityX = Ensemble.EMPTY_VELOCITY;
                }
                else
                {
                    this.VelocityX = bt.BtRefLayerVelocityBeam0 / 1000.0f;
                }

                if (bt.BtRefLayerVelocityBeam1 == PD0.BAD_VELOCITY)
                {
                    this.VelocityY = Ensemble.EMPTY_VELOCITY;
                }
                else
                {
                    this.VelocityY = bt.BtRefLayerVelocityBeam1 / 1000.0f;
                }

                if (bt.BtRefLayerVelocityBeam2 == PD0.BAD_VELOCITY)
                {
                    this.VelocityZ = Ensemble.EMPTY_VELOCITY;
                }
                else
                {
                    this.VelocityZ = bt.BtRefLayerVelocityBeam2 / 1000.0f;
                }

                if (bt.BtRefLayerVelocityBeam3 == PD0.BAD_VELOCITY)
                {
                    this.VelocityQ = Ensemble.EMPTY_VELOCITY;
                }
                else
                {
                    this.VelocityQ = bt.BtRefLayerVelocityBeam3 / 1000.0f;
                }

                #endregion

                BtRefLayerFar                = bt.BtRefLayerFar;
                BtRefLayerMin                = bt.BtRefLayerMin;
                BtRefLayerNear               = bt.BtRefLayerNear;
                BtRefLayerCorrBeam0          = bt.BtRefLayerCorrBeam0;              // Should divide by 255 to match RTB correlation range
                BtRefLayerCorrBeam1          = bt.BtRefLayerCorrBeam1;
                BtRefLayerCorrBeam2          = bt.BtRefLayerCorrBeam2;
                BtRefLayerCorrBeam3          = bt.BtRefLayerCorrBeam3;
                BtRefLayerEchoIntensityBeam0 = bt.BtRefLayerEchoIntensityBeam0;     // Should divide by 2 to match RTB amplidtude dB range
                BtRefLayerEchoIntensityBeam1 = bt.BtRefLayerEchoIntensityBeam1;
                BtRefLayerEchoIntensityBeam2 = bt.BtRefLayerEchoIntensityBeam2;
                BtRefLayerEchoIntensityBeam3 = bt.BtRefLayerEchoIntensityBeam3;
                BtRefLayerPercentGoodBeam0   = bt.BtRefLayerPercentGoodBeam0;
                BtRefLayerPercentGoodBeam1   = bt.BtRefLayerPercentGoodBeam1;
                BtRefLayerPercentGoodBeam2   = bt.BtRefLayerPercentGoodBeam2;
                BtRefLayerPercentGoodBeam3   = bt.BtRefLayerPercentGoodBeam3;
            }
Ejemplo n.º 4
0
        public void TestDecodeVelocityPgCorrEiBt()
        {
            PD0 pd0 = new PD0();

            pd0.FixedLeader.NumberOfCells = 5;

            #region Velocity

            Pd0Velocity vel = new Pd0Velocity();
            // 2 Byte Header
            // 8 Bytes per depth cell
            // 4 Beams per depth cell
            // 2 Bytes per beam
            byte[] velData = new byte[42];

            velData[0] = Pd0Velocity.ID_LSB;
            velData[1] = Pd0Velocity.ID_MSB;
            velData[2] = 0xE8;                                   // DS0 Beam 0 LSB
            velData[3] = 0x00;                                   // DS0 Beam 0 MSB
            velData[4] = 0xBD;                                   // DS0 Beam 1 LSB
            velData[5] = 0xFE;                                   // DS0 Beam 1 MSB
            velData[6] = 0xC8;                                   // DS0 Beam 2 LSB
            velData[7] = 0x01;                                   // DS0 Beam 2 MSB
            velData[8] = 0x72;                                   // DS0 Beam 3 LSB
            velData[9] = 0xFD;                                   // DS0 Beam 3 MSB

            velData[(4 * 8) + 2 + 0] = 0xD0;                     // DS4 Beam 0 LSB
            velData[(4 * 8) + 2 + 1] = 0x04;                     // DS4 Beam 0 MSB
            velData[(4 * 8) + 2 + 2] = 0xD5;                     // DS4 Beam 1 LSB
            velData[(4 * 8) + 2 + 3] = 0xFA;                     // DS4 Beam 1 MSB
            velData[(4 * 8) + 2 + 4] = 0xB0;                     // DS4 Beam 2 LSB
            velData[(4 * 8) + 2 + 5] = 0x05;                     // DS4 Beam 2 MSB
            velData[(4 * 8) + 2 + 6] = 0x8A;                     // DS4 Beam 3 LSB
            velData[(4 * 8) + 2 + 7] = 0xF9;                     // DS4 Beam 3 MSB

            vel.Decode(velData);

            #endregion
            pd0.AddDataType(vel);                       // Add Velocity

            #region Percent Good

            Pd0PercentGood pg = new Pd0PercentGood();

            // 2 Byte Header
            // 4 Bytes per depth cell
            // 4 Beams per depth cell
            // 2 Bytes per beam
            byte[] pgData = new byte[22];

            pgData[0] = Pd0PercentGood.ID_LSB;
            pgData[1] = Pd0PercentGood.ID_MSB;
            pgData[2] = 0xE8;                                   // DS0 Beam 0
            pgData[3] = 0x7B;                                   // DS0 Beam 1
            pgData[4] = 0x7A;                                   // DS0 Beam 2
            pgData[5] = 0xDF;                                   // DS0 Beam 3

            pgData[(4 * 4) + 2 + 0] = 0x6F;                     // DS4 Beam 0
            pgData[(4 * 4) + 2 + 1] = 0xDE;                     // DS4 Beam 1
            pgData[(4 * 4) + 2 + 2] = 0x15;                     // DS4 Beam 2
            pgData[(4 * 4) + 2 + 3] = 0x22;                     // DS4 Beam 3


            pg.Decode(pgData);

            #endregion
            pd0.AddDataType(pg);                        // Add Percent Good

            #region Correlation

            Pd0Correlation corr = new Pd0Correlation();

            // 2 Byte Header
            // 4 Bytes per depth cell
            // 4 Beams per depth cell
            // 2 Bytes per beam
            byte[] corrData = new byte[22];

            corrData[0] = Pd0Velocity.ID_LSB;
            corrData[1] = Pd0Velocity.ID_MSB;
            corrData[2] = 0xE8;                                   // DS0 Beam 0
            corrData[3] = 0x7B;                                   // DS0 Beam 1
            corrData[4] = 0x7A;                                   // DS0 Beam 2
            corrData[5] = 0xDF;                                   // DS0 Beam 3

            corrData[(4 * 4) + 2 + 0] = 0x6F;                     // DS4 Beam 0
            corrData[(4 * 4) + 2 + 1] = 0xDE;                     // DS4 Beam 1
            corrData[(4 * 4) + 2 + 2] = 0x15;                     // DS4 Beam 2
            corrData[(4 * 4) + 2 + 3] = 0x22;                     // DS4 Beam 3


            corr.Decode(corrData);

            #endregion
            pd0.AddDataType(corr);                      // Add Correlation

            #region Echo Intensity

            Pd0EchoIntensity ei = new Pd0EchoIntensity();

            // 2 Byte Header
            // 4 Bytes per depth cell
            // 4 Beams per depth cell
            // 2 Bytes per beam
            byte[] eiData = new byte[22];

            eiData[0] = Pd0Velocity.ID_LSB;
            eiData[1] = Pd0Velocity.ID_MSB;
            eiData[2] = 0xE8;                                   // DS0 Beam 0
            eiData[3] = 0x7B;                                   // DS0 Beam 1
            eiData[4] = 0x7A;                                   // DS0 Beam 2
            eiData[5] = 0xDF;                                   // DS0 Beam 3

            eiData[(4 * 4) + 2 + 0] = 0x6F;                     // DS4 Beam 0
            eiData[(4 * 4) + 2 + 1] = 0xDE;                     // DS4 Beam 1
            eiData[(4 * 4) + 2 + 2] = 0x15;                     // DS4 Beam 2
            eiData[(4 * 4) + 2 + 3] = 0x22;                     // DS4 Beam 3


            ei.Decode(eiData);

            #endregion
            pd0.AddDataType(ei);                        // Add Echo Intensity

            #region Bottom Track

            Pd0BottomTrack bt = new Pd0BottomTrack();

            // 2 Byte Header
            // 4 Bytes per depth cell
            // 4 Beams per depth cell
            // 2 Bytes per beam
            byte[] btData = new byte[Pd0BottomTrack.DATATYPE_SIZE];

            bt.Decode(btData);

            #endregion
            pd0.AddDataType(bt);                        // Add Bottom Track

            byte[] data = pd0.Encode();

            // Size
            int size = pd0.FixedLeader.GetDataTypeSize();
            size += pd0.VariableLeader.GetDataTypeSize();
            size += 2;      // Spare
            size += pd0.Header.GetDataTypeSize();
            size += pd0.Velocity.GetDataTypeSize();
            size += pd0.PercentGood.GetDataTypeSize();
            size += pd0.Correlation.GetDataTypeSize();
            size += pd0.EchoIntensity.GetDataTypeSize();
            size += pd0.BottomTrack.GetDataTypeSize();


            Assert.AreEqual(7, pd0.Header.NumberOfDataTypes(), "Number of Data Types is incorrect.");
            Assert.AreEqual(5, pd0.Header.NumberOfDepthCells, "Number of depth cells is incorrect.");
            Assert.AreEqual(size, MathHelper.LsbMsbShort(data[2], data[3]), "Number of Bytes is incorrect.");
            Assert.AreEqual(7, data[5], "Number of Data Types is incorrect.");
            Assert.AreEqual(size + 2, data.Length, "Array Size is incorrect.");     // Add 2 for the checksum

            int flOffset = pd0.Header.GetDataTypeSize();
            Assert.AreEqual(flOffset, MathHelper.LsbMsbShort(data[6], data[7]), "Fixed Leader offset is incorrect.");

            int vlOffset = pd0.Header.GetDataTypeSize() + Pd0FixedLeader.DATATYPE_SIZE;
            Assert.AreEqual(vlOffset, MathHelper.LsbMsbShort(data[8], data[9]), "Variable Leader offset is incorrect.");

            int velOffset = pd0.Header.GetDataTypeSize() + Pd0FixedLeader.DATATYPE_SIZE + Pd0VariableLeader.DATATYPE_SIZE;
            Assert.AreEqual(velOffset, MathHelper.LsbMsbShort(data[10], data[11]), "Velocity offset is incorrect.");

            int pgOffset = pd0.Header.GetDataTypeSize() + Pd0FixedLeader.DATATYPE_SIZE + Pd0VariableLeader.DATATYPE_SIZE + pd0.Velocity.GetDataTypeSize();
            Assert.AreEqual(pgOffset, MathHelper.LsbMsbShort(data[12], data[13]), "Percent Good offset is incorrect.");

            int corrOffset = pd0.Header.GetDataTypeSize() + Pd0FixedLeader.DATATYPE_SIZE + Pd0VariableLeader.DATATYPE_SIZE + pd0.Velocity.GetDataTypeSize() + pd0.PercentGood.GetDataTypeSize();
            Assert.AreEqual(corrOffset, MathHelper.LsbMsbShort(data[14], data[15]), "Correlation offset is incorrect.");

            int eiOffset = pd0.Header.GetDataTypeSize() + Pd0FixedLeader.DATATYPE_SIZE + Pd0VariableLeader.DATATYPE_SIZE + pd0.Velocity.GetDataTypeSize() + pd0.PercentGood.GetDataTypeSize() + pd0.Correlation.GetDataTypeSize();
            Assert.AreEqual(eiOffset, MathHelper.LsbMsbShort(data[16], data[17]), "Echo Intensity offset is incorrect.");

            int btOffset = pd0.Header.GetDataTypeSize() + Pd0FixedLeader.DATATYPE_SIZE + Pd0VariableLeader.DATATYPE_SIZE + pd0.Velocity.GetDataTypeSize() + pd0.PercentGood.GetDataTypeSize() + pd0.Correlation.GetDataTypeSize() + pd0.EchoIntensity.GetDataTypeSize();
            Assert.AreEqual(btOffset, MathHelper.LsbMsbShort(data[18], data[19]), "Bottom Track offset is incorrect.");
        }