MathGroup Archive 2006

[Date Index] [Thread Index] [Author Index]

Search the Archive

Intercepting and Controlling Mathematica Exceptions.

  • To: mathgroup at smc.vnet.net
  • Subject: [mg71889] Intercepting and Controlling Mathematica Exceptions.
  • From: "Philipp" <Philipp.M.O at gmail.com>
  • Date: Sat, 2 Dec 2006 05:11:23 -0500 (EST)

Dear All,

The following code was inspired by, or based upon:

1. the $AbortMessage trap concept by Omega Consulting Group
   (omegaconsultinggroup.com) originally published as "Aborting
    Messages" in "In and Out" section of The Mathematica Journal, 9.4,

2. private communication with Dale from Omega Consulting Group
   (omegaconsultinggroup.com),

3. a posting by Carl Woll from Wolfram Research

(http://groups.google.co.uk/group/comp.soft-sys.math.mathematica/browse_frm/thread/b4b92edd3116863b/361984f703ef6306?lnk=gst&q=%24AbortMessage&rnum=1#361984f703ef6306).

The described below MessagesAbort[] mechanism is extremely useful,
especially in situations where repetitive, though time consuming
calculation are performed.

I face such situation frequently. I receive updated daily, third party
stock market data stored in binary files that I search for
interesting patterns (the data, not the files).

The file translation functions (to a Mathematica "native" format),
which are a part of a package I'd written in Mathematica, contain
extensive data integrity checks that generate custom & inbuilt Messages
that I interpret either as warnings or as aborting errors.

The number of files varies from ~400 to ~1600 and the processing takes
at the maximum about 60 minutes, which makes the MessagesAbort[]
mechanism indispensable.

Although before I commit it to MathSource, I would like to publish it
here so anybody interested can test it & bring out THE RESULTING BUGS.

================================================
The MessagesAbort[] Code begins at the next line

Begin["System`"]

(******** MessagesAbort (Message OVERLOAD) ********)

MessagesAbort::usage = "\[FilledSmallSquare]
On[MessagesAbort[symbol::\"tag\", ...]] and Off[AbortMessage[]] extend
the Mathematica exception handling capacity.

\n\[FilledSmallSquare] On[MessagesAbort[]] transparently sets the
environment that any Message[symbol::\"tag\"] generated (printed) by
Mathematica aborts calculations immediately.

\n\[FilledSmallSquare] On[AbortMessages[symbol::\"tag\", ...]] sets the
environment to
abort immediately but only after any of the symbol::\"tag\", ...
messages is generated.

\n\[FilledSmallSquare] Off[AbortMessage[]] restores the exception
handling capacity to the Mathematica default.

\n\[FilledSmallSquare] On[symbol::\"tag\", ...] and
Off[symbol::\"tag\", ...] take precedence over
On[MessagesAbort[symbol:: \"tag\", ...]], i.e.,\n\t(Off[s::t];
On[MessagesAbort[s::t]]) will neither generate the Message[s::t] nor
abort the calculations."

On[MessagesAbort[msgNames___MessageName]] ^:= \
   (Unprotect[Message, $MessagesAbortQ];
    $MessagesAbortQ = False;
    Message[args___] := (Check[Block[{$MessagesAbortQ = False},
Message[args]], Abort[], msgNames]) /; $MessagesAbortQ;
    $MessagesAbortQ = True;
   Protect[Message, $MessagesAbortQ];);

Off[MessagesAbort[]] ^:= \
   (Unprotect[Message, $MessagesAbortQ];
    $MessagesAbortQ = False;
    Clear[Message];
   Protect[Message, $MessagesAbortQ];);

SetAttributes[MessagesAbort, HoldAll];

End[(* System` *)]

The MessagesAbort[] Code ends at the previous line.
===================================================

The MessagesAbort code addresses the problem of intercepting and
controlling Mathematica exceptions that generate Messages.

The general problem is defined as follows. Suppose that there are
several statements executed as a compound statement, say

(s1; s2; s3; ...)

Each of the sk statements can generate an error Message and it is
ESSENTIAL that the execution stops after some specific Message is
generated.

For example, with the default error handlers, the whole compound
statement will be executed,

In[1]:=  (Log[1, 1]; Prime[-12]; StringLength[ToString[N[Pi, 10^5]]])

         Divide::"indet" : Indeterminate expression 0/0 encountered.

         Prime::"intpp" : Positive integer argument expected in
                           Prime[-12].

Out[1]:= 100001

Wrapping it in Check doesn't help;

In[1]:=  Check[(Log[1, 1]; Prime[-12];
           Print[StringLength[ToString[N[Pi, 10^5]]]]), Abort[]]

         Divide::"indet" : Indeterminate expression 0/0 encountered.

         Prime::"intpp" : Positive integer argument expected in
                           Prime[-12].

         100001

Out[1]:= $Aborted

i.e., the Abort is issued only AFTER the last statement is evaluated.


The MessagesAbort function sets up a mechanism to overload the Message
function.

Executing,

In[]:=   On[MessagesAbort[Divide::"indet", Prime::"intpp"]]

will result in the following overload of the Message function,

In[]:=   Information["Message"]

         Message[args___] :=
          Check[Block[{$MessagesAbortQ = False},Message[args]],
              Abort[], Divide::indet, Prime::intpp] /; $MessagesAbortQ

with $MessagesAbortQ set to True, i.e.,

In[]:=   $MessagesAbortQ
Out[]=   True

The mechanism of action is rather straightforward.

1. Any Message generated will be intercepted by the above overload
   since the $MessagesAbortQ is True.

2. If the intercepted MessageName[symbol, tag] (symbol::tag) is
   Divide::"indet" or Prime::"intpp" the expr of

     Check[expr, failexpr, Divide::"indet", Prime::"intpp"]

   (i.e., the Block statement) will successfully generate the Message
   again, but this time using the ORIGINAL Message definition (since
   $MessagesAbortQ is set to False within the scope of the Block),

3. Successful generation/printing of the Message in 2. is considered a
   failure from the point of view of the Check statement, thus failexpr
   (i.e., Abort[]) will be executed and any outstanding computations
   will terminate immediately ("as soon as possible").


Now,

In[1]:=  On[MessagesAbort[Divide::"indet"]]

         (Log[1, 1]; Prime[-12]; StringLength[ToString[N[Pi, 10^5]]])

         Divide::"indet" : Indeterminate expression 0/0 encountered.

Out[1]:= $Aborted

and,

In[1]:=  On[MessagesAbort[Prime::"intpp"]]

         (Log[1, 1]; Prime[-12]; StringLength[ToString[N[Pi, 10^5]]])

         Divide::"indet" : Indeterminate expression 0/0 encountered.

         Prime::"intpp" : Positive integer argument expected in
                           Prime[-12].

Out[1]:= $Aborted

and, of course,

In[1]:=  On[MessagesAbort[]]

         (Log[1, 1]; Prime[-12]; StringLength[ToString[N[Pi, 10^5]]])

         Divide::"indet" : Indeterminate expression 0/0 encountered.

Out[1]:= $Aborted


I suggest that MessagesAbort[] Code is put initially in the Kernel
init.m file in
(...\Wolfram Research\Mathematica\5.2\Configuration\Kernel) directory.

Please feel free to comment on the code, suggest improvements and
point out any faults. Treat it as harshly as possible, and please
report the bugs.

Cheers,

Philipp.


  • Prev by Date: Re: RE: RE: Functional decomposition (solving f[f[x]] = g[x] for given g)
  • Next by Date: calculation speed
  • Previous by thread: Re: A serious error?
  • Next by thread: calculation speed