├── images
├── pdf.png
├── cc_by_4p0.png
├── arrow-down.png
├── octocat-small.png
├── figure_2
│ ├── period_000009.svg
│ ├── period_000008.svg
│ ├── period_000007.svg
│ ├── period_000006.svg
│ ├── period_000005.svg
│ └── period_000004.svg
└── figure_3
│ └── period_000004.svg
├── javascript
├── python-highlighting
│ ├── readme.txt
│ └── prism.js
├── google-analytics
│ ├── readme.txt
│ └── analytics.js
├── Minimal-MathJax
│ ├── fonts
│ │ └── HTML-CSS
│ │ │ └── TeX
│ │ │ └── woff
│ │ │ ├── MathJax_Math-Italic.woff
│ │ │ ├── MathJax_Main-Regular.woff
│ │ │ ├── MathJax_Size2-Regular.woff
│ │ │ ├── MathJax_Size3-Regular.woff
│ │ │ └── MathJax_Size4-Regular.woff
│ ├── readme.txt
│ └── jax
│ │ └── output
│ │ └── CommonHTML
│ │ ├── fonts
│ │ └── TeX
│ │ │ └── AMS-Regular.js
│ │ └── autoload
│ │ └── mtable.js
├── scale-fix
│ └── scale.fix.js
├── reference_list
│ └── reference_list.js
├── update_figures.js
├── README.md
└── html5shiv
│ └── html5shiv.js
├── Publication_template by AndrewGYork.pdf
├── LICENSE
├── figure_generation
├── figure_1.py
├── figure_2.py
└── figure_3.py
├── README.md
├── stylesheets
├── prism.css
└── styles.css
└── index.html
/images/pdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/images/pdf.png
--------------------------------------------------------------------------------
/javascript/python-highlighting/readme.txt:
--------------------------------------------------------------------------------
1 | Python syntax highlighting, via http://prismjs.com/
2 |
--------------------------------------------------------------------------------
/images/cc_by_4p0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/images/cc_by_4p0.png
--------------------------------------------------------------------------------
/images/arrow-down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/images/arrow-down.png
--------------------------------------------------------------------------------
/images/octocat-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/images/octocat-small.png
--------------------------------------------------------------------------------
/javascript/google-analytics/readme.txt:
--------------------------------------------------------------------------------
1 | This Google Analytics snippet is specific to me; you should replace it with your own.
2 |
--------------------------------------------------------------------------------
/Publication_template by AndrewGYork.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/Publication_template by AndrewGYork.pdf
--------------------------------------------------------------------------------
/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Math-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Math-Italic.woff
--------------------------------------------------------------------------------
/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Main-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Main-Regular.woff
--------------------------------------------------------------------------------
/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Size2-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Size2-Regular.woff
--------------------------------------------------------------------------------
/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Size3-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Size3-Regular.woff
--------------------------------------------------------------------------------
/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Size4-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndrewGYork/publication_template/HEAD/javascript/Minimal-MathJax/fonts/HTML-CSS/TeX/woff/MathJax_Size4-Regular.woff
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This work is licensed under the Creative Commons Attribution 4.0 International License.
2 | To view a copy of this license, visit:
3 | http://creativecommons.org/licenses/by/4.0/
4 | or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
5 |
--------------------------------------------------------------------------------
/javascript/Minimal-MathJax/readme.txt:
--------------------------------------------------------------------------------
1 | I want to use MathJax, but I don't want to rely on an internet connection (e.g. when I'm editing a local copy offline).
2 |
3 | I followed the recipe described here:
4 | https://tiborsimon.io/articles/web/minimal-mathjax/
5 | Starting from MathJax 2.7.0. ~500kB and a handful of files, so far. Not bad!
6 |
--------------------------------------------------------------------------------
/javascript/google-analytics/analytics.js:
--------------------------------------------------------------------------------
1 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
3 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
4 | })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
5 | ga('create', 'UA-90305913-1', 'auto');
6 | ga('send', 'pageview');
7 |
--------------------------------------------------------------------------------
/figure_generation/figure_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | import numpy as np
3 | import matplotlib.pyplot as plt
4 |
5 | assert os.path.isdir('./../images')
6 | if not os.path.isdir('./../images/figure_1'):
7 | os.mkdir('./../images/figure_1')
8 | x = np.linspace(0, 10, 1000)
9 | period = 2
10 | fig = plt.figure(figsize=(7, 3))
11 | plt.plot(x, np.sin(2 * np.pi * x / period))
12 | plt.xlim(x.min(), x.max())
13 | plt.ylim(-1, 1)
14 | plt.grid()
15 | plt.savefig('./../images/figure_1/period_%06i.svg'%period)
16 |
--------------------------------------------------------------------------------
/figure_generation/figure_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | import numpy as np
3 | import matplotlib.pyplot as plt
4 |
5 | assert os.path.isdir('./../images')
6 | if not os.path.isdir('./../images/figure_2'):
7 | os.mkdir('./../images/figure_2')
8 | x = np.linspace(0, 10, 1000)
9 | for period in np.arange(1, 10):
10 | fig = plt.figure(figsize=(7, 3))
11 | plt.plot(x, np.sin(2 * np.pi * x / period))
12 | plt.xlim(x.min(), x.max())
13 | plt.ylim(-1, 1)
14 | plt.grid()
15 | plt.savefig('./../images/figure_2/period_%06i.svg'%period)
16 |
--------------------------------------------------------------------------------
/javascript/scale-fix/scale.fix.js:
--------------------------------------------------------------------------------
1 | fixScale = function(doc) {
2 | var addEvent = 'addEventListener',
3 | type = 'gesturestart',
4 | qsa = 'querySelectorAll',
5 | scales = [1, 1],
6 | meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : [];
7 |
8 | function fix() {
9 | meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1];
10 | doc.removeEventListener(type, fix, true);
11 | }
12 | if ((meta = meta[meta.length - 1]) && addEvent in doc) {
13 | fix();
14 | scales = [.25, 1.6];
15 | doc[addEvent](type, fix, true);
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/figure_generation/figure_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | import numpy as np
3 | import matplotlib.pyplot as plt
4 |
5 | # We're going to make a single 'local' image:
6 | assert os.path.isdir('./../images')
7 | if not os.path.isdir('./../images/figure_3'):
8 | os.mkdir('./../images/figure_3')
9 | # ...and a bunch of images (for an interactive figure) in a separate
10 | # directory:
11 | if not os.path.isdir('./../../big_images'):
12 | os.mkdir('./../../big_images/')
13 | if not os.path.isdir('./../../big_images/figure_3'):
14 | os.mkdir('./../../big_images/figure_3')
15 | x = np.linspace(0, 10, 1000)
16 | for period in np.arange(1, 10):
17 | fig = plt.figure(figsize=(7, 3))
18 | plt.plot(x, np.sin(2 * np.pi * x / period))
19 | plt.xlim(x.min(), x.max())
20 | plt.ylim(-1, 1)
21 | plt.grid()
22 | if period == 4:
23 | # Save one local placeholder for the interactive figure
24 | plt.savefig('./../images/figure_3/period_%06i.svg'%period)
25 | # Save the rest of the interactive figure in a separate directory:
26 | plt.savefig('./../../big_images/figure_3/period_%06i.svg'%period)
27 |
--------------------------------------------------------------------------------
/javascript/reference_list/reference_list.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", function(event) {
2 | already_included = "";
3 | list_of_refs = document.createElement("ol");
4 | var links = document.getElementsByClassName("citation");
5 | for(var i = 0; i < links.length; i++){
6 | if (!(already_included.indexOf(links[i].innerText) >= 0)) {
7 | already_included = already_included.concat(links[i].innerText);
8 | li = document.createElement("li");
9 | li.appendChild(document.createTextNode("["));
10 | lnk = document.createElement("a");
11 | lnk.href = links[i].href;
12 | lnk.innerText = links[i].innerText;
13 | li.appendChild(lnk);
14 | li.appendChild(document.createTextNode(
15 | "] "+links[i].title+" "+links[i].href));
16 | list_of_refs.appendChild(li);
17 | }
18 | }
19 | if (links.length > 0) {
20 | sections = document.body.getElementsByTagName("section");
21 | last_section = sections[sections.length - 1];
22 | heading = document.createElement("h3");
23 | heading.appendChild(document.createTextNode("References"));
24 | last_section.appendChild(heading);
25 | last_section.appendChild(list_of_refs);
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A template for writing scientific papers
2 |
3 |
4 | View it in action here:
5 | https://andrewgyork.github.io/publication_template/
6 |
7 | This repository is intended to hold a (mostly) self-contained scientific publication. It contains:
8 |
9 | * HTML, javascript, and small images (index.html, and in the javascript and images directories)
10 | * Code which produces figures (in the `figure_code` directory)
11 |
12 | Some files aren't suitable for version control, (e.g. raw data, large numbers of pre-rendered figure images, etc). These are stored in a sister repository:
13 |
14 | https://github.com/AndrewGYork/publication_template_data
15 |
16 | Hopefully this makes it easier to nuke the version control history for big, non-text files without risking the small, important text-based files stored here.
17 |
18 | This work is licensed under a Creative Commons Attribution 4.0 International License
19 |
--------------------------------------------------------------------------------
/javascript/update_figures.js:
--------------------------------------------------------------------------------
1 | // Figure 2 interactively loads static images, stored locally
2 | function update_figure_2() {
3 | var period = document.getElementById("Figure_2_period").value;
4 | var filename = "./images/figure_2/period_" + period + ".svg";
5 | var image = document.getElementById("Figure_2_image");
6 | image.src = filename;
7 | }
8 |
9 | // Figure 3 interactively loads static images.
10 | // Check if our big images are available locally or remotely:
11 | var big_image_directory = "./../big_images";
12 | var img = new Image();
13 | img.onerror = function() {
14 | window.big_image_directory = "https://andrewgyork.github.io/publication_template_data/big_images";
15 | img.onerror = function() {
16 | window.big_image_directory = "";
17 | img.onerror = "";
18 | window.alert("Interactive images not found.");
19 | }
20 | img.src = big_image_directory + "/figure_3/period_000004.svg"
21 | }
22 | img.onload = function() {
23 | console.log("Loading interactive images from: " + big_image_directory)
24 | }
25 | img.src = big_image_directory + "/figure_3/period_000004.svg"
26 |
27 | function update_figure_3() {
28 | var period = document.getElementById("Figure_3_period").value;
29 | var filename = big_image_directory + "/figure_3/period_" + period + ".svg";
30 | var image = document.getElementById("Figure_3_image");
31 | image.src = filename;
32 | }
33 |
--------------------------------------------------------------------------------
/javascript/README.md:
--------------------------------------------------------------------------------
1 | `update_figures.js` is specific code, hand-written to animate the figures in this particular publication. If you copy this publication as a template, you'll have to rewrite this file yourself (or just use static figures).
2 |
3 | You should also delete or modify the `google-analytics/analytics.js` script, since the tracking code is specific to me.
4 |
5 | `reference_list/reference_list.js` is more general code; it's intended to search the document for citations formatted in a particular way, and append a (not too ugly) list of references to the end of the document. It's intended to stay the same every time the template is used, unless the user wants to do their reference list a different way.
6 |
7 | `scale-fix/scale-fix.js` came with the template that I based my work on, ['dinky' by 'broccolini'](https://github.com/broccolini/dinky). I believe it helps the document scale correctly for different size screens. It's possible that it's not doing anything, and it's just cruft, but I haven't taken the time to understand. Incidentally, 'broccolini' mentioned in their original work that 'attribution is not necessary but it is appreciated', so I put an attribution in a comment in index.html; if you copy this publication as a template, I'd appreciate it if this attribution remains.
8 |
9 | `html5shiv/html5shiv.js` is from [HTML5 boilerplate](https://html5boilerplate.com/). As I understand it, this file helps make HTML5 work with old versions of IE, but I haven't tested this extensively.
10 |
11 | `python-highlighting/prism.js` is from [prismjs.com/](http://prismjs.com/); the version I included allows python sytnax highlighting for code inside `
64 | Note that this is a limited PDF or print version; animated and interactive figures are disabled. For the full version of this article, please visit https://andrewgyork.github.io/publication_template
65 |
66 |
68 |
69 |
70 | Examples
71 |
Scientific papers from my lab which use this template:
80 | Version control tools like Git, Github, and Github Pages are great for developing, sharing, and documenting code. Why not for science, too? Consider the following workflow:
81 |
82 |
83 |
Discover or invent something. This is supposed to be the hard part. For me, this invariably involves writing wild and wooly exploratory Python code, which goes in a private Github repository, if I'm behaving myself.
84 |
Collect results into intelligible figures. I usually do this via Python code, which also belongs in a private Github repository.
85 |
Write explanatory text. I've always found this step is a mess. No set of tools I've tried (e.g. Word, LaTeX, Google Docs) fit my workflow (e.g. collaboration, version control, formatting). An HTML/CSS template with math typesetting, code syntax highlighting, and automatic reference listing (via Javascript) fits me perfectly - and allows collaborative writing via a private Github repo!
86 |
Circulate preprints. Existing options like email, arXiv, or bioR\(\chi\)iv are great, but it's 2016 - why are we using PDFs? The web makes sharing data, code, animations, and interactive figures straightforward. If the code, data, and HTML are already on Github, then sharing a preprint is as simple as activating Github Pages.
87 |
Submit for peer review. Historically, a huge mess. Much has been written about the unfortunate state of academic publishing. Why not cut out the middleman and solicit review directly from qualified colleagues? (A much longer discussion, and beyond the scope of this document - but I want to try it.)
88 |
Archive for posterity. I want my work to exist after I die, in an open, available and citable form. Github, Github Pages, and Zenodo address these problems cleanly (although there's room for improvement).
89 |
90 |
91 |
I've been careful about dependencies; Git and Github are helpful, but not required. You can download a .zip of this repository, edit index.html with a text editor, and view the results with a web browser. I avoid Javascript which loads via the web, so you can work offline. My figure generation code depends on the Scipy stack, but this is easy to swap out; all you have to do is generate static images, put them in the proper folder, and link to them from index.html. You can generate your static images using any tool you choose. If you happen to use code to generate your figures, though, great! You can put this code in the figure_generation directory, enabling version control and simple reproduction of your results by others.
92 |
93 |
Writing directly in HTML/CSS/Javascript isn't for everyone. It's fiddly, has a learning curve, and requires obsessive attention to detail. In my experience, writing a scientific publication already fits this description, so it's a small price to pay, and one I'm already paying.
94 |
95 |
96 | Math typesetting
97 |
98 |
I use MathJax for typesetting. I want to be able to work offline, but a local MathJax copy is huge, so I followed the recipe described by Tibor Simon to make a minimal version. The recipe's pretty cool; you delete most of MathJax, try to load it, watch your browser console, and copy files back one at a time until your browser stops complaining. I only support LaTex input; if you want more, you can follow Tibor's recipe and replace the contents of /javascript/Minimal-MathJax/.
107 |
108 | Example of inline math: \(\frac{a^3}{b}\)
109 |
110 |
111 | Code syntax highlighting
112 |
113 |
Prism.js makes HTML syntax highlighting easy. I only included Python highlighting; if you want more, download a freshly customized version from prismjs.com and replace /javascript/python-highlighting/prims.js.
An example of how to include a citation:
125 |
126 | [Eswaramoorthy2014].
127 |
128 | If you inspect the HTML, you'll see that inserting the citation is super clumsy, but at least you don't have to keep track of uniqueness, ordering, etc.
129 |
130 |
131 | Static and interactive figures
132 |
133 |
Version control isn't a great way to organize images, but you can get away with it if there aren't too many, and they don't change too often. Figure 1 uses an image stored in the local repository.
134 |
135 |
136 |
138 | Figure 1: A static figure using a local image. This image was generated by /figure_generation/figure_1.py.
139 |
140 |
141 |
Figure 2 is interactive; the images are pre-computed (by Python code, in this case) and stored in the local repository. Simple javascript changes the figure's img.src when the figure's select changes. The images are small and don't change much, so it's not horrible to store them in this repository. A similar figure with substantially more images would stretch the limits of this approach.
142 |
143 |
144 |
146 |
147 |
148 |
Period:
(change this to adjust the period of the sinusoidal plot)
159 |
160 |
161 | Figure 2: An interactive figure using local images. This figure's images were pre-generated by /figure_generation/figure_2.py, and switched dynamically by /javascript/update_figures.js.
162 |
163 |
164 |
Interactive figures can potentially contain huge numbers of images, which are clumsy to store in a version-controlled repository. My current preferred solution is to store such images in an auxiliary location. During the writing process, we generate these images automatically using the figure generation code and store them locally. Once the paper is ready to publish, we host a copy of these images in a second auxiliary repository. The figure update Javascript finds the appropriate image source for us.
165 |
166 |
167 |
169 |
170 |
171 |
Period:
(change this to adjust the period of the sinusoidal plot)
182 |
183 |
184 | Figure 3: An interactive figure using images that aren't stored in this repository. This figure's images were pre-generated by /figure_generation/figure_3.py, and switched dynamically by /javascript/update_figures.js.
185 |