cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Browse apps to extend the software in the new JMP Marketplace
Choose Language Hide Translation Bar
CaseyL
Level II

Reorder a list or column, according to an interlacing pattern

I am referring to interlacing as in older interlaced video techniques where the lines of pixels on your screen would be rendered in an alternating pattern of every second or every third row. (https://en.wikipedia.org/wiki/Interlaced_video has a good gif of the process)

 

so if you have your rows(1,2,3,4,.....99)

they would be rendered (factor 2) in the order rows(1,3,5,7......97,99,2,4,6,.....98)

or (factor 3) as rows(1,4,7.....2,5,8.....3,6,9....)

 

I'm trying to write a script that will reorder a sequence of arbitrary length according to this pattern with JSL but I can't quite figure out how to build an index to reorder this. I'm currently trying to work out matrix math to accomplish this but maybe a for loop would be smarter/easier?

 

// Create arbitrary sequence
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,21,22,23,24,25,26,27,28];
f = 3 // interlacing factor
//Start trying to work out an index or grouping for a future sorting op b = mod(a+f-1),3); //b = [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 2, 0, 1, 2, 0, 1, 2, 0]
// ????

 

1 ACCEPTED SOLUTION

Accepted Solutions

Re: Reorder a list or column, according to an interlacing pattern

EDIT #2: Far below is incorrect. This code should work:

Names Default To Here(1);

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27];

fact = 3;

x = shape(a, ceiling(nrow(a)/fact));
try(x[(nrow(a)+1)::(nrow(x)*ncol(x))] = .);
x = shape(x`, 1);
x = x[loc(!ismissing(x))];

 

 

 

/////////////////////////

#EDIT: I had to add an index to the end to prevent "start-over" when the factor does not evenly divide the number of rows

 

/////////////

Hi,

 

Check out the Shape() command. Along with transposing, you can get what you are after--

 

Names Default To Here(1);

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,21,22,23,24,25,26,27,28];

fact = 3;

shape(shape(a, ceiling(nrow(a)/fact))`, 1)`[1::nrow(a)]

Cheers,

Brady

View solution in original post

6 REPLIES 6

Re: Reorder a list or column, according to an interlacing pattern

EDIT #2: Far below is incorrect. This code should work:

Names Default To Here(1);

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27];

fact = 3;

x = shape(a, ceiling(nrow(a)/fact));
try(x[(nrow(a)+1)::(nrow(x)*ncol(x))] = .);
x = shape(x`, 1);
x = x[loc(!ismissing(x))];

 

 

 

/////////////////////////

#EDIT: I had to add an index to the end to prevent "start-over" when the factor does not evenly divide the number of rows

 

/////////////

Hi,

 

Check out the Shape() command. Along with transposing, you can get what you are after--

 

Names Default To Here(1);

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,21,22,23,24,25,26,27,28];

fact = 3;

shape(shape(a, ceiling(nrow(a)/fact))`, 1)`[1::nrow(a)]

Cheers,

Brady

CaseyL
Level II

Re: Reorder a list or column, according to an interlacing pattern

 

[1::nrow(a)]

removes the wrapped-around positions after the second shape, so unfortunately the wrong values are being truncated. 

 

 

I used what you gave me to flag the wrapped around values (as 0's in this case but maybe NaN or something would be better?) so that they can be easily identified and excised at the end of the operation. I know I use way too many variables, please ignore the sloppiness.

 

n = 28;						// Number of rows
f = 3;						// Interlacing factor (how many scans per frame)

q = ceiling(n/f);
r = q*f;
a = 1::r;

a[loc(a > n)] = 0;			//a = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 0 0];
s = shape(shape(a, q)`,1); 	//s = [1 4 7 10 13 16 19 22 25 28 2 5 8 11 14 17 20 23 26 0 3 6 9 12 15 18 21 24 27 0];
b = s[loc(s)];				//b = [1 4 7 10 13 16 19 22 25 28 2 5 8 11 14 17 20 23 26 3 6 9 12 15 18 21 24 27];
show(b);

c = [];
For(i = 1, i <= nrow(b), i++,
	c = c || a`[i] || b[i];
);
show(c`);					//c` gives a vector to copy/paste into a match() function that will translate progressive rows to interlaced rows

 

Re: Reorder a list or column, according to an interlacing pattern

Hi Casey,

 

You are right--my apologies! Try this code, which sets extra values to missing before the initial transpose, so they can be weeded out with Loc() later.

 

Names Default To Here(1);

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27];

fact = 3;

x = shape(a, ceiling(nrow(a)/fact));
try(x[(nrow(a)+1)::(nrow(x)*ncol(x))] = .);
x = shape(x`, 1);
x = x[loc(!ismissing(x))];
jthi
Super User

Re: Reorder a list or column, according to an interlacing pattern

This seems to be getting correct matrices (might require transposing if starting matrix is built differently)

 

Names Default To Here(1);

// Create arbitrary sequence
a = 1::30;
f = 3;
b = Mod(a+f-1,f);
m_interlaced = [];
For(i = 0, i <= f-1, i++,
	m_interlaced = m_interlaced |/ a[Loc(b, i)];
);
show(m_interlaced);

Names Default To Here(1);

// Create arbitrary sequence
a = 1::99;
f = 2;
b = Mod(a+f-1,f);
m_interlaced = [];
For(i = 0, i <= f-1, i++,
	m_interlaced = m_interlaced |/ a[Loc(b, i)];
);
show(m_interlaced);

 

 

-Jarmo
CaseyL
Level II

Re: Reorder a list or column, according to an interlacing pattern

in JMP14 this returns "Argument should be list" I believe referring to where b is called in the Loc function. I tried to modify b with as list() but i don't understand the result.

 

seperately, what does |/ do and is it related to the concat operator ||?

 

a = 1::30;
f = 3;
b = as list(Mod(a+f-1,f));
m_interlaced = [];
For(i = 0, i <= f-1, i++,
	m_interlaced = m_interlaced |/ a[Loc(b, i)];
);
show(m_interlaced);

/*:

m_interlaced = [](0, 1);
jthi
Super User

Re: Reorder a list or column, according to an interlacing pattern

I luckily still had JMP14 installed so I could test it out. One "workaround" would be like this:

Names Default To Here(1);

// Create arbitrary sequence
a = Transpose(1::30);
f = 3;
b = AsList(Mod(a+f-1,f));
m_interlaced = [];
For(i = 0, i <= f-1, i++,
	m_interlaced = m_interlaced |/ a[Loc(b, i)];
);
show(m_interlaced);

//m_interlaced = [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30];

 

 

-Jarmo