]> git.donarmstrong.com Git - using_make_for_science.git/blob - using_make_for_science.Rnw
add relevant xkcd
[using_make_for_science.git] / using_make_for_science.Rnw
1 \documentclass[ignorenonframetext]{beamer}
2 \usepackage[Symbols,MiscellaneousSymbols]{ucharclasses}
3 \usepackage{fontspec}
4 % \usepackage{bidi}
5 \setmainfont{FreeSerif}
6 \setsansfont{FreeSans}
7 \setmonofont{FreeMono}
8
9 \usepackage{array}
10 \usepackage{fancyref}
11 \usepackage{booktabs}
12 \usepackage{threeparttable}
13 \usepackage[backend=biber,natbib=true,hyperref=true,style=numeric-comp]{biblatex}
14 \bibliography{references}
15 \usepackage[nomargin,inline,draft]{fixme}
16 \usepackage{texshade}
17 \usepackage{tikz}
18 \usepackage{nameref}
19 \usepackage{zref-xr,zref-user}
20 \usepackage{metalogo}
21 \IfFileExists{upquote.sty}{\usepackage{upquote}}{}
22 \mode<article>{
23   \usepackage[x11names,svgnames,usenames,dvipsnames]{xcolor}
24   \usepackage[noxcolor]{beamerarticle}
25   \usepackage{fancyhdr}
26   \usepackage{graphicx}
27   \usepackage[bf]{caption}
28   \usepackage{rotating}
29   \usepackage{setspace}
30   \usepackage{acronym}
31   \usepackage{dcolumn}
32   \usepackage{adjustbox}
33   \usepackage{longtable}
34   \usepackage{geometry}
35   \usepackage{pdflscape}
36   \usepackage[hyperfigures,bookmarks,colorlinks]{hyperref}
37   \oddsidemargin 0.0in 
38   \textwidth 6.5in
39   \raggedbottom
40   \clubpenalty = 10000
41   \widowpenalty = 10000
42   \pagestyle{fancy}
43 }
44
45 \usepackage{minted}
46 \usepackage{tcolorbox}
47 \usepackage{etoolbox}
48 \BeforeBeginEnvironment{minted}{\begin{tcolorbox}}%
49 \AfterEndEnvironment{minted}{\end{tcolorbox}}%
50
51 \mode<presentation>{ 
52   \usetheme{CambridgeUS}
53   % http://identitystandards.illinois.edu/graphicstandardsmanual/generalguidelines/colors.html
54   \definecolor{ilboldblue}{HTML}{002058}
55   \definecolor{ilboldorange}{HTML}{E87722}
56   \definecolor{ilblue}{HTML}{606EB2}
57   \definecolor{ilorange}{HTML}{D45D00}
58   \setbeamercolor{alerted text}{fg=ilboldblue}
59   \setbeamercolor*{palette primary}{fg=ilblue,bg=ilorange}
60   \setbeamercolor*{palette secondary}{fg=ilblue!20!white,bg=ilorange}
61   \setbeamercolor*{palette tertiary}{bg=ilblue,fg=ilorange}
62   \setbeamercolor*{palette quaternary}{fg=ilblue,bg=ilorange}
63   
64   \setbeamercolor*{sidebar}{fg=ilorange,bg=ilboldblue}
65   
66   \setbeamercolor*{palette sidebar primary}{fg=ilblue!10!white,bg=ilorange}
67   \setbeamercolor*{palette sidebar secondary}{fg=ilorange}
68   \setbeamercolor*{palette sidebar tertiary}{fg=ilblue}
69   \setbeamercolor*{palette sidebar quaternary}{fg=ilorange}
70   
71   % \setbeamercolor*{titlelike}{parent=palette primary}
72   \setbeamercolor{titlelike}{parent=palette primary,fg=ilboldblue,bg=ilorange}
73   \setbeamercolor{frametitle}{fg=ilboldorange,bg=ilblue!80!white}
74   \setbeamercolor{frametitle right}{fg=ilboldblue,bg=ilorange}
75   
76   \setbeamercolor*{separation line}{}
77   \setbeamercolor*{fine separation line}{}
78   \setbeamercovered{transparent}  
79   \logo{\begin{tikzpicture}% Pale figure
80       {\node[opacity=0.7]{\IfFileExists{./logo.pdf}{\includegraphics[height=1.5cm]{logo.pdf}}{}%
81         };}%
82     \end{tikzpicture}}
83 }
84
85 \title{Using make for science}
86
87 \author{Don Armstrong}
88 \date{\today}
89 \subject{make for science}
90 \begin{document}
91
92 \IfFileExists{./relevant_xkcd.png}{\frame[plain]{\centering \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{./relevant_xkcd.png}}}
93
94 \frame[plain]{\titlepage}
95
96 \mode<article>{\maketitle}
97
98 \section{What make was made for}
99 \begin{frame}{What was make originally made to do?}
100   \begin{itemize}
101   \item Compiling and installing software from source
102   \item Replacement of operating system specific compilation and
103     installation shell scripts
104   \item Re-compile when dependencies of the software were modified
105   \end{itemize}
106 \end{frame}
107
108 \subsection{Brief history of makes}
109
110 \begin{frame}{Brief history of make-alikes}
111   \begin{itemize}
112   \item
113     \href{http://pubs.opengroup.org/onlinepubs/009695399/utilities/make.html}{POSIX
114       Make} (standardization of basic features of make)
115   \item \href{http://www.gnu.org/software/make/manual/}{GNU Make}
116     (standard make on Linux and OS X)
117   \item \href{https://www.freebsd.org/cgi/man.cgi?query=make(1)}{BSD
118       Make} (pmake or bmake)
119   \item
120     \href{https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx}{nmake}
121     (Part of visual studio)
122   \item \href{http://plan9.bell-labs.com/sys/doc/mk.html}{Mk} (Plan 9
123     replacement of make)
124   \end{itemize}
125 \end{frame}
126
127 \subsection{Other solutions in this problem space}
128
129 \begin{frame}{Other non-make dependency builders}
130   \begin{itemize}
131   \item Ant (popular for java software)
132   \item Cabal (popular for Haskell)
133   \item Maven (also java)
134   \item Rake (ruby build took)
135   \item Gradle (Rake DSL)
136   \item Leiningen (Clojure)
137   \item Tweaker (task definitions in any language)
138   \item Ruffus (Pipeline library for python)
139   \item
140     \href{https://en.wikipedia.org/wiki/List_of_build_automation_software}{Wikipedia
141       List of build automation software}
142   \end{itemize}
143 \end{frame}
144
145 \subsection{Why use GNU make?}
146 \begin{frame}{Why use GNU make?}
147   \begin{itemize}
148   \item Ubiquitous -- any machine which you can run command line tools
149     on has GNU make available.
150   \item Large community -- lots of people use GNU make. It's well
151     understood and you can get questions answered
152   \item Simple rules -- all of the rules are in a simple text file
153     which is easily edited and version controlled
154   \item Reasonable debugging -- you can see the commands that make is
155     going to run fairly easily: \mintinline{shell}{make -n target;}
156   \item Parallel -- make can make targets in parallel:
157     \mintinline{shell}{make -j8 all;}
158   \item Language agnostic -- make doesn't care what language your code
159     is written in
160   \end{itemize}
161 \end{frame}
162
163 \section{Introduction to Makefiles}
164
165 \begin{frame}[fragile]{Simple Makefile}
166 \begin{minted}[showtabs]{make}
167 hello_world:
168         echo "hello world" > hello_world
169 \end{minted}
170
171 \end{frame}
172
173 \subsection{General Syntax}
174
175 \begin{frame}[fragile]{Simple Makefile}
176 \begin{minted}[showtabs]{make}
177 TARGETS: PREREQUISITES
178         RECIPE
179 \end{minted}
180 \begin{itemize}
181 \item TARGETS are file names separated by spaces
182 \item PREREQUISITES are file names separated by spaces.
183 \item RECIPE lines start with a tab, are executed by the shell and
184   describe how to make the TARGETS (generally from the PREREQUISITES)
185 \item A TARGET is out of date if it does not exist or if it is older
186   than any of the prerequisites.
187 \end{itemize}
188 \end{frame}
189
190 \subsection{Variables}
191
192 \begin{frame}[fragile]{Some Variables}
193 \begin{itemize}
194 \item Two flavors of variables
195   \begin{itemize}
196   \item \mintinline{make}{FOO=bar} -- recursively expanded variables;
197     references to other variables are expanded at the time this
198     variable is expanded
199   \item \mintinline{make}{FOO:=bar} -- simply expanded variables; the
200     value is assigned at the moment the variable is created
201   \end{itemize}
202 \item Variables can come from the environment and can be overridden on
203   the command line: \mintinline{shell}{make FOO=bleargh} or
204   \mintinline{shell}{FOO=blah make}.
205 \item \mintinline{make}{$@} -- target name %$
206 \item \mintinline{make}{$*} -- current stem %$ 
207 \item \mintinline{make}{$^} -- all prerequisites %$
208 \item \mintinline{make}{$<} -- first prerequisite %$
209 \item \mintinline{make}{$(FOO)} -- how variables are referenced %$
210 \end{itemize}
211 \end{frame}
212
213 \subsection{Functions}
214
215 \begin{frame}[fragile]{Some Functions}
216   \begin{itemize}
217   \item \mintinline{make}{$(patsubst %.bam,%.sam,foo.sam bar.sam)} %$
218       -- returns foo.bam bar.bam.
219   \item \mintinline{make}{$(filter-out %.bam,foo.sam bar.bam)} %$
220       -- returns foo.sam
221   \item \mintinline{make}{$(words foo.sam bar.bam)} %$
222       -- returns the number of words in its argument (2)
223   \item \mintinline{make}{$(wordlist 1,2,foo.sam bar.bam bleargh.foo)} %$
224       -- returns the words in its last argument starting with the 1st
225       and ending with the second.
226   \end{itemize}
227 \end{frame}
228
229 \subsection{Rules}
230
231 \subsubsection{Default Target}
232
233 \begin{frame}[fragile]{How does make know what to build?}
234 \begin{minted}[showtabs]{make}
235 first_target: 
236         touch $@
237 second_target: first_target
238         touch $@
239 \end{minted}
240   \begin{itemize}
241   \item By default, make builds the first target.
242   \item You can specify a specific target to build on the command line
243     (\mintinline{shell}{make first_target}).
244   \item You can change the default target by using the variable
245     \mintinline{make}{.DEFAULT_GOAL := second_target}
246   \end{itemize}
247 \end{frame}
248
249
250 \subsubsection{Special Targets}
251
252 \begin{frame}[fragile]{Special Targets}
253 \begin{minted}[showtabs]{make}
254 .PHONY: clean
255
256 clean:
257         rm -f first_target second_target
258 \end{minted}
259   \begin{itemize}
260   \item \mintinline{make}{.PHONY} -- any time make considers this
261     target, it is run unconditionally, even if a file exists.
262   \item \mintinline{make}{.ONESHELL} -- when a target is built, all
263     lines will be given to a single invocation of the shell.
264   \item Lots of other special targets which are not described here.
265   \end{itemize}
266 \end{frame}
267
268
269 \subsubsection{Pattern Rules}
270
271
272 \begin{frame}[fragile]{Special Targets}
273 \begin{minted}[showtabs]{make}
274 %.fasta.gz: %.fasta
275         gzip -dc $< > $@
276
277 %.bam: %.sam
278         samtools view -b -o $@ $<
279 \end{minted}
280   \begin{itemize}
281   \item \% is the pattern stem which is accessible by
282     \mintinline{make}{$*} %$ within rules
283   \item The first rule uncompresses fasta files
284   \item The second rule turns sam files into bam files
285   \end{itemize}
286 \end{frame}
287
288 \section{Examples}
289
290 \subsection{This Presentation}
291
292 \begin{frame}[fragile]{How this presentation is made}
293 \inputminted[showtabs,breaklines,firstline=3]{make}{Makefile}
294 \end{frame}
295 \begin{frame}[fragile]{How this presentation is made}
296   \begin{itemize}
297   \item all is the default 
298   \item Download the optional relevant\_xkcd.png
299   \item Make .tex files from the knitr source.
300   \item The third rule uses latexmk to build the pdf using \XeLaTeX.
301   \end{itemize}
302 \end{frame}
303
304 \subsection{Calling records from SRA}
305
306 \begin{frame}{Calling records from SRA: The problem}
307   \begin{itemize}
308   \item ≈200 tissue samples from Roadmap Epigenomics
309   \item No consistent workflow
310   \item Reanalyze them all using STAR and cufflinks
311   \end{itemize}
312 \end{frame}
313
314 \begin{frame}[fragile]{Calling records from SRA: Downloading}
315 \begin{minted}[showtabs,breaklines]{make}
316 SRX=SRX007165
317 SRRS=SRR020291 SRR020290
318 NREADS=1
319 SRR_FILES=$(patsubst %,%.sra,$(SRRS))
320
321 get_srr: $(SRR_FILES)
322
323 $(SRR_FILES): %.sra:
324         rsync -avP "rsync://ftp-trace.ncbi.nlm.nih.gov/sra/sra-instant/reads/ByRun/sra/SRR/$(shell echo -n $*|sed 's/\(SRR[0-9][0-9][0-9]\).*/\1/')/$*/$*.sra" $@;
325 \end{minted}
326 %$
327   \begin{itemize}
328   \item First three lines are actually generated by other code and
329     included
330   \item Download all of the SRA files using rsync
331   \end{itemize}
332 \end{frame}
333
334 \begin{frame}[fragile]{Calling records from SRA: Dumping fastq}
335 \begin{minted}[showtabs,breaklines]{make}
336 ifeq ($(NREADS),1)
337 FASTQ_FILES:=$(patsubst %,%.fastq.gz,$(SRRS))
338 else
339 FASTQ_FILES:=$(patsubst %,%_1.fastq.gz,$(SRRS))  $(patsubst %,%_2.fastq.gz,$(SRRS))
340 endif
341
342 make_fastq: $(FASTQ_FILES)
343 \end{minted}
344 %$
345 \begin{itemize}
346 \item Use ifeq/else/endif to handle paired reads differently from
347   unpaired reads
348 \item FASTQ\_FILES is the full set of fastq files dumped from the SRAs.
349 \end{itemize}
350 \end{frame}
351
352 \begin{frame}[fragile]{Calling records from SRA: Dumping fastq #2}
353 \begin{minted}[showtabs,breaklines]{make}
354 ifeq ($(NREADS),1)
355 $(FASTQ_FILES): %.fastq.gz: %.sra
356 else
357 %_1.fastq.gz %_2.fastq.gz: %.sra
358 endif
359         $(MODULE) load sratoolkit/2.3.5-2; \
360         fastq-dump --split-3 --gzip $^;
361 \end{minted}
362 %$
363   \begin{itemize}
364   \item Handles NREADS of 1 and 2 differently
365   \item Call fastq-dump to dump the fastq files
366   \end{itemize}
367 \end{frame}
368
369 \begin{frame}[fragile]{Calling records from SRA: Align with STAR}
370 \begin{minted}[showtabs,breaklines]{make}
371 $(SRX)_star.bam:
372         $(MODULE) load STAR/2.4.2a; \
373         mkdir -p $(SRX)_star; \
374         STAR --outFileNamePrefix $(SRX)_star/ \
375         --outSAMtype BAM SortedByCoordinate \
376         --runThreadN $(CORES) \
377         --outSAMstrandField intronMotif \
378         --genomeDir $(STAR_INDEX_DIR) \
379         --readFilesCommand "gzip -dc" \
380         --readFilesIn $(TOPHAT_FASTQ_ARGUMENT);
381         ln $(SRX)_star/Aligned.*.bam $@ -s
382 \end{minted}
383 %$
384   \begin{itemize}
385   \item Call STAR with lots of options to do the alignment
386   \end{itemize}
387 \end{frame}
388
389 \begin{frame}[fragile]{Calling records from SRA: Call with cufflinks}
390 \begin{minted}[showtabs,breaklines]{make}
391 call: $(SRX)_genes.fpkm_tracking
392
393 $(SRX)_genes.fpkm_tracking: $(SRX)_star.bam $(BOWTIE_INDEX_DIR)$(GTF)
394         $(MODULE) load cufflinks/2.2.1; \
395         cufflinks -p $(CORES) -G $(wordlist 2,2,$^) $<
396         for file in genes.fpkm_tracking isoforms.fpkm_tracking skipped.gtf transcripts.gtf; do \
397                 mv $${file} $(SRX)_$${file}; \
398         done;
399 \end{minted}
400 %$
401   \begin{itemize}
402   \item Use cufflinks to call
403   \end{itemize}
404 \end{frame}
405
406 \begin{frame}[fragile]{Run it on biocluster}
407   \begin{minted}{shell}
408 ~donarm/uiuc_igb_scripts/dqsub --mem 70G \
409    --ppn 8 make call;
410 \end{minted}
411 \begin{itemize}
412 \item dqsub is my own qsub wrapper which avoids me having to write
413   little scripts for everything
414 \item \url{http://git.donarmstrong.com/?p=uiuc_igb_scripts.git;a=blob;f=dqsub}
415 \end{itemize}
416 \end{frame}
417
418 \section{Why not make?}
419
420 \begin{frame}{Why not make?}
421   \begin{itemize}
422   \item Timestamps, not MD5sums
423   \item Complicated workflows
424   \end{itemize}
425 \end{frame}
426
427 \subsection{Timestamps}
428
429 \begin{frame}[fragile]{Dealing with timestamps}
430   \begin{minted}[showtabs,breaklines]{make}
431 TARGET: PREREQ1 PREREQ1
432         if [ -e $@.tgt.md5sum ] && [ -e $@ ] \
433            && md5sum --status --check \
434            $@.tgt.md5sum; then \
435          touch $@; \
436         else \
437          RECIPE FOR $@; \
438          md5sum $^ > $@.tgt.md5sum; \
439         fi;
440 \end{minted}
441 % $
442 \begin{itemize}
443 \item Make builds things on the basis of timestamps
444 \item But what if the contents haven't changed and it's expensive to
445   rebuild?
446 \item Use md5sum!
447 \end{itemize}
448 \end{frame}
449
450 \subsection{Complicated Workflows}
451
452 \begin{frame}[fragile]{What about complicated workflows?}
453   \begin{itemize}
454   \item If your workflow is really complicated, what then?
455   \item Use some other language to write your workflow in
456   \item Use a simple makefile which just runs the workflow
457   \end{itemize}
458   \begin{minted}[showtabs,breaklines]{make}
459 complicated_workflow_done: req1 req2 req3
460         ./complicated_workflow.sh $^;
461         touch $@;
462 \end{minted}
463 \end{frame}
464
465 \section{Further Resources}
466
467 \begin{frame}{Further Resources}
468   \begin{itemize}
469   \item GNU Make Manual: \url{https://www.gnu.org/software/make/manual/}
470   \item Mailing lists: \url{http://www.gnu.org/software/make/}
471   \item Stack overflow: \url{http://stackoverflow.com/questions/tagged/make}
472   \item Myself: \href{mailto:don@donarmstrong.com}{don@donarmstrong.com}
473   \item This presentation: \url{http://git.donarmstrong.com/using\_make\_for\_science.git}
474   \end{itemize}
475 \end{frame}
476
477 \end{document}