You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
App designer - deleting an unnamed plot
1 view (last 30 days)
Show older comments
Hi folks,
I have the following code for generating 1 or multiple plots on an image.
function ROI(app, index1, index2)
hold (app.Image, "on")
plot(app.Image, index1, index2, app.innerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
plot(app.Image, index1, index2, app.outerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
end
My question is, suppose there are 3 such plots. Is there a way to delete 1 and only 1 of them selectively?
Thanks
Accepted Answer
Cris LaPierre
on 10 Apr 2021
If you capture the chart line object for each plot, you could use that with the delete function to remove just that line from the plot.
btw, it's best practice to always pair hold on with a corresponding hold off.
Here's a simple example.
% Create a plot with 3 lines
a=plot(rand(1,5));
hold on
b=plot(rand(1,5));
c=plot(rand(1,5));
hold off
% Now delete one of the lines using the line object
delete(b)
16 Comments
Teshan Rezel
on 11 Apr 2021
thanks @Cris LaPierre, but I can't really name them since the position and number of plots is dependant on a user input. so to name each plot proceduraly is not somethig I'm keen to do as it may slow down the app considerably.
Cris LaPierre
on 11 Apr 2021
I don't think it will slow it down, but I can understand your concern.
Another way to approach this is to use findobj to collect all the line objects in a plot, and then using delete to remove a specific line object. It may be a little harder to ensure you are removing the intended line.
% Create a plot with 3 lines
plot(rand(1,5));
hold on
plot(rand(1,5));
plot(rand(1,5));
hold off
% Now delete one of the lines using the line object
h = findobj('Type','line')
h =
3×1 Line array:
Line
Line
Line
delete(h(2))
Teshan Rezel
on 16 Apr 2021
hi @Cris LaPierre, I've tried doing this on app designer but it isn't deleting the plot. Any ideas why it isn't working please?
function ButtonPushed(app, index)
app.Counts(end) = 0;
app.Percentages(end) = 0;
app.Counts(index) = app.Counts(index) + 1;
app.Counts(end) = sum(app.Counts, 1:7);
for i = 1 : 7
app.Percentages(i) = (app.Counts(i) / app.Counts(end)) * 100;
end
app.Percentages(end) = sum(app.Percentages, 1:7);
app.CokeTable.Data = [app.Counts, app.Percentages];
app.tallyOrder(end+1) = index;
app.numManualTally = app.numManualTally + 1;
if app.numManualTally >= app.numSamplesPerImage
app.imageNumber = app.imageNumber + 1;
app.numManualTally = 0;
DeleteCrosshairs(app);
end
end
function DeleteCrosshairs(app)
f = findobj(app.Image, 'Type', 'line');
delete(f(end));
delete(f(end-1));
end
Cris LaPierre
on 16 Apr 2021
Edited: Cris LaPierre
on 16 Apr 2021
Is ButtonPushed supposed to have something to do with adding or removing a line plot from you image? It doesn't appear to be relevant.
I mocked up a simple example that plotted some lines on top of an image in app designer. The code in your DeleteCrosshairs succesfully removed 2 lines from the axes.
Teshan Rezel
on 18 Apr 2021
@Cris LaPierre apologies, I think I've not included the relevant functions! Here's the complete list!
methods (Access = private)
function ButtonPushed(app, index)
app.Counts(end) = 0;
app.Percentages(end) = 0;
app.Counts(index) = app.Counts(index) + 1;
app.Counts(end) = sum(app.Counts, 1:7);
for i = 1 : 7
app.Percentages(i) = (app.Counts(i) / app.Counts(end)) * 100;
end
app.Percentages(end) = sum(app.Percentages, 1:7);
app.CokeTable.Data = [app.Counts, app.Percentages];
app.tallyOrder(end+1) = index;
app.numManualTally = app.numManualTally + 1;
TallyCheck(app);
end
function ReverseButtonPushed(app, index)
app.Counts(end) = 0;
app.Percentages(end) = 0;
app.Counts(index) = app.Counts(index) - 1;
app.Counts(end) = sum(app.Counts, 1:7);
for i = 1 : 7
app.Percentages(i) = (app.Counts(i) / app.Counts(end)) * 100;
end
app.Percentages(end) = sum(app.Percentages, 1:7);
app.CokeTable.Data = [app.Counts, app.Percentages];
app.numManualTally = app.numManualTally - 1;
TallyCheck(app);
end
function ROI(app, index1, index2)
hold (app.Image, "on")
plot(app.Image, index1, index2, app.innerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
plot(app.Image, index1, index2, app.outerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
hold(app.Image, "off")
end
function DisplayCrosshairs(app)
I = imshow(app.img, "Parent", app.Image);
app.Image.XLim = [0 I.XData(2)];
app.Image.YLim = [0 I.YData(2)];
app.Width = app.Image.XLim;
app.Height = app.Image.YLim;
quarterHeight = range(app.Height)*0.125;
halfHeight = range(app.Height)*0.5;
threeQuarterHeight = range(app.Height)*0.875;
quarterWidth = range(app.Width)*0.125;
halfWidth = range(app.Width)*0.5;
threeQuarterWidth = range(app.Width)*0.875;
app.positionVector = {quarterWidth quarterHeight;halfWidth quarterHeight;threeQuarterWidth quarterHeight;quarterWidth halfHeight;halfWidth halfHeight;threeQuarterWidth halfHeight;quarterWidth threeQuarterHeight;halfWidth threeQuarterHeight;threeQuarterWidth threeQuarterHeight};
app.checkMatrix = [app.TopLeft.Value app.TopMiddle.Value app.TopRight.Value app.CentreLeft.Value app.CentreMiddle.Value app.CentreRight.Value app.BottomLeft.Value app.BottomMiddle.Value app.BottomRight.Value];
count = 0;
for i = 1 : 9
if app.checkMatrix(i) == 1
ROI(app, app.positionVector{i,1:2});
count = count + 1;
end
end
if count == 0
msgbox('Please select a quadrant for the crosshair to be displayed in');
end
end
function ResinThreshold(app)
imgGrey = rgb2gray(app.img);
[counts, ~] = imhist(imgGrey, 255);
T = otsuthresh(counts);
BW = imbinarize(imgGrey, T);
BW = bwareaopen(BW, app.AreaOpen.Value);
BW = imfill(BW, 'holes');
BW = bwperim(BW);
BW = imdilate(BW, ones(app.DilationMatrixDimensions.Value));
BW = imerode(BW, ones(app.ErosionMatrixDimensions.Value));
BW = imfill(BW, 'holes');
app.img = app.img.*repmat(uint8(BW),[1 1 3]);
end
function DisplayImage(app)
app.currentImage = fullfile(app.imageFolder(app.imageNumber).folder, app.imageFolder(app.imageNumber).name);
app.Image.Position = [0 0 app.UIFigure.Position(3:4)];
app.img = imread(app.currentImage);
if app.ThresholdResin.Value == 1
ResinThreshold(app);
end
DisplayCrosshairs(app);
app.ImageNumber.Value = app.imageNumber;
app.TotalNumber.Value = app.fileNumber;
app.numSamplesPerImage = sum(app.checkMatrix, 1:9);
end
function TallyCheck(app)
if app.numManualTally >= app.numSamplesPerImage
app.imageNumber = app.imageNumber + 1;
app.numManualTally = 0;
elseif app.numManualTally <= 0
app.imageNumber = app.imageNumber - 1;
app.numManualTally = app.numSamplesPerImage;
end
end
end
Cris LaPierre
on 19 Apr 2021
Still missing something. This code never even attempts to delete an object from your plot.
If you code is the combination of your two previous replies, then you you have two functions names ButtonPushed. They do different things, so perhaps you have a naming conflict?
Are you gettting any error messages? If so, share the entire message (all the red text).
Teshan Rezel
on 19 Apr 2021
Hey @Cris LaPierre, I think it's best if I attach the file as it saves some confusion...I don't think I'm explaining it well!
The way the app works is it will prompt you to select a folder with jpeg images on startup. Once selected, you can push each of the buttons on the left of the table to move to the next image. The number of times you need to click the buttons to move will depend on the number of crosshairs drawn, which can be varied by selecting the checkboxes in the "crosshair position" part of the "crosshair" tab.
Basically, I'm looking to delete a crosshair once a tally has been made. In other words, each time a button is pushed, a crosshair gets deleted.
Hope this is clear and I haven't missed anything out!
Cris LaPierre
on 19 Apr 2021
I've added the delete function you shared before to the app you shared previously. It is attached. I was able to confirm it deletes the crosshairs, but I'm definitely not comfortable navigating the app. Still, this should get your started.
Cris LaPierre
on 19 Apr 2021
I don't think so. Take some screenshots, please.
Teshan Rezel
on 19 Apr 2021
hi @Cris LaPierre, below is an image of when the top left plot should have been removed, but isn't. I'm not seeing any error messages!
Cris LaPierre
on 19 Apr 2021
It removes the last crosshair added. However, pressing on a button also advances to the next image. If you had a way to go back to the previous image, you would see the crosshair removed.
Comment out the DisplayImage(app); in the corresponding callback function to prevent the images from advancing.
Teshan Rezel
on 19 Apr 2021
Hi @Cris LaPierre, thanks. This appear to work for only one crosshair. However, for more than one crosshair per image, the app will now not progress to the next image once the requisite number of tallies has been made...
Cris LaPierre
on 19 Apr 2021
You have the code, and I've shown you it works for a single crosshair. Now you can adapt that into your app to obtain the behavior you want.
You may need to think through your design and logic to accomplish that. Right now the confusion was because you are removing a crosshair from the visible image, but then the same code immediately advances to the next image, where all crosshairs are shown again, making it appear like the crosshair was not removed.
Teshan Rezel
on 19 Apr 2021
hi @Cris LaPierre, sorry about this...I was just being very stupid...well, more than usual! This has been a tremendous help, thank you!
Cris LaPierre
on 19 Apr 2021
No need to apologize. This is no beginner app!
More Answers (0)
See Also
Categories
Find more on Line Plots in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)