Overlay line plot with shaded bar areas in matlab - matlab

I want to overlay my line plot in Matlab with colored bars for different x-axis values. The functionality I'm looking for is much like recessionplot(), but it should not indicate NBER recessions, but user defined periods. I'm able to do this with the following code, but the color of my original line is changed. How do I avoid this in the best way?
%%%%%%%%%%%% Functions to shade %%%%%%%%%%%%%%%%%%%
function []=shadedates(Start,Finish,colorstr)
curax=axis;
indx1=find(Finish>curax(1)); % First Date to include;
indx2=find(Start<curax(2)); % Last Date to include;
indx1=indx1(1);
indx2=indx2(length(indx2));
if Start(indx1)<curax(1);
Start(indx1)=curax(1);
end;
if Finish(indx2)>curax(2);
Finish(indx2)=curax(2);
end;
shade(Start(indx1:indx2),Finish(indx1:indx2),colorstr);
end
function []=shade(Start,Finish,colorstr)
% Start and Finish are Nx1 vectors of starting and ending years.
% The function shades between the start and finish pairs using colorstr
if ~exist('colorstr','var'); colorstr='y'; end; % default is yellow
curax=axis;
y=[curax(3) curax(4) curax(4) curax(3)];
hold on;
for i=1:length(Start);
x=[Start(i) Start(i) Finish(i) Finish(i)];
h=fill(x,y,colorstr);
set(h,'facealpha',.3)
end;
h = findobj(gca,'Type','patch');
set(h,'EdgeColor','none');
% This last one makes the tick marks visible
set(gca, 'Layer', 'top')
end
%%%%%%%%%%%%%%% Create data %%%%%%%%%%%%%%%%%%%%%%
GLI.Dates = transpose(714890:(714890+99));
GLI.GLI = cumsum([50;normrnd(0,1,99,1)]);
GLI.ProsStart = zeros(size(GLI.GLI));
GLI.RecStart = zeros(size(GLI.GLI));
GLI.ProsFin = zeros(size(GLI.GLI));
GLI.RecFin = zeros(size(GLI.GLI));
TempLag = GLI.GLI(1);
CurPhase = 0;
for i=2:size(GLI.GLI,1)
Temp = GLI.GLI(i);
if Temp > TempLag && CurPhase ~= 1
GLI.ProsStart(i-1) = 1;
if CurPhase == 2
GLI.RecFin(i-1) = 1;
end
CurPhase = 1;
elseif Temp < TempLag && CurPhase ~= 2
GLI.RecStart(i-1) = 1;
if CurPhase == 1
GLI.ProsFin(i-1) = 1;
end
CurPhase = 2;
end
TempLag = Temp;
end
if CurPhase == 1
GLI.ProsFin(end) = 1;
elseif CurPhase == 2
GLI.RecFin(end) = 1;
end
%%%%%%%%%%%%%%%%%%% Create plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
plot(GLI.Dates,GLI.GLI)
colorstr=[0 1 0];
shadedates(GLI.Dates(logical(GLI.ProsStart)),GLI.Dates(logical(GLI.ProsFin)),colorstr)
colorstr=[1 0 0];
shadedates(GLI.Dates(logical(GLI.RecStart)),GLI.Dates(logical(GLI.RecFin)),colorstr)

save a handle to the plotted object:
p = plot(GLI.Dates,GLI.GLI)
and then use this (after the calls to shadedates):
uistack(p,'top')
(I have this from here)

Related

how to update axes in guide - matlab

i write a code using GUI and Mfile in MATHLAB. in my program i have a board.each time, computer put a marble and rotate the board then get a marble place and rotate direction of the board from user and After each of these things, i want it shows the result in axes1 in GUI. but it doesen't work in line 9 in the code below:
% some codes...
1. while(currentDepth < 7)
2. if(mod(currentDepth,2) ~= (plrC-1))
3. plat(currentDepth);
4. drawTable(); % show the result in axes1 --> it works
5. else
6. getMarble();
7. drawTable(); % show the result in axes1 --> it works
8. rotate();
9. drawTable(); % show the result in axes1 --> it dosen't work
10. end
11. end
% some codes...
.
function drawTable()
global board;
% some codes...
imshow(board,[0 4]);
end
do you have any idea?
it's rotate function. th board is divided into 4 parts just 1 part rotates.
function rotate()
global board;
block = 0;
vector = 'non';
while(block<1 || block>4)
block = str2double(cell2mat(inputdlg('chose a block: 1/2/3/4','board rotation')));
end
switch block
case 1
k=1; z=1;
case 2
k=1; z=4;
case 3
k=4; z=1;
case 4
k=4; z=4;
end
while(~strcmp(vector,'left') && ~strcmp(vector,'right'))
vector = questdlg('rotate left or right','Rotation','left','right','right');
end
if(strcmp(vector,'left'))
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2));
else
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2),3);
end
end
ok now here we have a simplified code. make a new GUI with an axes then run the code below from 'OpeningFnc'. you will see my problem.
function test()
currentDepth = 1;
plrC = 1;
plrO = 2;
board = zeros(6);
while(currentDepth < 40)
if(mod(currentDepth,2) == 1)
plat();
drawTable(); % show the result in axes1 --> it works
else
getMarble();
drawTable(); % show the result in axes1 --> it works
rotate();
drawTable(); % show the result in axes1 --> it dosen't work
end
currentDepth = currentDepth +1;
end
function plat()
for a=1:5000
for b=1:5000
for c=1:50
m = a + b;
end
end
end
row = 1;
column = 1;
while(board(row,column) ~= 0)
row = randi(6);
column = randi(6);
end
board(row,column) = plrC;
row = randi([1 4]);
column = randi([1 4]);
board(row:row+2,column:column+2)=rot90(board(row:row+2,column:column+2));
end
function drawTable()
board(board==0) = board(board==0)+4;
B = zeros(305);
B(:,152:154) = 3;
B(152:154,:) = 3;
for i=1:6
for j=1:6
x = (i*5)+1+(i-1)*45;
y = (j*5)+1+(j-1)*45;
B(x:x+44,y:y+44) = board(i,j);
end
end
imshow(B,[0 4]);
board(board==4) = board(board==4)*0;
end
function getMarble()
board(board==0) = board(board==0)+4;
b = zeros(305);
b(:,152:154) = 3;
b(152:154,:) = 3;
for i=1:6
for j=1:6
x = (i*5)+1+(i-1)*45;
y = (j*5)+1+(j-1)*45;
b(x:x+44,y:y+44) = board(i,j);
end
end
imshow(b,[0 4]);
i = 0;
while(i~=4)
[x,y] = ginput(1);
if(x<0 || x>305 || y<0 || y>305)
i = 0;
else
i = b(ceil(y),ceil(x));
end
end
y = ceil(y/50);
x = ceil(x/50);
board(y,x) = plrO;
end
function rotate()
block = 0;
vector = 'non';
while(block<1 || block>4)
block = str2double(cell2mat(inputdlg('chose a block: 1/2/3/4','board rotation')));
end
switch block
case 1
k=1; z=1;
case 2
k=1; z=4;
case 3
k=4; z=1;
case 4
k=4; z=4;
end
while(~strcmp(vector,'left') && ~strcmp(vector,'right'))
vector = questdlg('rotate left or right','Rotation','left','right','right');
end
if(strcmp(vector,'left'))
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2));
else
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2),3);
end
end
end
as ThP said, i have to add drawnow() function at the end of drawTable.

Finger peak detection using MATLAB

I have to create an algorithm with Matlab that, with a image of a hand, can know the form of the hand by the number of raised fingers and the presence or absence of the thumb. So far, the algorithm is almost complete but I don't know what more I can do that could find the peaks that represents the fingers. We tried a lot of things but nothing works. The idea is to find when there is a sudden increasement but as the pixels are never completely aligned, nothing that we tried worked. Someone has any idea? Here is the code so far.
The image that he is reading is this one:
To know if the finger is relevant or not, we already have an idea that might work... but we need to find the fingers first.
clear all
close all
image=imread('mao2.jpg');
YCBCR = rgb2ycbcr(image);
image=YCBCR;
cb = image(:,:,2);
cr = image(:,:,3);
imagek(:,1) = cb(:);
imagek(:,2) = cr(:);
imagek = double(imagek);
[IDX, C] = kmeans(imagek, 2, 'EmptyAction', 'singleton');
s=size(image);
IDX= uint8(IDX);
C2=round(C);
imageNew = zeros(s(1),s(2));
temp = reshape(IDX, [s(1) s(2)]);
for i = 1 : 1 : s(1)
for j = 1 : 1 : s(2)
imageNew(i,j,:) = C2(temp(i,j));
end
end
imageNew=uint8(imageNew);
[m,n]=size(imageNew);
for i=1:1:m
for j = 1:1:n
if(imageNew(i,j)>=127)
pretobranco(i,j)=0;
else
pretobranco(i,j)=1;
end
end
end
I2=imfill(pretobranco);
imshow(I2);
imwrite(I2, 'mao1trab.jpg');
[m,n]=size(I2);
B=edge(I2);
figure
imshow(B);
hold on;
stats=regionprops(I2,'BoundingBox');
rect=rectangle('position', [stats(1).BoundingBox(1), stats(1).BoundingBox(2), stats(1).BoundingBox(3), stats(1).BoundingBox(4)], 'EdgeColor', 'r');
stats(1).BoundingBox(1)
stats(1).BoundingBox(2)
stats(1).BoundingBox(3)
stats(1).BoundingBox(4)
figure
Bound = B( stats(1).BoundingBox(2): stats(1).BoundingBox(2)+stats(1).BoundingBox(4)-1, stats(1).BoundingBox(1):stats(1).BoundingBox(1)+stats(1).BoundingBox(3)-1);
imshow(Bound)
y1 = round(stats(1).BoundingBox(2))
y2 = round(stats(1).BoundingBox(2)+stats(1).BoundingBox(4)-1)
x1 = round(stats(1).BoundingBox(1))
x2 = round(stats(1).BoundingBox(1)+stats(1).BoundingBox(3)-1)
% Bounding box contida em imagem[M, N].
[M,N] = size(Bound)
vertical=0;
horizontal=0;
if M > N
vertical = 1 %imagem vertical
else
horizontal = 1 %imagem horizontal
end
%Find thumb
MaoLeft = 0;
MaoRight = 0;
nPixelsBrancos = 0;
if vertical==1
for i = x1:1:x2
for j= y1:1:y2
if I2(j,i) == 1
nPixelsBrancos = nPixelsBrancos + 1; %Numero de pixels da mão
end
end
end
for i=x1:1:x1+30
for j=y1:1:y2
if I2(j,i) == 1
MaoLeft = MaoLeft + 1; %Number of pixels of the hand between the 30 first colums
end
end
end
for i=x2-30:1:x2
for j=y1:1:y2
if I2(j,1) == 1
MaoRight = MaoRight + 1; %Number of pixels of the hand between the 30 last colums
end
end
end
TaxaBrancoLeft = MaoLeft/nPixelsBrancos
TaxaBrancoRight = MaoRight/nPixelsBrancos
if TaxaBrancoLeft <= (7/100)
if TaxaBrancoRight <= (7/100)
Thumb = 0 %Thumb in both borders is defined as no Thumb.
else
ThumbEsquerdo = 1 %Thumb on left
end
end
if TaxaBrancoRight <= (7/100) && TaxaBrancoLeft >= (7/100)
ThumbDireito = 1 %Thumb on right
end
end
if horizontal==1
for i = x1:1:x2
for j= y1:y2
if I2(i,j) == 1
nPixelsBrancos = nPixelsBrancos + 1; %Numero de pixels da mão
end
end
end
for i=x1:1:x2
for j=y1:1:y1+30
if I2(i,j) == 1
MaoLeft = MaoLeft + 1; %Numero de pixels da mão entre as 30 primeiras colunas
end
end
end
for i=x1:1:x2
for j=y2-30:1:y2
if I2(j,1) == 1
MaoRight = MaoRight + 1; %Numero de pixels da mão entre as 30 ultimas colunas
end
end
end
TaxaBrancoLeft = MaoLeft/nPixelsBrancos
TaxaBrancoRight = MaoRight/nPixelsBrancos
if TaxaBrancoLeft <= (7/100)
if TaxaBrancoRight <= (7/100)
Thumb = 0 %Polegar nas duas bordas. Definimos como sem polegar.
else
ThumbEsquerdo = 1 %Polegar na borda esquerda
end
end
if TaxaBrancoRight <= (7/100) && TaxaBrancoLeft >= (7/100)
ThumbDireito = 1 %Polegar na borda direita
end
end
figure
imshow(I2);
%detecção da centroid
Ibw = im2bw(I2);
Ilabel = bwlabel(Ibw);
stat = regionprops(Ilabel,'centroid');
figure
imshow(I2); hold on;
for x = 1: numel(stat)
plot(stat(x).Centroid(1),stat(x).Centroid(2),'ro');
end
centroid = [stat(x).Centroid(1) stat(x).Centroid(2)] %coordenadas x e y da centroid
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Seemed like an interesting problem, so I gave it a shot. Basically you start with a Sobel filter to find the edges in your image (after slight denoising). Then clean up the resulting lines, use them to separate regions within your binary mask of the hand, use a watershed transform to find the wrist, some distance transforms to find other landmarks, then remove the palm. What you're left with is separate regions for each finger and thumb. You can count those regions easily enough or find which way they are pointing, or whatever you'd like.
imgURL = 'https://encrypted-tbn2.gstatic.com/imgs?q=tbn:ANd9GcRQsqJtlrOnSbJNTnj35Z0uG9BXsecX2AXn1vV0YDKodq-zSuqnnQ';
imgIn=imread(imgURL);
gaussfilt = fspecial('gaussian', 3, .5); % Blur starting image
blurImg = imfilter(double(img(:,:,1)), gaussfilt);
edgeImg = edge(blurImg, 'sobel'); % Use Sobel edge filter to pick out contours of hand + fingers
% Clean up contours
edgeImg = bwmorph(edgeImg, 'close', 1);
edgeImg = bwmorph(edgeImg, 'thin', Inf);
% Clean up rogue spots in corners
edgeImg([2 end-1], 2) = 0;
edgeImg([2 end-1], end-1) = 0;
% Extend lines to edge of image (correct for 'close' operation above
edgeImg([1 end],:) = edgeImg([2 end-1],:);
edgeImg(:, [1 end]) = edgeImg(:, [2 end-1]);
% Remove all but the longest line
regs = regionprops(edgeImg, 'Area', 'PixelIdxList');
regs(vertcat(regs.Area) ~= max(vertcat(regs.Area))) = [];
lineImg = false(size(edgeImg, 1), size(edgeImg, 2));
lineImg(regs.PixelIdxList) = 1;
fillImg = edgeImg;
% Close in wrist
if any(fillImg(1,:))
fillImg(1,:) = 1;
end
if any(fillImg(end,:))
fillImg(end,:) = 1;
end
if any(fillImg(:,1))
fillImg(:,1) = 1;
end
if any(fillImg(:,end))
fillImg(:,end) = 1;
end
fillImg = imfill(fillImg, 'holes');
fillImg([1 end], :) = 0;
fillImg(:, [1 end]) = 0;
fillImg([1 end],:) = fillImg([2 end-1],:);
fillImg(:, [1 end]) = fillImg(:, [2 end-1]);
% Start segmenting out hand + fingers
handBin = fillImg;
% Set lines in above image to 0 to separate closely-spaced fingers
handBin(lineImg) = 0;
% Erode these lines to make fingers a bit more separate
handBin = bwmorph(handBin, 'erode', 1);
% Segment out just hand (remove wrist)
distImg = bwdist(~handBin);
[cDx, cDy] = find(distImg == max(distImg(:)));
midWrist = distImg;
midWrist = max(midWrist(:)) - midWrist;
midWrist(distImg == 0) = Inf;
wristWatershed = watershed(imerode(midWrist, strel('disk', 10)));
whichRegion = wristWatershed(cDx, cDy);
handBin(wristWatershed ~= whichRegion) = 0;
regs = regionprops(handBin, 'Area', 'PixelIdxList');
regs(vertcat(regs.Area) ~= max(vertcat(regs.Area))) = [];
handOnly = zeros(size(handBin, 1), size(handBin, 2));
handOnly(regs.PixelIdxList) = 1;
% Find radius of circle around palm centroid that excludes wrist and splits
% fingers into separate regions.
% This is estimated as D = 1/3 * [(Centroid->Fingertip) + 2*(Centroid->Wrist)]
% Find Centroid-> Wrist distance
dist2w = wristWatershed ~= whichRegion;
dist2w = bwdist(dist2w);
distToWrist = dist2w(cDx, cDy);
% Find Centroid-> Fingertip distance
dist2FE = zeros(size(handOnly, 1), size(handOnly, 2));
dist2FE(cDx, cDy) = 1;
dist2FE = bwdist(dist2FE).*handOnly;
distToFingerEnd = max(dist2FE(:));
circRad = mean([distToFingerEnd, distToWrist, distToWrist]); % Estimage circle diameter
% Draw circle
X = bsxfun(#plus,(1:size(handOnly, 1))',zeros(1,size(handOnly, 2)));
Y = bsxfun(#plus,(1:size(handOnly, 2)),zeros(size(handOnly, 1),1));
B = sqrt(sum(bsxfun(#minus,cat(3,X,Y),reshape([cDx, cDy],1,1,[])).^2,3))<=circRad;
% Cut out binary mask within circle
handOnly(B) = 0;
% Label separate regions, where each now corresponds to a separate digit
fingerCount = bwlabel(handOnly);
% Display overlay image
figure()
imshow(imgIn)
hold on
overlayImg = imshow(label2rgb(fingerCount, 'jet', 'k'));
set(overlayImg, 'AlphaData', 0.5);
hold off
Results:
http://imgur.com/ySn1fPy

Matlab - Failures of function to detect collisions between line segments and circle

Many questions exist already covering how to detect collisions between a line segment and a circle.
In my code, I am using Matlab's linecirc function, then comparing the intersection points it returns with the ends of my line segments, to check that the points are within the line (linecirc assumes an infinite line, which I don't have/want).
Copying and adding some sprintf calls to the linecirc function shows that it is calculating points as intended. These seem to be being lost by my function.
My code is below:
function cutCount = getCutCountHex(R_g, centre)
clf;
cutCount = 0;
% Generate a hex grid
Dg = R_g*2;
L_b = 62;
range = L_b*8;
dx = Dg*cosd(30);
dy = 3*R_g;
xMax = ceil(range/dx); yMax = ceil(range/dy);
d1 = #(xc, yc) [dx*xc dy*yc];
d2 = #(xc, yc) [dx*(xc+0.5) dy*(yc+0.5)];
centres = zeros((xMax*yMax),2);
count = 1;
for yc = 0:yMax-1
for xc = 0:xMax-1
centres(count,:) = d1(xc, yc);
count = count + 1;
centres(count, :) = d2(xc, yc);
count = count + 1;
end
end
for i=1:size(centres,1)
centres(i,:) = centres(i,:) - [xMax/2 * dx, yMax/2 * dy];
end
hold on
axis equal
% Get counter for intersected lines
[VertexX, VertexY] = voronoi(centres(:,1), centres(:,2));
numLines = size(VertexX, 2);
for lc = 1:numLines
segStartPt = [VertexX(1,lc) VertexY(1,lc)];
segEndPt = [VertexX(2,lc) VertexY(2,lc)];
slope = (segEndPt(2) - segStartPt(2))/(segEndPt(1) - segStartPt(1));
intercept = segEndPt(2) - (slope*segEndPt(1));
testSlope = isinf(slope);
if (testSlope(1)==1)
% Pass the x-axis intercept instead
intercept = segStartPt(1);
end
[xInterceptionPoints, yInterceptionPoints] = ...
linecirc(slope, intercept, centre(1), centre(2), L_b);
testArr = isnan(xInterceptionPoints);
if (testArr(1) == 0) % Line intersects. Line segment may not.
interceptionPoint1 = [xInterceptionPoints(1), yInterceptionPoints(1)];
interceptionPoint2 = [xInterceptionPoints(2), yInterceptionPoints(2)];
% Test if first intersection is on the line segment
p1OnSeg = onSeg(segStartPt, segEndPt, interceptionPoint1);
p2OnSeg = onSeg(segStartPt, segEndPt, interceptionPoint2);
if (p1OnSeg == 1)
cutCount = cutCount + 1;
scatter(interceptionPoint1(1), interceptionPoint1(2), 60, 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k');
end
% Test if second intersection point is on the line segment
if (interceptionPoint1(1) ~= interceptionPoint2(1) || interceptionPoint1(2) ~= interceptionPoint2(2)) % Don't double count touching points
if (p2OnSeg == 1)
cutCount = cutCount + 1;
scatter(interceptionPoint2(1), interceptionPoint2(2), 60, 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k');
end
end
end
end
% Plot circle
viscircles(centre, L_b, 'EdgeColor', 'b');
H = voronoi(centres(:,1), centres(:,2));
for i = 1:size(H)
set(H(i), 'Color', 'g');
end
end
function boolVal = onSeg(segStart, segEnd, testPoint)
bvX = isBetweenOrEq(segStart(1), segEnd(1), testPoint(1));
bvY = isBetweenOrEq(segStart(2), segEnd(2), testPoint(2));
if (bvX == 1 && bvY == 1)
boolVal = 1;
else
boolVal = 0;
end
end
function boolVal = isBetweenOrEq(end1, end2, test)
if ((test <= end1 && test >= end2) || (test >= end1 && test <= end2))
boolVal = 1;
else
boolVal = 0;
end
end
It creates a hexagonal grid, then calculates the number of crossings between a circle drawn with a fixed radius (62 in this case) and a specified centre.
The scatter calls show the locations that the function counts.
Implementing sprintf calls within the if(p1OnSeg == 1) block indicates that my function has chosen fictitious intersection points (although it then deals with them correctly)
if (interceptionPoint1(1) > -26 && interceptionPoint1(1) < -25)
sprintf('p1 = [%f, %f]. Vx = [%f, %f], Vy = [%f, %f].\nxint = [%f, %f], yint = [%f, %f]',...
interceptionPoint1(1), interceptionPoint1(2), VertexX(1,lc), VertexX(2,lc), VertexY(1,lc), VertexY(2,lc),...
xInterceptionPoints(1), xInterceptionPoints(2), yInterceptionPoints(1), yInterceptionPoints(2))
end
Outputs
p1 = [-25.980762, 0.000000]. Vx = [-25.980762, -25.980762], Vy = [-15.000000, 15.000000].
xint = [-25.980762, -25.980762], yint = [0.000000, 0.000000]
A picture shows the strange points.
Sorry for the very long question but - why are these being detected. They don't lie on the circle (displaying values within a mylinecirc function detects the intersections at around (-25, 55) and (-25, -55) or so (as an infinite line would expect).
Moving the circle can remove these points, but sometimes this leads to other problems with detection. What's the deal?
Edit: Rotating my grid pattern created by [Vx, Vy] = voronoi(...) and then removing points with very large values (ie those going close to infinity etc) appears to have fixed this problem. The removal of 'large' value points seems to be necessary to avoid NaN values appearing in 'slope' and 'intercept'. My guess is this is related to a possible slight inclination due to rotation, coupled with then overflow of the expected intercept.
Example code added is below. I also edited in Jan de Gier's code, but that made no difference to the problem and so is not changed in the question code.
%Rotate slightly
RotAngle = 8;
RotMat = [cosd(RotAngle), -sind(RotAngle); sind(RotAngle), cosd(RotAngle)];
for i=1:size(centres,1)
centres(i,:) = centres(i,:) - [floor(xMax/2) * dx, floor(yMax/2) * dy]; %Translation
centres(i,:) = ( RotMat * centres(i,:)' ); %Rotation
end
% Get counter for intersected lines
[VertexX, VertexY] = voronoi(centres(:,1), centres(:,2));
% Filter vertices
numLines = size(VertexX, 2);
newVx = [];
newVy = [];
for lc = 1:numLines
testVec = [VertexX(:,lc) VertexY(:,lc)];
if ~any(abs(testVec) > range*1.5)
newVx = [newVx; VertexX(:,lc)'];
newVy = [newVy; VertexY(:,lc)'];
end
end
VertexX = newVx';
VertexY = newVy';
numLines = size(VertexX, 2);
Still appreciating answers or suggestions to clear up why this is/was occuring.
Example values that cause this are getCutCountHex(30, [0,0]) and ...(35, [0,0])
I cant reproduce your problem, but the thing I did notice is that your onSeg() function might be wrong: it returns true if the testpoint lies in the rectangle with two of the four corner points being segStart and segEnd.
A function that returns true iff a point is on (or more accurate: close enough to) the line segment (segStart,segEnd) could be:
function boolVal = onSeg(segStart, segEnd, testPoint)
tolerance = .5;
AB = sqrt((segEnd(1)-segStart(1))*(segEnd(1)-segStart(1))+(segEnd(2)-segStart(2))*(segEnd(2)-segStart(2)));
AP = sqrt((testPoint(1)-segEnd(1))*(testPoint(1)-segEnd(1))+(testPoint(2)-segEnd(2))*(testPoint(2)-segEnd(2)));
PB = sqrt((segStart(1)-testPoint(1))*(segStart(1)-testPoint(1))+(segStart(2)-testPoint(2))*(segStart(2)-testPoint(2)));
boolVal = abs(AB - (AP + PB)) < tolerance;
end
an approach that I found in one of the anwers here: Find if point lays on line segment. I hope that solves your problem.

Last plot in subplot becomes over-sized

I am using subplot function of MATLAB. Surprisingly the last plot in each subplot set becomes over-sized. Can anybody help me to resolve this issue? I have experimented with the parameters a little, but no luck. I am not able to post the plot figure.
function plotFluxVariabilityByGene(cRxn,KeggID,geneName)
load iJO1366; % Load the model iJO1366
%Find 'Gene' associated reactions from 'model'
reactions = rxnNamesFromKeggID(model,KeggID);
nCheck = 0; % Initialize counter
% Determine initial subplot dimensions
[R C setSize] = subplotSize(numel(reactions));
for n = 1 : numel(reactions)
% Get the name of nth reaction
rxn = reactions{n};
% Define the array for control reaction fluxes
cRxnArray = getCrxnArray(model,cRxn);
% Initialize storage for lower and upper limit-values
L = []; U = []; Avg = [];
% Get the fluxVariability values
for i = 1 : numel(cRxnArray)
modelMod = changeRxnBounds(model,cRxn,cRxnArray(i),'b');
[L(i) U(i)] = fluxVariability(modelMod,100,'max',{rxn});
Avg(i) = (L(i) + U(i))/2;
%fprintf('mthfcFlux = %f; Li = %f; Ui = %f\n',array(i),L(i),U(i));
end
% adjust the subplot number
nCheck = nCheck + 1;
% Determine the range of n to be saved in one file
if nCheck == 1
start = n;
elseif nCheck == setSize;
stop = n;
end
subplot(R,C,nCheck)
plot(cRxnArray,L,'-r','LineWidth',1); hold on;
plot(cRxnArray,L,'^r','MarkerSize',3,'LineWidth',2);
plot(cRxnArray,U,'-.b','LineWidth',1);
plot(cRxnArray,U,'^b','MarkerSize',2,'LineWidth',2);
plot(cRxnArray,Avg,'-','Color',[0.45,0.45,0.45],'LineWidth',2.5);
% Label X and Y axes
%xlabel([cRxn ' Flux']);
%ylabel(['fluxVariability ' char(rxn)]);
xlabel('Flux');
ylabel('fluxVariability');
hold off;
% Adjust X and Y axes limits
%xmn = min(cRxnArray) - ((max(cRxnArray) - min(cRxnArray))*0.05);
%xmx = max(cRxnArray) + ((max(cRxnArray) - min(cRxnArray))*0.05);
%ymn = min([U L]) - ((max([U L]) - min([U L]))*0.05);
%ymx = max([U L]) + ((max([U L]) - min([U L]))*0.05);
%if xmn ~= xmx
% xlim([xmn xmx]);
%end
%if ymn ~= ymx
% ylim([ymn ymx]);
%end
% Print which reactions are done
fprintf('\n......done for %s',char(rxn));
% If 'setSize' subplots are done then save the set in a file
if nCheck == setSize
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.fig']);
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.eps']); close(gcf);
% Determine initial subplot dimensions
[R C setSize] = subplotSize(numel(reactions)-n);
% Return nCheck to zero;
nCheck = 0;
end
end
% If nCheck is not equal to 16 then there are subplot that is not saved
% inside the for loop. Let's save it here.
if nCheck ~= setSize
stop = n;
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.fig']);
saveas(gcf,['TEST/' cRxn 'flux-Vs-' geneName '_fluxVariability' num2str(start) '-' num2str(stop) '.eps']); close(gcf);
end
fprintf('\nAll done\n');
end
%####################################################
%# Other functions ##
%####################################################
function rxnNames = rxnNamesFromKeggID(model,KeggID)
% Find 'Gene' associated reactions from 'model'
associatedRxns = findRxnsFromGenes(model,KeggID);
% Extract the reaction details from the structure to a cell
rxnDetails = eval(sprintf('associatedRxns.%s',KeggID));
% Extract only the reaction names from the cell
rxnNames = rxnDetails(:,1);
end
%####################################################
function cRxnArray = getCrxnArray(model,cRxn)
% Define the solver
changeCobraSolver('glpk');
% Find solution for the model
sol = optimizeCbModel(model);
% Change the objective of the default model to 'cRxn'
tmpModel = changeObjective(model,cRxn);
% Find slution for the changed model. This gives the maximum and
% minimum possible flux through the reaction 'cRxn' when the model is
% still viable
%solMax = optimizeCbModel(tmpModel,'max');
solMin = optimizeCbModel(tmpModel,'min');
% Create an array of 20 euqally spaced flux values between 'solMin' and
% 'sol.x'
%array = linspace(solMin.f,solMax.f,10);
cRxnArray = linspace(solMin.f,sol.x(findRxnIDs(model,cRxn)),20);
end
%####################################################
function [R C setSize] = subplotSize(remainingPlots)
% Sets number of columns and rows to 3 if total subplot >= 9
if remainingPlots > 7
R = 3; C = 3; setSize = 9;
elseif remainingPlots < 7
R = 2; C = 3; setSize = 6;
elseif remainingPlots < 5
R = 2; C = 2; setSize = 4;
elseif remainingPlots < 4
R = 1; C = 3; setSize = 3;
elseif remainingPlots < 3
R = 1; C = 2; setSize = 2;
end
end
%####################################################
My subplot looks like this:
I suspect its because you are calling subplotSize a second time inside your loop. This could be changing your R and C variables.
I would advise to check the R and C variables at the subplot command on each loop.

How can I optimize Clarke-Wright heuristic for TSP in Matlab?

I have implemented the Clarke-Wright huristic to solve TSP (based on the pseudo-code here). I have attached my implementation in Matlab. However it is not fast enough for me and takes O(n2) space (because of pairwise distances). I wonder if there is any theoretic or practical optimization I can apply to reduce the complexity (specially, space complexity).
It would be grateful if anyone can help me.
function [tour, length] = clarke_wright (data)
n=size(data,1); % number of records
center = mean(data,1); % mean of data
hubIdx = knnsearch(data,center,'k',1); % nearest record to center
distances = dist(data,data'); % this requires O(n^2) space :(
savings = zeros(n); % place to store the saving after adding an edge %
% Can be more vectorized? %
for i=1:n
if i==hubIdx
continue;
end
savings(i,(i+1):n)=distances(i,hubIdx)+distances(hubIdx,(i+1):n)-distances(i,(i+1):n);
end
minParent = 1:n;
[~,si] = sort(savings(:),'descend');
si=si(1:(end/2));
Vh = zeros(1,n);
Vh(hubIdx) = 1;
VhCount = n-1;
degrees = zeros(1,n);
selectedIdx = 1; % edge to try for insertion
tour = zeros(n,2);
curEdgeCount = 1;
while VhCount>2
i = mod(si(selectedIdx)-1,n)+1;
j = floor((si(selectedIdx)-1)/n)+1;
if Vh(i)==0 && Vh(j)==0 && (minParent(i)~=minParent(j)) && i~=j && i~=hubIdx && j~=hubIdx % always all degrees are <= 2, so it is not required to check them
% if (minParent(i)~=minParent(j)) && isempty(find(degrees>2, 1)) && i~=j && i~=hubIdx && j~=hubIdx && Vh(i)==0 && Vh(j)==0
degrees(i)=degrees(i)+1;
degrees(j)=degrees(j)+1;
tour(curEdgeCount,:) = [i,j];
if minParent(i)<minParent(j)
minParent(minParent==minParent(j))=minParent(i);
else
minParent(minParent==minParent(i))=minParent(j);
end
curEdgeCount = curEdgeCount + 1;
if degrees(i)==2
Vh(i) = 1;
VhCount = VhCount - 1;
end
if degrees(j)==2
Vh(j) = 1;
VhCount = VhCount - 1;
end
end
selectedIdx = selectedIdx + 1;
end
remain = find(Vh==0);
n1=remain(1);
n2=remain(2);
tour(curEdgeCount,:) = [hubIdx n1];
curEdgeCount = curEdgeCount + 1;
tour(curEdgeCount,:) = [hubIdx n2];
tour = stitchTour(tour);
tour=tour(:,1)';
length=distances(tour(end),tour(1));
for i=1:n-1 % how can I vectorize these lines?
length=length+distances(tour(i),tour(i+1));
end
end
function tour = stitchTour(t) % uniforms the tour [a b; b c; c d; d e;.... ]
n=size(t,1);
[~,nIdx] = sort(t(:,1));
t=t(nIdx,:);
tour(1,:) = t(1,:);
t(1,:) = -t(1,:);
lastNodeIdx = tour(1,2);
for i=2:n
nextEdgeIdx = find(t(:,1)==lastNodeIdx,1);
if ~isempty(nextEdgeIdx)
tour(i,:) = t(nextEdgeIdx,:);
t(nextEdgeIdx,:)=-t(nextEdgeIdx,:);
else
nextEdgeIdx = find(t(:,2)==lastNodeIdx,1);
tour(i,:) = t(nextEdgeIdx,[2 1]);
t(nextEdgeIdx,:)=-t(nextEdgeIdx,:);
end
lastNodeIdx = tour(i,2);
end
end
This is what you can do if space is an issue (will probably reduce calculation speed a bit).
I have not really looked into your code, but judging from the pseudo code this should do the trick:
For each pair or points, calculate the savings created by connecting them.
If this is better than the best savings found so far, update the best savings, and remember the two points.
After checking all pairs just implement the best savings.
This way you will barely require extra space at all.