function HeadViewOrbit(EEG, Record)
  % -----------------------------------------------------------------------
  % HeadViewOrbit - animate the net time course of selected independent
  %                 components in 3D while orbiting the head
  %
  % Args: EEG - the EEG structure from EEGLab
  %       Record - true to record an avi file
  %
  % --- BCT 05.05.22 ------------------------------------------------------

  % reconstruct the data to be displayed

  selComp = 1:size(EEG.icawinv,2); % selected components
%  selComp = [4 5 6 7 8];
  PlotData = EEG.icawinv(:,selComp) * mean(EEG.icaact(selComp,:,:), 3);
  [nElec nSamp] = size(PlotData);

  fprintf( ...
    '\nPlotting data reconstructed from components%s\n', ...
    sprintf(' %i', selComp) ...
  );

  % -----------------------------------------------------------------------
  % timing and frame count

  StartTime = EEG.xmin; StopTime = EEG.xmax; nFrames = nSamp;

  StartFrame = max(1, min(nSamp, 1 + (StartTime - EEG.xmin) * EEG.srate));
  StopFrame = max(1, min(nSamp, 1 + (StopTime - EEG.xmin) * EEG.srate));
  nFrames = max(2, min(nSamp, nFrames));
  FrameStep = (StopFrame - StartFrame) / (nFrames - 1);
  FrameList = round(StartFrame:FrameStep:StopFrame);
  TimeStep = (StopTime - StartTime) / (nFrames - 1);

  fprintf( ...
    'Animating from %.3f sec to %.3f sec in %i frames of %.1f msec\n', ...
    StartTime, StopTime, nFrames, TimeStep*1000 ...
  );

  % -----------------------------------------------------------------------
  % video parameters

  FileName = 'test.avi';
  FrameRate = 10; % frames per second
  KeyRate = 10; % key frames per second (=FrameRate => no interpolation)
  Quality = 100; % maximum quality
  Compression = 'none'; % no compression

  if Record
    fprintf( ...
      'Writing %s at %i frames/sec; quality = %i, compression = %s\n', ...
      FileName, FrameRate, Quality, Compression ...
    );
  end;

  % -----------------------------------------------------------------------
  % render the figure

  hFig = findobj('Tag', 'HeadView');
  try figure(hFig); clf(hFig, 'reset');
  catch
    hFig = figure; set(hFig, 'Tag', 'HeadView');
    feature('UseGenericOpenGL', 1);
  end;

  xAx = 640; yAx = 480; % initial size of axes
  xNC = 0; yNC = 26; % 26 pixels is the height of the toolbar
  xM = 0; yM = 0; % vertical and horizontal margins

  scrn = get(0, 'ScreenSize');
  posFig = [ ...
    scrn(1) + (scrn(3) - xAx - xNC)/2 - xM ...
    scrn(2) + (scrn(4) - yAx - yNC)/2 - yM ...
    xAx + xNC + 2*xM ...
    yAx + yNC + 2*yM ...
  ];
  clrFig = [250 250 246]/255;
  set(hFig, ...
    'Renderer', 'OpenGL', 'Color', clrFig, 'Position', posFig ...
  );
  hAxes = gca; set(hAxes, ...
    'Visible', 'off', 'Box', 'off', 'Color', 'none', ...
    'Units', 'pixels', 'DataAspectRatio', [1 1 1], ...
    'XLimMode', 'manual', 'XGrid', 'off', ...
    'XTick', [], 'XTickMode', 'manual', 'XColor', [.8 0 0], ...
    'XTickLabel', [], 'XTickLabelMode', 'manual', ...
    'YLimMode', 'manual', 'YGrid', 'off', ...
    'YTick', [], 'YTickMode', 'manual', 'YColor', [0 .6 0], ...
    'YTickLabel', [], 'YTickLabelMode', 'manual', ...
    'ZLimMode', 'manual', 'ZGrid', 'off', ...
    'ZTick', [], 'ZTickMode', 'manual', 'ZColor', [0 0 .8], ...
    'ZTickLabel', [], 'ZTickLabelMode', 'manual', ...
    'Projection', 'perspective', 'CameraUpVector', [0 1 0] ...
  );

  % adjust the layout of the figure to fit the window size
  fprintf('\nAdjust figure window size now\n'); pause;
  posFig = get(hFig, 'Position');
  xAx = posFig(3) - 2*xM - xNC;
  yAx = posFig(4) - 2*yM - yNC;
  posAxes = [1 + xNC/2 + xM 1 + yNC/2 + yM xAx yAx];

  xmov = -22; % offset to make room for the color bar
  dTheta = 2*pi/(nFrames-1); % rotation per frame

  %ymov = 0; % offset to center the head vertically
  %Phi = 0; % angle between line of sight and z axis

  %ymov = 15; % offset to center the head vertically
  %Phi = pi/6; % angle between line of sight and z axis

  %ymov = 20; % offset to center the head vertically
  %Phi = pi/4; % angle between line of sight and z axis

  ymov = 25; % offset to center the head vertically
  Phi = pi/3; % angle between line of sight and z axis

  InitTransform = ...
    ConstructRotation('x',-Phi)' * ...
    ConstructTranslation(xmov, ymov, 0)';
  FrameTransform = ...
    ConstructTranslation(-xmov, -ymov, 0)' * ...
    ConstructRotation('x',Phi)' * ...
    ConstructRotation('z',-dTheta)' * ...
    ConstructRotation('x',-Phi)' * ...
    ConstructTranslation(xmov, ymov, 0)';

  % initial size of the plot box
  xmin = -160; xmax = 160;
  ymin = -120; ymax = 120;
  zmin = -120; zmax = 120;
  posCam = [0 0 1000]; tgtCam = [0 0 0];
  angCam = atan(ymax/(posCam(3)))*360/pi;
%  angCam = atan(ymax/(posCam(3)-zmax))*360/pi;
  set(hAxes, ...
    'XLim', [xmin xmax], 'YLim', [ymin ymax], 'ZLim', [zmin zmax], ...
    'CameraPosition', posCam, 'CameraTarget', tgtCam, ...
    'CameraViewAngle', angCam, 'Position', posAxes ...
  );

  % setup the lighting
  Lights = [
    ymin  ymax  0; ...
    ymax  ymax  0; ...
    ymin  ymin  0; ...
    ymax  ymin  0 ...
  ];
  for i = 1:size(Lights,1)
    hLight(i) = light( ...
      'Position', Lights(i,:) + posCam + [xmov ymov 0], ...
      'Color', [1 1 1], 'Style', 'infinite' ...
    );
  end;
  % optical parameters of the head material
  lsDif = .17; % diffuse strength
  lsAmb = .34; % ambient strength

  % scaling of color values
  MaxVal = 1.05 * max(abs(min(min(PlotData))), abs(max(max(PlotData))));
  MaxVal = MaxVal * 2/3; % to show more action near zero
  amin = -MaxVal; amax = MaxVal; aspan = amax - amin;
  nclr = 256; % number of entries in the color map
  set(hAxes, 'CLim', [1 nclr], 'CLimMode', 'manual');
  cmap = rgb2hsv(jet(nclr));
  % desaturate the greens near zero
  cm = cmap(:,2); cmap(:,2) = (cm - cm(nclr/2))/(cm(1) - cm(nclr/2));
  % smooth the transition
  ns = fix(nclr/64+1);
  for j = 1:1
    for i = 1:1+nclr-ns, cm(i+(ns-1)/2) = mean(cmap(i:i+ns-1,2)); end;
    cmap(:,2) = (cm - cm(nclr/2))/(cm(1) - cm(nclr/2));
  end;
  % replace the greys with flesh tones
  cm = cmap(:,2);
  cmap = [cm cm cm] .* jet(nclr) + (1 - cm) * [255 245 220]/255;
  colormap(hAxes, cmap);

  % draw the color bar
  a = (ymax-ymin-36)/nclr; b = ymax-10-a*nclr; % (1-nclr)*a/2 + .1*ymax;
  c = xmax-48; d = xmax-42;
  for i = 0:nclr-1
    cbv(2*i+1,:) = [c i*a+b 0]; cbv(2*i+2,:) = [d i*a+b 0];
  end;
  for i = 1:nclr-1
    j = 2*i-1; cbf(i,:) = [j j+1 j+3 j+2];
  end;
  hCbar = patch( ...
    'Vertices', cbv, 'Faces', cbf, ...
    'FaceVertexCData', reshape([[1:nclr];[1:nclr]],2*nclr,1), ...
    'FaceColor', 'interp', 'FaceAlpha', 1.0, 'EdgeAlpha', 1.0, ...
    'EdgeColor', 'none', 'CDataMapping', 'direct', ...
    'FaceLighting', 'phong', 'EdgeLighting', 'phong', ...
    'DiffuseStrength', lsDif, 'SpecularStrength', 0.0, ...
    'AmbientStrength', lsAmb, 'SpecularExponent', 5.0, ...
    'SpecularColorReflectance', 1.0 ...
  );

  % annotate the color bar
  nct = 4;
  for i = -nct:nct
    yval = i/nct*nclr*a/2 + (ymax-10)-nclr*a/2;
    hLin(1+nct+i) = line( ...
      [c d], [yval-sign(i) yval-sign(i)], ...
      'LineWidth', 1, 'Color', [0 0 0] ...
    );
    hVal(1+nct+i) = text(...
      d+8, yval+2, 0, ...
      sprintf('%.0f µV', i/nct*MaxVal), ...
      'FontName', 'Verdana' ...
    );
  end;

  % place the time indicator
  hTxt = text(xmax-5, -ymax, 0, '', 'FontName', 'Verdana');
  set(hTxt, ...
    'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom' ...
  );

  % load the spline file, containing G and gx, among other things
%  load('head124electrodes.spl', '-mat');
  load('a_test_ica_32.spl', '-mat');
  if size(gx,2) ~= nElec
    error('Spline file has the wrong number of electrodes');
  end;
  Gplus = pinv([(G + 0.1); ones(1,nElec)]); % pseudo-inverse of what?
  nVrtx = size(gx,1); P = zeros(1,nVrtx);

  % load files containing the head surface in patch format
  vertices = load('mheadnewpos.txt', '-ascii');
  vertices = [vertices ones(size(vertices,1),1)];
  faces = load('mheadnewtri1.txt', '-ascii');
  vndx = sort(unique(faces(:)));
  clr = repmat(nclr/2, size(vertices,1), 1);

  % draw the head
  vtx = vertices * InitTransform;
  hHead = patch( ...
    'Vertices', vtx(:,1:3), 'Faces', faces, ...
    'FaceVertexCData', clr, 'FaceColor', 'interp', ...
    'FaceAlpha', 1.0, 'EdgeAlpha', 1.0, ...
    'EdgeColor', 'none', 'CDataMapping', 'direct', ...
    'FaceLighting', 'phong', 'EdgeLighting', 'phong', ...
    'DiffuseStrength', lsDif, 'SpecularStrength', 0.0, ...
    'AmbientStrength', lsAmb, 'SpecularExponent', 5.0, ...
    'SpecularColorReflectance', 1.0 ...
  );

  % -----------------------------------------------------------------------
  % animation loop

  try
    if Record video = avifile( ...
      FileName,'fps', FrameRate, 'keyframe', KeyRate, ...
      'quality', Quality, 'compression', Compression ...
    ); end;
    Count = 0; CurrTime = StartTime;
    for i = FrameList
      if mod(Count, 10) == 0, fprintf('\nframe'); end;
      Count = Count + 1; fprintf(' %i:%i', Count, i);
      set(hTxt, 'String', sprintf('%.0f ms', CurrTime * 1000));
      CurrTime = CurrTime + TimeStep;
      % interpolate - this code is adapted from headplot()
      vi = PlotData(:,i); vm = mean(vi); vi = [vi - vm; 0];
      ui = Gplus * vi; for j = 1:nVrtx P(j) = dot(ui, gx(j,:)); end;
      % convert to colormap indices and apply color to the heads
      clr(vndx) = min(nclr, double(1+round((nclr-1)*(P+vm-amin)/aspan)));
%      for j = 1:4, set(hHead(j), 'FaceVertexCData', clr); end;
      set(hHead, 'Vertices', vtx(:,1:3), 'FaceVertexCData', clr);
      vtx = vtx * FrameTransform;
      drawnow; % capture the frame
      if Record video = addframe(video, getframe(hFig, posAxes)); end;
    end;
    if Record video = close(video); end;
    fprintf('\n\nAnimation Complete.\n\n');
  catch
    if Record video = close(video); end;
    fprintf('\n\nAnimation Aborted.\n\n');
  end;
% end
