/* gnuPlot2D.c was originally generated by the autoSql program, which also 
 * generated gnuPlot2D.h and gnuPlot2D.sql.  This module links the database and
 * the RAM representation of objects. */

/* Copyright (C) 2005 The Regents of the University of California 
 * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */

#include "common.h"
#include "linefile.h"
#include "jksql.h"
#include "hash.h"
#include "portable.h"
#include "gnuPlot2D.h"


static char *gptEmptyField = "_NOT_SET_";

void graphPoint2DStaticLoad(char **row, struct graphPoint2D *ret)
/* Load a row from graphPoint2D table into ret.  The contents of ret will
 * be replaced at the next call to this function. */
{
ret->x = atof(row[0]);
ret->y = atof(row[1]);
ret->xDelta = atof(row[2]);
ret->yDelta = atof(row[3]);
ret->name = row[4];
ret->hName = row[5];
ret->groupName = row[6];
ret->other = row[7];
}

struct graphPoint2D *graphPoint2DLoad(char **row)
/* Load a graphPoint2D from row fetched with select * from graphPoint2D
 * from database.  Dispose of this with graphPoint2DFree(). */
{
struct graphPoint2D *ret;

AllocVar(ret);
ret->x = atof(row[0]);
ret->y = atof(row[1]);
ret->xDelta = atof(row[2]);
ret->yDelta = atof(row[3]);
ret->name = cloneString(row[4]);
ret->hName = cloneString(row[5]);
ret->groupName = cloneString(row[6]);
ret->other = cloneString(row[7]);
return ret;
}

struct graphPoint2D *graphPoint2DLoadAll(char *fileName) 
/* Load all graphPoint2D from a tab-separated file.
 * Dispose of this with graphPoint2DFreeList(). */
{
struct graphPoint2D *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[8];

while (lineFileRow(lf, row))
    {
    el = graphPoint2DLoad(row);
    slAddHead(&list, el);
    }
lineFileClose(&lf);
slReverse(&list);
return list;
}

struct graphPoint2D *graphPoint2DCommaIn(char **pS, struct graphPoint2D *ret)
/* Create a graphPoint2D out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new graphPoint2D */
{
char *s = *pS;

if (ret == NULL)
    AllocVar(ret);
ret->x = sqlSignedComma(&s);
ret->y = sqlSignedComma(&s);
ret->xDelta = sqlSignedComma(&s);
ret->yDelta = sqlSignedComma(&s);
ret->name = sqlStringComma(&s);
ret->hName = sqlStringComma(&s);
ret->groupName = sqlStringComma(&s);
ret->other = sqlStringComma(&s);
*pS = s;
return ret;
}

void graphPoint2DFree(struct graphPoint2D **pEl)
/* Free a single dynamically allocated graphPoint2D such as created
 * with graphPoint2DLoad(). */
{
struct graphPoint2D *el;

if ((el = *pEl) == NULL) return;
freeMem(el->name);
freeMem(el->hName);
freeMem(el->groupName);
freeMem(el->other);
freez(pEl);
}

void graphPoint2DFreeList(struct graphPoint2D **pList)
/* Free a list of dynamically allocated graphPoint2D's */
{
struct graphPoint2D *el, *next;

for (el = *pList; el != NULL; el = next)
    {
    next = el->next;
    graphPoint2DFree(&el);
    }
*pList = NULL;
}

void graphPoint2DOutput(struct graphPoint2D *el, FILE *f, char sep, char lastSep) 
/* Print out graphPoint2D.  Separate fields with sep. Follow last field with lastSep. */
{
fprintf(f, "%f", el->x);
fputc(sep,f);
fprintf(f, "%f", el->y);
fputc(sep,f);
fprintf(f, "%f", el->xDelta);
fputc(sep,f);
fprintf(f, "%f", el->yDelta);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->name);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->hName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->groupName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->other);
if (sep == ',') fputc('"',f);
fputc(lastSep,f);
}

/*
struct gnuPlot2D *gnuPlot2DLoad(char **row)
* Load a gnuPlot2D from row fetched with select * from gnuPlot2D
 * from database.  Dispose of this with gnuPlot2DFree(). *
{
struct gnuPlot2D *ret;
int sizeOne,i;
char *s;

AllocVar(ret);
ret->numPlots = sqlSigned(row[0]);
ret->numFiles = sqlSigned(row[1]);
ret->numFunctions = sqlSigned(row[9]);
s = row[2];
for (i=0; i<ret->numPlots; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->gpList, graphPoint2DCommaIn(&s, NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->gpList);
ret->fileName = cloneString(row[3]);
ret->directory = cloneString(row[4]);
sqlStringDynamicArray(row[5], &ret->tempFiles, &sizeOne);
assert(sizeOne == ret->numFiles);
ret->imageFormat = cloneString(row[6]);
sqlStringDynamicArray(row[7], &ret->styles, &sizeOne);
assert(sizeOne == ret->numPlots);
ret->functions = sqlSigned(row[8]);
sqlStringDynamicArray(row[10], &ret->functionStyles, &sizeOne);
assert(sizeOne == ret->numFunctions);
ret->grid = sqlSigned(row[11]);
ret->xtics = sqlSigned(row[12]);
ret->ytics = sqlSigned(row[13]);
ret->xTicFormat = cloneString(row[14]);
ret->yTicFormat = cloneString(row[15]);
ret->xDataLabels = sqlSigned(row[16]);
ret->yDataLabels = sqlSigned(row[17]);
ret->xlogAxis = sqlSigned(row[18]);
ret->ylogAxis = sqlSigned(row[19]);
ret->yMin = atof(row[20]);
ret->yMax = atof(row[21]);
ret->xMin = atof(row[22]);
ret->xMax = atof(row[23]);
ret->title = cloneString(row[24]);
ret->xlabel = cloneString(row[25]);
ret->ylabel = cloneString(row[26]);
ret->legend = cloneString(row[27]);
ret->other = cloneString(row[28]);
return ret;
}
*/
struct gnuPlot2D *gnuPlot2DLoad(char **row)
/* Load a gnuPlot2D from row fetched with select * from gnuPlot2D
 * from database.  Dispose of this with gnuPlot2DFree(). */
{
struct gnuPlot2D *ret;
int sizeOne,i;
char *s;

AllocVar(ret);
ret->numPlots = sqlSigned(row[0]);
ret->numFiles = sqlSigned(row[1]);
ret->numFunctions = sqlSigned(row[10]);
ret->maxPlots = sqlSigned(row[2]);
ret->maxFunctions = sqlSigned(row[3]);
s = row[4];
for (i=0; i<ret->numPlots; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->gpList, graphPoint2DCommaIn(&s, NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->gpList);
ret->fileName = cloneString(row[5]);
ret->directory = cloneString(row[6]);
sqlStringDynamicArray(row[7], &ret->tempFiles, &sizeOne);
assert(sizeOne == ret->numFiles);
ret->imageFormat = cloneString(row[8]);
sqlStringDynamicArray(row[9], &ret->styles, &sizeOne);
assert(sizeOne == ret->numPlots);
sqlStringDynamicArray(row[11], &ret->functions, &sizeOne);
assert(sizeOne == ret->numFunctions);
sqlStringDynamicArray(row[12], &ret->functionStyles, &sizeOne);
assert(sizeOne == ret->numFunctions);
ret->grid = sqlSigned(row[13]);
ret->xtics = sqlSigned(row[14]);
ret->ytics = sqlSigned(row[15]);
ret->xTicFormat = cloneString(row[16]);
ret->yTicFormat = cloneString(row[17]);
ret->xErrorBars = sqlSigned(row[18]);
ret->yErrorBars = sqlSigned(row[19]);
ret->xDataLabels = sqlSigned(row[20]);
ret->yDataLabels = sqlSigned(row[21]);
ret->xlogAxis = sqlSigned(row[22]);
ret->ylogAxis = sqlSigned(row[23]);
ret->yMin = atof(row[24]);
ret->yMax = atof(row[25]);
ret->xMin = atof(row[26]);
ret->yMax = atof(row[27]);
ret->title = cloneString(row[28]);
ret->xlabel = cloneString(row[29]);
ret->ylabel = cloneString(row[30]);
ret->legend = cloneString(row[31]);
ret->other = cloneString(row[32]);
return ret;
}

struct gnuPlot2D *gnuPlot2DLoadAll(char *fileName) 
/* Load all gnuPlot2D from a tab-separated file.
 * Dispose of this with gnuPlot2DFreeList(). */
{
struct gnuPlot2D *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[29];

while (lineFileRow(lf, row))
    {
    el = gnuPlot2DLoad(row);
    slAddHead(&list, el);
    }
lineFileClose(&lf);
slReverse(&list);
return list;
}

struct gnuPlot2D *gnuPlot2DCommaIn(char **pS, struct gnuPlot2D *ret)
/* Create a gnuPlot2D out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new gnuPlot2D */
{
char *s = *pS;
int i;

if (ret == NULL)
    AllocVar(ret);
ret->numPlots = sqlSignedComma(&s);
ret->numFiles = sqlSignedComma(&s);
ret->maxPlots = sqlSignedComma(&s);
ret->maxFunctions = sqlSignedComma(&s);
s = sqlEatChar(s, '{');
for (i=0; i<ret->numPlots; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->gpList, graphPoint2DCommaIn(&s,NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->gpList);
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->fileName = sqlStringComma(&s);
ret->directory = sqlStringComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->tempFiles, ret->numFiles);
for (i=0; i<ret->numFiles; ++i)
    {
    ret->tempFiles[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->imageFormat = sqlStringComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->styles, ret->numPlots);
for (i=0; i<ret->numPlots; ++i)
    {
    ret->styles[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->numFunctions = sqlSignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->functions, ret->numFunctions);
for (i=0; i<ret->numFunctions; ++i)
    {
    ret->functions[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
s = sqlEatChar(s, '{');
AllocArray(ret->functionStyles, ret->numFunctions);
for (i=0; i<ret->numFunctions; ++i)
    {
    ret->functionStyles[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->grid = sqlSignedComma(&s);
ret->xtics = sqlSignedComma(&s);
ret->ytics = sqlSignedComma(&s);
ret->xTicFormat = sqlStringComma(&s);
ret->yTicFormat = sqlStringComma(&s);
ret->xErrorBars = sqlSignedComma(&s);
ret->yErrorBars = sqlSignedComma(&s);
ret->xDataLabels = sqlSignedComma(&s);
ret->yDataLabels = sqlSignedComma(&s);
ret->xlogAxis = sqlSignedComma(&s);
ret->ylogAxis = sqlSignedComma(&s);
ret->yMin = sqlSignedComma(&s);
ret->yMax = sqlSignedComma(&s);
ret->xMin = sqlSignedComma(&s);
ret->yMax = sqlSignedComma(&s);
ret->title = sqlStringComma(&s);
ret->xlabel = sqlStringComma(&s);
ret->ylabel = sqlStringComma(&s);
ret->legend = sqlStringComma(&s);
ret->other = sqlStringComma(&s);
*pS = s;
return ret;
}

#ifdef NOT
struct gnuPlot2D *gnuPlot2DCommaIn(char **pS, struct gnuPlot2D *ret)
/* Create a gnuPlot2D out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new gnuPlot2D */
{
char *s = *pS;
int i;

if (ret == NULL)
    AllocVar(ret);
ret->numPlots = sqlSignedComma(&s);
ret->numFiles = sqlSignedComma(&s);
s = sqlEatChar(s, '{');
for (i=0; i<ret->numPlots; ++i)
    {
    s = sqlEatChar(s, '{');
    slSafeAddHead(&ret->gpList[i], graphPoint2DCommaIn(&s,NULL));
    s = sqlEatChar(s, '}');
    s = sqlEatChar(s, ',');
    }
slReverse(&ret->gpList);
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->fileName = sqlStringComma(&s);
ret->directory = sqlStringComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->tempFiles, ret->numFiles);
for (i=0; i<ret->numFiles; ++i)
    {
    ret->tempFiles[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->imageFormat = sqlStringComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->styles, ret->numPlots);
for (i=0; i<ret->numPlots; ++i)
    {
    ret->styles[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->functions = sqlSignedComma(&s);
ret->numFunctions = sqlSignedComma(&s);
s = sqlEatChar(s, '{');
AllocArray(ret->functionStyles, ret->numFunctions);
for (i=0; i<ret->numFunctions; ++i)
    {
    ret->functionStyles[i] = sqlStringComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
ret->grid = sqlSignedComma(&s);
ret->xtics = sqlSignedComma(&s);
ret->ytics = sqlSignedComma(&s);
ret->xTicFormat = sqlStringComma(&s);
ret->yTicFormat = sqlStringComma(&s);
ret->xDataLabels = sqlSignedComma(&s);
ret->yDataLabels = sqlSignedComma(&s);
ret->xlogAxis = sqlSignedComma(&s);
ret->ylogAxis = sqlSignedComma(&s);
ret->yMin = sqlSignedComma(&s);
ret->yMax = sqlSignedComma(&s);
ret->xMin = sqlSignedComma(&s);
ret->xMax = sqlSignedComma(&s);
ret->title = sqlStringComma(&s);
ret->xlabel = sqlStringComma(&s);
ret->ylabel = sqlStringComma(&s);
ret->legend = sqlStringComma(&s);
ret->other = sqlStringComma(&s);
*pS = s;
return ret;
} 
#endif	/*	NOT	*/

void gnuPlot2DFree(struct gnuPlot2D **pEl)
/* Free a single dynamically allocated gnuPlot2D such as created
 * with gnuPlot2DLoad(). */
{
struct gnuPlot2D *el;
int i;
if ((el = *pEl) == NULL) return;
for(i=0;i<el->numPlots;i++)
    {
    graphPoint2DFreeList(&el->gpList[i]);
    }
freeMem(el->fileName);
freeMem(el->directory);
/* All strings in tempFiles are allocated at once, so only need to free first. */
freeMem(el->tempFiles[0]);
freeMem(el->tempFiles);
freeMem(el->imageFormat);
/* All strings in styles are allocated at once, so only need to free first. */
freeMem(el->styles[0]);
freeMem(el->styles);
/* All strings in functionStyles are allocated at once, so only need to free first. */
freeMem(el->functionStyles[0]);
freeMem(el->functionStyles);
freeMem(el->xTicFormat);
freeMem(el->yTicFormat);
freeMem(el->title);
freeMem(el->xlabel);
freeMem(el->ylabel);
freeMem(el->legend);
freeMem(el->other);
freez(pEl);
}

void gnuPlot2DFreeList(struct gnuPlot2D **pList)
/* Free a list of dynamically allocated gnuPlot2D's */
{
struct gnuPlot2D *el, *next;

for (el = *pList; el != NULL; el = next)
    {
    next = el->next;
    gnuPlot2DFree(&el);
    }
*pList = NULL;
}

void gnuPlot2DOutput(struct gnuPlot2D *el, FILE *f, char sep, char lastSep) 
/* Print out gnuPlot2D.  Separate fields with sep. Follow last field with lastSep. */
{
int i;
fprintf(f, "%d", el->numPlots);
fputc(sep,f);
fprintf(f, "%d", el->numFiles);
fputc(sep,f);
fprintf(f, "%d", el->maxPlots);
fputc(sep,f);
fprintf(f, "%d", el->maxFunctions);
fputc(sep,f);
/* Loading graphPoint2D list. */
el->gpList = needMem(sizeof(struct graphPoint2D **) *el->maxPlots);
for(i=0;i<el->numPlots; i++)
    {
    struct graphPoint2D *it = el->gpList[i];
    if (sep == ',') fputc('{',f);
    for (i=0; i<el->numPlots; ++i)
        {
        fputc('{',f);
        graphPoint2DCommaOut(it,f);
        it = it->next;
        fputc('}',f);
        fputc(',',f);
        }
    if (sep == ',') fputc('}',f);
    }
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->fileName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->directory);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->numFiles; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->tempFiles[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->imageFormat);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->numPlots; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->styles[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%d", el->numFunctions);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->numFunctions; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->functions[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->numFunctions; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->functionStyles[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%d", el->grid);
fputc(sep,f);
fprintf(f, "%d", el->xtics);
fputc(sep,f);
fprintf(f, "%d", el->ytics);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->xTicFormat);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->yTicFormat);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%d", el->xErrorBars);
fputc(sep,f);
fprintf(f, "%d", el->yErrorBars);
fputc(sep,f);
fprintf(f, "%d", el->xDataLabels);
fputc(sep,f);
fprintf(f, "%d", el->yDataLabels);
fputc(sep,f);
fprintf(f, "%d", el->xlogAxis);
fputc(sep,f);
fprintf(f, "%d", el->ylogAxis);
fputc(sep,f);
fprintf(f, "%f", el->yMin);
fputc(sep,f);
fprintf(f, "%f", el->yMax);
fputc(sep,f);
fprintf(f, "%f", el->xMin);
fputc(sep,f);
fprintf(f, "%f", el->yMax);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->title);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->xlabel);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->ylabel);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->legend);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->other);
if (sep == ',') fputc('"',f);
fputc(lastSep,f);
}

/*

void gnuPlot2DOutput(struct gnuPlot2D *el, FILE *f, char sep, char lastSep) 
* Print out gnuPlot2D.  Separate fields with sep. Follow last field with lastSep. *
{
int i;
fprintf(f, "%d", el->numPlots, sep);
fputc(sep,f);
fprintf(f, "%d", el->numFiles, sep);
fputc(sep,f);
fprintf(f, "%d", el->maxPlots, sep);
fputc(sep,f);
fprintf(f, "%d", el->maxFunctions, sep);
fputc(sep,f);
* Loading graphPoint2D list. *
    {
    for(i=0;i<el->numPlots; i++)
	{
	struct graphPoint2D *it = el->gpList[i];
	if (sep == ',') fputc('{',f);
	for (; it!=NULL; it=it->next)
	    {
	    fputc('{',f);
	    graphPoint2DCommaOut(it,f);
	    it = it->next;
	    fputc('}',f);
	    fputc(',',f);
	    }
	if (sep == ',') fputc('}',f);
	}
    }
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->fileName, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->directory, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->numFiles; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->tempFiles[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->imageFormat, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->numPlots; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->styles[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
for (i=0; i<el->numFunctions; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->functions[i], sep);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
fputc(sep,f);
fprintf(f, "%d", el->numFunctions, sep);
fputc(sep,f);
if (sep == ',') fputc('{',f);
for (i=0; i<el->numFunctions; ++i)
    {
    if (sep == ',') fputc('"',f);
    fprintf(f, "%s", el->functionStyles[i]);
    if (sep == ',') fputc('"',f);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
fputc(sep,f);
fprintf(f, "%d", el->grid, sep);
fputc(sep,f);
fprintf(f, "%d", el->xtics, sep);
fputc(sep,f);
fprintf(f, "%d", el->ytics, sep);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->xTicFormat, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->yTicFormat, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%d", el->xDataLabels, sep);
fputc(sep,f);
fprintf(f, "%d", el->yDataLabels, sep);
fputc(sep,f);
fprintf(f, "%d", el->xlogAxis, sep);
fputc(sep,f);
fprintf(f, "%d", el->ylogAxis, sep);
fputc(sep,f);
fprintf(f, "%f", el->yMin, sep);
fputc(sep,f);
fprintf(f, "%f", el->yMax, sep);
fputc(sep,f);
fprintf(f, "%f", el->xMin, sep);
fputc(sep,f);
fprintf(f, "%f", el->xMax, sep);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->title, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->xlabel, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->ylabel, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->legend, sep);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->other, lastSep);
if (sep == ',') fputc('"',f);
fputc(lastSep,f);
} 
*/


/*** Handwritten code after this point ***/

/**
 *   Creates a gnuPlot2D struct with default settings,
 * still needs data.
 * @return gnuPlot2D initialized struct
*/
struct gnuPlot2D *createGnuPlot2D() 
{
struct gnuPlot2D *ret;
int i;
AllocVar(ret);
ret->numPlots = 0;
ret->numFiles = 0;
ret->maxPlots = 10;
ret->maxFunctions = 10;
ret->gpList = needMem(sizeof(struct graphPoint2D **)*ret->maxPlots);
for(i=0;i<ret->maxPlots;i++)
    ret->gpList[i] = NULL;
ret->fileName = cloneString("tempPlot.png");
ret->directory = cloneString("/tmp");
ret->tempFiles = needMem(sizeof(char **)*ret->maxPlots);
for(i=0;i<ret->maxPlots;i++)
    ret->tempFiles[i] = cloneString(gptEmptyField);
ret->imageFormat = cloneString("png color");
ret->styles = needMem(sizeof(char **)*ret->maxPlots);
for(i=0;i<ret->maxPlots;i++)
    ret->styles[i] = cloneString(gptEmptyField);
ret->functions = needMem(sizeof(char **)*ret->maxPlots);
for(i=0;i<ret->maxFunctions;i++)    
    ret->functions[i] = cloneString(gptEmptyField);
ret->numFunctions = 0;
ret->functionStyles = needMem(sizeof(char **)*ret->maxPlots);
for(i=0;i<ret->maxFunctions;i++)
    ret->functionStyles[i] = cloneString(gptEmptyField);
ret->grid = 1;
ret->xtics = 0;
ret->ytics = 0;
ret->xTicFormat = cloneString(gptEmptyField);
ret->yTicFormat = cloneString(gptEmptyField);
ret->xDataLabels = 0;
ret->yDataLabels = 0;
ret->xlogAxis = 0;
ret->ylogAxis = 0;
ret->yMin = 0;
ret->yMax = 0;
ret->xMin = 0;
ret->xMax = 0;
ret->title = cloneString(gptEmptyField);
ret->xlabel = cloneString(gptEmptyField);
ret->ylabel = cloneString(gptEmptyField);
ret->legend = cloneString(gptEmptyField);
ret->other = cloneString(gptEmptyField);
return ret;
}

void checkBufferSize(char **s, int more, int *max, int *size)
{
while((*size + more) >= *max)
    {
    ExpandArray(*s,*max, 2*(*max));
    *max = 2*(*max);
    }
*size = *size + more;
} 


void addCmdString(char **head, char *tail, int *maxBuffSize, int *buffSize) 
{
checkBufferSize(head, (strlen(tail)+1), maxBuffSize, buffSize);
strncat(*head, tail, strlen(tail));
}


void addCmdStrings(char **head, char *tail1, char *tail2, int *maxBuffSize, int *buffSize)
{
addCmdString(head,tail1,maxBuffSize,buffSize);
addCmdString(head,"\"",maxBuffSize,buffSize);
addCmdString(head,tail2,maxBuffSize,buffSize);
addCmdString(head,"\"\n",maxBuffSize,buffSize);
}



void writeOutHeader(char **cmd, int *maxBuffSize, int *buffSize) 
{
char *message = "#This plot was automatically generated by the gnuPlot2D program\n";
addCmdString(cmd, message,maxBuffSize, buffSize); 
}

/**
 * Sets the file format for output, i.e. jpeg,png,eps,etc.
 * Example pd->imageFormat = "png"
 */
void writeOutSetOutput(struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize)
{
char *setOutput = "set output ";
addCmdString(cmd, setOutput, maxBuffSize, buffSize);
addCmdString(cmd, "\"" , maxBuffSize,buffSize);
addCmdString(cmd, pd->fileName, maxBuffSize, buffSize);
addCmdString(cmd, "\"\n", maxBuffSize, buffSize);
}

/**
 * If the log axis flats are set then writes out the gnuplot
 * command for log axis.
 * @param examines gnuPlot2D->setXLog and gnuPlot2D->setYLog
 */
void writeOutLogAxis( struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize)
{
char *setXLog = "set logscale x\n";
char *setYLog = "set logscale y\n";
int additions = 0;
if(pd->xlogAxis) 
{
additions += strlen(setXLog);
}
if(pd->ylogAxis)
{
additions += strlen(setYLog);
}
checkBufferSize(cmd, additions, maxBuffSize, buffSize);
if(pd->xlogAxis) 
strncat(*cmd, setXLog, strlen(setXLog));
if(pd->ylogAxis)
strncat(*cmd, setYLog, strlen(setYLog));
}

/**
 * Set the terminal type, i.e. output type: png, jpeg, x11, etc
 * <code><pre> 
 * set terminal {<terminal-type>}
 * </pre></code>
 * @param uses gnuPlot->imageFormat to set, usage gp->imageFormat="jpeg"
 */
void writeOutTerminal(struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize)
{
char *setTerminal = "set term ";
if(sameWord(pd->imageFormat, gptEmptyField)) 
    return;
checkBufferSize(cmd, (strlen(setTerminal) + strlen(pd->imageFormat) + 2), maxBuffSize, buffSize);
strncat(*cmd, setTerminal, strlen(setTerminal));
strncat(*cmd, pd->imageFormat, strlen(pd->imageFormat));
strncat(*cmd, "\n", 1);
}

/**
 * Lays out the axis and other documentations using gnuplot
 * commands.
 *
 * <p><b>Key/Legend:</b>As this command is rather complicated
 * the command is just copied verbatim if gnuPlot2D->title is set.
 * 
 * <code><pre>
 * Keys:
 *   set key {  left | right | top | bottom | outside | below
 *               | <position>}
 *              {Left | Right} {{no}reverse}
 *              {samplen <sample_length>} {spacing <vertical_spacing>}
 *              {width <width_increment>}
 *              {title "<text>"}
 *              {{no}box { {linestyle | ls <line_style>}
 *                         | {linetype | lt <line_type>}
 *                           {linewidth | lw <line_width>}}}
 *   Example:
 *   pt->title = "set key left bottom Left title 'Legend' box 3"
 *</pre></code>
 *<p><b>Labels:</b> Uses the strings supplied for the the gnuplot
 *   label command, same for gnuPlot2D->ylabel and gnuPlot2D->xlabel.
 * <code><pre> 
 *   Labels:
 *   set xlabel {"<label>"} {<xoff>}{,<yoff>} {"<font>{,<size>}"}
 * </pre></code>
 * Example: gp->xlabel = "x axis stuff";
 * <p><b>Title:</b> Uses string supplied in gnuplot2D->title to create
 * gnuplot command to set title:
 * <code><pre>
 *   Title:
 *   set title {"<title-text>"} {<xoff>}{,<yoff>} {"<font>,{<size>}"}
 *  </pre></code>
 *
 * Example: gp->title = "With this plot I conclude my thesis";
 */
void writeOutInfoLabels(struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize)
{
char *setXLabel = "set xlabel ";
char *setYLabel = "set ylabel ";
char *setTitle = "set title ";

if(!sameString(pd->xlabel, gptEmptyField)) 
    addCmdStrings(cmd, setXLabel, pd->xlabel, maxBuffSize, buffSize);

if(!sameString(pd->ylabel, gptEmptyField)) 
    addCmdStrings(cmd, setYLabel, pd->ylabel, maxBuffSize, buffSize);

if(!sameString(pd->title, gptEmptyField)) 
    addCmdStrings(cmd, setTitle, pd->title, maxBuffSize, buffSize);

if(!sameString(pd->legend, gptEmptyField)) 
    addCmdString(cmd, pd->legend, maxBuffSize, buffSize);

}



void addListOfXTicNames(struct graphPoint2D *gp, char **cmd, int *maxBuffSize, int *buffSize)
{
char buff[256];
sprintf(buff, "%g", gp->x);
addCmdString(cmd, " \"", maxBuffSize, buffSize);
addCmdString(cmd, gp->name, maxBuffSize, buffSize);
addCmdString(cmd, "\" ", maxBuffSize, buffSize);
addCmdString(cmd, buff, maxBuffSize, buffSize);
}

void addListOfYTicNames(struct graphPoint2D *gp, char **cmd, int *maxBuffSize, int *buffSize)
{
char buff[256];
sprintf(buff, "%g", gp->x);
addCmdString(cmd, " \"", maxBuffSize, buffSize);
addCmdString(cmd, gp->name, maxBuffSize, buffSize);
addCmdString(cmd, "\" ", maxBuffSize, buffSize);
addCmdString(cmd, buff, maxBuffSize, buffSize);
}



/**
 *   Writes out the tick labels for each data point in the data set
 *   if that flag is set. Currently cycles through all of the data
 *   points and puts their name on the axis (rotated on x-axis). The
 *   idea is for use with bar charts etc.
 *   
 *   <code><pre>
 *   Gnuplot documentation:
 *       set xtics {axis | border} {{no}mirror} {{no}rotate}
 *                {  autofreq
 *                 | <incr>
 *                 | <start>, <incr> {,<end>}
 *                 | ({"<label>"} <pos> {,{"<label>"} <pos>}...) }
 *      set noxtics
 *      show xtics
 *   </pre></code>
 */
void writeOutTicLabels(struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize)
{

if(pd->xtics) 
    {
    int i;
    char * setXtics = "set xtics rotate (";
    char *end = ")\n";
    addCmdString(cmd, setXtics, maxBuffSize, buffSize);
    for(i=0;i<pd->numPlots;i++) 
	{
	addListOfXTicNames(pd->gpList[i], cmd, maxBuffSize, buffSize);
	if((i+1) < pd->numPlots) 
	    {
	    addCmdString(cmd,",", maxBuffSize, buffSize);
	    }
	}
    addCmdString(cmd, end, maxBuffSize, buffSize);
    }
if(pd->ytics)
    {
    int i;
    char * setYtics = "set ytics (";
    char *end = ")\n";
    addCmdString(cmd, setYtics, maxBuffSize, buffSize);
    for(i=0; i<pd->numPlots; i++) 
	{
	addListOfYTicNames(pd->gpList[i], cmd, maxBuffSize, buffSize);
	if((i+1) < pd->numPlots) 
	    {
	    addCmdString(cmd,",", maxBuffSize, buffSize);
	    }
	}
    addCmdString(cmd, end, maxBuffSize, buffSize);
    }
}

/**
 * This just puts whatever you have in the other char* into the
 * gnuplot description, The function doesn't even add a newline. This
 * is sort of a power user capability for hacks not currently supported.  
*/
void writeOutOther(struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize) 
{
if(differentString(pd->other, gptEmptyField))
    {
    addCmdString(cmd, pd->other,maxBuffSize, buffSize); 
    }
}

void setMinMax(float min, float max,char **cmd,int *maxBuffSize,int *buffSize)
{
char buff[256];
sprintf(buff, "[%g:%g] ", min, max);
addCmdString(cmd, buff, maxBuffSize, buffSize);
}

/**
 * Write out plots. This is by far the most complicated outputing
 * part as each bit includes not only data file names but also the 
 * styes, as well as all of the functions. The plot command is 
 * laid out using the gnuplot syntax:
 *
 * <p><code><pre>
 * Gnuplot Documentation:
 *  plot {<ranges>}
 *          {<function> | {"<datafile>" {datafile-modifiers}}}
 *          {axes <axes>} {<title-spec>} {with <style>}
 *           {, {definitions,} <function> ...}
 *
 *  Examples:
 *    plot sin(x)
 *    plot f(x) = sin(x*a), a = .2, f(x), a = .4, f(x)
 *    plot [t=1:10] [-pi:pi*2] tan(t), \
 *           "data.1" using (tan($2)):($3/$4) smooth csplines \
 *            axes x1y2 notitle with lines 5
 *
 * </pre></code>
 * Varables examined/used:
 * <ol>
 * <li>gp->tempFiles;</li> 
 * <li>gp->numPlots;</li>
 * <li>gp->numFiles;</li>
 * <li>gp->functions;</li>
 * <li>gp->functionStyles;</li>
 * <li>gp->numFunctions;</li>
 * <li>gp->styles;</li>
 * </ol>
 * 
 * <p>stles has some of the more interesting possiblities, an example is:
 * <p><code>gp->styles[0] = "linespoints lt 1 lw 2  pt 3 ps 2" where
 * lt = lineType, lw = lineWidth, pt = point type, ps = point size.
 */
void writeOutPlot(struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize)
{
int i,j;
addCmdString(cmd, "plot " ,maxBuffSize, buffSize); 
if(pd->xMin != 0 || pd->xMax != 0) 
    setMinMax(pd->xMin, pd->xMax,cmd,maxBuffSize,buffSize);
if(pd->yMin != 0 || pd->yMax != 0) 
    setMinMax(pd->yMin, pd->yMax,cmd,maxBuffSize,buffSize);
for(i=0;i<pd->numPlots;i++) 
    {
    if(i!=0)
	addCmdString(cmd, ",\"" ,maxBuffSize, buffSize); 
    else 
	addCmdString(cmd, "\"" ,maxBuffSize, buffSize); 
    
    addCmdString(cmd, pd->tempFiles[i], maxBuffSize, buffSize);
    addCmdString(cmd, "\" ", maxBuffSize, buffSize);
    if(pd->gpList[i]->groupName != NULL) 
	{
	addCmdString(cmd, " title \"", maxBuffSize, buffSize);
	addCmdString(cmd, pd->gpList[i]->groupName, maxBuffSize, buffSize);
	addCmdString(cmd, "\" ", maxBuffSize, buffSize);
	}
    if(differentString(pd->styles[i],gptEmptyField)) 
	{
	addCmdString(cmd, " with ", maxBuffSize, buffSize);
	addCmdString(cmd, pd->styles[i], maxBuffSize, buffSize);
	}
    if((i+1) <= pd->numPlots || pd->numFunctions > 0) 
	addCmdString(cmd, "\t\\\n", maxBuffSize, buffSize);
    else 
	addCmdString(cmd, "\n", maxBuffSize, buffSize);
    }
for(j=0;j<pd->numFunctions;j++)
    {
    if(i!=0)
	addCmdString(cmd, "," ,maxBuffSize, buffSize); 
    addCmdString(cmd, pd->functions[j], maxBuffSize, buffSize);
    if(differentString(pd->functionStyles[j],gptEmptyField)) 
	{
	addCmdString(cmd, " with ", maxBuffSize, buffSize);
	addCmdString(cmd, pd->functionStyles[j], maxBuffSize, buffSize);
	
	}
    if((j+1) >= pd->numFunctions) 
	addCmdString(cmd, "\n", maxBuffSize, buffSize);
    else 
	addCmdString(cmd, "\t\\\n", maxBuffSize, buffSize);
    }
addCmdString(cmd, "\n", maxBuffSize, buffSize);
}

void writeOutGrid(struct gnuPlot2D *pd, char **cmd, int *maxBuffSize, int *buffSize)
{
addCmdString(cmd, "set grid\n", maxBuffSize, buffSize);
}

void writeOutData(struct gnuPlot2D *pd, 
		  struct graphPoint2D *gp,
		  char *fileName) 
{
FILE *out = mustOpen(fileName, "w");
struct graphPoint2D *g;
for(g=gp ; g != NULL; g = g->next) 
    {
    fprintf(out, "%g\t%g", g->x, g->y);
    if(pd->xErrorBars) 
	fprintf(out, "\t%g", g->xDelta);
    if(pd->yErrorBars)
	fprintf(out, "\t%g", g->yDelta);
    fprintf(out,"\n");
    }
carefulClose(&out);
}

/**
 *   gptGenerateCmd - takes a gnuPlot2D struct and generates a string
 *  containg output to generate plot in gnuplot according to the
 *  information contained. Will errAbort if problems are
 *  encountered. On sucess returns the absolute pathname of the plot or
 *  NULL if plot is displayed in xwindow.  
 *  @param struct gnuPlot2D -contains data to plot 
 *  @return char *cmd - sequence of instructions to create desired plot
 *  remember to free this.
 */
char *gptGenerateCmd(struct gnuPlot2D *pd)
{
int maxBuffSize = 1024, buffSize = 0;
char *cmd = needMem(sizeof(char) * maxBuffSize);
int i;
/* first generate our data files */
for(i=0; i<pd->numPlots; i++) 
    {
    struct tempName tmpFile;
    makeTempName(&tmpFile, "gnuPlot2D_", ".dat");
//    sprintf(fileBuffer, "%s/%s",pd->directory,tmpFile);
    ExpandArray(pd->tempFiles,pd->numFiles,(pd->numFiles+1));
    pd->tempFiles[pd->numFiles] = cloneString(tmpFile.forCgi);
    //  writeOutData(pd, pd->gpList[i],fileBuffer);
    writeOutData(pd, pd->gpList[i],tmpFile.forCgi);
    pd->numFiles++;
    }

writeOutHeader(&cmd, &maxBuffSize, &buffSize);
writeOutSetOutput(pd, &cmd, &maxBuffSize, &buffSize);
/* Now write out our different parameters */
writeOutLogAxis(pd, &cmd, &maxBuffSize, &buffSize);

writeOutTerminal(pd, &cmd, &maxBuffSize, &buffSize);
writeOutGrid(pd, &cmd, &maxBuffSize, &buffSize);
writeOutInfoLabels(pd, &cmd, &maxBuffSize, &buffSize);
writeOutTicLabels(pd, &cmd, &maxBuffSize, &buffSize);
writeOutOther(pd, &cmd, &maxBuffSize, &buffSize);
writeOutPlot(pd, &cmd, &maxBuffSize, &buffSize);
return cmd;

}

/**
 * gptPlotFromCmd - this function takes a string generated from gptGenerateCmd() 
 * and generates the actual plot described by it.
 * @param string - cmd, a string containing the commands necessary to
 * generated a gnuplot. Basically a memory version of the batch file
 * which could be used to generate gnuplot from command line
 */
void gptPlotFromCmd(char *cmd)
{
gnuplot_ctrl *gpc = gnuplot_init();
gnuplot_cmd(gpc, cmd);
gnuplot_close(gpc);
}

void gptQuickPlotXY(char *title, char *fileName, 
		    char *fileFormat, double *x, double *y, int numPoints)
{
gnuplot_ctrl *gpc = gnuplot_init();

gnuplot_cmd(gpc, "set term %s", fileFormat);
if(differentString(fileFormat,"x11"))
    gnuplot_cmd(gpc, "set ouput \"%s\"",fileName);
gnuplot_plot_xy(gpc, x,y,numPoints,title);
gnuplot_close(gpc);
}

void gptAddGraphPointList(struct gnuPlot2D *gPlot, 
			  struct graphPoint2D *gpList,
			  char *newStyle)
{
char *finalStyle = NULL;
if(gpList == NULL)
    return;
if (newStyle == NULL) 
    finalStyle = cloneString("linespoints");
else 
    finalStyle = cloneString(newStyle);
if(gPlot->numPlots+1 >= gPlot->maxPlots) 
    {
    ExpandArray(gPlot->gpList, gPlot->maxPlots, (gPlot->maxPlots*2));
    ExpandArray(gPlot->styles, gPlot->maxPlots, (gPlot->maxPlots*2));
    gPlot->maxPlots *= 2;
    }
gPlot->gpList[gPlot->numPlots] = gpList;
gPlot->styles[gPlot->numPlots] = finalStyle;
gPlot->numPlots++;
}

/**
 * gptRemoveTempFiles - removes temp files created. 
 */
void gptRemoveTempFiles(struct gnuPlot2D *gPlot)
{
int i;
for(i=0; i<gPlot->numFiles; i++)
    {
    remove(gPlot->tempFiles[i]);
    }
}
