Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seeing truncated messages in Mathematica

Is it possible to see full version of a Message that got truncated? IE, I see something along the lines of 0.105309,0.394682,<<20>>,<<20>>,<<20>>,0.394631 in the Messages window. I'm guessing <<20>> represents omitted parts, how do I get the whole thing?

The function called is FindMaximum on a problem with 50 variables.

Update: Simon's answer seems to work for general messages, also I found an approach that's specific to capturing the FindMaximum "not a real number" message.

To get the point which causes FindMaximum to fail with "not a real number" message you can do the following (redefining Message is the only approach I could find because the point doesn't get passed to EvaluationMonitor or StepMonitor)

Unprotect[Message];
Message[FindMaximum::"nrnum", args___] := (captured = {args}; 
   Print["Captured FindMaximum::nrnum at ", First[{args}]]);
{badvals, badvars, badobj} = ReleaseHold[captured];
like image 556
Yaroslav Bulatov Avatar asked Nov 24 '10 08:11

Yaroslav Bulatov


3 Answers

I'm not sure if you can recover a long message that has already been generated. As $MessageList and Message[] only store the message names, not the arguments passed to them.

To stop Short[] from being automatically applied to messages you can Unset[$MessagePrePrint]. It's default value is Automatic -- whatever that entails.


Rather than print long messages all the time, it might be better to use something like

General::longmsg="A long message (`1`) was produced. The full message has been saved in `2`";
$MessagePrePrint=With[{bc=ByteCount[#]},If[bc>65536,
  With[{fn=FileNameJoin[{$HomeDirectory,StringJoin["MmaMsg",ToString/@DateList[]]}]},
    Put[#,fn];Message[General::longmsg,bc,Row[{fn}]];Short[Shallow[#],1]],
  #]]&;

This will print out the message as normal unless the ByteCount is too large ( > 65536) in which case it will print out two messages: The first informs you that a large message was produced and gives you the file where it was saved. The second is the truncated version of the full message.

like image 104
Simon Avatar answered Nov 15 '22 22:11

Simon


I'm not in front of the right computer right now, so I can't test it for sure... But I think you can fully customize the message handling behavior with something like:

Block[{Message = f}, ...]

For example you might use

f[args___] := Print[{args}];

Again, not in front of Mathematica right now. Please feel free to wiki edit this answer.

like image 39
Andrew Moylan Avatar answered Nov 15 '22 20:11

Andrew Moylan


Undocumented function Internal`HandlerBlock (uncovered by Maxim Rytin) is applicable here:

Off[FindMaximum::"nrnum"]
Internal`HandlerBlock[{"Message", Print}, 
 Message[FindMaximum::"nrnum", arg1, arg2, arg3]]
(* => Hold[Message[FindMaximum::nrnum,arg1,arg2,arg3],False]*)

Another handler type is "MessageTextFilter". "Message" is invoked for every generated message and passes one argument of the form Hold[..., ...] to the handler function, with the second element set to False for quieted messages. "MessageTextFilter" is invoked for messages that actually get printed and calls the function with three arguments.

Maxim Rytin


Another possibility is to modify $MessagePrePrint in such a way that it will print messages containing in-line cells with truncated arguments which can be expanded to full arguments on evaluation. It can be done with Interpretation:

truncatingRules = {lst : {x_, y__} /; 
     MatrixQ[lst, NumberQ] && Length[lst] > 3 :>
    {x /. v : {a_, b__} /; Length[v] > 3 :>
       {a, 
        Interpretation[Style[Skeleton[Length[{b}]], Gray], 
         Sequence @@ {b}]},
     Interpretation[Style[Skeleton[Length[{y}]], Gray], 
      Sequence @@ {y}]},
   lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 3 :>
    {x, Interpretation[Style[Skeleton[Length[{y}]], Gray], 
      Sequence @@ {y}]}};

InlineCellInsideMessage[expr_] := 
 Style[DisplayForm[
   Cell[BoxData[MakeBoxes[expr, StandardForm]], "Input"]], 
  FontWeight -> Bold, FontFamily -> "Courier", Background -> Yellow, 
  FontColor -> Red, FontSize -> 12, StripOnInput -> True, 
  AutoNumberFormatting -> True, ShowStringCharacters -> True]

$MessagePrePrint = 
 Function[expr, 
  If[TrueQ[ByteCount[Unevaluated[expr]] < $OutputSizeLimit/20.], 
   InlineCellInsideMessage[expr],
   InlineCellInsideMessage[expr /. truncatingRules]
   ]]

Of course, the above version of $MessagePrePrint is just a draft but it illustrates the main idea.

like image 34
Alexey Popkov Avatar answered Nov 15 '22 22:11

Alexey Popkov