Alison Kohout Waves in Ice Project

Real-Time Spectral Analysis for Wave Motion Processing in Ice

As part of the Waves in Ice Observation System (WIIOS) project, I developed a C-based signal processing system to analyze wave motion data in sea ice environments. This project was a unique challenge, as my formal programming training was limited to Fortran basics during my mathematics degree. I independently learned C to build this system from the ground up. Due to the constrained memory on the sensors, only essential libraries were included, requiring me to write all algorithms from scratch. As a result, the code deviates from conventional formatting standards. Please note that this software was initially developed for personal use and not intended for public sharing. I am currently working on refining the code with AI assistance to make it accessible in a polished, shareable format. Below, I outline the core components of the system, accompanied by relevant code snippets.

Data Acquisition & Preprocessing

[GitHub Links: main.c, sc_misc.c, signal_conditioning.c]

  • Captured 640-second burst samples at 64 Hz using IMU and Kistler accelerometers.
  • Designed a digital filtering pipeline, including:
    • A low-pass 2nd-order Butterworth filter (0.5 Hz cutoff).
    • Downsampling to 2 Hz for efficient processing.
    • High-pass filtering to derive displacement data.

Code Snippet: Downsampling Implementation

                        
/******************************************************************************
 * Function: decimate
 * Purpose: Decimates (downsamples) a signal after applying an anti-aliasing
 *          Butterworth filter
 * 
 * Parameters:
 *   in[]  - Input signal array
 *   out[] - Output decimated signal array
 *   sr1   - Input sampling rate (Hz)
 *   sr2   - Output sampling rate (Hz)
 *   n1    - Length of input array
 *   n2    - Length of output array
 * 
 * Returns:
 *   void
 * 
 * Notes:
 *   - Implements 2nd order Butterworth filter
 *   - Supports two specific sampling rate combinations:
 *     1. 8 Hz input (sr1=0.125) with 0.5 Hz cutoff
 *     2. 64 Hz input (sr1=0.015625) with 2 Hz cutoff
 *   - Requires integer ratio between input and output sampling rates
 *   - Includes bounds checking and error logging
 * 
 * Filter Coefficients:
 *   8 Hz sampling:  a = [1.0, -1.4542, 0.5741]
 *                   b = [0.0300, 0.0599, 0.0300]
 *   64 Hz sampling: a = [1.0, -1.7238, 0.7575]
 *                   b = [0.0084, 0.0169, 0.0084]
 * 
 *****************************************************************************/

void decimate(long double *in, long double *out, float sr1, float sr2, int n1, int n2) {

       logger("Start decimate",0.0);

       int i, j, ii, n, jj;
       int step;
       long double out1[n1];
       long double a[3],b[3];

       logger("    n1",n1);
       // intialize out
       for (i=0;i<n2;i++) out[i] = 0.0;

       // butter worth filter with 8 Hz sample rate and 0.5 Hz cut off
       if (sr1==0.125) {
           logger("    Butter worth filter with 8 Hz sample rate, 0.5 Hz cut off",0.0);
           a[0] = 1.000000000000000;
           a[1] = -1.454243586251585;
           a[2] = 0.574061915083955;
           b[0] = 0.029954582208092;
           b[1] = 0.059909164416185;
           b[2] = 0.029954582208092;
       }
       // butter worth filter with 64 Hz sample rate and 2 Hz cut off
       if (sr1==0.015625) {
           logger("    Butter worth filter with 64 Hz sample rate, 2 Hz cut off",0.0);
           a[0] = 1.000000000000000;
           a[1] = -1.723776172762509;
           a[2] = 0.757546944478829;
           b[0] = 0.008442692929080;
           b[1] = 0.016885385858160;
           b[2] = 0.008442692929080;
       }
       if (!floorf(sr2/sr1==sr2/sr1)) {
              debug("Error: step a non integer",0.0);
              return;
       }  

       out1[0] = in[0];
       out1[1] = in[1];
       for (i=2; i<n1; i++){
            out1[i] = b[0]*in[i] +  b[1]*in[i-1] + b[2]*in[i-2] 
                                - a[1]*out1[i-1] - a[2]*out1[i-2];
       } 
       
       step = sr2/sr1;
       logger("    step",step);
       for (i=0, j=0; i<n1; i+=step,j++){
              if (j>=n2) {
                  fprintf(stderr,"ERROR: out of bounds in decimate. Exiting.\n");
                  exit(0);
              }
              out[j] = out1[i];
       } 

       logger("End decimate",0.0);
       return;
}


                        

Spectral Analysis

[GitHub Links: process.c, nr_four.c, direction.c]

  • Applied Welch’s method for power spectral density estimation using:
    • 256-second data segments with 50% overlap.
    • 10% cosine windowing to reduce spectral leakage.
    • Detrending algorithms for each segment to remove noise.
    • Calculation of spectral moments for wave characterization.

Automated Quality Control System

[GitHub Link: qc.c]

  • Developed validation mechanisms, including statistical tests.
  • Implemented spike detection to identify anomalies.
  • Monitored consecutive data changes to ensure consistency.

Real-Time Processing Constraints

  • Utilized a dual-core Edison processor for computations.
  • Managed operations within a 1 GB RAM limitation.
  • Optimized data storage on a 32 GB SD card.

Technical Skills Highlighted

  • Advanced digital signal processing techniques.
  • Real-time programming for embedded systems.
  • Statistical analysis and data validation methods.
  • Sensor integration and memory optimization.

This project demonstrates a blend of advanced programming proficiency and deep mathematical understanding of spectral analysis and signal processing, tailored to the unique challenges of studying wave dynamics in Antarctic sea ice.