3

I am looking for the prototypical 'Hello World' program that creates a Mathematica Notebook file.

I have this working program.

 package graphica;

 import com.wolfram.jlink.*;

 /**
  *
  * @author Nilo
  */
public class MathematicaTester {

public static void main(String[] args) {

    KernelLink ml = null; 
    String jLinkDir = "C:\\Program Files\\Wolfram Research\\Mathematica\\8.0\\SystemFiles\\Links\\JLink";
    System.setProperty("com.wolfram.jlink.libdir", jLinkDir);

    try { 
        ml = MathLinkFactory.createKernelLink("-linkmode launch -linkname 'C:\\Program Files\\Wolfram Research\\Mathematica\\8.0\\MathKernel.exe'");

        ml.discardAnswer();
        String expr = "Sum[k^2,{k,1,11}]";
        ml.evaluate(expr);
        ml.waitForAnswer();
        String x = ml.getString();
        System.out.println("Result = " + x);

    } catch (MathLinkException e) { 
        System.out.println("Fatal error opening link: " + 
        e.getMessage()); 
        return; 
    }
}
}

When I run this I get the following -expected- output.

run:
Result = 506
BUILD SUCCESSFUL (total time: 2 seconds)

QUESTION:

I want to change this program so that a Mathematica Notebook is created. The program will ( eventually ) add line after line of mma command strings. It would be nice if a Mathematica frontend is started at the same time and that the mma code is evaluated by request from the Java program. Essential is the creation of a Notebook that can be opened later by the mma front-end.

Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
nilo de roock
  • 4,077
  • 4
  • 34
  • 62
  • I don't know Mathematica throughoutly, but if the notebook is like a project file, you have to know its structure. If it is binary in addition, you have to reverse engineer it... Does the official site (or any unofficial) says anything about it? – zeller Nov 07 '11 at 14:10
  • @david - Mathematica - Java integration is based on J/Link. I have browsed the docs but did not find what I need. - I want to make sure I did not miss anything or can get a HelloWorld here before I start hacking. – nilo de roock Nov 07 '11 at 14:22
  • 2
    @niloderoock Mathematica notebooks are actually plain text so you can get at the underlying structure by looking at one with a text editor. The Java bits I can't help you with. – Verbeia Nov 07 '11 at 15:48
  • 1
    I don't know much Java, so I'll stay out of that realm. But it seems that you managed to evaluate arbitrary expressions in the kernel, from Java. The function to create a notebook object is `CreateDocument[]` (and then you can see the docs for all the functions to manipulate it, including writing into it and saving it). Now the catch is that this only works if a front end is present. So you'll need to evaluate it as `UsingFrontEnd[nb = CreateDocument[]]`. This will cause the kernel to launch a background front end and use it. Tested on Win using a command line session, hope it works in J – Szabolcs Nov 21 '11 at 14:28
  • Just make sure you're in an environment where a Front End can function (even if it doesn't have a visible window). If you're on Linux, this means you need X (Google for headless X server) – Szabolcs Nov 21 '11 at 14:31
  • @Szabolcs Thank you, will try that. I am on Win btw. – nilo de roock Nov 21 '11 at 14:51
  • Please let me know the result, I'm curious too. – Szabolcs Nov 21 '11 at 15:21
  • I get Fatal error opening link: MLGet out of sequence. probably because I do a getString to fetch the result. There is no documentation I found about data types to expect. I can try them all later, when I have more time. Assuming the statement worked, of course. - Documentation is scarce on this. – nilo de roock Nov 21 '11 at 16:16
  • @Szabolcs - I finally managed to create a working solution / answer from the tips I received here and there, thanks. At least this proves that the technology works. – nilo de roock Nov 26 '11 at 16:45
  • 1
    @niloderoock Thanks for posting the code. – Szabolcs Nov 26 '11 at 19:21

3 Answers3

6

A method for creating a formatted notebook file is shown here:

How to create a notebook with a properly formatted expression

You can box format your Mathematica code (mathCommand) using a kernel call, e.g.

String mathCommand = "Plot[Sin[x], {x, 0, 6}]";
mathCommand = "FullForm[ToBoxes[Defer[" + mathCommand + "]]]";
MathKernel kernel = new MathKernel();
kernel.Compute(mathCommand);
mathCommand = kernel.Result.ToString();

Then encapsulate it like so, and save it with .nb extension.

Notebook[{Cell[BoxData[
... ( inserted box-formatted output ) ...
], "Input"]
},
WindowSize->{615, 750},
WindowMargins->{{328, Automatic}, {Automatic, 76}},
StyleDefinitions->"Default.nb"
]
Community
  • 1
  • 1
Chris Degnen
  • 8,443
  • 2
  • 23
  • 40
  • Looks promising, I am going to try this. – nilo de roock Nov 07 '11 at 16:37
  • Have you -tested- this ? Clearly, this answer is not self-containing. – nilo de roock Nov 10 '11 at 15:26
  • @ nilo, I have added `MathKernel kernel = new MathKernel();` Other than that, the version in the link works on C#. – Chris Degnen Nov 10 '11 at 19:27
  • Thanks @ Chris, that explains it, because I am using Java. I had to find a solution for a JLinkNativeLibrary missing error as well as MGet synhronization failures. Now I am at the point that I can actually do something with Mathematica like adding "1+1". So I am not quite there yet, but I am making progress. ;-) – nilo de roock Nov 10 '11 at 20:04
3

Mathematica notebooks are plaintext files with structures like

Notebook[{Cell[],Cell[]}]

You can work out the required structure by viewing them with a text editor. Assuming you can get Java to create a text file, save it with a .nb file name ending, and invoke the command-line version of Mathematica, then what you want should be doable. You will probably want to set the input cells to initialization type.

Brett Champion
  • 8,497
  • 1
  • 27
  • 44
Verbeia
  • 4,400
  • 2
  • 23
  • 44
2

It took some research but I managed to answer the question myself.

 package graphica;

 import com.wolfram.jlink.*;

 /**
  *
  * @author Nilo
  */
 public class MathematicaTester {

     public static void main(String[] args) {

         KernelLink ml = null; 
         String jLinkDir = "C:\\Program Files\\Wolfram Research\\Mathematica\\8.0\    \SystemFiles\\Links\\JLink";
         System.setProperty("com.wolfram.jlink.libdir", jLinkDir);

         try { 
             ml = MathLinkFactory.createKernelLink("-linkmode launch -linkname 'C:\\Program Files\\Wolfram Research\\Mathematica\\8.0\\MathKernel.exe'");
        //test-1
             ml.discardAnswer();
             String expr = "Sum[k,{k,1,11}]";
             ml.evaluate(expr);
             ml.waitForAnswer();
             String x = ml.getString();
             System.out.println("Result = " + x);
       //test-2
             expr = "UsingFrontEnd[nb=NotebookPut[Notebook[{Cell[\"Graphics3D[Cuboid[]]\", \"Input\"]}]]]";
             System.out.println("Result = " + ml.evaluateToOutputForm(expr, 40) );
             expr = "UsingFrontEnd[NotebookSave[nb,\"TERRANOVA1\"]]";
             System.out.println("Result = " + ml.evaluateToOutputForm(expr, 40) );

         } catch (MathLinkException e) { 
             System.out.println("Fatal error opening link: " + 
             e.getMessage()); 
             return; 
         }
     }
 }
nilo de roock
  • 4,077
  • 4
  • 34
  • 62