11
$\begingroup$

I saved an InterpolationFunction in a ".mx" files using DumpSave on a variable that was scoped by a Module. Here is a stripped-down example:

Module[{interpolation},
   interpolation=Interpolation[Range[10]];
   DumpSave["interpolation.mx", interpolation];
]

Is there a way to find out the variable name, presumably of the form interpolation$nnn, of the expression when I Get the interpolation? It is not apparent what the variable is when using

<<"interpolation.mx"

Next time I will not use a Module for scoping the save variable, but meantime I'd like to access the saved data and assign it to a new variable.

$\endgroup$
6
  • 1
    $\begingroup$ Why don't you just use Export? When just dealing with data, I find it really annoying that DumpSave saves variable names. Export["interp.mx", Interpolation@Range[10]]. $\endgroup$
    – Szabolcs
    Mar 13, 2012 at 22:36
  • $\begingroup$ I would solve it using Block instead Module, besides it, the question is interesting, to see how to work with internal module variables. $\endgroup$
    – FJRA
    Mar 14, 2012 at 0:20
  • $\begingroup$ @szabolcs thanks for the tip. I'll use Export next time. Aside from the variable name, are the mx files equivalent? I.e. platform-specific? $\endgroup$
    – JxB
    Mar 14, 2012 at 2:18
  • $\begingroup$ @JxB yep, they're platform specific. Lately I use Export["file.mmaz", Compress[expression], "String"] and Uncompress@Import["file.mmaz", "String"] for good performance and platform independence. The disadvantage is relatively high memory use, and of course it is still slower than MX. If performance is not an issue (small expressions), just export/import to/from the WDX format. $\endgroup$
    – Szabolcs
    Mar 14, 2012 at 6:25
  • 1
    $\begingroup$ For the future you may wish to reference these save options I outlined. $\endgroup$
    – Mr.Wizard
    Mar 14, 2012 at 10:40

3 Answers 3

9
$\begingroup$

You can open the MX file in an ASCII editor. The variable name is there in plain text (interpolation$511 in my case). The rest is binary gibberish.

So given an MX file with a single variable with the $ suffix, the following expression can be used to access that variable directly:

getExpression[filename_] := Module[{a}, 
   ToExpression[(a = StringCases[Import[filename, "Text"], 
   WordCharacter ... ~~ "$" ~~ NumberString][[1]])];
   << (filename);
   ToExpression[a]
  ]

E.g.,

result = getExpression["interpolation.mx"]
  (* InterpolatingFunction[{{1,10}},<>] *)

Evaluating the variable name before reading it with Get (or <<) seemingly overcomes the Temporary attribute discussed in Leonid`s answer. As a (perhaps unwanted) side-effect of the above expression, the original variable remains defined.

This approach could probably be extended to work with multiple variables and expressions in one MX file.

$\endgroup$
4
  • $\begingroup$ So I could parse the first n bytes of the file, using ReadList say, to get the name. Nice to know. $\endgroup$
    – JxB
    Mar 14, 2012 at 2:21
  • $\begingroup$ I wonder if manually renaming the variable in a text editor (or with Mma) to remove the $nnn from the variable works, or breaks the file formatting. Will check into it. $\endgroup$
    – JxB
    Mar 14, 2012 at 2:23
  • $\begingroup$ Sjoerd, I added an expression for reassigning the variable directly from Mma. Hope you don't mind. $\endgroup$
    – JxB
    Mar 14, 2012 at 3:48
  • $\begingroup$ @JxB Of course not, it's a great addition. $\endgroup$ Mar 14, 2012 at 6:28
6
$\begingroup$

You seem to be out of luck (although I will be happy to be proven wrong). This is a rather subtle point, related to the Temporary attribute and garbage-collection. I will just share a few observations. First, note that after loading of .mx file on a fresh kernel, the variable is not found anywhere, it is not among the living:

<< "interpolation.mx"
names = Flatten[Names[# <> "*"] & /@ Contexts[]];
Flatten@StringCases[names, ___ ~~ "interpolation" ~~ ___]

{"Manipulate`Dump`interpolationToAnimation", 
   "Manipulate`Dump`interpolationToManipulate"}

Here is one way to make it persist:

Module[{interpolation},
  ClearAll[interpolation];
  interpolation = Interpolation[Range[10]];
  DumpSave["interpolation.mx", interpolation];
]

Now it will be found. By using ClearAll, I removed the Temporary attribute from interpolation. Interestingly, another way to do this is to define a DownValue rather than an OwnValue for it:

Module[{interpolation}, 
  interpolation[1] = Interpolation[Range[10]];
  DumpSave["interpolation.mx", interpolation];
]

In this case, too, it can be found, since garbage-collection of Module-generated variables works differently for DownValues.

I can not fully explain why this affected the code for DumpSave, which is still inside Module. One guess I have is that it gets recorded by DumpSave all right, with all attributes, including Temporary. Then, when you load it, it probably gets garbage-collected immediately after creation, due to this attribute.

Serializing in this manner using Module is also bad (although I am myself guilty of having done this, e.g. here) for another reason: Module-generated variables are only guaranteed to be unique within a single Mathematica session. It is better to use some custom code to generate variables with names guaranteed to be unique for all sessions (which is easy to do. I recommend to read this discussion).

$\endgroup$
2
  • $\begingroup$ Very interesting! Please see my edit to Sjoerd's answer: Evaluating the variable name first is a hack to get around the Temporary issue, I suppose because the variable is then already defined when it is read in? I confess I do not fully understand what is going on. $\endgroup$
    – JxB
    Mar 14, 2012 at 3:52
  • $\begingroup$ @JxB Looks like you are right, good catch. So, apparently, I was proven wrong (which is good, at least in this case:-)). I am a bit surprised, because the mechanism that is used in .mx files is quite low-level, it presumably does not communicate with the high-level kernel state, but populates the symbols directly at the low level. So, I'd think it would add the Temporary attribute. Perhaps, it prevents immediate garbage collection because it was referenced in the input line, but these are all just guesses. $\endgroup$ Mar 14, 2012 at 20:14
1
$\begingroup$

Here is another method, although I don't know how to capture the symbol name programatically...

On[General::newsym];
Get["/tmp/test.mx"];
Off[General::newsym];
 (* General::newsym: Symbol a$1772 is new. >> *)
$\endgroup$
1
  • $\begingroup$ Curious: execute this once, and you get the symbol name; a 2nd time and the message disappears but the symbol gets assigned. $\endgroup$
    – JxB
    Mar 14, 2012 at 20:41

Your Answer

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

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