mailing-list for TeXmacs Users

Text archives Help


Re: [TeXmacs] Mathematica plugin with Graphics


Chronological Thread 
  • From: Tian-Min Yan <address@hidden>
  • To: address@hidden
  • Subject: Re: [TeXmacs] Mathematica plugin with Graphics
  • Date: Tue, 30 Oct 2012 22:58:55 +0100
  • Authentication-results: spamcheck-ng1.citic74.net; dkim=pass (2048-bit key) header.i=@gmail.com; dkim-asp=none

Hi Philippe,

Thank you for the explanation. It sounds interesting to fully utilize
the new features in Mathematica. In order to see whether we have hope to
improve the interface, I hacked into the plugin a bit. The outcome looks
optimistic. Now I am able to export the figure as a temporary file (all
formats are available as long as Mathematica supports).

Currently I need to find a way to present the figure in TeXmacs
instantly after the typing. For the EPS file, is that simply put the EPS
script into the buffer? I got the plain text as a result...

Moreover, how to load a figure into TeXmacs from this temporary file,
like a .PNG file? I think that should be quite simple, though I don't
have much time to dig further...

I attached the (ugly!) modified tm_mathematica.c file here to present
the idea. Some explanations are shown as following.

------------------------------------------------------------------------
Based on the original code
("/texmacs-texmacs/src/plugins/mathematica/src.lazy/tm_mathematica.c"),
the new version of MathLink seems no long deals with the obsolete packet
"DISPLAYPKT", where the original code handled the PS display. Instead,
almost all useful return values are directed into "TEXTPACKET". If one
inputs "Plot[Sin[x], {x, 0, 1}]" or whatever plotting command, the
return value is always a TEXTPACKET starting with "Graphics" or
"Graphics3D" after "Print[]". Such objects cannot be handled by the
TeXForm[] function, therefore error message is raised. On the other
hand, if it is some ordinary expressions, they are readily converted
into the corresponding TeX strings (still there are incorrect
"translations" with the TeXForm[] function).

So, I think the solution may be firstly to identify the type of the
object returned by Mathematica, then we tackle with it according to its
type. In this case, we need twice evaluations, but the second evaluation
uses the return valued from the first one. I did not see performance
deterioration.

For the first evaluation, we can use
Print[ExportString[ToExpression[expr], "Text"]] and return a string as
the universal representation. In the second evaluation, if the string
starts with "Graphics", we reevaluate it with Export["./tmp.eps",
ToExpression[str]] or whatever format and obtain a temporary file from
the plot. Otherwise, we use Print[TeXForm[ToExpression[str]]] to get TeX
strings, just as usual. I even see some objects like "Button" can be
treated in the same way.



Best,
Tian-Min


On Tue, 2012-10-30 at 19:01 +0100, address@hidden
wrote:
> Hi Tian-Min,
>
> The plugin worked perfectly for graphics in old times when Mathematica
> produced pure postscript graphics (this was in versions <=5).
> If you are happy with the old-style Mathematica graphics, in your
> mathematica session simply evaluate : Get["Version5`Graphics`"]
> and then the plugin will recognize the ps graphics and show them in
> TeXmacs (but only for old -or unchanged- graphics functions, old options
> etc.)
>
> It would be nice to benefit from the new mathematica graphics, but that
> would require someone to volunteer for improving the plugin in that area.
>
> Best,
> Philippe
>
>
> Tian-Min Yan - address@hidden wrote:
> > Hi all,
> >
> > I am using Mathematica 8. The Mathematica plugin in TeXmacs works
> > perfectly with a single expression if it does not contain graphical
> > elements. But if we use functions involving plots, the output is
> > problematic. Has anybody figured out the implementation of embedded
> > figures with the Mathematica plugin?
> >
> > Best,
> > Tian-Min
> >
> >
> >
> >
>

/******************************************************************************
 * MODULE     : tm_mathematica.c
 * DESCRIPTION: Interface with Mathematica
 * COPYRIGHT  : (C) 2005  Andrey Grozin
 *******************************************************************************
 * This software falls under the GNU general public license version 3 or later.
 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mathlink.h"

#define CLOSED 11L
#define PRE_NAME  "/plugins/mathematica/ps/pre"
#define POST_NAME "/plugins/mathematica/ps/post"
#define LOG "./log.mma"
// #define LOG_PS "./log.ps"
/* MODIFY THE EXTENSION TO EXPORT DIFFERENT FORMAT*/
#define FIG_NAME "./tmp.eps" 

#ifdef LOG
static FILE *log;
#endif
#ifdef LOG_PS
static FILE *psfile;
#endif

MLENV env =(MLENV)0;
MLINK link=(MLINK)0;
static size_t size=128;
static char *input,*pre_name,*post_name;
static char *mls_buf;
static int protect_hat=0;

static void texput(char *s, FILE* fid) {
  char c; int n,nl; char* pc;
  nl=0; pc=s;
  while( (c=*(s++)) ) {
    if (c=='\\') {
      c=*(s++);
      if ((c>='0')&&(c<='9')) {
	n=c-'0';
	while (1) {
	  c=*(s++);
	  if ((c<'0')||(c>'9')) {
	    if (n==0x0a) { putc(' ', fid); *(pc++) = ' '; nl=1; }
	    else { putc(n, fid); *(pc++) = n; }
	    if (c)
	      if (nl) {
		if (c=='>') nl=0;
		else if (c>' ') { putc(c, fid); *(pc++) = c; nl=1; }
		else if (protect_hat&&(c=='^')) { putc(' ', fid); *(pc++) = ' '; }
		else {putc(c, fid); *(pc++) = c;}
	      }
	    break;
	  } else n=8*n+(c-'0');
	}
	if (c=='\0') {*(pc++) = '\0'; break;}
      } else if (protect_hat&&(c=='^')) {putc(' ', fid); *(pc++) = ' ';}
      else {putc(c, fid); *(pc++) = c;}
    } else if (nl) {
      if (c=='>') nl=0;
      else if (c>' ') {
	if (protect_hat&&(c=='^')) { putc(' ', fid); *(pc++) = ' '; }
	else { putc(c, fid); *(pc++) = c;}
	nl=1;
      }
    } else if (protect_hat&&(c=='^')) { putc(' ', fid); *(pc++) = ' '; }
    else {putc(c, fid); *(pc++) = c;}
  }
}

static void psput(char *s) {
  char c; int n,l; char* pc;
  pc = s;
  while( ( c=*(s++) ) ) {
    if (c=='\\') {
      c=*(s++);
      if ((c>='0')&&(c<='7')) {
	l=0; n=c-'0';
	while (1) {
	  l++; c=*(s++);
	  if ((l>=3)||(c<'0')||(c>'7')) {
	    putchar(n);
	    *(pc++) = n;
#ifdef LOG_PS
	    fputc(n,psfile);
#endif
	    if (c) {
	      putchar(c);
	      *(pc++) = c;
#ifdef LOG_PS
	      fputc(c,psfile);
#endif
	    }
	    break;
	  } else n=8*n+(c-'0');
	}
	if (c=='\0') {*(pc++)='\0'; break;}
      } else {
	putchar(c);
	*(pc++) = c;
#ifdef LOG_PS
	fputc(c,psfile);
#endif
      }
    } else {
      putchar(c);
      *(pc++) = c;
#ifdef LOG_PS
      fputc(c,psfile);
#endif
    }
  }
}

static void prelude(char *name) {
  FILE *ps=fopen(name,"r");
  char(c);
  while (1) {
    c=getc(ps);
    if (c==EOF) break;
    putchar(c);
#ifdef LOG_PS
    fputc(c,psfile);
#endif
  }
  fclose(ps);
}

static void regularize(char* s) 
{
  /* delete '\\\012' and '\012>' */
  char c; char* pc;
  pc=s;
  while( (c=*(s++)) ) {
    if(c=='\\') {
      c=*(s++);
      if(c=='\\') { s+=5; }
      else if((c<='9')&&(c>='0')) {
	while((c=*(s++))) { if(c=='>'||c==' ') break; }
      }
    }
    else *(pc++) = c;
  }
  *pc = '\0';
}

static void eps_to_string()
{
  FILE* f_ps; int c;
  
  fputs("ps:", stdout); fflush(stdout);
  if( ( f_ps = fopen(FIG_NAME, "r") ) ) {
    while((c=fgetc(f_ps)) != EOF) {
      putchar(c);
    }
    putchar( '\0' ); putchar( '\n' );
    fclose(f_ps);
  } else {
    fputs("Cannot open tmp.eps\n", stdout);
  }
}

static void evaluate(int type, char* s)
{
  int pkt,more,non_ps,msg; long err;
  char *result,*symbol;
  /* FILE* f_log; */

  MLPutFunction(link, "EvaluatePacket", 1L);
  switch(type) {
  case -1: /* No way! */
    exit(1);
  case 0: /* TeX */
    MLPutFunction(link, "Print", 1L);
    MLPutFunction(link, "TeXForm", 1L);
    MLPutFunction(link, "ToExpression", 1L);
    MLPutString(link,s);
    break;
  case 1: /* Graphics */
    regularize(s); /* remove control characters */
    /*    
	  f_log = fopen("./fig.log", "w");
	  fputs(s, f_log);
	  fclose(f_log);  
    */
    MLPutFunction(link, "Export", 2L);
    MLPutString(link, FIG_NAME);
    MLPutFunction(link, "ToExpression", 1L);
    MLPutString(link, s);
    break;
  }
  MLEndPacket(link);

  more=1; non_ps=1; msg=0;
  do {
    switch (pkt=MLNextPacket(link)) {
    case RETURNPKT:
#ifdef LOG
      fputs("RETURNPKT@evaluate\n\n",log); fflush(log);
#endif
      more=0; break;
    case RETURNTEXTPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"RETURNTEXTPKT@evaluate: \"%s\"\n\n",result); fflush(log);
#endif
      MLDisownString(link,result);
      more=0; break;
    case INPUTNAMEPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"INPUTNAMEPKT@evaluate: \"%s\"\n",result); fflush(log);
#endif
      MLDisownString(link,result);
      break;
    case OUTPUTNAMEPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"OUTPUTNAMEPKT@evaluate: \"%s\"\n",result); fflush(log);
#endif
      MLDisownString(link,result);
      break;
    case TEXTPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"TEXTPKT@evaluate: \"%s\"\n",result); fflush(log);
#endif
      if (msg) {
	fputs("{\\magenta ",stdout);
	protect_hat=1; texput(result, stdout);
	fputs("}\n\n",stdout);
	protect_hat=0; msg=0;
      } else {
	
	switch(type) {
	case 0: /* TeX */
	  fputs("$\\displaystyle ",stdout);
	  texput(result, stdout);
	  fputs("$",stdout);
	  break;
	case 1: /* graphics */
	  break;
	default:
	  fputs("Oops, nothing happened...\n", stdout);
	  break;
	}
      }
      MLDisownString(link,result);
      break;
    case MESSAGEPKT:
      MLGetSymbol(link,(const char**)&symbol);
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"MESSAGEPKT@evaluate: \"%s\"  \"%s\"\n",symbol,result); fflush(log);
#endif
      MLDisownSymbol(link,symbol);
      MLDisownString(link,result);
      msg=1;
      break;
    case DISPLAYPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"DISPLAYPK@evaluate: \"%s\"\n",result); fflush(log);
#endif
      if (non_ps) {
	fputs("\2ps:",stdout);
#ifdef LOG_PS
	psfile=fopen(LOG_PS,"w");
#endif
	prelude(pre_name); non_ps=0;
      }
      psput(result);
      MLDisownString(link,result);
      break;
    case DISPLAYENDPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"DISPLAYENDPKT@evaluate: \"%s\"\n",result); fflush(log);
#endif
      psput(result);
      prelude(post_name);
      fputs("\5{}{}\n\n",stdout);
#ifdef LOG_PS
      fclose(psfile);
#endif
      non_ps=1;
      MLDisownString(link,result);
      break;
    case CALLPKT:
#ifdef LOG
      fputs("CALLPKT@evaluate\n",log); fflush(log);
#endif
      break;
    default:
#ifdef LOG
      fprintf(log,"UNKNOWN PACKET@evaluate: %1d\n",pkt); fflush(log);
#endif
      break;
    }
    MLNewPacket(link);
    err=MLError(link);
    if (err==CLOSED) {
      fputs("\\red The end\5",stdout);
      MLClose(link);
      MLDeinitialize(env);
      exit(0);
    } else if (err) {
      printf("\\red Error %ld: %s\5",err,MLErrorMessage(link));
      exit(1);
    }
  } while (more);

}

static void command(char *s) {
  int pkt,more,non_ps,msg, type, is_buf; long err;
  char *result,*symbol;
  fputs("\2latex:",stdout);
  MLPutFunction(link,"EvaluatePacket",1L);
  MLPutFunction(link,"Print",1L);
  //  MLPutFunction(link,"TeXForm",1L);
  MLPutFunction(link, "ExportString", 2L);
  MLPutFunction(link,"ToExpression",1L);
  MLPutString(link,s);
  MLPutString(link,"Text");
  MLEndPacket(link);
  more=1; non_ps=1; msg=0; type = 0; is_buf = 0;

  do {
    switch (pkt=MLNextPacket(link)) {
    case RETURNPKT:
#ifdef LOG
      fputs("RETURNPKT@command\n\n",log); fflush(log);
#endif
      more=0;
      break;
    case RETURNTEXTPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"RETURNTEXTPKT@command: \"%s\"\n\n",result); fflush(log);
#endif
      MLDisownString(link,result);
      more=0;
      break;
    case INPUTNAMEPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"INPUTNAMEPKT@command: \"%s\"\n",result); fflush(log);
#endif
      MLDisownString(link,result);
      break;
    case OUTPUTNAMEPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"OUTPUTNAMEPKT@command: \"%s\"\n",result); fflush(log);
#endif
      MLDisownString(link,result);
      break;
    case TEXTPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"TEXTPKT@command: \"%s\"\n",result); fflush(log);
#endif
      if (msg) {
	fputs("{\\magenta ",stdout);
	protect_hat=1; texput(result, stdout);
	fputs("}\n\n",stdout);
	protect_hat=0; msg=0;
      } else {
	
	if( is_buf ) {
	  fputs("TEXTPKT more than once?\n", stdout);
	  break;
	}
	if( ! ( mls_buf = (char*)malloc(strlen(result)+1) ) ) {
	  fputs("Cannot allocate memory for the returning TEXT packet.\n", stdout);
	  break;
	}
	is_buf = 1;
	
	strcpy(mls_buf, result);
	//	fputs("$\\displaystyle ",stdout);
	char* pKeyword;
	if( pKeyword=strstr(mls_buf, "Graphics") )
	  if( (mls_buf - pKeyword) == 0 )  { /* begin with keyword "Graphics" */
	    type = 1; fputs("Graphics\n", stdout); break;
	  }
	  
	// texput(result, stdout);
	//	fputs("$",stdout);
      }
      MLDisownString(link,result);
      break;
    case MESSAGEPKT:
      MLGetSymbol(link,(const char**)&symbol);
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"MESSAGEPKT@command: \"%s\"  \"%s\"\n",symbol,result); fflush(log);
#endif
      MLDisownSymbol(link,symbol);
      MLDisownString(link,result);
      msg=1;
      break;
    case DISPLAYPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"DISPLAYPK@command: \"%s\"\n",result); fflush(log);
#endif
      if (non_ps) {
	fputs("\2ps:",stdout);
#ifdef LOG_PS
	psfile=fopen(LOG_PS,"w");
#endif
	prelude(pre_name); non_ps=0;
      }
      psput(result);
      MLDisownString(link,result);
      break;
    case DISPLAYENDPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"DISPLAYENDPKT@command: \"%s\"\n",result); fflush(log);
#endif
      psput(result);
      prelude(post_name);
      fputs("\5{}{}\n\n",stdout);
#ifdef LOG_PS
      fclose(psfile);
#endif
      non_ps=1;
      MLDisownString(link,result);
      break;
    case INPUTPKT:
      MLGetString(link,(const char**)&result);
#ifdef LOG
      fprintf(log,"INPUTPKT@command: \"%s\"\n",result); fflush(log);
#endif
      printf("\2prompt#\\red %s{}\5\5",result);
      fflush(stdout);
      MLDisownString(link,result);
      if (getline(&input,&size,stdin)>=0) command(input);
      break;
    case CALLPKT:
#ifdef LOG
      fputs("CALLPKT@command\n",log); fflush(log);
#endif
      break;
    default:
#ifdef LOG
      fprintf(log,"UNKNOWN PACKET@command: %1d\n",pkt); fflush(log);
#endif
      break;
    }
    MLNewPacket(link);
    err=MLError(link);
    if (err==CLOSED) {
      fputs("\\red The end\5",stdout);
      MLClose(link);
      MLDeinitialize(env);
      exit(0);
    } else if (err) {
      printf("\\red Error %ld: %s\5",err,MLErrorMessage(link));
      exit(1);
    }
  } while (more);
  


  if(is_buf) {
    evaluate(type, mls_buf);
    free(mls_buf); is_buf = 0;
  }

  /* post-process, e.g., reading a generated figure */
  switch(type) {
  case 0: /* tex */
    break;
  case 1: /* figure */
    /* e.g., read the generated EPS file and dump to TeXmacs*/
    eps_to_string();
    /* or can use other methods, like loading .png, .svg., whatever */
    fputs("$",stdout); 
    break;
  default:
    break;
  }
}



int main(int argc, char *argv[]) {
  int err;
  size_t InNum=1,l;
  char *tm_path;
#ifdef LOG
  log=fopen(LOG,"w");
#endif

  tm_path=getenv("TEXMACS_PATH");
  /* tm_path = (char*)"./"; */

  if (tm_path==NULL) exit(1);
  l=strlen(tm_path);
  pre_name=(char*)malloc(l+strlen(PRE_NAME)+1);
  post_name=(char*)malloc(l+strlen(POST_NAME)+1);
  strcpy(pre_name,tm_path);  strcpy(pre_name+l,PRE_NAME);
  strcpy(post_name,tm_path); strcpy(post_name+l,POST_NAME);

  input=(char*)malloc(size);

  env=MLInitialize((MLParametersPointer)0);
  if (env==(MLENV)0) {
    fputs("\2latex:\\red Initialization of MathLink failed\5",stdout);
    exit(1);
  }

  link=MLOpenString(env,"-linkname \"math -mathlink\"",&err);
  if (link==(MLINK)0) {
    fputs("\2latex:\\red Link with Mathematica failed",stdout);
    MLDeinitialize(env);
    exit(1);
  }

  fputs("\2latex:\\red Mathematica",stdout);

  while (1) {
    /* Prompt */
    printf("\2prompt#\\red In[%1d]:= {}\5\5",InNum++);
    fflush(stdout);
    if (getline(&input,&size,stdin)>=0) command(input);
  }

  return 0;
}



Archive powered by MHonArc 2.6.19.

Top of page