├── README ├── epscompress.c ├── epscompress.mexa64 ├── epscompress.mexglx ├── epscompress.mexmaci ├── epscompress.mexmaci64 ├── epscompress.mexw32 ├── epscompress.mexw64 ├── examples ├── comparison01.m ├── comparison02.m ├── ex01.m ├── ex02.m ├── ex03.m ├── ex04.m ├── ex05.m ├── ex06.m ├── ex07.m ├── ex08.m ├── ex09.m ├── ex10.m ├── ex11.m ├── ex12.m ├── ex13.m ├── ex14.m ├── ex15.m ├── ex16.m ├── ex17.m ├── laprint.m ├── run_all.m ├── test01.m ├── test02.m ├── test03.m ├── test04.m ├── test05.m ├── test06.m ├── test07.m ├── test08.m ├── test09.m ├── test10.m ├── test11.m ├── test12.m ├── test13.m ├── test14.m ├── test15.m ├── test16.m ├── test17.m ├── test18.m ├── test19.m ├── testing.tex └── userguide.tex ├── matlabfrag.m ├── package.m └── userguide.pdf /README: -------------------------------------------------------------------------------- 1 | matlabfrag is a function which exports a Matlab figure to .eps and .tex files for use in LaTeX/pdfLaTeX/LyX. It is inspired by LaPrint, but is intended to be more WYSIWYG, by respecting figure handles better. 2 | 3 | Some of the advantages of matlabfrag compared to LaPrint are: 4 | - Much more emphasis on WYSIWYG. 5 | - Handles figures that need the OpenGL or Z-Buffer renderers. 6 | - Text objects are sized correctly (such as with a legend). 7 | - Tick labels are handled better. 8 | - Reduced number of options (which could also be viewed as a disadvantage). 9 | 10 | To include the figures in LaTeX, pdfLaTeX and LyX I recommend the pstool package. More information can be found in the User Guide. 11 | 12 | Copyright (c) 2008--2011, Zebb Prime 13 | 14 | Code covered by the BSD License. -------------------------------------------------------------------------------- /epscompress.c: -------------------------------------------------------------------------------- 1 | /** \file epscompress.c 2 | * 3 | * Compresses an EPS file generated from Matlab using the LZW 4 | * algorithm. 5 | * 6 | * According to most sources, the patents for LZW compression expired 7 | * around 2003--2004. If this is incorrect, please let the author know. 8 | * 9 | * This particular algorithm uses an unbalenced binary search tree to 10 | * determine if a string exists in the dictionary. 11 | * 12 | * Version 0.2 10-Sep-2010 13 | * 14 | * See the license at the bottom of the file. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include "mex.h" 21 | 22 | /* Maximum table size, 2^MaxBits */ 23 | #define TABLESIZE 4096 24 | /* Number of branches for each node */ 25 | #define TABLEDEPTH 3 26 | /* Locations of each tree branch */ 27 | #define CHILD 0 28 | #define LEFT 1 29 | #define RIGHT 2 30 | /* Max/Min output bit sizes. */ 31 | #define BITMAX 12 32 | #define BITMIN 9 33 | /* Special input/output values. */ 34 | #define CLEARTABLE 256 35 | #define ENDOFDATA 257 36 | /* First free location in the index. */ 37 | #define FIRSTFREE 258 38 | /* Maximum string storage space */ 39 | #define MAXSTR 1024 40 | /* Maximum output width. */ 41 | #define OUTPUTWIDTH 75 42 | /* Number of lines between DSC comments before compression starts */ 43 | #define DSCGRACE 10 44 | 45 | /** 46 | * Structure containing information about the current LZW 47 | * compression state. 48 | */ 49 | typedef struct{ 50 | /* Index and dictionary tables */ 51 | unsigned int Index[ TABLEDEPTH ][ TABLESIZE ]; 52 | unsigned char Dictionary[ TABLESIZE ]; 53 | /* Current character being processed. */ 54 | unsigned char CurrentChar; 55 | /* Current index (equivalent to the prefix). */ 56 | int CurrentIndex; 57 | /* Next free index. */ 58 | unsigned int NextIndex; 59 | /* Variable to store the maximum index for the current bitsize */ 60 | unsigned int MaxIndex; 61 | /* Current output bitsize. */ 62 | unsigned int BitSize; 63 | } LZW_State; 64 | 65 | /** 66 | * Structure containing information about the IO state. 67 | */ 68 | typedef struct{ 69 | /* File pointers */ 70 | FILE *fin; 71 | FILE *fout; 72 | unsigned int Storage; 73 | unsigned int ColumnWidth; 74 | int StorageIndex; 75 | } IO_State; 76 | 77 | /** 78 | * Initialise LZW_State data structure. 79 | */ 80 | void LZW_State_Init( LZW_State *x ) 81 | { 82 | memset( x->Index, 0, sizeof( x->Index ) ); 83 | memset( x->Dictionary, 0, sizeof( x->Dictionary ) ); 84 | x->CurrentChar = 0; 85 | x->CurrentIndex = -1; 86 | x->NextIndex = FIRSTFREE; 87 | x->MaxIndex = (1<BitSize = BITMIN; 89 | } 90 | 91 | /** 92 | * Initialise IO_State data structure. File pointers 93 | * (fin and fout) need to be initialised seperately. 94 | */ 95 | void IO_State_Init( IO_State *x ) 96 | { 97 | x->Storage = 0; 98 | x->ColumnWidth = 0; 99 | x->StorageIndex = 0; 100 | } 101 | 102 | /** 103 | * Private function to format the output into at max character widths. 104 | */ 105 | void asciiprv_put( char x, IO_State *y ) 106 | { 107 | fputc( x, y->fout ); 108 | y->ColumnWidth++; 109 | /* If output is full, print a newline */ 110 | if( y->ColumnWidth == OUTPUTWIDTH ) 111 | { 112 | fputc( 10, y->fout ); 113 | y->ColumnWidth = 0; 114 | } 115 | } 116 | 117 | /** 118 | * Takes a variable bit-length raw input stream, and formats it into 119 | * ASCII85 format. 120 | */ 121 | void asciistreamout( unsigned int x, IO_State *y, LZW_State *z ) 122 | { 123 | int shift, ii; 124 | const int divisors[] = { 85*85*85*85, 85*85*85, 85*85, 85, 1 }; 125 | 126 | /* Shift the new data in. */ 127 | shift = (32-z->BitSize-y->StorageIndex); 128 | if( shift >= 0 ) y->Storage |= (x<Storage |= (x>>-shift); 130 | 131 | y->StorageIndex += z->BitSize; 132 | 133 | /* If the buffer is full (i.e. 32-bits) output the 5 characters. */ 134 | if( y->StorageIndex >= 32 ) 135 | { 136 | /* Special case, 0 gets written out as z */ 137 | if( y->Storage == 0 ) asciiprv_put( 'z', y ); 138 | else 139 | { 140 | /* Otherwise, output the 5 characters. */ 141 | for( ii=0; ii<5; ii++ ) 142 | { 143 | asciiprv_put( (char)( ( y->Storage/divisors[ii] )%85+33 ), y ); 144 | } 145 | } 146 | y->StorageIndex -= 32; 147 | /* Add any left-over bits to the storage. */ 148 | if( y->StorageIndex == 0 ) y->Storage = 0; 149 | else y->Storage = (x<<(32-y->StorageIndex)); 150 | } 151 | } 152 | 153 | /** 154 | * Cleanup the output stream. Outputs whatever partially completed bits 155 | * are present. 156 | */ 157 | void asciistreamout_cleanup( IO_State *y ) 158 | { 159 | int ii,numBytes; 160 | const int divisors[] = { 85*85*85*85, 85*85*85, 85*85, 85, 1 }; 161 | 162 | /* Only output as many bytes as required, as per Adobe ASCII85 */ 163 | numBytes = 5 - (32-y->StorageIndex)/8; 164 | for( ii=0; iiStorage/divisors[ii] )%85+33 ), y ); 167 | } 168 | 169 | /* Cleanup variables, output the 'end of data' string. */ 170 | y->StorageIndex = 0; 171 | y->Storage = 0; 172 | y->ColumnWidth = 0; 173 | fprintf(y->fout,"~>"); 174 | } 175 | 176 | /** 177 | * Update the Dictionary with new values, and outputs the current prefix. 178 | */ 179 | void NotInDictionary( unsigned int fromNode, unsigned int from, IO_State *y, LZW_State *z ) 180 | { 181 | int temp; 182 | 183 | /* Update the tables */ 184 | z->Index[ fromNode ][ from ] = z->NextIndex; 185 | z->Dictionary[ z->NextIndex ] = z->CurrentChar; 186 | z->NextIndex++; 187 | 188 | /* Output the current index (prefix) */ 189 | asciistreamout( z->CurrentIndex, y, z ); 190 | /* Update to the new index (prefix) */ 191 | z->CurrentIndex = z->CurrentChar; 192 | 193 | /* Check to see if bitsize has been exceeded. */ 194 | if( z->NextIndex == z->MaxIndex ) 195 | { 196 | if( z->BitSize == BITMAX ) 197 | { 198 | asciistreamout( CLEARTABLE, y, z ); 199 | temp = z->CurrentIndex; 200 | LZW_State_Init( z ); 201 | z->CurrentIndex = temp; 202 | } 203 | else 204 | { 205 | z->BitSize++; 206 | z->MaxIndex = (1<BitSize); 207 | } 208 | } 209 | } 210 | 211 | /** 212 | * LZW Compression function. 213 | */ 214 | void LZW( char x, IO_State *y, LZW_State *z) 215 | { 216 | unsigned int X; 217 | 218 | if( z->CurrentIndex == -1 ) 219 | { 220 | z->CurrentIndex = x; 221 | return; 222 | } 223 | 224 | z->CurrentChar = x; 225 | 226 | /* Test to see if prefix exists as a child. */ 227 | X = z->Index[ CHILD ][ z->CurrentIndex ]; 228 | if( X==0 ) 229 | { 230 | NotInDictionary( CHILD, z->CurrentIndex, y, z ); 231 | return; 232 | } 233 | 234 | /* Binary tree search for current string. */ 235 | while( 1 ) 236 | { 237 | /* If we find a value in the dictionary */ 238 | if( z->CurrentChar == z->Dictionary[ X ] ) 239 | { 240 | z->CurrentIndex = X; 241 | break; 242 | } 243 | /* Otherwise, search through the tree */ 244 | if( z->CurrentChar > z->Dictionary[ X ] ) 245 | { 246 | if( z->Index[ RIGHT ][ X ] == 0 ) 247 | { 248 | NotInDictionary( RIGHT, X, y, z ); 249 | break; 250 | } 251 | else 252 | { 253 | X = z->Index[ RIGHT ][ X ]; 254 | } 255 | } 256 | else 257 | { 258 | if( z->Index[ LEFT ][ X ] == 0 ) 259 | { 260 | NotInDictionary( LEFT, X, y, z ); 261 | break; 262 | } 263 | else X = z->Index[ LEFT ][ X ]; 264 | } 265 | } 266 | } 267 | 268 | /** 269 | * Main function call in a c-mex environment. 270 | */ 271 | void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) 272 | { 273 | const char eps_magic[] = {0xc5,0xd0,0xd3,0xc6,0}; 274 | char str[ DSCGRACE ][ MAXSTR ]; 275 | int comp_state = 0; 276 | int ii, jj; 277 | 278 | IO_State y; 279 | LZW_State z; 280 | 281 | IO_State_Init( &y ); 282 | LZW_State_Init( &z ); 283 | 284 | /* Sanity check the inputs */ 285 | if( nrhs != 2 ) mexErrMsgTxt("Two input arguments required.\n"); 286 | 287 | if( nlhs != 0 ) mexErrMsgTxt("Too many output arguments.\n"); 288 | 289 | if ( !( mxIsChar(prhs[0]) && mxIsChar(prhs[1]) ) ) 290 | mexErrMsgTxt("Inputs (filenames) must both be of type string.\n."); 291 | 292 | y.fin = fopen( mxArrayToString( prhs[0] ), "r" ); 293 | if( y.fin == NULL ) 294 | mexErrMsgTxt("Cannot open the input file for reading.\n"); 295 | 296 | y.fout = fopen( mxArrayToString( prhs[1] ), "w" ); 297 | if( y.fout == NULL ) 298 | mexErrMsgTxt("Cannot open the output file for writing.\n"); 299 | 300 | /* Read the header */ 301 | fgets( &str[0][0], MAXSTR, y.fin ); 302 | if( ( strncmp( &str[0][0], "%!PS-Adobe-", 11 ) && strncmp( &str[0][0], eps_magic, 4 ) ) ) 303 | { 304 | fclose(y.fin); 305 | fclose(y.fout); 306 | mexErrMsgTxt("Input file is not an EPS file.\n"); 307 | } 308 | fputs( &str[0][0], y.fout ); 309 | 310 | comp_state = 0; 311 | while( !feof( y.fin ) ) 312 | { 313 | str[0][0] = 0; 314 | fgets( &str[0][0], MAXSTR, y.fin ); 315 | /* If compression is off */ 316 | if( comp_state == 0 ) 317 | { 318 | /* If the next line is a DSC comment, output and continue */ 319 | if( !strncmp( &str[0][0], "%%", 2 ) ) fputs( &str[0][0], y.fout ); 320 | 321 | /* Otherwise, determine if we need to start compression by scanning 322 | ahead. */ 323 | else 324 | { 325 | for( ii=1; iichar').'; 28 | fclose(fh); 29 | texfile = regexprep(texfile,'\\begin\{psfrags\}','%\\begin{psfrags}'); 30 | texfile = regexprep(texfile,'\\psfragscanon%','%\\psfragscanon%'); 31 | texfile = regexprep(texfile,'\\includegraphics','%\\includegraphics'); 32 | texfile = regexprep(texfile,'\\end\{psfrags\}','%\\end{psfrags}'); 33 | fh = fopen('comparison01-laprint.tex','w'); 34 | fwrite(fh,texfile); 35 | fh=fclose(fh); 36 | movefile('comparison01-laprint*','graphics/'); -------------------------------------------------------------------------------- /examples/comparison02.m: -------------------------------------------------------------------------------- 1 | %% A quick and dirty comparison between Matlabfrag and LaPrint 2 | close all; 3 | hfig = figure; 4 | set(hfig,'units','centimeters'); 5 | pos = get(hfig,'position'); 6 | set(hfig,'position',[pos(1:2),5.5,6]); 7 | 8 | %% Draw the figure 9 | [x,y,z] = peaks(20); 10 | surf(x.*1e-3,y.*1e-3,z.*1e-4); 11 | xlabel('x axis'); 12 | ylabel('y axis'); 13 | zlabel('z axis'); 14 | 15 | %% Produce the figure with matlabfrag 16 | matlabfrag('graphics/comparison02-matlabfrag'); 17 | 18 | %% Produce the figure with LaPrint 19 | % These are the options required to make LaPrint behave in the same manner 20 | % as matlabfrag 21 | laprint(1,'comparison02-laprint','width',6,'factor',1,'scalefonts','off',... 22 | 'keepfontprops','on','asonscreen','on','keepticklabels','off'); 23 | % Now open the file, and comment out parts of it to make it compatible with 24 | % pstool. 25 | fh = fopen('comparison02-laprint.tex','r'); 26 | texfile = fread(fh,inf,'uint8=>char').'; 27 | fclose(fh); 28 | texfile = regexprep(texfile,'\\begin\{psfrags\}','%\\begin{psfrags}'); 29 | texfile = regexprep(texfile,'\\psfragscanon%','%\\psfragscanon%'); 30 | texfile = regexprep(texfile,'\\includegraphics','%\\includegraphics'); 31 | texfile = regexprep(texfile,'\\end\{psfrags\}','%\\end{psfrags}'); 32 | fh = fopen('comparison02-laprint.tex','w'); 33 | fwrite(fh,texfile); 34 | fh=fclose(fh); 35 | movefile('comparison02-laprint*','graphics/'); -------------------------------------------------------------------------------- /examples/ex01.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex01'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | hfig = figure(gcf); 8 | plot(rand(2)); 9 | axis([1 2 0 1]); 10 | matlabfrag('graphics/ex01-1'); 11 | matlabfrag('graphics/ex01-2','epspad',[10,10,10,10],... 12 | 'handle',hfig,'compress',true); -------------------------------------------------------------------------------- /examples/ex02.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex02'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | xlabel('should not see this text','UserData',... 10 | 'matlabfrag:Plays nice with \LaTeX'); 11 | matlabfrag('graphics/ex02'); -------------------------------------------------------------------------------- /examples/ex03.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | 3 | %% Everything below appears in userguide 4 | hfig = figure; 5 | plot([-1 1],rand(2)); 6 | axis([-1 1 0 1]); 7 | set(hfig,'units','centimeters',... 8 | 'NumberTitle','off','Name','ex03'); 9 | pos = get(hfig,'position'); 10 | set(hfig,'position',[pos(1:2),8,3]); 11 | %% The following is excluded from userguide 12 | matlabfrag('graphics/ex03'); -------------------------------------------------------------------------------- /examples/ex04.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex04'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | xlabel('Red text!','color',[1 0 0]); 10 | ht = text(1,0.5,'Green text!'); 11 | set(ht,'color',[0 1 0]); 12 | %% The following is excluded from userguide 13 | matlabfrag('graphics/ex04'); -------------------------------------------------------------------------------- /examples/ex05.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex05'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | hx = xlabel('12pt font'); 10 | set(hx,'FontSize',12); 11 | text(1,0.5,'8pt font','FontSize',8); 12 | %% The following is excluded from userguide 13 | matlabfrag('graphics/ex05'); -------------------------------------------------------------------------------- /examples/ex06.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex06'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | xlabel('Italic font','FontAngle','italic'); 10 | ht = text(1,0.5,'Oblique font'); 11 | set(ht,'FontAngle','oblique'); 12 | %% The following is excluded from userguide 13 | matlabfrag('graphics/ex06'); -------------------------------------------------------------------------------- /examples/ex07.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex07'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | hx=xlabel('Bold font'); 10 | set(hx,'FontWeight','bold'); 11 | text(1,0.5,'Demi font','FontWeight','demi'); 12 | title('Light font','FontWeight','light'); 13 | %% The following is excluded from userguide 14 | matlabfrag('graphics/ex07'); -------------------------------------------------------------------------------- /examples/ex08.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex08'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | xlabel('Comic sans?','FontName','Comic Sans MS'); 10 | ht = text(1,0.5,'Fixed-width'); 11 | set(ht,'FontName','FixedWidth'); 12 | %% The following is excluded from userguide 13 | matlabfrag('graphics/ex08'); -------------------------------------------------------------------------------- /examples/ex09.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex09'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),4,3]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | xlabel('$x=\frac{\alpha}{\beta}$','interpreter','none'); 10 | text(1.5,0.5,'$x=\frac{\alpha}{\beta}$',... 11 | 'interpreter','latex'); 12 | %% The following is excluded from userguide 13 | matlabfrag('graphics/ex09'); -------------------------------------------------------------------------------- /examples/ex10.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex10'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),6,5]); 6 | %% Everything below appears in userguide 7 | plot(rand(2)); 8 | axis([1 2 0 1]); 9 | title(['2d matrix ';' weird alignment']); 10 | xlabel({'cells';'are';'better!'}); 11 | text(2,0.5,'multiline in LaTeX','HorizontalAlignment',... 12 | 'right','UserData',['matlabfrag:\begin{tabular}',... 13 | '{@{}r@{}}multiline\\in\\\LaTeX\end{tabular}']); 14 | %% The following is excluded from userguide 15 | matlabfrag('graphics/ex10'); -------------------------------------------------------------------------------- /examples/ex11.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex11'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),6,3]); 6 | %% Everything below appears in userguide 7 | plot([1 exp(1)],rand(2)); 8 | hax = gca; 9 | set(hax,'xlim',[1 exp(1)],'xtick',[1 exp(0.5) exp(1)],... 10 | 'xticklabel',{'$e^0$','$e^{0.5}$','$e^1$'}); 11 | set(hax,'ylim',[0 1],'ytick',[0 real(exp(-i*7*pi/4)) 1],... 12 | 'yticklabel',{'$\ytick{3\pi/2}$','$\ytick{7\pi/4}$','$\ytick{2\pi}$'}); 13 | %% The following is excluded from userguide 14 | matlabfrag('graphics/ex11'); -------------------------------------------------------------------------------- /examples/ex12.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex12'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),6,4]); 6 | %% Everything below appears in userguide 7 | plot([-1 1],rand(3,2)); 8 | hleg = legend('L = 1 m','L = 2 m','L = 3 m'); 9 | hlegc = get(hleg,'children'); 10 | % This example needs updating 11 | %set(hlegc(9),'userdata','matlabfrag:$L=\SI{1}{m}$'); 12 | %set(hlegc(6),'userdata','matlabfrag:$L=\SI{2}{m}$'); 13 | %set( findobj(hlegc,'string','L = 3 m'), 'userdata',... 14 | % 'matlabfrag:$L=\SI{3}{m}$'); 15 | %% The following is excluded from userguide 16 | matlabfrag('graphics/ex12'); -------------------------------------------------------------------------------- /examples/ex13.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex13'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),7,5]); 6 | %% Everything below appears in userguide 7 | [x,y,z] = peaks(20); 8 | surf(x.*1e-3,y.*1e-3,z); 9 | % placed inside the label, need to set xticklabelmode to manual 10 | xlabel('x axis ($x10^{-3}$)','interpreter','latex',... 11 | 'userdata','matlabfrag:x axis $\left(\times10^{-3}\right)$'); 12 | set(gca,'xticklabelmode','manual'); 13 | % manually placed as a text object: 14 | ylabel('ylabel'); 15 | set(gca,'yticklabelmode','manual'); 16 | text(-10e-3,0,-10,'$x10^{-3}$','interpreter','latex',... 17 | 'userdata','matlabfrag:$\times10^{-3}$'); 18 | %% The following is excluded from userguide 19 | matlabfrag('graphics/ex13'); -------------------------------------------------------------------------------- /examples/ex14.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex14'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),8,6]); 6 | %% Everything below appears in userguide 7 | peaks; 8 | hs = get(gca,'children'); 9 | set(hs,'facealpha',0.4,'edgealpha',0.4); 10 | hl=legend('legend'); 11 | set(hl,'location','northeast'); 12 | xlabel('X','userdata','matlabfrag:$\mathrm X$'); 13 | ylabel('Y','userdata','matlabfrag:$\mathbf Y$'); 14 | zlabel('Z','fontsize',12,'userdata','matlabfrag:$\mathcal Z$') 15 | matlabfrag('graphics/ex14','renderer','opengl','dpi',720); 16 | %% The following is excluded from userguide -------------------------------------------------------------------------------- /examples/ex15.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex15'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),8,6]); 6 | 7 | load wind 8 | wind_speed = sqrt(u.^2 + v.^2 + w.^2); 9 | 10 | hpatch = patch(isosurface(x,y,z,wind_speed,35)); 11 | isonormals(x,y,z,wind_speed,hpatch) 12 | set(hpatch,'FaceColor','red','EdgeColor','none'); 13 | 14 | [f vt] = reducepatch(isosurface(x,y,z,wind_speed,45),0.05); 15 | daspect([1,1,1]); 16 | hcone = coneplot(x,y,z,u,v,w,vt(:,1),vt(:,2),vt(:,3),2); 17 | set(hcone,'FaceColor','blue','EdgeColor','none'); 18 | 19 | camproj perspective 20 | camva(25); 21 | 22 | hlight = camlight('headlight'); 23 | set(hpatch,'AmbientStrength',.1,... 24 | 'SpecularStrength',1,... 25 | 'DiffuseStrength',1); 26 | set(hcone,'SpecularStrength',1); 27 | 28 | hsline = streamline(x,y,z,u,v,w,80,30,11); 29 | xd = get(hsline,'XData'); 30 | yd = get(hsline,'YData'); 31 | zd = get(hsline,'ZData'); 32 | delete(hsline) 33 | 34 | i=110; 35 | campos([xd(i),yd(i),zd(i)]) 36 | camtarget([xd(i+5)+min(xd)/100,yd(i),zd(i)]) 37 | camlight(hlight,'headlight') 38 | set(gca,'xticklabel','','yticklabel','','zticklabel',''); 39 | drawnow 40 | %% Everything below appears in userguide 41 | lighting phong; 42 | set(gcf,'Renderer','zbuffer'); 43 | text(0,0,0,'smiley','userdata','matlabfrag:\blacksmiley'); 44 | drawnow; 45 | matlabfrag('graphics/ex15'); 46 | %% The following is excluded from userguide -------------------------------------------------------------------------------- /examples/ex16.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex16'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),6,4]); 6 | %% Everything below appears in userguide 7 | s = tf('s'); 8 | bodemag(1/(s/100+1)); 9 | %% The following is excluded from userguide 10 | matlabfrag('graphics/ex16','epspad',[5 15 0 0]); -------------------------------------------------------------------------------- /examples/ex17.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','ex17'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),12,12]); 6 | %% Everything below appears in userguide 7 | subplot(2,2,1),plot([-1e-3 1e-3],1e-3*rand(2)); 8 | axis([-1e-3 1e-3 0 1e-3]); 9 | set(gca,'xaxislocation','bottom','yaxislocation','left'); 10 | % 11 | subplot(2,2,2),plot([-1e-3 1e-3],1e-3*rand(2)); 12 | axis([-1e-3 1e-3 0 1e-3]); 13 | set(gca,'xaxislocation','top','yaxislocation','left'); 14 | % 15 | subplot(2,2,3),plot([-1e-3 1e-3],1e-3*rand(2)); 16 | axis([-1e-3 1e-3 0 1e-3]); 17 | set(gca,'xaxislocation','bottom','yaxislocation','right'); 18 | % 19 | subplot(2,2,4),plot([-1e-3 1e-3],1e-3*rand(2)); 20 | axis([-1e-3 1e-3 0 1e-3]); 21 | set(gca,'xaxislocation','top','yaxislocation','right'); 22 | %% The following is excluded from userguide 23 | matlabfrag('graphics/ex17'); -------------------------------------------------------------------------------- /examples/run_all.m: -------------------------------------------------------------------------------- 1 | %% Clean up. 2 | close all; 3 | clear all; 4 | clc; 5 | %% Comparisons 6 | % Run the comparisons first, because LaPrint requires 7 | % the figure number. Seriously, wtf? 8 | if exist('laprint','file') 9 | run comparison01; 10 | close all; 11 | run comparison02; 12 | close all; 13 | else 14 | warning('run_all:noLaPrint','LaPrint not found. Skipping the comparisons'); 15 | end 16 | %% Run the scripts 17 | ii=1; 18 | while exist( sprintf('ex%02i',ii), 'file' ) 19 | run( sprintf('ex%02i',ii) ); 20 | ii = ii+1; 21 | end 22 | %% Run the extra testing scripts 23 | ii=1; 24 | while exist( sprintf('test%02i',ii), 'file' ) 25 | run( sprintf('test%02i',ii) ); 26 | ii = ii+1; 27 | end -------------------------------------------------------------------------------- /examples/test01.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test01'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),8,6]); 5 | 6 | %% 7 | plot([0,1],rand(6,2)); 8 | ylim([0,1]); 9 | hleg=legend('line 1','line 2','3','4','5','6'); 10 | h6=findobj(hleg,'string','6'); 11 | set(h6,'userdata','matlabfrag:Line6'); 12 | %% 13 | matlabfrag('graphics/test01'); -------------------------------------------------------------------------------- /examples/test02.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test02'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),8,6]); 5 | 6 | %% 7 | plot([0,1],rand(6,2)); 8 | ylim([0,1]); 9 | hleg=legend('line 1','line 2','3','4','5','6'); 10 | set(gca,'fontangle','italic'); 11 | h6=findobj(hleg,'string','6'); 12 | set(h6,'userdata','matlabfrag:Line6'); 13 | %% 14 | matlabfrag('graphics/test02'); -------------------------------------------------------------------------------- /examples/test03.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test03'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),8,6]); 5 | 6 | %% 7 | plot([0,1],rand(6,2)); 8 | hleg=legend('line 1','line 2','3','4','5','6'); 9 | ylim([0,1]); 10 | set(gca,'xticklabel',''); 11 | set(gca,'fontname','fixedwidth','fontweight','bold'); 12 | h6=findobj(hleg,'string','6'); 13 | set(h6,'userdata','matlabfrag:Line6'); 14 | %% 15 | matlabfrag('graphics/test03'); -------------------------------------------------------------------------------- /examples/test04.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test04'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),8,6]); 5 | 6 | %% 7 | plot([-1,1],rand(6,2)); 8 | ylim([0,1]); 9 | hleg=legend('line 1','line 2','3','4','5','6'); 10 | set(gca,'ytick',0:0.2:1); 11 | set(gca,'yticklabel',{'0','0.2','0.4','0.6','0.8','1'}); 12 | set(gca,'xtick',-1:0.5:1); 13 | set(gca,'xticklabel',{'-1','-0.5','0','0.5','1'}); 14 | h6=findobj(hleg,'string','6'); 15 | set(h6,'userdata','matlabfrag:Line6'); 16 | %% 17 | matlabfrag('graphics/test04'); -------------------------------------------------------------------------------- /examples/test05.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test05'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),8,6]); 5 | 6 | %% 7 | plot([-1,1],rand(6,2)); 8 | ylim([0,1]); 9 | hleg=legend('line 1','line 2','3','4','5','6'); 10 | h6=findobj(hleg,'string','6'); 11 | set(gca,'ytick',0:0.1:1,'xtick',-1:0.5:1); 12 | set(h6,'userdata','matlabfrag:Line6'); 13 | %% 14 | matlabfrag('graphics/test05'); -------------------------------------------------------------------------------- /examples/test06.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test06'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),8,6]); 5 | 6 | %% 7 | plot([0,1],rand(6,2)); 8 | ylim([0,1]); 9 | hleg=legend('line 1','line 2','3','4','5','6'); 10 | h6=findobj(hleg,'string','6'); 11 | set(h6,'userdata','matlabfrag:Line6'); 12 | set(hleg,'position',[0.3 0.3 0.3 0.3]); 13 | if exist('legendshrink','file') 14 | legendshrink(0.5); 15 | else 16 | warning('test06:noLegendShrink',... 17 | 'This test requires legendshrink to run properly'); 18 | end 19 | 20 | %% 21 | matlabfrag('graphics/test06'); -------------------------------------------------------------------------------- /examples/test07.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test07'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),5,6]); 5 | 6 | %% 7 | plot([0,1],rand(6,2)); 8 | ylim([0,1]); 9 | 10 | hleg=legend('line 1','line 2','3','4','5','6'); 11 | h6=findobj(hleg,'string','6'); 12 | set(h6,'userdata','matlabfrag:Line6'); 13 | set(gca,'fontname','palatino'); 14 | title('Title!','fontname','Helvetica','fontsize',12); 15 | 16 | %% 17 | matlabfrag('graphics/test07-painters'); 18 | matlabfrag('graphics/test07-opengl','renderer','opengl'); -------------------------------------------------------------------------------- /examples/test08.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test08'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),5,6]); 5 | 6 | %% 7 | spy; 8 | set(gca,'xticklabel','','yticklabel',''); 9 | xlabel(''); 10 | 11 | %% 12 | matlabfrag('graphics/test08-painters'); 13 | matlabfrag('graphics/test08-opengl','renderer','opengl'); -------------------------------------------------------------------------------- /examples/test09.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test09'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),8,6]); 5 | 6 | %% 7 | plot([-1 1],rand(6,2)); 8 | set(gca,'xtick',-1:0.2:1); 9 | set(gca,'ytick',0:0.25:1); 10 | set(gca,'xticklabel',{'-1' '' '' '' '' '0' '' '' '' '' '1' }); 11 | set(gca,'yticklabel',{'0' '' '0.5' '' '1'}); 12 | hleg=legend('line 1','line 2','3','4','5','6'); 13 | h6=findobj(hleg,'string','6'); 14 | set(h6,'userdata','matlabfrag:Line6'); 15 | 16 | %% 17 | matlabfrag('graphics/test09'); -------------------------------------------------------------------------------- /examples/test10.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test10'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),6,4]); 5 | 6 | %% 7 | plot([-1 1],rand(6,2)); 8 | set(gca,'xtick',[-0.5 0.5]); 9 | set(gca,'xticklabel',{'red','green'}); 10 | hleg=legend('line 1','line 2','3','4','5','6'); 11 | h6=findobj(hleg,'string','6'); 12 | set(h6,'userdata','matlabfrag:Line6'); 13 | 14 | %% 15 | matlabfrag('graphics/test10'); -------------------------------------------------------------------------------- /examples/test11.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'units','centimeters','NumberTitle','off','Name','test11'); 3 | pos = get(hfig,'position'); 4 | set(hfig,'position',[pos(1:2),6,4]); 5 | 6 | %% 7 | plot([-1 1],rand(6,2)); 8 | set(gca,'xtick',[]); 9 | hleg=legend('line 1','line 2','3','4','5','6'); 10 | h6=findobj(hleg,'string','6'); 11 | set(h6,'userdata','matlabfrag:Line6'); 12 | 13 | %% 14 | matlabfrag('graphics/test11'); -------------------------------------------------------------------------------- /examples/test12.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','test12'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),6,4]); 6 | %% Everything below appears in userguide 7 | y1 = 1e-6*rand(1,2); 8 | y2 = 1e-6*rand(1,2); 9 | x = [0 1e-3]; 10 | hax = plotyy(x,y1,x,y2); 11 | set(hax(1),'xtick',1e-3*[0 7/32 1/2 47/64 1]); 12 | set(hax(2),'ylim',[0 1e-6],'ytick',1e-6*[0 1/3 2/3 1],'yticklabelmode','auto'); 13 | set(hax(2),'xticklabel',''); 14 | %% The following is excluded from userguide 15 | matlabfrag('graphics/test12'); -------------------------------------------------------------------------------- /examples/test13.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','test13'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),6,4]); 6 | %% Everything below appears in userguide 7 | plot([0 1],rand(6,2)); 8 | set(gca,'ylim',[0 1],'xlim',[0.2 1],'xtick',0:0.25:1); 9 | matlabfrag('graphics/test13a'); 10 | set(gca,'xticklabel',{'0.00','0.25','0.50','0.75','1'}); 11 | matlabfrag('graphics/test13b') -------------------------------------------------------------------------------- /examples/test14.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','test14'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),6,4]); 6 | %% Everything below appears in userguide 7 | plot([0 1],rand(6,2)); 8 | set(gca,'ylim',[0 1],'xlim',[0 1],'xtick',0:0.2:1,'xticklabel','0|0.2||0.6\ |0.8|Unity'); 9 | matlabfrag('graphics/test14'); -------------------------------------------------------------------------------- /examples/test15.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig = figure; 3 | set(hfig,'units','centimeters','NumberTitle','off','Name','test15'); 4 | pos = get(hfig,'position'); 5 | set(hfig,'position',[pos(1:2),32,16]); 6 | %% Everything below appears in userguide 7 | plot([0 1],rand(6,2)); 8 | matlabfrag('graphics/test15'); -------------------------------------------------------------------------------- /examples/test16.m: -------------------------------------------------------------------------------- 1 | %% Preamble -- not to appear in userguide 2 | hfig(1) = figure; 3 | set(hfig(1),'units','centimeters','NumberTitle','off','Name','test16-fig1'); 4 | pos = get(hfig(1),'position'); 5 | set(hfig(1),'position',[pos(1:2),6,4]); 6 | hfig(2) = figure; 7 | set(hfig(2),'units','centimeters','NumberTitle','off','Name','test16-fig2'); 8 | pos = get(hfig(2),'position'); 9 | set(hfig(2),'position',[pos(1:2),6,4]); 10 | %% Everything below appears in userguide 11 | hax(1) = axes('parent',hfig(1)); 12 | hax(2) = axes('parent',hfig(2)); 13 | plot(hax(1),[0 1],1e-3*rand(6,2)); 14 | plot(hax(2),[0 1],1e-6*rand(6,2)); 15 | set(hax(1),'ylim',1e-3*[0 1]); 16 | set(hax(2),'ylim',1e-6*[0 1]); 17 | xlabel(hax(1),'x label');xlabel(hax(2),'x label'); 18 | ylabel(hax(1),'y label');ylabel(hax(2),'y label'); 19 | matlabfrag('graphics/test16-fig1','handle',hfig(1)); 20 | matlabfrag('graphics/test16-fig2','handle',hfig(2)); -------------------------------------------------------------------------------- /examples/test17.m: -------------------------------------------------------------------------------- 1 | set(0,'defaulttextinterpreter','latex') 2 | 3 | hfig(1) = figure; 4 | set(hfig(1),'NumberTitle','off','Name','test17-fig1'); 5 | surf(peaks(23)); 6 | xlabel('$\alpha^\beta$'); 7 | legend('$\theta = 23$'); 8 | matlabfrag('graphics/test17-fig1'); 9 | 10 | hfig(2) = figure; 11 | set(hfig(2),'NumberTitle','off','Name','test17-fig2'); 12 | surf(peaks(34)); 13 | xlabel('$\alpha^\beta$'); 14 | legend('$\theta = 34$'); 15 | matlabfrag('graphics/test17-fig2'); 16 | 17 | set(0,'defaulttextinterpreter','tex'); -------------------------------------------------------------------------------- /examples/test18.m: -------------------------------------------------------------------------------- 1 | hfig = figure; 2 | set(hfig,'NumberTitle','off','Name','test18','units','centimeters'); 3 | hpos = get(hfig,'position'); 4 | set(hfig,'position',[hpos(1:2),6,5]); 5 | plot([1e-5 1],-1e-3*rand(2,6)); 6 | set(gca,'xtick',[1e-5 1e-4 1e-3 1e-2 1e-1 1],'xscale','log'); 7 | xlabel('X label'); 8 | legend('Legend'); 9 | matlabfrag('graphics/test18-fig1','unaryminus','normal'); 10 | matlabfrag('graphics/test18-fig2','unaryminus','short'); -------------------------------------------------------------------------------- /examples/test19.m: -------------------------------------------------------------------------------- 1 | x=1:0.1:100; 2 | y=sin(x); 3 | y2=sin(x)-1; 4 | fig = figure; 5 | yyaxis left 6 | plot(x,y) 7 | title('$F_z$'); 8 | text(pi,0,'$\leftarrow \sin{x} \frac{abc}{de_f}$') 9 | xlabel('yabdxd $F_x\cdot\ y\cdot\phi$') 10 | ylabel('$\varphi$') 11 | 12 | ylim([-2 2]) 13 | 14 | yyaxis right 15 | plot(x,y2) 16 | ylabel('$\varphi_2$') 17 | l = legend({'abcyasdfasdfadsfadsfasdfa','$F_x$'}); 18 | 19 | matlabfrag('graphics/test19'); -------------------------------------------------------------------------------- /examples/testing.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,11pt]{article} 2 | 3 | \usepackage[T1]{fontenc}\usepackage{lmodern}\usepackage[sc]{mathpazo}\linespread{1.1}% Palatino font 4 | \usepackage[colorlinks,urlcolor=black,linkcolor=black]{hyperref} 5 | \usepackage{upquote,fancyvrb,subfig,microtype,sistyle,refstyle,wasysym} 6 | \usepackage[process=all,crop=preview]{pstool} 7 | 8 | \newcommand\matlabfrag{\texorpdfstring{\href{http://www.mathworks.com/matlabcentral/fileexchange/21286}{{\ttfamily matlabfrag}}}{matlabfrag}} 9 | 10 | \title{\matlabfrag\ test document} 11 | \author{Zebb Prime} 12 | 13 | \begin{document} 14 | \maketitle 15 | \begin{figure}[ht] 16 | \centering 17 | \fbox{\psfragfig{graphics/test01}} 18 | \caption{Output from {\ttfamily test01.m}; making sure multiple legend lines are printed properly.} 19 | \figlabel{test01} 20 | \end{figure} 21 | \begin{figure}[ht] 22 | \centering 23 | \fbox{\psfragfig{graphics/test02}} 24 | \caption{Output from {\ttfamily test02.m}; testing italic font for the main axes property. The 25 | tick labels aren't italic because they've been rendered in math mode.} 26 | \figlabel{test02} 27 | \end{figure} 28 | \begin{figure}[ht] 29 | \centering 30 | \fbox{\psfragfig{graphics/test03}} 31 | \caption{Output from {\ttfamily test03.m}; bold and fixed-width test with multiple legend entries.} 32 | \figlabel{test03} 33 | \end{figure} 34 | \begin{figure}[ht] 35 | \centering 36 | \fbox{\psfragfig{graphics/test04}} 37 | \caption{Output from {\ttfamily test04.m}; tick labels entered as cells.} 38 | \figlabel{test04} 39 | \end{figure} 40 | \begin{figure}[ht] 41 | \centering 42 | \fbox{\psfragfig{graphics/test05}} 43 | \caption{Output from {\ttfamily test05.m}; tick label alignment test. Y tick labels should be 44 | nicely right aligned, and x tick labels should be aligned by the numbers excluding any negative 45 | sign, if present.} 46 | % 47 | \clearpage 48 | % 49 | \figlabel{test05} 50 | \end{figure} 51 | \begin{figure}[ht] 52 | \centering 53 | \fbox{\psfragfig{graphics/test06}} 54 | \caption{Output from {\ttfamily test06.m}; legend movement test. The legend should appear slightly 55 | left and down of centre, and be shrunk to not fill its axes.} 56 | \figlabel{test06} 57 | \end{figure} 58 | \begin{figure}[ht] 59 | \centering 60 | \subfloat{\fbox{\psfragfig[crop=preview]{graphics/test07-painters}}} 61 | \quad 62 | \subfloat{\fbox{\psfragfig[crop=preview]{graphics/test07-opengl}}} 63 | \caption{Output from {\ttfamily test07.m}; different fonts test. The left image is rendered using 64 | painters, while the right is rendered using opengl.} 65 | \figlabel{test07} 66 | \end{figure} 67 | \begin{figure}[ht] 68 | \centering 69 | \subfloat{\fbox{\psfragfig[crop=preview]{graphics/test08-painters}}} 70 | \quad 71 | \subfloat{\fbox{\psfragfig[crop=preview]{graphics/test08-opengl}}} 72 | \caption{Output from {\ttfamily test08.m}; No text test. The left image is rendered using 73 | painters, while the right is rendered using opengl.} 74 | \figlabel{test08} 75 | \end{figure} 76 | \begin{figure} 77 | \centering 78 | \fbox{\psfragfig{graphics/test09}} 79 | \caption{Output from {\ttfamily test09.m}; some empty tick labels test. Some of the tick labels 80 | in both the $x$ and $y$ axes should be empty.} 81 | % 82 | \clearpage 83 | % 84 | \figlabel{test09} 85 | \end{figure} 86 | \begin{figure} 87 | \centering 88 | \fbox{\psfragfig{graphics/test10}} 89 | \caption{Output from {\ttfamily test10.m}; x-tick label vertical alignment test.} 90 | \figlabel{test10} 91 | \end{figure} 92 | \begin{figure} 93 | \centering 94 | \fbox{\psfragfig{graphics/test11}} 95 | \caption{Output from {\ttfamily test11.m}; empty x-ticks while {\ttfamily ticklabelmode} 96 | is {\ttfamily auto}.} 97 | \figlabel{test11} 98 | \end{figure} 99 | \begin{figure}[ht] 100 | \centering 101 | \fbox{\psfragfig{graphics/test12}} 102 | \caption{Output from the {\ttfamily test12.m}; scaling with unusual tick values.} 103 | \figlabel{test12} 104 | \end{figure} 105 | \begin{figure}[ht] 106 | \centering 107 | \subfloat[graphics/test13a]{ \fbox{\psfragfig{graphics/test13a} }} 108 | \quad 109 | \subfloat[graphics/test13b]{ \fbox{\psfragfig{graphics/test13b} }} 110 | \caption{Output from the {\ttfamily test13.m}; Fixed the weird bug that occurs when 111 | manually setting both [xyz]lim and [xyz]tick, with [xyz]tick values outside of [xyz]lim. 112 | Both graphics should be identical.} 113 | \figlabel{test13} 114 | \end{figure} 115 | \begin{figure}[ht] 116 | \centering 117 | \fbox{\psfragfig{graphics/test14}} 118 | \caption{Output from the {\ttfamily test14.m}; Blank strings (as opposed to empty) in the 119 | xlabel, and a space forced with {\ttfamily `$\backslash~$'} for alignment after $0.6$.} 120 | \figlabel{test14} 121 | \end{figure} 122 | % 123 | \clearpage 124 | % 125 | \begin{figure}[ht] 126 | \centering 127 | \fbox{\psfragfig[width=\linewidth]{graphics/test15}} 128 | \caption{Output from the {\ttfamily test15.m}; For very large images, make sure that the 129 | 16-bit integers in the eps file don't saturate by reducing the painters DPI.} 130 | \figlabel{test15} 131 | \end{figure} 132 | \begin{figure}[ht] 133 | \centering 134 | \subfloat[graphics/test16-fig1]{ \fbox{\psfragfig{graphics/test16-fig1} }} 135 | \quad 136 | \subfloat[graphics/test16-fig2]{ \fbox{\psfragfig{graphics/test16-fig2} }} 137 | \caption{Output from the {\ttfamily test16.m}; when exporting a figure that isn't the 138 | current one, axis scaling labels can break. Fig-1 should be scaled to $10^{-3}$, and 139 | Fig-2 should be scaled to $10^{-6}$.} 140 | \figlabel{test16} 141 | \end{figure} 142 | \begin{figure}[ht] 143 | \centering 144 | \subfloat[graphics/test17a]{ \fbox{\psfragfig{graphics/test17-fig1} }} 145 | \\ 146 | \subfloat[graphics/test17b]{ \fbox{\psfragfig{graphics/test17-fig2} }} 147 | \caption{Output from the {\ttfamily test17.m}; in some circumstances the x-label was 148 | disappearing from the image. It should be present in both cases.} 149 | \end{figure} 150 | % 151 | \clearpage 152 | % 153 | \begin{figure}[ht] 154 | \centering 155 | \subfloat[graphics/test18-fig1]{ \fbox{\psfragfig{graphics/test18-fig1} }} 156 | \quad 157 | \subfloat[graphics/test18-fig2]{ \fbox{\psfragfig{graphics/test18-fig2} }} 158 | \caption{Output from {\ttfamily test18.m}; comparison between plots using normal unary minus length in the tick axes to plots using the shorter unary minus.} 159 | \end{figure} 160 | % 161 | \clearpage 162 | % 163 | \begin{figure}[ht] 164 | \centering 165 | \subfloat[graphics/test19]{ \fbox{\psfragfig{graphics/test19} } } 166 | \caption{Test of user set math mode and double Y-axis.} 167 | \end{figure} 168 | \end{document} -------------------------------------------------------------------------------- /examples/userguide.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,11pt]{article} 2 | 3 | \usepackage[T1]{fontenc}\usepackage{lmodern}\usepackage[sc]{mathpazo}\linespread{1.1}% Palatino font 4 | \usepackage[colorlinks,urlcolor=black,linkcolor=black]{hyperref} 5 | \usepackage{upquote,fancyvrb,subfig,microtype,sistyle,refstyle,wasysym} 6 | \usepackage[process=auto,crop=pdfcrop]{pstool} 7 | 8 | \newcommand\ytick[1]{\ensuremath{\mathcal R(e^{#1 i})}} 9 | 10 | \newcommand\matlabfrag{\texorpdfstring{\href{http://www.mathworks.com/matlabcentral/fileexchange/21286}{{\ttfamily matlabfrag}}}{matlabfrag}} 11 | \newcommand\psfragname{\texorpdfstring{\href{http://www.ctan.org/tex-archive/help/Catalogue/entries/psfrag.html}{{\ttfamily psfrag}}}{psfrag}} 12 | \newcommand\pstoolname{\texorpdfstring{\href{http://www.ctan.org/tex-archive/help/Catalogue/entries/pstool.html}{{\ttfamily pstool}}}{pstool}} 13 | \newcommand\matlab{\texorpdfstring{{\sc Matlab}}{Matlab}} 14 | \newcommand\tex{\texorpdfstring{{\sc .tex}}{.tex}} 15 | \newcommand\eps{\texorpdfstring{{\sc .eps}}{.eps}} 16 | \newcommand\pdf{\texorpdfstring{{\sc .pdf}}{.pdf}} 17 | \def\'#1'{{\ttfamily \textquotesingle #1\textquotesingle}} 18 | 19 | % Get rid of that stupid S thing in section references. 20 | \newref{sec}{% 21 | name = \RSsectxt, 22 | names = \RSsecstxt, 23 | Name = \RSSectxt, 24 | Names = \RSSecstxt, 25 | refcmd = {\ref{#1}}, 26 | rngtxt = \RSrngtxt, 27 | lsttxt = \RSlsttxt} 28 | 29 | \title{\matlabfrag\ user guide} 30 | \author{Zebb Prime} 31 | 32 | \begin{document} 33 | \maketitle 34 | \tableofcontents 35 | \section{Introduction}% 36 | \matlabfrag\ is a function which exports a \matlab\ figure to \eps\ and \tex\ files for use in LaTeX 37 | with \psfragname. It is inspired by LaPrint, but is intended to be more WYSIWYG, by respecting figure 38 | handles better. The main reasons to use \matlabfrag\ are the same as those for using \psfragname: figure 39 | font matching that of the document, and the ability to have complex mathematical expressions typeset 40 | by LaTeX. 41 | 42 | \section{Background}% 43 | I wrote \matlabfrag\ after becoming frustrated with the default LaPrint behaviour, including it 44 | putting the line to insert the graphic in the output \tex\ file: \verb|\includegraphics{FileName.eps}| 45 | 46 | Whilst these problems could be addressed using one of the many options in LaPrint, I decided to 47 | take a stand against the many \matlab\ scripts and functions available which try to impose their 48 | own sense of style on my figures, and instead write a function which does everything possible to 49 | respect the figure handles. Everyone has their own sense of style, for better or worse, and I'm sure 50 | most users have their own little scripts set up to format their figures in their own way. 51 | 52 | The problem I have with the \verb|\includegraphics{FileName.eps}| line in the \tex\ 53 | file is that I keep my figures in a {\ttfamily graphics} subdirectory of my main document. This meant I had to 54 | manually edit the \tex\ file every time I exported the figure from \matlab. 55 | 56 | \section{Compared to LaPrint}% 57 | In this section I compare the output from {\ttfamily LaPrint} and \matlabfrag\ for an identical 58 | figure. I have chosen some examples that shows some of the weaknesses of {\ttfamily LaPrint}, so 59 | be sure to take these comparisons with a grain of salt. 60 | 61 | The code for the first comparison is given in\par 62 | {\verb|examples/comparison01.m|}\par\noindent 63 | and the results are shown in \Figref{comparison01}. Notice that the legend box for the LaPrint 64 | output has been shrunk, and is too small for the equation, and the y axis scale has disappeared. 65 | I am unwilling to blame {\ttfamily LaPrint} for the equation not rendering as it may by a bug 66 | in any stage of the fairly complicated conversion process (which has nothing to do with 67 | \matlabfrag). The output \tex\ and \eps\ files appear to have the text conversion set up 68 | properly. 69 | \begin{figure}[ht] 70 | \centering 71 | \subfloat[graphics/comparison01-matlabfrag]{\figlabel{comparison01-matlabfrag}% 72 | \fbox{\psfragfig{graphics/comparison01-matlabfrag}}} 73 | \, 74 | \subfloat[graphics/comparison01-laprint]{\fbox{\psfragfig{graphics/comparison01-laprint}}} 75 | \caption{\matlabfrag\ output versus {\ttfamily LaPrint} output for a simple graph. Notice the 76 | legend box for the {\ttfamily LaPrint} is incorrectly sized, and the y axis scale has 77 | disappeared. I am unsure why the equation is not rendering in the {\ttfamily LaPrint} 78 | version, and it is unlikely to be the fault of {\ttfamily LaPrint}.} 79 | \figlabel{comparison01} 80 | \end{figure} 81 | 82 | In this second comparison a scaled version of the \matlab\ {\ttfamily peaks} function is 83 | presented. The \matlab\ code for this example is given in:\par 84 | {\verb|examples/comparison02.m|}\par\noindent 85 | and the results are shown in \Figref{comparison02}. The axis labels are handled better by 86 | \matlabfrag\, and it also manages to reproduce the x and y axis scales, but I stress that they 87 | only work well for the default orientation of a {\ttfamily surf} plot. If you start rotating 88 | the image they are unlikely to come out correctly. This is discussed further in \Secref{adv-axis}. 89 | \begin{figure}[ht] 90 | \centering 91 | \subfloat[graphics/comparison02-matlabfrag]{\fbox{\psfragfig{graphics/comparison02-matlabfrag}}} 92 | \, 93 | \subfloat[graphics/comparison02-laprint]{\fbox{\psfragfig{graphics/comparison02-laprint}}} 94 | \caption{\matlabfrag\ output versus {\ttfamily LaPrint}.} 95 | \figlabel{comparison02} 96 | \end{figure} 97 | 98 | \section{Usage}% 99 | \subsection{Within \matlab}% 100 | Using \matlabfrag\ within \matlab\ is easy. Simply format the figure how you like it, then run 101 | \matlabfrag. The format for the \matlabfrag\ command is: 102 | \begin{verbatim} 103 | matlabfrag(FileName,OPTIONS) 104 | \end{verbatim} 105 | where {\ttfamily FileName} (required) is the file name for the output \tex\ and \eps\ files, and 106 | {\ttfamily OPTIONS} are key-value pairs for the optional options: 107 | \begin{itemize} 108 | \item[{\'handle'}] The handle for the figure to export. The default is {\ttfamily gcf} (`get 109 | current figure'). 110 | \item[{\'epspad'}] The number of points to pad the output \eps\ file by. The default is {\ttfamily [0,0,0,0]}. 111 | \item[{\'renderer'}] The output renderer. The default is {\ttfamily painters}. The renderer is 112 | discussed in more detail in \Secref{renderers}. 113 | \item[{\'dpi'}] The output resolution (DPI or more appropriately, PPI) of the figure. 114 | For the {\ttfamily painters} renderer this defaults to 3200, and when 115 | using the {\ttfamily opengl} or {\ttfamily zbuffer} renderers the default is 300. 116 | A discussion of renderers is given in \Secref{renderers}. 117 | \item[{\'compress'}] New in v0.7.0 is the option to compress eps files using LZW compression which is part of the EPS standard. 118 | Compression requires that the auxiliary file, {\ttfamily epscompress.c} be compiled within \matlab\ (if a binary version for your system has not been shipped with \matlabfrag), as described in \Secref{compile-epscompress}. 119 | \end{itemize} 120 | Some examples are given below.\nobreak 121 | \VerbatimInput[firstline=7,lastline=12]{ex01.m} 122 | See \Figref{ex01} for the output. 123 | \begin{figure}[ht] 124 | \centering 125 | \subfloat[graphics/ex01-1]{\fbox{\psfragfig[crop=preview]{graphics/ex01-1}}}\quad 126 | \subfloat[graphics/ex01-2]{\fbox{\psfragfig[crop=preview]{graphics/ex01-2}}} 127 | \caption{\matlabfrag\ options example showing the {\ttfamily epspad} option at work.} 128 | \figlabel{ex01} 129 | \end{figure} 130 | 131 | If you wish to show something different in \matlab\ and in the \tex\ document, then you 132 | can add it into the {\ttfamily UserData} property of the text, with a {\ttfamily matlabfrag:} prefix. This is 133 | especially useful if you have macros in LaTeX which you want to use, or if you want to use some 134 | commands not included in the \matlab\ LaTeX installation. In this example, the \verb|\LaTeX| macro 135 | typesets LaTeX as \LaTeX. 136 | \VerbatimInput[firstline=7,lastline=11]{ex02.m} 137 | See \Figref{ex02} for the output. 138 | \begin{figure}[ht] 139 | \centering 140 | \psfragfig{graphics/ex02} 141 | \caption{UserData example; X-label should say `Plays nice with \LaTeX'.} 142 | \figlabel{ex02} 143 | \end{figure} 144 | 145 | \subsection{Within LaTeX}\seclabel{in-latex}% 146 | The \tex\ and \eps\ files can be included in a LaTeX document (pdfLaTeX is treated seperately below) 147 | by either loading the \psfragname\ package and including the \tex\ file before the \eps\ file: 148 | \begin{verbatim} 149 | \documentclass{article} 150 | \usepackage{graphicx,psfrag} 151 | \begin{document} 152 | \input{FileName.tex} 153 | \includegraphics{FileName.eps} 154 | \end{document} 155 | \end{verbatim} 156 | or my preferred method; loading the \pstoolname\ package (v1.2 onwards), and using the 157 | \verb|\psfragfig| macro: 158 | \begin{verbatim} 159 | \documentclass{article} 160 | \usepackage{pstool} 161 | \begin{document} 162 | \psfragfig{FileName} 163 | \end{document} 164 | \end{verbatim} 165 | Notice the lack of a file extension in the \verb|\psfragfig| macro. This is a requirement of \pstoolname. 166 | \pstoolname\ also loads the {\ttfamily graphicx}, {\ttfamily psfrag} and {\ttfamily color} packages (as well as a few others), 167 | so it is not necessary to explicitly load these packages. 168 | 169 | For more information about \pstoolname\ or \psfragname\ please see their respective manuals. 170 | 171 | The text replacement performed by \psfragname\ occurs somewhere between the conversion from 172 | \textsc{dvi} to \textsc{ps} in some seemingly magical process that I don't understand. This means 173 | that if you look at the \textsc{dvi} output directly you will see a {\ttfamily PSFrag replacements} 174 | table next to the figure. This is normal, so do not panic. 175 | 176 | \subsection{Within pdfLaTeX}% 177 | There are several ways to include files with PostScript commands (such as \psfragname) in pdfLaTeX such 178 | as {\ttfamily pst-pdf}, {\ttfamily auto-pst-pdf}, {\ttfamily ps4pdf} and \pstoolname, by far the most useful of which is 179 | \pstoolname. The document is set up the same way as the LaTeX example above: 180 | \begin{verbatim} 181 | \documentclass{article} 182 | \usepackage{pstool} 183 | \begin{document} 184 | \psfragfig{FileName} 185 | \end{document} 186 | \end{verbatim} 187 | The only difference being that \pstoolname\ runs some external processes to run the postscript commands, 188 | and as such it needs the \verb|-shell-escape| (or possibly \verb|--shell-escape| depending upon your LaTeX distribution) command when being called:\par 189 | {\verb|pdflatex -shell-escape example.tex|}\par\noindent 190 | where {\ttfamily example.tex} is the code above. 191 | 192 | \subsection{Within LyX}\seclabel{in-lyx}% 193 | Using \matlabfrag\ withing LyX is relatively simple. The steps to setting LyX up with \pstoolname\ 194 | are: 195 | \begin{enumerate} 196 | \item Ensure \pstoolname\ is installed in your LaTeX distribution. If you wish to use \pstoolname\ 197 | with non-\textsc{pdf} output, please ensure \pstoolname\ is v1.2 or greater. 198 | \item Load \pstoolname\ in the document preamble by going to: {\ttfamily Document - Settings}, then 199 | choose {\ttfamily LaTeX Preamble} in the navigation panel in the left. Insert the line 200 | \verb|\usepackage{pstool}| and apply the settings. 201 | \item Enable \verb|-shell-escape| (or possibly \verb|--shell-escape| as mentioned above) in pdfLaTeX by going to: {\ttfamily Tools - Preferences}, then 202 | choose {\ttfamily Converters} in the navigation panel in the left. Under {\ttfamily Converter Definitions} 203 | find the {\ttfamily LaTeX (pdflatex) -> PDF (pdflatex)} entry. Below this change the line\par 204 | {\verb|pdflatex $$i|}\par\noindent 205 | to\par 206 | {\verb|pdflatex -shell-escape $$i|}\par\noindent 207 | then click {\ttfamily Modify} to the 208 | upper right, then {\ttfamily Apply} and {\ttfamily Save} down the bottom. 209 | \end{enumerate} 210 | Please note that these steps were written for LyX version 1.5.6, but they should be similar for other 211 | versions. 212 | 213 | Once \pstoolname\ is set up for use in LyX, \matlabfrag\ images can be inserted by clicking on the 214 | \TeX\ button (Insert Tex Code), and placing the {\ttfamily psfragfig} command in:\par 215 | {\verb|\psfragfig{FileName}|}\par\noindent 216 | The {\ttfamily ERT} box created with the {\ttfamily psfragfig} command inside it should be placed as you 217 | would place a normal figure, for example inside a {\ttfamily float:Figure}. 218 | 219 | Please also read the discussion at the end of \Secref{in-latex} regarding the \textsc{dvi} output. 220 | Naturally the same applies for the \textsc{dvi} output from LyX as well. 221 | 222 | \section{Creating figures in \matlab}% 223 | I am now going to suggest a few ways to manipulate figures in \matlab\ before exporting them using \matlabfrag. 224 | 225 | \subsection{Sizing}% 226 | I suggest that the first thing you do when creating a figure is setting it to the size that you want 227 | in the final document. This way the figure does not need to be resized at any stage, which prevents 228 | line sizes changing, text over-running borders, etc. This can be done within \matlab\ using: 229 | \VerbatimInput[firstline=4,lastline=10]{ex03.m} 230 | See \Figref{ex03} for the output from this example, {\ttfamily examples/ex03.m}. 231 | \begin{figure}[ht] 232 | \centering 233 | \psfragfig{graphics/ex03} 234 | \caption{Resizing example; the figure is sized to \SI{8}{cm} by \SI{3}{cm}.} 235 | \figlabel{ex03} 236 | \end{figure} 237 | 238 | \subsection{{\ttfamily Color}}% 239 | The {\ttfamily color} property is a three element vector representing the RGB colour of the text. 240 | \matlabfrag\ will respect the colour set in \matlab, but may require that you load the {\ttfamily color} 241 | package in LaTeX (\pstoolname\ implicitly loads the {\ttfamily color} package). 242 | \VerbatimInput[firstline=7,lastline=11]{ex04.m} 243 | See \Figref{ex04} for the output from this example, {\ttfamily examples/ex04.m}. 244 | \begin{figure}[ht] 245 | \centering 246 | \psfragfig{graphics/ex04} 247 | \caption{{\ttfamily Color} example; the text should be coloured.} 248 | \figlabel{ex04} 249 | \end{figure} 250 | 251 | \subsection{{\ttfamily FontSize}}% 252 | All text in \matlab\ figures has a {\ttfamily FontSize} property which \matlabfrag\ respects; the size 253 | specified in the figure is the size it will be in the LaTeX output document. 254 | \VerbatimInput[firstline=7,lastline=11]{ex05.m} 255 | See \Figref{ex05} for the output from this example, {\ttfamily examples/ex05.m}. 256 | \begin{figure}[ht] 257 | \centering 258 | \psfragfig{graphics/ex05} 259 | \caption{{\ttfamily FontSize} example; the text should be different sizes.} 260 | \figlabel{ex05} 261 | \end{figure} 262 | 263 | 264 | \subsection{{\ttfamily FontAngle}}% 265 | {\ttfamily FontAngle} is a property shared by all text in a \matlab\ figure. \matlabfrag\ respects 266 | {\ttfamily FontAngle} in that {\ttfamily italic} and {\ttfamily oblique} will be italic in the LaTeX output 267 | document. 268 | \VerbatimInput[firstline=7,lastline=11]{ex06.m} 269 | See \Figref{ex06} for the output from this example, {\ttfamily examples/ex06.m}. 270 | \begin{figure}[ht] 271 | \centering 272 | \psfragfig{graphics/ex06} 273 | \caption{{\ttfamily FontAngle} example; Oblique and Italic font should both be italic here.} 274 | \figlabel{ex06} 275 | \end{figure} 276 | 277 | \subsection{{\ttfamily FontWeight}}% 278 | Another text property from \matlab\ figures that \matlabfrag\ respects is {\ttfamily FontWeight}, such 279 | that any text set to {\ttfamily bold} will be made bold in the output LaTeX document. {\ttfamily light}, 280 | {\ttfamily demi} and {\ttfamily normal} have no effect on the font in the LaTeX output. 281 | \VerbatimInput[firstline=7,lastline=12]{ex07.m} 282 | See \Figref{ex07} for the output from this example, {\ttfamily examples/ex07.m}. 283 | \begin{figure}[ht] 284 | \centering 285 | \psfragfig{graphics/ex07} 286 | \caption{{\ttfamily FontWeight} example; bold should be bold, demi and light do not really translate to 287 | LaTeX, so they should default to normal.} 288 | \figlabel{ex07} 289 | \end{figure} 290 | 291 | \subsection{{\ttfamily FontName}}% 292 | {\ttfamily FontName} is a property that \matlabfrag\ \emph{does not} respect, with one exception. One 293 | of the basic ideas behind using \matlabfrag\ and \psfragname\ is to match the font in figures to 294 | that of the text, so it does not make sense to use this property, except when it has been set to 295 | {\ttfamily FixedWidth}, in which case the font in the output LaTeX document will be fixed-width (i.e., 296 | \verb|\ttfamily|). 297 | \VerbatimInput[firstline=7,lastline=11]{ex08.m} 298 | See \Figref{ex08} for the output from this example, {\ttfamily examples/ex08.m}. 299 | \begin{figure}[ht] 300 | \centering 301 | \psfragfig{graphics/ex08} 302 | \caption{{\ttfamily FontName} example; fixed-width should be in a typewriter font, while Comic Sans should 303 | be changed to the font of the document.} 304 | \figlabel{ex08} 305 | \end{figure} 306 | 307 | \subsection{{\ttfamily Interpreter}}% 308 | \matlab\ has three (well, two really) text interpreters that is uses to render the text. These 309 | are {\ttfamily tex}, {\ttfamily latex} and {\ttfamily none}. I generally don't recommend the use of the default 310 | {\ttfamily tex} interpreter if rendering anything mathematical and using \matlabfrag, as while the {\ttfamily tex} 311 | interpreter may render a mathematical expression fine, it may not work in LaTeX. 312 | 313 | The {\ttfamily latex} interpreter is especially useful for rendering mathematical formula. 314 | \VerbatimInput[firstline=7,lastline=11]{ex09.m} 315 | See \Figref{ex09} for the output from this example, {\ttfamily examples/ex09.m}. 316 | \begin{figure}[ht] 317 | \centering 318 | \psfragfig{graphics/ex09} 319 | \caption{{\ttfamily Interpreter} example; both equations should be the same, despite using a different 320 | interpreter in \matlab.} 321 | \figlabel{ex09} 322 | \end{figure} 323 | 324 | \subsection{Multi-line text}% 325 | Multi-line text can be entered into \matlab\ using either a cell or a two-dimensional character 326 | matrix. If using a character matrix, \matlabfrag\ preserves all of the white spaces, so if you 327 | do not wish for this to occur, use cells instead (or check out the {\ttfamily cellstr} function). 328 | 329 | \matlabfrag\ recreates multi-line text using a {\ttfamily tabular} environment. If you also use the 330 | {\ttfamily UserData} property, you will need to manually put the {\ttfamily tabular} environment in, as 331 | \matlabfrag\ will ignore any {\ttfamily UserData} that is not a string. 332 | \VerbatimInput[firstline=7,lastline=13]{ex10.m} 333 | See \Figref{ex10} for the output from this example, {\ttfamily examples/ex10.m}. 334 | \begin{figure}[ht] 335 | \centering 336 | \psfragfig{graphics/ex10} 337 | \caption{Multi-line example; three different ways to make multi-line text. 2D arrays, cells 338 | and using {\ttfamily tabular}.} 339 | \figlabel{ex10} 340 | \end{figure} 341 | 342 | \subsection{Custom tick labels}% 343 | Custom tick labels can be added directly as strings for LaTeX to interpret. In this example, 344 | the \verb|\ytick| macro has been defined in the preamble of this document as: 345 | \par{\verb|\newcommand\ytick[1]{\ensuremath{\mathcal R(e^{#1 i})}}|}\par\noindent 346 | The \matlab\ example code is: 347 | \VerbatimInput[firstline=7,lastline=12]{ex11.m} 348 | See \Figref{ex11} for the output from this example, {\ttfamily examples/ex11.m}. 349 | \begin{figure}[ht] 350 | \centering 351 | \psfragfig{graphics/ex11} 352 | \caption{Custom tick label example.} 353 | \figlabel{ex11} 354 | \end{figure} 355 | 356 | \subsection{Legends}\seclabel{legends}% 357 | Legends can, with a bit of manipulation, be used in exactly the same way as other text objects. 358 | 359 | If LaTeX strings are entered into the legend, the LaTeX interpreter can be turned 360 | on using the legend handle directly: 361 | \begin{verbatim} 362 | hleg = legend($\ddot\alpha$,$\ddot\beta$); 363 | set(hleg,'interpreter','latex'); 364 | \end{verbatim} 365 | 366 | To use the \matlabfrag\ {\ttfamily userdata} auto-substitution feature with legend texts, 367 | the text objects inside the legend need to be accessed directly. Each legend entry 368 | appears as three child objects of the legend ({\ttfamily line}, {\ttfamily marker} and 369 | {\ttfamily text} in that order), and the entries are in reverse order to that which 370 | they were entered into {\ttfamily legend} as. Knowing this order, the {\ttfamily userdata} 371 | property of the text objects can be set: 372 | \VerbatimInput[firstline=7,lastline=11]{ex12.m} 373 | If each legend string is unique, then another method is find the text object is to use 374 | the {\ttfamily findobj} function in \matlab. 375 | \VerbatimInput[firstline=12,lastline=13]{ex12.m} 376 | The output from this example, {\ttfamily examples/ex12.m}, is given in \Figref{ex12}. 377 | \begin{figure} 378 | \centering 379 | \psfragfig{graphics/ex12} 380 | \caption{Using the {\ttfamily userdata} feature with legends.} 381 | \figlabel{ex12} 382 | \end{figure} 383 | 384 | \subsection{Tick scaling values}\seclabel{axis-scaling}% 385 | Tick values automatically generated by \matlab\ may have a scaling value placed at the end 386 | of the axis. In two-dimensional plots these will be handled by \matlabfrag\ fairly well, but 387 | in some circumstances, such as three-dimensional plots, they will work badly. An example of 388 | them being automatically placed in the figure is given in \Figref{comparison02} and the file\par 389 | {\verb|examples/comparison02.m|}\par\noindent 390 | When \matlabfrag\ fails to insert the scaling properly, I suggest you manually modify the 391 | axis ticks, and place the scaling in either the axis label, or place it manually as a text 392 | object. Example code for doing this is: 393 | \VerbatimInput[firstline=7,lastline=17]{ex13.m} 394 | See \Figref{ex13} for the output from this example, {\ttfamily examples/ex13.m}. 395 | \begin{figure}[ht] 396 | \centering 397 | \psfragfig{graphics/ex13} 398 | \caption{Manually inserted axis scalings.} 399 | \figlabel{ex13} 400 | \end{figure} 401 | You can read more about why this is necessary in \Secref{adv-axis}. 402 | 403 | \section{Frequently (occasionally) asked questions}% 404 | \subsection{How do I compile \ttfamily{epscompress.c}}\seclabel{compile-epscompress} 405 | The prerequisites for compiling are a C compiler. 406 | \begin{itemize} 407 | \item In Windows, \matlab\ ships with a compiler already. 408 | \item In OSX, installing Xcode is sufficient. 409 | \item In Linux, {\ttfamily gcc} should be easily installable (if not already installed). 410 | \end{itemize} 411 | If you have not already done so, within \matlab\ you need to configure {\ttfamily mex} compilation:\par 412 | {\verb|mex -setup|}\par\noindent 413 | Finally, compile {\ttfamily epscompress.c} by navigating to the folder where you extracted \matlabfrag, and running:\par 414 | {\verb|mex epscompress.c|} 415 | 416 | \subsection{Why does the output have three digit numbers all through it?} 417 | 418 | Either you are looking at the \eps\ output and that is how it is supposed to look, 419 | or there was a problem processing the image with \psfragname. Check out the troubleshooting section 420 | below. 421 | 422 | \subsection{Why doesn't the \tex\ file have the 423 | \texorpdfstring{{\ttfamily includegraphics}}{includegraphics} statement in it like LaPrint does?} 424 | 425 | Firstly, read the Background section above. With all the image files stored in a 426 | {\ttfamily graphics} subdirectory of the main document, I would have to manually open the \tex\ file and 427 | insert the path into the that line. This was one of the reasons I wrote \matlabfrag\ in the first 428 | place. 429 | 430 | I have considered including an option to produce this output for those who would rather use this 431 | behaviour than load \pstoolname\ but decided against it due to the directory problems. From v1.2 onwards 432 | \pstoolname\ works fine in LaTeX so there really is no need to manually put the \verb|\includegraphics| 433 | line in. 434 | 435 | \section{Troubleshooting} 436 | \subsection{I get an error in \matlab!} 437 | The only errors that should be generated from \matlabfrag\ are from using it with an old version 438 | of \matlab\ or calling it with invalid parameters. Unfortunately the error messages generated from 439 | the {\ttfamily inputParser} class are a bit cryptic, but you should be able to work out if it is a 440 | parameter error. A simple way to check this is to use an example that is known to work. 441 | 442 | If using a version of \matlab\ older than v7, you will receive a parse error, rather than a sane 443 | error message telling you your version of matlab is too old. An example of this error is: 444 | \begin{verbatim} 445 | "identifier" expected, "(" found. 446 | \end{verbatim} 447 | As this is a parse error, it occurs before any code in the script has run, hence I am unable to 448 | output a sane error message. The only way to output a sane error message in such an old version 449 | of \matlab\ would be to rewrite \matlabfrag\ so that it doesn't use anonymous functions, which I 450 | don't want to do. 451 | 452 | No other errors should be generated by \matlabfrag. If you encounter one it is most likely a bug. 453 | Please email the smallest self-contained example that reproduces the bug to me at 454 | \par\noindent{\ttfamily zebb.prime+matlabfrag@gmail.com} 455 | 456 | \subsection{I get a warning in \matlab!} 457 | Warnings created by \matlabfrag\ are there for a reason. Read through them, as they explain what 458 | the problem is and what \matlabfrag\ is doing about it. 459 | 460 | \subsection{I get the {\ttfamily Unable to interpret TeX string} warning in \matlab!} 461 | This warning occurs when the TeX or LaTeX interpreter (whichever is chosen) cannot 462 | interpret the string, and can be caused by calling macros which don't exist in 463 | the version of LaTeX that ships with \matlab\ or by trying to interpret a LaTeX string 464 | with the TeX interpreter (and vice versa). 465 | 466 | To troubleshoot, ensure the string is correct, and the appropriate interpreter is used. 467 | An example known to work is: 468 | \begin{verbatim} 469 | title('Force versus $\sin(\alpha)$','interpreter','latex'); 470 | \end{verbatim} 471 | The {\ttfamily none} interpreter can also be used, however the box around the text may end up 472 | a very different size to the final text. The following example also works, but the bounding box 473 | in \matlab\ is much wider than in the final document: 474 | \begin{verbatim} 475 | title('Force versus $\sin(\alpha)$','interpreter','none'); 476 | \end{verbatim} 477 | Another alternative is to use the {\ttfamily userdata} 478 | feature of \matlabfrag\ with a placeholder for the screen text. A working example is: 479 | \begin{verbatim} 480 | title('Force versus sin(a)','userdata',... 481 | 'matlabfrag:Force versus $\sin(\alpha)$'); 482 | \end{verbatim} 483 | This is also a good option for using macros that aren't included with the version of LaTeX 484 | that ships with \matlab. For example, in \Secref{legends}, the \verb|\SI| macro is used to format the 485 | numbers and units. The package that provides this command, {\ttfamily sistyle}, is loaded 486 | in the preamble of this document. 487 | 488 | As this warning has to do with the way \matlab\ renders text on screen and not \matlabfrag, 489 | please do not contact me about it. 490 | 491 | \subsection{My graphic exports from \matlab\ fine, but does not compile in LaTeX/pdfLaTeX/LyX!} 492 | \begin{enumerate} 493 | \item Check that all LaTeX statements in your figure are valid. If you are having problems, try a 494 | simple example that is known to work. 495 | \item If you have manually loaded the {\ttfamily graphicx} package, make sure you don't have a 496 | driver (e.g. {\ttfamily pdftex}) specified. 497 | \item If using pdfLaTeX and \pstoolname, check: 498 | \begin{enumerate} 499 | \item \verb|-shell-escape| option (or possibly \verb|--shell-escape| depending upon your LaTeX distribution) is set when calling pdfLaTeX. 500 | \end{enumerate} 501 | \item If using LaTeX and \pstoolname, check: 502 | \begin{enumerate} 503 | \item \pstoolname\ is at least at version 1.2. An alternative location to finding \pstoolname\ is 504 | \url{http://github.com/wspr/pstool/}. 505 | \end{enumerate} 506 | \item If using LaTeX or pdfLaTeX with anything else: 507 | \begin{enumerate} 508 | \item Install \pstoolname ! 509 | \end{enumerate} 510 | \item If using LyX: 511 | \begin{enumerate} 512 | \item Check to see if the \pstoolname\ package is loading by going to {\ttfamily Document -- LaTeX log}, 513 | and trying to find the \pstoolname\ entry. If it is not found then try repeating the instructions 514 | in \Secref{in-lyx}. If it is there, check to see if it is issuing a warning that \verb|-shell-escape| 515 | is disabled. If so, follow the instructions in \Secref{in-lyx}. 516 | \end{enumerate} 517 | \end{enumerate} 518 | 519 | \subsection{My graphic exports from \matlab\ and compiles in LaTeX/\texorpdfstring{\\}{}pdfLaTeX/LyX but doesn't look right!} 520 | \begin{enumerate} 521 | \item If you use a {\ttfamily includegraphics} option such as {\ttfamily rotate}, there is a bug 522 | in \pstoolname\ prior to v1.2b that caused the option to be applied twice. 523 | \item The text is running over lines or is cut out! 524 | \begin{enumerate} 525 | \item This most likely happens if you resize the image in LaTeX using a \verb|[width=x]| argument. 526 | It is usually better to size the image in \matlab\ in the first place, and do no further resizing. 527 | If you are having problems with a small figure size in \matlab\ cutting off axes labels, try manually positioning the axes within the figure. 528 | \item If you have mathematical equations, use the {\ttfamily latex} interpreter. This will make the 529 | text object be roughly the right size, which will let \matlab\ place it properly. This is 530 | especially useful for legends, as shown in \Figref{comparison01-matlabfrag}. 531 | \item If the text appears to be cropped from the outside of the graphic then try padding the \eps\ 532 | file using the {\ttfamily epspad} option, or try the {\ttfamily pdfcrop} option 533 | for \pstoolname:\par 534 | {\verb|\usepackage[crop=pdfcrop]{pstool}|} 535 | \end{enumerate} 536 | \item A complicated graphic appears different on screen than it does in the document. 537 | \begin{enumerate} 538 | \item This is most likely an issue caused by a renderer. For more information, read the discussion 539 | on renderers in \Secref{renderers}. 540 | \end{enumerate} 541 | \end{enumerate} 542 | 543 | \section{Advanced usage: a discussion on renderers}\seclabel{renderers}% 544 | \matlab\ has three different renderers that it uses to render a graphic on screen; {\ttfamily Painters}, 545 | {\ttfamily OpenGL}, and {\ttfamily Z-Buffer}. Of these, only the {\ttfamily Painters} renderer can export 546 | an image in a native text format which is needed for the text substitution process. If one of the 547 | other renderers is used the text becomes rasterised, and hence normally no text replacement can take place. 548 | 549 | As of \matlabfrag\ {\ttfamily v0.6.0}\footnote{There have been a series of bug fixes since 550 | {\ttfamily v0.6.0}, so I always recommend using the latest version.}, 551 | an {\ttfamily EXPORTFIG} and {\ttfamily epscombine} style hack 552 | has been included, which manually places text objects inside rasterised \eps\ images. The result of this 553 | is that text can now be substituted with LaTeX font and code, but also that all the text now appears 554 | in the foreground (i.e. all text appears in front of the image, regardless of its placement in the 555 | original image). 556 | 557 | A downside to placing a rasterised image inside an \eps\ file is that it is uncompressed, which creates 558 | a very large \eps\ file. However, during the conversion to {\ttfamily pdf} the image is compressed to a 559 | reasonable file size. If you are using \pstoolname, from {\ttfamily v1.3} it defaults to a lossless 560 | compression technique similar to \textsc{png}. This is the most suitable compression for technical 561 | graphics, but should you prefer it, lossy compression can be turned on. For more information, refer to 562 | the \pstoolname\ documentation. 563 | 564 | When printing a rasterised image, the resolution is set using the {\ttfamily dpi} option in \matlabfrag. 565 | The default is 300 for {\ttfamily OpenGL} and {\ttfamily Z-Buffer} rendered images, which is usually 566 | considered to be print quality. The default for the {\ttfamily Painters} renderer is 3200. Using a large 567 | {\ttfamily dpi} value for {\ttfamily Painters} rendered images reduces quantisation error while only 568 | increasing the file size by a small amount. 569 | 570 | By default \matlabfrag\ will use the {\ttfamily Painters} renderer unless either the figure has had 571 | the renderer manually set (which causes the {\ttfamily renderermode} property to become {\ttfamily manual}), 572 | or the {\ttfamily renderer} option is set in \matlabfrag. 573 | 574 | An example of choosing the renderer in \matlabfrag, and increasing the image DPI is given in 575 | \par{\verb|examples/ex14.m|}\par\noindent 576 | an extract of which is: 577 | \VerbatimInput[firstline=7,lastline=15]{ex14.m} 578 | The output for this example is given in \Figref{ex14}. 579 | \begin{figure}[ht] 580 | \centering 581 | \psfragfig{graphics/ex14} 582 | \caption{Example showing the use of the {\ttfamily OpenGL} renderer.} 583 | \figlabel{ex14} 584 | \end{figure} 585 | 586 | An example showing \matlabfrag\ detecting a manually set renderer is given in 587 | \par{\verb|examples/ex15.m|}\par\noindent 588 | which is largely based off of the ``Moving the Camera Through a Scene'' example in the \matlab\ 589 | documentation. An extract of this example is: 590 | \VerbatimInput[firstline=41,lastline=45]{ex15.m} 591 | The output from this example is given in \Figref{ex15}. 592 | \begin{figure}[ht] 593 | \centering 594 | \psfragfig{graphics/ex15} 595 | \caption{Example output when the renderer is set to {\ttfamily zbuffer} and shading set to 596 | {\ttfamily phong}.} 597 | \figlabel{ex15} 598 | \end{figure} 599 | 600 | \section{Advanced usage: a discussion on axis ticks}\seclabel{adv-axis}% 601 | Easily the hardest part about writing \matlabfrag\ has been dealing with axis ticks. Their positioning 602 | and circumstances when the labels are modified are completely hidden from the user. For example, if the 603 | axis is logarithmic, and the ticks occur at powers of 10, then the {\ttfamily xticklabel} properties 604 | are written as the power of ten (e.g. 2) and rendered as the 10 to the power of the number (e.g. $10^2$). 605 | \matlabfrag\ handles this case by detecting whether {\ttfamily xscale} is set to {\ttfamily log}, and 606 | {\ttfamily xticklabelmode} is set to {\ttfamily auto}. If so, it automatically inserts the appropriate 607 | LaTeX code. A simple example of this behaviour can be shown with the code: 608 | \VerbatimInput[firstline=7,lastline=8]{ex16.m} 609 | from {\ttfamily examples/ex16.m}, which produces \Figref{ex16}. 610 | \begin{figure}[ht] 611 | \centering 612 | \psfragfig{graphics/ex16} 613 | \caption{An example {\ttfamily bodemag} plot demonstrating ticks of the format $10^x$. Note that 614 | the axis tick labels are grey. This is due to the {\ttfamily bodemag} function setting them grey 615 | using the {\ttfamily xcolor} and {\ttfamily ycolor} axis properties.} 616 | \figlabel{ex16} 617 | \end{figure} 618 | 619 | The above case is fairly simple in comparison to how \matlab\ handles axes that have been scaled by 620 | a power of ten. For example, if $x\in[0\quad10^{-3}]$, then the x ticks would read, say 621 | $[0\quad0.5\quad1]$, and a $\times10^{-3}$ would be placed to the lower right of the x axis. 622 | Unfortunately, this $\times10^{-3}$ text object is completely hidden from the user, and as soon as 623 | the tick labels are modified by the user it disappears. Both \matlabfrag\ and {\ttfamily LaPrint} 624 | have to modify the tick labels to make it possible for \psfragname\ to do text substitution, thus 625 | we have to manually recreate this scaling. In \matlabfrag\ this is performed by detecting when: 626 | \begin{enumerate} 627 | \item {\ttfamily xticklabelmode} is set to {\ttfamily auto}, and 628 | \item there is a scaling value between the {\ttfamily xtick} and {\ttfamily xticklabel} that is 629 | equal to a power of ten. 630 | \end{enumerate} 631 | In these circumstances, \matlabfrag\ does its best to place the scaling value in the most appropriate 632 | location. For two-dimensional graphs this isn't too bad, but for three-dimensional plots it is very 633 | difficult. 634 | 635 | The locations for all of the scaling values for all permutations of x and y axis locations 636 | in a two dimensional plot are shown in \Figref{ex17}. The code for this example is given in:\par 637 | {\verb|examples/ex17.m|}. 638 | \begin{figure}[ht] 639 | \centering 640 | \psfragfig{graphics/ex17} 641 | \caption{Axis scale positions for all permutations of the x and y axis locations.} 642 | \figlabel{ex17} 643 | \end{figure} 644 | 645 | Lastly, support for tick scaling in three-dimensional plots has been added to \matlabfrag\ for 646 | the default orientation of {\ttfamily surf} plots, such as that shown previously in 647 | \Figref{comparison02}. If you start to rotate the orientation of the plot it will probably break 648 | horribly. In these circumstances I suggest you manually place the scaling in the axis label, or 649 | as a text object. Please read through \Secref{axis-scaling} for some information and an example 650 | of how to do this. 651 | 652 | \end{document} -------------------------------------------------------------------------------- /matlabfrag.m: -------------------------------------------------------------------------------- 1 | % function matlabfrag(FileName,OPTIONS) 2 | % Exports a matlab figure to an .eps file and a .tex file for use with 3 | % psfrag in LaTeX. It provides similar functionality to Laprint, but 4 | % with an emphasis on making it more WYSIWYG, and respecting the handle 5 | % options for any given text, such as fontsize, fontweight, fontangle, 6 | % etc. 7 | % 8 | % .tex file entries can be overridden by placing a string in the 9 | % 'UserData' field of the text handle, prefixed by 'matlabfrag:'. 10 | % 11 | % For use in pdflatex, I recommend the pstool package. 12 | % 13 | % INPUTS 14 | % FileName (Required) - A string containting the name of the output files. 15 | % OPTIONS (Optional) - additional options are added in 'key' and 'value' 16 | % pairs 17 | % Key | Value 18 | % ---------------------------------------------------------------------- 19 | % 'handle' | Figure to create the .eps and .tex files from. 20 | % | default is gcf (current figure handle) 21 | % 'epspad' | [Left,Bottom,Right,Top] - Pad the eps figure by 22 | % | the number of points in the input vector. Default 23 | % | is [0,0,0,0]. 24 | % 'renderer' | ['painters'|'opengl'|'zbuffer'] - The renderer used 25 | % | to generate the figure. The default is 'painters'. 26 | % | If you have manually specified the renderer, 27 | % | matlabfrag will use this value. 28 | % 'dpi' | DPI to print the images at. Default is 300 for OpenGL 29 | % | or Z-Buffer images, and 3200 for painters images. 30 | % 'compress' | [0|1|true|false] - whether to compress the resulting 31 | % | eps file or not. Default is true (compression on). 32 | % 'unaryminus' | ['normal'|'short'] - whether to use a short or normal 33 | % | unary minus sign on tick labels. Default is 'normal'. 34 | % 35 | % EXAMPLE 36 | % plot(1:10,rand(1,10)); 37 | % set(gca,'FontSize',8); 38 | % title('badness $\phi$','interpreter','latex','fontweight','bold'); 39 | % xlabel('1 to 10','userdata','matlabfrag:\macro'); 40 | % ylabel('random','fontsize',14); 41 | % matlabfrag('RandPlot','epspad',[5,0,0,0],'compress',false); 42 | % 43 | % v0.7.0devb04 30-May-2013 44 | % 45 | % Please report bugs as issues on github. 46 | % 47 | % Released on the Matlab File Exchange 48 | 49 | function matlabfrag(FileName,varargin) 50 | 51 | % Nice output if the user calls matlabfrag without any parameters. 52 | if nargin == 0 53 | help matlabfrag 54 | return; 55 | end 56 | 57 | % Matlab version check 58 | v = version; 59 | v = regexp(v,'(\d+)\.(\d+)\.\d+\.\d+','tokens'); 60 | v = str2double(v{1}); 61 | if v(1) < 7 62 | error('matlabfrag:oldMatlab','Matlabfrag requires Matlab r2007a or newer to run'); 63 | elseif v(1) == 7 64 | if v(2) < 4 65 | error('matlabfrag:oldMatlab','Matlabfrag requires Matlab r2007a or newer to run'); 66 | end 67 | end 68 | 69 | % Version information is taken from the above help information 70 | HelpText = help('matlabfrag'); 71 | LatestVersion = regexp(HelpText,'(v[\d\.]+\w*?) ([\d]+\-[\w]+\-[\d]+)','tokens'); 72 | LatestVersion = LatestVersion{1}; 73 | Version = LatestVersion{1}; 74 | VersionDate = LatestVersion{2}; 75 | TEXHDR = sprintf('%% Generated using matlabfrag\n%% Version: %s\n%% Version Date: %s\n%% Author: Zebb Prime',... 76 | Version,VersionDate); 77 | 78 | % Global macros 79 | REPLACEMENT_FORMAT = '%03d'; 80 | USERDATA_PREFIX = 'matlabfrag:'; 81 | NEGTICK_SHORT_COMMAND = 'matlabfragNegTickShort'; 82 | NEGTICK_SHORT_SCRIPT_COMMAND = 'matlabfragNegTickShortScript'; 83 | NEGTICK_NO_WIDTH_COMMAND = 'matlabfragNegTickNoWidth'; 84 | ACTION_FUNC_NAME = @(x) sprintf('f%i',x); 85 | ACTION_DESC_NAME = @(x) sprintf('d%i',x); 86 | 87 | % Debug macro levels 88 | KEEP_TEMPFILE = 1; 89 | SHOW_OPTIONS = 1; 90 | PAUSE_BEFORE_PRINT = 2; 91 | PAUSE_AFTER_PRINT = 2; 92 | STEP_THROUGH_ACTIONS = 3; 93 | 94 | p = inputParser; 95 | p.FunctionName = 'matlabfrag'; 96 | 97 | p.addRequired('FileName', @(x) ischar(x) ); 98 | p.addParameter('handle', gcf, @(x) ishandle(x) && strcmpi(get(x,'Type'),'figure') ); 99 | p.addParameter('epspad', [0,0,0,0], @(x) isnumeric(x) && (all(size(x) == [1 4])) ); 100 | p.addParameter('renderer', 'painters', ... 101 | @(x) any( strcmpi(x,{'painters','opengl','zbuffer'}) ) ); 102 | p.addParameter('dpi', 300, @(x) isnumeric(x) ); 103 | p.addParameter('compress',1, @(x) (isnumeric(x) || islogical(x) ) ); 104 | p.addParameter('debuglvl',0, @(x) isnumeric(x) && x>=0); 105 | p.addParameter('unaryminus','normal', @(x) any( strcmpi(x,{'short','normal'}) ) ); 106 | p.parse(FileName,varargin{:}); 107 | 108 | if p.Results.debuglvl >= SHOW_OPTIONS 109 | fprintf(1,'OPTION: FileName = %s\n',p.Results.FileName); 110 | fprintf(1,'OPTION: handle = %f\n',p.Results.handle); 111 | fprintf(1,'OPTION: epspad = [%i %i %i %i]\n',p.Results.epspad); 112 | fprintf(1,'OPTION: renderer = %s\n',p.Results.renderer); 113 | fprintf(1,'OPTION: dpi = %i\n',p.Results.dpi); 114 | fprintf(1,'OPTION: debuglvl = %i\n',p.Results.debuglvl); 115 | fprintf(1,'OPTION: compress = %i\n',p.Results.compress); 116 | fprintf(1,'OPTION: unaryminus = %s\n',p.Results.unaryminus); 117 | fprintf(1,'OPTION: Parameters using their defaults:'); 118 | fprintf(1,' %s',p.UsingDefaults{:}); 119 | fprintf(1,'\n'); 120 | end 121 | 122 | if FigureHasNoText(p) 123 | return; 124 | end 125 | 126 | % Tick unary minus commands. Used to have a zero width X minus (for nice 127 | % alignment), and shorter minus signs if requested. 128 | if strcmpi(p.Results.unaryminus,'short') 129 | writeOutNegTickNoWidth = @(fid) fprintf(fid,'\n\\providecommand\\%s{\\scalebox{0.6}[1]{\\makebox[0pt][r]{\\ensuremath{-}}}}%%',NEGTICK_NO_WIDTH_COMMAND); 130 | writeOutNegTickShort = @(fid) fprintf(fid,'\n\\providecommand\\%s{\\scalebox{0.6}[1]{\\ensuremath{-}}}%%',NEGTICK_SHORT_COMMAND); 131 | writeOutNegTickShortScript = @(fid) fprintf(fid,'\n\\providecommand\\%s{\\scalebox{0.6}[1]{\\ensuremath{\\scriptstyle -}}}%%',NEGTICK_SHORT_SCRIPT_COMMAND); 132 | else 133 | writeOutNegTickNoWidth = @(fid) fprintf(fid,'\n\\providecommand\\%s{\\makebox[0pt][r]{\\ensuremath{-}}}%%',NEGTICK_NO_WIDTH_COMMAND); 134 | end 135 | 136 | % Create Action and UndoAction structures, and initialise the length field 137 | % to 0. 138 | Actions.length = 0; 139 | UndoActions.length = 0; 140 | StringCounter = 0; 141 | 142 | % PsfragCmds are currently in the order: 143 | % {LatexString, ReplacementString, Alignment, TextSize, Colour, 144 | % FontAngle (1-italic,0-normal), FontWeight (1-bold,0-normal), 145 | % FixedWidth (1-true,0-false), LabelType } 146 | PsfragCmds = {}; 147 | 148 | % Before doing anthing to the figure, make sure it is fully drawn 149 | drawnow; 150 | 151 | % Set up the page size to be printed 152 | Units = get(p.Results.handle,'Units'); 153 | set(p.Results.handle,'Units','centimeters'); 154 | Pos = get(p.Results.handle,'Position'); 155 | set(p.Results.handle,'Units',Units); 156 | SetUnsetProperties('PaperUnits to cm, PaperPos to Pos',p.Results.handle,... 157 | 'PaperUnits','centimeters','PaperPosition',Pos); 158 | 159 | % Process the picture 160 | ProcessFigure(p.Results.handle); 161 | 162 | % Apply the actions resulting from the processing 163 | if p.Results.debuglvl >= STEP_THROUGH_ACTIONS 164 | disp('STEPPING: Starting to apply actions'); 165 | for ii=1:Actions.length 166 | fprintf(1,'STEPPING: Press space to apply: %s\n',Actions.( ACTION_DESC_NAME(ii) )); 167 | pause; 168 | Actions.( ACTION_FUNC_NAME(ii) )(); 169 | end 170 | disp('STEPPING: Finished applying actions'); 171 | else 172 | for ii=1:Actions.length 173 | Actions.( ACTION_FUNC_NAME(ii) )(); 174 | end 175 | end 176 | 177 | if p.Results.debuglvl >= PAUSE_BEFORE_PRINT 178 | disp('PAUSING: Paused before printing'); 179 | pause; 180 | end 181 | 182 | % Test to see if the directory (if specified) exists 183 | [pathstr,namestr] = fileparts(FileName); 184 | if ~isempty(pathstr) 185 | currentdir = pwd; 186 | try 187 | cd(pathstr); 188 | catch 189 | % Create it if it doesn't exist 190 | mkdir(pathstr); 191 | cd(pathstr); 192 | end 193 | % Tidy up the string 194 | pathstr = pwd; 195 | cd(currentdir); 196 | FileName = [pathstr,filesep,namestr]; 197 | else 198 | FileName = namestr; 199 | end 200 | 201 | dpiswitch = ['-r',num2str( round( p.Results.dpi ) )]; 202 | % Unless over-ridden, check to see if 'renderermode' is 'manual' 203 | renderer = lower( p.Results.renderer ); 204 | if any( strcmpi(p.UsingDefaults,'renderer') ) 205 | if strcmpi(get(p.Results.handle,'renderermode'),'manual') 206 | renderer = lower( get(p.Results.handle,'renderer') ); 207 | if p.Results.debuglvl >= SHOW_OPTIONS 208 | fprintf(1,['OPTION: Renderer being overridden by manual renderermode.\n',... 209 | ' It is now %s.\n'],renderer); 210 | end 211 | end 212 | end 213 | 214 | if strcmpi(renderer,'painters') 215 | % If using default dpi 216 | if any( strcmpi(p.UsingDefaults,'dpi') ) 217 | current_dpi = 3200; 218 | else 219 | current_dpi = p.Results.dpi; 220 | end 221 | 222 | % Test to see whether the DPI is too high or not. 223 | temp_units = get(p.Results.handle,'units'); 224 | set(p.Results.handle,'units','inches'); 225 | temp_pos = get(p.Results.handle,'position'); 226 | set(p.Results.handle,'units',temp_units); 227 | 228 | if temp_pos(3) * current_dpi > 32000 229 | old_dpi = current_dpi; 230 | current_dpi = 100*floor((30000 / temp_pos(3))/100); 231 | warning('matlabfrag:ImageTooWide',... 232 | ['Figure width is too large for %i DPI. Reducing\n',... 233 | 'it to %i DPI.'],old_dpi,current_dpi); 234 | end 235 | 236 | if temp_pos(4) * current_dpi > 32000 237 | old_dpi = current_dpi; 238 | current_dpi = 100*floor((30000 / temp_pos(4))/100); 239 | warning('matlabfrag:defaultDPI:ImageTooHigh',... 240 | ['Figure height is too large for %i DPI. Reducing\n',... 241 | 'it to %i DPI.'],old_dpi,current_dpi); 242 | end 243 | 244 | dpiswitch = sprintf('-r%i',current_dpi); 245 | clear temp_units temp_pos current_dpi old_dpi 246 | 247 | % Export the image to an eps file 248 | drawnow; 249 | print(p.Results.handle,'-depsc2','-loose',dpiswitch,'-painters',FileName); 250 | FileWait( [FileName,'.eps'] ); 251 | else 252 | % If using the opengl or zbuffer renderer 253 | EpsCombine(p.Results.handle,renderer,FileName,dpiswitch,... 254 | p.Results.debuglvl>=KEEP_TEMPFILE) 255 | end 256 | 257 | if p.Results.debuglvl >= PAUSE_AFTER_PRINT 258 | disp('PAUSING: Paused after printing'); 259 | pause; 260 | end 261 | 262 | % Pad the eps if requested 263 | if any( p.Results.epspad ) 264 | fh = fopen([FileName,'.eps'],'r'); 265 | epsfile = fread(fh,inf,'uint8=>char').'; 266 | fclose(fh); 267 | bb = regexpi(epsfile,'\%\%BoundingBox:\s+(-*\d+)\s+(-*\d+)\s+(-*\d+)\s+(-*\d+)','tokens'); 268 | bb = str2double(bb{1}); 269 | epsfile = regexprep(epsfile,sprintf('%i(\\s+)%i(\\s+)%i(\\s+)%i',bb),... 270 | sprintf('%i$1%i$2%i$3%i',bb+round(p.Results.epspad.*[-1,-1,1,1]))); 271 | fh = fopen([FileName,'.eps'],'w'); 272 | fwrite(fh,epsfile); 273 | fclose(fh); 274 | end 275 | 276 | % Compress the eps if requested 277 | if p.Results.compress 278 | if exist('epscompress','file') ~= 3 279 | if ~any( strcmpi(p.UsingDefaults,'compress') ) 280 | warning('matlabfrag:epscompress:NotFound',... 281 | ['Cannot find a compiled version of epscompress, thus the eps\n',... 282 | 'file will not be compressed. To compile epscompress, in Matlab\n',... 283 | 'navigate to the matlabfrag folder and run:\n',... 284 | ' >> mex -setup %% If mex hasn''t been setup before\n',... 285 | ' >> mex epscompress.c\n\n',... 286 | 'Suppress this warning in the future by running:\n',... 287 | ' >> warning off matlabfrag:epscompress:NotFound\n',... 288 | 'or turning the ''compress'' option off.']); 289 | end 290 | else 291 | try 292 | movefile([FileName,'.eps'],[FileName,'-uncompressed.eps']); 293 | epscompress([FileName,'-uncompressed.eps'],[FileName,'.eps']); 294 | delete([FileName,'-uncompressed.eps']); 295 | catch 296 | warning(['epscompress of ',FileName,'-uncompressed.eps',' failed!']) 297 | end 298 | end 299 | end 300 | 301 | % Apply the undo action to restore the image to how 302 | % was originally 303 | if p.Results.debuglvl >= STEP_THROUGH_ACTIONS 304 | disp('Starting to apply undo actions'); 305 | for ii=UndoActions.length:-1:1 306 | fprintf(1,'Press space to unapply: %s\n',UndoActions.( ACTION_DESC_NAME(ii) )); 307 | pause; 308 | UndoActions.( ACTION_FUNC_NAME(ii) )(); 309 | end 310 | disp('Finished applying undo actions'); 311 | else 312 | for ii=UndoActions.length:-1:1 313 | UndoActions.( ACTION_FUNC_NAME(ii) )(); 314 | end 315 | end 316 | 317 | % Flush all drawing operations 318 | drawnow; 319 | 320 | % Sort by text size first 321 | [Y,I] = sortrows( cell2mat( PsfragCmds(:,4) ) ); %#ok<*ASGLU> Required for backward compatibility 322 | PsfragCmds = PsfragCmds(I,:); 323 | % Now sort by colour 324 | [Y,I] = sortrows( cell2mat( PsfragCmds(:,5) ), [3 2 1] ); 325 | PsfragCmds = PsfragCmds(I,:); 326 | % Now sort by font angle 327 | [Y,I] = sortrows( cell2mat( PsfragCmds(:,6) ) ); 328 | PsfragCmds = PsfragCmds(I,:); 329 | % Now sort by font weight 330 | [Y,I] = sortrows( cell2mat( PsfragCmds(:,7) ) ); 331 | PsfragCmds = PsfragCmds(I,:); 332 | % Now sort by whether it is 'fixed width' 333 | [Y,I] = sortrows( cell2mat( PsfragCmds(:,8) ) ); 334 | PsfragCmds = PsfragCmds(I,:); 335 | % Now sort by label type 336 | [Y,I] = sortrows( PsfragCmds(:,9) ); 337 | PsfragCmds = PsfragCmds(I,:); 338 | clear Y 339 | 340 | % Finally write the latex-file 341 | try 342 | fid = fopen([FileName,'.tex'],'w'); 343 | fwrite(fid,TEXHDR); 344 | 345 | FontStylePrefix = 'matlabtext'; 346 | FontStyleId = double('A')-1; 347 | NewFontStyle = 1; 348 | CurrentColour = [0 0 0]; 349 | CurrentFontSize = 0; 350 | CurrentWeight = 0; 351 | CurrentAngle = 0; 352 | CurrentlyFixedWidth = 0; 353 | CurrentType = PsfragCmds{1,9}; 354 | 355 | fprintf(fid,'\n%%'); 356 | if strcmpi( p.Results.unaryminus, 'short' ) 357 | writeOutNegTickShort(fid); 358 | writeOutNegTickShortScript(fid); 359 | end 360 | writeOutNegTickNoWidth(fid); 361 | 362 | fprintf(fid,'\n%%\n%%%% <%s>',CurrentType); 363 | for ii=1:size(PsfragCmds,1) 364 | % Test to see if the font size has changed 365 | if ~(CurrentFontSize == PsfragCmds{ii,4}) 366 | CurrentFontSize = PsfragCmds{ii,4}; 367 | NewFontStyle = 1; 368 | end 369 | % Test to see if the colour has changed 370 | if ~all(CurrentColour == PsfragCmds{ii,5}) 371 | CurrentColour = PsfragCmds{ii,5}; 372 | NewFontStyle = 1; 373 | end 374 | % Test to see if the font angle has changed 375 | if ~(CurrentAngle == PsfragCmds{ii,6}) 376 | CurrentAngle = PsfragCmds{ii,6}; 377 | NewFontStyle = 1; 378 | end 379 | % Test to see if the font weight has changed 380 | if ~(CurrentWeight == PsfragCmds{ii,7}) 381 | CurrentWeight = PsfragCmds{ii,7}; 382 | NewFontStyle = 1; 383 | end 384 | % Test to see if 'fixedwidth' has changed 385 | if ~(CurrentlyFixedWidth == PsfragCmds{ii,8}) 386 | CurrentlyFixedWidth = PsfragCmds{ii,8}; 387 | NewFontStyle = 1; 388 | end 389 | % Test to see if 'type' has changed 390 | if ~strcmpi(CurrentType,PsfragCmds{ii,9}) 391 | fprintf(fid,'\n%%\n%%%% ',CurrentType); 392 | CurrentType = PsfragCmds{ii,9}; 393 | fprintf(fid,'\n%%\n%%%% <%s>',CurrentType); 394 | if ~NewFontStyle 395 | fprintf(fid,'\n%%'); 396 | end 397 | end 398 | if NewFontStyle 399 | FontStyleId = FontStyleId + 1; 400 | if CurrentAngle; Angle = '\itshape'; 401 | else Angle = ''; end; 402 | if CurrentWeight; Weight = '\bfseries\boldmath'; 403 | else Weight = ''; end; 404 | if CurrentlyFixedWidth; Fixed = '\ttfamily'; 405 | else Fixed = ''; end; 406 | fprintf(fid,['\n%%\n\\providecommand\\%s%s{\\color[rgb]{%.3f,%.3f,'... 407 | '%.3f}\\fontsize{%.2f}{%.2f}%s%s%s\\selectfont\\strut}%%'],FontStylePrefix,... 408 | char(FontStyleId),CurrentColour(1),CurrentColour(2),... 409 | CurrentColour(3),CurrentFontSize,CurrentFontSize,Angle,Weight,Fixed); 410 | NewFontStyle = 0; 411 | end 412 | 413 | if(iscell(PsfragCmds{ii,2})) % Legend has a seperate text cell for each entry 414 | for ci=1:length(PsfragCmds{ii,2}) 415 | fprintf(fid,'\n\\psfrag{%s}',PsfragCmds{ii,2}{ci}); 416 | 417 | % Only put in positioning information if it is not [bl] aligned 418 | if ~strcmp(PsfragCmds{ii,3},'bl') || ~strcmp(PsfragCmds{ii,3},'lb') 419 | fprintf(fid,'[%s][%s]',PsfragCmds{ii,3},PsfragCmds{ii,3}); 420 | end 421 | fprintf(fid,'{\\%s%s %s}%%',FontStylePrefix,... 422 | char(FontStyleId),EscapeSpecial(RemoveSpaces(PsfragCmds{ii,1}{ci}))); 423 | end 424 | else % All other text 425 | fprintf(fid,'\n\\psfrag{%s}',PsfragCmds{ii,2}); 426 | 427 | % Only put in positioning information if it is not [bl] aligned 428 | if ~strcmp(PsfragCmds{ii,3},'bl') || ~strcmp(PsfragCmds{ii,3},'lb') 429 | fprintf(fid,'[%s][%s]',PsfragCmds{ii,3},PsfragCmds{ii,3}); 430 | end 431 | fprintf(fid,'{\\%s%s %s}%%',FontStylePrefix,... 432 | char(FontStyleId),EscapeSpecial(RemoveSpaces(PsfragCmds{ii,1}))); 433 | end 434 | 435 | end 436 | fprintf(fid,'\n%%\n%%%% ',CurrentType); 437 | 438 | fclose(fid); 439 | 440 | catch % -- needed for r2007a support 441 | err = lasterror; %#ok 442 | if fid > 0 443 | fclose(fid); 444 | end 445 | err.stack.line 446 | rethrow( err ); 447 | end 448 | % All done! Below are the sub-functions 449 | 450 | % Find all of the 'text' and 'axes' objects in the 451 | % figure and dispatch the processing of them 452 | function ProcessFigure(parent) 453 | 454 | % Show all of the hidden handles 455 | hidden = get(0,'showhiddenhandles'); 456 | set(0,'showhiddenhandles','on'); 457 | 458 | % Get all text and axes handles 459 | axeshandles = findobj(parent,'Type','axes','visible','on'); 460 | if v(1) < 8 || (v(1) == 8 && v(2) < 4) % Prior to MATLAB R2014b, legends and colorbars were axes objects 461 | legendhandles = findobj(parent,'Type','axes','Tag','legend','visible','on'); 462 | else 463 | legendhandles = findobj(parent,'Type','Legend','visible','on'); 464 | end 465 | axeshandles = setdiff(axeshandles,legendhandles); 466 | texthandles = findobj(parent,'Type','text','visible','on'); 467 | 468 | % Hide all of the hidden handles again 469 | set(0,'showhiddenhandles',hidden); 470 | 471 | % Get the position of all the text objects 472 | textpos = GetTextPos(texthandles); 473 | 474 | % Freeze all legends (after axes and legend listeners have been disables) 475 | for jj=1:length(legendhandles) 476 | ProcessLegends(legendhandles(jj)); 477 | end 478 | 479 | % Freeze all axes, and process ticks. 480 | for jj=1:length(axeshandles) 481 | ProcessTicks(axeshandles(jj)); 482 | end 483 | 484 | % Process all text. 485 | for jj=1:length(texthandles) 486 | ProcessText(texthandles(jj),textpos{jj}); 487 | end 488 | end 489 | 490 | % Get all fo the text object's positions. 491 | function TextPos = GetTextPos(texthandles) 492 | TextPos = cell(1,length(texthandles)); 493 | for jj=1:length(texthandles) 494 | TextPos{jj} = get(texthandles(jj),'position'); 495 | AddUndoAction('Reset text posision', @() set(texthandles(jj),'position', TextPos{jj} )); 496 | end 497 | end 498 | 499 | % Process a text handle, extracting the appropriate data 500 | % and creating 'action' functions 501 | function ProcessText(handle,Pos) 502 | % Get some of the text properties. 503 | String = get(handle,'string'); 504 | UserData = get(handle,'UserData'); 505 | UserString = {}; 506 | 507 | % Process the strings alignment options 508 | [halign,valign] = GetAlignment(handle); 509 | % Test to see if UserData is valid. 510 | if ischar(UserData) 511 | if ~isempty(sscanf(UserData,'%s')) 512 | UserString = regexp(UserData,[USERDATA_PREFIX,'(.*)'],'tokens'); 513 | end 514 | end 515 | % Test for multiline strings (using cells). 516 | if iscell(String) 517 | % Error checking. Luckily Matlab is fairly nice with the way it 518 | % treats its strings in figures. 519 | assert( size(String,2) == 1 && iscellstr(String),... 520 | 'matlabfrag:WeirdError',['Weird ''String'' formatting.\n',... 521 | 'Please raise an issue on github (see the help text for a link),\n',... 522 | 'as this error should not occur.']); 523 | % If the cell only has 1 element, then do nothing. 524 | if size(String,1)==1 525 | String = String{:}; 526 | else 527 | temp = sprintf('\\begin{tabular}{@{}%c@{}}%s',halign,String{1}); 528 | for jj=2:length(String) 529 | temp = sprintf('%s\\\\%s',temp,String{jj}); 530 | end 531 | String = sprintf('%s\\end{tabular}',temp); 532 | end 533 | end 534 | % Test for multiline strings using matrices 535 | if size(String,1) > 1 536 | temp = sprintf('\\begin{tabular}{@{}%c@{}}%s',halign,... 537 | regexprep(String(1,:),' ','~')); 538 | for jj=2:size(String,1) 539 | temp = sprintf('%s\\\\%s',temp,... 540 | regexprep(String(jj,:),' ','~')); 541 | end 542 | String = sprintf('%s\\end{tabular}',temp); 543 | end 544 | % If there is no text, return. 545 | if isempty(sscanf(String,'%s')) && isempty(UserString); return; end; 546 | % Retrieve the common options 547 | [FontSize,FontAngle,FontWeight,FixedWidth] = CommonOptions(handle); 548 | % Assign a replacement action for the string 549 | CurrentReplacement = ReplacementString(); 550 | SetUnsetProperties('Replacing text string',handle,'String',CurrentReplacement); 551 | % Check for a 'UserData' property, which replaces the string with latex 552 | if ~isempty(UserString) 553 | String = cell2mat(UserString{:}); 554 | end 555 | % Replacement action for the interpreter 556 | if ~strcmpi(get(handle,'interpreter'),'none') 557 | SetUnsetProperties('Text Interpreter to none',handle,'interpreter','none'); 558 | end 559 | % Make sure the final position is the same as the original one 560 | AddAction('Set text pos to where it originally was', @() set(handle,'position',Pos) ); 561 | 562 | % Get the text colour 563 | Colour = get(handle,'color'); 564 | % Finally create the replacement command 565 | AddPsfragCommand(String,CurrentReplacement,[valign,halign],... 566 | FontSize,Colour,FontAngle,FontWeight,FixedWidth,'text'); 567 | end 568 | 569 | % Process the legends. This should be done after the axes have been processed 570 | % and the legend listeners have been disabled. 571 | function ProcessLegends(handle) 572 | % Make sure legend ends up where it started from 573 | lpos = get(handle,'position'); 574 | SetUnsetProperties('Legend Pos to current Pos',handle,'Position', lpos ); 575 | 576 | String = handle.String; 577 | 578 | % Retrieve the common options 579 | [FontSize,FontAngle,FontWeight,FixedWidth] = CommonOptions(handle); 580 | 581 | % Assign a replacement action for the legend strings 582 | CurrentReplacement={}; 583 | for jj=1:length(handle.String) 584 | CurrentReplacement{jj} = [repmat('0',1,length(cell2mat(handle.String(jj)))) ReplacementString()]; % Legend box needs extra padding 585 | end 586 | SetUnsetProperties('Replacing text string',handle,'String',CurrentReplacement); 587 | 588 | % Replacement action for the interpreter 589 | if ~strcmpi(get(handle,'interpreter'),'none') 590 | SetUnsetProperties('Text Interpreter to none',handle,'interpreter','none'); 591 | end 592 | 593 | % Legend object does not store text colors properly 594 | Colour = [0 0 0]; 595 | % Finally create the replacement command 596 | AddPsfragCommand(String,CurrentReplacement,'cl',... 597 | FontSize,Colour,FontAngle,FontWeight,FixedWidth,'text'); 598 | end 599 | 600 | % Processes the position, position mode and 'ticks' of an axis, then returns. 601 | % Don't do anything if it is a legend 602 | function ProcessTicks(handle) 603 | 604 | % Make sure figure doesn't resize itself while we are messing with it. 605 | for jj=['x' 'y' 'z'] 606 | AutoTickLabel.(jj) = strcmpi(get(handle,[jj,'ticklabelmode']),'auto'); 607 | end 608 | SetUnsetProperties('TickModes to manual',handle,... 609 | 'xlimmode','manual','ylimmode','manual','zlimmode','manual',... 610 | 'xtickmode','manual','ytickmode','manual','ztickmode','manual',... 611 | 'xticklabelmode','manual','yticklabelmode','manual','zticklabelmode','manual'); 612 | apos = get(handle,'position'); 613 | SetUnsetProperties('Fix Axes Pos',handle,'position', apos ); 614 | tickpropcell = {'xtick','ytick','ztick','xticklabel','yticklabel','zticklabel','xlim','ylim','zlim'}; 615 | tickprops = get(handle,tickpropcell); 616 | varg = reshape( [ tickpropcell; tickprops ], 1, 2*length(tickprops) ); 617 | SetUnsetProperties('Fix ticks',handle, varg{:} ); 618 | try 619 | hlist = get(handle,'ScribeLegendListeners'); 620 | SetUnsetProperties('Disable legend fontname listener',hlist.fontname,'enabled','off'); 621 | catch % -- required for r2007a support 622 | err = lasterror; %#ok 623 | if ~isempty(regexpi(err.message,'''enabled''')) 624 | error('matlabfrag:legendlistener',... 625 | ['Oops, it looks like Matlab has changed the way it does legend\n',... 626 | 'callbacks. Please let me know if you see by raising an issue\n',... 627 | 'on github (see the help text for a link).']); 628 | end 629 | end 630 | % Extract common options. 631 | [FontSize,FontAngle,FontWeight,FixedWidth] = CommonOptions(handle); 632 | SetUnsetProperties('Axes font to fixed-width',handle,'FontName','fixedwidth'); 633 | FontName = 'fixedwidth'; 634 | % Test to see if the plot is 2D or 3D. 635 | Plot2D = isempty(get(handle,'zticklabel')) && all( get(handle,'view') == [0 90] ); 636 | % Loop through all axes 637 | for jj = ['x' 'y' 'z'] 638 | ticklabels = get(handle,[jj,'ticklabel']); 639 | ticks = get(handle,[jj,'tick']); 640 | lims = get(handle,[jj,'lim']); 641 | % If there are no ticks, skip to the next axis 642 | if isempty(ticks) 643 | continue; 644 | end 645 | % Trim the ticks (if they lay outside lims) 646 | if AutoTickLabel.(jj) 647 | ticks = ticks( ticks >= lims(1) ); 648 | ticks = ticks( ticks <= lims(2) ); 649 | SetUnsetProperties('Trimming tick labels',handle,[jj,'tick'],ticks); 650 | end 651 | set(handle,[jj,'tickmode'],'manual',[jj,'ticklabelmode'],'manual'); 652 | if ~isempty(ticklabels) 653 | tickcolour = get(handle,[jj,'color']); 654 | 655 | % Test to see if it is on a logarithmic scale 656 | if strcmpi(get(handle,[jj,'scale']),'log') && AutoTickLabel.(jj) 657 | ticklabelcell = mat2cell(ticklabels,ones(1,size(ticklabels,1)),size(ticklabels,2)); 658 | if strcmpi( p.Results.unaryminus, 'short' ) 659 | ticklabels = cellfun(@(x) ['\mathmodel',... 660 | regexprep( RemoveSpaces(x), '-', ['\\',NEGTICK_SHORT_SCRIPT_COMMAND,' '] ),... 661 | '\mathmoder'],ticklabelcell,'uniformoutput',0); 662 | else 663 | ticklabels = cellfun(@(x) ['\mathmodel',RemoveSpaces(x),... 664 | '\mathmoder'],ticklabelcell,'uniformoutput',0); 665 | end 666 | 667 | % Test to see if there is a common factor 668 | elseif strcmpi(get(handle,[jj,'scale']),'linear') && AutoTickLabel.(jj) 669 | for kk=1:size(ticklabels,1) 670 | % Find the first non-NaN ratio between tick labels and tick 671 | % values 672 | scale = ticks(kk)/str2double(ticklabels(kk,:)); 673 | if ~isnan(scale); break; end; 674 | end 675 | 676 | % If the scale is not 1, then we need to place a marker near the 677 | % axis 678 | if abs(scale-1) > 1e-3 679 | scale = log10(scale); 680 | % Make sure it is an integer. 681 | assert( abs(scale-round(scale))<1e-2, 'matlabfrag:AxesScaling:NonInteger',... 682 | ['Non integer axes scaling. This is most likely a bug in matlabfrag.\n',... 683 | 'Please let me know the ytick and yticklabel values for this plot.']); 684 | if strcmpi( p.Results.unaryminus, 'short' ) 685 | LatexScale = ['\mathmodel\times10^{', regexprep( num2str(round(scale)), '-', ['\\',NEGTICK_SHORT_SCRIPT_COMMAND,' '] ), '}\mathmoder']; 686 | else 687 | LatexScale = ['\mathmodel\times10^{',num2str(round(scale)),'}\mathmoder']; 688 | end 689 | % Different action depending if the plot is 2D or 3D 690 | if Plot2D 691 | %2D Plot... fairly easy. 692 | % Common required data... 693 | Xlims = get(handle,'xlim'); 694 | Ylims = get(handle,'ylim'); 695 | Xdir = get(handle,'xdir'); 696 | Ydir = get(handle,'ydir'); 697 | XAlignment = get(handle,'XAxisLocation'); 698 | YAlignment = get(handle,'YAxisLocation'); 699 | % 2D plot, so only x and y... 700 | CurrentReplacement = ReplacementString(); 701 | 702 | % If the axes are reversed, reverse the lims 703 | if strcmpi(Xdir,'reverse') 704 | Xlims = Xlims(end:-1:1); 705 | end 706 | if strcmpi(Ydir,'reverse') 707 | Ylims = Ylims(end:-1:1); 708 | end 709 | 710 | % X axis scale 711 | if strcmpi(jj,'x') 712 | if strcmpi(XAlignment,'bottom'); 713 | ht = text(Xlims(2),Ylims(1),CurrentReplacement,... 714 | 'fontsize',FontSize,'fontname',FontName,... 715 | 'HorizontalAlignment','center','VerticalAlignment','top',... 716 | 'parent',handle,'interpreter','none'); 717 | extent = get(ht,'extent'); 718 | position = get(ht,'position'); 719 | set(ht,'position',[position(1) position(2)-1.0*extent(4) position(3)]); 720 | Alignment = 'tc'; 721 | else 722 | ht = text(Xlims(2),Ylims(2),CurrentReplacement,... 723 | 'fontsize',FontSize,'fontname',FontName,... 724 | 'HorizontalAlignment','center','VerticalAlignment','bottom',... 725 | 'parent',handle,'interpreter','none'); 726 | extent = get(ht,'extent'); 727 | position = get(ht,'position'); 728 | set(ht,'position',[position(1) position(2)+1.0*extent(4) position(3)]); 729 | Alignment = 'bc'; 730 | end 731 | 732 | % Y axis scale 733 | else 734 | if strcmpi(XAlignment,'bottom') 735 | if strcmpi(YAlignment,'left') 736 | ht = text(Xlims(1),Ylims(2),CurrentReplacement,... 737 | 'fontsize',FontSize,'fontname',FontName,... 738 | 'HorizontalAlignment','center','VerticalAlignment','bottom',... 739 | 'parent',handle,'interpreter','none'); 740 | else 741 | ht = text(Xlims(2),Ylims(2),CurrentReplacement,... 742 | 'fontsize',FontSize,'fontname',FontName,... 743 | 'HorizontalAlignment','center','VerticalAlignment','bottom',... 744 | 'parent',handle,'interpreter','none'); 745 | end 746 | extent = get(ht,'extent'); 747 | position = get(ht,'position'); 748 | set(ht,'position',[position(1) position(2)+0.5*extent(4) position(3)]); 749 | Alignment = 'bc'; 750 | else 751 | if strcmpi(YAlignment,'left') 752 | ht = text(Xlims(1),Ylims(1),CurrentReplacement,... 753 | 'fontsize',FontSize,'fontname',FontName,... 754 | 'HorizontalAlignment','center','VerticalAlignment','top',... 755 | 'parent',handle,'interpreter','none'); 756 | else 757 | ht = text(Xlims(2),Ylims(1),CurrentReplacement,... 758 | 'fontsize',FontSize,'fontname',FontName,... 759 | 'HorizontalAlignment','center','VerticalAlignment','top',... 760 | 'parent',handle,'interpreter','none'); 761 | end 762 | extent = get(ht,'extent'); 763 | position = get(ht,'position'); 764 | set(ht,'position',[position(1) position(2)-0.5*extent(4) position(3)]); 765 | Alignment = 'tc'; 766 | end 767 | end 768 | 769 | % Create the replacement command 770 | AddPsfragCommand(LatexScale,CurrentReplacement,Alignment,FontSize,... 771 | tickcolour,FontAngle,FontWeight,FixedWidth,[jj,'scale']); 772 | % Delete the label 773 | AddUndoAction('Delete axis scale', @() delete(ht) ); 774 | else 775 | % Why is this so hard? 776 | warning('matlabfrag:scaled3Daxis',... 777 | ['It looks like your %s axis is scaled on a 3D plot. Unfortunately\n',... 778 | 'these are very hard to handle, so there may be a problem with\n',... 779 | 'its placement. If you know of a better algorithm for placing it,\n',... 780 | 'please let me know by creating an issue at www.github.com/zprime/matlabfrag',... 781 | ],jj); 782 | % :-( 783 | CurrentReplacement = ReplacementString(); 784 | Xlim = get(handle,'xlim'); 785 | Ylim = get(handle,'ylim'); 786 | Zlim = get(handle,'zlim'); 787 | axlen = @(x) x(2)-x(1); 788 | switch lower( jj ) 789 | case 'x' 790 | ht = text(Xlim(1)+0.6*axlen(Xlim),... 791 | Ylim(1)-0.3*axlen(Ylim),... 792 | Zlim(1),... 793 | CurrentReplacement,'fontsize',FontSize,... 794 | 'fontname',FontName,'parent',handle,'interpreter','none'); 795 | Alignment = 'bl'; 796 | case 'y' 797 | ht = text(Xlim(1)-0.3*axlen(Xlim),... 798 | Ylim(1)+0.6*axlen(Ylim),... 799 | Zlim(1),... 800 | CurrentReplacement,'fontsize',FontSize,... 801 | 'fontname',FontName,'horizontalalignment',... 802 | 'right','parent',handle,'interpreter','none'); 803 | Alignment = 'br'; 804 | case 'z' 805 | ht = text(Xlim(1),Ylim(2),Zlim(2)+0.2*axlen(Zlim),... 806 | CurrentReplacement,'fontsize',FontSize,... 807 | 'fontname',FontName,'horizontalalignment',... 808 | 'right','parent',handle,'interpreter','none'); 809 | Alignment = 'br'; 810 | otherwise 811 | error('matlabfrag:wtf',['Bad axis; this error shouldn''t happen.\n',... 812 | 'please report it as a bug.']); 813 | end 814 | % Create the replacement command 815 | AddPsfragCommand(LatexScale,CurrentReplacement,Alignment,FontSize,... 816 | tickcolour,FontAngle,FontWeight,FixedWidth,[jj,'scale']); 817 | % Delete the label 818 | AddUndoAction('DeleteAxesScale', @() delete(ht) ); 819 | end 820 | end 821 | end 822 | 823 | % Test whether all of the ticks are numbers, if so, substitute in 824 | % proper minus signs. 825 | if ~iscell(ticklabels) 826 | ticklabels = mat2cell(ticklabels,ones(1,size(ticklabels,1)),size(ticklabels,2)); 827 | end 828 | TicksAreNumbers = 1; 829 | for kk=1:size(ticklabels,1) 830 | if isempty(ticklabels{kk,:}) 831 | continue; 832 | end 833 | if isnan(str2double(ticklabels{kk,:})) 834 | TicksAreNumbers = 0; 835 | break; 836 | end 837 | end 838 | if TicksAreNumbers 839 | if (Plot2D && strcmpi(jj,'x')) || (~Plot2D && any(strcmpi(jj,{'x','y'})) ) 840 | for kk=1:size(ticklabels) 841 | if isempty(ticklabels{kk,:}) 842 | continue; 843 | end 844 | ticklabels{kk,:} = ['\mathmodel',... 845 | RemoveSpaces( regexprep(ticklabels{kk,:},'-',['\\',NEGTICK_NO_WIDTH_COMMAND,' ']) ),... 846 | '\mathmoder']; 847 | end 848 | else 849 | for kk=1:size(ticklabels) 850 | if isempty(ticklabels{kk,:}) 851 | continue; 852 | end 853 | if strcmpi( p.Results.unaryminus, 'short' ) 854 | ticklabels{kk,:} = ['\mathmodel',... 855 | RemoveSpaces( regexprep(ticklabels{kk,:},'-',['\\',NEGTICK_SHORT_COMMAND,' ']) ),... 856 | '\mathmoder']; 857 | else 858 | ticklabels{kk,:} = ['\mathmodel', RemoveSpaces( ticklabels{kk,:} ),'\mathmoder']; 859 | end 860 | end 861 | end 862 | end 863 | clear TicksAreNumbers 864 | 865 | tickreplacements = cell(1,size(ticklabels,1)); 866 | % Process the X and Y tick alignment 867 | if ~strcmpi(jj,'z') 868 | switch get(handle,[jj,'axislocation']) 869 | case 'left' 870 | tickalignment = 'rc'; 871 | case 'right' 872 | tickalignment = 'lc'; 873 | case 'bottom' 874 | tickalignment = 'ct'; 875 | case 'top' 876 | tickalignment = 'cb'; 877 | otherwise 878 | tickalignment = 'cr'; 879 | warning('matlabfrag:UnknownAxisLocation',... 880 | 'Unknown axis location defaulting to ''cr'''); 881 | end 882 | else 883 | % Fixed Z tick alignment 884 | tickalignment = 'cr'; 885 | end 886 | 887 | % Now process the actual tick labels themselves... 888 | for kk=1:size(ticklabels,1) 889 | if isempty( ticklabels{kk,:} ) 890 | tickreplacements{kk} = ''; 891 | continue; 892 | end 893 | tickreplacements{kk} = ReplacementString(); 894 | AddPsfragCommand(ticklabels{kk,:},tickreplacements{kk},... 895 | tickalignment,FontSize,tickcolour,FontAngle,FontWeight,... 896 | FixedWidth,[jj,'tick']); 897 | end 898 | % Now add the replacement action... 899 | SetUnsetProperties('Tick replacement',handle,[jj,'ticklabel'],tickreplacements); 900 | end 901 | end 902 | end % of ProcessTicks 903 | 904 | % Get the next replacement string 905 | function CurrentReplacement = ReplacementString() 906 | CurrentReplacement = sprintf(REPLACEMENT_FORMAT,StringCounter); 907 | StringCounter = StringCounter+1; 908 | end 909 | 910 | % Extract and process the options that are common to text labels as 911 | % well as axes ticks 912 | function [FontSize,FontAngle,FontWeight,FixedWidth] = CommonOptions(handle) 913 | % First get the fontsize (making sure it is in points) 914 | temp_prop = get(handle,'FontUnits'); 915 | if ~strcmpi(temp_prop,'points') 916 | SetUnsetProperties('FontUnits to points',handle,'FontUnits','points'); 917 | end 918 | FontSize = get(handle,'FontSize'); 919 | % % SetUnsetProperties('FontSize to 10',handle,'Fontsize',10); 920 | % Now get the font angle (read - italics) 921 | switch get(handle,'FontAngle') 922 | case 'normal' 923 | FontAngle = 0; 924 | case 'italic' 925 | FontAngle = 1; 926 | case 'oblique' 927 | warning('matlabfrag:ObliqueFont',... 928 | 'Nobody in their right mind uses Oblique font. Defaulting to italic.'); 929 | FontAngle = 1; 930 | otherwise 931 | warning('matlabfrag:UnknownFontType',... 932 | 'Unknown FontAngle for the string "%s"',get(handle,'String')); 933 | FontAngle = 0; 934 | end 935 | % % if FontAngle 936 | % % SetUnsetProperties('FontAngle to normal',handle,'FontAngle','normal'); 937 | % % end 938 | % Now get the FontWeight (read - bold) 939 | switch get(handle,'FontWeight') 940 | case 'light' 941 | warning('matlabfrag:LightFontNotSupported',... 942 | 'Light FontWeight does not really translate to LaTeX... Defaulting to normal.'); 943 | FontWeight = 0; 944 | case 'normal' 945 | FontWeight = 0; 946 | case 'demi' 947 | warning('matlabfrag:DemiFontNotSupported',... 948 | 'Demi FontWeight does not really translate to LaTeX... Defaulting to normal.'); 949 | FontWeight = 0; 950 | case 'bold' 951 | FontWeight = 1; 952 | otherwise 953 | warning('matlabfrag:UnknownFontWeight',... 954 | 'Unknown FontWeight for the string %s',get(handle,'String')); 955 | end 956 | % % if FontWeight 957 | % % SetUnsetProperties('FontWeight to normal',handle,'FontWeight','normal'); 958 | % % end 959 | % Test to see if the font is 'fixed width' 960 | if strcmpi(get(handle,'FontName'),'FixedWidth') 961 | FixedWidth = 1; 962 | else 963 | FixedWidth = 0; 964 | end 965 | % % if ~FixedWidth 966 | % % SetUnsetProperties('Set text to FixedWidth',handle,'FontName','fixed-width'); 967 | % % end 968 | end 969 | 970 | % Adds a PsFrag command to the cell. This is a function to ensure allow a 971 | % standard calling convention to be established. 972 | function AddPsfragCommand(LatexString,ReplacementString,Alignment,... 973 | FontSize,Colour,FontAngle,FontWeight,FixedWidth,Type) 974 | PsfragCmds(size(PsfragCmds,1)+1,:) = {LatexString,ReplacementString,... 975 | Alignment,FontSize,Colour,FontAngle,FontWeight,FixedWidth,Type}; 976 | end 977 | 978 | % Set and then unset some handle properties using 'Actions' and 979 | % 'UndoActions' 980 | function SetUnsetProperties(description,handle,varargin) 981 | Props = varargin(1:2:end); 982 | PropVals = varargin(2:2:end); 983 | TempPropVals = get(handle,Props); 984 | AddAction(description, @() set(handle,Props,PropVals) ); 985 | AddUndoAction(description, @() set(handle,Props,TempPropVals) ); 986 | end 987 | 988 | % Add an 'action' function to the list of actions to perform before the 989 | % image is saved. 990 | function AddAction(description,action) 991 | Actions.length = Actions.length + 1; 992 | Actions.( ACTION_FUNC_NAME( Actions.length ) ) = action; 993 | Actions.( ACTION_DESC_NAME( Actions.length ) ) = description; 994 | end 995 | 996 | % Adds an 'undo-action' function to the list... these get processed after 997 | % the image has been saved, to restore the screen state. 998 | function AddUndoAction(description,action) 999 | UndoActions.length = UndoActions.length + 1; 1000 | UndoActions.( ACTION_FUNC_NAME( UndoActions.length ) ) = action; 1001 | UndoActions.( ACTION_DESC_NAME( UndoActions.length ) ) = description; 1002 | end 1003 | 1004 | % Surrounds the Matlab supported Tex characters in math mode 1005 | function str = EscapeSpecial(str) 1006 | specialcharacterlist={'\alpha', '\upsilon', '\sim', '\angle',... 1007 | '\phi', '\leq', '\ast', '\chi', '\infty', '\beta', '\psi',... 1008 | '\clubsuit', '\gamma', '\omega', '\diamondsuit', '\delta',... 1009 | '\Gamma', '\heartsuit', '\epsilon', '\Delta', '\spadesuit',... 1010 | '\zeta', '\Theta', '\leftrightarrow', '\eta', '\Lambda',... 1011 | '\leftarrow', '\theta', '\Xi', '\Leftarrow', '\vartheta',... 1012 | '\Pi', '\uparrow', '\iota', '\Sigma', '\rightarrow',... 1013 | '\kappa', '\Upsilon', '\Rightarrow', '\lambda', '\Phi',... 1014 | '\downarrow', '\mu', '\Psi', '\circ', '\nu', '\Omega',... 1015 | '\pm', '\xi', '\forall', '\geq', '\pi', '\exists', '\propto',... 1016 | '\rho', '\ni', '\partial', '\sigma', '\cong', '\bullet', '\varsigma',... 1017 | '\approx', '\div', '\tau', '\Re', '\neq', '\equiv', '\oplus',... 1018 | '\aleph', '\Im', '\cup', '\wp', '\otimes', '\subseteq', '\oslash',... 1019 | '\cap', '\in', '\supseteq', '\supset', '\lceil', '\subset', '\int',... 1020 | '\cdot', '\o', '\rfloor', '\neg', '\nabla', '\lfloor', '\times', ... 1021 | '\ldots','\perp', '\surd', '\prime', '\wedge', '\varpi', '\0',... 1022 | '\rceil', '\rangle', '\mid', '\vee', '\langle', '\copyright'}; 1023 | 1024 | % First escape any % text characters 1025 | str = strrep(str,'%','\%'); 1026 | 1027 | % If the user manually defines math mode (with two unescaped $ 1028 | % characters), or the string is already in math mode, 1029 | % there is no need to escape anything on our end 1030 | if isempty(regexp(str, '(?char').'; 1186 | fh = fclose(fh); 1187 | catch % -- required for r2007a support 1188 | err = lasterror; %#ok 1189 | if fh > 0 1190 | fh = close(fh); 1191 | end 1192 | rethrow( err ); 1193 | end 1194 | if ~keep_tempfile 1195 | delete([tmp_file,'.eps']); 1196 | end 1197 | textobj = regexpi(paintersfile,TEXTOBJ_REGEXP,'match'); 1198 | textobjpos = regexpi(paintersfile,TEXTOBJ_REGEXP); 1199 | texthdr = regexpi(paintersfile,TEXTHDR_REGEXP,'match'); 1200 | texthdrpos = regexpi(paintersfile,TEXTHDR_REGEXP); 1201 | textData = cell(length(textobjpos)+length(texthdrpos),2); 1202 | textData(:,1) = num2cell([texthdrpos.';textobjpos.']); 1203 | textData(:,2) = [texthdr,textobj].'; 1204 | [Ysort,Isort] = sortrows( cell2mat( textData(:,1) ) ); 1205 | textData = textData(Isort,:); 1206 | 1207 | % Open up the target file, and read the contents. 1208 | try 1209 | fh = fopen([filename,'.eps'],'r'); 1210 | epsfile = fread(fh,inf,'uint8=>char').'; 1211 | fh = fclose(fh); 1212 | catch % -- this is required for r2007a support 1213 | err = lasterror; %#ok 1214 | if fh > 0 1215 | fh = close(fh); 1216 | end 1217 | rethrow( err ); 1218 | end 1219 | % Insert the new text 1220 | findex = regexp(epsfile,'end %%Color Dict'); 1221 | epsfile = sprintf('%s\n\n%s\n%s',... 1222 | epsfile(1:findex-1),... 1223 | sprintf('%s\n',textData{:,2}),... 1224 | epsfile(findex:end)); 1225 | try 1226 | fh = fopen([filename,'.eps'],'w'); 1227 | fwrite(fh,epsfile); 1228 | fh = fclose(fh); 1229 | catch % -- this is required for r2007a support 1230 | err = lasterror; %#ok 1231 | if fh > 0 1232 | fh = fclose(fh); 1233 | end 1234 | rethrow( err ); 1235 | end 1236 | end 1237 | 1238 | % Test to see if there is any text in the figure 1239 | function NoText = FigureHasNoText(p) 1240 | NoText = 0; 1241 | 1242 | hidden = get(0,'showhiddenhandles'); 1243 | set(0,'showhiddenhandles','on'); 1244 | tempht = findobj(p.Results.handle,'type','text','visible','on'); 1245 | tempha = findobj(p.Results.handle,'type','axes','visible','on'); 1246 | set(0,'showhiddenhandles',hidden); 1247 | 1248 | for kk=tempht.' 1249 | temptext = get(kk,'string'); 1250 | if ischar(temptext) 1251 | temptext = mat2cell(temptext,ones(1,size(temptext,1))); 1252 | end 1253 | if isempty( regexp( temptext, '\S', 'once' )); 1254 | tempht = setxor(tempht,kk); 1255 | end 1256 | end 1257 | 1258 | for kk=tempha.' 1259 | if isempty( get(kk,'xticklabel') ) 1260 | if isempty( get(kk,'yticklabel') ) 1261 | if isempty( get(kk,'zticklabel') ) 1262 | tempha = setxor(tempha,kk); 1263 | end 1264 | end 1265 | end 1266 | end 1267 | 1268 | if isempty(tempht) && isempty(tempha) 1269 | % No Text! Why are you using this then? 1270 | warning('matlabfrag:noText',['No text in image. You would be better off ',... 1271 | 'using a function like savefig.\n',... 1273 | '.tex file will not be created.']); 1274 | 1275 | % Set up the figure 1276 | OrigUnits = get(p.Results.handle,'units'); 1277 | set(p.Results.handle,'units','centimeters'); 1278 | Pos = get(p.Results.handle,'position'); 1279 | OrigPPos = get(p.Results.handle,{'paperunits','paperposition'}); 1280 | set(p.Results.handle,'paperunits','centimeters','paperposition',Pos); 1281 | 1282 | % Test to see if the directory (if specified) exists 1283 | [pathstr,namestr] = fileparts(p.Results.FileName); 1284 | if ~isempty(pathstr) 1285 | if ~exist(['./',pathstr],'dir') 1286 | mkdir(pathstr); 1287 | end 1288 | % Tidy up the FileName 1289 | FileName = [pathstr,filesep,namestr]; 1290 | else 1291 | FileName = namestr; 1292 | end 1293 | 1294 | % Print the image 1295 | print(p.Results.handle,'-depsc2',['-',p.Results.renderer],... 1296 | sprintf('-r%i',p.Results.dpi),'-loose',FileName); 1297 | 1298 | % Restore the figure 1299 | set(p.Results.handle,'units',OrigUnits,'paperunits',... 1300 | OrigPPos{1},'paperposition',OrigPPos{2}); 1301 | 1302 | NoText = 1; 1303 | end 1304 | end 1305 | 1306 | end % of matlabfrag(FileName,p.Results.handle) 1307 | 1308 | % Copyright (c) 2008--2013, Zebb Prime 1309 | % All rights reserved. 1310 | % 1311 | % Redistribution and use in source and binary forms, with or without 1312 | % modification, are permitted provided that the following conditions are met: 1313 | % * Redistributions of source code must retain the above copyright 1314 | % notice, this list of conditions and the following disclaimer. 1315 | % * Redistributions in binary form must reproduce the above copyright 1316 | % notice, this list of conditions and the following disclaimer in the 1317 | % documentation and/or other materials provided with the distribution. 1318 | % * Neither the name of the organization nor the 1319 | % names of its contributors may be used to endorse or promote products 1320 | % derived from this software without specific prior written permission. 1321 | % 1322 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 1323 | % ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1324 | % WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1325 | % DISCLAIMED. IN NO EVENT SHALL ZEBB PRIME BE LIABLE FOR ANY 1326 | % DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1327 | % (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1328 | % LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 1329 | % ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1330 | % (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1331 | % SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /package.m: -------------------------------------------------------------------------------- 1 | %% Package matlabfrag for upload to the Mathworks File Exchange. 2 | close all; 3 | clear all; 4 | clc; 5 | addpath ./ 6 | 7 | %% Compile the figures 8 | cd examples 9 | run_all 10 | 11 | %% Compile the documentation 12 | if ispc 13 | texpath = ''; 14 | elseif ismac 15 | texpath = 'export PATH=$PATH:/usr/texbin:/usr/local/bin; '; 16 | else 17 | texpath = 'export PATH=$PATH:/usr/bin:/usr/local/bin; '; 18 | end 19 | 20 | for ii=1:3 21 | [res,out] = system( sprintf('%spdflatex -interaction=nonstopmode -shell-escape userguide.tex', texpath )); 22 | if res ~= 0 23 | error('package:pdflatex','pdfLaTeX compilation failed with error:\n%s',out); 24 | end 25 | end 26 | 27 | %% Remove GPL from userguide 28 | % During submission to the file exchange, Mathworks search all the files 29 | % for the string "GPL", because they require all files to be covered by the 30 | % BSD license. Therefore, to prevent submission delays, all instances of 31 | % "/Producer (dvips + GPL Ghostscript..." will have the GPL removed. 32 | cd .. 33 | fin = fopen(['examples',filesep,'userguide.pdf'],'r'); 34 | fout = fopen('userguide.pdf','w'); 35 | while( ~feof( fin ) ) 36 | line = fgets( fin ); 37 | line = regexprep(line,'GPL\sGhostscript','Ghostscript'); 38 | fwrite( fout, line ); 39 | end 40 | fin = fclose(fin); 41 | fout = fclose(fout); 42 | 43 | %% Zip it up 44 | zip('matlabfrag',{'matlabfrag.m',... 45 | 'epscompress.*',... 46 | 'userguide.pdf',... 47 | ['examples',filesep,'userguide.tex'],... 48 | ['examples',filesep,'testing.tex'],... 49 | ['examples',filesep,'ex*.m'],... 50 | ['examples',filesep,'comparison*.m'],... 51 | ['examples',filesep,'test*.m'] }); 52 | 53 | %% Clean up the output files 54 | close all 55 | cd examples 56 | delete(['graphics',filesep,'*']); 57 | rmdir('graphics'); 58 | delete('userguide.aux'); 59 | delete('userguide.log'); 60 | delete('userguide.out'); 61 | delete('userguide.toc'); -------------------------------------------------------------------------------- /userguide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zprime/matlabfrag/0388c9f351ba7045aae484c07fc8f15c54842d8d/userguide.pdf --------------------------------------------------------------------------------