TeXempelvis

En blogg om typsättning med TeX och LaTeX

Latex och Matlab

Skriver man tekniska rapporter i Latex är det ofta man behöver infoga data beräknad eller analyserad i något externt program.

Infoga data i Latex-dokument kan man göra på många olika sätt och i några inlägg kommer jag ta upp olika metoder för att lösa detta. Den första metoden är från programmet skriva ut datan till en fil som är direkt läsbar från Latex. Det här är speciellt användbart om det bara är lite data man behöver eller om datan inte följer något egentligt system.

På elektroniktekprogrammet på Chalmers är Matlab ett vanligt använt program för att göra numeriska beräkningar och analyser av data. Principerna torde vara lika även för andra program eller programmeringsspråk även om syntaxen givetvis kan skilja sig. De flesta programmeringsspråken kan skriva till filer, så att göra samma sak som nedan i till exempel Python går också bra.

Tanken här är att:

  1. Göra intressanta beräkningar i Matlab. Den här delen kommer inte diskuteras i det här inlägget, vektorer med numeriska värden kommer att användas för att illustrera det här steget. Det borde sedan vara möjligt att med utgång från det här inlägget anpassa funktionerna så att de kan användas i ens projekt.

  2. Spara värdena till en fil med hjälp av Matlabs funktioner för att skriva och läsa från filer.

  3. Inkludera filen i Latex-dokumentet.

Ett praktiskt första exempel. Låt säga att du har matrisen A = [1 2 3; 4 5 6; 7 8 9] som du vill använda i en ekvation i Latex. Matlab har en funktion latex() som “översätter” inargumentet till Latex-kod. Den här funktionen, kombinerad med funktionen sym() gör att vi får en rad kod som vi kan klistra in i vårt dokument.

Hela syftet med det här projeketet var dock att göra få det att automatiskt uppdateras när man gör nya beräkningar i Matlab och att då klippa och klistra är inte alltid trevligt, så vill automatisera processen.

Matlab har bland annat lågnivåfunktionerna fopen, fclose, fprintf för att öppna och läsa i filer. Med hjälp av dessa kan vi skriva Latex-utrycket som vi precis tagit fram i en fil, som sedan kan inkluderas i rapporten. Är det många ekvationer ska infogas blir det lätt opraktiskt med en ekvation per fil, så vi skriver alltihop till samma fil, men skapar nya kommandon för att använda dem. Vi passar samtidigt på att generalisera det lite till en funktion som kan spara det den får som inargument

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function SaveAsLatex(varargin)
% Funktion för att spara ett Latex-formatterat uttryck till en fil för att sedan kunna användas i ett dokument.
% Används som: SaveAsLatex(handle, inputVariable, file)
%	handle			- är namnet på kommandot i Latex
%	inputVariable	- är vektorn eller matrisen man vill spara
% 	file			- är filen man vill spara det till

handle = char(varargin{1});
latexedVariable = latex(sym(varargin{2}));

file = fopen(varargin{3}, 'a');
fprintf(file,'\\newcommand{\\%s}{\n\t',handle);
fprintf(file,'\t%s\n}',latexedVariable);
fclose(file);

Ovanstående funktion innehåller, som ni säkert ser, inte någon kontroll av indatan eller om filen finns. Kommandot file = fopen('filnamn', 'a') säger till Matlab att öppna filen “filnamn” och sedan lägga till (append) kommande eventuella innehåll. fprintf skriver sedan innehållet till filen. Första inargumentet är en variabel som innehåller den öppnade filen, medan det andra argumentet är det som faktiskt ska skrivas. Det tredje argumentet är en variabel i Matlab som man vill skicka in i det andra argumentet, i det här fallet som en sträng, %s. Precis som i Latex finns det i Matlab tecken som har speciella betydelser, \n ger en nyrad, \t ett tabbindrag och för att få ett omvänt snedstreck ( \ ) måste man därför skriva två stycken \ efter varandra. För att få kod som kan köras i Latex vill vi ju ha \newcommand utskrivet i filen, inte en nyrad och sedan “ewcommand”. Den andra fprintf skriver den faktiska “latexifierade” variabeln som också är en sträng (%s). Avslutningsvis stänger vi filen eftersom vi inte ska använda den något mer.

Ovanstående funktion kan till exempel användas på det här sättet:

1
2
3
4
A = [1 2 3; 4 5 6; 7 8 9];
B = [10 11 12;13 14 15;16 17 18];
SaveAsLatex('eqA',A,'equations.tex')
SaveAsLatex('eqB',B,'equations.tex')

och i rapporten kan vi sedan hänvisa till dessa ekvationer som följande:

1
2
3
4
5
6
7
8
9
10
11
12
13
\documentclass{article}
\input{equations}

\begin{document}
    Here we have a nice matrix:
    \[
        \eqA{}
    \]
    And here is another one:
    \[
        \eqB{}
    \]
\end{document}

Skriva data till tabell

Om man istället vill skriva ut en stor mängd mätvärden i en tabell kan man också använda funktionen fwrite().

Givet vektorernaL = [180 182.123 176 130 220.899 200.156] och H = [0.0025 0.0037 0.0035 0.0045 0.0078 0.1258] som innehåller sex mätningar av någonting som ska skrivas ut i en tabell.

Även här öppnar vi först filen med fopen().

1
file = fopen('measuredata.tex','w');

I exemplet används tabellerna från paketet longtable som definitivt är något att titta på om man inte känner till det sedan tidigare. Bland annat så stödjer det tabeller som kan brytas över flera sidor, vilket är väldigt bra när man har stora tabeller med mycket data.

Vi skriver ut början på tabellen tillsammans med kolumnjusteringarna med

1
fprintf(file,'\\begin{longtable}{lgggrrr} \n');

Sedan vill vi skriva ut datan på en ny rad. I det här fallet skriver vi först ut texten “measured distance” för att sedan använda L(:) för att plocka ut varje element i vektorn L. Nu vill vi dock inte längre behandla datan som strängar som i exemplet ovan, utan använder istället några av de andra formatSpec som finns i Matlab. Vi passar dessutom på att avrunda några av talen. Detta görs i mitt tycke mer lämpligtvis i Latex med paketet siunitx men jag vill visa att man kan göra det även här.

%u ger positiva heltal (unsigned integrer). %d eller %i ger positiva såväl som negativa heltal (signed integer). För tal med decimaler är det framförallt %fför fixed-point, %eför exponentnotation och %g för en mer kompakt variant av %f(utan nollor på slutet) som är intressanta. En längre lista finns i Matlabs hjälp.

Avrundning kan ske genom att antingen specificera antalet decimaler (för %f och %e) eller antalet värdesiffror (för %g)

Förutom avrundning specificeras även precisionen, som är det minsta antalet tecken som skrivs ut.

Exemplet %6.4f skriver ut pi enligt följande 3.1416.

1
2
fprintf(file,'\t Measured distance [mm] & %g & %g & % g & % g & % g & % g \\\\ \n',L(:));
fprintf(file,'\t Deviation [mm] & %6.4g & % 6.4g & % 6.4g & % 6.4g & % 6.4g & % 6.4g \\\\ \n',H(:)*10^3);

Vi passar även på att ändra H till millimeter, då datan i vektorn var i meter.

1
2
fprintf(file,'\\end{longtable}');
fclose(file);

Avslutningsvis så avslutar vi tabellen och stänger filen. Tabellen kan sedan lätt inkluderas med \input{measuredata} i ett dokument, till exempel det nedan.

1
2
3
4
5
6
7
8
9
\documentclass{article}
\begin{document}
\section{Mätdata}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec lectus tortor, aliquet quis iaculis eget, scelerisque sit amet nibh.

\input{measuredata.tex}

Etiam at dignissim dolor, sed consequat arcu. Vestibulum aliquet, enim at laoreet pulvinar, est felis consequat ipsum, eget adipiscing dolor dolor quis urna.
\end{document}

Det finns andra sätt att flytta data från Matlab till Latex, men det här är ett exempel som är lätt att få fungerande och som bara använder Matlab.

Comments