function h = timeseries_image(op, bg_img)

% image window setup

global st;
colors = [1 0 0;1 1 0;0 1 0;0 1 1;0 0 1;1 0 1];


if nargin==0,
	% get the image's filename {P}
	%-----------------------------------------------------------------------
	bg_img      = spm_get(1,'.img','Please select background image',[],0);
	timeseries_image('init',bg_img);
	return;
end;


if strcmp(op,'init')
    % Create figure, set up all callbacks and user interface.
    % ----------------------------------------------------------------------
    spm_defaults;
    h = spm_figure('Create','Image Window', 'Timeseries Analysis', 'on');
    if isempty(h)
        error('Can''t create graphics window');
    end
    spm_figure('Clear','Image Window');
    st.fig = h;
    st.n = 0;
    st.Space = eye(4);
    st.centre = [0 0 0];
    st.callback = ';';
    st.xhairs = 1;
    st.hld = 1;
    st.mode = 1;
    st.vols = cell(24,1);
    st.bb = [ [-78 78]' [-112 76]' [-50 85]' ];
    st.plugins = [];

    %spm_orthviews('Reset');
    spm_orthviews('Image', bg_img, [0.0 0.45 1 0.55]);
    if isempty(st.vols{1}), return; end;

    spm_orthviews('MaxBB');
    st.callback = 'timeseries_image(''shopos'');';
    st.B = [0 0 0  0 0 0  1 1 1  0 0 0];

    WS = spm('WinScale');

    % Crosshair position
    %-----------------------------------------------------------------------
    uicontrol(h,'Style','Frame','Position',[60 25 210 325].*WS, 'Tag', 'LeftImageControlFrame');
    uicontrol(h,'Style','Frame','Position',[70 235 190 110].*WS, 'Tag', 'PositionImageControlFrame');
    uicontrol(h,'Style','Text', 'Position',[75 320 170 016].*WS,'String','Crosshair Position');
    uicontrol(h,'Style','Text', 'Position',[75 295 25 020].*WS,'String','mm:');
    uicontrol(h,'Style','Text', 'Position',[165 295 25 020].*WS,'String','vx:');
    %uicontrol(h,'Style','Text', 'Position',[75 220 65 020].*WS,'String','Intensity:');
    %uicontrol(h,'Style','Text', 'Position',[140 220  85 020].*WS,'String','', 'Tag', 'intensity_text');

    defxyz_mm = spm_orthviews('pos');
    defxyz_vox = spm_orthviews('pos', 1);

    %mm controls
    uicontrol(h,'Style', 'edit', 'Position', [100 295 40 020].*WS, 'String', sprintf('%.1f',defxyz_mm(1)), ...
        'Tag', 'postext_x_mm', 'Callback','timeseries_image(''setposmm'')');
    uicontrol(h,'Style', 'edit', 'Position', [100 275 40 020].*WS, 'String', sprintf('%.1f',defxyz_mm(2)), ...
        'Tag', 'postext_y_mm', 'Callback','timeseries_image(''setposmm'')');
    uicontrol(h,'Style', 'edit', 'Position', [100 255 40 020].*WS, 'String', sprintf('%.1f',defxyz_mm(3)), ...
        'Tag', 'postext_z_mm', 'Callback','timeseries_image(''setposmm'')');
    uicontrol(h,'Style', 'text', 'Position', [140 295 15 020].*WS, 'String', 'x');
    uicontrol(h,'Style', 'text', 'Position', [140 275 15 020].*WS, 'String', 'y');
    uicontrol(h,'Style', 'text', 'Position', [140 255 15 020].*WS, 'String', 'z');

    %vox controls
    uicontrol(h,'Style', 'edit', 'Position', [190 295 40 020].*WS, 'String', sprintf('%.1f',defxyz_vox(1)), ...
        'Tag', 'postext_x_vox', 'Callback','timeseries_image(''setposvx'')');
    uicontrol(h,'Style', 'edit', 'Position', [190 275 40 020].*WS, 'String', sprintf('%.1f',defxyz_vox(2)), ...
        'Tag', 'postext_y_vox', 'Callback','timeseries_image(''setposvx'')');
    uicontrol(h,'Style', 'edit', 'Position', [190 255 40 020].*WS, 'String', sprintf('%.1f',defxyz_vox(3)), ...
        'Tag', 'postext_z_vox', 'Callback','timeseries_image(''setposvx'')');
    uicontrol(h,'Style', 'text', 'Position', [230 295 15 020].*WS, 'String', 'x');
    uicontrol(h,'Style', 'text', 'Position', [230 275 15 020].*WS, 'String', 'y');
    uicontrol(h,'Style', 'text', 'Position', [230 255 15 020].*WS, 'String', 'z');


    % ROI controls
    % ----------------------------------------------------------------------
    uicontrol(h, 'Style', 'Frame', 'Position', [70 35 190 190].*WS, 'Tag', 'ROIImageControlFrame');
    uicontrol(h, 'Style', 'text', 'Position', [75 195 30 020].*WS, 'String', 'Add:');
    % The UserData for this button is used to index the current color - that is, which
    % color the next ROI added will be.
    uicontrol(h, 'Style', 'pushbutton', 'Position', [105 195 70 020].*WS, 'String', 'ROI .img',...
        'Callback', 'timeseries_image(''addimg'')', 'UserData', 1, 'Tag', 'AddROIImgButton',...
        'ToolTipString', 'Add ROI .img file to ROIs menu and display');
    uicontrol(h, 'Style', 'pushbutton', 'Position', [195 195 60 020].*WS, 'String', 'Clear All', ...
        'Callback', 'timeseries_image(''clearrois'')', 'Enable', 'off',...
        'ToolTipString', 'Clear all ROIs from current menu and display', ...
        'Tag', 'ClearROIButton');
    uicontrol(h, 'Style', 'text', 'Position', [75 145 30 020].*WS, 'String', 'ROIs:');
    uicontrol(h, 'Style', 'listbox', 'Position', [105 65 150 100].*WS, 'Enable', 'on', 'String', [],...
        'Tag', 'ROIListBox', 'Max', 1, 'Min', 1);
    %uicontrol(h, 'Style', 'listbox', 'Position', [105 65 150 100].*WS, 'Enable', 'on',...
    %    'Tag', 'ROIListBox', 'String', {'boss'; 'man'; 'muddy'; 'waters'});
    uicontrol(h, 'Style', 'pushbutton', 'Position', [150 40 60 020].*WS, 'String', 'Jump', ...
        'Callback', 'timeseries_image(''listjump'')', 'Enable', 'off', ...
        'ToolTipString', 'Jump to center of highlighted ROI',...
        'Tag', 'JumpROIButton');


    % General information
    %-----------------------------------------------------------------------
    uicontrol(h,'Style','Frame','Position',[305  25 280 325].*WS, 'Tag', 'RightImageControlFrame',...
        'UserData', spm_vol(bg_img));
    uicontrol(h,'Style','Text','Position' ,[310 325 50 020].*WS,...
    	'HorizontalAlignment','right', 'String', 'File:');
    uicontrol(h,'Style','Text','Position' ,[360 325 210 020].*WS,...
    	'HorizontalAlignment','left', 'String', spm_str_manip(st.vols{1}.fname,'k25'),'FontWeight','bold');
    uicontrol(h,'Style','Text','Position' ,[310 305 100 020].*WS,...
    	'HorizontalAlignment','right', 'String', 'Dimensions:');
    uicontrol(h,'Style','Text','Position' ,[410 305 160 020].*WS,...
    	'HorizontalAlignment','left', 'String', sprintf('%d x %d x %d', st.vols{1}.dim(1:3)),'FontWeight','bold');


    % Mode controls and reporting
    % ----------------------------------------------------------------------
    uicontrol(h, 'Style', 'Frame', 'Position', [315 35 260 265].*WS, 'Tag', 'ModeImageControlFrame');
    uicontrol(h, 'Style', 'text', 'Position', [395 265 100 020].*WS, 'String', 'Analysis Mode:');
    uicontrol(h, 'Style', 'radiobutton', 'Position', [320 245 125 020].*WS, 'String', 'Single-voxel',...
        'Max', 1, 'Min', 0, 'Value', 1, 'Tag', 'SingleVoxModeButton', ...
        'Callback', 'timeseries_image(''singlevoxpush'')');
    uicontrol(h, 'Style', 'radiobutton', 'Position', [445 245 125 020].*WS, 'String', 'ROI mean',...
        'Max', 1, 'Min', 0, 'Value', 0, 'Tag', 'ROIMeanModeButton', ...
        'Callback', 'timeseries_image(''roimeanpush'')', 'Enable', 'off');
    uicontrol(h, 'Style', 'text', 'Position', [325 185 240 020].*WS,...
        'String', 'Currently displaying timeseries for:');
    uicontrol(h, 'Style', 'text', 'Position', [325 165 240 020].*WS, 'Tag', 'DisplayingText',...
        'String', sprintf('Single voxel at  %.1f  %.1f  %.1f  mm', defxyz_mm));

    
end



if strcmp(op,'shopos'),
	% The position of the crosshairs has been moved.
	%-----------------------------------------------------------------------
    mmpos = spm_orthviews('pos');
    set(findobj('Tag', 'postext_x_mm'),'String',sprintf('%.1f',mmpos(1)));
    set(findobj('Tag', 'postext_y_mm'),'String',sprintf('%.1f',mmpos(2)));
    set(findobj('Tag', 'postext_z_mm'),'String',sprintf('%.1f',mmpos(3)));

    voxpos = spm_orthviews('pos',1);
    set(findobj('Tag', 'postext_x_vox'),'String',sprintf('%.1f',voxpos(1)));
    set(findobj('Tag', 'postext_y_vox'),'String',sprintf('%.1f',voxpos(2)));
    set(findobj('Tag', 'postext_z_vox'),'String',sprintf('%.1f',voxpos(3)));

    currx = str2num(get(findobj('Tag', 'postext_x_mm'), 'String'));
    curry = str2num(get(findobj('Tag', 'postext_y_mm'), 'String'));
    currz = str2num(get(findobj('Tag', 'postext_z_mm'), 'String'));


    set_flag = 0;
    if get(findobj('Tag', 'SingleVoxModeButton'), 'Value')==1
        %i.e., we are in single-voxel mode
        set(findobj('Tag', 'DisplayingText'), 'String', ...
            sprintf('Single voxel at  %.1f  %.1f  %.1f  mm', currx, curry, currz));
    else
        rois = get(findobj('Tag', 'ROIListBox'), 'UserData');
        list = get(findobj('Tag', 'ROIListBox'), 'String');
        for i = size(rois,1):-1:1
            curr = rois{i};
            curr_roiname = list{i};
            vinv = inv(curr.mat);
            currpos = [currx; curry; currz];
            currpos_vox = vinv(1:3,:)*[currpos; 1]; 
            if spm_sample_vol(curr, currpos_vox(1), currpos_vox(2), currpos_vox(3), 1) > 0
                % i.e., we've found our location in the current ROI
                set(findobj('Tag', 'DisplayingText'), ...
                'String', sprintf('Mean values across ROI %s', curr_roiname));
                set_flag = 1;
            end
        end
        if set_flag==0
            %i.e., we never found our location in listed ROI
            %keyboard;
            set(findobj('Tag', 'DisplayingText'), ...
                'String', sprintf('Nothing'));
        end
    end
                
    timeseries_plotcontrol('newpos');

	return;
end;

if strcmp(op,'setposmm'),
	% Move the crosshairs to the specified position
	%-----------------------------------------------------------------------
    pos_x = str2num(get(findobj('Tag', 'postext_x_mm'),'String'));
    pos_y = str2num(get(findobj('Tag', 'postext_y_mm'),'String'));
    pos_z = str2num(get(findobj('Tag', 'postext_z_mm'),'String'));
    pos = [pos_x; pos_y; pos_z;];

    spm_orthviews('Reposition',pos);

	return;
end;

if strcmp(op,'setposvx'),
	% Move the crosshairs to the specified position
	%-----------------------------------------------------------------------
    pos_x = str2num(get(findobj('Tag', 'postext_x_vox'),'String'));
    pos_y = str2num(get(findobj('Tag', 'postext_y_vox'),'String'));
    pos_z = str2num(get(findobj('Tag', 'postext_z_vox'),'String'));
    pos = [pos_x; pos_y; pos_z;];

	tmp = st.vols{1}.premul*st.vols{1}.mat;
	pos = tmp(1:3,:)*[pos ; 1];
	spm_orthviews('Reposition',pos);

	return;

end;

if strcmp(op, 'addimg')
    % Add ROI .img file to the list and the display
    % --------------------------------------------------------------------
    img = spm_get(1, '.img', 'Select ROI .img file to add');
    set(findobj('Tag', 'Image Window'), 'Pointer', 'watch');
    set(findobj('Tag', 'plotfig'), 'Pointer', 'watch');
    v = spm_vol(img);
    [Y,XYZ] = spm_read_vols(v);
    v.XYZ = XYZ(:,find(Y==max(max(max(Y)))));
    half = round((size(v.XYZ,2) / 2));
    v.center = v.XYZ(:,half);

    rois = get(findobj('Tag', 'ROIListBox'), 'UserData');
    
    for i = 1:size(rois,1)
        curr = rois{i};
        if strcmp(curr.fname, v.fname)
            fprintf('\nROI %s has already been added!\n', v.fname);
            return;
        end
    end

    rois = vertcat(rois, {v});
    set(findobj('Tag', 'ROIListBox'), 'UserData', rois);
    liststring = get(findobj('Tag', 'ROIListBox'), 'String');
    liststring = vertcat(liststring, {spm_str_manip(v.fname, 'a20')});
    set(findobj('Tag', 'ROIListBox'), 'String', liststring);
        
    colorindex = get(findobj('Tag', 'AddROIImgButton'),'UserData');
    spm_orthviews('addcolouredimage', 1, v.fname, colors(colorindex,:));
    colorindex = colorindex + 1;
    if (colorindex > size(colors, 1))
        colorindex = 1;
    end
    set(findobj('Tag', 'AddROIImgButton'),'UserData', colorindex);

    set(findobj('Tag', 'ROIMeanModeButton'), 'Enable', 'on');
    set(findobj('Tag', 'ClearROIButton'), 'Enable', 'on');
    set(findobj('Tag', 'JumpROIButton'), 'Enable', 'on');

    cache = get(findobj('Tag', 'IntensityCheckBox'), 'UserData');
    cache.r = vertcat(cache.r, cell(1));
    set(findobj('Tag', 'IntensityCheckBox'),'UserData', cache);
    return;
    set(findobj('Tag', 'Image Window'), 'Pointer', 'arrow');
    set(findobj('Tag', 'plotfig'), 'Pointer', 'arrow');
end


if strcmp(op, 'clearrois')
    % Clear the ROI list and purge the display of blobs.
    % -----------------------------------------------------------------------
    set(findobj('Tag', 'ROIListBox'), 'UserData', []);
    set(findobj('Tag', 'ROIListBox'), 'String', []);
    set(findobj('Tag', 'ROIListBox'), 'Value', 1);
    spm_orthviews('rmBlobs', 1);
    timeseries_image('singlevoxpush');
    set(findobj('Tag', 'ROIMeanModeButton'), 'Enable', 'off');
    set(findobj('Tag', 'ClearROIButton'), 'Enable', 'off');
    set(findobj('Tag', 'JumpROIButton'), 'Enable', 'off');

    cache = get(findobj('Tag', 'IntensityCheckBox'), 'UserData');
    cache.r = [];
    set(findobj('Tag', 'IntensityCheckBox'),'UserData', cache);

    return;
end


if strcmp(op, 'listjump')
    % Jump to the 'center' of the ROI currently selected in the list box.
    % ----------------------------------------------------------------------
    n = get(findobj('Tag', 'ROIListBox'), 'Value');
    rois = get(findobj('Tag', 'ROIListBox'), 'UserData');
    v = rois{n};
    spm_orthviews('Reposition', v.center);
    
    return;
end


if strcmp(op, 'singlevoxpush')
    % Switch to single-voxel analysis mode, if not already there.
    % -----------------------------------------------------------------------
    set(findobj('Tag', 'SingleVoxModeButton'), 'Value', 1);
    set(findobj('Tag', 'ROIMeanModeButton'), 'Value', 0);
    timeseries_image('shopos');    

    return;
end


if strcmp(op, 'roimeanpush')
    % Switch to ROI-mean analysis mode, if not already there.
    % -----------------------------------------------------------------------
    set(findobj('Tag', 'SingleVoxModeButton'), 'Value', 0);
    set(findobj('Tag', 'ROIMeanModeButton'), 'Value', 1);
    timeseries_image('shopos');    

    return;
end

