1
$\begingroup$

Along the lines of a couple previous posts, I coded this function to show you where in your notebook your biggest space-wasters are. Useful for when your file is becoming huge and unmanageable for hunting down the graphics/big tables/whatever.

ClearAll[memShame];

memShame[nb_:EvaluationNotebook[],originalPos_:EvaluationCell[],OptionsPattern[{"Timeout"->30}]]:=DynamicModule[
{bcs={},maxPos,indices,index,nCells=Length@Cells@nb,pal},
indices=RandomSample@Range@nCells;

CheckAbort[TimeConstrained[
PrintTemporary[Dynamic[Refresh[
Column[{OutputForm@Row[{Length@bcs," of ",nCells}],
ProgressIndicator[N[(Length@bcs+1)/nCells]]}],
TrackedSymbols:>{},UpdateInterval->1]]];
Do[AppendTo[bcs,{ByteCount@NotebookRead@(Cells[nb][[index]]),Cells[nb][[index]]}],{index,indices}]
,OptionValue["Timeout"]],Null;];

maxPos=First@FirstPosition[First/@bcs,Max[First/@bcs]];
SelectionMove[First@Cells@nb,Next,Cell,maxPos-1];
CreateWindow[pal=PaletteNotebook[{OutputForm@Row[{"Checked ",Length@bcs," out of ",nCells," cells."}],
Grid[({PercentForm[#[[1]]/N@Total[First/@bcs],3],OutputForm@Row[{Round[#[[1]]/10^6.,0.01]," MB"}],#[[2]]}&)
/@(SortBy[bcs,-First[#]&][[;;UpTo[15]]]),Alignment->Right,gd]
,DefaultButton["Done",(NotebookClose[pal];SelectionMove[originalPos,All,Cell];DialogReturn[];)]}]
,WindowTitle->"Biggest bads",WindowSize->All];
]

Main question: As it is now, this seems to work just fine, but I need to call

memShame[EvaluationNotebook[],EvaluationCell[]] instead of just memShame[], unless this code is in the same notebook. I'm sure this is because those arguments don't get evaluated until it gets to my auxiliary notebook, which is where I'd like to hold this code.

Is there some way to refer to the calling / visible / otherwise-active Notebook/Cell that will do what I want? Or some way to have the defaults evaluated sooner, when those default arguments would be accurate?

(Bonus question: This routine seems to work well, but is pretty godawful slow, taking several minutes to get through a ~50MB file with 2500 cells. Is there anything stupid I'm doing which is causing a bottleneck, i.e. something I could easily change for a speedup, or would that be a more involved job?)


For future reference, fixed code below:

ClearAll[memShame];
SetAttributes[memShame,HoldAll];
memShame[nb_:EvaluationNotebook[],originalPos_:EvaluationCell[],OptionsPattern[{"Timeout"->30}]]:=DynamicModule[{bcs={},originalPosEval=originalPos,maxPos,indices,index,nCells=Length@Cells@nb,pal},
indices=RandomSample@Range@nCells;
CheckAbort[
TimeConstrained[
PrintTemporary[Dynamic[Refresh[Column[{OutputForm@Row[{Length@bcs," of ",nCells}],ProgressIndicator[N[(Length@bcs+1)/nCells]]}],TrackedSymbols:>{},UpdateInterval->1]]];
Do[AppendTo[bcs,{ByteCount@NotebookRead@(Cells[nb][[index]]),Cells[nb][[index]]}],{index,indices}],OptionValue["Timeout"]],Null;];
maxPos=First@FirstPosition[First/@bcs,Max[First/@bcs]];
SelectionMove[First@Cells@nb,Next,Cell,maxPos-1];
CreateWindow[pal=PaletteNotebook[{OutputForm@Row[{"Checked ",Length@bcs," out of ",nCells," cells."}],
Grid[
({PercentForm[#[[1]]/N@Total[First/@bcs],3],OutputForm@Row[{Round[#[[1]]/10^6.,0.01]," MB"}],#[[2]]}&)
/@(SortBy[bcs,-First[#]&][[;;UpTo[15]]])
,Alignment->Right,gd]
,DefaultButton["Done",(NotebookClose[pal];SelectionMove[originalPosEval,All,Cell];DialogReturn[];)]}],WindowTitle->"Biggest bads",WindowSize->All];
]
$\endgroup$
2
  • 1
    $\begingroup$ As for your bonus question: In my experience, working with notebooks via the front-end is extremely slow and unreliable, and should be avoided if possible. I would suggest you read the entire notebook in one go using NotebookGet. Then you can apply do something like Cases[notebookExpression, c:Cell[___,CellID->id_,___]:>{id,ByteCount[c]},All] to get the byte count of all cells with a CellID (which you can then use to find the cell in the actual notebook). You can also just look for all cells, but then identifying them will be a bit trickier, and all "normal" cells will have a CellID. $\endgroup$
    – Lukas Lang
    Jan 9, 2023 at 8:45
  • $\begingroup$ Related: Notebook cells space on disk profiler $\endgroup$ Jan 9, 2023 at 15:22

1 Answer 1

1
$\begingroup$

The issue is that the default values EvaluationNotebook[] and EvaluationCell[] are evaluated when the function is defined, not when it is called. The easiest solution is to wrap the left side of your function definition in HoldPattern (or at least the parts with the defaults)

Consider these three definitions made in one notebook:

f[x_ : EvaluationNotebook[]] := x
HoldPattern@g[x_ : EvaluationNotebook[]] := x
h[HoldPattern[x_ : EvaluationNotebook[]]] := x

Now, in another notebook:

EvaluationNotebook[]
f[]
g[]
h[]
(* NotebookObject["Untitled-2"] *)
(* NotebookObject["Untitled-1"] *)
(* NotebookObject["Untitled-2"] *)
(* NotebookObject["Untitled-2"] *)

As you can see, both g and h properly delay the evaluation of EvaluationNotebook[] to the point where the functions are called.

$\endgroup$
2
  • $\begingroup$ Thanks, that's 90% of exactly what I needed. Now I'm stuck on that last 10%: SelectionMove[originalPos,All,Cell], working as intended, returns the scrolling to where you executed memShame from. Using HoldPatterns (or SetAttribute[memShame,HoldAll]) both seem to work great for passing through the values I wanted, but now that one line to return to the original notebook and view is being uncooperative. I tried adding SetSelectedNotebook[nb]; before it, I tried returning them from the function, and I tried various other combinations of Hold/Release, but I've got nothing. Any more tips? $\endgroup$
    – Trev
    Jan 9, 2023 at 9:28
  • 1
    $\begingroup$ @Trev Now, EvalutionCell[] will be evaluated too late in the process. Specifically, it will be evaluated inside the button, which is of course too late. The easiest is to add something like originalPosEvaluated=originalPos to the DynamicModule variables, and then to use that in the SelectionMove command $\endgroup$
    – Lukas Lang
    Jan 9, 2023 at 10:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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