Skip to main content

debugging - Automatically add debug contents to a program


Sometimes I'll use Print[1] or Print[n] to debug in a long loop, but it's really a boring job to add these sentence by sentence and removing them sentence by sentence. (It's already boring to read this first three lines sentence by sentence so you can imagine how boring it is to add these stuff sentence by sentence. :P) So my question is how to throw this job to a program?


Let's take this small (and stupid) program as an example:


Do[j=i^2;Thread[{{1},{2,3}}],{i,3}]

I would like to add two Print in this program to determin where the problem occurs.


Do[Print@1;j=i^2;Print@2;Thread[{{1},{2,3}}],{i,3}]

In this way I can know that it's the second step that goes wrong.



Any idea how to do this automatically?



Answer



Yesterday I checked my account's question list again and find this question lying inside. After a year wrestling mostly with Hold stuffs, I think I finally found a, well, not that elegant solution. Any suggestions or new answers are surely welcomed!!!


It seems that this question is not that bad, actually I may say that It's quite hard for one to solve this problem using all sorts of evaluation manipulation techniques. and it has real applications sometimes.




As usual, my code first:


SetAttributes[adddebug, HoldFirst]
adddebug[orig_, func_: Echo, level_: {2}] :=
Module[{$count = 1, tempf},
Replace[

Replace[Hold[orig], HoldPattern[CompoundExpression[comp__]] :>
Block[{},
tempf @@
Riffle[List @@ (Hold /@ Hold[comp]),
With[{$func = func, q = #}, Hold@$func@q] & /@
Range[$count, ($count = $count + Length@Hold[comp] + 1) -
1], {2, -1, 2}] /; True],level],
tempf[seg__] :>
Block[{},
tempf[Hold[CompoundExpression]] @@ (tempf /@ {seg}) /; True],level] /. tempf[Hold[seg_]] :> seg

]

adddebug[Do[j = i^2; Thread[{{1}, {2, 3}}], {i, 3}]]

The result is satisfying



Hold[Do[j = i^2; Echo[1]; Thread[{{1}, {2, 3}}]; Echo[2], {i, 3}]]





Some additional notes:



Why I say this question is not that trivial is because I should protect CompoundExpression and its content from evaluating while still need to operate on CompoundExpression's structure and use in place evaluation techniques extensively.


So I install protection in the following ways:




  1. When pattern-matching, Use HoldPattern




  2. Use unique symbol tempf as a medium to mark Where CompoundExpression previoulsly existed. Use tempf[Hold[CompoundExpression]].





  3. make every element of CompoundExpression Hold at all times, and mark them using tempf[Hold[expr]]




  4. I'm quite satisfied by the last ReplaceAll's design, as previously I’ve already make where should be CompoundExpression tempf[Hold[CompoundExpression]] and where should be CompoundExpression's element tempf[Hold[element]], Now I can safely use ReplaceAll once to make those stuffs back to their original form!






I still am looking foward to a better solution, so if anyone has any idea, post something, Thanks!


Comments

Popular posts from this blog

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1.