# Interactively inspecting parts of an object

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.

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:

It does not evaluate parts of held expressions:

An expression is normally shown in InputForm...

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

... and clicking again shows StandardForm:

Try

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


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

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.

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}]


(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}]


(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.)