Andrew Que
Sites list
Photos
Computers
Projects
Contact
Main
Next week Previous week
 Aug 31 to Aug 25  -  Aug 24 to Aug 18  -  Aug 17 to Aug 11  -  Aug 10 to Aug 4 -  Aug 3 to Jul 28 
November - October - September - August - July - June - May
2013 - 2012 - 2011 - 2010 - 2009
Current week

+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-05
   Camp.
No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-02
   This is a shot from a few mornings ago.  While I was approaching State St. I saw this frame and I had to stop and capture it.  There is some interesting color contrast—blue sky, white building, yellow-orange tint from the street light.  There is also some texture contrast.  A solid blue sky, rough brick, shinny smooth tile, and the chain linked fence.  I found it interesting.
   At work I've been learning C Sharp.  Today I learned about how the language implements interfaces and abstract classes.  I also learned the type-checking is often done at run-time rather than compile time.  This I really don't like because I'd rather have type checking errors reported when I'm building rather than when I'm trying to run on the target system.  In addition, exceptions seem to lock our application and the entire system—and this makes for an irritating debug process.  But I am using a microsoft programming environment, and it's a long way from the stability I got use to working in aerospace.
No comments have been added
+ Add a comment
Cannon Fire
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-05
   Went with Amber to a Civil War reenactment in Boscobel, Wisconsin.  There was a fairly large group of precipitants which made for a good battle.  The cannon fire was really great—you could feel the concussion in your chest.  There was also a good demonstration of Civil War battlefield medical treatment.  While the presents of anesthetic was an improvement over Revolutionary War era medicine it still left a lot to be desired.  I also found it interesting that doctors treated wounded from both sides.
No comments have been added
- Average Class + Add a comment

I thought I'd share a simple moving average template class. I got this idea while at work yesterday when talking to an electrical engineer about making a writing efficient average function. Afterward I continued to think about ways to continue to improve upon the idea.

A mean average is simply the sum of all the data divided by the number of data points. A moving average assumes a fixed number of data points. When new data is added, the oldest sample is lost replaced with the new data added. So the mean average reflects the average over the most recent data only. This functions like a low-pass filter and is often used as an easy way to clean up analog signals.

What if the moving average was over a huge number of samples, and the type of samples was some kind of object with computationally difficult math operations? Perhaps the moving average is being preformed on a long list of arbitrary-precision data points. Adding up all the data points and dividing by the number of points could take too long.

We can speed the process of taking the average by keeping a sum. When a new point is added, the oldest data point is subtracted from the sum, and the new data added. In this way the only math operation needed to take the average at any time is dividing by the number of samples.

In making an average class I also considered how to resize the moving average. If the average becomes larger, empty data is simply placed at the end. If it becomes smaller, only the most recent samples need to be saved.

Here is a C++ implementation:

//==============================================================================
// Template class for keeping a moving average.
// Assumes math operations on 'TYPE' are computationally expensive, so used
// sparingly.
//==============================================================================
templateclass TYPE >
  class Average
  {
    protected:
      // Storage of all the data points that make the average.
      TYPE * array;

      // A representation of zero in the type of this template.
      TYPE zero;

      // Index into 'array' to save next data point.
      unsigned currentIndex;

      // How many data points are currently in array.
      unsigned top;

      // Length of 'array'.
      unsigned length;

      // Running sum used to compute average.
      TYPE sum;

    public:
      //------------------------------------------------------------------------
      // Create moving average with 'lengthParameter' number of samples to be
      // averaged together.
      //------------------------------------------------------------------------
      Average( unsigned lengthParameter )
      {
        length = lengthParameter;

        // Allocate storage for
        array = new TYPE[ length ];

        // We need a definition of zero, so make a cast to get this.
        // NOTE: This is important if TYPE is truly a class.
        zero = static_cast< TYPE >( 0 );

        reset();
      }

      //------------------------------------------------------------------------
      // Reset all data in average.
      // NOTE: Average result will be the equivalent of zero.
      //------------------------------------------------------------------------
      void reset()
      {
        // Empty array.
        for ( currentIndex = 0; currentIndex < length; ++currentIndex )
          array[ currentIndex ] = zero;

        currentIndex = 0;
        top = 0;
        sum = 0;
      }

      //------------------------------------------------------------------------
      // Resize the number of samples used in average.
      // If the size becomes larger, then the average will not change until
      // more data is added.
      // If the size becomes smaller, then the last 'newLength' samples will be
      // copied to new average.
      //------------------------------------------------------------------------
      void resize( unsigned newLength )
      {
        // Allocate memory for new array.
        TYPE * newArray = new TYPE[ newLength ];

        // Reset sum.
        sum = zero;
        for ( unsigned count = newLength; count > 0--count )
        {
          unsigned index = count - 1;

          // Do we have data to copy from the old array at this index?
          if ( index < top )
          {
            // Get previous data index.
            if ( currentIndex == 0 )
              currentIndex = length - 1;
            else
              currentIndex -= 1;

            // Save data in new array.
            newArray[ index ] = array[ currentIndex ];

            // Sum this data.
            sum += newArray[ index ];
          }
          else
            // Set this position to zero.
            newArray[ index ] = zero;
       }

        // Delete old array holder and switch to new array.
        delete array;
        array = newArray;

        // Move top if the new length is lower than previous top.
        if ( top > newLength )
          top = newLength;

        // New length.
        length = newLength;

        // Set new index location.
        currentIndex = top;
        if ( currentIndex >= length )
          currentIndex = 0;
      }

      //------------------------------------------------------------------------
      // Return the computed average.
      // NOTE: Uses the data in the average thus far.  If average isn't full,
      // then only those data points in the array are used.
      //------------------------------------------------------------------------
      TYPE get() const
      {
        TYPE result;

        if ( top > 0 )
          result = sum / static_cast< TYPE >( top );
        else
          result = zero;

        return result;
      }

      //------------------------------------------------------------------------
      // Return the number of data points in the moving average so far.
      //------------------------------------------------------------------------
      unsigned getNumberOfDataPoints() const
      {
        return top;
      }

      //------------------------------------------------------------------------
      // Add new data to average.
      //------------------------------------------------------------------------
      void push( TYPE newData )
      {
        // Remove old data from average sum.
        sum -= array[ currentIndex ];

        // Add new data to average sum.
        sum += newData;

        // Save new data.
        array[ currentIndex ] = newData;

        // Advance index.
        ++currentIndex;

        // If this marks the top...
        if ( currentIndex > top )
          // Update the top.
          top = currentIndex;

        // Wrap-around index.
        if ( currentIndex >= length )
          currentIndex = 0;
      }

  };

Download the code

Use it like this:

  Average< int > average( 5 );

  average.push( 1 );
  average.push( 2 );
  average.push( 3 );

  int meanAverage = average.get();

This code will create a rolling average of up to 5 elements.  It then adds the data [1, 2, 3] to the average.  'meanAverage' will be 2.

No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-03
   Started a short contract job today, and it has become customary for me to take a reflection shot on the first day.
No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-02
   Did a set along State Street in the early morning hours, hoping to test my twilight strategy.  Despite having a fairly dark sky I could have still begun eariler.  However, the things I wanted to have happen did happen.  I did not get the heavy lens flare like when I was shooting at night.
   This shot is one I liked quite a bit, but need to shoot again.  The HDR brings out the detail inside the store.  By this point in my ride the sun had just about risen, so I faked the sky by using the sky from the darkest of the images. 
No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-01
   Dawn over the city of Madison as seen from the edge of Lake Monona.  This is an other HDR shot consisting of 3 images: -3, -1, +1 f-stops.  There were two things I wanted to see.  First, if I could capture better clouds and stars at twilight.  Two, would the images wash out less in twilight.  By the time I took these shots it was past twilight.  However I did capture some stars and the clouds.  The wash out from street light is mitigated by the light from the sky.
No comments have been added


Designed and maintained by Andrew Que
(C) Copyright 2001-2012