How does [hist] from SMLib work in Pure Data? - puredata

I put the following message into a [hist 0 100 10] object (in SMLib):
0 1 2 3 3 4 5 5 5 6 7 7 7 7 8 9 10 11 11 11 11 11 12 13 14 15 16 17 18 19 20 21 22 23 23 23 23 23 23 23 23 23 23 67 99 100 107
I then hit 'absolute' and the following is output.
6 19 18 0 0 0 0 1 0 3
I was expecting it to count the occurrences of the numbers into even bins of size 10 but only six numbers are in the first bin, and the 67 is in the wrong bin!
I counted up how it's evaluated it and got the following:
[0, 1, 2, 3, 3, 4] = 6
[5, 5, 5, 6, 7, 7, 7, 7, 8, 9, 10, 11, 11, 11, 11, 11, 12, 13, 14] = 19
[15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23] = 18
[] = 0
[] = 0
[] = 0
[] = 0
[67] = 1
[] = 0
[99, 100, 107] = 3
But.. I was expecting the following result.
16 14 13 0 0 0 1 0 0 3

Fixed it!
I was using [hist 0 100 10] when I should have been using [hist 5 105 10]!

Related

How to get list of neighbors with distance N from index in matrix? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a matrix like this:
35 1 6 26 19 24
3 32 7 21 23 25
31 9 2 22 27 20
8 28 33 17 10 15
30 5 34 12 14 16
4 36 29 13 18 11
I want a list of neighbors with distance 3 for each cell. For example,
the list of neighbors with distance 3 for (1, 1) is:
[8, 28, 33, 17, 26, 21, 22, 17]
Visual explanation:
[35] 1 6 |26| 19 24
3 32 7 |21| 23 25
31 9 2 |22| 27 20
-------------------
8 28 33 |17| 10 15
-------------------
30 5 34 12 14 16
4 36 29 13 18 11
The list of neighbors with distance 3 for (3, 3) is
[4, 36, 29, 13, 18, 11, 24, 25, 20, 15, 16]
Visual explanation:
35 1 6 26 19 |24|
3 32 7 21 23 |25|
31 9 [2] 22 27 |20|
8 28 33 17 10 |15|
30 5 34 12 14 |16|
------------------------
4 36 29 13 18 |11|
------------------------
Generate an all-zero "index matrix" idx with the same size of your matrix A, and set the "seed" to 1:
A = [ ...
35 1 6 26 19 24; ...
3 32 7 21 23 25; ...
31 9 2 22 27 20; ...
8 28 33 17 10 15; ...
30 5 34 12 14 16; ...
4 36 29 13 18 11 ...
]
idx = zeros(size(A));
idx(3, 2) = 1
We get:
A =
[...]
idx =
0 0 0 0 0 0
0 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
Now, we use 2-D convolution, i.e. MATLAB's conv2 method to create the correct index matrix w.r.t. to the distance d:
idx = logical(conv2(idx, ones(2*d+1), 'same') - conv2(idx, ones(2*d-1), 'same'))
(Convolution is the key to success.)
Then, we get:
idx =
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
1 1 1 1 1 0
Since we already casted the indices to logical, we can directly access the proper elements in the matrix A:
B = A(idx).'
The final result:
B =
4 36 29 13 19 23 27 10 14 18
Please notice the difference in the result as you wrote (3, 2) in your second example, but actually marked (3, 3) as "seed".
Hope that helps!
Disclaimer: Tested with Octave 5.1.0, but also works with MATLAB Online.

Select only group of records for where condition

I have a table similar to this
THid Sid TID Sealantid
1 1 1 1
2 1 2 1
3 1 3 4
4 1 4 1
5 1 5 1
6 1 6 1
33 2 1 1
34 2 2 1
35 2 3 1
36 2 4 1
37 2 5 1
38 2 6 1
65 3 1 1
66 3 2 1
67 3 3 4
68 3 4 1
69 3 5 1
70 3 6 1
97 4 1 1
98 4 2 1
99 4 3 8
100 4 4 1
101 4 5 1
102 4 6 1
129 5 1 1
130 5 2 1
131 5 3 8
132 5 4 1
133 5 5 1
134 5 6 1
161 6 1 1
162 6 2 1
163 6 3 4
164 6 4 1
165 6 5 1
166 6 6 1
193 7 1 1
194 7 2 1
195 7 3 4
196 7 4 1
197 7 5 1
198 7 6 1
225 8 1 1
226 8 2 1
227 8 3 4
228 8 4 1
229 8 5 1
230 8 6 1
257 9 1 1
258 9 2 1
259 9 3 1
260 9 4 1
261 9 5 1
262 9 6 1
289 10 1 1
290 10 2 1
291 10 3 4
292 10 4 1
293 10 5 1
294 10 6 1
Here I wanted to find records only Sid's "where all sealantid=1"
Simple query I tried this
select * from table where sealantid=1
but this gives me all sid's but I want only SID's, Tid's (1 to 6) where all the sealantid=1
In this table 2 , 9
You can use NOT EXISTS with a subquery
Try this:
WITH SampleData AS (
SELECT V.*
FROM (VALUES
(1, 1, 1, 1)
,(2, 1, 2, 1)
,(3, 1, 3, 4)
,(4, 1, 4, 1)
,(5, 1, 5, 1)
,(6, 1, 6, 1)
,(33, 2, 1, 1)
,(34, 2, 2, 1)
,(35, 2, 3, 1)
,(36, 2, 4, 1)
,(37, 2, 5, 1)
,(38, 2, 6, 1)
,(65, 3, 1, 1)
,(66, 3, 2, 1)
,(67, 3, 3, 4)
,(68, 3, 4, 1)
,(69, 3, 5, 1)
,(70, 3, 6, 1)
,(97, 4, 1, 1)
,(98, 4, 2, 1)
,(99, 4, 3, 8)
,(100, 4, 4, 1)
,(101, 4, 5, 1)
,(102, 4, 6, 1)
,(129, 5, 1, 1)
,(130, 5, 2, 1)
,(131, 5, 3, 8)
,(132, 5, 4, 1)
,(133, 5, 5, 1)
,(134, 5, 6, 1)
,(161, 6, 1, 1)
,(162, 6, 2, 1)
,(163, 6, 3, 4)
,(164, 6, 4, 1)
,(165, 6, 5, 1)
,(166, 6, 6, 1)
,(193, 7, 1, 1)
,(194, 7, 2, 1)
,(195, 7, 3, 4)
,(196, 7, 4, 1)
,(197, 7, 5, 1)
,(198, 7, 6, 1)
,(225, 8, 1, 1)
,(226, 8, 2, 1)
,(227, 8, 3, 4)
,(228, 8, 4, 1)
,(229, 8, 5, 1)
,(230, 8, 6, 1)
,(257, 9, 1, 1)
,(258, 9, 2, 1)
,(259, 9, 3, 1)
,(260, 9, 4, 1)
,(261, 9, 5, 1)
,(262, 9, 6, 1)
,(289, 10, 1, 1)
,(290, 10, 2, 1)
,(291, 10, 3, 4)
,(292, 10, 4, 1)
,(293, 10, 5, 1)
,(294, 10, 6, 1)
) AS V (THid, Sid, TID, Sealantid)
)
SELECT DISTINCT SD.Sid
FROM SampleData AS SD
WHERE NOT EXISTS (
SELECT 1 FROM SampleData AS C
WHERE SD.Sid = C.Sid AND C.Sealantid <> 1
)
You can try it on fiddle
An alternative could be LEFT JOIN or NOT IN
SELECT DISTINCT SD.Sid
FROM SampleData AS SD
LEFT JOIN (
SELECT DISTINCT Sid FROM SampleData WHERE Sealantid <> 1
) AS C
ON SD.Sid = C.Sid
WHERE c.Sid IS NULL
SELECT DISTINCT SD.Sid
FROM SampleData AS SD
WHERE SD.Sid NOT IN (
SELECT DISTINCT Sid FROM SampleData WHERE Sealantid <> 1
)
You can use gruop by with having:
Select sid
From table
Group by sid
Having min(sealantId) = 1
And max(sealantId) = 1

Extract elements from matrix

How can I extract the elements: [1,2,5,6], [3,4,7,8], [9,10,13,14], [11,12,15,16] ?
A = [1, 2, 3, 4;
5, 6, 7, 8;
9, 10, 11, 12;
13, 14, 15, 16;];
I'm using octave.
Best regards, Chris.
If you need four matrices then use
out = mat2cell(A,[2 2], [2 2]);
If you need four vectors with values , then use
out = cellfun(#(x)(reshape(x,1,[])),mat2cell(A,[2 2], [2 2]),'UniformOutput',0);
output will be
out{:,:}
ans =
1 5 2 6
ans =
9 13 10 14
ans =
3 7 4 8
ans =
11 15 12 16
Thanks, to Joe Serrano ,If you need the value in each of the four vectors in same order use,
out = cellfun(#(x)(reshape(x',1,[])),mat2cell(A,[2 2], [2 2]),'UniformOutput',0);
output will be
out{:,:}
ans =
1 2 5 6
ans =
9 10 13 14
ans =
3 4 7 8
ans =
11 12 15 16

Can I do max filter on a sub_blocks with matlab

For example, I have a 4x4 matrix, I want to split the max into 2x2 sub_regions. and do max on the sub_region.
1, 2, 3, 4
5, 6, 7, 8
9, 10, 11, 12
13, 14, 15, 16
\|/
6, 6, 8, 8
6, 6, 8, 8
14, 14, 16, 16
14, 14, 16, 16
Does this suit your need?
(Assuming your data is in a matrix called M)
>> cellfun(#(x) max(x(:)), mat2cell(M, [2 2], [2 2]))
ans =
6 8
14 16
EDIT:
You could also include kron to achieve your desired output:
>> kron(cellfun(#(x) max(x(:)), mat2cell(M, [2 2], [2 2])), ones(2))
ans =
6 6 8 8
6 6 8 8
14 14 16 16
14 14 16 16
colfilt will get the job done:
>> M = 2; N = 2;
>> B = colfilt(A,[M N],'distinct',#(x)repmat(max(x),[M*N 1]))
B =
6 6 8 8
6 6 8 8
14 14 16 16
14 14 16 16
The key is to use the 'distinct' block type option. Test data: A = reshape(1:16,4,4).'.
You can also use blockproc if you prefer:
B = blockproc(A,[M N],#(b) repmat(max(b.data(:)),[M N]))
OR
B = kron(blockproc(A,[M N],#(b) max(b.data(:))),ones(M,N))
Note: Image Processing Toolbox required for both.

How can I generate the following Matrices in Matlab - fast method?

I have two input variables:
N=10;
M=4;
Using Matlab, I want to generate the following matrices - without using for loops, for any M and N:
%N = 1 2 3 4 5 6 7 8 9
Mat1 = [2, 3, 4, 5, 6, 7, 8, 9, 10; %M=1 -> Mat1(1, i) = N(i)+1
3, 6, 9, 12, 15, 18, 21, 27, 30; %M=2 -> Mat1(2, i) = N(i)+N(i)*2
4, 8, 12, 16, 20, 24, 28, 32, 36; %M=3 -> Mat1(2, i) = N(i)+N(i)*3
5, 10, 15, 20, 25, 30, 35, 40, 45] %M=4 -> Mat1(2, i) = N(i)+N(i)*4
%N = 1 2 3 4 5 6 7 8 9
Mat2 = [1, 2, 3, 4, 5, 6, 7, 8, 9; %M=1 -> Mat2(2, i) = N(i)
1, 4, 7, 10, 13, 16, 19, 25, 28; %M=2 -> Mat2(2, i) = N(i)+N(i)*2-2
1, 5, 9, 13, 17, 21, 25, 29, 33; %M=3 -> Mat2(2, i) = N(i)+N(i)*3-3
1, 6, 11, 16, 21, 26, 31, 36, 41] %M=4 -> Mat2(2, i) = N(i)+N(i)*4-4
General description:
% i=1:N
%Mat1(M, i) = N(i)+N(i)*M , if M>1
% N(i)+1 , if M=1
%Mat2(M, i) = N(i)+N(i)*M-M , if M>1
% N(i) , if M=1
I wrote a code with two for loops, but I would like to ask if there is any method to get these results, without using loops. I tried with bsxfun and arrayfun, but I did not manage to get the right result:
clear Mat1 Mat2
N=10;
M=9;
Mat1 = ones(M, N);
Mat2 = ones(M, N);
for i=1:M
for j=1:N
if i==1
Mat1(i, j) = j+1;
Mat2(i, j) = j;
elseif j ==1
Mat1(i, j) = j+j*i;
elseif i~=1 && j~=1
Mat1(i, j) = j+j*i;
Mat2(i, j) = j+j*i-i;
end
end
end
Thank you
My try:
N=10;
M=4;
mat1 = bsxfun(#(x,y) x*(y.*(y>1)+1)+(y==1), 1:N,(1:M)')
mat2 = bsxfun(#(x,y) x*(y.*(y>1)+1)-(y>1).*y, 1:N,(1:M)')
I think this might do what you are looking for:
First matrix:
Mat1 = (2:N+1)'*(1:N);
Mat1 = Mat1(1:M,:);
Mat1(1,:) = 2:N+1;
This gives (N=10, M=4):
Mat1 =
2 3 4 5 6 7 8 9 10 11
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
Second matrix:
tmp = (0:N-2)'*(1:N-1);
Mat2 = repmat((4:3:3*N),M-1,1) + tmp(1:M-1,:);
Mat2 = [ones(M,1), [2:N; Mat2]];
Which gives:
Mat2 =
1 2 3 4 5 6 7 8 9 10
1 4 7 10 13 16 19 22 25 28
1 5 9 13 17 21 25 29 33 37
1 6 11 16 21 26 31 36 41 46
It was a bit of a puzzle, as it is not all too clear what exactly are the rules to build these matrices. But if it is just these matrices you want, this should be a fast way to get them.
For all N and M these lines of code produce the same matrices as you code with for loops does.
Meanwhile I learned how to use bsxfun and repmat. I got a compact code for both Mat1 and Mat2 generators:
N=10;
M=4;
Mat1 = bsxfun(#times, (1:M)', (1:N)) +...
[ones(1, N) ; horzcat( ones(M-1,1) , repmat(2:N,M-1,1) ) ];
Mat2 = [ones(M,1), [(2:N); bsxfun(#plus, (2:M)',(2:N)) +...
horzcat( zeros(M-1,1), bsxfun(#times, (2:M)',(1:N-2)) ) ] ];
Mat1 =
2 3 4 5 6 7 8 9 10 11
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
Mat2 =
1 2 3 4 5 6 7 8 9 10
1 4 7 10 13 16 19 22 25 28
1 5 9 13 17 21 25 29 33 37
1 6 11 16 21 26 31 36 41 46
I haven't tried these for every test case so I am not sure if it's totally general. I think you should be able to investigate what I used to do this and arrive at a solution for the first matrix as well. I think you might have some typos in your sample matrices above, hopefully this will get you on the right track
M=4;
N=10;
Mat2=repmat([1:N],M,1);
Mat2(2:M,:)=Mat2(2:M,:)+bsxfun(#times, Mat2(2:M,:), [2:M]');
Mat2(2:M,:)=bsxfun(#minus, Mat2(2:M,:), [2:M]');
gives us:
Mat2 =
1 2 3 4 5 6 7 8 9 10
1 4 7 10 13 16 19 22 25 28
1 5 9 13 17 21 25 29 33 37
1 6 11 16 21 26 31 36 41 46
with M=5 and N=10
Mat2 =
1 2 3 4 5 6 7 8 9 10
1 4 7 10 13 16 19 22 25 28
1 5 9 13 17 21 25 29 33 37
1 6 11 16 21 26 31 36 41 46
1 7 13 19 25 31 37 43 49 55
and I think this is Mat1:
Mat1=repmat([1:N],M,1);
Mat1(2:M,:)=Mat1(2:M,:)+bsxfun(#times, Mat1(2:M,:), [2:M]');
Mat1(1,:)=Mat1(1,:)+1;
Mat1 =
2 3 4 5 6 7 8 9 10 11
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50