Loop function in Matlab Programming - matlab

I am trying to make a loop as below description in Matlab programming.
It likes two trees exploration.
Problem1:
I create a function with two input variables and output with four vars.
From originCoord(x,y,z) it creates two new coordinates R(x,y,z), L(x,y,z); (R means Right, L: left)
next R(x,y,z) -> new R1(x1,y1,z1) & L1(x1,y1,z1)
and L(x,y,z) -> new L2(x2,y2,z2) & R2(x2,y2,z2)
then to be continued
.....
loop will stop when one of the newCcoordinates() == targetCoordinates(xtarget, ytarget).
%from initial 3D point (x y z) using treeExploreation fuction to create two
%new3D points with coordinates (x1,y1,z1) and (x2,y2,z2)
%then from these new point, using this function two create new four 3D_Points...
%x y z are scala
rightPoint = [x1,y1,z1];
leftPoint = [x2,y2,z2];
targetPoint = [xtarget, ytarget, ztarget];
%store twop 3D points into coordExplore
coordExplore = [rightPoint,leftPoint];
temp = [];
flag = 0;
while (~flag)
for i=1:length(coordExplore)
[newrightPoint,newleftPoint]=treeExploration(coordExplore(i)); %help me at here !!!!
%this function with input (x,y,z) output two new coordinates i.e.
% newrightPoint(x3,y3,z3) and newleftPoint(x4,y4,z4)
if (newrightPoint==targetPoint) || (newleftPoint==targetPoint)
%this condition is to compare the output coordinates whether the same as
%the targetPoint
flag=1;
break;
else
temp =[newrightPoint,newleftPoint];
end
end
coordExplore = temp;
temp = [];
end
I got stuck when the output always greater than input. I cannot use all the output for the next loop.
Please help me to comment on how to make a loop for this case. Thanks.
Updated problems:
*I wish coordExplore(1) = rightPoint (x1 y1 z1)
and coordExplore(2) = leftPoint (x2 y2 z2)
BUT with index i=1, coordExplore(1) = x1; i=2 -> coordExplore(2) = y1;
I use the loop with coordExplore(i) in order to work from point-to-point within each point has its own coordinates(x y z). How can I do that?*
Problem2:
when one of the newCcoordinates() == targetCoordinates(xtarget, ytarget), how can I know which varibales in which direction from origin loop to last loop generating the result? (like which brands of the tree achieving the target).
In C++, I can use stack to save but in Matlab I do not know how can I save the variable for each loop.

Problem 1:
If I have understood what you want to achieve correctly, something like this should do the job.
reached_target = False;
coord = [x, y];
while ~reached_target
number_of_nodes = size(coord, 1)
new_coord = zeros(2*number_of_nodes)
for ii = 1:number_of_nodes
new_coord(ii*2-1, :) = doRightRunning(coord(ii, 1);
new_coord(ii*2, :) = doLeftRunning(coord(ii, 2);
end
target_ind = new_coord(:, 1) == x_target && new_coord(:, 2) == y_target;
if any(target_ind)
reached_target = True;
disp(find(target_ind));
end
end
However, the code you've shown doesn't match your explanations, so it's not clear if the next layer of the tree is 2 times or 4 times the size of the previous layer.
The code here basically calculates all the left and right runs for the current coordinates until the target is reached.
I haven't tested it yet, so look for bugs.
Problem 2:
It is not necessary to save the trail for knowing the turns it has made to reach the target. When a matching coordinate is found, its place in the list of coordinates reveal its trail. All you need to do is convert its index to binary and interpret 0 as right turn and 1 as left turn (since in the code, the right turn is placed on top, and the left turn on the bottom).
Example: Let's say we are in the 3rd layer of the tree with 8 coordinates and let's say the 6th coordinate matches the target. So starting from index 0, we have found a match at index which is 101 in binary format. It reveals that the turns to reach this coordinate are Left-Right-Left.

Related

Matlab Cell array accessing data

I am trying to access the first and last number in a cell array. More specifically I need the first and last X value to see how much displacement there is. I am importing a trackmate file, which is why I've added the trackmate script below (hoping it might be of some help).
The script below is the one I use; I work on a mac
addpath('/Applications/Fiji.app/scripts')
clipZ = true;
scaleT = true;
[tracks] = importTrackMateTracks('8Tracks.xml', clipZ, scaleT);
n_tracks = numel( tracks );
tracks{:,:,:};
% tracks = IMPORTTRACKMATETRACKS(file) opens the track file 'file' and
% returns the tracks in the variable 'tracks'. 'tracks' is a cell array,
% one cell per track. Each cell is made of 4xN double array, where N is the
% number of spots in the track. The double array is organized as follow:
% [ Ti, Xi, Yi, Zi ; ...] where T is the index of the frame the spot has been
% detected in. T is always an integer. X, Y, Z are the spot spatial
% coordinates in physical units.
I think the answer is the following, and it is based upon IMPORTTRACKMATETRACKS help paragraph, even if it appears badly written (it is incongruous in dimensions for the double arrays):
tracks = importTrackMateTracks('8Tracks.xml', clipZ, scaleT);
x_displacements = zeros(length(tracks), 1);
for i = 1:length(tracks)
current_track = tracks{i};
first_x = current_track(1, 2);
last_x = current_track(end, 2);
x_displacements(i) = last_x - first_x;
end
is that what you are searching for?

How to label graph edges with a loop?

I'm using a for loop to add more nodes and edges on my plot. However, when I add labels on new edges the old labels are removed. I don't know how to keep old edge-labels nor how to store the results of labeledge.
This is what I have got so far.
for r = 1: 10
for j = 1:10
H = addnode(P,nodeName{r}{j});
P = addedge(H, s{r}{j}, t{r}{j}, w{r}{j});
figure;
hold on;
h = plot(P);
labeledge(h,s{r}{j},t{r}{j},labelText{r}{j})
end
end
Every time in the new plot, I can only see the newest cluster of labels while old labels are gone. Ideally, I'd love to hold on the results of labeledge but hold on can't do this. I need to show labels in each step in the loop, thus adding another overall labeledge is not my ideal solution. Any hint would be appreciated.
Edit: All my variables are multiple cells of difference sizes in cell arrays. I use for loop to help to pick up vectors from cells because I don't know how to insert all the levels of information from such cell arrays of cells etc. into addNode function.
The main problem in your code is that you keep plotting the graph again and again. This isn't necessary. Instead, use one loop to create the graph object (G), then plot it all at once, and then use another loop for labeling the graph:
P = graph;
for r = 1: 10
for j = 1:10
P = addedge(P, s{r}{j}, t{r}{j}, w{r}{j});
end
end
h = plot(P);
for r = 1: 10
for j = 1:10
labeledge(h,s{r}{j},t{r}{j},labelText{r}{j})
end
end
If you wish to plot your graph on every iteration, you can use subgraph for that:
for k = 1:height(P.Nodes)
H = subgraph(P,1:k);
figure;
h = plot(H);
c = 1;
out = false;
for r = 1: 10
if ~out
for j = 1:10
if c < k
labeledge(h,c,labelText{r}{j})
else
out = true;
break
end
c = c+1;
end
else
break
end
end
end
Besides that, you should know that (from Matlab documentation):
For the best performance, construct graphs all at once using a single call to graph. Adding nodes or edges in a loop can be slow for large graphs.
Also, regardless of the above recommendation, for an easier manipulation of your data, you should first convert your cells to an array. If your cell array contains a different number of elements in each cell, then it is better to collapse it all to one column:
C = [s{:}]; % and the same for t and w
while any(cellfun(#iscell,C))
C = vertcat(C{:});
end
C = cellfun(#(x) x(:),C,'UniformOutput', false);
S = vertcat(C{:});
Labels = [labelText{:}]; % and the same nodeName
while any(cellfun(#iscell,Labels))
Labels = vertcat(Labels{:});
end
Try to remove the 'figure;' command out of the FOR loop and try to see if this worked.

Matlab identify objects at boundary

I know basic commands in order to identify objects in a picture like:
level = graythresh(bw);
bw = im2bw(bw,level);
cc = bwconncomp(bw, 4);
cc.NumObjects;
graindata = regionprops(cc, 'basic');
perimeter = regionprops(cc, 'perimeter');
Those codes above is the code I am using.
In the picture attached, I can get the number to be 4. So the code identify that there is in total 4 objects.
However, this picture actually contains two objects. If we replicate this picture and move the replicate to the up, down, left and right, we can see that there is only two objects. But they are "separated" by the boundary.
It is not doable to change the way of making the image so the only way I can think of is to use some function or codes in matlab.
I will really appreciate it if someone can provide some matlab function to solve this problem.
All you need to do is loop over the border rows and columns and merge any regions that line up on opposite sides. The following code will produce an image with the regions labelled by number in the way you want.
cc=bwconncomp(bw);
[rows,cols] = size(reg);
% matrix of region labels
regions = uint8(zeros(rows,cols));
% label each pixel with an integer for its region number
for i = 1:length(cc.PixelIdxList)
region(cc.PixelIdxList{i}) = i;
end
% loop over rows, merge the regions if pixels line up
for i = 1:rows
left = region(i,1);
right = region(i,end);
if (left>0) && (right>0) && (left~=right)
region(region==right) = left;
end
end
% loop over columns, merge the regions if pixels line up
for j = 1:cols
top = region(1,j);
bottom = region(end,j);
if (top>0) && (bottom>0) && (top~=bottom)
region(region==bottom) = top;
end
end

Accessing rows at a fixed interval

I'm looking for a way to update certain elements in a vector [nx113] for every full rotation of my system.
%% # Iterate through timesteps
for tt = 1:nTimeSteps
% # Initialise ink on transfer roller
rollers(2).ink = [zeros(1,98),ones(1,5),zeros(1,113)];
% # Rotate all rollers
for ii = 1:N
rollers(ii).ink(:) = ...
circshift(rollers(ii).ink(:),rollers(ii).rotDirection);
end
% # Update all roller-connections
for ii = 1:N
for jj = 1:nBins(ii)
if(rollers(ii).connections(jj) ~= 0)
index1 = rollers(ii).connections(jj);
index2 = find(ii == rollers(index1).connections);
ink1 = rollers(ii).ink(jj);
ink2 = rollers(index1).ink(index2);
rollers(ii).ink(jj) = (ink1+ink2)/2;
rollers(index1).ink(index2) = (ink1+ink2)/2;
end
end
end
% # Calculate average amount of ink on each roller
for ii = 1:N
averageAmountOfInk(tt,ii) = mean(rollers(ii).ink);
end
rollers(18).TakeOff = averageAmountOfInk*0.6;
end
the vector rollers(2).ink is the vector i'd like to update. currently the vector is populated only once so i have ones from row 98:103. I would like this range of elements to be populated for each 'rotation' of my system not just the first time.
The reason - I'm trying to show ink being added intermittently from only a small section of the roller surface, hence the need for only five cells to be populated.
i thought that if i iterated from 1 to the number of timesteps, in steps size nBins-Max in the loop:
for tt = 1:nBins_max:nTimeSteps
this doesn't seem to be what i'm after.
I'm also hoping to remove ink from the system at the end. for every revolution i would like to be able to remove a percentage of ink on each rotation so it does not stay in the system (as if it was being printed onto a sheet and taken away).
Hopefully someone can understand this and perhaps offer some advice on how to proceed on either or both of my issues.
Your explanation doesn't quite match your code (or vice-versa if you prefer) so I'm not entirely sure what you want to do, but the following may help you towards a solution or towards expressing your problem more clearly.
The vector rollers(2).ink has 1 row and 216 columns, so an operation such as rollers(2).ink(98:103) = something is not updating rows 98 through to 103. Note also that element 98 of that vector is initialised to 0, it's not included in the elements which are initialised to 1.
You write that you want to update a range of the elements in that vector, then write a loop statement for tt = 1:nBins_max:nTimeSteps which strides over a vector of time steps. Surely you want to write something like rollers(2).ink(99:103) = new_values.
As for removing ink from the rollers at every rotation, you could just execute a line such as rollers(2).ink = rollers(2).ink * 0.975 every rotation; obviously you'll want to replace the removal rate of 2.5% every rotation that I have chosen with whatever is right for your simulation.

Matlab: seqlogo with uniform plot column heights

In Matlab, I want to make a seqlogo plot of an amino acid sequence profile. But instead of scaling the heights of the plot columns by entropy, I want all the columns to be the same height.
I'm in the process of modifying the code from the answers to this question, but I wonder if there is a parameter to seqlogo or some other function that I have missed that will make the column heights uniform.
Alternatively, is there a statistical transformation I can apply to the sequence profile to hack the desired output? (column heights uniform, height of each letter linearly proportion to
its probability in the seqprofile)
Probably the easiest way around this problem is to directly modify the code for the Bioinformatics Toolbox function SEQLOGO (if possible). In R2010b, you can do:
edit seqlogo
And the code for the function will be shown in the editor. Next, find the following lines (lines 267-284) and either comment them out or remove them entirely:
S_before = log2(nSymbols);
freqM(freqM == 0) = 1; % log2(1) = 0
% The uncertainty after the input at each position
S_after = -sum(log2(freqM).*freqM, 1);
if corrError
% The number of sequences correction factor
e_corr = (nSymbols -1)/(2* log(2) * numSeq);
R = S_before - (S_after + e_corr);
else
R = S_before - S_after;
end
nPos = (endPos - startPos) + 1;
for i =1:nPos
wtM(:, i) = wtM(:, i) * R(i);
end
Then put this line in their place:
wtM = bsxfun(#times,wtM,log2(nSymbols)./sum(wtM));
You will probably want to save the file under a new name, like seqlogo_norm.m, so you can still use the original unmodified SEQLOGO function. Now you can create sequence profile plots with all the columns normalized to the same height. For example:
S = {'LSGGQRQRVAIARALAL',... %# Sample amino acid sequence
'LSGGEKQRVAIARALMN',...
'LSGGQIQRVLLARALAA',...
'LSGGERRRLEIACVLAL',...
'FSGGEKKKNELWQMLAL',...
'LSGGERRRLEIACVLAL'};
seqlogo_norm(S,'alphabet','aa'); %# Use the modified SEQLOGO function
OLD ANSWER:
I'm not sure how to transform the sequence profile information to get the desired output from the Bioinformatics Toolbox function SEQLOGO, but I can show you how to modify the alternative seqlogo_new.m that I wrote for my answer to the related question you linked to. If you change the line that initializes bitValues from this:
bitValues = W{2};
to this:
bitValues = bsxfun(#rdivide,W{2},sum(W{2}));
Then you should get each column scaled to a height of 1. For example:
S = {'ATTATAGCAAACTA',... %# Sample sequence
'AACATGCCAAAGTA',...
'ATCATGCAAAAGGA'};
seqlogo_new(S); %# After applying the above modification
For now, my workaround is to generate a bunch of fake sequences that match the sequence profile, then feed those sequences to http://weblogo.berkeley.edu/logo.cgi . Here is the code to make the fake sequences:
function flatFakeSeqsFromPwm(pwm, letterOrder, nSeqsToGen, outFilename)
%translates a pwm into a bunch of fake seqs with the same probabilities
%for use with http://weblogo.berkeley.edu/
%pwm should be a 4xn or a 20xn position weight matrix. Each col must sum to 1
%letterOrder = e.g. 'ARNDCQEGHILKMFPSTWYV' for my data
%nSeqsToGen should be >= the # of pixels tall you plan to make your chart
[height windowWidth] = size(pwm);
assert(height == length(letterOrder));
assert(isequal(abs(1-sum(pwm)) < 1.0e-10, ones(1, windowWidth))); %assert all cols of pwm sum to 1.0
fd = fopen(outFilename, 'w');
for i = 0:nSeqsToGen-1
for seqPos = 1:windowWidth
acc = 0; %accumulator
idx = 0;
while i/nSeqsToGen >= acc
idx = idx + 1;
acc = acc + pwm(idx, seqPos);
end
fprintf(fd, '%s', letterOrder(idx));
end
fprintf(fd, '\n');
end
fclose(fd);
end