aboutsummaryrefslogtreecommitdiff
path: root/reproduce/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'reproduce/analysis')
-rwxr-xr-xreproduce/analysis/bash/download-multi-try112
-rw-r--r--reproduce/analysis/config/INPUTS.mk15
-rw-r--r--reproduce/analysis/config/delete-me-num.mk2
-rw-r--r--reproduce/analysis/config/pdf-build.mk21
-rw-r--r--reproduce/analysis/make/delete-me.mk126
-rw-r--r--reproduce/analysis/make/download.mk91
-rw-r--r--reproduce/analysis/make/initialize.mk339
-rw-r--r--reproduce/analysis/make/paper.mk139
-rw-r--r--reproduce/analysis/make/top.mk136
9 files changed, 981 insertions, 0 deletions
diff --git a/reproduce/analysis/bash/download-multi-try b/reproduce/analysis/bash/download-multi-try
new file mode 100755
index 0000000..1fd7497
--- /dev/null
+++ b/reproduce/analysis/bash/download-multi-try
@@ -0,0 +1,112 @@
+# Attempt downloading multiple times before crashing whole project. From
+# the top project directory (for the shebang above), this script must be
+# run like this:
+#
+# $ /path/to/download-multi-try downloader lockfile input-url downloaded-name
+#
+# NOTE: The `downloader' must contain the option to specify the output name
+# in its end. For example "wget -O". Any other option can also be placed in
+# the middle.
+#
+# Due to temporary network problems, a download may fail suddenly, but
+# succeed in a second try a few seconds later. Without this script that
+# temporary glitch in the network will permanently crash the project and
+# it can't continue. The job of this script is to be patient and try the
+# download multiple times before crashing the whole project.
+#
+# LOCK FILE: Since there is ultimately only one network port to the outside
+# world, downloading is done much faster in serial, not in parallel. But
+# the project's processing may be done in parallel (with multiple threads
+# needing to download different files at the same time). Therefore, this
+# script uses the `flock' program to only do one download at a time. To
+# benefit from it, any call to this script must be given the same lock
+# file.
+#
+# Copyright (C) 2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# This script is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This script is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. See <http://www.gnu.org/licenses/>.
+
+
+
+
+
+# Script settings
+# ---------------
+# Stop the script if there are any errors.
+set -e
+
+
+
+
+
+# Input arguments and necessary sanity checks.
+inurl="$3"
+outname="$4"
+lockfile="$2"
+downloader="$1"
+if [ "x$downloader" = x ]; then
+ echo "$0: downloader (first argument) not given."; exit 1;
+fi
+if [ "x$lockfile" = x ]; then
+ echo "$0: lock file (second argument) not given."; exit 1;
+fi
+if [ "x$inurl" = x ]; then
+ echo "$0: full input URL (third argument) not given."; exit 1;
+fi
+if [ "x$outname" = x ]; then
+ echo "$0: output name (fourth argument) not given."; exit 1;
+fi
+
+
+
+
+
+# Try downloading multiple times before crashing.
+counter=0
+maxcounter=10
+while [ ! -f "$outname" ]; do
+
+ # Increment the counter. We need the `counter=' part here because
+ # without it the evaluation of arithmetic expression will be like and
+ # error and the script is set to crash on errors.
+ counter=$((counter+1))
+
+ # If we have passed a maximum number of trials, just exit with
+ # a failed code.
+ if (( counter > maxcounter )); then
+ echo
+ echo "Failed $maxcounter download attempts: $outname"
+ echo
+ exit 1
+ fi
+
+ # If this isn't the first attempt print a notice and wait a little for
+ # the next trail.
+ if (( counter > 1 )); then
+ tstep=$((counter*5))
+ echo "Download trial $counter for '$outname' in $tstep seconds."
+ sleep $tstep
+ fi
+
+ # Attempt downloading the file (one-at-a-time). Note that the
+ # `downloader' ends with the respective option to specify the output
+ # name. For example "wget -O" (so `outname', that comes after it) will
+ # be the name of the downloaded file.
+ flock "$lockfile" bash -c \
+ "if ! $downloader $outname $inurl; then rm -f $outname; fi"
+done
+
+
+
+
+
+# Return successfully
+exit 0
diff --git a/reproduce/analysis/config/INPUTS.mk b/reproduce/analysis/config/INPUTS.mk
new file mode 100644
index 0000000..eb38295
--- /dev/null
+++ b/reproduce/analysis/config/INPUTS.mk
@@ -0,0 +1,15 @@
+# Input files necessary for this project.
+#
+# This file is read by the configure script and running Makefiles.
+#
+# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice and
+# this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+WFPC2IMAGE = WFPC2ASSNu5780205bx.fits
+WFPC2MD5 = a4791e42cd1045892f9c41f11b50bad8
+WFPC2SIZE = 62kb
+WFPC2URL = https://fits.gsfc.nasa.gov/samples
diff --git a/reproduce/analysis/config/delete-me-num.mk b/reproduce/analysis/config/delete-me-num.mk
new file mode 100644
index 0000000..17f608c
--- /dev/null
+++ b/reproduce/analysis/config/delete-me-num.mk
@@ -0,0 +1,2 @@
+# Number of samples to create
+delete-me-num = 50
diff --git a/reproduce/analysis/config/pdf-build.mk b/reproduce/analysis/config/pdf-build.mk
new file mode 100644
index 0000000..3a86ff3
--- /dev/null
+++ b/reproduce/analysis/config/pdf-build.mk
@@ -0,0 +1,21 @@
+# Make the final PDF?
+# -------------------
+#
+# During the project's early phases, it is usually not necessary to build
+# the PDF file (which makes a lot of output lines on the command-line and
+# can make it hard to find the commands and possible errors (and their
+# outputs). Also, in some cases, only the produced results may be of
+# interest and not the final PDF, so LaTeX (and its necessary packages) may
+# not be installed.
+#
+# If this variable is given any string, a PDF will be made with
+# LaTeX. Otherwise, a notice will just printed that for now, no PDF will be
+# created.
+#
+# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice and
+# this notice are preserved. This file is offered as-is, without any
+# warranty.
+pdf-build-final = yes
diff --git a/reproduce/analysis/make/delete-me.mk b/reproduce/analysis/make/delete-me.mk
new file mode 100644
index 0000000..c4cfffe
--- /dev/null
+++ b/reproduce/analysis/make/delete-me.mk
@@ -0,0 +1,126 @@
+# Dummy Makefile to create a random dataset for plotting.
+#
+# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# This Makefile is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This Makefile is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# A copy of the GNU General Public License is available at
+# <http://www.gnu.org/licenses/>.
+
+
+
+
+
+# Dummy dataset
+# -------------
+#
+# We will use AWK to generate a table showing X and X^2 and draw its plot.
+dmdir = $(texdir)/delete-me
+dm = $(dmdir)/data.txt
+$(dmdir): | $(texdir); mkdir $@
+$(dm): $(pconfdir)/delete-me-num.mk | $(dmdir)
+
+ # When the plotted values are re-made, it is necessary to also
+ # delete the TiKZ externalized files so the plot is also re-made.
+ rm -f $(tikzdir)/delete-me.pdf
+
+ # Generate the table of random values.
+ awk 'BEGIN {for(i=1;i<=$(delete-me-num);i+=0.5) print i, i*i; }' > $@
+
+
+
+
+
+# WFPC2 image PDF
+# -----------------
+#
+# For an example image, we'll make a PDF copy of the WFPC II image to
+# display in the paper.
+dddemodir = $(texdir)/delete-me-demo
+$(dddemodir): | $(texdir); mkdir $@
+demopdf = $(dddemodir)/wfpc2.pdf
+$(demopdf): $(dddemodir)/%.pdf: $(indir)/%.fits | $(dddemodir)
+
+ # When the plotted values are re-made, it is necessary to also
+ # delete the TiKZ externalized files so the plot is also re-made.
+ rm -f $(tikzdir)/delete-me-wfpc2.pdf
+
+ # Convert the dataset to a PDF.
+ astconvertt --colormap=gray --fluxhigh=4 $< -h0 -o$@
+
+
+
+
+
+# Histogram of WFPC2 image
+# ------------------------
+#
+# For an example plot, we'll show the pixel value histogram also.
+histogram = $(dddemodir)/wfpc2-hist.txt
+$(histogram): $(dddemodir)/%-hist.txt: $(indir)/%.fits | $(dddemodir)
+
+ # When the plotted values are re-made, it is necessary to also
+ # delete the TiKZ externalized files so the plot is also re-made.
+ rm -f $(tikzdir)/delete-me-wfpc2.pdf
+
+ # Generate the pixel value distribution
+ aststatistics --lessthan=5 $< -h0 --histogram -o$@
+
+
+
+
+
+# Basic statistics
+# ----------------
+#
+# This is just as a demonstration on how to get analysic configuration
+# parameters from variables defined in `reproduce/analysis/config/'.
+stats = $(dddemodir)/wfpc2-stats.txt
+$(stats): $(dddemodir)/%-stats.txt: $(indir)/%.fits | $(dddemodir)
+ aststatistics $< -h0 --mean --median > $@
+
+
+
+
+
+# TeX macros
+# ----------
+#
+# This is how we write the necessary parameters in the final PDF.
+#
+# NOTE: In LaTeX you cannot use any non-alphabetic character in a variable
+# name.
+$(mtexdir)/delete-me.tex: $(dm) $(demopdf) $(histogram) $(stats)
+
+ # Write the number of random values used.
+ echo "\newcommand{\deletemenum}{$(delete-me-num)}" > $@
+
+ # Note that since Make variables start with a `$(', if you want to
+ # use `$' within the shell (not Make), you have to quote any
+ # occurance of `$' with another `$'. That is why there are `$$' in
+ # the AWK command below.
+ #
+ # Here, we are first using AWK to find the minimum and maximum
+ # values, then using it again to read each separately to use in the
+ # macro definition.
+ mm=$$(awk 'BEGIN{min=99999; max=-min}
+ {if($$2>max) max=$$2; if($$2<min) min=$$2;}
+ END{print min, max}' $(dm));
+ v=$$(echo "$$mm" | awk '{printf "%.3f", $$1}');
+ echo "\newcommand{\deletememin}{$$v}" >> $@
+ v=$$(echo "$$mm" | awk '{printf "%.3f", $$2}');
+ echo "\newcommand{\deletememax}{$$v}" >> $@
+
+ # Write the statistics of the WFPC2 image as a macro.
+ mean=$$(awk '{printf("%.2f", $$1)}' $(stats))
+ echo "\newcommand{\deletemewfpctwomean}{$$mean}" >> $@
+ median=$$(awk '{printf("%.2f", $$2)}' $(stats))
+ echo "\newcommand{\deletemewfpctwomedian}{$$median}" >> $@
diff --git a/reproduce/analysis/make/download.mk b/reproduce/analysis/make/download.mk
new file mode 100644
index 0000000..a721863
--- /dev/null
+++ b/reproduce/analysis/make/download.mk
@@ -0,0 +1,91 @@
+# Download all the necessary inputs if they are not already present.
+#
+# Since most systems only have one input/connection into the network,
+# downloading is essentially a serial (not parallel) operation. so the
+# recipes in this Makefile all use a single file lock to have one download
+# script running at every instant.
+#
+# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# This Makefile is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This Makefile is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. See <http://www.gnu.org/licenses/>.
+
+
+
+
+
+# Download input data
+# --------------------
+#
+# The input dataset properties are defined in `$(pconfdir)/INPUTS.mk'. For
+# this template we only have one dataset to enable easy processing, so all
+# the extra checks in this rule may seem redundant.
+#
+# In a real project, you will need more than one dataset. In that case,
+# just add them to the target list and add an `elif' statement to define it
+# in the recipe.
+#
+# Files in a server usually have very long names, which are mainly designed
+# for helping in data-base management and being generic. Since Make uses
+# file names to identify which rule to execute, and the scope of this
+# research project is much less than the generic survey/dataset, it is
+# easier to have a simple/short name for the input dataset and work with
+# that. In the first condition of the recipe below, we connect the short
+# name with the raw database name of the dataset.
+#
+# Download lock file: Most systems have a single connection to the
+# internet, therefore downloading is inherently done in series. As a
+# result, when more than one dataset is necessary for download, if they are
+# done in parallel, the speed will be slower than downloading them in
+# series. We thus use the `flock' program to tie/lock the downloading
+# process with a file and make sure that only one downloading event is in
+# progress at every moment.
+$(indir):; mkdir $@
+downloadwrapper = $(bashdir)/download-multi-try
+inputdatasets = $(foreach i, wfpc2, $(indir)/$(i).fits)
+$(inputdatasets): $(indir)/%.fits: | $(indir) $(lockdir)
+
+ # Set the necessary parameters for this input file.
+ if [ $* = wfpc2 ]; then
+ origname=$(WFPC2IMAGE); url=$(WFPC2URL); mdf=$(WFPC2MD5);
+ else
+ echo; echo; echo "Not recognized input dataset: '$*.fits'."
+ echo; echo; exit 1
+ fi
+
+ # Download (or make the link to) the input dataset.
+ if [ -f $(INDIR)/$$origname ]; then
+ ln -s $(INDIR)/$$origname $@
+ else
+ touch $(lockdir)/download
+ $(downloadwrapper) "wget --no-use-server-timestamps -O" \
+ $(lockdir)/download $$url/$$origname $@
+ fi
+
+ # Check the md5 sum to see if this is the proper dataset.
+ sum=$$(md5sum $@ | awk '{print $$1}')
+ if [ $$sum != $$mdf ]; then
+ wrongname=$(dir $@)/wrong-$(notdir $@)
+ mv $@ $$wrongname
+ echo; echo; echo "Wrong MD5 checksum for '$$origname' in $$wrongname"
+ echo; echo; exit 1
+ fi
+
+
+
+
+
+# Final TeX macro
+# ---------------
+#
+# It is very important to mention the address where the data were
+# downloaded in the final report.
+$(mtexdir)/download.tex: $(pconfdir)/INPUTS.mk | $(mtexdir)
+ echo "\\newcommand{\\wfpctwourl}{$(WFPC2URL)}" > $@
diff --git a/reproduce/analysis/make/initialize.mk b/reproduce/analysis/make/initialize.mk
new file mode 100644
index 0000000..a034494
--- /dev/null
+++ b/reproduce/analysis/make/initialize.mk
@@ -0,0 +1,339 @@
+# Project initialization.
+#
+# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# This Makefile is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This Makefile is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# A copy of the GNU General Public License is available at
+# <http://www.gnu.org/licenses/>.
+
+
+
+
+
+# High-level directory definitions
+# --------------------------------
+#
+# Basic directories that are used throughout the project.
+#
+# Locks are used to make sure that an operation is done in series not in
+# parallel (even if Make is run in parallel with the `-j' option). The most
+# common case is downloads which are better done in series and not in
+# parallel. Also, some programs may not be thread-safe, therefore it will
+# be necessary to put a lock on them. This project uses the `flock' program
+# to achieve this.
+texdir = $(BDIR)/tex
+lockdir = $(BDIR)/locks
+indir = $(BDIR)/inputs
+mtexdir = $(texdir)/macros
+bashdir = reproduce/analysis/bash
+pconfdir = reproduce/analysis/config
+installdir = $(BDIR)/software/installed
+# --------- Delete for no Gnuastro ---------
+gconfdir = reproduce/software/config/gnuastro
+# ------------------------------------------
+
+
+
+
+
+# TeX build directory
+# ------------------
+#
+# In scenarios where multiple users are working on the project
+# simultaneously, they can't all build the final paper together, there will
+# be conflicts! It is possible to manage the working on the analysis, so no
+# conflict is caused in that phase, but it would be very slow to only let
+# one of the project members to build the paper at every instance
+# (independent parts of the paper can be added to it independently). To fix
+# this problem, when we are in a group setting, we'll use the user's ID to
+# create a separate LaTeX build directory for each user.
+#
+# The same logic applies to the final paper PDF: each user will create a
+# separte final PDF (for example `paper-user1.pdf' and `paper-user2.pdf')
+# and no `paper.pdf' will be built. This isn't a problem because
+# `initialize.tex' is a .PHONY prerequisite, so the rule to build the final
+# paper is always executed (even if it is present and nothing has
+# changed). So in terms of over-all efficiency and processing steps, this
+# doesn't change anything.
+ifeq (x$(GROUP-NAME),x)
+texbdir = $(texdir)/build
+final-paper = paper.pdf
+else
+user = $(shell whoami)
+texbdir = $(texdir)/build-$(user)
+final-paper = paper-$(user).pdf
+endif
+tikzdir = $(texbdir)/tikz
+
+
+
+
+
+# Original system environment
+# ---------------------------
+#
+# Before defining the local sub-environment here, we'll need to save the
+# system's environment for some scenarios (for example after `clean'ing the
+# built programs).
+sys-path := $(PATH)
+sys-rm := $(shell which rm)
+curdir := $(shell echo $$(pwd))
+
+
+
+
+
+# High level environment
+# ----------------------
+#
+# We want the full recipe to be executed in one call to the shell. Also we
+# want Make to run the specific version of Bash that we have installed
+# during `./configure' time.
+#
+# Regarding the directories, this project builds its major dependencies
+# itself and doesn't use the local system's default tools. With these
+# environment variables, we are setting it to prefer the software we have
+# build here.
+.ONESHELL:
+.SHELLFLAGS = -ec
+export CCACHE_DISABLE := 1
+export PATH := $(installdir)/bin
+export LD_LIBRARY_PATH := $(installdir)/lib
+export LDFLAGS := -L$(installdir)/lib
+export SHELL := $(installdir)/bin/bash
+export CPPFLAGS := -I$(installdir)/include
+
+
+
+
+
+# Python enviroment
+# -----------------
+#
+# The main Python environment variable is `PYTHONPATH'. However, so far we
+# have found several other Python-related environment variables on some
+# systems which might interfere. To be safe, we are removing all their
+# values.
+export PYTHONPATH := $(installdir)/lib/python/site-packages
+export PYTHONPATH3 := $(PYTHONPATH)
+export _LMFILES_ :=
+export PYTHONPATH2 :=
+export LOADEDMODULES :=
+export MPI_PYTHON_SITEARCH :=
+export MPI_PYTHON2_SITEARCH :=
+export MPI_PYTHON3_SITEARCH :=
+
+
+
+
+
+# High-level level directories
+# ----------------------------
+#
+# These are just the top-level directories for all the separate steps. The
+# directories (or possible sub-directories) for individual steps will be
+# defined and added within their own Makefiles.
+#
+# The `.SUFFIXES' rule with no prerequisite is defined to eliminate all the
+# default implicit rules. The default implicit rules are to do with
+# programming (for example converting `.c' files to `.o' files). The
+# problem they cause is when you want to debug the make command with `-d'
+# option: they add too many extra checks that make it hard to find what you
+# are looking for in the outputs.
+.SUFFIXES:
+$(lockdir): | $(BDIR); mkdir $@
+$(texbdir): | $(texdir); mkdir $@
+$(tikzdir): | $(texbdir); mkdir $@ && ln -fs $@ tex/tikz
+
+
+
+
+
+# High-level Makefile management
+# ------------------------------
+#
+# About `.PHONY': these are targets that must be built even if a file with
+# their name exists.
+#
+# Only `$(mtexdir)/initialize.tex' corresponds to a file. This is because
+# we want to ensure that the file is always built in every run: it contains
+# the project version which may change between two separate runs, even when
+# no file actually differs.
+packagebasename := $(shell echo paper-$$(git describe --dirty --always))
+packagecontents = $(texdir)/$(packagebasename)
+.PHONY: all clean dist dist-zip distclean clean-mmap $(packagecontents) \
+ $(mtexdir)/initialize.tex
+
+# --------- Delete for no Gnuastro ---------
+clean-mmap:; rm -f reproduce/config/gnuastro/mmap*
+# ------------------------------------------
+
+clean: clean-mmap
+ # Delete the top-level PDF file.
+ rm -f *.pdf
+
+ # Delete all the built outputs except the dependency
+ # programs. We'll use Bash's extended options builtin (`shopt') to
+ # enable "extended glob" (for listing of files). It allows extended
+ # features like ignoring the listing of a file with `!()' that we
+ # are using afterwards.
+ shopt -s extglob
+ rm -rf $(BDIR)/!(dependencies)
+
+distclean: clean
+ # We'll be deleting the built environent programs and just need the
+ # `rm' program. So for this recipe, we'll use the host system's
+ # `rm', not our own.
+ $(sys-rm) -rf $(BDIR) reproduce/build
+ $(sys-rm) -f Makefile .gnuastro .local
+ $(sys-rm) -f $(pconfdir)/LOCAL.mk $(gconfdir)/gnuastro-local.conf
+
+
+
+
+
+# Packaging rules
+# ---------------
+#
+# With the rules in this section, you can package the project in a state
+# that is ready for building the final PDF with LaTeX. This is useful for
+# collaborators who only want to contribute to the text of your project,
+# without having to worry about the technicalities of the analysis.
+$(packagecontents): | $(texdir)
+
+ # Set up the output directory, delete it if it exists and remake it
+ # to fill with new contents.
+ dir=$(texdir)/$(packagebasename)
+ rm -rf $$dir
+ mkdir $$dir
+
+ # Build a small Makefile to help in automatizing the paper building
+ # (including the bibliography).
+ m=$$dir/Makefile
+ echo "paper.pdf: paper.tex paper.bbl" > $$m
+ printf "\tpdflatex -shell-escape -halt-on-error paper\n" >> $$m
+ echo "paper.bbl: tex/src/references.tex" >> $$m
+ printf "\tpdflatex -shell-escape -halt-on-error paper\n" >> $$m
+ printf "\tbiber paper\n" >> $$m
+ echo ".PHONY: clean" >> $$m
+ echo "clean:" >> $$m
+ printf "\trm -f *.aux *.auxlock *.bbl *.bcf\n" >> $$m
+ printf "\trm -f *.blg *.log *.out *.run.xml\n" >> $$m
+
+ # Copy the top-level contents into it.
+ cp configure COPYING for-group README.md README-hacking.md $$dir/
+
+ # Build the top-level directories.
+ mkdir $$dir/reproduce $$dir/tex $$dir/tex/tikz $$dir/tex/build
+
+ # Copy all the necessary `reproduce' and `tex' contents.
+ shopt -s extglob
+ cp -r tex/src $$dir/tex/src
+ cp tex/tikz/*.pdf $$dir/tex/tikz
+ cp -r reproduce/ $$dir/reproduce
+ cp -r tex/build/!($(packagebasename)) $$dir/tex/build
+
+ # Clean up un-necessary/local files: 1) the $(texdir)/build*
+ # directories (when building in a group structure, there will be
+ # `build-user1', `build-user2' and etc), are just temporary LaTeX
+ # build files and don't have any relevant/hand-written files in
+ # them. 2) The `LOCAL.mk' and `gnuastro-local.conf' files just have
+ # this machine's local settings and are irrelevant for anyone else.
+ rm -rf $$dir/tex/build/build*
+ rm $$dir/reproduce/software/config/installation/LOCAL.mk
+ rm $$dir/reproduce/software/config/gnuastro/gnuastro-local.conf
+
+ # PROJECT SPECIFIC: under this comment, copy any other file for
+ # packaging, or remove any of the copied files above to suite your
+ # project.
+
+ # Since the packaging is mainly intended for high-level building of
+ # the PDF with LaTeX, we'll comment the `makepdf' LaTeX macro in
+ # the paper.
+ sed -e's|\\newcommand{\\makepdf}{}|%\\newcommand{\\makepdf}{}|' \
+ paper.tex > $$dir/paper.tex
+
+ # Just in case the package users want to rebuild some of the
+ # figures (manually un-comments the `makepdf' command we commented
+ # above), correct the TikZ external directory, so the figures can
+ # be rebuilt.
+ pgfsettings="$$dir/tex/src/preamble-pgfplots.tex"
+ sed -e's|{tikz/}|{tex/tikz/}|' $$pgfsettings > $$pgfsettings.new
+ mv $$pgfsettings.new $$pgfsettings
+
+ # Clean temporary (currently those ending in `~') files.
+ cd $(texdir)
+ find $(packagebasename) -name \*~ -delete
+
+# Package into `.tar.gz'.
+dist: $(packagecontents)
+ curdir=$$(pwd)
+ cd $(texdir)
+ tar -cf $(packagebasename).tar $(packagebasename)
+ gzip -f --best $(packagebasename).tar
+ cd $$curdir
+ mv $(texdir)/$(packagebasename).tar.gz ./
+
+# Package into `.zip'.
+dist-zip: $(packagecontents)
+ curdir=$$(pwd)
+ cd $(texdir)
+ zip -q -r $(packagebasename).zip $(packagebasename)
+ cd $$curdir
+ mv $(texdir)/$(packagebasename).zip ./
+
+
+
+
+
+# Check the version of programs which write their version
+# -------------------------------------------------------
+pvcheck = prog="$(strip $(1))"; \
+ ver="$(strip $(2))"; \
+ name="$(strip $(3))"; \
+ macro="$(strip $(4))"; \
+ verop="$(strip $(5))"; \
+ if [ "x$$verop" = x ]; then V="--version"; else V=$$verop; fi; \
+ v=$$($$prog $$V | awk '/'$$ver'/{print "y"; exit 0}'); \
+ if [ x$$v != xy ]; then \
+ echo; echo "PROJECT ERROR: Not running $$name $$ver"; echo; \
+ exit 1; \
+ fi; \
+ echo "\newcommand{\\$$macro}{$$ver}" >> $@
+
+lvcheck = idir=$(BDIR)/dependencies/installed/include; \
+ f="$$idir/$(strip $(1))"; \
+ ver="$(strip $(2))"; \
+ name="$(strip $(3))"; \
+ macro="$(strip $(4))"; \
+ v=$$(awk '/^\#/&&/define/&&/'$$ver'/{print "y";exit 0}' $$f); \
+ if [ x$$v != xy ]; then \
+ echo; echo "PROJECT ERROR: Not linking with $$name $$ver"; \
+ echo; exit 1; \
+ fi; \
+ echo "\newcommand{\\$$macro}{$$ver}" >> $@
+
+
+
+
+# Project initialization results
+# ------------------------------
+#
+# This file will store some basic info about the project that is necessary
+# for the final PDF. Since these are not version controlled, it must be
+# calculated everytime the project is run. So even though this file
+# actually exists, it is also aded as a `.PHONY' target above.
+$(mtexdir)/initialize.tex: | $(mtexdir)
+
+ # Version of the project.
+ @v=$$(git describe --dirty --always);
+ echo "\newcommand{\projectversion}{$$v}" > $@
diff --git a/reproduce/analysis/make/paper.mk b/reproduce/analysis/make/paper.mk
new file mode 100644
index 0000000..5378ee3
--- /dev/null
+++ b/reproduce/analysis/make/paper.mk
@@ -0,0 +1,139 @@
+# Build the final PDF paper/report.
+#
+# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# This Makefile is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This Makefile is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# A copy of the GNU General Public License is available at
+# <http://www.gnu.org/licenses/>.
+
+
+
+
+# LaTeX macros for paper
+# ----------------------
+#
+# To report the input settings and results, the final report's PDF (final
+# target of this project) uses macros generated from various steps of the
+# project. All these macros are defined through `$(mtexdir)/project.tex'.
+#
+# `$(mtexdir)/project.tex' is actually just a combination of separate files
+# that keep the LaTeX macros related to each workhorse Makefile (in
+# `reproduce/src/make/*.mk'). Those individual macros are pre-requisites to
+# `$(mtexdir)/project.tex'. The only workhorse Makefile that doesn't need
+# to produce LaTeX macros is this Makefile (`reproduce/src/make/paper.mk').
+#
+# This file is thus the interface between the processing scripts and the
+# final PDF: when we get to this point, all the processing has been
+# completed.
+#
+# Note that if you don't want the final PDF and just want the processing
+# and file outputs, you can remove the value of `pdf-build-final' in
+# `reproduce/analysis/config/pdf-build.mk'.
+$(mtexdir)/project.tex: $(foreach s, $(subst paper,,$(makesrc)), $(mtexdir)/$(s).tex)
+
+ # If no PDF is requested, or if LaTeX isn't available, don't
+ # continue to building the final PDF. Otherwise, merge all the TeX
+ # macros into one for building the PDF.
+ @if [ -f .local/bin/pdflatex ] && [ x"$(pdf-build-final)" != x ]; then
+
+ # Put a LaTeX input command for all the necessary macro files.
+ rm -f $(mtexdir)/project.tex
+ for t in $(subst paper,,$(makesrc)); do
+ echo "\input{tex/build/macros/$$t.tex}" >> $(mtexdir)/project.tex
+ done
+ else
+ echo
+ echo "-----"
+ echo "The processing has COMPLETED SUCCESSFULLY! But the final "
+ echo "LaTeX-built PDF paper will not be built."
+ echo
+ if [ x$(more-on-building-pdf) = x1 ]; then
+ echo "To do so, make sure you have LaTeX within the project (you"
+ echo "can check by running './.local/bin/latex --version'), _AND_"
+ echo "make sure that the 'pdf-build-final' variable has a value."
+ echo "'pdf-build-final' is defined in: "
+ echo "'reproduce/analysis/config/pdf-build.mk'."
+ echo
+ echo "If you don't have LaTeX within the project, please re-run"
+ echo "'./configure' when you have internet access. To speed it up,"
+ echo "you can keep the previous configuration files (answer 'n'"
+ echo "when it asks about re-writing previous configuration files)."
+ else
+ echo "For more, run './.local/bin/make more-on-building-pdf=1'"
+ fi
+ echo
+ echo "" > $@
+ fi
+
+
+
+
+
+# The bibliography
+# ----------------
+#
+# We need to run the `biber' program on the output of LaTeX to generate the
+# necessary bibliography before making the final paper. So we'll first have
+# one run of LaTeX (similar to the `paper.pdf' recipe), then `biber'.
+#
+# NOTE: `$(mtexdir)/project.tex' is an order-only-prerequisite for
+# `paper.bbl'. This is because we need to run LaTeX in both the `paper.bbl'
+# recipe and the `paper.pdf' recipe. But if `tex/src/references.tex' hasn't
+# been modified, we don't want to re-build the bibliography, only the final
+# PDF.
+$(texbdir)/paper.bbl: tex/src/references.tex \
+ | $(tikzdir) $(texbdir) $(mtexdir)/project.tex
+ # If `$(mtexdir)/project.tex' is empty, don't build PDF.
+ @macros=$$(cat $(mtexdir)/project.tex)
+ if [ x"$$macros" != x ]; then
+
+ # We'll run LaTeX first to generate the `.bcf' file (necessary
+ # for `biber') and then run `biber' to generate the `.bbl' file.
+ p=$$(pwd);
+ export TEXINPUTS=$$p:$$TEXINPUTS;
+ cd $(texbdir);
+ pdflatex -shell-escape -halt-on-error $$p/paper.tex;
+ biber paper
+
+ fi
+
+
+
+
+
+# The final paper
+# ---------------
+#
+# Run LaTeX in the `$(texbdir)' directory so all the intermediate and
+# auxiliary files stay there and keep the top directory clean. To be able
+# to run everything cleanly from there, it is necessary to add the current
+# directory (top project directory) to the `TEXINPUTS' environment
+# variable.
+paper.pdf: $(mtexdir)/project.tex paper.tex $(texbdir)/paper.bbl \
+ | $(tikzdir) $(texbdir)
+
+ # If `$(mtexdir)/project.tex' is empty, don't build the PDF.
+ @macros=$$(cat $(mtexdir)/project.tex)
+ if [ x"$$macros" != x ]; then
+
+ # Go into the top TeX build directory and make the paper.
+ p=$$(pwd)
+ export TEXINPUTS=$$p:$$TEXINPUTS
+ cd $(texbdir)
+ pdflatex -shell-escape -halt-on-error $$p/paper.tex
+
+ # Come back to the top project directory and copy the built PDF
+ # file here.
+ cd $$p
+ cp $(texbdir)/$@ $(final-paper)
+
+ fi
diff --git a/reproduce/analysis/make/top.mk b/reproduce/analysis/make/top.mk
new file mode 100644
index 0000000..a85c530
--- /dev/null
+++ b/reproduce/analysis/make/top.mk
@@ -0,0 +1,136 @@
+# Top-level Makefile (first to be loaded).
+#
+# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+#
+# This Makefile is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This Makefile is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# A copy of the GNU General Public License is available at
+# <http://www.gnu.org/licenses/>.
+
+
+
+
+
+# Load the local configuration (created after running `./configure').
+include reproduce/software/config/installation/LOCAL.mk
+
+
+
+
+
+# Ultimate target of this project
+# -------------------------------
+#
+# The final paper/report (`paper.pdf') is the main target of this
+# project. As defined in the Make paradigm, it must be the first target
+# that Make encounters (immediately after loading the local configuration
+# settings, necessary for a group building scenario mentioned next).
+#
+#
+# Group build
+# -----------
+#
+# This project can also be configured to have a shared build directory
+# between multiple users. In this scenario, many users (on a server) can
+# have their own/separate version controlled project source, but share the
+# same build outputs (in a common directory). This will allow a group to
+# work separately, on parallel parts of the analysis that don't
+# interfere. It is thus very useful in cases were special storage
+# requirements or CPU power is necessary and its not possible/efficient for
+# each user to have a fully separate copy of the build directory.
+#
+# Controlling this requires two variables that are available at this stage:
+#
+# - `GROUP-NAME': from `LOCAL.mk' (which was built by `./configure').
+# - `reproducible_paper_group_name': from the `./for-group' script (if it
+# was used to call Make).
+#
+# The analysis is only done when both have the same group name. Note that
+# when the project isn't being built for a group, both variables will be an
+# empty string.
+#
+#
+# Only processing, no LaTeX PDF
+# -----------------------------
+#
+# If you are just interested in the processing and don't want to build the
+# PDF, you can skip the creatation of the final PDF by removing the value
+# of `pdf-build-final' in `reproduce/analysis/config/pdf-build.mk'.
+ifeq (x$(reproducible_paper_group_name),x$(GROUP-NAME))
+all: paper.pdf
+else
+all:
+ @if [ "x$(GROUP-NAME)" = x ]; then \
+ echo "Project is NOT configured for groups, please run"; \
+ echo " $$ .local/bin/make"; \
+ else \
+ echo "Project is configured for groups, please run"; \
+ echo " $$ ./for-group $(GROUP-NAME) make -j8"; \
+ fi
+endif
+
+
+
+
+
+# Define source Makefiles
+# -----------------------
+#
+# To keep things clean, managable and readable, each set of operations
+# is (and must be) classified (modularized) by context into separate
+# Makefiles: the more the better. These modular steps are then
+# included in this top-level Makefile through the `include' command of
+# the next step. Each Makefile should also produce a LaTeX macro file
+# with the same fixed name (used to keep all the parameters and
+# relevant outputs of the steps in it for the final paper).
+#
+# In the rare case that no special LaTeX macros are necessary in a
+# workhorse Makefile, you can simply make an empty file with `touch
+# $@'. This will not add any lines to the final combined LaTeX macros
+# file, but will create the file that is a prerequisite to the final
+# paper generation.
+#
+# To (significantly) help in readability, this top-level Makefile should be
+# the only one in charge of including Makefiles. So if you care about easy
+# maintainence and understandability (even for your self, in one year! It
+# is VERY IMPORTANT and as a scientist, you MUST care about it!), do not
+# include Makefiles from any other Makefile.
+#
+# IMPORTANT NOTE: order matters in the inclusion of the processing
+# Makefiles. As the project grows, some Makefiles will define
+# variables/dependencies that later Makefiles need. Therefore we are using
+# a `foreach' loop in the next step to explicitly request loading them in
+# the same order that they are defined here (we aren't just using a
+# wild-card like the configuration Makefiles).
+makesrc = initialize \
+ download \
+ delete-me \
+ paper
+
+
+
+
+
+# Include all analysis Makefiles
+# ------------------------------
+#
+# 1) All the analysis configuration-Makefiles (Makefiles that only define
+# variables with no rules or order).
+#
+# 2) From the software configuration-Makefiles, we only include the one
+# containing software versions, just incase its necessary to
+# use/report outside of the acknowledgments section of the paper.
+#
+# 3) Finally, we'll import all the analysis workhorse-Makefiles which
+# contain rules to actually do this project's processing.
+include reproduce/analysis/config/*.mk
+include reproduce/software/config/installation/versions.mk
+include $(foreach s,$(makesrc), reproduce/analysis/make/$(s).mk)