The CsfCalc Tool

Chesapeake Times, Vol 14 | July 2023

For a couple years now, SonarWiz has been shipping with a little command-line utility called CsfCalc.exe. It hasn’t gotten a lot of attention, but it can be pretty handy for some purposes. We’ve mainly used it as a repair tool for files having some bad data in them; this allows for us to provide a script or instructions to repair files without a customer having to upload a large project. It can also be used to extract columns of computed (per-record) data from CSF files, for further inspection/manipulation within a spreadsheet, or perhaps as part of an automated ETL pipeline.

CsfCalc’s operation is fairly simple: for each CSF file specified by its command-line arguments, open the file and read each row; for each row, calculate a value, and then output that value to a specified location.

Invoking the CsfCalc utility with no arguments, as in the following example, shows a brief usage message listing the parameters:

CsfCalc takes two or three arguments:

The –files “<files>” argument is required, and tells CsfCalc which CSF files it’s meant to be operating on. Though I prefer to use full explicit paths here, the format will also accept paths specified relative to the current working directory. Note that the file names allow for wildcards, allowing you to operate on subsets of a project’s files.

The –source “<source>” argument is required, and controls what value CsfCalc will compute for each row. The source can be any of the CSF header or record fields described below, or calculations involving one or more of them. The fields described below are the variables available to operate on, and the operators/functions that are usable can be found in the online documentation of the muparserX library. There are also a handful of windowing and aggregating functions, but they’re fairly complex and won’t be further described here.

The –target “<target>” argument is optional, and controls where the calculated values are sent. If not specified, values computed per the –source argument above are written to the screen, one per line. When this is done, CsfCalc is operating in read-only mode, and no changes are made to the CSF. If specified, the argument
chooses a CSF field to write values to; allowable places to write are a subset of the record-level fields shown below. Several of the fields are intentionally immutable, often because they’re calculated values that SonarWiz will overwrite; ZEdit follows this same pattern in some places.

Note that in the usage screenshot above that I navigated the command prompt to the CSF folder within the project location and launched CsfCalc with that as the current working directory. This isn’t strictly necessary, but it’s useful to make quick spreadsheet-compatible data dumps sitting alongside a project’s CSFs, as in this example that produces a one-column CSV file showing the difference between calculated CMG and imported sensor heading:

The resultant file is easily opened with a spreadsheet program for further investigation and calculations.

Though it’s possible to do, we mostly suggest that CsfCalc not be used for CSF editing, except in a repair scenario as directed by support. It’s fairly easy to irreversibly damage files with this tool, necessitating re- import, and editing some fields can cause other, computed fields to become stale and require recomputation within SonarWiz. Making backups of files to be edited is also recommended, of course. That said, here’s an example of how I might repair some files where cable out values in feet were accidentally introduced, by converting them to meters:

Not all CSF fields are exposed through this tool, though many are. The full name of a field is specified as its source and its name separated by an underscore. The “OffsetX” field from in the CSF header, for example, is called “Header_OffsetX” while the record-level KP field is has “Record_PipeKilometers” as a name.

Header – there are only two fields presently available to read from the CSF header:
– OffsetX
– OffsetY

Record – many record-level fields are exposed, most having self-explanatory names with units included:
– Index – a generated integer in [0 .. RecordCount – 1]
– SystemTime
– SoundVelocityWaterTwoWayMetersPerSecond
– SoundVelocitySedimentTwoWayMetersPerSecond
– LengthSeconds
– AltitudeMeters
– AltitudePortMeters
– AltitudeStarboardMeters
– AntennaHeightMeters
– CableOutMeters
– SensorDepthMeters
– SwellMeters
– PitchDegrees
– RollDegrees
– MinSampleAmplitude
– MaxSampleAmplitude
– SamplesPerRecord
– TideHeightM
– DatumSeparationUnits
– HeaveMeters
– PipeKilometers
– OrigCoordY
– OrigCoordX
– FishX
– FishY
– PortX
– PortY
– StarboardX
– StarboardY
– SpeedKnots
– CourseMadeGood
– SensorHeading
– DepthMeters
– DistanceToPreviousMeters
– Event
– MagneticFieldnT
– MagneticStrength

Though handy for some purposes as-is, CsfCalc could be improved a bit in the future. Multiple output columns could quickly generate CSV reports similar to the ones SonarWiz creates, with the addition of some user-defined fields. Additional CSF fields could be added as well. Some upcoming changes to the CSF format would likely mesh well with these changes, and make CsfCalc much more powerful and usable within automated pipelines.