function build_synth

% function build_synth
%
% Generate several files "DATA/synth*.mat" containing synthetic data.
% Each file contains an object array "r" with the following fields:
%   r( i ).theta     azimuth in radians
%   r( i ).T         integer time frame index
% Each object r( i ) represents a location estimate.
%
% This data can be useful to demonstrate confident clustering.
% See IDIAP RR 04-14 (2004) or Lathoud's PhD thesis (2006).
%
% Note that the present script generates data with exactly one
% location estimate per time frame ( r( i ).T = i ).
%
% However, the same format "r" can be used to contain
% data with multiple location estimates per time frame.
%
% By Guillaume Lathoud, 2006 - lathoud@idiap.ch

  SELF_P = 0.1;

  OUTPUT_DIR = 'DATA';

  if ~exist( OUTPUT_DIR, 'dir' )
    mkdir( '.', OUTPUT_DIR );
  end
  

  
  nframes = 1200;
  
  i2 = repmat(NaN,1,nframes);
  i3 = repmat(NaN,1,nframes);
  
  i2( 1 ) = randint( 1,1, [1 2] );
  i3( 1 ) = randint( 1,1, [1 3] );
  
  % Introduce and remove objects gradually
  % so we can test the "variable number of objects" conditions
  
  i2_ind = i2;
  i2_ind( 1:62 ) = 1;
  i2_ind( 63:end-63 ) = 2;
  i2_ind( end-62:end ) = 3;
  
  i2_m{1} = cumsum([1 0] );  % First one is self-loop probability
  i2_m{2} = cumsum([SELF_P 1-SELF_P] );
  i2_m{3} = cumsum([1 0] );
  
  %%%
  
  i3_ind = i3;
  i3_ind( 1:100 ) = 1;
  i3_ind( 101:200 ) = 2;
  i3_ind( 201:end-201 ) = 3;
  i3_ind( end-200:end-101 ) = 4;
  i3_ind( end-100:end ) = 5;
  
  m = zeros( 3 );
  m( i3( 1 ), i3( 1 ) ) = 1;
  i3_m{ 1 } = cumsum( m, 1 );
  
  m = zeros( 3 );
  v = setdiff( 1:3, i3( 1 ) );
  v = v( randperm( 2 ) );
  v = [ i3( 1 )  v( 1 ) ];
  m( v( 1 ), v( 1 ) ) = SELF_P;
  m( v( 2 ), v( 2 ) ) = SELF_P;
  m( v( 1 ), v( 2 ) ) = 1-SELF_P;
  m( v( 2 ), v( 1 ) ) = 1-SELF_P;
  i3_m{ 2 } = cumsum( m, 1 );
  
  a = SELF_P;
  b = 1-SELF_P;
  c = 0;
  
  m = [ a b c; c a b; b c a ];
  i3_m{ 3 } = cumsum( m, 1 );

  m = zeros( 3 );
  v = randperm( 3 );
  m( v( 1 ), v( 1 ) ) = SELF_P;
  m( v( 2 ), v( 2 ) ) = SELF_P;
  m( v( 1 ), v( 2 ) ) = 1-SELF_P;
  m( v( 2 ), v( 1 ) ) = 1-SELF_P;
  m( v( 1 ), v( 3 ) ) = 1/2;
  m( v( 2 ), v( 3 ) ) = 1/2;
  i3_m{ 4 } = cumsum( m, 1 );
  
  m = zeros( 3 );
  v = v( 1:2 );
  v = v( randint( 1,1,[1 2] ) );
  m( v, : ) = 1;
  i3_m{ 5 } = cumsum( m, 1 );
  
  
  current_m2 = i2_m{1};
  current_m3 = i3_m{1};
  
  

  
  for a = 2:nframes

    p = rand(1,1);
    
    v = [ 0 current_m2 ];
    ind = find( ( v(1:end-1) <= p ) & ( p < v(2:end) ) );
    m2 = i2_m{ i2_ind( a ) };
    
    if ind < 2
      i2( a ) = i2( a-1 );
      current_m2( 1 ) = m2( 1 ) .* current_m2( 1 );
      current_m2( 2:end ) = m2( 2:end ) .* ( 1-current_m2(1) );
    else
      v = setdiff( 1:2, i2( a-1 ) );
      i2( a ) = v;
      current_m2 = m2;
    end

    %%%
    
    v = [ 0 current_m3(:,i3(a-1)).' ];
    ind = find( ( v(1:end-1) <= p ) & ( p < v(2:end) ) );
    m3 = i3_m{ i3_ind( a ) };
    
    i3( a ) = ind;

    current_m3 = m3;
    
  end
  
  n = 0:nframes-1;
  
  % sequence 1:  one object, sharp turns
  
  az = 2-(1:300)/150;
  az = [ az az(end) + (1:200) /200];
  az(end+1:nframes) = az(end);
  az = mod( az, 2*pi );
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_01.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 2: two non-moving objects
  
  x1 = repmat( 2.5, size( n ) );
  x2 = repmat( 0.5, size( n ) );
  
  az = x1 .* (i2 == 1 ) + x2 .* ( i2 == 2 );
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_02.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 3:  two object, one moving, the other not, no crossing
  

  x1 = 2 * tripuls( -1:.002:1, 2 );
  x1 = [ x1( 250: end ) x1( 1:249 ) ];
  x1 = repmat( x1, 1, ceil( n(end) / length( x1 ) ) );
  x1 = x1(1:length(n));
  x1 = x1 + 0.5;
  
  x2 = zeros(size(n));
  az = x1 .* (i2==1) + x2 .* (i2==2);
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_03.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 4: two objects, one moving, the other not, several crossings
   
  x1 = 2 * tripuls( -1:.002:1, 2 );
  x1 = [ x1( 250: end ) x1( 1:249 ) ];
  x1 = repmat( x1, 1, ceil( n(end) / length( x1 ) ) );
  x1 = x1(1:length(n));
  
  x2 = 1 + zeros(size(n));
  az = x1 .* (i2==1) + x2 .* (i2==2);
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_04.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 5: two objects, one moving, the other not, one "touch" crossing
  
  x1 = 2 * tripuls( -1:.002:1, 2 );
  x1 = [ x1( 250: end ) x1( 1:249 ) ];
  x1 = repmat( x1, 1, ceil( n(end) / length( x1 ) ) );
  x1 = x1(1:length(n));
  
  x2 = zeros(size(n));
  az = x1 .* (i2==1) + x2 .* (i2==2);
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_05.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 6: two objects, one moving, the other not, one zero-speed crossing
  
  x1 =  1 + sin( 2*pi*n/1000);
  
  x2 = zeros(size(n));
  az = x1 .* (i2==1) + x2 .* (i2==2);
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_06.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 7: two objects, two moving, several crossings
  
  x1 = 1 + sin( 2*pi*n/1000);
  
  x2 = 1.5 - (1:300)/500;
  x2 = [ x2 x2(end)+(1:200)/600 ];
  x2 = [ x2 x2(end) - (1:300)/400 ];
  x2 = [ x2 x2(end)+(1:500)/750 ];
  x2 = x2( 1:nframes );

  az = x1 .* (i2==1) + x2 .* (i2==2);
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_07.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );

  % sequence 8: three non-moving objects
  
  x1 = repmat( 0.5, size( n ) );
  x2 = repmat( 1, size( n ) );
  x3 = repmat( 1.5, size( n ) );
  
  az = x1 .* (i3==1) + x2 .* (i3==2) + x3 .* (i3==3);
  az = mod(az,2*pi);
    
  outfilename = fullfile( OUTPUT_DIR, 'synth_08.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 9: three objects, two moving, one not, several crossings of all three
  
  x1 = 1 + sin( 2*pi*n/1000);
  x2 = 1 + zeros(size(n));
  
  x3 = 2 - 2 * tripuls( -1:.002:1, 2 );
  x3 = repmat( x3, 1, ceil( n(end) / length( x3 ) ) );
  x3 = x3( [ 251:end 1:250 ] );
  x3 = x3(1:length(n));
  
  az = x1 .* (i3==1) + x2 .* (i3==2) + x3 .* (i3==3);
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_09.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
  
  % sequence 10: three objects, two moving, one not, several crossings of all three
  % slight shift in time w.r.t. sequence 9
  
  x1 = 1 + sin( 2*pi*n/1000);
  x2 = 1 + zeros(size(n));
  
  x3 = 2 - 2 * tripuls( [ -0.5:.002:1 -1+0.002:0.002:-0.5-0.002 ], 2 );
  x3 = repmat( x3, 1, ceil( n(end) / length( x3 ) ) );
  x3 = x3( [ 251:end 1:250 ] );
  x3 = x3(1:length(n));
  
  az = x1 .* (i3==1) + x2 .* (i3==2) + x3 .* (i3==3);
  az = mod(az,2*pi);
  
  outfilename = fullfile( OUTPUT_DIR, 'synth_10.mat' );
  mysave( outfilename, az );
  disp( [ mfilename ' wrote out "' outfilename '".' ] );
    
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Generate a "r" object array from a list of azimuths "az"

function mysave( outfilename, az )

  if nargin < 2
    error( [ mfilename ' needs 2 input arguments.' ] );
  end

  for n = 1:numel( az )
    r( n ).theta = az( n );
    r( n ).T     = n;
  end

  save( outfilename, 'r' );
  