Update exo5_python_fr.org

parent 4f465fe8
#+TITLE: Analyse du risque de défaillance des joints toriques de la navette Challenger #+TITLE: Analyse du risque de défaillance des joints toriques de la navette Challenger
#+AUTHOR: Arnaud Legrand #+AUTHOR: GNIBGA Wedan Emmanuel
#+DATE: 2021
#+LANGUAGE: fr #+LANGUAGE: fr
#+OPTIONS: H:3 creator:nil timestamp:nil skip:nil toc:nil num:t ^:nil ~:~
# #+OPTIONS: author:nil title:nil date:nil
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="http://www.pirilampo.org/styles/readtheorg/css/htmlize.css"/> #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="http://www.pirilampo.org/styles/readtheorg/css/htmlize.css"/>
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="http://www.pirilampo.org/styles/readtheorg/css/readtheorg.css"/> #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="http://www.pirilampo.org/styles/readtheorg/css/readtheorg.css"/>
#+HTML_HEAD: <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> #+HTML_HEAD: <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
...@@ -9,214 +13,303 @@ ...@@ -9,214 +13,303 @@
#+HTML_HEAD: <script type="text/javascript" src="http://www.pirilampo.org/styles/lib/js/jquery.stickytableheaders.js"></script> #+HTML_HEAD: <script type="text/javascript" src="http://www.pirilampo.org/styles/lib/js/jquery.stickytableheaders.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="http://www.pirilampo.org/styles/readtheorg/js/readtheorg.js"></script> #+HTML_HEAD: <script type="text/javascript" src="http://www.pirilampo.org/styles/readtheorg/js/readtheorg.js"></script>
#+LATEX_HEADER: \usepackage{a4} #+LATEX_HEADER: \usepackage[utf8]{inputenc}
#+LATEX_HEADER: \usepackage[T1]{fontenc}
#+LATEX_HEADER: \usepackage{textcomp}
#+LATEX_HEADER: \usepackage[a4paper,margin=.8in]{geometry}
#+LATEX_HEADER: \usepackage[french]{babel} #+LATEX_HEADER: \usepackage[french]{babel}
#+LATEX_HEADER: \usepackage[usenames,dvipsnames,svgnames,table]{xcolor}
# #+PROPERTY: header-args :session :exports both #+LATEX_HEADER: \usepackage{palatino}
#+LATEX_HEADER: \usepackage{svg}
Le 27 Janvier 1986, veille du décollage de la navette /Challenger/, eu #+LATEX_HEADER: \let\epsilon=\varepsilon
lieu une télé-conférence de trois heures entre les ingénieurs de la *Préambule :* Les explications données dans ce document sur le contexte
Morton Thiokol (constructeur d'un des moteurs) et de la NASA. La de l'étude sont largement reprises de l'excellent livre d'Edward
discussion portait principalement sur les conséquences de la R. Tufte intitulé /Visual Explanations: Images and Quantities, Evidence
température prévue au moment du décollage de 31°F (juste en dessous de and Narrative/, publié en 1997 par /Graphics Press/ et réédité en 2005,
0°C) sur le succès du vol et en particulier sur la performance des ainsi que de l'article de Dalal et al. intitulé /Risk Analysis of the
joints toriques utilisés dans les moteurs. En effet, aucun test Space Shuttle: Pre-Challenger Prediction of Failure/ et publié en 1989
n'avait été effectué à cette température. dans /Journal of the American Statistical Association/.
L'étude qui suit reprend donc une partie des analyses effectuées cette * Contexte
nuit là et dont l'objectif était d'évaluer l'influence potentielle de Dans cette étude, nous vous proposons de revenir sur [[https://fr.wikipedia.org/wiki/Accident_de_la_navette_spatiale_Challenger][l'accident de la
la température et de la pression à laquelle sont soumis les joints navette spatiale Challenger]]. Le 28 Janvier 1986, 73 secondes après son
toriques sur leur probabilité de dysfonctionnement. Pour cela, nous lancement, la navette Challenger se désintègre (voir Figure [[fig:photo]])
disposons des résultats des expériences réalisées par les ingénieurs et entraîne avec elle, les sept astronautes à son bord. Cette
de la NASA durant les 6 années précédant le lancement de la navette explosion est due à la défaillance des deux joints toriques
Challenger. assurant l'étanchéité entre les parties hautes et basses des
propulseurs (voir Figure [[fig:oring]]). Ces joints ont perdu de leur
* Chargement des données efficacité en raison du froid particulier qui régnait au moment du
Nous commençons donc par charger ces données: lancement. En effet, la température ce matin là était juste en dessous
#+begin_src python :results value :session *python* :exports both de 0°C alors que l'ensemble des vols précédents avaient été effectués
import numpy as np à une température d'au moins 7 à 10°C de plus.
import pandas as pd
data = pd.read_csv("shuttle.csv") #+NAME: fig:photo
data #+ATTR_LATEX: :width 10cm
#+CAPTION: Photos de la catastrophe de Challenger.
file:challenger5.jpg
# #+NAME: fig:photo
# #+ATTR_LATEX: :width 6cm
# #+CAPTION: Photo montage de la catastrophe de Challenger. De gauche à droite, de haut en bas : traînée de fumée après la désintégration de la navette spatiale américaine Challenger 73 secondes après son lancement ; débris d'un propulseur d'appoint à poudre ; joints toriques brûlés, les fautifs de l'accident ; décollage final de Challenger ; cérémonie funéraire tenue par le président Ronald Reagan en hommage aux astronautes ; explosion en vol de Challenger
# file:Challenger_Photo_Montage.jpg
# # From https://upload.wikimedia.org/wikipedia/commons/a/a8/Challenger_Photo_Montage.jpg
#+NAME: fig:oring
#+ATTR_LATEX: :width 10cm
#+CAPTION: Schéma des propulseurs de la navette challenger. Les joints toriques (un joint principale et un joint secondaire) en caoutchouc de plus de 11 mètres de circonférence assurent l'étanchéité entre la partie haute et la partie basse du propulseur.
file:o-ring.png
# From https://upload.wikimedia.org/wikipedia/commons/a/a8/Challenger_Photo_Montage.jpg
# https://i0.wp.com/www.kylehailey.com/wp-content/uploads/2014/01/Screen-Shot-2013-12-30-at-12.05.04-PM-1024x679.png?zoom=2&resize=594%2C393
Le plus étonnant est que la cause précise de cet accident avait été
débattue intensément plusieurs jours auparavant et était encore
discutée la veille même du décollage, pendant trois heures de
télé-conférence entre les ingénieurs de la Morton Thiokol
(constructeur des moteurs) et de la NASA. Si la cause immédiate de
l'accident (la défaillance des joints toriques) a rapidement été
identifiée, les raisons plus profondes qui ont conduit à ce désastre
servent régulièrement de cas d'étude, que ce soit dans des cours de
management (organisation du travail, décision technique malgré des
pressions politiques, problèmes de communication), de statistiques
(évaluation du risque, modélisation, visualisation de données), ou de
sociologie (symptôme d'un historique, de la bureaucratie et du
conformisme à des normes organisationnelles).
Dans l'étude que nous vous proposons, nous nous intéressons
principalement à l'aspect statistique mais ce n'est donc qu'une
facette (extrêmement limitée) du problème et nous vous invitons à lire
par vous même les documents donnés en référence dans le
préambule. L'étude qui suit reprend donc une partie des analyses
effectuées cette nuit là et dont l'objectif était d'évaluer
l'influence potentielle de la température et de la pression à laquelle
sont soumis les joints toriques sur leur probabilité de
dysfonctionnement. Pour cela, nous disposons des résultats des
expériences réalisées par les ingénieurs de la NASA durant les 6
années précédant le lancement de la navette Challenger.
Dans le répertoire ~module2/exo5/~ de votre espace =gitlab=, vous
trouverez les données d'origine ainsi qu'une analyse pour chacun des
différents parcours proposés. Cette analyse comporte quatre étapes :
1. Chargement des données
2. Inspection graphique des données
3. Estimation de l'influence de la température
4. Estimation de la probabilité de dysfonctionnement des joints
toriques
Les deux premières étapes ne supposent que des compétences de base en
R ou en Python. La troisième étape suppose une familiarité avec la
régression logistique (généralement abordée en L3 ou M1 de stats,
économétrie, bio-statistique...) et la quatrième étape des bases de
probabilités (niveau lycée). Nous vous présentons donc dans la
prochaine section une introduction à la régression logistique qui ne
s'attarde pas sur les détails du calcul, mais juste sur le sens donné
aux résultats de cette régression.
* Introduction à la régression logistique
Imaginons que l'on dispose des données suivantes qui indiquent pour
une cohorte d'individus s'ils ont déclaré une maladie particulière ou
pas. Je montre ici l'analyse avec R mais le code Python n'est pas forcément
très éloigné. Les données sont stockées dans une data frame dont voici
un bref résumé :
#+begin_src R :results output :session *R* :exports none
library(Hmisc) # pour calculer un intervalle de confiance sur des données binomiales
library(ggplot2)
library(dplyr)
set.seed(42)
proba = function(age) {
val=(age-50)/4
return(exp(val)/(1+exp(val)))
}
df = data.frame(Age = runif(400,min=22,max=80))
df$Malade = sapply(df$Age, function(x) rbinom(n=1,size=1,prob=proba(x)))
#+end_src #+end_src
#+RESULTS: #+RESULTS:
#+begin_example #+begin_example
Date Count Temperature Pressure Malfunction Le chargement a nécessité le package : lattice
0 4/12/81 6 66 50 0 Le chargement a nécessité le package : survival
1 11/12/81 6 70 50 1 Le chargement a nécessité le package : Formula
2 3/22/82 6 69 50 0 Le chargement a nécessité le package : ggplot2
3 11/11/82 6 68 50 0
4 4/04/83 6 67 50 0
5 6/18/82 6 72 50 0
6 8/30/83 6 73 100 0
7 11/28/83 6 70 100 0
8 2/03/84 6 57 200 1
9 4/06/84 6 63 200 1
10 8/30/84 6 70 200 1
11 10/05/84 6 78 200 0
12 11/08/84 6 67 200 0
13 1/24/85 6 53 200 2
14 4/12/85 6 67 200 0
15 4/29/85 6 75 200 0
16 6/17/85 6 70 200 0
17 7/29/85 6 81 200 0
18 8/27/85 6 76 200 0
19 10/03/85 6 79 200 0
20 10/30/85 6 75 200 2
21 11/26/85 6 76 200 0
22 1/12/86 6 58 200 1
#+end_example
Le jeu de données nous indique la date de l'essai, le nombre de joints Attachement du package : ‘Hmisc’
toriques mesurés (il y en a 6 sur le lançeur principal), la
température (en Fahrenheit) et la pression (en psi), et enfin le
nombre de dysfonctionnements relevés.
* Inspection graphique des données The following objects are masked from ‘package:base’:
Les vols où aucun incident n'est relevé n'apportant aucune information
sur l'influence de la température ou de la pression sur les
dysfonctionnements, nous nous concentrons sur les expériences où au
moins un joint a été défectueux.
#+begin_src python :results value :session *python* :exports both
data = data[data.Malfunction>0]
data
#+end_src
#+RESULTS: format.pval, units
: Date Count Temperature Pressure Malfunction
: 1 11/12/81 6 70 50 1
: 8 2/03/84 6 57 200 1
: 9 4/06/84 6 63 200 1
: 10 8/30/84 6 70 200 1
: 13 1/24/85 6 53 200 2
: 20 10/30/85 6 75 200 2
: 22 1/12/86 6 58 200 1
Très bien, nous avons une variabilité de température importante mais
la pression est quasiment toujours égale à 200, ce qui devrait
simplifier l'analyse.
Comment la fréquence d'échecs varie-t-elle avec la température ?
#+begin_src python :results output file :var matplot_lib_filename="freq_temp_python.png" :exports both :session *python*
import matplotlib.pyplot as plt
plt.clf()
data["Frequency"]=data.Malfunction/data.Count
data.plot(x="Temperature",y="Frequency",kind="scatter",ylim=[0,1])
plt.grid(True)
plt.savefig(matplot_lib_filename)
print(matplot_lib_filename)
#+end_src
#+RESULTS:
[[file:freq_temp_python.png]]
À première vue, ce n'est pas flagrant mais bon, essayons quand même Attachement du package : ‘dplyr’
d'estimer l'impact de la température $t$ sur la probabilité de
dysfonctionnements d'un joint.
* Estimation de l'influence de la température The following objects are masked from ‘package:Hmisc’:
Supposons que chacun des 6 joints toriques est endommagé avec la même src, summarize
probabilité et indépendamment des autres et que cette probabilité ne
dépend que de la température. Si on note $p(t)$ cette probabilité, le
nombre de joints $D$ dysfonctionnant lorsque l'on effectue le vol à
température $t$ suit une loi binomiale de paramètre $n=6$ et
$p=p(t)$. Pour relier $p(t)$ à $t$, on va donc effectuer une
régression logistique.
#+begin_src python :results value :session *python* :exports both The following objects are masked from ‘package:stats’:
import statsmodels.api as sm
data["Success"]=data.Count-data.Malfunction filter, lag
data["Intercept"]=1
The following objects are masked from ‘package:base’:
# logit_model=sm.Logit(data["Frequency"],data[["Intercept","Temperature"]]).fit() intersect, setdiff, setequal, union
logmodel=sm.GLM(data['Frequency'], data[['Intercept','Temperature']], family=sm.families.Binomial(sm.families.links.logit)).fit() #+end_example
logmodel.summary() #+begin_src R :results output :session *R* :exports both
summary(df)
str(df)
#+end_src #+end_src
#+RESULTS: #+RESULTS:
#+begin_example #+begin_example
Generalized Linear Model Regression Results Age Malade
============================================================================== Min. :22.01 Min. :0.000
Dep. Variable: Frequency No. Observations: 7 1st Qu.:35.85 1st Qu.:0.000
Model: GLM Df Residuals: 5 Median :50.37 Median :1.000
Model Family: Binomial Df Model: 1 Mean :50.83 Mean :0.515
Link Function: logit Scale: 1.0 3rd Qu.:65.37 3rd Qu.:1.000
Method: IRLS Log-Likelihood: -3.6370 Max. :79.80 Max. :1.000
Date: Fri, 20 Jul 2018 Deviance: 3.3763 'data.frame': 400 obs. of 2 variables:
Time: 16:56:08 Pearson chi2: 0.236 $ Age : num 75.1 76.4 38.6 70.2 59.2 ...
No. Iterations: 5 $ Malade: int 1 1 0 1 1 1 0 0 1 1 ...
===============================================================================
coef std err z P>|z| [0.025 0.975]
-------------------------------------------------------------------------------
Intercept -1.3895 7.828 -0.178 0.859 -16.732 13.953
Temperature 0.0014 0.122 0.012 0.991 -0.238 0.240
===============================================================================
#+end_example #+end_example
L'estimateur le plus probable du paramètre de température est 0.0014 Voici une représentation graphique des données qui permet de mieux
et l'erreur standard de cet estimateur est de 0.122, autrement dit on percevoir le lien qu'il peut y avoir entre l'âge et le fait de
ne peut pas distinguer d'impact particulier et il faut prendre nos contracter cette maladie ou pas :
estimations avec des pincettes. #+begin_src R :results output graphics :file fig1.svg :exports both :width 4 :height 3 :session *R*
ggplot(df,aes(x=Age,y=Malade)) + geom_point(alpha=.3,size=3) + theme_bw()
* Estimation de la probabilité de dysfonctionnant des joints toriques #+end_src
La température prévue le jour du décollage est de 31°F. Essayons
d'estimer la probabilité de dysfonctionnement des joints toriques à
cette température à partir du modèle que nous venons de construire:
#+begin_src python :results output file :var matplot_lib_filename="proba_estimate_python.png" :exports both :session *python*
import matplotlib.pyplot as plt
data_pred = pd.DataFrame({'Temperature': np.linspace(start=30, stop=90, num=121), 'Intercept': 1}) #+ATTR_LATEX: :width 8cm
data_pred['Frequency'] = logmodel.predict(data_pred[['Intercept','Temperature']]) #+RESULTS:
data_pred.plot(x="Temperature",y="Frequency",kind="line",ylim=[0,1]) [[file:fig1.svg]]
plt.scatter(x=data["Temperature"],y=data["Frequency"])
plt.grid(True) Il apparaît clairement sur ces données que plus l'on est âgé, plus la
probabilité de développer cette maladie est importante. Mais comment
estimer cette probabilité à partir uniquement de ces valeurs binaires
(malade/pas malade) ? Pour chaque tranche d'âge (par exemple de 5 ans),
on pourrait regarder la fréquence de la maladie (le code qui suit est
un peu compliqué car le calcul de l'intervalle de confiance pour ce
type de données nécessite un traitement particulier via la fonction
=binconf=).
#+begin_src R :results output graphics :file fig1bis.svg :exports both :width 4 :height 3 :session *R*
age_range=5
df_grouped = df %>% mutate(Age=age_range*(floor(Age/age_range)+.5)) %>%
group_by(Age) %>% summarise(Malade=sum(Malade),N=n()) %>%
rowwise() %>%
do(data.frame(Age=.$Age, binconf(.$Malade, .$N, alpha=0.05))) %>%
as.data.frame()
ggplot(df_grouped,aes(x=Age)) + geom_point(data=df,aes(y=Malade),alpha=.3,size=3) +
geom_errorbar(data=df_grouped,
aes(x=Age,ymin=Lower, ymax=Upper, y=PointEst), color="darkred") +
geom_point(data=df_grouped, aes(x=Age, y=PointEst), size=3, shape=21, color="darkred") +
theme_bw()
#+end_src
plt.savefig(matplot_lib_filename) #+ATTR_LATEX: :width 8cm
print(matplot_lib_filename) #+RESULTS:
[[file:fig1bis.svg]]
L'inconvénient de cette approche est que ce calcul est effectué
indépendemment pour chaque tranches d'âges, que la tranche d'âge est
arbitraire, et qu'on n'a pas grande idée de la façon dont ça
évolue. Pour modéliser cette évolution de façon plus continue, on
pourrait tenter une régression linéaire (le modèle le plus simple
possible pour rendre compte de l'influence d'un paramètre) et ainsi
estimer l'effet de l'âge sur la probabilité d'être malade :
#+begin_src R :results output graphics :file fig2.svg :exports both :width 4 :height 3 :session *R*
ggplot(df,aes(x=Age,y=Malade)) + geom_point(alpha=.3,size=3) +
theme_bw() + geom_smooth(method="lm")
#+end_src #+end_src
#+ATTR_LATEX: :width 8cm
#+RESULTS: #+RESULTS:
[[file:proba_estimate_python.png]] [[file:fig2.svg]]
Comme on pouvait s'attendre au vu des données initiales, la La ligne bleue est la régression linéaire au sens des moindres carrés
température n'a pas d'impact notable sur la probabilité d'échec des et la zone grise est la zone de confiance à 95% de cette
joints toriques. Elle sera d'environ 0.2, comme dans les essais estimation (avec les données dont on dispose et cette hypothèse de
précédents où nous il y a eu défaillance d'au moins un joint. Revenons linéarité, la ligne bleue est la plus probable et il y a 95% de chance
à l'ensemble des données initiales pour estimer la probabilité de que la vraie ligne soit dans cette zone grise).
défaillance d'un joint:
Mais on voit clairement dans cette représentation graphique que cette
#+begin_src python :results output :session *python* :exports both estimation n'a aucun sens. Une probabilité doit être comprise entre 0
data = pd.read_csv("shuttle.csv") et 1 et avec une régression linéaire on arrivera forcément pour des
print(np.sum(data.Malfunction)/np.sum(data.Count)) valeurs un peu extrêmes (jeune ou âgé) à des prédictions aberrantes
(négative ou supérieures à 1). C'est tout simplement dû au fait qu'une
régression linéaire fait l'hypothèse que $\textsf{Malade} =
\alpha.\textsf{Age} + \beta + \epsilon$, où $\alpha$ et $\beta$ sont des nombres réels et $\epsilon$
est un bruit (une variable aléatoire de moyenne nulle), et estime $\alpha$
et $\beta$ à partir des données.
Cette technique n'a pas de sens pour estimer une probabilité et il
convient donc d'utiliser ce que l'on appelle une [[https://fr.wikipedia.org/wiki/R%C3%A9gression_logistique][régression
logistique]] :
#+begin_src R :results output graphics :file fig3.svg :exports both :width 4 :height 3 :session *R*
ggplot(df,aes(x=Age,y=Malade)) + geom_point(alpha=.3,size=3) +
theme_bw() +
geom_smooth(method = "glm",
method.args = list(family = "binomial")) + xlim(20,80)
#+end_src #+end_src
#+ATTR_LATEX: :width 8cm
#+RESULTS: #+RESULTS:
: 0.06521739130434782 [[file:fig3.svg]]
Cette probabilité est donc d'environ $p=0.065$, sachant qu'il existe Ici, la bibliothèque =ggplot= fait tous les calculs de régression
un joint primaire un joint secondaire sur chacune des trois parties du logistique pour nous et nous montre uniquement le résultat "graphique"
lançeur, la probabilité de défaillance des deux joints d'un lançeur mais dans l'analyse que nous vous proposerons pour Challenger, nous
est de $p^2 \approx 0.00425$. La probabilité de défaillance d'un des réalisons la régression et la prédiction à la main (en =R= ou en =Python=
lançeur est donc de $1-(1-p^2)^3 \approx 1.2%$. Ça serait vraiment selon le parcours que vous choisirez) de façon à pouvoir effectuer si
pas de chance... Tout est sous contrôle, le décollage peut donc avoir besoin une inspection plus fine. Comme avant, la courbe bleue indique
lieu demain comme prévu. l'estimation de la probabilité d'être malade en fonction de l'âge et
la zone grise nous donne des indications sur l'incertitude de cette
Seulement, le lendemain, la navette Challenger explosera et emportera estimation, i.e., "sous ces hypothèses et étant donné le peu de
avec elle ses sept membres d'équipages. L'opinion publique est données qu'on a et leur variabilité, il y a 95% de chances pour que la
fortement touchée et lors de l'enquête qui suivra, la fiabilité des vraie courbe se trouve quelque part (n'importe où) dans la zone
joints toriques sera directement mise en cause. Au delà des problèmes grise".
de communication interne à la NASA qui sont pour beaucoup dans ce
fiasco, l'analyse précédente comporte (au moins) un petit Dans ce modèle, on suppose que $P[\textsf{Malade}] = \pi(\textsf{Age})$ avec
problème... Saurez-vous le trouver ? Vous êtes libre de modifier cette $\displaystyle\pi(x)=\frac{e^{\alpha.x + \beta}}{1+e^{\alpha.x + \beta}}$. Cette
analyse et de regarder ce jeu de données sous tous les angles afin formule (étrange au premier abord) a la bonne propriété de nous donner
d'expliquer ce qui ne va pas. systématiquement une valeur comprise entre 0 et 1 et de bien tendre
rapidement vers $0$ quand l'âge tend vers $-\infty$ et vers $1$ quand l'âge
tend vers $+\infty$ (mais ce n'est pas bien sûr pas la seule motivation).
En conclusion, lorsque l'on dispose de données évènementielles
(binaires) et que l'on souhaite estimer l'influence d'un paramètre sur
la probabilité d'occurrence de l'évènement (maladie, défaillance...),
le modèle le plus naturel et le plus simple est celui de la
régression logistique. Notez, que même en se restreignant à une petite
partie des données (par exemple, uniquement les patients de moins de
50 ans), il est possible d'obtenir une estimation assez raisonnable,
même si, comme on pouvait s'y attendre, l'incertitude augmente
singulièrement.
#+begin_src R :results output graphics :file fig4.svg :exports both :width 4 :height 3 :session *R*
ggplot(df[df$Age<50,],aes(x=Age,y=Malade)) + geom_point(alpha=.3,size=3) +
theme_bw() +
geom_smooth(method = "glm",
method.args = list(family = "binomial"),fullrange = TRUE) + xlim(20,80)
#+end_src
#+ATTR_LATEX: :width 8cm
#+RESULTS:
[[file:fig4.svg]]
* Emacs Setup :noexport:
This document has local variables in its postembule, which should
allow Org-mode (9) to work seamlessly without any setup. If you're
uncomfortable using such variables, you can safely ignore them at
startup. Exporting may require that you copy them in your .emacs.
# Local Variables:
# eval: (add-to-list 'org-latex-packages-alist '("" "minted"))
# eval: (setq org-latex-listings 'minted)
# eval: (setq org-latex-minted-options '(("style" "Tango") ("bgcolor" "Moccasin") ("frame" "lines") ("linenos" "true") ("fontsize" "\\small")))
# eval: (setq org-latex-pdf-process '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
# End:
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment