Commits

Tom Roche  committed 40f7a47

Framework upgrade, plus fixes for terrae module upgrades

Major change: now uses new-style framework for drivers (notably more modularity, setup moved to bash_utilities). Also:

* bash_utilities: uses GEIA's to track yesterday's (23 Apr 13) changes to terrae/EMVL
* renamed driver: regrid_reunit_retemporalize.sh -> CLMCN_driver.sh (plus minor internal renamings)
* regrid_global_to_AQMEII.r tracks driver changes
* uber_driver: uses FILE_LIST, parameterizes driver

Tested on terrae/EMVL from 'uber_driver.sh' in fresh terminal.

TODO:
*** reunit before regridding--input units are per area!
* all regrids: how to nudge off/onshore as required? e.g., soil or burning emissions should never be offshore, marine emissions should never be onshore.
* all regrid maps: add Caribbean islands (esp Bahamas! for offshore burning), Canadian provinces, Mexican states
* test on
** tlrPanP5 (which now has R package=ncdf4, but readAsciiTable of input .txt's is very slow compared to terrae)
** HPCC (once problem with ncdf4 on amad1 is debugged: in process with JOB and KMF)

  • Participants
  • Parent commits 59364a3

Comments (0)

Files changed (5)

File CLMCN_driver.sh

+#!/usr/bin/env bash
+
+# ----------------------------------------------------------------------
+# description
+# ----------------------------------------------------------------------
+
+# A top-level driver for creating an inventory of N2O emissions from natural/unmanaged soils over the AQMEII-NA domain from the CLM-CN global inventory:
+
+# * converts global/unprojected CLM-CN data to AQMEII-NA, an LCC-projected subdomain
+# * converts monthly to hourly data (over each month)
+# * checks conservation of mass over the conversions
+
+# Expects to run on linux. Utility dependencies include:
+# * bash with arithmetic support
+# * basename, dirname
+# * unzip
+# * curl or wget
+# * ncdump
+# * NCL
+# * R
+
+# TODO: failing functions should fail this (entire) driver!
+
+# Configure as needed for your platform.
+
+# ----------------------------------------------------------------------
+# constants with some simple manipulations
+# ----------------------------------------------------------------------
+
+THIS="$0"
+THIS_FN="$(basename ${THIS})"
+THIS_DIR="$(dirname ${THIS})"
+
+# workspace
+export WORK_DIR="$(pwd)" # keep it simple for now: same dir as top of repo
+
+### downloading
+WGET_TO_FILE='wget --no-check-certificate -c -O'
+CURL_TO_FILE='curl -C - -o'
+CURL_TO_STREAM='curl'
+
+# model/inventory constants
+export MODEL_YEAR='2008'
+export NOMINAL_GRIDCELL_AREA='1.440e8' # in meter^2, is a float ; stringtofloat(getenv("NOMINAL_GRIDCELL_AREA"))
+export MOLAR_MASS_N2O='44.0128'    # grams per mole of N2O, per wolframalpha.com
+export NITROGEN_MASS_N2O='28.0134' # grams per mole of N2,  per wolframalpha.com
+export SECONDS_PER_HOUR='3600'     # 60 * 60
+export CMAQ_RADIUS='6370000'       # in meters
+
+# for visualization (generally)
+export OUTPUT_SIGNIFICANT_DIGITS='3' # see conservation report below
+# PROJ.4 string for unprojected data
+export GLOBAL_PROJ4='+proj=longlat +ellps=WGS84'
+
+# for plotting (specifically)
+# PDF_VIEWER='xpdf' # set this in bash_utilities::setup_apps
+# temporally disaggregate multiple plots
+DATE_FORMAT='%Y%m%d_%H%M'
+export PDF_DIR="${WORK_DIR}"
+
+## conservation report constants
+# need 5 additional digits for float output, e.g., "4.85e+04"
+# bash arithmetic gotcha: allow no spaces around '='!
+# export CONSERV_REPORT_FIELD_WIDTH=$((OUTPUT_SIGNIFICANT_DIGITS + 5))
+export CONSERV_REPORT_FIELD_WIDTH='9' # width of 'AQMEII-NA'
+export CONSERV_REPORT_FLOAT_FORMAT="%${CONSERV_REPORT_FIELD_WIDTH}.$((OUTPUT_SIGNIFICANT_DIGITS - 1))e"
+# echo -e "${THIS_FN}: CONSERV_REPORT_FLOAT_FORMAT=${CONSERV_REPORT_FLOAT_FORMAT}" # debugging
+export CONSERV_REPORT_INT_FORMAT="%${CONSERV_REPORT_FIELD_WIDTH}i"
+export CONSERV_REPORT_COLUMN_SEPARATOR="  "
+export CONSERV_REPORT_TITLE="Is N2O conserved from input to output? units=mgN"
+export CONSERV_REPORT_SUBTITLE="(note (US land area)/(earth land area) ~= 6.15e-02)"
+
+# ----------------------------------------------------------------------
+# helpers
+# ----------------------------------------------------------------------
+
+### helpers in this repo
+
+export CALL_REGRID_FN='regrid_global_to_AQMEII.r'
+export CALL_REGRID_FP="${WORK_DIR}/${CALL_REGRID_FN}"
+export CALL_RETEMP_FN='retemp_reunit.ncl'
+export CALL_RETEMP_FP="${WORK_DIR}/${CALL_RETEMP_FN}"
+export CALL_CONSERV_FN='check_conservation.ncl'
+export CALL_CONSERV_FP="${WORK_DIR}/${CALL_CONSERV_FN}"
+
+# These helpers should have been cloned into the cwd, but JIC (and for later use). TODO: R-package my code
+
+### helpers from elsewhere
+
+BASH_UTILS_URI='https://bitbucket.org/tlroche/geia_regrid/raw/eef59bc6849c2c022415fe9a879310f482c9d8f4/bash_utilities.sh'
+export BASH_UTILS_FN="$(basename ${BASH_UTILS_URI})"
+BASH_UTILS_FP="${WORK_DIR}/${BASH_UTILS_FN}"
+
+STATS_FUNCS_URI='https://bitbucket.org/tlroche/aqmeii_ag_soil/raw/0fa7d1180b67265540cdf0dd1d82e06d9b4fa789/netCDF.stats.to.stdout.r'
+STATS_FUNCS_FN="$(basename ${STATS_FUNCS_URI})"
+export STATS_FUNCS_FP="${WORK_DIR}/${STATS_FUNCS_FN}"
+
+SUMMARIZE_FUNCS_URI='https://bitbucket.org/tlroche/edgar-4.2_minus_soil_and_biomass_to_aqmeii-na/raw/618f09df886a86c9bd15880f37bbf1bf9295b638/summarize.ncl'
+SUMMARIZE_FUNCS_FN="$(basename ${SUMMARIZE_FUNCS_URI})"
+export SUMMARIZE_FUNCS_FP="${WORK_DIR}/${SUMMARIZE_FUNCS_FN}"
+
+TIME_FUNCS_URI='https://bitbucket.org/tlroche/edgar-4.2_minus_soil_and_biomass_to_aqmeii-na/raw/618f09df886a86c9bd15880f37bbf1bf9295b638/time.ncl'
+TIME_FUNCS_FN="$(basename ${TIME_FUNCS_URI})"
+export TIME_FUNCS_FP="${WORK_DIR}/${TIME_FUNCS_FN}"
+
+VIS_FUNCS_URI='https://bitbucket.org/tlroche/edgar-4.2_minus_soil_and_biomass_to_aqmeii-na/raw/a2a39d8100260726b7825125b835bdd1959aa91f/visualization.r'
+VIS_FUNCS_FN="$(basename ${VIS_FUNCS_URI})"
+export VIS_FUNCS_FP="${WORK_DIR}/${VIS_FUNCS_FN}"
+
+# ----------------------------------------------------------------------
+# inputs
+# ----------------------------------------------------------------------
+
+### raw input
+
+# Raw input data is global/unprojected CLM-CN netCDF, with coordvars=
+# lat==(-90,+90)
+# lon==(0,+360), hence need to
+export ROTATE_INPUT="true"
+# time: 14 months (not "decimal year" per `time:units`:
+#       month[0]== month[1], month[12]== month[13] (per Saikawa)
+# Get from my repository.
+CLM_CN_RAW_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/2008PTONCLMCNN2O.nc'
+CLM_CN_RAW_FN="$(basename ${CLM_CN_RAW_URI})"
+CLM_CN_RAW_FN_ROOT="${CLM_CN_RAW_FN%.*}" # everything left of the dot
+export CLM_CN_RAW_FP="${WORK_DIR}/${CLM_CN_RAW_FN}"
+
+CLM_CN_RAW_PDF_FN="${CLM_CN_RAW_FN_ROOT}_$(date +${DATE_FORMAT}).pdf"
+export CLM_CN_RAW_PDF_FP="${WORK_DIR}/${CLM_CN_RAW_PDF_FN}" # path to PDF output
+
+# TODO: automate getting this metadata from the netCDF
+export CLM_CN_RAW_DATAVAR_NAME='n2oemissions'
+export CLM_CN_RAW_DATAVAR_LONGNAME='N2O emissions'
+export CLM_CN_RAW_DATAVAR_UNIT='mgN/m2/month'
+# export CLM_CN_RAW_DATAVAR_NA='-999.0' # not used--hopefully they have no missing data
+export CLM_CN_RAW_TIME_VAR_NAME='time'
+
+### Template for `raster` regridding.
+
+# The template input is a copy of some meteorological data with 52 "real" datavars.
+# That data is in the IOAPI format, which here is basically a wrapper around netCDF.
+# (IOAPI can be used with other data, and similar wrappers exist for other models.)
+# I removed all but one of the datavars (with NCO 'ncks'). TODO: script that!
+TEMPLATE_INPUT_GZ_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/emis_mole_all_20080101_12US1_cmaq_cb05_soa_2008ab_08c.EXTENTS_INPUT.nc.gz'
+TEMPLATE_INPUT_GZ_FN="$(basename ${TEMPLATE_INPUT_GZ_URI})"
+TEMPLATE_INPUT_GZ_FP="${WORK_DIR}/${TEMPLATE_INPUT_GZ_FN}"
+TEMPLATE_INPUT_ROOT="${TEMPLATE_INPUT_GZ_FN%.*}" # everything left of the LAST dot
+TEMPLATE_INPUT_FN="${TEMPLATE_INPUT_ROOT}"
+export TEMPLATE_INPUT_FP="${WORK_DIR}/${TEMPLATE_INPUT_FN}"
+# export TEMPLATE_INPUT_BAND='1' # `ncks` makes dim=TSTEP first
+export TEMPLATE_VAR_NAME='emi_n2o'
+
+# ----------------------------------------------------------------------
+# intermediate products
+# ----------------------------------------------------------------------
+
+### netCDF regridded to AQMEII-NA
+
+CLM_CN_REGRID_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/2008PTONCLMCNN2O_regrid.nc'
+CLM_CN_REGRID_FN="$(basename ${CLM_CN_REGRID_URI})"
+CLM_CN_REGRID_FN_ROOT="${CLM_CN_REGRID_FN%.*}" # everything left of the dot
+export CLM_CN_REGRID_FP="${WORK_DIR}/${CLM_CN_REGRID_FN}"
+
+export CLM_CN_REGRID_DATAVAR_NAME="${CLM_CN_RAW_DATAVAR_NAME}"
+export CLM_CN_REGRID_X_VAR_NAME='COL'
+export CLM_CN_REGRID_Y_VAR_NAME='ROW'
+export CLM_CN_REGRID_TIME_VAR_NAME='TSTEP' # more IOAPI-like than 'time'
+export CLM_CN_REGRID_TIME_VAR_UNIT='month (1=2, 2=Jan, ... 13=Dec, 13=14)'
+
+CLM_CN_REGRID_PDF_FN="${CLM_CN_REGRID_FN_ROOT}_$(date +${DATE_FORMAT}).pdf"
+export CLM_CN_REGRID_PDF_FP="${WORK_DIR}/${CLM_CN_REGRID_PDF_FN}" # path to PDF output
+
+### map scale factors (MSFs)
+# load MSFs from some GRIDCRO2D_<date/> which is pretty large, so gzip it
+
+MSF_GZ_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/GRIDCRO2D_080101.gz'
+MSF_GZ_FN="$(basename ${MSF_GZ_URI})"
+MSF_FN_ROOT="${MSF_GZ_FN%.*}" # everything left of the dot
+MSF_FN="${MSF_FN_ROOT}"       # does not normally have an extension
+MSF_GZ_FP="${WORK_DIR}/${MSF_GZ_FN}"
+export MSF_FP="${WORK_DIR}/${MSF_FN}"
+export MSF_VAR_NAME='MSFX2'
+
+### data container files
+### create data container files from extents/template file
+
+##### TODO: driver must ensure output_fp_template does not exist!
+export CLM_CN_TARGET_FN_TEMPLATE_STR='######'
+# problem: NCL currently (version=6.1.2) does not support *.ncf :-( workaround below
+CLM_CN_TARGET_FN_ROOT_TEMPLATE="emis_mole_N2O_${CLM_CN_TARGET_FN_TEMPLATE_STR}_12US1_cmaq_cb05_soa_2008ab_08c"
+CLM_CN_TARGET_EXT_CMAQ='ncf'
+CLM_CN_TARGET_EXT_NCL='nc'
+CLM_CN_TARGET_FN_TEMPLATE_CMAQ="${CLM_CN_TARGET_FN_ROOT_TEMPLATE}.${CLM_CN_TARGET_EXT_CMAQ}"
+CLM_CN_TARGET_FN_TEMPLATE_NCL="${CLM_CN_TARGET_FN_ROOT_TEMPLATE}.${CLM_CN_TARGET_EXT_NCL}"
+export CLM_CN_TARGET_FP_TEMPLATE_CMAQ="${WORK_DIR}/${CLM_CN_TARGET_FN_TEMPLATE_CMAQ}"
+export CLM_CN_TARGET_FP_TEMPLATE_NCL="${WORK_DIR}/${CLM_CN_TARGET_FN_TEMPLATE_NCL}"
+
+## global metadata for both {template, "real" monthly/hourly data container} files
+export CLM_CN_TARGET_FILE_ATTR_HISTORY='see https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na'
+
+## metadata for datavar in both {template, "real" monthly/hourly data container} files
+export CLM_CN_TARGET_VAR_NAME='N2O'
+# IOAPI pads varattr=long_name to length=16 with spaces
+export CLM_CN_TARGET_VAR_ATTR_LONG_NAME="$(printf '%-16s' ${CLM_CN_TARGET_VAR_NAME})"
+# IOAPI pads varattr=units to length=16 with spaces
+export CLM_CN_TARGET_VAR_ATTR_UNITS="$(printf '%-16s' 'moles/s')"
+# IOAPI pads varattr=var_desc to length=80 with spaces
+export CLM_CN_TARGET_VAR_ATTR_VAR_DESC="$(printf '%-80s' 'Model species ${CLM_CN_TARGET_TEMPLATE_VAR_NAME}')"
+
+# ----------------------------------------------------------------------
+# functions
+# ----------------------------------------------------------------------
+
+# TODO: test for resources, reuse if available
+# {setup_paths, setup_apps} isa bash util, so `get_helpers` first
+function setup {
+  for CMD in \
+    "mkdir -p ${WORK_DIR}" \
+    'get_helpers' \
+    'setup_paths' \
+    'setup_apps' \
+    'setup_resources' \
+  ; do
+    if [[ -z "${CMD}" ]] ; then
+      echo -e "${THIS_FN}::${FUNCNAME[0]}: ERROR: '${CMD}' not defined"
+      exit 1
+    else
+      echo -e "\n$ ${THIS_FN}::${FUNCNAME[0]}::${CMD}\n"
+      eval "${CMD}" # comment this out for NOPing, e.g., to `source`
+    fi
+  done
+#  echo -e "\n$ ${THIS_FN}: PDF_VIEWER='${PDF_VIEWER}'" # debugging
+} # end function setup
+
+function get_helpers {
+  for CMD in \
+    'get_bash_utils' \
+    'get_stats_funcs' \
+    'get_summarize_funcs' \
+    'get_time_funcs' \
+    'get_vis_funcs' \
+  ; do
+    if [[ -z "${CMD}" ]] ; then
+      echo -e "${THIS_FN}::${FUNCNAME[0]}: ERROR: '${CMD}' not defined"
+      exit 1
+    else
+      echo -e "\n$ ${THIS_FN}::${FUNCNAME[0]}::${CMD}\n"
+      eval "${CMD}" # comment this out for NOPing, e.g., to `source`
+    fi
+  done
+} # end function get_helpers
+
+function get_bash_utils {
+  if [[ -z "${BASH_UTILS_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: BASH_UTILS_FP not defined"
+    exit 1
+  fi
+  if [[ ! -r "${BASH_UTILS_FP}" ]] ; then
+    for CMD in \
+      "${WGET_TO_FILE} ${BASH_UTILS_FP} ${BASH_UTILS_URI}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ ! -r "${BASH_UTILS_FP}" ]] ; then
+    echo -e "${THIS_FN}::${FUNCNAME[0]}: ERROR: BASH_UTILS_FP=='${BASH_UTILS_FP}' not readable"
+    exit 1
+  fi
+  # This is bash, so gotta ...
+  source "${BASH_UTILS_FP}"
+} # end function get_bash_utils
+
+function get_stats_funcs {
+  if [[ -z "${STATS_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: STATS_FUNCS_FP not defined"
+    exit 1
+  fi
+  if [[ ! -r "${STATS_FUNCS_FP}" ]] ; then
+    for CMD in \
+      "${WGET_TO_FILE} ${STATS_FUNCS_FP} ${STATS_FUNCS_URI}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ ! -r "${STATS_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}::${FUNCNAME[0]}: ERROR: STATS_FUNCS_FP=='${STATS_FUNCS_FP}' not readable"
+    exit 1
+  fi
+} # end function get_stats_funcs
+
+function get_summarize_funcs {
+  if [[ -z "${SUMMARIZE_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: SUMMARIZE_FUNCS_FP not defined"
+    exit 1
+  fi
+  if [[ ! -r "${SUMMARIZE_FUNCS_FP}" ]] ; then
+    for CMD in \
+      "${WGET_TO_FILE} ${SUMMARIZE_FUNCS_FP} ${SUMMARIZE_FUNCS_URI}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ ! -r "${SUMMARIZE_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}::${FUNCNAME[0]}: ERROR: SUMMARIZE_FUNCS_FP=='${SUMMARIZE_FUNCS_FP}' not readable"
+    exit 1
+  fi
+} # end function get_summarize_funcs
+
+function get_time_funcs {
+  if [[ -z "${TIME_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: TIME_FUNCS_FP not defined"
+    exit 1
+  fi
+  if [[ ! -r "${TIME_FUNCS_FP}" ]] ; then
+    for CMD in \
+      "${WGET_TO_FILE} ${TIME_FUNCS_FP} ${TIME_FUNCS_URI}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ ! -r "${TIME_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}::${FUNCNAME[0]}: ERROR: TIME_FUNCS_FP=='${TIME_FUNCS_FP}' not readable"
+    exit 1
+  fi
+} # end function get_time_funcs
+
+function get_vis_funcs {
+  if [[ -z "${VIS_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: VIS_FUNCS_FP not defined"
+    exit 11
+  fi
+  if [[ ! -r "${VIS_FUNCS_FP}" ]] ; then
+    for CMD in \
+      "${WGET_TO_FILE} ${VIS_FUNCS_FP} ${VIS_FUNCS_URI}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ ! -r "${VIS_FUNCS_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: cannot download VIS_FUNCS_FP=='${VIS_FUNCS_FP}'"
+    exit 12
+  fi
+} # end function get_vis_funcs
+
+function setup_resources {
+  for CMD in \
+    'get_raw_input' \
+    'get_template_input' \
+    'get_regrid' \
+    'get_MSFs' \
+    'get_target_template' \
+  ; do
+    if [[ -z "${CMD}" ]] ; then
+      echo -e "${THIS_FN}::${FUNCNAME[0]}: ERROR: '${CMD}' not defined"
+      exit 1
+    else
+      echo -e "\n$ ${THIS_FN}::${FUNCNAME[0]}::${CMD}\n"
+      eval "${CMD}" # comment this out for NOPing, e.g., to `source`
+    fi
+  done
+} # end function setup_resources
+
+### get the (nearly) raw input
+function get_raw_input {
+  if [[ -z "${CLM_CN_RAW_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: CLM_CN_RAW_FP not defined"
+    exit 1
+  fi
+  if [[ ! -r "${CLM_CN_RAW_FP}" ]] ; then
+    for CMD in \
+      "${WGET_TO_FILE} ${CLM_CN_RAW_FP} ${CLM_CN_RAW_URI}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ ! -r "${CLM_CN_RAW_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: cannot read CLM_CN_RAW_FP=='${CLM_CN_RAW_FP}'"
+    exit 2
+  fi
+} # end function get_raw_input
+
+### get the "template" file, used for extent-setting and emissions-file creation
+function get_template_input {
+  if [[ -z "${TEMPLATE_INPUT_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: TEMPLATE_INPUT_FP not defined"
+    exit 3
+  fi
+  if [[ ! -r "${TEMPLATE_INPUT_FP}" ]] ; then
+    if [[ ! -r "${TEMPLATE_INPUT_GZ_FP}" ]] ; then
+      for CMD in \
+        "${WGET_TO_FILE} ${TEMPLATE_INPUT_GZ_FP} ${TEMPLATE_INPUT_GZ_URI}" \
+      ; do
+        echo -e "$ ${CMD}"
+        eval "${CMD}"
+      done
+    fi
+    if [[ -r "${TEMPLATE_INPUT_GZ_FP}" ]] ; then
+      for CMD in \
+        "gunzip ${TEMPLATE_INPUT_GZ_FP}" \
+      ; do
+        echo -e "$ ${CMD}"
+        eval "${CMD}"
+      done
+    fi
+  fi
+  if [[ ! -r "${TEMPLATE_INPUT_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: cannot read TEMPLATE_INPUT_FP=='${TEMPLATE_INPUT_FP}'"
+    exit 4
+  fi
+} # end function get_template_input
+
+### get the regridded output from the R script? no:
+### only for testing. TODO: provide commandline-switch control for this
+function get_regrid {
+  if [[ -z "${CLM_CN_REGRID_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: CLM_CN_REGRID_FP not defined"
+    exit 5
+  fi
+  # if [[ ! -r "${CLM_CN_REGRID_FP}" ]] ; then
+  #   for CMD in \
+  #     "${WGET_TO_FILE} ${CLM_CN_REGRID_FP} ${CLM_CN_REGRID_URI}" \
+  #   ; do
+  #     echo -e "$ ${CMD}"
+  #     eval "${CMD}"
+  #   done
+  # fi
+  # if [[ ! -r "${CLM_CN_REGRID_FP}" ]] ; then
+  #   echo -e "${THIS_FN}: ERROR: cannot read CLM_CN_REGRID_FP=='${CLM_CN_REGRID_FP}'"
+  #   exit 6
+  # fi
+} # function get_regrid
+
+function get_MSFs {
+  if [[ -z "${MSF_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: MSF_FP not defined"
+    exit 7
+  fi
+  if [[ ! -r "${MSF_FP}" ]] ; then
+    if [[ ! -r "${MSF_GZ_FP}" ]] ; then
+      for CMD in \
+        "${WGET_TO_FILE} ${MSF_GZ_FP} ${MSF_GZ_URI}" \
+      ; do
+        echo -e "$ ${CMD}"
+        eval "${CMD}"
+      done
+    fi
+    if [[ -r "${MSF_GZ_FP}" ]] ; then
+      for CMD in \
+        "gunzip ${MSF_GZ_FP}" \
+      ; do
+        echo -e "$ ${CMD}"
+        eval "${CMD}"
+      done
+    fi
+  fi
+  if [[ ! -r "${MSF_FP}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: cannot read MSF_FP=='${MSF_FP}'"
+    exit 8
+  fi
+} # end function get_MSFs
+
+function get_target_template {
+  if [[ -z "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: CLM_CN_TARGET_FP_TEMPLATE_NCL not defined"
+    exit 9
+  fi
+  if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
+    # delete: NCL will recreate
+    for CMD in \
+      "rm ${CLM_CN_TARGET_FP_TEMPLATE_NCL}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: cannot delete CLM_CN_TARGET_FP_TEMPLATE_NCL=='${CLM_CN_TARGET_FP_TEMPLATE_NCL}'"
+    exit 10
+  fi
+} # function get_target_template
+
+### regrid from global/unprojected to AQMEII/LCC
+function regrid {
+  # If this fails ...
+  for CMD in \
+    "Rscript ${CALL_REGRID_FP}" \
+  ; do
+  cat <<EOM
+
+About to run command='${CMD}'. WARNING: may seem to hang while processing!
+
+EOM
+    eval "${CMD}"
+  done
+  # ... just start R ...
+#  R
+  # ... and source ${CALL_REGRID_FP}, e.g.,
+#   source('....r')
+
+  # After exiting R, show cwd and display output PDF.
+  if [[ -r "${CLM_CN_RAW_PDF_FP}" ]] ; then
+    if [[ -r "${CLM_CN_REGRID_PDF_FP}" ]] ; then
+      #      "${PDF_VIEWER} ${CLM_CN_RAW_PDF_FP} &" \
+      for CMD in \
+          "ls -alht ${WORK_DIR}" \
+          "${PDF_VIEWER} ${CLM_CN_REGRID_PDF_FP} &" \
+          ; do
+          echo -e "$ ${CMD}"
+          eval "${CMD}"
+      done
+    else
+      echo -e "${THIS_FN}: ERROR: regrid not plotted: ${CLM_CN_REGRID_PDF_FP}"
+    fi
+  else
+    echo -e "${THIS_FN}: ERROR: input not plotted: ${CLM_CN_RAW_PDF_FP}"
+  fi
+} # end function regrid
+
+### "Retemporalize" from annual to hourly (and put in CMAQ-style file)
+### then check mass conservation
+function retemp_conserv {
+  # ncl # bail to NCL and copy script lines
+  # TODO: pass commandline args to NCL
+  # punt: just use envvars :-(
+
+  for SCRIPT in \
+      "${CALL_RETEMP_FP}" \
+      "${CALL_CONSERV_FP}" \
+      ; do
+      cat <<EOM
+
+About to run NCL script="${SCRIPT}"
+
+EOM
+      # '-n' -> http://www.ncl.ucar.edu/Document/Functions/Built-in/print.shtml
+      CMD="ncl -n ${SCRIPT}"
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+  done
+} # end function retemp_conserv
+
+function teardown {
+  if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
+    # delete: NCL will recreate
+    for CMD in \
+      "rm ${CLM_CN_TARGET_FP_TEMPLATE_NCL}" \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
+  if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
+    echo -e "${THIS_FN}: ERROR: cannot delete CLM_CN_TARGET_FP_TEMPLATE_NCL=='${CLM_CN_TARGET_FP_TEMPLATE_NCL}'"
+    exit 11
+  fi
+
+  ### show new monthly/hourly files (i.e., hourly emissions by month)
+
+  for CMD in \
+    "ls -alh ${WORK_DIR}/*.ncf" \
+    "ls -alht ${WORK_DIR}/*.nc" \
+  ; do
+    echo -e "$ ${CMD}"
+    eval "${CMD}"
+  done
+} # end function teardown
+
+# ----------------------------------------------------------------------
+# payload
+# ----------------------------------------------------------------------
+
+# should always
+# * begin with `setup` setup paths, apps, helpers, resources
+# * end with `teardown` for tidy and testing (e.g., plot display)
+for CMD in \
+  'setup' \
+  'regrid' \
+  'retemp_conserv' \
+  'teardown' \
+; do
+  if [[ -z "${CMD}" ]] ; then
+    echo -e "${THIS_FN}::main loop: ERROR: '${CMD}' not defined"
+    exit 1
+  else
+    echo -e "\n$ ${THIS_FN}::main loop: ${CMD}\n"
+    eval "${CMD}" # comment this out for NOPing, e.g., to `source`
+  fi
+done
+
+# ----------------------------------------------------------------------
+# debugging
+# ----------------------------------------------------------------------

File netCDF.stats.to.stdout.r

-# R code to write simple stats (min, mean, median, max) for an input file.
-# Run this like
-# $ Rscript ./netCDF.stats.to.stdout.r netcdf.fp=./GEIA_N2O_oceanic.nc data.var.name=emi_n2o
-# or
-# > source('./netCDF.stats.to.stdout.r')
-# > netCDF.stats.to.stdout(...)
-
-# ----------------------------------------------------------------------
-# constants
-# ----------------------------------------------------------------------
-
-this.fn <- 'netCDF.stats.to.stdout.r'      # TODO: get like $0
-
-# ----------------------------------------------------------------------
-# functions
-# ----------------------------------------------------------------------
-
-# syntactic sugar
-q1 <- function(vec) { quantile(vec, 0.25) } # first quartile
-q3 <- function(vec) { quantile(vec, 0.75) } # third quartile
-
-# the main event
-netCDF.stats.to.stdout <- function(
-  netcdf.fp, # /path/to/netcdf/file, can be relative or FQ
-  data.var.name,   # name of data variable (datavar) of interest
-  stats.precision=3 # sigdigs to use for min, median, max of obs  
-) {
-
-  # TODO: test arguments!
-
-#  # start debug
-#  cat(sprintf(
-#    '%s: netcdf.fp==%s, data.var.name==%s\n',
-#    this.fn, netcdf.fp, data.var.name))
-#  system(sprintf('ls -alth %s', netcdf.fp))
-#  system(sprintf('ncdump -h %s', netcdf.fp))
-#  #   end debug
-
-  # create strings for use in output below (far below)
-  # double-sprintf-ing to set precision by constant: cool or brittle?
-  stat.str.template <- sprintf('%%.%ig', stats.precision)
-  # use these in function=subtitle.stats as sprintf inputs
-  sum.str.template <- sprintf('sum=%s', stat.str.template)
-  max.str.template <- sprintf('max=%s', stat.str.template)
-  mea.str.template <- sprintf('mean=%s', stat.str.template)
-  med.str.template <- sprintf('med=%s', stat.str.template)  # median==2nd quartile
-  min.str.template <- sprintf('min=%s', stat.str.template)
-  q1.str.template <- sprintf('q1=%s', stat.str.template)    # 1st quartile
-  q3.str.template <- sprintf('q3=%s', stat.str.template)    # 3rd quartile
-
-  # needed to parse netCDF
-  library(ncdf4)
-
-  # open netCDF file, uncautiously
-  # NOTE: you must assign when you nc_open!
-  netcdf.file <- ncdf4::nc_open(
-    filename=netcdf.fp,
-    write=FALSE,    # will only read below
-    readunlim=TRUE) # it's a small file
-
-  # uncautiously get the data out of the datavar
-  data.var.data <- ncvar_get(
-    nc=netcdf.file,
-    varid=data.var.name)
-
-#  # start debug
-#  cat(sprintf('%s: data.var.name==%s has size==\n',
-#    this.fn, data.var.name))
-#  print(dim(data.var.data))
-#  #   end debug
-
-  if (is.numeric(data.var.data) && sum(!is.na(data.var.data))) {
-#    unsparse.data <- data.var.data[!is.na(data.var.data)]
-    # collapse its structure
-    unsparse.data <- c(data.var.data[!is.na(data.var.data)])
-    obs <- length(unsparse.data)
-    if (obs > 0) {
-      cells.str <- sprintf('cells=%i', length(data.var.data))
-      obs.str <- sprintf('obs=%i', obs)
-      min.str <- sprintf(min.str.template, min(unsparse.data))
-      q1.str <- sprintf(q1.str.template, q1(unsparse.data))
-      mea.str <- sprintf(mea.str.template, mean(unsparse.data))
-      med.str <- sprintf(med.str.template, median(unsparse.data))
-      q3.str <- sprintf(q3.str.template, q3(unsparse.data))
-      max.str <- sprintf(max.str.template, max(unsparse.data))
-      sum.str <- sprintf(sum.str.template, sum(unsparse.data))
-
-      # at last: output!
-      cat(sprintf('For %s var=%s\n', netcdf.fp, data.var.name))
-      cat(sprintf('\t%s\n', cells.str))
-      cat(sprintf('\t%s\n', obs.str))
-      # 6-number summary
-      cat(sprintf('\t%s\n', min.str))
-      cat(sprintf('\t%s\n', q1.str))
-      cat(sprintf('\t%s\n', med.str))
-      cat(sprintf('\t%s\n', mea.str))
-      cat(sprintf('\t%s\n', q3.str))
-      cat(sprintf('\t%s\n', max.str))
-      cat(sprintf('\t%s\n', sum.str))
-
-    } else {
-      cat(sprintf('%s: %s var=%s has no non-NA data',
-        this.fn, data.var.name, netcdf.fp))
-    }
-  } else {
-    cat(sprintf('%s: %s var=%s has no numeric non-NA data',
-      this.fn, data.var.name, netcdf.fp))
-  }
-
-  # teardown
-  nc_close(netcdf.file)
-
-} # end function netCDF.stats.to.stdout
-
-netCDF.stats.to.stdout.by.timestep <- function(
-  netcdf.fp, # /path/to/netcdf/file, can be relative or FQ
-  data.var.name,   # name of data variable (datavar) of interest
-  time.dim.name='time', # of time dimension in datavar args
-  stats.precision=3 # sigdigs to use for min, median, max of obs
-) {
-
-  # TODO: test arguments!
-
-#  # start debug
-#  cat(sprintf(
-#    '%s: netcdf.fp==%s, data.var.name==%s, time.dim.name=%s\n',
-#    this.fn, netcdf.fp, data.var.name, time.dim.name))
-#  system(sprintf('ls -alth %s', netcdf.fp))
-#  system(sprintf('ncdump -h %s', netcdf.fp))
-#  #   end debug
-
-  # create strings for use in output below (far below)
-  # double-sprintf-ing to set precision by constant: cool or brittle?
-  stat.str.template <- sprintf('%%.%ig', stats.precision)
-  # use these in function=subtitle.stats as sprintf inputs
-  sum.str.template <- sprintf('sum=%s', stat.str.template)
-  max.str.template <- sprintf('max=%s', stat.str.template)
-  mea.str.template <- sprintf('mean=%s', stat.str.template)
-  med.str.template <- sprintf('med=%s', stat.str.template)  # median==2nd quartile
-  min.str.template <- sprintf('min=%s', stat.str.template)
-  q1.str.template <- sprintf('q1=%s', stat.str.template)    # 1st quartile
-  q3.str.template <- sprintf('q3=%s', stat.str.template)    # 3rd quartile
-
-  # needed to parse netCDF
-  library(ncdf4)
-
-  # open netCDF file, uncautiously
-  # NOTE: you must assign when you nc_open!
-  netcdf.file <- ncdf4::nc_open(
-    filename=netcdf.fp,
-    write=FALSE,    # will only read below
-    readunlim=TRUE) # it's a small file? TODO: read by timestep!
-
-  # Find the index of the datavar of interest
-  # (in the list of all non-coordinate variables).
-  netcdf.file.vars.n <- netcdf.file$nvars
-  data.var.index <- -1 # an invalid index
-  for (i in 1:netcdf.file.vars.n) {
-    netcdf.file.var <- netcdf.file$var[[i]]
-    if (netcdf.file.var$name == data.var.name) {
-      data.var.index <- i
-    }
-  }
-  if (data.var.index == -1) {
-    stop(sprintf('%s: ERROR: failed to find data.var.index\n', this.fn))
-  }
-
-#  # start debug
-#  cat(sprintf('%s: data.var.name==%s has var posn=%i and size==\n',
-#    this.fn, data.var.name, data.var.index))
-#  print(dim(data.var.data))
-#  #   end debug
-
-  # can only compute n.timesteps once we have the datavar's dims ...
-  data.var <- netcdf.file$var[[data.var.index]]
-  data.var.dims <- data.var$size
-  data.var.dims.n <- data.var$ndims
-  # ... and particularly the position of dimension$name==time.dim.name
-  time.dim.index <- -1 # an invalid index
-  for (i in 1:data.var.dims.n) {
-    data.var.dim <- data.var$dim[[i]]
-    if (data.var.dim$name == time.dim.name) {
-      time.dim.index <- i
-    }
-  }
-  if (time.dim.index == -1) {
-    stop(sprintf("%s: ERROR: failed to find time.dim.index for time.dim.name='%s'\n",
-      this.fn, time.dim.name))
-  } # else
-  n.timesteps <- data.var.dims[time.dim.index]
-
-#  # start debug
-#  cat(sprintf('%s: time.dim.name==%s has dim posn=%i and size=%i\n',
-#    this.fn, time.dim.name, time.dim.index, n.timesteps))
-#  #   end debug
-
-# TODO: ncdf4 bug?
-#  # compute read vectors for use in `ncvar_get`: read all timestep values
-#  vec.start.template <- rep(1, data.var.dims.n)   # ASSERT: constant
-##  vec.count.template <- rep(-1, data.var.dims.n)  # ASSERT: constant
-#  # see bug below, try instead
-#  vec.count.template <- data.var.dims             # ASSERT: constant
-
-  # iterate over the timesteps
-  for (i in 1:n.timesteps) {
-
-#    vec.start <- vec.start.template
-#    vec.start[time.dim.index] <- i # only get the i'th timestep
-#    vec.count <- vec.count.template
-#    vec.count[time.dim.index] <- i # only get the i'th timestep
-#
-#    # start debug
-#    cat(sprintf('%s: vec.start==\n', this.fn))
-#    print(vec.start)
-#    cat(sprintf('%s: vec.count==\n', this.fn))
-#    print(vec.count)
-#    #   end debug
-
-    data.var.data <- ncdf4::ncvar_get(
-      nc=netcdf.file,
-      varid=data.var.name
-# TODO: {debug, bug report} why this fails
-#      varid=data.var.name,
-#      start=vec.start,
-#      count=vec.count
-    )
-# each loop call increases time dimension! e.g.,
-# > netCDF.stats.to.stdout.r: dim(data.var.data)==
-# > [1] 144  96
-# ...
-# > netCDF.stats.to.stdout.r: dim(data.var.data)==
-# > [1] 144  96   2
-# ...
-# > netCDF.stats.to.stdout.r: dim(data.var.data)==
-# > [1] 144  96   3
-    # workaround: read unlimited (above), then just take the slice of interest
-    data.var.timestep <- data.var.data[,,i]
-                                  
-#    # start debug
-#    cat(sprintf('%s: dim(data.var.timestep)==\n', this.fn))
-#    print(dim(data.var.timestep))
-#    cat(sprintf('%s: summary(data.var.timestep)==\n', this.fn))
-#    print(summary(c(data.var.timestep))) # collapse its structure
-#    #   end debug
-
-    if (is.numeric(data.var.timestep) && sum(!is.na(data.var.timestep))) {
-#      unsparse.data <- data.var.timestep[!is.na(data.var.timestep)]
-      # collapse its structure
-      unsparse.data <- c(data.var.timestep[!is.na(data.var.timestep)])
-      obs <- length(unsparse.data)
-      if (obs > 0) {
-        cells.str <- sprintf('cells=%i', length(data.var.timestep))
-        obs.str <- sprintf('obs=%i', obs)
-        min.str <- sprintf(min.str.template, min(unsparse.data))
-        q1.str <- sprintf(q1.str.template, q1(unsparse.data))
-        mea.str <- sprintf(mea.str.template, mean(unsparse.data))
-        med.str <- sprintf(med.str.template, median(unsparse.data))
-        q3.str <- sprintf(q3.str.template, q3(unsparse.data))
-        max.str <- sprintf(max.str.template, max(unsparse.data))
-        sum.str <- sprintf(sum.str.template, sum(unsparse.data))
-
-        # at last: output!
-        cat(sprintf('For %s data.var=%s, timestep=%i of %i\n',
-          netcdf.fp, data.var.name, i, n.timesteps))
-        cat(sprintf('\t%s\n', cells.str))
-        cat(sprintf('\t%s\n', obs.str))
-        # 6-number summary
-        cat(sprintf('\t%s\n', min.str))
-        cat(sprintf('\t%s\n', q1.str))
-        cat(sprintf('\t%s\n', med.str))
-        cat(sprintf('\t%s\n', mea.str))
-        cat(sprintf('\t%s\n', q3.str))
-        cat(sprintf('\t%s\n', max.str))
-        cat(sprintf('\t%s\n', sum.str))
-
-#        rm( # debugging why output is same for each timestep
-#          cells.str,
-#          obs.str,
-#          min.str,
-#          q1.str,
-#          med.str,
-#          mea.str,
-#          q3.str,
-#          max.str,
-#          sum.str)
-
-      } else {
-        cat(sprintf('%s: %s data.var=%s has no non-NA data',
-          this.fn, data.var.name, netcdf.fp))
-      }
-    } else {
-      cat(sprintf('%s: %s data.var=%s has no numeric non-NA data',
-        this.fn, data.var.name, netcdf.fp))
-    }
-
-    rm( # debugging why output is same for each timestep
-#      data.var.data,
-      data.var.timestep,
-      unsparse.data)
-
-  } # end for (i in 1:n.timesteps)
-
-  # teardown
-  ncdf4::nc_close(netcdf.file)
-  rm(this.fn) # hopefully prevents overwriting `this.fn` in prior namespaces
-} # end function netCDF.stats.to.stdout.by.timestep
-
-# ----------------------------------------------------------------------
-# code
-# ----------------------------------------------------------------------
-
-# if this is called as a script, provide a main(): see
-# https://stat.ethz.ch/pipermail/r-help/2012-September/323551.html
-# https://stat.ethz.ch/pipermail/r-help/2012-September/323559.html
-if (!interactive()) {
-
-# start debug
-#  cat(sprintf('%s: interactive()==TRUE\n', this.fn))
-#   end debug
-  
-  # TODO: fix `strsplit` regexp below to make this unnecessary
-  library(stringr)
-
-  # pass named arguments: var above separated by '='
-
-  args <- commandArgs(TRUE)
-  # args is now a list of character vectors
-  # First check to see if any arguments were passed, then evaluate each argument:
-  # assign val (RHS) to key (LHS) for arguments of the (required) form 'key=val'
-  if (length(args)==0) {
-    cat(sprintf('%s: no arguments supplied, exiting\n', this.fn))
-#    q(status=1) # KLUDGE:
-# Currently this is not seeing arguments when called from Rscript,
-# so this exit also exits the caller :-(    
-  } else {
-  # simple positional args work
-  # TODO: also support positional usage
-  #  netcdf.fp <- args[1]
-  #  data.var.name <- args[2]
-    # TODO: test arg length: 2 is required!
-
-# start debug
-#    cat(sprintf('%s: got length(args)==%i\n', this.fn, length(args)))
-#   end debug
-
-    for (i in 1:length(args)) {
-#       eval(parse(text=args[[i]]))
-      # `eval(parse())` is unsafe and requires awkward quoting:
-      # e.g., of the following (bash) commandlines
-
-      # - Rscript ./netCDF.stats.to.stdout.r netcdf.fp="GEIA_N2O_oceanic.nc" data.var.name="emi_n2o"
-      #   fails
-
-      # + Rscript ./netCDF.stats.to.stdout.r 'netcdf.fp="GEIA_N2O_oceanic.nc"' 'data.var.name="emi_n2o"'
-      #   succeeds
-
-      # so instead
-      # TODO: use package `optparse` or `getopt`
-      args.keyval.list <-
-        strsplit(as.character(parse(text=args[[i]])),
-          split='[[:blank:]]*<-|=[[:blank:]]*', fixed=FALSE)
-  #                            split='[ \t]*<-|=[ \t]*', fixed=FALSE)
-      args.keyval.vec <- unlist(args.keyval.list, recursive=FALSE, use.names=FALSE)
-      # TODO: test vector elements!
-      # Neither wants to remove all whitespace from around arguments :-( so
-      args.key <- str_trim(args.keyval.vec[1], side="both")
-      args.val <- str_trim(args.keyval.vec[2], side="both")
-
-# start debug
-#       cat(sprintf('%s: got\n', this.fn))
-#       cat('\targs.keyval.list==\n')
-#       print(args.keyval.list)
-#       cat('\targs.keyval.vec==\n')
-#       print(args.keyval.vec)
-#       cat(sprintf('\targs.key==%s\n', args.key))
-#       cat(sprintf('\targs.val==%s\n', args.val))
-#   end debug
-
-      # A real case statement would be nice to have
-      if        (args.key == 'netcdf.fp') {
-        netcdf.fp <- args.val
-      } else if (args.key == 'data.var.name') {
-        data.var.name <- args.val
-      } else {
-        stop(sprintf("unknown argument='%s'", args.key))
-        # TODO: show usage
-        q(status=1) # exit with error
-      }
-    } # end for loop over arguments
-
-    # payload!
-    netCDF.stats.to.stdout(netcdf.fp, data.var.name)
-
-  } # end if testing number of arguments
-} # end if (!interactive())

File regrid_global_to_AQMEII.r

 z.var.name <- Sys.getenv('CLM_CN_REGRID_TIME_VAR_NAME')
 z.var.unit <- Sys.getenv('CLM_CN_REGRID_TIME_VAR_UNIT')
 
-stat.script.fp <- './netCDF.stats.to.stdout.r' # Sys.getenv('STAT_SCRIPT_FP')
+stat.script.fp <- './netCDF.stats.to.stdout.r' # Sys.getenv('STATS_FUNCS_FP')
 
 ## plotting
 
-viz.funcs.fp <- Sys.getenv('VIZ_FUNCS_FP')
+viz.funcs.fp <- Sys.getenv('VIS_FUNCS_FP')
 global.proj4 <- Sys.getenv('GLOBAL_PROJ4')
 
 # ----------------------------------------------------------------------

File regrid_reunit_retemporalize.sh

-#!/usr/bin/env bash
-
-# Requires NCL, R, and bash with arithmetic support.
-# Driver for [regrid_global_to_AQMEII.r,retemp_monthly_to_hourly.ncl,check_conservation.ncl], 
-# * converting global/unprojected CLM-CN data to AQMEII-NA, an LCC-projected subdomain
-# * converting monthly to hourly data (over each month)
-# * checking conservation of mass
-# Configure as needed for your platform.
-
-# ----------------------------------------------------------------------
-# constants with some simple manipulations
-# ----------------------------------------------------------------------
-
-THIS_FN="$(basename $0)"
-# will do the real work
-export CALL_REGRID_FN='regrid_global_to_AQMEII.r'
-export CALL_RETEMP_FN='retemp_reunit.ncl'
-export CALL_CONSERV_FN='check_conservation.ncl'
-
-# model/inventory constants
-export MODEL_YEAR='2008'
-export NOMINAL_GRIDCELL_AREA='1.440e8' # in meter^2, is a float ; stringtofloat(getenv("NOMINAL_GRIDCELL_AREA"))
-export MOLAR_MASS_N2O='44.0128'    # grams per mole of N2O, per wolframalpha.com
-export NITROGEN_MASS_N2O='28.0134' # grams per mole of N2,  per wolframalpha.com
-export SECONDS_PER_HOUR='3600'     # 60 * 60
-export CMAQ_RADIUS='6370000'       # in meters
-
-# for R on EMVL: don't ask :-(
-R_DIR='/usr/local/apps/R-2.15.2/intel-13.0/bin'
-R="${R_DIR}/R"
-RSCRIPT="${R_DIR}/Rscript"
-
-# Ensure $NCARG_ROOT is set for NCL--it should be in your dotfiles, but, JIC ...
-# tlrPanP5
-#NCL_VERSION='ncl_ncarg-6.1.0.Linux_Debian_x86_64_nodap_gcc445'
-#export NCARG_ROOT="${HOME}/bin/${NCL_VERSION}"
-## Only change default if absolutely necessary!
-#NCL_EXEC='ncl'
-# terrae (temporary: they gotta upgrade RHEL, meanwhile use Herwehe's)
-# NCL_VERSION='ncl_ncarg-6.1.0.Linux_RedHat_x86_64_gcc412'
-NCL_VERSION='ncl_ncarg-6.1.2.Linux_RHEL5.6_x86_64_gcc412'
-export NCARG_ROOT="/home/hhg/ncl_ncarg/${NCL_VERSION}"
-NCL_EXEC="${NCARG_ROOT}/bin/ncl"
-
-# workspace
-export WORK_DIR="$(pwd)" # keep it simple for now: same dir as top of repo
-
-# will do the real work
-export CALL_REGRID_FP="${WORK_DIR}/${CALL_REGRID_FN}"
-export CALL_RETEMP_FP="${WORK_DIR}/${CALL_RETEMP_FN}"
-export CALL_CONSERV_FP="${WORK_DIR}/${CALL_CONSERV_FN}"
-
-# for visualization (generally)
-export OUTPUT_SIGNIFICANT_DIGITS='3' # see conservation report below
-# PROJ.4 string for unprojected data
-export GLOBAL_PROJ4='+proj=longlat +ellps=WGS84'
-
-# for plotting (specifically)
-PDF_VIEWER='xpdf'  # whatever works on your platform
-# temporally disaggregate multiple plots
-DATE_FORMAT='%Y%m%d_%H%M'
-export PDF_DIR="${WORK_DIR}"
-
-## Raw input data
-
-# Raw input data is global/unprojected CLM-CN netCDF, with coordvars=
-# lat==(-90,+90)
-# lon==(0,+360), hence need to
-export ROTATE_INPUT="true"
-# time: 14 months (not "decimal year" per `time:units`:
-#       month[0]== month[1], month[12]== month[13] (per Saikawa)
-# Get from my repository.
-CLM_CN_RAW_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/2008PTONCLMCNN2O.nc'
-CLM_CN_RAW_FN="$(basename ${CLM_CN_RAW_URI})"
-CLM_CN_RAW_FN_ROOT="${CLM_CN_RAW_FN%.*}" # everything left of the dot
-export CLM_CN_RAW_FP="${WORK_DIR}/${CLM_CN_RAW_FN}"
-
-CLM_CN_RAW_PDF_FN="${CLM_CN_RAW_FN_ROOT}_$(date +${DATE_FORMAT}).pdf"
-export CLM_CN_RAW_PDF_FP="${WORK_DIR}/${CLM_CN_RAW_PDF_FN}" # path to PDF output
-
-# TODO: automate getting this metadata from the netCDF
-export CLM_CN_RAW_DATAVAR_NAME='n2oemissions'
-export CLM_CN_RAW_DATAVAR_LONGNAME='N2O emissions'
-export CLM_CN_RAW_DATAVAR_UNIT='mgN/m2/month'
-# export CLM_CN_RAW_DATAVAR_NA='-999.0' # not used--hopefully they have no missing data
-export CLM_CN_RAW_TIME_VAR_NAME='time'
-
-## Template for `raster` regridding.
-
-# The template input is a copy of some meteorological data with 52 "real" datavars.
-# That data is in the IOAPI format, which here is basically a wrapper around netCDF.
-# (IOAPI can be used with other data, and similar wrappers exist for other models.)
-# I removed all but one of the datavars (with NCO 'ncks'). TODO: script that!
-TEMPLATE_INPUT_GZ_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/emis_mole_all_20080101_12US1_cmaq_cb05_soa_2008ab_08c.EXTENTS_INPUT.nc.gz'
-TEMPLATE_INPUT_GZ_FN="$(basename ${TEMPLATE_INPUT_GZ_URI})"
-TEMPLATE_INPUT_GZ_FP="${WORK_DIR}/${TEMPLATE_INPUT_GZ_FN}"
-TEMPLATE_INPUT_ROOT="${TEMPLATE_INPUT_GZ_FN%.*}" # everything left of the LAST dot
-TEMPLATE_INPUT_FN="${TEMPLATE_INPUT_ROOT}"
-export TEMPLATE_INPUT_FP="${WORK_DIR}/${TEMPLATE_INPUT_FN}"
-# export TEMPLATE_INPUT_BAND='1' # `ncks` makes dim=TSTEP first
-export TEMPLATE_VAR_NAME='emi_n2o'
-
-## Intermediate product
-# netCDF regridded to AQMEII-NA
-
-CLM_CN_REGRID_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/2008PTONCLMCNN2O_regrid.nc'
-CLM_CN_REGRID_FN="$(basename ${CLM_CN_REGRID_URI})"
-CLM_CN_REGRID_FN_ROOT="${CLM_CN_REGRID_FN%.*}" # everything left of the dot
-export CLM_CN_REGRID_FP="${WORK_DIR}/${CLM_CN_REGRID_FN}"
-
-export CLM_CN_REGRID_DATAVAR_NAME="${CLM_CN_RAW_DATAVAR_NAME}"
-export CLM_CN_REGRID_X_VAR_NAME='COL'
-export CLM_CN_REGRID_Y_VAR_NAME='ROW'
-export CLM_CN_REGRID_TIME_VAR_NAME='TSTEP' # more IOAPI-like than 'time'
-export CLM_CN_REGRID_TIME_VAR_UNIT='month (1=2, 2=Jan, ... 13=Dec, 13=14)'
-
-CLM_CN_REGRID_PDF_FN="${CLM_CN_REGRID_FN_ROOT}_$(date +${DATE_FORMAT}).pdf"
-export CLM_CN_REGRID_PDF_FP="${WORK_DIR}/${CLM_CN_REGRID_PDF_FN}" # path to PDF output
-
-## map scale factors (MSFs)
-# load MSFs from some GRIDCRO2D_<date/> which is pretty large, so gzip it
-
-MSF_GZ_URI='https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na/downloads/GRIDCRO2D_080101.gz'
-MSF_GZ_FN="$(basename ${MSF_GZ_URI})"
-MSF_FN_ROOT="${MSF_GZ_FN%.*}" # everything left of the dot
-MSF_FN="${MSF_FN_ROOT}"       # does not normally have an extension
-MSF_GZ_FP="${WORK_DIR}/${MSF_GZ_FN}"
-export MSF_FP="${WORK_DIR}/${MSF_FN}"
-export MSF_VAR_NAME='MSFX2'
-
-## create data container files from extents/template file
-##### TODO: driver must ensure output_fp_template does not exist!
-export CLM_CN_TARGET_FN_TEMPLATE_STR='######'
-# problem: NCL currently (version=6.1.2) does not support *.ncf :-( workaround below
-CLM_CN_TARGET_FN_ROOT_TEMPLATE="emis_mole_N2O_${CLM_CN_TARGET_FN_TEMPLATE_STR}_12US1_cmaq_cb05_soa_2008ab_08c"
-CLM_CN_TARGET_EXT_CMAQ='ncf'
-CLM_CN_TARGET_EXT_NCL='nc'
-CLM_CN_TARGET_FN_TEMPLATE_CMAQ="${CLM_CN_TARGET_FN_ROOT_TEMPLATE}.${CLM_CN_TARGET_EXT_CMAQ}"
-CLM_CN_TARGET_FN_TEMPLATE_NCL="${CLM_CN_TARGET_FN_ROOT_TEMPLATE}.${CLM_CN_TARGET_EXT_NCL}"
-export CLM_CN_TARGET_FP_TEMPLATE_CMAQ="${WORK_DIR}/${CLM_CN_TARGET_FN_TEMPLATE_CMAQ}"
-export CLM_CN_TARGET_FP_TEMPLATE_NCL="${WORK_DIR}/${CLM_CN_TARGET_FN_TEMPLATE_NCL}"
-
-## global metadata for both {template, "real" monthly/hourly data container} files
-export CLM_CN_TARGET_FILE_ATTR_HISTORY='see https://bitbucket.org/tlroche/clm_cn_global_to_aqmeii-na'
-
-## metadata for datavar in both {template, "real" monthly/hourly data container} files
-export CLM_CN_TARGET_VAR_NAME='N2O'
-# IOAPI pads varattr=long_name to length=16 with spaces
-export CLM_CN_TARGET_VAR_ATTR_LONG_NAME="$(printf '%-16s' ${CLM_CN_TARGET_VAR_NAME})"
-# IOAPI pads varattr=units to length=16 with spaces
-export CLM_CN_TARGET_VAR_ATTR_UNITS="$(printf '%-16s' 'moles/s')"
-# IOAPI pads varattr=var_desc to length=80 with spaces
-export CLM_CN_TARGET_VAR_ATTR_VAR_DESC="$(printf '%-80s' 'Model species ${CLM_CN_TARGET_TEMPLATE_VAR_NAME}')"
-
-## conservation report constants
-# need 5 additional digits for float output, e.g., "4.85e+04"
-# bash arithmetic gotcha: allow no spaces around '='!
-export OUTPUT_SIGNIFICANT_DIGITS='3' # see conservation report below
-# export CONSERV_REPORT_FIELD_WIDTH=$((OUTPUT_SIGNIFICANT_DIGITS + 5))
-export CONSERV_REPORT_FIELD_WIDTH='9' # width of 'AQMEII-NA'
-export CONSERV_REPORT_FLOAT_FORMAT="%${CONSERV_REPORT_FIELD_WIDTH}.$((OUTPUT_SIGNIFICANT_DIGITS - 1))e"
-# echo -e "${THIS_FN}: CONSERV_REPORT_FLOAT_FORMAT=${CONSERV_REPORT_FLOAT_FORMAT}" # debugging
-export CONSERV_REPORT_INT_FORMAT="%${CONSERV_REPORT_FIELD_WIDTH}i"
-export CONSERV_REPORT_COLUMN_SEPARATOR="  "
-export CONSERV_REPORT_TITLE="Is N2O conserved from input to output? units=mgN"
-export CONSERV_REPORT_SUBTITLE="(note (US land area)/(earth land area) ~= 6.15e-02)"
-
-# These helpers should have been cloned into the cwd, but JIC (and for later use). TODO: R-package my code
-
-# use version in this repo
-# STAT_SCRIPT_URI='https://bitbucket.org/tlroche/geia_regrid/raw/6ecdb8ae7d6fd661f7c4616a14b817c5aa9c7f90/netCDF.stats.to.stdout.r'
-# STAT_SCRIPT_FN="$(basename ${STAT_SCRIPT_URI})"
-# export STAT_SCRIPT_FP="${WORK_DIR}/${STAT_SCRIPT_FN}"
-
-VIZ_FUNCS_URI='https://bitbucket.org/tlroche/edgar-4.2_minus_soil_and_biomass_to_aqmeii-na/raw/a2a39d8100260726b7825125b835bdd1959aa91f/visualization.r'
-VIZ_FUNCS_FN="$(basename ${VIZ_FUNCS_URI})"
-export VIZ_FUNCS_FP="${WORK_DIR}/${VIZ_FUNCS_FN}"
-
-# ----------------------------------------------------------------------
-# setup
-# ----------------------------------------------------------------------
-
-# for netcdf4 (ncdf4.so, libnetcdf.so.7) on EMVL:
-# I may need to run this from CLI, not here, and
-# you may not need this at all!
-module add netcdf-4.1.2
-
-mkdir -p ${WORK_DIR}
-
-# get the (nearly) raw input
-if [[ -z "${CLM_CN_RAW_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: CLM_CN_RAW_FP not defined"
-  exit 1
-fi
-if [[ ! -r "${CLM_CN_RAW_FP}" ]] ; then
-  for CMD in \
-    "wget --no-check-certificate -c -O ${CLM_CN_RAW_FP} ${CLM_CN_RAW_URI}" \
-  ; do
-    echo -e "$ ${CMD}"
-    eval "${CMD}"
-  done
-fi
-if [[ ! -r "${CLM_CN_RAW_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: cannot read CLM_CN_RAW_FP=='${CLM_CN_RAW_FP}'"
-  exit 2
-fi
-
-# get the "template" file, used for extent-setting and emissions-file creation
-if [[ -z "${TEMPLATE_INPUT_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: TEMPLATE_INPUT_FP not defined"
-  exit 3
-fi
-if [[ ! -r "${TEMPLATE_INPUT_FP}" ]] ; then
-  if [[ ! -r "${TEMPLATE_INPUT_GZ_FP}" ]] ; then
-    for CMD in \
-      "wget --no-check-certificate -c -O ${TEMPLATE_INPUT_GZ_FP} ${TEMPLATE_INPUT_GZ_URI}" \
-    ; do
-      echo -e "$ ${CMD}"
-      eval "${CMD}"
-    done
-  fi
-  if [[ -r "${TEMPLATE_INPUT_GZ_FP}" ]] ; then
-    for CMD in \
-      "gunzip ${TEMPLATE_INPUT_GZ_FP}" \
-    ; do
-      echo -e "$ ${CMD}"
-      eval "${CMD}"
-    done
-  fi
-fi
-if [[ ! -r "${TEMPLATE_INPUT_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: cannot read TEMPLATE_INPUT_FP=='${TEMPLATE_INPUT_FP}'"
-  exit 4
-fi
-
-# get the regridded output from the R script? no:
-# only for testing. TODO: provide commandline-switch control for this
-if [[ -z "${CLM_CN_REGRID_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: CLM_CN_REGRID_FP not defined"
-  exit 5
-fi
-# if [[ ! -r "${CLM_CN_REGRID_FP}" ]] ; then
-#   for CMD in \
-#     "wget --no-check-certificate -c -O ${CLM_CN_REGRID_FP} ${CLM_CN_REGRID_URI}" \
-#   ; do
-#     echo -e "$ ${CMD}"
-#     eval "${CMD}"
-#   done
-# fi
-# if [[ ! -r "${CLM_CN_REGRID_FP}" ]] ; then
-#   echo -e "${THIS_FN}: ERROR: cannot read CLM_CN_REGRID_FP=='${CLM_CN_REGRID_FP}'"
-#   exit 6
-# fi
-
-if [[ -z "${MSF_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: MSF_FP not defined"
-  exit 7
-fi
-if [[ ! -r "${MSF_FP}" ]] ; then
-  if [[ ! -r "${MSF_GZ_FP}" ]] ; then
-    for CMD in \
-      "wget --no-check-certificate -c -O ${MSF_GZ_FP} ${MSF_GZ_URI}" \
-    ; do
-      echo -e "$ ${CMD}"
-      eval "${CMD}"
-    done
-  fi
-  if [[ -r "${MSF_GZ_FP}" ]] ; then
-    for CMD in \
-      "gunzip ${MSF_GZ_FP}" \
-    ; do
-      echo -e "$ ${CMD}"
-      eval "${CMD}"
-    done
-  fi
-fi
-if [[ ! -r "${MSF_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: cannot read MSF_FP=='${MSF_FP}'"
-  exit 8
-fi
-
-if [[ -z "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: CLM_CN_TARGET_FP_TEMPLATE_NCL not defined"
-  exit 9
-fi
-if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
-  # delete: NCL will recreate
-  for CMD in \
-    "rm ${CLM_CN_TARGET_FP_TEMPLATE_NCL}" \
-  ; do
-    echo -e "$ ${CMD}"
-    eval "${CMD}"
-  done
-fi
-if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: cannot delete CLM_CN_TARGET_FP_TEMPLATE_NCL=='${CLM_CN_TARGET_FP_TEMPLATE_NCL}'"
-  exit 10
-fi
-
-if [[ -z "${VIZ_FUNCS_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: VIZ_FUNCS_FP not defined"
-  exit 11
-fi
-if [[ ! -r "${VIZ_FUNCS_FP}" ]] ; then
-  for CMD in \
-    "wget --no-check-certificate -c -O ${VIZ_FUNCS_FP} ${VIZ_FUNCS_URI}" \
-  ; do
-    echo -e "$ ${CMD}"
-    eval "${CMD}"
-  done
-fi
-if [[ ! -r "${VIZ_FUNCS_FP}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: cannot download VIZ_FUNCS_FP=='${VIZ_FUNCS_FP}'"
-  exit 12
-fi
-
-# ----------------------------------------------------------------------
-# payload
-# ----------------------------------------------------------------------
-
-# ----------------------------------------------------------------------
-# regrid from global/unprojected to AQMEII/LCC
-# ----------------------------------------------------------------------
-
-cat <<EOM
-
-About to run R script="${CALL_REGRID_FP}"
-
-EOM
-
-# If this fails ...
-"${RSCRIPT}" "${CALL_REGRID_FP}"
-# ... just start R ...
-# "${R}"
-# ... and source ${CALL_REGRID_FP}, e.g.,
-# source('....r')
-
-# ----------------------------------------------------------------------
-# display cwd and PDFs (if plotted)
-# ----------------------------------------------------------------------
-
-if [[ -r "${CLM_CN_RAW_PDF_FP}" ]] ; then
-  if [[ -r "${CLM_CN_REGRID_PDF_FP}" ]] ; then
-#      "${PDF_VIEWER} ${CLM_CN_RAW_PDF_FP} &" \
-    for CMD in \
-      "ls -alht ${WORK_DIR}" \
-      "${PDF_VIEWER} ${CLM_CN_REGRID_PDF_FP} &" \
-    ; do
-      echo -e "$ ${CMD}"
-      eval "${CMD}"
-    done
-  else
-    echo -e "${THIS_FN}: ERROR: regrid not plotted: ${CLM_CN_REGRID_PDF_FP}"
-  fi
-else
-  echo -e "${THIS_FN}: ERROR: input not plotted: ${CLM_CN_RAW_PDF_FP}"
-fi
-
-# ----------------------------------------------------------------------
-# "retemporalize" from {monthly, native units} to {hourly, CMAQ units}
-# ----------------------------------------------------------------------
-
-# ${NCL_EXEC} # bail to NCL and copy script lines
-# TODO: pass commandline args to NCL
-# punt: just use envvars :-(
-
-for SCRIPT in \
-  "${CALL_RETEMP_FP}" \
-  "${CALL_CONSERV_FP}" \
-; do
-cat <<EOM
-
-About to run NCL script="${SCRIPT}"
-
-EOM
-  # '-n' -> http://www.ncl.ucar.edu/Document/Functions/Built-in/print.shtml
-  CMD="${NCL_EXEC} -n ${SCRIPT}"
-  echo -e "$ ${CMD}"
-  eval "${CMD}"
-done
-
-# ----------------------------------------------------------------------
-# cleanup/teardown
-# ----------------------------------------------------------------------
-
-if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
-  # delete: NCL will recreate
-  for CMD in \
-    "rm ${CLM_CN_TARGET_FP_TEMPLATE_NCL}" \
-  ; do
-    echo -e "$ ${CMD}"
-    eval "${CMD}"
-  done
-fi
-if [[ -r "${CLM_CN_TARGET_FP_TEMPLATE_NCL}" ]] ; then
-  echo -e "${THIS_FN}: ERROR: cannot delete CLM_CN_TARGET_FP_TEMPLATE_NCL=='${CLM_CN_TARGET_FP_TEMPLATE_NCL}'"
-  exit 11
-fi
-
-# ----------------------------------------------------------------------
-# show new monthly/hourly files (i.e., hourly emissions by month)
-# ----------------------------------------------------------------------
-
-for CMD in \
-  "ls -alh ${WORK_DIR}/*.ncf" \
-  "ls -alht ${WORK_DIR}/*.nc" \
-; do
-  echo -e "$ ${CMD}"
-  eval "${CMD}"
-done

File uber_driver.sh

 
 # If you decide to run this, you should first
 
-# * un/comment var=ACCESS to reflect your available/desired git protocol
+# * un/comment var=ACCESS to reflect your available/desired file-transfer protocol
+# * if using ACCESS='file', edit FILE_LIST below
 # * edit var=USERNAME to reflect yours on bitbucket
 # * edit var=REPO_ROOT to state where to create your repo clone
 # * remember to enable netCDF-4 on your system, e.g.
 # > module add netcdf-4.1.2 # on terrae (a cluster on which I work)
 
-# ACCESS='file'       # use uncommitted code in current directory
+ACCESS='file'       # use uncommitted code in current directory
 # ACCESS='git/ssh'    # outgoing ssh works (preferred if available)
 # ACCESS='http+cert'  # outgoing ssh blocked, but you have certificates
-ACCESS='http-cert'  # (terrae) outgoing ssh blocked, no certs installed
+# ACCESS='http-cert'  # (terrae) outgoing ssh blocked, no certs installed
 
 REPO_ROOT='/tmp' # or location of your choice: repo/workspace created in subdir
 PROJECT_NAME='clm_cn_global_to_aqmeii-na'
+# what actually does the work
+DRIVER_FN='CLMCN_driver.sh'
+
+# if [[ "${ACCESS}" == 'file' ]], you'll need
+FILE_LIST="./${DRIVER_FN} \
+    ./check_conservation.ncl \
+    ./regrid_global_to_AQMEII.r \
+    ./retemp_reunit.ncl \
+    ./summarize.ncl \
+    ./time.ncl"
+
 REPO_DIR="${REPO_ROOT}/${PROJECT_NAME}"
 if [[ -d "${REPO_DIR}" ]] ; then
   echo -e "ERROR? repo dir='${REPO_DIR}' exists: move or delete it before running this script"
   exit 1
-else
-  mkdir -p ${REPO_ROOT}
 fi
 
+### USER BEWARE: following `if`s should probably be a `case`
+
 if [[ "${ACCESS}" == 'file' ]] ; then
-  mkdir -p ${REPO_DIR}
-  # TODO: define constant for this file list
-  cp \
-    ./check_conservation.ncl \
-    ./netCDF.stats.to.stdout.r \
-    ./regrid_global_to_AQMEII.r \
-    ./regrid_reunit_retemporalize.sh \
-    ./retemp_reunit.ncl \
-    ./summarize.ncl \
-    ./time.ncl \
-   ${REPO_DIR}/
+  if [[ ! -x "./${DRIVER_FN}" ]] ; then
+    echo -e "ERROR: ACCESS==file, but driver=='${DRIVER_FN}' not executable"
+    exit 2
+  else
+    for CMD in \
+      "mkdir -p ${REPO_DIR}" \
+      "cp ${FILE_LIST} ${REPO_DIR}/ " \
+    ; do
+      echo -e "$ ${CMD}"
+      eval "${CMD}"
+    done
+  fi
 fi
 
 if [[ "${ACCESS}" == 'git/ssh' ]] ; then
   pushd ${REPO_ROOT}
   REPO_URI="git@bitbucket.org:tlroche/${PROJECT_NAME}.git"
   git clone ${REPO_URI}
+  popd
 fi
 
 if [[ "${ACCESS}" == 'http+cert' ]] ; then
 #  REPO_URI="https://${USERNAME}@bitbucket.org/tlroche/${PROJECT_NAME}.git"
   REPO_URI="https://tlroche@bitbucket.org/tlroche/${PROJECT_NAME}.git"
   git clone ${REPO_URI}
+  popd
 fi
 
 if [[ "${ACCESS}" == 'http-cert' ]] ; then
 #  REPO_URI="https://${USERNAME}@bitbucket.org/tlroche/${PROJECT_NAME}.git"
   REPO_URI="https://tlroche@bitbucket.org/tlroche/${PROJECT_NAME}.git"
   env GIT_SSL_NO_VERIFY=true git clone ${REPO_URI}
+  popd
 fi
 
-popd
 pushd ${REPO_DIR}
-./regrid_reunit_retemporalize.sh
+./${DRIVER_FN}