Announcement

Collapse
No announcement yet.

Lowrance MCC saved data structure.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Me too

    I'd love to get a copy of your work too, Robert. I am still using a Lowrance head unit to record my side scan data. I still want to get the data into a format I can mosaic.

    Please send to erik (at symbol) greendragon.org

    Thanks,

    Erik

    Comment


    • #17
      Lowrance Data Files

      Hi There,

      I work with some programmers and I have been struggling with this for a long time. I have uploaded the CSV files to an SQL Database, and then used Reporting services to bring out just the data I needed for Surfer. I would be really interested if you can send me the files that you have created and I will have my team look at them.

      My email is cplahn golder com. Insert punctuation!!!

      Comment


      • #18
        Saved data

        Hey there -

        I did email Robert a while back and didn't get much response from him, but he's a busy guy.

        I've collected the info I have on decoding these files(with the exception of some source code that's too big to upload right now, I'm trying to pull out the relevant pieces) and uploaded it to a yahoo group I created to work with the M1 sonar from Burton electronics that I own. You can read what I have there:

        groups.yahoo.com/group/burtonsidescan

        and if you manage to get a copy of Robert's code, I'd appreciate you letting me know there or in email, so I can put that there too. Seems like enough people are interested in this that we might be able to get a group of programmers together for an open source project.

        Erik

        Comment


        • #19
          Hello from snowy Russia) I've recently bought lowrance elite-5 chartplotter. Seller ensured me it could provide me with 'time', 'x', 'y', 'depth' data. And I was very disappointed (to sending it back to the store) with its inabilty to write depth values directly to microSD card. then looking for a new one I've pointed out that HDS-5 enables to save data in *.slg format. and when I first opened the sample file (downloaded with hds3.5 firmware update) in Sonar Log Viewer app I was really happy to see real 'time' values (eg. 10/25/2008 10:13:45) on a tooltip (it appears when you move mouse pointer across the echogram). but exporting data to *.csv file didn't make sense - 'time' values transformed into 'time offset' values;( then i've spent 4 long hours disassembling this ... *.slg file format to find 'start time' mark... that was a bad idea... only written 90% of code I realized that 'time' value I've seen was only *.slg file 'last write time' + 'time offset' of the currnt record. nevertheless I'm still looking for a device (maybe you could suggest me one) but my C# code may come in handy to someone. Happy usage:

          Code:
          /*
           * Copyright (c) 2011 Mikant
           * 
           * Permission is hereby granted, free of charge, to any person
           * obtaining a copy of this software and associated documentation
           * files (the "Software"), to deal in the Software without
           * restriction, including without limitation the rights to use,
           * copy, modify, merge, publish, distribute, sublicense, and/or sell
           * copies of the Software, and to permit persons to whom the
           * Software is furnished to do so, subject to the following
           * conditions:
           * 
           * The above copyright notice and this permission notice shall be
           * included in all copies or substantial portions of the Software.
           * 
           * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
           * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
           * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
           * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
           * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
           * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
           * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
           * OTHER DEALINGS IN THE SOFTWARE.
           */
          
          using System.IO;
          using GS.Geometry.Files;
          
          namespace GS.Geometry.Files.Tests {
              internal class Program {
                  static void Main(string[] args) {
                      
                      // open *.slg file
                      SLG slg = new SLG(@"C:\Users\Mikant\Desktop\LSUD\Sims\Logs\Sonar\sonar.slg");
          
                      // get first data record
                      SLG.Chunk chunk = slg[0];
          
                      // define if Depth data exists in the first data record
                      // (unnecessary: if data doesn't exist depth would be returned as zero)
                      bool depthExists = chunk.DataExists(SLG.DataField.Depth);
          
                      // get the depth
                      float depth = chunk.Depth;
                  }
              }
          }
          
          namespace GS.Geometry.Files {
          
              public class SLG {
                  private readonly int _format;
                  private readonly int _bytesPerChunk;
                  private readonly Chunk[] _chunks;
          
                  public SLG(string fileName) {
                      // note: this wouldn't work for a corruped file
                      // no exception handling or data validation mechanisms used
                      using (BinaryReader reader = new BinaryReader(File.OpenRead(fileName))) {
                          _format = reader.ReadInt32();
                          _bytesPerChunk = reader.ReadInt32();
          
                          var terminal = reader.ReadInt16();
                          int headerLength = (int)(reader.BaseStream.Position);
          
                          _chunks = new Chunk[(int)((reader.BaseStream.Length - headerLength) / _bytesPerChunk)];
          
                          for (int i = 0; i < _chunks.Length; i++)
                              _chunks[i] = new Chunk(reader, _bytesPerChunk);
                      }
                  }
          
                  public Chunk this[int index] {
                      get { return _chunks[index]; }
                  }
          
                  public class Chunk {
          
                      private readonly DataField _mask;
          
                      private readonly float _waterTemp;
                      private readonly float _waterSpeed;
                      private readonly float _lowerLimit;
                      private readonly float _depth;
                      private readonly float _surfaceDepth;
                      private readonly float _topOfBottomDepth;
                      private readonly int _timeOffset;
                      private readonly int _positionX;
                      private readonly int _positionY;
                      private readonly float _speed;
                      private readonly float _track;
                      private readonly float _altitude;
                      private readonly byte[] _data;
          
                      private readonly short _sampleRate;
          
                      public bool DataExists(DataField field) {
                          return (_mask & field) != 0;
                      }
          
                      public Chunk(BinaryReader reader, int length) {
          
                          long start = reader.BaseStream.Position;
          
                          // this mask defines available fields in the chunk
                          _mask = (DataField)reader.ReadInt16();
          
                          _lowerLimit = DataExists(DataField.LowerLimit) ? reader.ReadSingle() : 0;
                          _depth = DataExists(DataField.Depth) ? reader.ReadSingle() : 0;
          
                          _waterTemp = DataExists(DataField.WaterTemp) ? reader.ReadSingle() : 0;
                          _waterSpeed = DataExists(DataField.WaterSpeed) ? reader.ReadSingle() : 0;
          
                          // this data is stored in Mercator Meter format
                          // see http://www.colby.edu/chemistry/Colby%20Compass/AcqBathometricData.pdf
                          // for disambiguation. there is a convertion algorithm =)
                          _positionX = DataExists(DataField.Position) ? reader.ReadInt32() : 0;
                          _positionY = DataExists(DataField.Position) ? reader.ReadInt32() : 0;
          
                          _surfaceDepth = DataExists(DataField.SurfaceDepth) ? reader.ReadSingle() : 0;
                          _topOfBottomDepth = DataExists(DataField.TopOfBottomDepth) ? reader.ReadSingle() : 0;
                          _timeOffset = DataExists(DataField.TimeOffset) ? reader.ReadInt32() : 0;
          
                          _speed = DataExists(DataField.Speed) ? reader.ReadSingle() : 0;
                          _track = DataExists(DataField.Track) ? reader.ReadSingle() : 0;
                          _altitude = DataExists(DataField.Altitude) ? reader.ReadSingle() : 0;
          
                          // magic number: its name's a presumption
                          _sampleRate = reader.ReadInt16();
          
                          // in my case _sampleRate was always set to 2400
                          // at first I thought it is '_data.Length', but it's not:
                          // in some cases _data.Length was < 2400
                          //if (_sampleRate != 2400)
                          //    throw new Exception();
          
                          int headerLength = (int)(reader.BaseStream.Position - start);
          
                          _data = reader.ReadBytes(length - headerLength);
          
                      }
          
                      #region Properties
                      public float WaterTemp {
                          get { return _waterTemp; }
                      }
                      public float WaterSpeed {
                          get { return _waterSpeed; }
                      }
                      public float LowerLimit {
                          get { return _lowerLimit; }
                      }
                      public float Depth {
                          get { return _depth; }
                      }
                      public float SurfaceDepth {
                          get { return _surfaceDepth; }
                      }
                      public float TopOfBottomDepth {
                          get { return _topOfBottomDepth; }
                      }
                      public int TimeOffset {
                          get { return _timeOffset; }
                      }
                      public int PositionX {
                          get { return _positionX; }
                      }
                      public int PositionY {
                          get { return _positionY; }
                      }
                      public float Speed {
                          get { return _speed; }
                      }
                      public float Track {
                          get { return _track; }
                      }
                      public float Altitude {
                          get { return _altitude; }
                      }
                      public byte[] Data {
                          get { return _data; }
                      }
                      #endregion
          
                  }
          
                  // not sure about exact flags,
                  // because I had only one *.slg file with
                  // 3 different flag groups
                  public enum DataField : short {
                      // it is meant that WaterTemp flag is one of
                      // 16 or 128, and WaterSpeed flag is another
                      WaterTemp = 16 | 128,
                      WaterSpeed = 16 | 128,
          
                      // 3 flags and 5 fields (2 groups needed)
                      LowerLimit = 1024 | 2048 | 8192,
                      Depth = 1024 | 2048 | 8192,
                      SurfaceDepth = 1024 | 2048 | 8192,
                      TopOfBottomDepth = 1024 | 2048 | 8192,
                      TimeOffset = 1024 | 2048 | 8192,
          
                      // 3 flags and 4 fields (1 group more needed)
                      Position = 4 | 256 | 16384, // grouped: PositionX & PositionY
                      Speed = 4 | 256 | 16384,
                      Track = 4 | 256 | 16384,
                      Altitude = 4 | 256 | 16384,
          
                      Unused = 1 | 2 | 8 | 32 | 64 | 512 | 4096 | 16384
                  }
          
              }
          }
          note that I have not seen (unfortunately for me, fortunately for you) this topic while writing the code, so it is free of some incorrectnesses in the previous posts

          Comment


          • #20
            problem with sonar viewer output chart

            i have big problem with the sonar viewr ouput chart.. it doesnt display the real time.. what should i do.. i need to do tidal correction

            Comment


            • #21
              Originally posted by raymond View Post
              i have big problem with the sonar viewr ouput chart.. it doesnt display the real time.. what should i do.. i need to do tidal correction
              Is the time incorrect, or is the time stamp missing?
              If ord incorrect maybe you should set the correct time on the recording unit.

              Comment


              • #22
                theres no time stamp only time offset

                Comment


                • #23
                  Hi Robert,
                  I hope you are still there.
                  We are using Eagle Fish Elite500C in Bhutan Himalayas to measure depth of glacial lakes (http://www.jst.go.jp/global/english/...08_bhutan.html), 3 years now. For the trip to the nearest lake requires 7 to 10 days of high-elevation walk one way, we want to get 100% out from our slg format data files. For this reason, we want to know the file format (structure, layout) of the slg files. Please let me know the information you have about the slg file format.
                  My e-mail address is "fd5c-tknk AT MARK asahi-net or jp (please punctuate)".
                  Thanks.
                  Last edited by stakenaka; 11-04-2011, 08:44 AM. Reason: Add e-mail address for reply

                  Comment


                  • #24
                    Originally posted by raymond View Post
                    theres no time stamp only time offset
                    If so, I think that you must calculate the actual time using the time offset.
                    I'm not a programmer, so I'm sorry I can't help you on that. I only know the theory regarding this.

                    If I understand you correctly, you have a file with no time-stamp on the pings, only a time offset. The time is probably recorded in the header of the file, and stamped as the recording "start time". Then you need to calculate the actual time for the actual ping (I recon that every ping is stamped with a time offset?).
                    This could probably be solved by a converting filter, but again, I'm not a programmer....

                    Comment


                    • #25
                      automated processing of log files

                      Have you seen this website that does automated processing of Lowrance log files to create contour maps? www.ciAngler.com

                      Comment


                      • #26
                        Originally posted by johnsomb View Post
                        Have you seen this website that does automated processing of Lowrance log files to create contour maps? www.ciAngler.com
                        No, but we are using "Dr. Depth" that makes same kind of contour maps from Lowrance data.
                        What we want to do with our data is, if possible, finding out the two layer structure - water and ice that are supposed to exist at the bottom of the glacial lakes.

                        Anyway, thanks for your suggestion.

                        Comment


                        • #27
                          I have written a java based Vaadin widget for displaying SLG sonar logs in a web site. It's not a standalone application but only a building block that web application developer can use. While doing research I stumbled across this thread and previous posts about the file format were very helpful deciphering the log file format. So therefore I think that contributing back this to this thread is in order. Code that was created is released under open source license (Apache 2.0). Enjoy.

                          Source code and binaries
                          https://github.com/capeisti/SonarWidget
                          http://vaadin.com/addon/sonarwidget

                          Really simple demo using the widget. In the demo there is only one SLG file stored in the server and the data is from one of my adventures.
                          http://samuli.virtuallypreinstalled.com/SonarWidget/

                          Obviously this is not useful for everyone but if there is someone who plans to create a web service for sharing sonar logs this could be useful. Or take and use only parts of it whatever fits your needs. LowranceSonar.java would be the most interesting part.

                          What I plan to do next is to implement a support for structure scan SL2 files. Like with SLG no official specification can be found about the format and so far I haven't found any good reverse engineered descriptions either. File format resembles in some extent SLG but on my own I haven't been able to get meaningful data out yet. Pointers would be appreciated.

                          Comment

                          Working...
                          X