9
$\begingroup$

There have been times when I want to find the structure of an object in order to extract some part of it. For example, extracting the x and y coordinates from a Graphics object generated by Plot. I start by using FullForm or InputForm, which works well if the object is small. If it's large I get its Dimensions and evaluate object[[1]], object[[2]], object[[2,1]], object[[2,2]], object[[2,2,1]], object[[2,2,2]] and so on until I find what I want. For the example above I eventually find that g[[1, 1, 3, 2, 1]] is the list of points.

I would like to automate this using Manipulate. So far I have tried:

InspectObject[o_] := Module[
{d = Dimensions[o], iter},
iter = MapIndexed[{Subscript[i, First[#2]], 1, #1, 1} &, d];
Manipulate[
o[[##]] & @@ Thread[Subscript[i, Range[Length[d]]]], ##] & @@ iter
]

which is supposed to create a slider that varies from 1 to d[[k]] for each dimension of the object. But the Manipulate indices are not being evaluated properly.

g=Plot[Sin[x], {x, -3, 3}];
InspectObject[g]

should be equivalent to:

Manipulate[g[[i]], {i, 1, 2, 1}]

It would be even cooler if I could inspect each part recursively and interactively specify a range for each level.

$\endgroup$
0

4 Answers 4

12
$\begingroup$

I use something similar to @Sjoerd's suggestion with OpenerView. Here is the essence:

ClearAll[Inspect]
Inspect[x_] := inspect2[x]

ClearAll[inspect2]
SetAttributes[inspect2, HoldAll]
inspect2[x:_[a__]] :=
  OpenerView @ {inspectView[x] // Framed, Dynamic @ Column[List @@ inspect2 /@ Hold[a]]}

inspect2[x_] := inspectView[x]

SetAttributes[inspectView, HoldAll]
inspectView[x_] :=
  Module[{v = Function[Null, Dynamic[Tooltip[x // # // HoldForm // Short[#, 1]&, #]], HoldAll]}
  , FlipView @ { v[InputForm], v[FullForm], v[StandardForm] }
  ]

Sample use:

screenshot showing <code>Inspect[g]</code>

It does not evaluate parts of held expressions:

screenshot showing inspection of held expression

An expression is normally shown in InputForm...

screenshot showing InputForm

... but clicking on it toggles to FullForm...

screenshot showing FullForm

... and clicking again shows StandardForm:

screenshot showing StandardForm

$\endgroup$
11
$\begingroup$

Try

OpenerView[{Head[#], args @@ #} ] & //@ g

enter image description here

[For this demonstration I opened a few of the OpenerView-s. There are many more to explore.]

$\endgroup$
4
$\begingroup$

Here is the simple method I use. I create a button (with label "[[?]]") that finds the position of the current selection in the last output. You can add the button to a custom utilities palette for easy access.

Button["\[LeftDoubleBracket]?\[RightDoubleBracket]", 
 Print@Position[%, ToExpression@CurrentValue@"SelectionData"]]

Here's how to use it to grab the points generated from your sine plot.

enter image description here

$\endgroup$
2
$\begingroup$

Here is my try using MapIndexed, Mouseover, and Tooltip. The idea is to highlight parts of an expression as the mouse is over it and to display at the same time the exact level indices corresponding to it.

Here is a simple example to understand the core idea :

myExpr = {{1, 2, {11, 22}}, {3, 4, {111, {222}}}};

and

level = 3; (* For example all parts at level 3 will be highlighted in red *)
MapIndexed[
(* When the mouse is over one of these part, this particular part will be also highlighted
 in yellow and its corresponding exact level part will be displayed in a tooltip
*)
 Mouseover[Style[#1, Red, Bold], 
   Tooltip[Style[#1, Red, Bold, Background -> Yellow], 
    Style[Rest@#2, Blue, 26]]] &, Style[myExpr, 30], {level + 1}]

enter image description here

(Important : This snapshot image does not show that the mouse pointer is actually over 111 when the tooltip {2,3,1} is displayed.)

Let's apply that into a Manipulate which will let you choose interactively the level part to highlight, and let's explore the OP's object.

g=Plot[Sin[x], {x, -3, 3}];

myObject = List @@ g;

depth = Depth@myObject;

Manipulate[
 MapIndexed[
  Mouseover[Style[#1, Red, Bold], 
    Tooltip[Style[#1, Red, Bold, Background -> Yellow], 
     Style[Rest@#2, Blue, 26]]] &, Style[myObject, fontsize], {level}],
{{fontsize, 15, Style["Font Size : ", 15]}, 8, 30, 1}, "", "", 
{{level, 2, Style["Level :  ", 25, Bold]}, 
Range[2, Depth@myObject] // Thread[Rule[#, Style[# - 1, 25] & /@ #]] &, 
ControlType -> SetterBar, BaselinePosition -> 0}, ContentSize -> {650, 400}]

enter image description here

(Once again : the snapshot image does not show that the mouse pointer is actually over the part highlighted in yellow when the tooltip {1,1,3,2,1} is displayed.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.