{"id":2248,"date":"2017-05-08T02:00:14","date_gmt":"2017-05-08T07:00:14","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=2248"},"modified":"2017-05-09T04:30:28","modified_gmt":"2017-05-09T09:30:28","slug":"stop-if","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2017\/05\/08\/stop-if\/","title":{"rendered":"Stop If"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p><i>Today's guest post comes from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495\">Sean de Wolski<\/a>, one of my fellow Application Engineers.  You might recognize him from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/\">MATLAB answers<\/a> and the <a href=\"https:\/\/blogs.mathworks.com\/pick\/\">pick of the week<\/a> blog!<\/i><\/p><p>Have you ever wanted MATLAB to pause in debug mode when a certain condition is met?  Perhaps when a specific problem-file out of a directory is read or on an iteration of a <tt>for<\/tt>-loop that yields an unexpected result? Perhaps that <tt>for<\/tt>-loop has to iterate a few dozen or hundred times before the problem iteration occurs and you don't want to walk through step by step in debug mode?<\/p><p>In this post, we're going to survey a few different ways to handle this.<\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#ec62e039-1fdd-4866-a681-806c7c32e6d0\">Keyboard<\/a><\/li><li><a href=\"#39b3267b-dada-44b8-89c0-e0cb315633f0\">DBSTOP ...<\/a><\/li><li><a href=\"#4996be2d-07bf-4f3d-80ad-8bfb8b55ab92\">Testing and Clean Up<\/a><\/li><li><a href=\"#4a4a8a10-1e5d-4951-b84e-b57f2c32c704\">Bonus<\/a><\/li><li><a href=\"#d8bb6987-c8bf-4bbd-92b2-a50c163d63fb\">Comments<\/a><\/li><\/ul><\/div><h4>Keyboard<a name=\"ec62e039-1fdd-4866-a681-806c7c32e6d0\"><\/a><\/h4><p>I was talking with a MATLAB user recently about the merits of the <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/keyboard.html\"><tt>keyboard<\/tt><\/a> function of which I'm not a big fan.  Keyboard pulls you into debug mode as soon as it's encountered.  They claimed to like it for difficult debugging when certain criteria are met.<\/p><p>Here's a simple example scenario.  CM is the cameraman image:<\/p><pre class=\"codeinput\">imshow(CM)\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2017\/cameraman.png\" alt=\"\"> <\/p><p>This is a simple algorithm to show how many pixels are brighter than each pixel value in the <i>uint8<\/i> range of <tt>[0 255]<\/tt>.<\/p><pre class=\"codeinput\">xg = zeros(1, 256);\r\n<span class=\"keyword\">for<\/span> ii = 0:255\r\n    xg(ii+1) = sum(CM(:)&gt;ii);\r\n<span class=\"keyword\">end<\/span>\r\n\r\nplot(0:255, xg)\r\nylabel(<span class=\"string\">'Pixels Greater Than X'<\/span>)\r\naxis <span class=\"string\">tight<\/span>\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2017\/pixplot.png\" alt=\"\"> <\/p><p>Somewhere around iteration 125 appears to be giving me problems; I'd expect the curve to be positive through to 255.<\/p><p>I want to see what's happening on iteration 125 and the subsequent ones. One way would be to put a break point on the calculation line, hit run, and then hit the continue button 125 times hoping I don't get in a rhythm and accidentally skip it.  This has some obvious shortcomings in that it doesn't scale and is time consuming.<\/p><p>The approach with <tt>keyboard<\/tt> would look like this:<\/p><pre class=\"codeinput\">xg = zeros(1, 256);\r\n<span class=\"keyword\">for<\/span> ii = 0:255\r\n    <span class=\"keyword\">if<\/span> ii == 125\r\n        keyboard\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2017\/keyboard.png\" alt=\"\"> <\/p><p>Now on the 125th iteration, we enter the if-statement and can step in debug mode into the problem area.  This is pretty straight-forward and is a safe, decent solution.  However, it requires changing the code in order to debug it and will require changing it again once we've fixed the bug.<\/p><h4>DBSTOP ...<a name=\"39b3267b-dada-44b8-89c0-e0cb315633f0\"><\/a><\/h4><p>What if we could just stop if?  Well you can! <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/dbstop.html\"><tt>dbstop<\/tt><\/a>, the function underlying breakpoints, supports a wide range of <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/matlab_prog\/set-breakpoints.html\">conditional breakpoints<\/a>.<\/p><p>These breakpoints can be set from the breakpoints menu on the editor tab or with <tt>dbstop<\/tt> directly.  Here's the same code encapsulated in a function called <tt>badForLoop<\/tt>.<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">function<\/span> badForLoop(CM)\r\nxg = zeros(1, 256);\r\n<span class=\"keyword\">for<\/span> ii = 0:255\r\n    xg(ii+1) = sum(CM(:)&gt;ii); \r\n<span class=\"keyword\">end<\/span>\r\n\r\nplot(0:255, xg)\r\nylabel(<span class=\"string\">'Pixels Greater Than X'<\/span>)\r\naxis <span class=\"string\">tight<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><p>To set it from the breakpoints menu, select \"Set Condition\" while the cursor is on the line you'd like to stop on.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2017\/setconditionmenu.png\" alt=\"\"> <\/p><p>Then enter your condition; any valid MATLAB code will work here.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2017\/setcondition.png\" alt=\"\"> <\/p><p>To set the same breakpoint programmatically:<\/p><pre class=\"language-matlab\">dbstop <span class=\"string\">in<\/span> <span class=\"string\">badForLoop<\/span> <span class=\"string\">at<\/span> <span class=\"string\">4<\/span> <span class=\"string\">if<\/span> <span class=\"string\">(ii==125)<\/span>\r\n<\/pre><pre class=\"codeinput\">badForLoop(CM);\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2017\/stoppedatcondition.png\" alt=\"\"> <\/p><h4>Testing and Clean Up<a name=\"4996be2d-07bf-4f3d-80ad-8bfb8b55ab92\"><\/a><\/h4><p>If you think you have a fix, you can then disable the breakpoint without clearing it by either clicking on the yellow breakpoint itself (an X will appear over it indicating it's disabled).  If the problem is resolved, clicking the breakpoint again will clear it or you can reenable it by right clicking.  This can be done from the menu as well and clearing can be done with <tt>dbclear<\/tt>.<\/p><p>The analogous workflow with <tt>keyboard<\/tt> would be to highlight the selection and comment it out to \"disable\" and then delete to clear.<\/p><p>The fix for this toy problem was that the image was stored as an <i>int8<\/i> with a range <tt>[-128 127]<\/tt> rather than a <i>uint8<\/i> with range <tt>[0 255]<\/tt>.<\/p><h4>Bonus<a name=\"4a4a8a10-1e5d-4951-b84e-b57f2c32c704\"><\/a><\/h4><p>Additionally, <tt>dbstop<\/tt> has some predefined conditions to stop on including on errors, warnings, or if nans or infs are encountered.  If you haven't discovered <tt>dbstop if error<\/tt> yet, I strongly suggest giving it a try.  When an error occurs, it stops and you can view the state of the world as it was when the error occurred.<\/p><h4>Comments<a name=\"d8bb6987-c8bf-4bbd-92b2-a50c163d63fb\"><\/a><\/h4><p>Do you have any debugging war stories where one of these tricks could've helped?  What about other uses for the <tt>keyboard<\/tt> command?  Let us know <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=2248#respond\">here<\/a>.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_7d6c2fb5cf7e47ebbde8a666637d5300() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='7d6c2fb5cf7e47ebbde8a666637d5300 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 7d6c2fb5cf7e47ebbde8a666637d5300';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2017 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_7d6c2fb5cf7e47ebbde8a666637d5300()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2017a<br><\/p><\/div><!--\r\n7d6c2fb5cf7e47ebbde8a666637d5300 ##### SOURCE BEGIN #####\r\n%% Stop If\r\n% _Today's guest post comes from\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495 Sean de\r\n% Wolski>, one of my fellow Application Engineers.  You might\r\n% recognize him from <https:\/\/www.mathworks.com\/matlabcentral\/answers\/ MATLAB\r\n% answers> and the <https:\/\/blogs.mathworks.com\/pick\/ pick of the week>\r\n% blog!_\r\n%\r\n% Have you ever wanted to MATLAB to pause in debug mode when a certain\r\n% condition is met?  Perhaps when a specific problem-file out of a\r\n% directory is read or on an iteration of a |for|-loop that yields an\r\n% unexpected result? Perhaps that |for|-loop has to iterate a few dozen or\r\n% hundred times before the problem iteration occurs and you don't want to\r\n% walk through step by step in debug mode?\r\n%\r\n% In this post, we're going to survey a few different ways to handle this.\r\n%\r\n%% Keyboard\r\n%\r\n% I was talking with a MATLAB user recently about the merits of the\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/keyboard.html |keyboard|>\r\n% function of which I'm not a big fan.  Keyboard pulls you into debug mode\r\n% as soon as it's encountered.  They claimed to like it for difficult\r\n% debugging when certain criteria are met.\r\n%\r\n% Here's a simple example scenario.  CM is the cameraman image:\r\nimshow(CM) \r\n%%\r\n%\r\n% <<cameraman.png>>\r\n%%\r\n% This is a simple algorithm to show how many pixels are brighter than each\r\n% pixel value in the _uint8_ range of |[0 255]|.\r\nxg = zeros(1, 256);\r\nfor ii = 0:255\r\n    xg(ii+1) = sum(CM(:)>ii); \r\nend\r\n\r\nplot(0:255, xg)\r\nylabel('Pixels Greater Than X')\r\naxis tight\r\n%%\r\n%\r\n% <<pixplot.png>>\r\n\r\n%%\r\n% Somewhere around iteration 125 appears to be giving me problems; I'd\r\n% expect the curve to be positive through to 255.\r\n%\r\n% I want to see what's happening on iteration 125 and the subsequent ones.\r\n% One way would be to put a break point on the calculation line, hit run,\r\n% and then hit the continue button 125 times hoping I don't get in a rhythm\r\n% and accidentally skip it.  This has some obvious shortcomings in that it\r\n% doesn't scale and is time consuming.\r\n%\r\n% The approach with |keyboard| would look like this:\r\n\r\nxg = zeros(1, 256);\r\nfor ii = 0:255\r\n    if ii == 125\r\n        keyboard\r\n    end        \r\nend\r\n\r\n%%\r\n%\r\n% <<keyboard.png>>\r\n%%\r\n% Now on the 125th iteration, we enter the if-statement and can step in\r\n% debug mode into the problem area.  This is pretty straight-forward and is\r\n% a safe, decent solution.  However, it requires changing the code in order\r\n% to debug it and will require changing it again once we've fixed the bug.\r\n\r\n%% DBSTOP ...\r\n%\r\n% What if we could just stop if?  Well you can can!\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/dbstop.html |dbstop|>, the\r\n% function underlying breakpoints, supports a wide range of\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/matlab_prog\/set-breakpoints.html\r\n% conditional breakpoints>.\r\n%\r\n% These breakpoints can be set from the breakpoints menu on the editor tab\r\n% or with |dbstop| directly.  Here's the same code encapsulated in a\r\n% function called |badForLoop|.\r\n%\r\n% <include>badForLoop.m<\/include>\r\n%\r\n% To set it from the breakpoints menu, select \"Set Condition\"\r\n% while the cursor is on the line you'd like to stop on.  \r\n%\r\n% <<setconditionmenu.png>>\r\n%\r\n% Then enter your condition; any valid MATLAB code will work here.\r\n%\r\n% <<setcondition.png>>\r\n%\r\n% To set the same breakpoint programmatically:\r\n% \r\n%   dbstop in badForLoop at 4 if (ii==125)\r\n% \r\n\r\nbadForLoop(CM);\r\n\r\n%%\r\n%\r\n% <<stoppedatcondition.png>>\r\n\r\n\r\n%% Testing and Clean Up\r\n% If you think you have a fix, you can then disable the breakpoint without\r\n% clearing it by either clicking on the yellow breakpoint itself (an X will\r\n% appear over it indicating it's disabled).  If the problem is resolved,\r\n% clicking the breakpoint again will clear it or you can reenable it by\r\n% right clicking.  This can be done from the menu as well and clearing can\r\n% be done with |dbclear|.\r\n%\r\n% The analogous workflow with |keyboard| would be to highlight the selection\r\n% and comment it out to \"disable\" and then delete to clear.\r\n%\r\n% The fix for this toy problem was that the image was stored as an _int8_\r\n% with a range |[-128 127]| rather than a _uint8_ with range |[0 255]|.\r\n%\r\n\r\n\r\n%% Bonus\r\n%\r\n% Additionally, |dbstop| has some predefined conditions to stop on\r\n% including on errors, warnings, or if nans or infs are encountered.  If\r\n% you haven't discovered |dbstop if error| yet, I strongly suggest giving\r\n% it a try.  When an error occurs, it stops and you can view the state of\r\n% the world as it was when the error occurred.  \r\n\r\n%% Comments\r\n% Do you have any debugging war stories where one of these tricks could've\r\n% helped?  What about other uses for the |keyboard| command?  Let us know\r\n% <https:\/\/blogs.mathworks.com\/loren\/?p=2248#respond here>.\r\n\r\n##### SOURCE END ##### 7d6c2fb5cf7e47ebbde8a666637d5300\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2017\/stoppedatcondition.png\" onError=\"this.style.display ='none';\" \/><\/div><!--introduction--><p><i>Today's guest post comes from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495\">Sean de Wolski<\/a>, one of my fellow Application Engineers.  You might recognize him from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/\">MATLAB answers<\/a> and the <a href=\"https:\/\/blogs.mathworks.com\/pick\/\">pick of the week<\/a> blog!<\/i>... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2017\/05\/08\/stop-if\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[13],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/2248"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=2248"}],"version-history":[{"count":6,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/2248\/revisions"}],"predecessor-version":[{"id":2399,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/2248\/revisions\/2399"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=2248"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=2248"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=2248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}