# Access Ping360 data for post processing, Python

Hey!
I have a bin file from a Ping360 sonar and i am trying to access the data in order to post process it using Python (3.9). I am looking into the decode_pingviewer_sensor_log_file.py script found here: Needs Python 3.7+ · GitHub, however I cant seem to figure out how to access the sonar data by itself or what format this is in. I am assuming the “data” that is printed from this script is the backscattering values in dB and that they are arranged by range from closest to the sonar to furthest.

Does anyone have any tips on how I might access the data directly?

Hi @Winter, welcome to the forum

I’d recommend you instead use/refer to the decode_sensor_binary_log.py file from our Ping Viewer repository, since it actually gets updated. I believe the one you linked to was originally a one-off example - not sure where you found that link, but if it’s on our forums or in our documentation then please let me know so I can update it

The .bin files produced by Ping Viewer are described in the Ping Viewer documentation, as:

The relevant data message specification for the ping360 is device_data, in the Ping Protocol docs.

The decode_sensor_binary_log.py script parses a binary log file into PingMessage instances (using/from the bluerobotics-ping library), and filters them into only the messages containing scan data. For the Ping360 that’s the device_data message, which has a data attribute that is a bytearray of the intensity values returned by the sonar. You can index into that directly if you want to (e.g. decoded_message.data[0] for the first intensity value), but for processing purposes I’d recommend converting the data to a numpy array instead (e.g. np.frombuffer(decoded_message.data, np.uint8)).

You can look at the message specification for the other available attributes, but of particular note are the angle (for direction) and sample_period (used to determine distance).

A few gotchas:

1. the ping angles are measured in gradians, so the angle attribute is a value from 0 to 399
2. the ping360 zero angle is at the back where the penetrator is, so ‘forwards’ (the direction of the arrow on the bottom of the Ping360) is at angle 200 gradians
3. Sonar (and all time of flight sensors) measure the time it takes for the pulse to return, so while d_{sound} = v_{sound} * t_{sample}, the target is half of that: d_{target} = \frac{d_{sound}}{2}

The following function can be used to determine the target distance per sample:

def meters_per_sample(ping_message, v_sound=1500):
""" Returns the target distance per sample, in meters.

'ping_message' is the message being analysed.
'v_sound' is the operating speed of sound [m/s]. Default 1500.

"""
# sample_period is in 25ns increments
# time of flight includes there and back, so divide by 2
return v_sound * ping_message.sample_period * 12.5e-9


If you have the sample index (from within the data array) the distance at the start of the sample time is just

sample_start_distance = sample_index * meters_per_sample(ping_message, v_sound)


(i.e. the first sample (index 0) has distance 0m).
Alternatively, you can get the distance to the middle of the sample time with

sample_average_distance = (sample_index + 0.5) * meters_per_sample(ping_message, v_sound)


We’re currently looking to add some more thorough examples of using our ping libraries - is there anything in particular you’d be interested in?

Thank you so much! this answered pretty much all of my questions brilliantly. Just one last thing, am a correct in assuming that the intensity signals are the volumetric backscattering strength in decibel? (usually referred to as “S_v” in fishery acoustics literature).

Thank you again so much for all your help! I cant think of anything particular at the moment, but I will let you know if i do