Extract contents from cell array - matlab

I have a series of Images, stored into an array A. So every entry of A contains an Image (matrix). All matrices are equally sized.
Now I want to extract the value of a specific position (pixel), but my current approach seems to be slow and I think there may be a better way to do it.
% Create data that resembles my problem
N = 5
for i = 1:N
A{i} = rand(5,5);
end
% my current approach
I = size(A{1},1);
J = size(A{1},2);
val = zeros(N,1);
for i = 1:I
for j = 1:J
for k = 1:N
B(k) = A{k}(i,j);
end
% do further operations on B for current i,j, don't save B
end
end
I was thinking there should be some way along the lines of A{:}(i,j) or vertcat(A{:}(i,j)) but both lead to
??? Bad cell reference operation.
I'm using Matlab2008b.
For further information, I use fft on B afterwards.
Here are the results of the answer by Cris
| Code | # images | Extracting Values | FFT | Overall |
|--------------|----------|-------------------|----------|-----------|
| Original | 16 | 12.809 s | 19.728 s | 62.884 s |
| Original | 128 | 105.974 s | 23.242 s | 177.280 s |
| ------------ | -------- | ----------------- | ------- | --------- |
| Answer | 16 | 42.122 s | 27.382 s | 104.565 s |
| Answer | 128 | 36.807 s | 26.623 s | 102.601 s |
| ------------ | -------- | ----------------- | ------- | --------- |
| Answer (mod) | 16 | 14.772 s | 27.797 s | 77.784 s |
| Answer (mod) | 128 | 13.637 s | 28.095 s | 83.839 s |
The answer codes was modded to double(squeeze(A(i,j,:))); because without double the FFT took much longer.
Answer (mod) uses double(A(i,j,:));
So the improvement seems to really kick in for larger sets of images, however I currently plan with processing ~ 500 images per run.
Update
Measured with the profile function, the result of using/omitting squeeze
| Code | # Calls | Time |
|--------------------------------|---------|----------|
| B = double(squeeze(A(i,j,:))); | 1431040 | 36.325 s |
| B= double(A(i,j,:)); | 1431040 | 14.289 s |

A{:}(i,j) does not work because A{:} is a comma-separated list of elements, equivalent to A{1},A{2},A{3},...A{end}. It makes no sense to index into such an array.
To speed up your operation, I recommend that you create a 3D matrix out of your data, like this:
A3 = cat(3,A{:});
Of course, this will only work if all elements of A have the same size (as was originally specified in the question).
Now you can quickly access the data like so:
for i = 1:I
for j = 1:J
B = squeeze(A3(i,j,:));
% do further operations on B for current i,j, don't save B
end
end
Depending on the operations you apply to each B, you could vectorize those operations as well.
Edit: Since you apply fft to each B, you can obtain that also without looping:
B_fft = fft(A3,[],3); % 3 is the dimension along which to apply the FFT

Related

Postresql matrix multiplication of a table (multiply a table by itself)

I have a square table similar to this:
| c | d |
| - | - |
a | 1 | 2 |
b | 3 | 4 |
I want to calculate matrix multiplication result where this table is multiplied by itself, i.e., this:
| c | d |
| -- | - |
a | 7 | 10 |
b | 15 | 22 |
While I understand that SQL should not be my language of choice for this task, I need to do this in that language. How do I do this?
It will make your life easier if you represent your matrix elements as (i,j,a[i,j]).
WITH matrix AS (SELECT * FROM
(VALUES ('a','a',1), ('a','b',1), ('b','a',2), ('b','b',3)) AS t(i,j,a))
SELECT m1.i as i, m2.j as j, sum(m1.a * m2.a) FROM matrix m1, matrix m2
GROUP BY m1.i, m2.j
ORDER BY i,j
This will handle sparse matrices nicely as well
Here a dbfiddle that you might be able to visualize.

Extract the data from txt file with various format speification in matlab

I would like to extract Andy's result from the below txt file. My expectation is extracting 1.033, -0.017, 1.016 and put these into the cell array. Is there any possible way to extract these? I have around 100 files with same format as below.
Total 6 outlier 0
| Thomas | -0.255 | -0.006 | -0.261 |
| Todd | 1.012 | 0.112 | 1.124 |
| Harry | -0.033 | 0.005 | -0.028 |
| Andy | 1.033 | -0.017 | 1.016 |
| Zheng | 0.152 | 0.226 | 0.378 |
| Betsi | -19.409 | 1.010 | -18.399 |
| Andrew | -0.066 | 0.048 | -0.018 |
| Tom | -95.582 | 0.590 | -94.991 |
I assume there is no new line in you text file.
Let's try something:
%Open you file and load the data
fid = fopen('the_path_of_your_file');
line = fgetl(fid);
%We split the data using the '||' delimiter. Each personne's results
%is stored in a cell.
txtSplitCell = strsplit(line,'||');
%Here we check in each cell if 'Andy' appears
indAndy = cellfun(#(c)strfind(c,'Andy')),...
txtSplitCell,'UniformOutput',false);
%We split the content of Andy's results cell with the second sperator '|'
%to get the values
resAndyRaw = strsplit(txtSplitCell{find(indAndy,1)},'|');
% We only select the subsection of the cell array that actually contains
%Andy's results (in other words we remove 'Andy' in the results cell
%and we convert that into matrix;
resAndyTab = cell2mat(resAndyRaw(strcmp(resAndyRaw,'Andy'):end));
%Note: strcmp(resAndyRaw,'Andy') enable locating the postion of
%'Andy' in the resulting cell array of the strsplit function.
% Consequently thus this code should work for thomas as well.
fclose(fid)
print(resAndyTab)
I can't run that code yet (no matlab on my computer). So test it please and correct it if needed.
Bye.

Cross tab with a list of values instead of summation

I want a Cross tab that lists field values and counts them instead of just giving a count for the summation. I know I could make this with groups but I cant list the values vertically that way. From my research I believe I have to use a Display String Formula.
SQL Field Data
-------------------------------------------------
| Play # | Formation |Back Set | R/P | PLAY |
-------------------------------------------------
| 1 | TREY | FG | R | TRUCK |
-------------------------------------------------
| 2 | T | FG | R | RHINO |
-------------------------------------------------
| 3 | D | FG | P | 5 STEP |
-------------------------------------------------
| 4 | D | FG | P | 5 STEP |
-------------------------------------------------
| 5 | K JET | NG | R | DOG |
-------------------------------------------------
Desired report structure:
-----------------------------------------------------------
| Backet & Formation | Run | Pass |
-----------------------------------------------------------
| NG K JET | BULLA 1 | |
| | HELL 3 | |
-----------------------------------------------------------
| FG D | | 5 STEP 2 |
-----------------------------------------------------------
| NG K JET | DOG | |
-----------------------------------------------------------
| FG T | RHINO | |
-----------------------------------------------------------
Don't see why a Crosstab is necessary for this - especially if the entire body of the report is just that table.
Group your records by Bracket and Formation - If that's not
something natively configured in your table, make a new Formula field
and group on that.
Drop the 3 relevant fields into whichever section you need to display. (It might be a Footer, based on whether or not you want repeats
Write a formula to determine whether or not Run or Pass are displayed, and place it in their suppression field. (Good luck getting a Crosstab to do that for you! It tends to prefer 0s over blanks.)
If there's more to the report than just this table, you can cheat the system by placing your "table" into a subreport. And of course you can stretch Line objects across the sections and it will stretch to form the table outlines

Scala - Remove first row of Spark DataFrame

I know dataframes are supposed to be immutable and everything and I know it's not a great idea to try to change them. However, the file I'm receiving has a useless header of 4 columns (the whole file has 50+ columns). So, what I"m trying to do is just get rid of the very top row because it throws everything off.
I've tried a number of different solutions (mostly found on here) like using .filter() and map replacements, but haven't gotten anything to work.
Here's an example of how the data looks:
H | 300 | 23098234 | N
D | 399 | 54598755 | Y | 09983 | 09823 | 02983 | ... | 0987098
D | 654 | 65465465 | Y | 09983 | 09823 | 02983 | ... | 0987098
D | 198 | 02982093 | Y | 09983 | 09823 | 02983 | ... | 0987098
Any ideas?
The cleanest way I've seen so far is something along the lines of filtering out the first row
csv_rows = sc.textFile('path_to_csv')
skipable_first_row = csv_rows.first()
useful_csv_rows = csv_rows.filter(row => row != skipable_first_row)

Matlab: find inner boundary of set of vertices

I have a set of (x,y) points defined in the following way:
map=[0,0;66,0;66,44;44,44;44,66;110,66;110,110;0,110];
There is then a function that connects these points (which are vertices, i.e. corner points) together to form a closed shape. The example vertices I have given form a shape something like this:
________________________________________
| |
| |
| |
| ____________________|
| |
| |_______
| |
| |
| |
| |
|___________________________|
I would like to now automatically generate a second set of vertices that form a boundary inside the shape, offset by some amount. I.e. this:
inner_boundary=[5,5;61,5;61,39;39,39;39,71;105,71;105,105;5,105];
________________________________________
| ___________________________________ |
| | | |
| | _____________________| |
| | | ____________________|
| | | |
| | | |_______
| | |________ |
| | | |
| | | |
| |______________________| |
|___________________________|
Any ideas on how to do this? I've been racking my brains but can't think of a robust way to do this. I need it to automatically do this for any input set of vertices. Also, to clarify - I am just interested in how to specify the set of vertices, not the drawing part.
Many thanks!
Here is a solution based on Image Processing Toolbox functions. The basic idea is as follows:
Use "poly2mask" to create a BW (0-1) image from the polygon
coordinates
Use "imerode" to erode the mask by 1 pixel
Use "bwboundaries" to trace the new, eroded, boundary
Code example:
x = [4 10 10 4 4];
y = [4 4 10 10 4];
mask = poly2mask(x,y,12,12);
mask_eroded = imerode(mask, 1);
newBnds = bwboundaries(mask_eroded);
newBnds = newBnds{1};
Note that the newBnds will probably contain more points than you want because it traces every single pixel on the boundary. You can write a simple iterative routine to discard non-endpoints.