function [x, y, orientation] = FlyTracker(filename, FrameRange,...
                        NBackFrames, opt1, sqrsize,...
                        alpha, ellipse)

%FLYTRACKER
% Usage: 
%  [x, y, orientation] = FlyTracker(filename, FrameRange, ...
%                        NBackFrames, opt1, sqrsize,...
%                        alpha, ellipse)
%
% This function takes an input filename for a movie and tracks the position
% of a fly from StartFrame to EndFrame.  The movie can be in any format
% (.avi, .mpg, .mp2, etc.).  The following are a list of input parameters
% and output variables.
%
% Input:
%      filename:    must be the complete string of the movie filename
%      FrameRange:  range of frames to examine
%      NBackFrames: number of frames in static background, used only to
%                   find fly in first frame
%      opt1:        'neg' or 'pos'.  This multiplies the frame data by a
%                   negative sign ('neg') or not ('pos').  FindFly needs the 
%                   fly to be a bright spot, so the choice of this depends on
%                   the origional image.  If the original image is RGB, chances
%                   are that 'neg' needs to be selected.
%      sqrsize:     This is half the length of the sides of the square 
%                   around the brightest spot to be used in the CM calculation
%                   and the orientation  calculation.
%      alpha:       This is the weighting parameter for the running
%                   background.  It must be close to 1 for best results.
%                   0.9 seems like a good value for this, anything less
%                   seems to degrade SNR.  But for generalities sake, it
%                   is still a user input parameter.
%      ellipse:     parameters of the elliptical area that will be tracked
%
% Output:
%      x,y:         The x and y locations of the fly in each frame      
%      orientation: A matrix containing the UHP and LHP body axis orientation 
%                   angles for each frame.  UHP are in the first row, LHP are in
%                   the second row.  See FlyOrient and FindFly for more
%                   details.

% This function uses the videoReader function to input the video file into a Matlab object.
% Usage on videoReader and other functions in the videoIO toolbox can be
% found in the videoIO documentation.

%Written by Dan Valente 8/8/07

%Please note: Video indexes start at frame 0
StartFrame = FrameRange(1);
EndFrame = FrameRange(end);
NFrames = EndFrame-StartFrame+1;

%If NBackFrames is smaller than the number of frames we want to look at,
% we'll just take a smaller background average using all the frames of
% interest.
if (NBackFrames >= NFrames)
    NBackFrames = NFrames;
end

%initialize some variables
x = [];
y = [];
orientUHP=[];
orientLHP=[];

%load in video object using videoReader
video = videoReader(filename);
info = getinfo(video);
width = info.width;
height = info.height;

%just prevents error if user wants to track to end, but enters the
% incorrect EndFrame (recall frame index starts at 0).
if (info.numFrames == EndFrame)
    EndFrame = EndFrame-1;
elseif (info.numFrames < EndFrame)
    EndFrame = info.numFrames-1;
end

%seek to StartFrame for initial background calculation
seek(video, StartFrame);

mask = ellipse.mask;

disp('Calculating background...')
background = zeros(height, width);
for bframe = 1:NBackFrames; 
    img = getframe(video);
    current = mask.*double(img(:,:,1));  %just take first color matrix and mask out unwanted portions
    background = background + current/NBackFrames ;
    next(video);
end
flipper = 256*ones(height, width).*mask;
if (strcmp(opt1,'neg') == 1)        %make sure our fly will be a bright spot
    background = -background+flipper;
end


%seek to StartFrame for tracking
seek(video,StartFrame);
disp('Beginning tracking...')
tic

for frame = StartFrame:EndFrame
        disp(num2str(frame))
        img = getframe(video);
        img = mask.*double(img(:,:,1));   %just take first color matrix
        
        %make sure our fly will be a bright spot
        if (strcmp(opt1,'neg') == 1)   
            img = -img+flipper;
        elseif (strcmp(opt1,'pos') == 1)
            img = img;
        end
         
        % Calculate square of difference image (to reduce noise) and track
        temp = (img-background).^2;
              
        [x_raw y_raw bodyline sqr]=FindFly(temp,sqrsize); 
        
        
        %Just in case of a false track due to objects in the video that are
        %brighter than fly and vary over time.  We assume that these are
        %very far away from the fly.  One may want to change the threshold
        %from 100 pixels to something smaller, if need be.  Any reasonably
        %large number should do, and if you choose an incorrect threshold,
        %you can use the CleanData function to fix this.
        if (frame~=StartFrame)
            if (sqrt((x_raw-x(end))^2+(y_raw-y(end))^2) >= 100)
                x_raw = x(end);
                y_raw = y(end);
            end
        end
        
        x = [x x_raw];
        y = [y y_raw];
        orientUHP = [orientUHP bodyline(1)];
        orientLHP = [orientLHP bodyline(2)];
% %         
%         figure(2)
%         imagesc(img)
%         colormap gray
%         hold on
%         plot(x_raw,y_raw, '.r')
% %        
%         
        %grab whatever the background was before the fly got there.
        temp = background(sqr(1):sqr(2),sqr(3):sqr(4));
        %update
        background = alpha*background+(1-alpha)*img;
        %make sure we only update image outside of fly
        background(sqr(1):sqr(2),sqr(3):sqr(4)) = temp;
       
        worked = next(video);
        if (worked == 0)
            break
        end
end
disp('Finished tracking.')
disp('Have a lovely day.')
toc

%Now we have to make sure that the y vector is based on a coordinate
%system with the origin in the lower left hand corner of the square, 
%for plotting purposes.
y = height-y;

orientation = [orientUHP;orientLHP];

return; 
    