diff --git a/montage/README.md b/montage/README.md
new file mode 100644
index 0000000..b5da874
--- /dev/null
+++ b/montage/README.md
@@ -0,0 +1,48 @@
+
+
+Montage Workflow Example
+------------------------
+
+This workflow gives an example of using Makeflow to parallelize
+the Montage astronomical image mosaic tool.
+
+If you have not done so already, please clone this example repository like so:
+```
+git clone https://github.com/cooperative-computing-lab/makeflow-examples.git
+cd ./makeflow-examples/montage
+```
+
+First, build the Montage binary for your architecture:
+
+```
+git clone https://github.com/Caltech-IPAC/Montage ./montage
+cp ./mDAG.c ./montage/grid/Pegasus
+cd montage
+make
+cd ..
+```
+
+Then, create a working directory and generate a workflow:
+
+```
+mkdir ./montage_example
+./montage/bin/mDAG 2mass j m51 0.5 0.5 0.00277778 ./montage_example http://montage-web.ipac.caltech.edu/workspace/m51
+```
+
+Next, run the file_get.pl script to grab all the necessary images of the sky using the URLs generated by mDAG:
+
+```
+cp ./file_get.pl ./montage_example
+cd ./montage_example
+perl ./file_get.pl ./url.list
+```
+
+Finally, execute the workflow using makeflow locally,
+or using a batch system like Condor, SGE, or Work Queue:
+
+```
+makeflow montage.mf
+makeflow -T condor montage.mf
+makeflow -T sge montage.mf
+makeflow -T wq montage.mf
+```
diff --git a/montage/file_get.pl b/montage/file_get.pl
new file mode 100644
index 0000000..09a38c7
--- /dev/null
+++ b/montage/file_get.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+#
+#Copyright (C) 2016- The University of Notre Dame
+#This software is distributed under the GNU General Public License.
+#See the file COPYING for details.
+#
+
+use strict;
+use Scalar::Util qw(looks_like_number);
+use Math::Complex;
+use POSIX;
+
+my $num_args = $#ARGV + 1;
+if($num_args ne 1) {
+ print "Must specify input data file.\n";
+ exit 1;
+}
+
+my $in = $ARGV[0];
+my $result = 0;
+my $i = 1;
+open(INPUT, $in);
+
+ while (my $line = ) {
+ chomp $line;
+ my @parts = split(" ",$line);
+ my $final = $parts[0];
+ my $intermediate = $parts[0] . ".gz";
+ my $url = $parts[1];
+ $result = system("curl $url -o $intermediate");
+ if($result ne 0) { print "Error in curl #$i\n"; exit 1; }
+ $result = system("gunzip -c $intermediate > $final; rm $intermediate");
+ if($result ne 0) { print "Error in gunzip and rm #$i\n"; exit 1; }
+ $i++;
+ sleep(1);
+ }
+
+close(INPUT);
+exit 0;
diff --git a/montage/mDAG.c b/montage/mDAG.c
new file mode 100644
index 0000000..74c11cd
--- /dev/null
+++ b/montage/mDAG.c
@@ -0,0 +1,2961 @@
+/*
+
+Version Developer Date Change
+------- --------------- ------- -----------------------
+1.3 Mats Rynge 17Sep10 Updated to Pegasus DAX schema version 2
+1.2 John Good 28Mar06 Add MAGZP processing for 2MASS and fix
+ location of "idstr" in some file names
+1.1 John Good 28Mar06 Added mode based on input template file
+1.0 John Good 30Nov05 Baseline code, pretty much just a port
+ of Joe Jacob's PERL code.
+
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define MAXSTR 1024
+
+char *svc_value();
+
+int readTemplate(char *template);
+int printError (char *msg);
+int stradd (char *header, char *card);
+
+int strcasecmp (const char *s1, const char *s2);
+
+char *url_encode (char *s);
+int tcp_connect (char *hostname, int port);
+
+int lookup (char *mosaicCenter, double *ra, double *dec);
+
+static struct WorldCoor *wcs;
+
+int naxis1, naxis2;
+int sys;
+double epoch;
+
+int debug = 1;
+FILE *fdebug;
+
+char fmt [MAXSTR];
+char dfmt [MAXSTR];
+
+
+/******************************************************************************/
+/* */
+/* mDAG */
+/* */
+/* Creates an XML-based Directed Acyclic Graph (DAG) that specifies "jobs" */
+/* or Montage modules to be run to produce a mosaic, "files" to be */
+/* consumed or generated during processing (input, intermediate, and output */
+/* files), and "dependencies" between jobs and files that imply an order */
+/* in which jobs should be run. In this "abstract graph", logical names are */
+/* assigned to jobs and files. The abstract graph is intended to be an input */
+/* to a job scheduler, such as Pegasus in the Chimera Virtual Data System. */
+/* */
+/* Inputs: */
+/* */
+/* 1) Directory name containing the input data files to be mosaicked. */
+/* 2) Montage template header file specifying the mosaic parameters. */
+/* 3) Directory name for output and temporary files produced by this script. */
+/* */
+/* Outputs: */
+/* */
+/* 1) XML-based DAG */
+/* */
+/* 2) Data files needed for processing the workflow specified in the DAG: */
+/* */
+/* a) Projected image table */
+/* b) Background-corrected image table */
+/* c) Table listing the individual difference image fit plane parameter */
+/* files that will be generated by each run of mFitplane during mosaic */
+/* processing. */
+/* */
+/* NOTE: just filename = 35 characters long */
+/******************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int i, j, k, ncol, nimages;
+ int haveHdr, itmp, istat, mAddCntr;
+ int nparents, parent, parent_prev;
+ int naxis1s, naxis2s;
+
+ //Flag for outputting Makeflow instead of DAX
+ int dax_mode = 1;
+
+ char line [MAXSTR];
+ char mproj [MAXSTR];
+ char survey [MAXSTR];
+ char band [MAXSTR];
+ char hdrFile [MAXSTR];
+ char mosaicCenter[MAXSTR];
+ char mosaicWidth [MAXSTR];
+ char mosaicHeight[MAXSTR];
+ char mosaicCdelt [MAXSTR];
+ char workdir [MAXSTR];
+ char urlbase [MAXSTR];
+ char workurlbase [MAXSTR];
+ char timestr [MAXSTR];
+ char cmd [MAXSTR];
+ char status [MAXSTR];
+ char msg [MAXSTR];
+ char fname [MAXSTR];
+ char fitname [MAXSTR];
+ char plusname [MAXSTR];
+ char minusname [MAXSTR];
+ char jobid [MAXSTR];
+ char fileList [MAXSTR];
+ char parentList [MAXSTR];
+ char sortedParent[MAXSTR];
+
+ char *fileid;
+ char *parentid;
+ int haveurlbase = 0;
+
+ clock_t timeval;
+
+ double width;
+ double height;
+ double cdelt;
+ double crval1, crval2;
+ double crpix1, crpix2;
+
+ int tileSize, tileOverlapX, tileOverlapY;
+ int numTiles, numTilesX, numTilesY;
+
+ int ifname, iurl, icntr1, icntr2, iplusname, iminusname, iscale;
+ int cntr, cntr1, cntr2, id, level;
+
+ int shrinkFactor, shrinkFactorX, shrinkFactorY;
+
+ double x, y, z;
+ double xc, yc, zc;
+ double xpos, ypos, dtr;
+ double dist, maxRadius;
+ double lonc, latc;
+
+ FILE *fp;
+ FILE *fdag;
+ FILE *ffit;
+ FILE *fcache;
+ FILE *furl;
+ FILE *ffile;
+ FILE *fparent;
+
+ char dv_version [MAXSTR];
+
+ int maxtbl = 1000;
+
+ char key[MAXSTR];
+ char val[MAXSTR];
+
+ struct stat type;
+
+ HT_table_t *depends;
+
+ char *path = getenv("MONTAGE_HOME");
+
+
+ /* Various time value variables */
+
+ char buffer[256];
+
+ int yr, mo, day, hr, min, sec, pid;
+
+ time_t curtime;
+ struct tm *loctime;
+
+ char idstr[256];
+
+
+ dtr = atan(1.0)/45.;
+
+ strcpy(dv_version, "1.0");
+
+ HT_set_debug(0);
+
+
+ /* Generate a unique ID based on data/time/pid */
+
+ curtime = time (NULL);
+ loctime = localtime (&curtime);
+
+ strftime(buffer, 256, "%Y", loctime);
+ yr = atoi(buffer);
+
+ strftime(buffer, 256, "%m", loctime);
+ mo = atoi(buffer);
+
+ strftime(buffer, 256, "%d", loctime);
+ day = atoi(buffer);
+
+ strftime(buffer, 256, "%H", loctime);
+ hr = atoi(buffer);
+
+ strftime(buffer, 256, "%M", loctime);
+ min = atoi(buffer);
+
+ strftime(buffer, 256, "%S", loctime);
+ sec = atoi(buffer);
+
+ pid = (int)getpid();
+
+ sprintf(idstr, "%04d%02d%02d_%02d%02d%02d_%d",
+ yr, mo, day, hr, min, sec, pid);
+
+
+
+ /* Set up the dependency hash table */
+
+ depends = HT_create_table(maxtbl);
+
+ timeval = time(0);
+
+ strcpy(timestr, ctime((const time_t *)(&timeval)));
+
+ for(i=0; i 1)
+ svc_debug(fdebug);
+ }
+
+
+
+ /* Get the location/size information */
+
+ haveHdr = 0;
+
+ if(argc < 2)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Usage: %s survey band objstr width height cdelt workdir workurlbase [urlbase] | %s -m survey band objstr width height cdelt workdir workurlbase [urlbase] | %s -h survey band hdrfile workdir workurlbase [urlbase] (object/location string must be a single argument)\"]\n", argv[0], argv[0]);
+ exit(0);
+ }
+
+ if(strcmp(argv[1], "-h") == 0)
+ {
+ if(argc < 7)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Usage: %s survey band objstr width height cdelt workdir workurlbase [urlbase] | %s -m survey band objstr width height cdelt workdir workurlbase [urlbase] | %s -h survey band hdrfile workdir workurlbase [urlbase] (object/location string must be a single argument)\"]\n", argv[0], argv[0]);
+ exit(0);
+ }
+
+ haveHdr = 1;
+
+ strcpy(survey, argv[2]);
+ strcpy(band, argv[3]);
+ strcpy(hdrFile, argv[4]);
+ strcpy(workdir, argv[5]);
+ strcpy(workurlbase, argv[6]);
+ if(argc == 8) {
+ strcpy(urlbase, argv[7]);
+ haveurlbase = 1;
+ }
+ }
+ else if(strcmp(argv[1], "-m") == 0)
+ {
+ if(argc < 9)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Usage: %s survey band objstr width height cdelt workdir workurlbase [urlbase] | %s -m survey band objstr width height cdelt workdir workurlbase [urlbase] | %s -h survey band hdrfile workdir workurlbase [urlbase] (object/location string must be a single argument)\"]\n", argv[0], argv[0]);
+ exit(0);
+ }
+
+ dax_mode = 0;
+
+ strcpy(survey, argv[1]);
+ strcpy(band, argv[2]);
+ strcpy(mosaicCenter, argv[3]);
+ strcpy(mosaicWidth, argv[4]);
+ strcpy(mosaicHeight, argv[5]);
+ strcpy(mosaicCdelt, argv[6]);
+ strcpy(workdir, argv[7]);
+ strcpy(workurlbase, argv[8]);
+ if(argc == 10) {
+ strcpy(urlbase, argv[9]);
+ haveurlbase = 1;
+ }
+
+ width = fabs(atof(mosaicWidth));
+ height = fabs(atof(mosaicHeight));
+ cdelt = fabs(atof(mosaicCdelt));
+
+ naxis1 = (int)(width / cdelt) + 0.5;
+ naxis2 = (int)(height / cdelt) + 0.5;
+
+ crpix1 = (naxis1+1.)/2.;
+ crpix2 = (naxis2+1.)/2.;
+ }
+ else
+ {
+ if(argc < 9)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Usage: %s survey band objstr width height cdelt workdir workurlbase [urlbase] | %s -h survey band hdrfile workdir workurlbase [urlbase] (object/location string must be a single argument)\"]\n", argv[0], argv[0]);
+ exit(0);
+ }
+
+ strcpy(survey, argv[1]);
+ strcpy(band, argv[2]);
+ strcpy(mosaicCenter, argv[3]);
+ strcpy(mosaicWidth, argv[4]);
+ strcpy(mosaicHeight, argv[5]);
+ strcpy(mosaicCdelt, argv[6]);
+ strcpy(workdir, argv[7]);
+ strcpy(workurlbase, argv[8]);
+ if(argc == 10) {
+ strcpy(urlbase, argv[9]);
+ haveurlbase = 1;
+ }
+
+ width = fabs(atof(mosaicWidth));
+ height = fabs(atof(mosaicHeight));
+ cdelt = fabs(atof(mosaicCdelt));
+
+ naxis1 = (int)(width / cdelt) + 0.5;
+ naxis2 = (int)(height / cdelt) + 0.5;
+
+ crpix1 = (naxis1+1.)/2.;
+ crpix2 = (naxis2+1.)/2.;
+ }
+
+ istat = stat(workdir, &type);
+ if(istat < 0)
+ printError("work directory doesn't exist");
+
+ strcpy(mproj, "mProjectPP");
+
+ if(strcasecmp(survey, "dss") == 0
+ || strcasecmp(survey, "dposs") == 0)
+ strcpy(mproj, "mProject");
+
+
+ /**************************************************************/
+ /* If we already have the header, we need the size and center */
+ /* or if we have the size/center, we need to build the header */
+ /**************************************************************/
+
+ if(haveHdr)
+ {
+ maxRadius = 0;
+
+ readTemplate(hdrFile);
+
+
+ /* Coordinates of center */
+
+ pix2wcs(wcs, naxis1/2., naxis2/2.,
+ &xpos, &ypos);
+
+ xc = cos(ypos*dtr) * cos(xpos*dtr);
+ yc = cos(ypos*dtr) * sin(xpos*dtr);
+ zc = sin(ypos*dtr);
+
+ convertCoordinates(sys, epoch, xpos, ypos,
+ EQUJ, 2000., &lonc, &latc, 0.0);
+
+ sprintf(mosaicCenter, "%.6f %.6f eq J2000", lonc, latc);
+
+
+ /* Lower left */
+
+ pix2wcs(wcs, 0.5, 0.5, &xpos, &ypos);
+
+ x = cos(ypos*dtr) * cos(xpos*dtr);
+ y = cos(ypos*dtr) * sin(xpos*dtr);
+ z = sin(ypos*dtr);
+
+ dist = acos(x*xc + y*yc + z*zc) / dtr;
+
+ if(dist > maxRadius)
+ maxRadius = dist;
+
+
+ /* Lower right */
+
+ pix2wcs(wcs, naxis1+0.5, 0.5, &xpos, &ypos);
+
+ x = cos(ypos*dtr) * cos(xpos*dtr);
+ y = cos(ypos*dtr) * sin(xpos*dtr);
+ z = sin(ypos*dtr);
+
+ dist = acos(x*xc + y*yc + z*zc) / dtr;
+
+ if(dist > maxRadius)
+ maxRadius = dist;
+
+
+ /* Upper right */
+ pix2wcs(wcs, naxis1+0.5,
+ naxis2+0.5, &xpos, &ypos);
+
+ x = cos(ypos*dtr) * cos(xpos*dtr);
+ y = cos(ypos*dtr) * sin(xpos*dtr);
+ z = sin(ypos*dtr);
+
+ dist = acos(x*xc + y*yc + z*zc) / dtr;
+
+ if(dist > maxRadius)
+ maxRadius = dist;
+
+
+ /* Upper left */
+
+ pix2wcs(wcs, 0.5, naxis2+0.5, &xpos, &ypos);
+
+ x = cos(ypos*dtr) * cos(xpos*dtr);
+ y = cos(ypos*dtr) * sin(xpos*dtr);
+ z = sin(ypos*dtr);
+
+ dist = acos(x*xc + y*yc + z*zc) / dtr;
+
+ if(dist > maxRadius)
+ maxRadius = dist;
+
+ width = 2. * maxRadius;
+ height = 2. * maxRadius;
+
+ sprintf(mosaicWidth, "%.6f", width);
+ sprintf(mosaicHeight, "%.6f", height);
+ }
+
+ else
+ {
+ /****************************************************/
+ /* Find the coordinates for the center of the image */
+ /****************************************************/
+
+ lookup(mosaicCenter, &crval1, &crval2);
+
+
+ /*******************************/
+ /* Create header template file */
+ /*******************************/
+
+ sprintf(hdrFile, "%s/region.hdr", workdir);
+
+ fp = fopen(hdrFile, "w+");
+
+ if(fp == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening header template file\"]\n");
+ exit(0);
+ }
+
+ fprintf(fp, "SIMPLE = T\n" );
+ fprintf(fp, "BITPIX = -64\n" );
+ fprintf(fp, "NAXIS = 2\n" );
+ fprintf(fp, "NAXIS1 = %d\n", naxis1 );
+ fprintf(fp, "NAXIS2 = %d\n", naxis2 );
+ fprintf(fp, "CTYPE1 = '%s'\n", "RA---TAN" );
+ fprintf(fp, "CTYPE2 = '%s'\n", "DEC--TAN" );
+ fprintf(fp, "CRVAL1 = %11.6f\n", crval1 );
+ fprintf(fp, "CRVAL2 = %11.6f\n", crval2 );
+ fprintf(fp, "CRPIX1 = %11.6f\n", crpix1 );
+ fprintf(fp, "CRPIX2 = %11.6f\n", crpix2 );
+ fprintf(fp, "CDELT1 = %.9f\n", -cdelt );
+ fprintf(fp, "CDELT2 = %.9f\n", cdelt );
+ fprintf(fp, "CROTA2 = %11.6f\n", 0.0 );
+ fprintf(fp, "EQUINOX = %d\n", 2000 );
+
+ if(strcasecmp(survey, "2MASS") == 0)
+ {
+ if(strcasecmp(band, "J") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 20.9044);
+
+ else if(strcasecmp(band, "H") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 20.4871);
+
+ else if(strcasecmp(band, "K") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 19.9757);
+ }
+
+ fprintf(fp, "END\n" );
+
+ fclose(fp);
+ }
+
+
+
+ /***********************************/
+ /* Create big header template file */
+ /***********************************/
+
+ sprintf(hdrFile, "%s/big_region.hdr", workdir);
+
+ fp = fopen(hdrFile, "w+");
+
+ if(fp == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening big header template file\"]\n");
+ exit(0);
+ }
+
+ fprintf(fp, "SIMPLE = T\n" );
+ fprintf(fp, "BITPIX = -64\n" );
+ fprintf(fp, "NAXIS = 2\n" );
+ fprintf(fp, "NAXIS1 = %d\n", naxis1+3000 );
+ fprintf(fp, "NAXIS2 = %d\n", naxis2+3000 );
+ fprintf(fp, "CTYPE1 = '%s'\n", "RA---TAN" );
+ fprintf(fp, "CTYPE2 = '%s'\n", "DEC--TAN" );
+ fprintf(fp, "CRVAL1 = %11.6f\n", crval1 );
+ fprintf(fp, "CRVAL2 = %11.6f\n", crval2 );
+ fprintf(fp, "CRPIX1 = %11.6f\n", crpix1+1500 );
+ fprintf(fp, "CRPIX2 = %11.6f\n", crpix2+1500 );
+ fprintf(fp, "CDELT1 = %.9f\n", -cdelt );
+ fprintf(fp, "CDELT2 = %.9f\n", cdelt );
+ fprintf(fp, "CROTA2 = %11.6f\n", 0.0 );
+ fprintf(fp, "EQUINOX = %d\n", 2000 );
+
+ if(strcasecmp(survey, "2MASS") == 0)
+ {
+ if(strcasecmp(band, "J") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 20.9044);
+
+ else if(strcasecmp(band, "H") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 20.4871);
+
+ else if(strcasecmp(band, "K") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 19.9757);
+ }
+
+ fprintf(fp, "END\n" );
+ fclose(fp);
+
+
+ /************************************************/
+ /* Get list of raw input images for this region */
+ /************************************************/
+
+ /* this is how mExec is implemented */
+ double scaleWidth = width * 1.42;
+ double scaleHeight = height * 1.42;
+
+ if(path)
+ sprintf(cmd, "%s/bin/mArchiveList %s %s \"%s\" %.2f %.2f %s/images.tbl",
+ path, survey, band, mosaicCenter, scaleWidth, scaleHeight, workdir);
+ else
+ sprintf(cmd, "mArchiveList %s %s \"%s\" %.2f %.2f %s/images.tbl",
+ survey, band, mosaicCenter, scaleWidth, scaleHeight, workdir);
+
+ if(debug)
+ {
+ fprintf(fdebug, "[%s]\n", cmd);
+ fflush(fdebug);
+ }
+
+ svc_run(cmd);
+
+ strcpy( status, svc_value( "stat" ));
+
+ if (strcmp( status, "ERROR") == 0)
+ {
+ strcpy( msg, svc_value( "msg" ));
+
+ printError(msg);
+ }
+
+ if (strcmp(status, "ABORT") == 0)
+ {
+ strcpy( msg, svc_value( "msg" ));
+
+ printError(msg);
+ }
+
+ nimages = atof(svc_value("count"));
+
+ if (nimages == 0)
+ {
+ sprintf( msg, "%s has no data covering this area", survey);
+
+ printError(msg);
+ }
+
+
+
+ /*****************************************/
+ /* Get the image lists the DAG will need */
+ /*****************************************/
+
+ if(path)
+ sprintf(cmd, "%s/bin/mDAGTbls %s/images.tbl %s/big_region.hdr %s/rimages.tbl %s/pimages.tbl %s/cimages.tbl",
+ path, workdir, workdir, workdir, workdir, workdir);
+ else
+ sprintf(cmd, "mDAGTbls %s/images.tbl %s/big_region.hdr %s/rimages.tbl %s/pimages.tbl %s/cimages.tbl",
+ workdir, workdir, workdir, workdir, workdir);
+
+
+ if(debug)
+ {
+ fprintf(fdebug, "[%s]\n", cmd);
+ fflush(fdebug);
+ }
+
+ svc_run(cmd);
+
+ strcpy( status, svc_value( "stat" ));
+
+ if (strcmp( status, "ERROR") == 0)
+ {
+ strcpy( msg, svc_value( "msg" ));
+
+ printError(msg);
+ }
+
+
+
+ /******************************************/
+ /* Get the overlap list the DAG will need */
+ /******************************************/
+
+ if(path)
+ sprintf(cmd, "%s/bin/mOverlaps %s/rimages.tbl %s/diffs.tbl",
+ path, workdir, workdir);
+ else
+ sprintf(cmd, " mOverlaps %s/rimages.tbl %s/diffs.tbl",
+ workdir, workdir);
+
+ if(debug)
+ {
+ fprintf(fdebug, "[%s]\n", cmd);
+ fflush(fdebug);
+ }
+
+ svc_run(cmd);
+
+ strcpy( status, svc_value( "stat" ));
+
+ if (strcmp( status, "ERROR") == 0)
+ {
+ strcpy( msg, svc_value( "msg" ));
+
+ printError(msg);
+ }
+
+
+
+ /********************************************/
+ /* Determine number of output mosaic tiles. */
+ /********************************************/
+
+ tileSize = 7200;
+ tileOverlapX = 100;
+ tileOverlapY = 100;
+
+ numTilesX = naxis1 / tileSize + 1;
+ numTilesY = naxis2 / tileSize + 1;
+
+ numTiles = numTilesX * numTilesY;
+
+
+
+ /****************************************************/
+ /* Determine shrink factor for presentation image. */
+ /****************************************************/
+
+ shrinkFactorX = (int)(naxis1 / 1024. + 1.);
+ shrinkFactorY = (int)(naxis2 / 1024. + 1.);
+
+ shrinkFactor = shrinkFactorX;
+ if(shrinkFactor < shrinkFactorY)
+ shrinkFactor = shrinkFactorY;
+
+ if(debug)
+ {
+ fprintf(fdebug, "\n");
+ fprintf(fdebug, "numTilesX = %d\n", numTilesX);
+ fprintf(fdebug, "numTilesY = %d\n", numTilesY);
+ fprintf(fdebug, "numTiles = %d\n", numTiles);
+ fprintf(fdebug, "\n");
+ fprintf(fdebug, "shrinkFactorX = %d\n", shrinkFactorX);
+ fprintf(fdebug, "shrinkFactorY = %d\n", shrinkFactorY);
+ fprintf(fdebug, "shrinkFactor = %d\n", shrinkFactor);
+ fprintf(fdebug, "\n");
+ fflush(fdebug);
+ }
+
+ if(numTiles > 1)
+ {
+ /*******************************/
+ /* Create header template file */
+ /*******************************/
+
+ sprintf(hdrFile, "%s/shrunken.hdr", workdir);
+
+ fp = fopen(hdrFile, "w+");
+
+ if(fp == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening header template file\"]\n");
+ exit(0);
+ }
+
+ naxis1s = floor((double)naxis1/shrinkFactor);
+ naxis2s = floor((double)naxis2/shrinkFactor);
+
+ fprintf(fp, "SIMPLE = T\n" );
+ fprintf(fp, "BITPIX = -64\n" );
+ fprintf(fp, "NAXIS = 2\n" );
+ fprintf(fp, "NAXIS1 = %d\n", naxis1s );
+ fprintf(fp, "NAXIS2 = %d\n", naxis2s );
+ fprintf(fp, "CTYPE1 = '%s'\n", "RA---TAN" );
+ fprintf(fp, "CTYPE2 = '%s'\n", "DEC--TAN" );
+ fprintf(fp, "CRVAL1 = %11.6f\n", crval1 );
+ fprintf(fp, "CRVAL2 = %11.6f\n", crval2 );
+ fprintf(fp, "CRPIX1 = %11.6f\n", crpix1/shrinkFactor );
+ fprintf(fp, "CRPIX2 = %11.6f\n", crpix2/shrinkFactor );
+ fprintf(fp, "CDELT1 = %.9f\n", -cdelt*shrinkFactor );
+ fprintf(fp, "CDELT2 = %.9f\n", cdelt*shrinkFactor );
+ fprintf(fp, "CROTA2 = %11.6f\n", 0.0 );
+ fprintf(fp, "EQUINOX = %d\n", 2000 );
+
+ if(strcasecmp(survey, "2MASS") == 0)
+ {
+ if(strcasecmp(band, "J") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 20.9044);
+
+ else if(strcasecmp(band, "H") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 20.4871);
+
+ else if(strcasecmp(band, "K") == 0)
+ fprintf(fp, "MAGZP = %11.6f\n", 19.9757);
+ }
+
+ fprintf(fp, "END\n" );
+
+ fclose(fp);
+ }
+
+
+
+ /**************************************************************************/
+ /* If we are tiling the output mosaic: */
+ /* */
+ /* Create tiled header files, subset image tables, and list of shrunken */
+ /* images. */
+ /**************************************************************************/
+
+ if(!dax_mode)
+ {
+ sprintf(cmd, "%s/montage.makeflow", workdir);
+ fdag = fopen(cmd, "w+");
+ }
+
+ if(numTiles > 1)
+ {
+ sprintf(cmd, "%s/slist.tbl", workdir);
+
+ fp = fopen(cmd, "w+");
+
+ if(fp == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening image list\"]\n");
+ exit(0);
+ }
+
+ fprintf(fp, "| file |\n");
+ fprintf(fp, "| char |\n");
+
+ for(i=0; i\n");
+ fprintf(fdag, "\n", timestr);
+ fprintf(fdag, "\n\n");
+ fprintf(fdag, "\n\n");
+
+ fflush(fdag);
+
+ fprintf(fdag, " \n", survey);
+ fprintf(fdag, " \n", band);
+ fprintf(fdag, " \n", mosaicCenter);
+
+ if(haveHdr)
+ fprintf(fdag, " \n");
+ else
+ {
+ fprintf(fdag, " \n", mosaicWidth);
+ fprintf(fdag, " \n", mosaicHeight);
+ }
+
+ fprintf(fdag, "\n\n");
+ fflush(fdag);
+ }
+
+ /******************************************/
+ /* compose the url lfn cache list */
+ /******************************************/
+
+ sprintf(cmd, "%s/images.tbl", workdir);
+
+ ncol = topen(cmd);
+
+ ifname = tcol("file");
+ iurl = tcol("URL");
+
+ if(ifname < 0)
+ printError("'Raw' image list does not have column 'file'");
+
+ if(iurl < 0)
+ printError("'Raw' image list does not have column 'url'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ fprintf(furl, "%s %s pool=\"ipac_cluster\"\n", tval(ifname), tval(iurl));
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "%s:\n\twget %s -O %s.gz %s.gz ; gunzip -d %s.gz\n\n", tval(ifname), tval(iurl), tval(ifname), tval(ifname), tval(ifname));
+ }
+ }
+
+ tclose();
+ fclose(furl);
+
+
+ /******************************************/
+ /* DAG: "filename" lines for input images */
+ /******************************************/
+
+ if(dax_mode)
+ {
+ if(debug)
+ {
+ fprintf(fdebug, "Generating DAG file filename list ...\n");
+ fflush(fdebug);
+ }
+
+ fprintf(fdag, " \n\n");
+
+ sprintf(cmd, "%s/rimages.tbl", workdir);
+
+ ncol = topen(cmd);
+
+ ifname = tcol("file");
+
+ if(ifname < 0)
+ printError("'Raw' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ fprintf(fdag, " \n", tval(ifname));
+ }
+
+ fprintf(fdag, "\n");
+ fflush(fdag);
+ tclose();
+ }
+
+
+ /**********************************************/
+ /* DAG: "filename" lines for projected images */
+ /* including area files */
+ /**********************************************/
+
+ if(dax_mode)
+ {
+ sprintf(cmd, "%s/pimages.tbl", workdir);
+
+ ncol = topen(cmd);
+
+ ifname = tcol("file");
+
+ if(ifname < 0)
+ printError("'Projected' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ fprintf(fdag, " \n", tval(ifname));
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname)-5] = '\0';
+
+ strcat(fname, "_area.fits");
+
+ fprintf(fdag, " \n", fname);
+ }
+
+ fprintf(fdag, "\n");
+ fflush(fdag);
+ tclose();
+ }
+
+
+ /***********************************************/
+ /* DAG: "filename" lines for difference images */
+ /* and fit output files (plus one more file */
+ /* with a list of these fits) */
+ /***********************************************/
+
+ sprintf(cmd, "%s/diffs.tbl", workdir);
+
+ ncol = topen(cmd);
+ ifname = tcol("diff");
+ icntr1 = tcol("cntr1");
+ icntr2 = tcol("cntr2");
+
+ if(ifname < 0)
+ printError("'Diff' image list does not have column 'diff'");
+
+ sprintf(cmd, "%s/statfile.tbl", workdir);
+
+ ffit = fopen(cmd, "w+");
+
+ sprintf(fmt, "|%%7s|%%7s|%%22s|\n");
+ sprintf(dfmt, " %%7d %%7d %%22s \n");
+
+ fprintf(ffit, fmt, "cntr1", "cntr2", "stat");
+ fprintf(ffit, fmt, "int", "int", "char");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ cntr1 = atoi(tval(icntr1));
+ cntr2 = atoi(tval(icntr2));
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", tval(ifname));
+ }
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname)-5] = '\0';
+
+ sprintf(fitname, "fit%s.txt", fname+4);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n", fitname);
+ }
+
+ fprintf(ffit, dfmt, cntr1, cntr2, fitname);
+ }
+
+ fflush(fdag);
+ tclose();
+
+ fclose(ffit);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n");
+ fprintf(fdag, "\n");
+ fflush(fdag);
+ }
+
+ fprintf(fcache, "statfile_%s.tbl %s/%s/statfile.tbl pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+
+
+ /***********************************************/
+ /* DAG: "filename" lines for corrections table */
+ /* and the corrected image files (including */
+ /* area files) */
+ /***********************************************/
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n");
+ fprintf(fdag, "\n");
+ fflush(fdag);
+
+ sprintf(cmd, "%s/cimages.tbl", workdir);
+
+ ncol = topen(cmd);
+ ifname = tcol("file");
+
+ if(ifname < 0)
+ printError("'Corrected' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ fprintf(fdag, " \n", tval(ifname));
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname)-5] = '\0';
+
+ strcat(fname, "_area.fits");
+
+ fprintf(fdag, " \n", fname);
+ }
+
+ fprintf(fdag, "\n");
+ fflush(fdag);
+ tclose();
+ }
+
+
+ /***********************************************/
+ /* DAG: "filename" lines for template files, */
+ /* subset image files, output files, and */
+ /* shrunken output files. */
+ /***********************************************/
+
+ if(dax_mode)
+ {
+ if(numTiles > 1)
+ {
+ for(i=0; i\n", i, j, idstr);
+ fprintf(fdag, " \n", i, j, idstr);
+ fprintf(fdag, " \n", i, j);
+ fprintf(fdag, " \n", i, j, idstr);
+ fprintf(fdag, " \n", i, j, idstr);
+ fprintf(fdag, " \n", i, j, idstr);
+ fprintf(fdag, "\n");
+
+ fprintf(fcache, "region_%d_%d_%s.hdr %s/%s/region_%d_%d.hdr pool=\"ipac_cluster\"\n", i, j, idstr, workurlbase, workdir, i, j);
+ fprintf(fcache, "cimages_%d_%d_%s.tbl %s/%s/cimages_%d_%d.tbl pool=\"ipac_cluster\"\n", i, j, idstr, workurlbase, workdir, i, j);
+
+ }
+ }
+
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, "\n");
+ fflush(fdag);
+
+ fprintf(fcache, "slist_%s.tbl %s/%s/slist.tbl pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+ fflush(fdag);
+ fflush(fcache);
+ }
+ else
+ {
+ fprintf(fdag, " \n");
+ fprintf(fdag, "\n");
+ fflush(fdag);
+ }
+
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, "\n");
+
+ if(numTiles == 1)
+ {
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, "\n");
+ }
+ else
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, "\n\n");
+ fflush(fdag);
+
+ fprintf(fcache, "region_%s.hdr %s/%s/region.hdr pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+ fprintf(fcache, "big_region_%s.hdr %s/%s/big_region.hdr pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+
+ if(numTiles > 1)
+ {
+ fprintf(fcache, "shrunken_%s.hdr %s/%s/shrunken.hdr pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+ }
+
+ fprintf(fcache, "pimages_%s.tbl %s/%s/pimages.tbl pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+ fprintf(fcache, "cimages_%s.tbl %s/%s/cimages.tbl pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+ fflush(fcache);
+
+ /* to be saved in user's storage space */
+ fprintf(fcache, "dag_%s.xml %s/%s/dag.xml pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+ fprintf(fcache, "images_%s.tbl %s/%s/images.tbl pool=\"ipac_cluster\"\n", idstr, workurlbase, workdir);
+ }
+
+ /**************************************************/
+ /* DAG: "job" lines for mProject/mProjectPP jobs. */
+ /**************************************************/
+
+ if(debug)
+ {
+ fprintf(fdebug, "Generating DAG file job list ...\n");
+ fflush(fdebug);
+ }
+
+ id = 0;
+ level = 9;
+
+ if(numTiles > 1)
+ level = 12;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n");
+ }
+
+ cntr = 0;
+
+ sprintf(cmd, "%s/rimages.tbl", workdir);
+
+ ncol = topen(cmd);
+
+ ifname = tcol("file");
+ iscale = tcol("scale");
+
+ if(ifname < 0)
+ printError("'Raw' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ ++id;
+ ++cntr;
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname) - 5] = '\0';
+
+ if(dax_mode)
+ {
+ fprintf(fdag," \n", id, mproj, level, cntr);
+
+ if(iscale >= 0)
+ fprintf(fdag," \n -X\n -x %s\n \n \n \n \n\n", tval(iscale), fname, fname, idstr);
+ else
+ fprintf(fdag," \n -X\n \n \n \n \n\n", fname, fname, idstr);
+
+ fprintf(fdag," \n", fname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "%s.fits", fname);
+ HT_add_entry(depends, key, val);
+
+ if(haveurlbase)
+ {
+ if(dax_mode)
+ {
+ fprintf(fcache,"%s.fits %s/%s.fits pool=\"ipac_cluster\"\n",fname,urlbase,fname);
+ }
+ }
+
+ if(dax_mode)
+ {
+ fprintf(fdag," \n", fname);
+ }
+
+ sprintf(key, "p%s.fits", fname);
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag," \n", fname);
+
+ fprintf(fdag," \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "big_region.hdr");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag," \n\n\n");
+ }
+
+ if(!dax_mode)
+ {
+ if(iscale >= 0)
+ {
+ fprintf(fdag, "p%s.fits p%s_area.fits: %s.fits big_region.hdr ./%s\n\t./%s -X -x %s %s.fits p%s.fits big_region.hdr\n\n", fname, fname, fname, mproj, mproj, tval(iscale), fname, fname);
+ }
+ else
+ {
+ fprintf(fdag, "p%s.fits p%s_area.fits: %s.fits big_region.hdr ./%s\n\t./%s -X %s.fits p%s.fits big_region.hdr\n\n", fname, fname, fname, mproj, mproj, fname, fname);
+ }
+ }
+ }
+
+ tclose();
+ fflush(fcache);
+ fclose(fcache);
+
+
+
+ /***************************************/
+ /* DAG: "job" lines for mDiffFit jobs. */
+ /***************************************/
+
+ cntr = 0;
+
+ sprintf(cmd, "%s/diffs.tbl", workdir);
+
+ ncol = topen(cmd);
+
+ icntr1 = tcol("cntr1");
+ icntr2 = tcol("cntr2");
+ iplusname = tcol("plus");
+ iminusname = tcol("minus");
+
+ --level;
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ ++id;
+ ++cntr;
+
+ cntr1 = atoi(tval(icntr1));
+ cntr2 = atoi(tval(icntr2));
+
+ strcpy(plusname, tval(iplusname));
+ strcpy(minusname, tval(iminusname));
+
+ plusname [strlen(plusname) - 5] = '\0';
+ minusname[strlen(minusname) - 5] = '\0';
+
+ fname[strlen(fname) - 5] = '\0';
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level, cntr);
+
+ fprintf(fdag, " \n -s \n \n \n \n \n \n\n",
+ cntr1, cntr2, plusname, minusname, cntr1, cntr2, idstr);
+
+ fprintf(fdag, " \n");
+ fprintf(fdag, " \n");
+
+ fprintf(fdag, " \n",
+ cntr1, cntr2);
+ }
+
+ sprintf(key, "fit.%06d.%06d.txt", cntr1, cntr2);
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ plusname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "p%s.fits", plusname);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ plusname);
+
+ fprintf(fdag, " \n",
+ minusname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "p%s.fits", minusname);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ minusname);
+
+ fprintf(fdag, " \n", cntr1, cntr2);
+ }
+
+ sprintf(key, "diff.%06d.%06d.fits", cntr1, cntr2);
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "big_region.hdr");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "fit.%06d.%06d.txt diff.%06d.%06d.fits diff.%06d.%06d_area.fits: p%s.fits p%s_area.fits p%s.fits p%s_area.fits big_region.hdr ./mDiffFit\n\t./mDiffFit -s fit.%06d.%06d.txt p%s.fits p%s.fits diff.%06d.%06d.fits big_region.hdr\n\n", cntr1, cntr2, cntr1, cntr2, cntr1, cntr2, plusname, plusname, minusname, minusname, cntr1, cntr2, plusname, minusname, cntr1, cntr2);
+ }
+ }
+
+ tclose();
+
+
+
+ /****************************************/
+ /* DAG: "job" line for mConcatFit jobs. */
+ /****************************************/
+
+ ++id;
+
+ --level;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level);
+
+ fprintf(fdag, " \n \n \n .\n \n\n", idstr);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "statfile.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n");
+ }
+
+ sprintf(key, "fits.tbl");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ sprintf(cmd, "%s/diffs.tbl", workdir);
+
+ ncol = topen(cmd);
+ icntr1 = tcol("cntr1");
+ icntr2 = tcol("cntr2");
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "fits.tbl: ");
+ }
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ cntr1 = atoi(tval(icntr1));
+ cntr2 = atoi(tval(icntr2));
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ }
+ else
+ {
+ fprintf(fdag, "fit.%06d.%06d.txt ", cntr1, cntr2);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "fit.%06d.%06d.txt", cntr1, cntr2);
+ HT_add_entry(depends, key, val);
+ }
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, " ./mConcatFit\n\t./mConcatFit statfile.tbl fits.tbl .\n\n", path);
+ }
+ tclose();
+
+
+ /*************************************/
+ /* DAG: "job" line for mBgModel job. */
+ /*************************************/
+
+ ++id;
+
+ --level;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level);
+
+ fprintf(fdag, " \n -i 100000\n \n \n \n \n\n", idstr);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "pimages.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n");
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "fits.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n");
+ }
+
+ sprintf(key, "corrections.tbl");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, "corrections.tbl: pimages.tbl fits.tbl ./mBgModel\n\t./mBgModel -i 100000 pimages.tbl fits.tbl corrections.tbl\n\n", path);
+ }
+
+ /*****************************************/
+ /* DAG: "job" line for mBackground jobs. */
+ /*****************************************/
+
+ --level;
+
+ cntr = 0;
+
+ sprintf(cmd, "%s/rimages.tbl", workdir);
+
+ ncol = topen(cmd);
+ ifname = tcol("file");
+
+ if(ifname < 0)
+ printError("'Raw' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname) - 5] = '\0';
+
+ ++id;
+ ++cntr;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level, cntr);
+
+ fprintf(fdag, " \n -t\n \n \n \n \n \n\n",
+ fname, fname, idstr);
+
+ fprintf(fdag, " \n",
+ fname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "p%s.fits", fname);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", fname);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "pimages.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n");
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "corrections.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", fname);
+ }
+
+ sprintf(key, "c%s.fits", fname);
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ fname);
+
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, "c%s.fits c%s_area.fits: p%s.fits p%s_area.fits pimages.tbl corrections.tbl ./mBackground\n\t./mBackground -t p%s.fits c%s.fits pimages.tbl corrections.tbl\n\n", fname, fname, fname, fname, fname, fname);
+ }
+ }
+
+ fflush(fdag);
+
+
+
+ /**********************************************/
+ /* DAG: "job" lines for tile mImgtbl jobs. */
+ /* We have to regenerate the cimages table(s) */
+ /* because the pixel offsets and sizes need */
+ /* to be exactly right and the original is */
+ /* only an approximation. */
+ /**********************************************/
+
+ --level;
+
+ cntr = 0;
+
+ if(numTiles > 1)
+ {
+ for(i=0; i\n",
+ id, level, cntr);
+
+ fprintf(fdag, " \n .\n -t \n \n \n\n",
+ i, j, idstr, i, j);
+
+ fprintf(fdag, " \n",
+ i, j, idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "cimages_%d_%d.tbl", i, j);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", i, j);
+ }
+
+ sprintf(key, "newcimages_%d_%d.tbl",i,j);
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ sprintf(cmd, "%s/cimages_%d_%d.tbl", workdir, i, j);
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "newcimages_%d_%d.tbl: cimages.tbl ", i, j);
+ }
+
+ ncol = topen(cmd);
+ ifname = tcol("file");
+
+ if(ifname < 0)
+ printError("'Corrected' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname) - 5] = '\0';
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ fname);
+ }
+ else
+ {
+ fprintf(fdag, "%s.fits ", fname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "%s.fits", fname);
+ HT_add_entry(depends, key, val);
+ }
+
+ tclose();
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, " ./mImgtbl\n\t./mImgtbl . -t cimages.tbl newcimages_%d_%d.tbl\n\n", i, j);
+ }
+
+ fflush(fdag);
+ }
+ }
+ }
+ else
+ {
+ ++id;
+ ++cntr;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ id, level, cntr);
+
+ fprintf(fdag, " \n .\n -t \n \n \n\n", idstr);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "cimages.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n");
+ }
+
+ sprintf(key, "newcimages.tbl");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ sprintf(cmd, "%s/cimages.tbl", workdir);
+
+ ncol = topen(cmd);
+ ifname = tcol("file");
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "newcimages.tbl: cimages.tbl ");
+ }
+
+ if(ifname < 0)
+ printError("'Corrected' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname) - 5] = '\0';
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ fname);
+ }
+ else
+ {
+ fprintf(fdag, "%s.fits ", fname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "%s.fits", fname);
+ HT_add_entry(depends, key, val);
+ }
+
+ tclose();
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, " ./mImgtbl\n\t./mImgtbl . -t cimages.tbl newcimages.tbl\n\n", path);
+ }
+
+ fflush(fdag);
+ }
+
+
+
+ /*******************************************/
+ /* DAG: "job" lines for tile mAdd jobs. */
+ /*******************************************/
+
+ --level;
+
+ cntr = 0;
+
+ if(numTiles > 1)
+ {
+ for(i=0; i\n",
+ id, level, cntr);
+
+ fprintf(fdag, " \n -e\n \n \n \n \n\n",
+ i, j, i, j, idstr, i, j, idstr);
+
+ fprintf(fdag, " \n",
+ i, j);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "newcimages_%d_%d.tbl", i, j);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ i, j, idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "region_%d_%d.hdr", i, j);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ i, j, idstr);
+ }
+
+ sprintf(key, "tile_%d_%d.fits", i, j);
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ i, j, idstr);
+ }
+
+ sprintf(cmd, "%s/cimages_%d_%d.tbl", workdir, i, j);
+
+ ncol = topen(cmd);
+ ifname = tcol("file");
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "tile_%d_%d_%s.fits tile_%d_%d_%s_area.fits: newcimages_%d_%d.tbl region.hdr ", i, j, idstr, i, j, idstr, i, j);
+ }
+
+ if(ifname < 0)
+ printError("'Corrected' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname) - 5] = '\0';
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ fname);
+
+ fprintf(fdag, " \n",
+ fname);
+ }
+ else
+ {
+ fprintf(fdag, "%s.fits %s_area.fits ", fname, fname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "%s.fits", fname);
+ HT_add_entry(depends, key, val);
+ }
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, " ./mAdd\n\t./mAdd -e newcimages_%d_%d.tbl region.hdr tile_%d_%d_%s.fits\n\n", i, j, i, j, idstr);
+ }
+
+ fflush(fdag);
+ }
+ }
+ }
+ else
+ {
+ ++id;
+ ++cntr;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ id, level, cntr);
+
+ fprintf(fdag, " \n -e\n \n \n \n \n\n", idstr, idstr);
+
+ fprintf(fdag, " \n");
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "newcimages.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "region.hdr");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "mosaic.fits");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(cmd, "%s/cimages.tbl", workdir);
+
+ ncol = topen(cmd);
+ ifname = tcol("file");
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "mosaic_%s.fits mosaic_%s_area.fits: newcimages.tbl region.hdr ", idstr, idstr);
+ }
+
+ if(ifname < 0)
+ printError("'Corrected' image list does not have column 'file'");
+
+ while(1)
+ {
+ istat = tread();
+
+ if(istat < 0)
+ break;
+
+ strcpy(fname, tval(ifname));
+
+ fname[strlen(fname) - 5] = '\0';
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ fname);
+
+ fprintf(fdag, " \n",
+ fname);
+ }
+ else
+ {
+ fprintf(fdag, "%s.fits %s_area.fits ", fname, fname);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "%s.fits", fname);
+ HT_add_entry(depends, key, val);
+
+ }
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, " ./mAdd\n\t./mAdd -e newcimages.tbl region.hdr mosaic_%s.fits\n\n", idstr);
+ }
+
+ fflush(fdag);
+ }
+
+ mAddCntr = cntr;
+
+
+
+ /*******************************************/
+ /* DAG: "job" lines for tile mShrink jobs. */
+ /*******************************************/
+
+ --level;
+
+ cntr = 0;
+
+ if(numTiles > 1)
+ {
+ for(i=0; i\n", id, level, cntr);
+
+ fprintf(fdag, " \n \n \n %d\n \n\n",
+ i, j, idstr, i, j, idstr, shrinkFactor);
+
+ fprintf(fdag, " \n",
+ i, j, idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "tile_%d_%d.fits", i, j);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n",
+ i, j, idstr);
+ }
+
+ sprintf(key, "shrunken_%d_%d.fits", i, j);
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, "shrunken_%d_%d_%s.fits: tile_%d_%d_%s.fits ./mShrink\n\t./mShrink tile_%d_%d_%s.fits shrunken_%d_%d_%s.fits %d\n\n",
+ i, j, idstr, i, j, idstr, i, j, idstr, i, j, idstr, shrinkFactor);
+ }
+
+ }
+ }
+ }
+ else
+ {
+ ++id;
+ ++cntr;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level, cntr);
+
+ fprintf(fdag, " \n \n \n %d\n \n\n", idstr, idstr, shrinkFactor);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "mosaic.fits");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "shrunken.fits");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, "shrunken_%s.fits: mosaic_%s.fits ./mShrink\n\t./mShrink mosaic_%s.fits shrunken_%s.fits %d\n\n", idstr, idstr, idstr, idstr, shrinkFactor);
+ }
+ }
+
+ fflush(fdag);
+
+
+
+ /*******************************************/
+ /* DAG: If there are tiles, we need to */
+ /* do a final coadd of the shrunken tile */
+ /* images to make a full area shrunken */
+ /* mosaic. */
+ /*******************************************/
+
+ if(numTiles > 1)
+ {
+ /***********/
+ /* mImgTbl */
+ /***********/
+
+ ++id;
+
+ --level;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level);
+
+ fprintf(fdag, " \n .\n -t \n \n \n\n", idstr, idstr);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "slist.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "simages.tbl");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(!dax_mode)
+ {
+ fprintf(fdag, "simages_%s.tbl: slist_%s.tbl ", idstr, idstr);
+ }
+
+ for(i=0; i\n",
+ i, j, idstr);
+ }
+ else
+ {
+ fprintf(fdag, "shrunken_%d_%d_%s.fits ", i, j, idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "shrunken_%d_%d.fits", i, j);
+ HT_add_entry(depends, key, val);
+ }
+ }
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, " ./mImgtbl\n\t./mImgtbl . -t slist_%s.tbl simages_%s.tbl\n\n", idstr, idstr);
+ }
+
+ fflush(fdag);
+
+
+ /********/
+ /* mAdd */
+ /********/
+
+ ++id;
+
+ --level;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level, mAddCntr+1);
+
+ fprintf(fdag, " \n -n\n -e\n \n \n \n \n\n", idstr, idstr, idstr);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "simages.tbl");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "shrunken.hdr");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "shrunken.fits");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(!dax_mode) {
+ fprintf(fdag, "shrunken_%s.fits: simages_%s.tbl shrunken_%s.hdr ", idstr, idstr, idstr);
+ }
+
+ for(i=0; i\n",
+ i, j, idstr);
+ }
+ else
+ {
+ fprintf(fdag, "shrunken_%d_%d_%s.fits ", i, j, idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "shrunken_%d_%d.fits", i, j);
+ HT_add_entry(depends, key, val);
+ }
+ }
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, " ./mAdd\n\t./mAdd -n -e simages_%s.tbl shrunken_%s.hdr shrunken_%s.fits\n\n", idstr, idstr, idstr);
+ }
+
+ }
+
+ fflush(fdag);
+
+
+
+ /****************************/
+ /* DAG: Make the final JPEG */
+ /****************************/
+
+ ++id;
+
+ --level;
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", id, level);
+
+ fprintf(fdag, " \n -ct 1\n -gray \n min max gaussianlog\n -out \n \n\n", idstr, idstr);
+
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "ID%06d", id);
+ sprintf(val, "shrunken.fits");
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "shrunken.jpg");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "dag.xml");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n", idstr);
+ fprintf(fdag, " \n", idstr);
+ }
+
+ sprintf(key, "images.tbl");
+ sprintf(val, "ID%06d", id);
+ HT_add_entry(depends, key, val);
+
+ if(dax_mode)
+ {
+ fprintf(fdag, " \n\n\n\n");
+ }
+ else
+ {
+ fprintf(fdag, "shrunken_%s.jpg: shrunken_%s.fits ./mJPEG\n\t./mJPEG -ct 1 -gray shrunken_%s.fits min max gaussianlog -out shrunken_%s.jpg\n\n",
+ idstr, idstr, idstr, idstr);
+ }
+
+ fflush(fdag);
+
+
+
+ /*******************************************/
+ /* DAG: Flow control dependencies. */
+ /* First, mDiffs depend on mProjects */
+ /*******************************************/
+
+ if(dax_mode)
+ {
+ if(debug)
+ {
+ fprintf(fdebug, "Generating DAG file parent/child info ...\n");
+ fflush(fdebug);
+ }
+
+ fprintf(fdag, " \n\n");
+
+ sprintf(fileList, "%s/files.lis", workdir);
+ sprintf(parentList, "%s/parents.lis", workdir);
+ sprintf(sortedParent, "%s/sortedParents.lis", workdir);
+
+ for(i=1; i<=id; ++i)
+ {
+ sprintf(jobid, "ID%06d", i);
+
+ fileid = HT_lookup_key(depends, jobid);
+
+ ffile = fopen(fileList, "w+");
+
+ if(ffile == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening working file list for write\"]\n");
+ exit(0);
+ }
+
+ while(fileid != (char *)NULL)
+ {
+ fprintf(ffile, "%s\n", fileid);
+ fflush(ffile);
+
+ fileid = HT_next_entry(depends);
+ }
+
+ fclose(ffile);
+
+ ffile = fopen(fileList, "r");
+
+ if(ffile == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening working file list for read\"]\n");
+ exit(0);
+ }
+
+ fparent = fopen(parentList, "w+");
+
+ if(fparent == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening parent list\"]\n");
+ exit(0);
+ }
+
+ nparents = 0;
+
+ fprintf(fparent, "| parent |\n");
+
+ while(1)
+ {
+ if(fgets(line, MAXSTR, ffile) == (char *)NULL)
+ break;
+
+ if(line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = '\0';
+
+ parentid = HT_lookup_key(depends, line);
+
+ while(parentid != (char *)NULL)
+ {
+ parent = atoi(parentid+2);
+
+ fprintf(fparent, " %12d\n", parent);
+ fflush(fparent);
+
+ ++nparents;
+
+ parentid = HT_next_entry(depends);
+ }
+ }
+
+ fclose(ffile);
+ fclose(fparent);
+
+ unlink(fileList);
+
+ if(nparents > 0)
+ {
+
+ if(path)
+ sprintf(cmd, "%s/bin/mTblSort %s parent %s", path, parentList, sortedParent);
+ else
+ sprintf(cmd, "mTblSort %s parent %s", parentList, sortedParent);
+
+ svc_run(cmd);
+
+ strcpy( status, svc_value( "stat" ));
+
+ if (strcmp( status, "ERROR") == 0)
+ {
+ strcpy( msg, svc_value( "msg" ));
+
+ printError(msg);
+ }
+
+ unlink(parentList);
+
+ fparent = fopen(sortedParent, "r");
+
+ if(fparent == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Error opening sorted parent list\"]\n");
+ exit(0);
+ }
+
+ fgets(line, MAXSTR, fparent);
+
+ fprintf(fdag, " \n", jobid);
+
+ for(j=0; j 0 && parent == parent_prev)
+ continue;
+
+ fprintf(fdag, " \n", parent);
+ }
+
+ fprintf(fdag, " \n\n");
+ fflush(fdag);
+
+ fclose(fparent);
+ }
+ unlink(sortedParent);
+ }
+
+ fprintf(fdag, "\n");
+ fflush(fdag);
+ fclose(fdag);
+
+ if(debug)
+ {
+ fprintf(fdebug, "done.\n");
+ fflush(fdebug);
+ }
+ }
+
+ printf("[struct stat=\"OK\", id=\"%s\"]\n", idstr);
+ exit(0);
+}
+
+
+
+
+
+
+/**************************************************/
+/* */
+/* Read the output header template file. */
+/* Specifically extract the image size info. */
+/* Also, create a single-string version of the */
+/* header data and use it to initialize the */
+/* output WCS transform. */
+/* */
+/**************************************************/
+
+int readTemplate(char *template)
+{
+ int j;
+ FILE *fp;
+ char line[MAXSTR];
+ char header[80000];
+
+ fp = fopen(template, "r");
+
+ if(fp == (FILE *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Bad template: %s\"]\n",
+ template);
+ fflush(stdout);
+ exit(1);
+ }
+
+ strcpy(header, "");
+
+ if(debug)
+ {
+ fprintf(fdebug, "\nTemplate Header (%s):\n",
+ template);
+ fflush(fdebug);
+ }
+
+ for(j=0; j<1000; ++j)
+ {
+ if(fgets(line, MAXSTR, fp) == (char *)NULL)
+ break;
+
+ if(line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = '\0';
+
+ if(line[strlen(line)-1] == '\r')
+ line[strlen(line)-1] = '\0';
+
+ stradd(header, line);
+
+ if(debug)
+ {
+ fprintf(fdebug, "%s\n", line);
+ fflush(fdebug);
+ }
+ }
+
+ if(debug)
+ {
+ fprintf(fdebug, "\n");
+ fflush(fdebug);
+ }
+
+
+ wcs = wcsinit(header);
+
+ if(wcs == (struct WorldCoor *)NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Output wcsinit() failed.\"]\n");
+ fflush(stdout);
+ exit(1);
+ }
+
+ naxis1 = wcs->nxpix;
+ naxis2 = wcs->nypix;
+
+ if(wcs->syswcs == WCS_J2000)
+ {
+ sys = EQUJ;
+ epoch = 2000.;
+
+ if(wcs->equinox == 1950.)
+ epoch = 1950;
+ }
+ else if(wcs->syswcs == WCS_B1950)
+ {
+ sys = EQUB;
+ epoch = 1950.;
+
+ if(wcs->equinox == 2000.)
+ epoch = 2000;
+ }
+ else if(wcs->syswcs == WCS_GALACTIC)
+ {
+ sys = GAL;
+ epoch = 2000.;
+ }
+ else if(wcs->syswcs == WCS_ECLIPTIC)
+ {
+ sys = ECLJ;
+ epoch = 2000.;
+
+ if(wcs->equinox == 1950.)
+ {
+ sys = ECLB;
+ epoch = 1950.;
+ }
+ }
+ else
+ {
+ sys = EQUJ;
+ epoch = 2000.;
+ }
+
+
+ if(debug)
+ {
+ fprintf(fdebug, "DEBUG> Template WCS initialized\n\n");
+ fflush(fdebug);
+ }
+
+ fclose(fp);
+
+ return(0);
+}
+
+
+
+int stradd(char *header, char *card)
+{
+ int i, hlen, clen;
+
+ hlen = strlen(header);
+ clen = strlen(card);
+
+ for(i=0; i ", mosaicCenter);
+ fflush(fdebug);
+ }
+
+ send(socket, request, strlen(request), 0);
+
+
+ /* Read the data coming back */
+
+ count = 0;
+ j = 0;
+
+ while(1)
+ {
+ for(i=0; i' && ptr < endPtr)
+ ++ptr;
+
+ if(ptr >= endPtr)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Can't find RA in lookup return.\"]\n");
+ fflush(stdout);
+ exit(1);
+ }
+
+ ++ptr;
+
+ *ra = atof(ptr);
+
+
+ /* Find the Dec */
+
+ ptr = strstr(result, "\"lat\"");
+
+ if(!ptr)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Can't find Dec in lookup return.\"]\n");
+ fflush(stdout);
+ exit(1);
+ }
+
+ while(*ptr != '>' && ptr < endPtr)
+ ++ptr;
+
+ if(ptr >= endPtr)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Can't find Dec in lookup return.\"]\n");
+ fflush(stdout);
+ exit(1);
+ }
+
+ ++ptr;
+
+ *dec = atof(ptr);
+
+ if(debug)
+ {
+ fprintf(fdebug, " (%.6f,%.6f)\n\n", *ra, *dec);
+ fflush(fdebug);
+ }
+
+ return(0);
+}
+
+
+
+
+/***********************************************/
+/* This is the basic "make a connection" stuff */
+/***********************************************/
+
+int tcp_connect(char *hostname, int port)
+{
+ int sock_fd;
+ struct hostent *host;
+ struct sockaddr_in sin;
+
+
+ if((host = gethostbyname(hostname)) == NULL)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Couldn't find host %s\"]\n", hostname);
+ fflush(stdout);
+ return(0);
+ }
+
+ if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"Couldn't create socket()\"]\n");
+ fflush(stdout);
+ return(0);
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+
+ bcopy(host->h_addr_list[0], &sin.sin_addr, host->h_length);
+ //bcopy(host->h_addr, &sin.sin_addr, host->h_length);
+
+ if(connect(sock_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ {
+ printf("[struct stat=\"ERROR\", msg=\"%s: connect failed.\"]\n", hostname);
+ fflush(stdout);
+ return(0);
+ }
+
+ return sock_fd;
+}
+
+
+
+/**************************************/
+/* This routine URL-encodes a string */
+/**************************************/
+
+static unsigned char hexchars[] = "0123456789ABCDEF";
+
+char *url_encode(char *s)
+{
+ int len;
+ register int i, j;
+ unsigned char *str;
+
+ len = strlen(s);
+
+ str = (unsigned char *) malloc(3 * strlen(s) + 1);
+
+ j = 0;
+
+ for (i=0; i '9') ||
+ (str[j] > 'Z' && str[j] < 'a' && str[j] != '_') ||
+ (str[j] > 'z'))
+ {
+ str[j++] = '%';
+
+ str[j++] = hexchars[(unsigned char) s[i] >> 4];
+
+ str[j] = hexchars[(unsigned char) s[i] & 15];
+ }
+
+ ++j;
+ }
+
+ str[j] = '\0';
+
+ return ((char *) str);
+}
+
+
+/* vim: set noexpandtab tabstop=3: */
diff --git a/montage/montage.png b/montage/montage.png
new file mode 100644
index 0000000..a240c2f
Binary files /dev/null and b/montage/montage.png differ