1 #include <gtk/gtk.h>
2 #include "ggobi.h"
3 #include "externs.h"
4 #include "GGobiAPI.h"
5 
6 #include "ggobiClass.h"
7 
8 #include <stdio.h>
9 
10 #include "plugin.h"
11 #include "dspdesc.h"
12 #include "macros.h"
13 
14 #include "config.h"
15 
16 #define MAX_PER_ROW 100
17 
18 /*
19  Jittering:  d->jitdata is added directly to world data, so the
20    appropriate values of jitdata should be divided by PRECISION1
21    and then added to tform where we're using that; where we're using
22    planar, we're ok, because planar already includes jittering.
23  Shift and scale:  see splot_plane_to_screen in splot.c
24    Take care of shifting by describing only those points that
25      are within the viewing area.
26    Scaling:  sp->scale.{x,y}
27       screen=(planar - pmid) * (max*(scale/2)) / PRECISION1
28       screen += max/2
29 */
30 
31 /* In sp_plot_edges.c */
32 gboolean splot_plot_edge (gint m, GGobiData *d, GGobiData *e,
33 		 splotd *sp, displayd *display, ggobid *gg);
34 gboolean splot_hidden_edge (gint m, GGobiData *d, GGobiData *e,
35 		   splotd *sp, displayd *display, ggobid *gg);
36 
37 /* c(color.red, color.green, color.blue) */
38 void
describe_color(FILE * fp,GdkColor color)39 describe_color (FILE *fp, GdkColor color)
40 {
41   fprintf (fp, "%.3f", color.red / 65535.0);
42   ADD_COMMA(fp);
43   fprintf (fp, "%.3f", color.green / 65535.0);
44   ADD_COMMA(fp);
45   fprintf (fp, "%.3f", color.blue / 65535.0);
46 }
47 
48 /*
49 colormap=list (
50  name="",
51  ncolors=,
52  type="",
53  system="rgb",
54  backgroundColor=c(r,g,b),
55  hiddenColor=c(r,g,b),
56  accentColor=c(r,g,b),
57  foregroundColors=list ( c(r,g,b), ...)
58 ),
59 */
60 void
describe_colorscheme(FILE * fp,ggobid * gg)61 describe_colorscheme (FILE *fp, ggobid *gg)
62 {
63   gint i;
64   colorschemed *scheme = gg->activeColorScheme;
65 
66   OPEN_NAMED_LIST(fp, "colormap");
67 
68   fprintf (fp, "name='%s',\n", scheme->name);
69   fprintf (fp, "ncolors=%d,\n", scheme->n);
70   fprintf (fp, "type=%d,\n", scheme->type);
71   /* the only scheme we currently support */
72   fprintf (fp, "system='rgb',\n");
73 
74   OPEN_NAMED_C(fp, "backgroundColor");
75   describe_color (fp, scheme->rgb_bg);
76   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
77 
78   OPEN_NAMED_C (fp, "hiddenColor");
79   describe_color (fp, scheme->rgb_hidden);
80   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
81 
82   OPEN_NAMED_C (fp, "accentColor");
83   describe_color (fp, scheme->rgb_accent);
84   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
85 
86   OPEN_NAMED_LIST(fp, "foregroundColors");
87   for (i=0; i<scheme->n; i++) {
88     OPEN_C(fp);  /* one foreground color */
89     describe_color (fp, scheme->rgb[i]);
90     CLOSE_C(fp);  /* one foreground color */
91     if (i < scheme->n-1)
92       ADD_COMMA(fp);
93   }
94   CLOSE_LIST(fp); /* foregroundColors */
95 
96   CLOSE_LIST(fp); /* colormap */
97   ADD_COMMA(fp);
98   ADD_CR(fp);
99 }
100 
101 
102 /*
103 stickylabels = list(list(index=, label=""),
104                     list(index=, label=""), ...)),
105 */
106 void
describe_sticky_labels(FILE * fp,GGobiData * d,cpaneld * cpanel,ggobid * gg)107 describe_sticky_labels (FILE *fp, GGobiData *d, cpaneld *cpanel, ggobid *gg)
108 {
109   gint j;
110 
111   if (d->sticky_ids && g_slist_length (d->sticky_ids) > 0) {
112     GSList *l;
113     ADD_COMMA(fp);
114     OPEN_NAMED_LIST(fp, "stickylabels");
115     for (l = d->sticky_ids; l; l = l->next) {
116       OPEN_LIST(fp);  /* one sticky label */
117       j = GPOINTER_TO_INT (l->data);
118       fprintf (fp, "index=%d", j);
119       ADD_COMMA(fp);
120       fprintf (fp, "label=");
121 
122       fprintf (fp, "'%s'", identify_label_fetch(j, cpanel, d, gg));
123 
124       CLOSE_LIST(fp);  /* one sticky label */
125       if (l->next)
126         ADD_COMMA(fp);
127     }
128     CLOSE_LIST(fp);  /* stickylabels */
129   }
130 }
131 
132 /*
133   iscr.x -= (sp->max.x / 2);
134   gtmp =  (iscr.x * PRECISION1) / (sp->iscale.x);
135   planarx = gtmp + sp->pmid.x
136 */
137 static greal
scale_convert(splotd * sp,gint ival,gint max,greal mid,gint scale)138 scale_convert (splotd *sp, gint ival, gint max, greal mid, gint scale)
139 {
140   gint itmp;
141 
142   ival -= (max / 2);
143   itmp = (ival * PRECISION1) / (scale);
144   return ((greal) itmp + mid);
145 }
146 
147 /*
148     list(
149       projection = "",
150       scale = c(x= , y= ),  # a float between 0 and 1
151       # limits are derived by converting the screen size into tform
152       # coords and also into planar coordinates
153       # Update: these limits are not used in the R scripts
154       # that generate the plots, but we'll leave them in for
155       # a while just in case.  dfs, March 2006
156       tformLims = c(xmin=, xmax=, ymin=, ymax=),
157       planarLims = c(xmin=, xmax=, ymin=, ymax=),
158       points = list(
159         # x and y are tform for 2d plots, planar for tours;
160         # for 1dplots, one is the data (tform) and the other is
161         #     the 'spreadData'
162         x = c(), y = c(),
163         hidden = c(), missing = c(),
164         color = c(), glyphtype = c(), glyphsize = c(),
165       ),
166       edges = list(
167         # src and dest are integers which index into points${x,y}
168         src = c(), dest = c(),
169         hidden = c(), missing = c(),
170         color = c(), linetype = c(), linewidth = c(),
171       ),
172       stickylabels = list(list(index=, label=""),
173                           list(index=, label=""), ...)),
174       # the parameters corresponding to the current projection
175       params = list(label="", orientation=""),
176       params = list(xlabel="", ylabel="",),
177       params = list(F, labels, ranges),
178       params = list(F, labels, ranges),
179       params = list(F, labels, ranges),
180       dparams = list(xF, xlabels, xranges, yF, ylabels, yranges),
181 */
182 void
describe_scatterplot_plot(FILE * fp,ggobid * gg,displayd * display,splotd * sp,dspdescd * desc,ProjectionMode projection)183 describe_scatterplot_plot (FILE *fp, ggobid *gg, displayd *display,
184    splotd *sp, dspdescd *desc, ProjectionMode projection)
185 {
186   vartabled *vt;
187   cpaneld *cpanel = &display->cpanel;
188   gint i, j, m;
189   gint k = -1;
190   const gchar *const *gnames = GGOBI(getPModeNames)(&k);
191   GGobiData *d = display->d;
192   GGobiData *e = display->e;
193   /*gboolean missing;*/
194   icoords scr;
195   fcoords tfmin, tfmax;
196   fcoords pmin, pmax;
197   float ftmp;
198   gint counter;
199 
200   OPEN_LIST(fp);  /* plot; unlabelled */
201 
202   /* A scatterplot is both a display type and a plot type */
203   fprintf (fp, "type='scatterplot'"); ADD_COMMA(fp);
204   fprintf (fp, "projection='%s'", gnames[(gint) projection]); ADD_COMMA(fp);
205 
206   /*-- scale parameters ------------------------------------------*/
207 
208   fprintf (fp, "scale=c(%.3f, %.3f)", sp->scale.x, sp->scale.y);
209   ADD_COMMA(fp); ADD_CR(fp);
210 
211   /* Find the tform values of the screen min and max */
212   tfmin.x = tfmin.y = tfmax.x = tfmax.y = 0.0;
213 
214   scr.x = scr.y = 0;
215   /*splot_screen_to_tform (cpanel, sp, &scr, &tfmin, gg);*/
216   if(sp && GGOBI_IS_EXTENDED_SPLOT(sp)) {
217      GGobiExtendedSPlotClass *klass;
218      klass = GGOBI_EXTENDED_SPLOT_GET_CLASS(sp);
219      if(klass->screen_to_tform)
220        klass->screen_to_tform(cpanel, sp, &scr, &tfmin, gg);
221      else
222        g_printerr ("screen_to_tform routine needed\n");
223   }
224 
225   scr.x = sp->max.x;
226   scr.y = sp->max.y;
227   /*splot_screen_to_tform (cpanel, sp, &scr, &tfmax, gg);*/
228   if(sp && GGOBI_IS_EXTENDED_SPLOT(sp)) {
229      GGobiExtendedSPlotClass *klass;
230      klass = GGOBI_EXTENDED_SPLOT_GET_CLASS(sp);
231      if(klass->screen_to_tform)
232        klass->screen_to_tform(cpanel, sp, &scr, &tfmax, gg);
233      else
234        g_printerr ("screen_to_tform routine needed\n");
235   }
236 
237   // Swap ymin and ymax
238   ftmp = tfmin.y;
239   tfmin.y = tfmax.y;
240   tfmax.y = ftmp;
241 
242   /* Update: none of these limits are now used in the R scripts that
243    * generate the plots, but we'll leave them in for a while just in
244    * case.  dfs, March 2006
245    */
246   fprintf (fp,
247     "tformLims=c(xmin=%.3f, xmax=%.3f, ymin=%.3f, ymax=%.3f),",
248     tfmin.x, tfmax.x, tfmin.y, tfmax.y);
249   ADD_CR(fp);
250 
251    /* Now how do I find the planar coordinates for the same points? */
252    /*   For those four values of iscr.{x,y},  do this:
253     iscr.x -= (sp->max.x / 2);
254     gtmp = (iscr.x * PRECISION1) / (sp->iscale.x);
255     planarx = gtmp + sp->pmid.x
256     */
257 
258   // Swap y min and max up front.
259   pmin.x = scale_convert (sp, 0, sp->max.x, sp->pmid.x, sp->iscale.x);
260   pmax.y = scale_convert (sp, 0, sp->max.y, sp->pmid.y, sp->iscale.y);
261   pmax.x = scale_convert (sp, sp->max.x, sp->max.x, sp->pmid.x, sp->iscale.x);
262   pmin.y = scale_convert (sp, sp->max.y, sp->max.y, sp->pmid.x, sp->iscale.y);
263 
264   fprintf (fp,
265     "planarLims=c(xmin=%.3f, xmax=%.3f, ymin=%.3f, ymax=%.3f),",
266     pmin.x, pmax.x, pmin.y, pmax.y);
267   ADD_CR(fp);
268 
269   /*-- row-wise data ----------------------------------------*/
270 
271   OPEN_NAMED_LIST(fp, "points");
272 
273   /* raw row number -- the edges use these  */
274   OPEN_NAMED_C(fp, "index");
275   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
276     i = d->rows_in_plot.els[m];
277     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
278     fprintf (fp, "%d", i);
279     if (m < d->nrows_in_plot-1)
280       ADD_COMMA(fp);
281   }
282   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
283 
284   /* x coordinates */
285   OPEN_NAMED_C(fp, "x");
286   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
287     i = d->rows_in_plot.els[m];
288     if (projection == P1PLOT) {
289       fprintf (fp, "%g", d->tform.vals[i][sp->p1dvar]);
290     } else if (projection == XYPLOT) {
291       fprintf (fp, "%g", d->tform.vals[i][sp->xyvars.x]);
292       /*  Is this how to add jittering to tform?
293       fprintf (fp, "%g", d->tform.vals[i][sp->xyvars.x] +
294 	       d->jitdata.vals[i][sp->xyvars.x] / precis);
295       */
296     } else {  /* planar already includes jitdata! */
297       fprintf (fp, "%g", sp->planar[i].x);
298     }
299     if (m < d->nrows_in_plot-1)
300       ADD_COMMA(fp);
301     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
302   }
303   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
304 
305   /* y coordinates */
306   OPEN_NAMED_C(fp, "y");
307   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
308     i = d->rows_in_plot.els[m];
309     if (projection == P1PLOT) {
310       /* I <think> spread_data is in tform coordinates, but it's hard
311          to tell.  And maybe it doesn't matter because the spread axis
312          isn't going to be labelled.
313       */
314       fprintf (fp, "%g", sp->p1d.spread_data.els[m]);
315     } else if (projection == XYPLOT) {
316       fprintf (fp, "%g", d->tform.vals[i][sp->xyvars.y]);
317     } else {
318       fprintf (fp, "%g", sp->planar[i].y);
319     }
320     if (m < d->nrows_in_plot-1)
321       ADD_COMMA(fp);
322     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
323   }
324   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
325 
326   /* color */
327   OPEN_NAMED_C(fp, "color");
328   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
329     i = d->rows_in_plot.els[m];
330     fprintf (fp, "%d", d->color_now.els[i]);
331     if (m < d->nrows_in_plot-1)
332       ADD_COMMA(fp);
333     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
334   }
335   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
336 
337   /* glyphtype */
338   OPEN_NAMED_C(fp, "glyphtype");
339   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
340     i = d->rows_in_plot.els[m];
341     fprintf (fp, "%d", d->glyph_now.els[i].type);
342     if (m < d->nrows_in_plot-1)
343       ADD_COMMA(fp);
344     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
345   }
346   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
347 
348   /* glyphsize */
349   OPEN_NAMED_C(fp, "glyphsize");
350   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
351     i = d->rows_in_plot.els[m];
352     fprintf (fp, "%d", d->glyph_now.els[i].size);
353     if (m < d->nrows_in_plot-1)
354       ADD_COMMA(fp);
355     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
356   }
357   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
358 
359   /* hiddenness */
360   OPEN_NAMED_C(fp, "hidden");
361   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
362     i = d->rows_in_plot.els[m];
363     fprintf (fp, "%d", d->hidden_now.els[i]);
364     if (m < d->nrows_in_plot-1)
365       ADD_COMMA(fp);
366     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
367   }
368   CLOSE_C(fp); /*ADD_COMMA(fp);*/ ADD_CR(fp);
369 
370   /* missingness */
371   /*
372   if (d->nmissing > 0) {
373     OPEN_NAMED_C(fp, "missing");
374     for (m=0; m<d->nrows_in_plot; m++) {
375     i = d->rows_in_plot.els[m];
376       missing = false;
377       if(GGOBI_IS_EXTENDED_SPLOT(sp)) {
378         GGobiExtendedSPlotClass *klass;
379         klass = GGOBI_EXTENDED_SPLOT_GET_CLASS(sp);
380         if (klass->draw_case_p)
381           missing = klass->draw_case_p (sp, i, d, gg);
382       }
383       fprintf (fp, "%d,", missing);
384     }
385     CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
386   }
387   */
388   CLOSE_LIST(fp);  /* points */
389   ADD_COMMA(fp);
390   ADD_CR(fp);
391 
392   /*-- parameters for each projection ---------------------------------*/
393 
394   if (projection == P1PLOT) {
395     OPEN_NAMED_LIST(fp, "params");
396     vt = vartable_element_get (sp->p1dvar, d);
397     fprintf (fp, "label='%s',", vt->collab_tform);
398     /* type: TEXTURE=0, ASH=1 */
399     fprintf (fp, "type=%d,", cpanel->p1d.type);
400     /* plot orientation: HORIZONTAL=0, VERTICAL=1 */
401     fprintf (fp, "orientation=%d,", display->p1d_orientation);
402     /* whether we're drawing line segments */
403     fprintf (fp, "lines=%d", cpanel->p1d.ASH_add_lines_p);
404     CLOSE_LIST(fp); /* p1plot params */
405   } else if (projection == XYPLOT) {
406     OPEN_NAMED_LIST(fp, "params");
407     vt = vartable_element_get (sp->xyvars.x, d);
408     fprintf (fp, "xlabel='%s',", vt->collab_tform);
409     vt = vartable_element_get (sp->xyvars.y, d);
410     fprintf (fp, "ylabel='%s'", vt->collab_tform);
411     CLOSE_LIST(fp);  /* xyplot params */
412   } else if (projection == TOUR1D) {
413     /* F, variable labels, variable lims */
414     OPEN_NAMED_LIST(fp, "params");
415     /* F */
416     OPEN_NAMED_C(fp, "F");
417     for (k=0; k<display->t1d.nsubset; k++) {
418       j = display->t1d.subset_vars.els[k];
419       fprintf (fp, "%.3f", display->t1d.F.vals[0][j]);
420       if (k < display->t1d.nsubset-1)
421         ADD_COMMA(fp);
422     }
423     CLOSE_C(fp);
424     ADD_COMMA(fp);
425     /* variable labels */
426     OPEN_NAMED_C(fp, "labels");
427     for (k=0; k<display->t1d.nsubset; k++) {
428       j = display->t1d.subset_vars.els[k];
429       vt = vartable_element_get (j, d);
430       fprintf (fp, "'%s'", vt->collab_tform);
431       if (k < display->t1d.nsubset-1)
432         ADD_COMMA(fp);
433     }
434     CLOSE_C(fp);
435     ADD_COMMA(fp);
436     /* variable ranges */
437     OPEN_NAMED_LIST(fp, "ranges");
438     for (k=0; k<display->t1d.nsubset; k++) {
439       j = display->t1d.subset_vars.els[k];
440       vt = vartable_element_get (j, d);
441       OPEN_C(fp);
442       fprintf (fp, "%.3f, %.3f", vt->lim.min, vt->lim.max);
443       CLOSE_C(fp);
444       if (k < display->t1d.nsubset-1)
445         ADD_COMMA(fp);
446     }
447     CLOSE_LIST(fp);  /* tour1d ranges */
448     CLOSE_LIST(fp);  /* tour1d params */
449   } else if (projection == TOUR2D3) {
450     /* F, variable labels, variable lims */
451     OPEN_NAMED_LIST(fp, "params");
452     /* F */
453     OPEN_NAMED_C(fp, "F");
454     for (k=0; k<display->t2d3.nsubset; k++) {
455       j = display->t2d3.subset_vars.els[k];
456       fprintf (fp, "%.3f", display->t2d3.F.vals[0][j]);
457       if (k < display->t2d3.nsubset-1)
458         ADD_COMMA(fp);
459     }
460     for (k=0; k<display->t2d3.nsubset; k++) {
461       j = display->t2d3.subset_vars.els[k];
462       fprintf (fp, "%.3f", display->t2d3.F.vals[1][j]);
463       if (k < display->t2d3.nsubset-1)
464         ADD_COMMA(fp);
465     }
466     CLOSE_C(fp);
467     ADD_COMMA(fp);
468     /* variable labels */
469     OPEN_NAMED_C(fp, "labels");
470     for (k=0; k<display->t2d3.nsubset; k++) {
471       j = display->t2d3.subset_vars.els[k];
472       vt = vartable_element_get (j, d);
473       fprintf (fp, "'%s'", vt->collab_tform);
474       if (k < display->t2d3.nsubset-1)
475         ADD_COMMA(fp);
476     }
477     CLOSE_C(fp);
478     ADD_COMMA(fp);
479     /* variable ranges */
480     OPEN_NAMED_LIST(fp, "ranges");
481     for (k=0; k<display->t2d3.nsubset; k++) {
482       j = display->t2d3.subset_vars.els[k];
483       vt = vartable_element_get (j, d);
484       OPEN_C(fp);
485       fprintf (fp, "%.3f, %.3f", vt->lim.min, vt->lim.max);
486       CLOSE_C(fp);
487       if (k < display->t2d3.nsubset-1)
488         ADD_COMMA(fp);
489     }
490     CLOSE_LIST(fp);  /* tour2d3 ranges */
491     CLOSE_LIST(fp);  /* tour2d3 params */
492   } else if (projection == TOUR2D) {
493     /* F, variable labels, variable lims */
494     OPEN_NAMED_LIST(fp, "params");
495     /* F */
496     OPEN_NAMED_C(fp, "F");
497     for (k=0; k<display->t2d.nsubset; k++) {
498       j = display->t2d.subset_vars.els[k];
499       fprintf (fp, "%.3f", display->t2d.F.vals[0][j]);
500       if (k < display->t2d.nsubset-1)
501         ADD_COMMA(fp);
502     }
503     ADD_COMMA(fp);
504     for (k=0; k<display->t2d.nsubset; k++) {
505       j = display->t2d.subset_vars.els[k];
506       fprintf (fp, "%.3f", display->t2d.F.vals[1][j]);
507       if (k < display->t2d.nsubset-1)
508         ADD_COMMA(fp);
509     }
510     CLOSE_C(fp);  /* F */
511     ADD_COMMA(fp);
512     /* variable labels */
513     OPEN_NAMED_C(fp, "labels");
514     for (k=0; k<display->t2d.nsubset; k++) {
515       j = display->t2d.subset_vars.els[k];
516       vt = vartable_element_get (j, d);
517       fprintf (fp, "'%s'", vt->collab_tform);
518       if (k < display->t2d.nsubset-1)
519         ADD_COMMA(fp);
520     }
521     CLOSE_C(fp); /* labels */
522     ADD_COMMA(fp);
523     /* variable ranges */
524     OPEN_NAMED_LIST(fp, "ranges");
525     for (k=0; k<display->t2d.nsubset; k++) {
526       j = display->t2d.subset_vars.els[k];
527       vt = vartable_element_get (j, d);
528       OPEN_C(fp);
529       fprintf (fp, "%.3f, %.3f", vt->lim.min, vt->lim.max);
530       CLOSE_C(fp);
531       if (k < display->t2d.nsubset-1)
532         ADD_COMMA(fp);
533     }
534     CLOSE_LIST(fp);   /* tour2d ranges */
535     CLOSE_LIST(fp);  /* tour2d params */
536   } else if (projection == COTOUR) {
537     /* xF, x variable labels, x variable lims; ditto for y */
538     OPEN_NAMED_LIST(fp, "params");
539     /* xF */
540     OPEN_NAMED_C(fp, "xF");
541     for (k=0; k<display->tcorr1.nsubset; k++) {
542       j = display->tcorr1.subset_vars.els[k];
543       fprintf (fp, "%.3f", display->tcorr1.F.vals[0][j]);
544       if (k < display->tcorr1.nsubset-1)
545         ADD_COMMA(fp);
546     }
547     CLOSE_C(fp);
548     ADD_COMMA(fp);
549     /* variable labels */
550     OPEN_NAMED_C(fp, "xlabels");
551     for (k=0; k<display->tcorr1.nsubset; k++) {
552       j = display->tcorr1.subset_vars.els[k];
553       vt = vartable_element_get (j, d);
554       fprintf (fp, "'%s'", vt->collab_tform);
555       if (k < display->tcorr1.nsubset-1)
556         ADD_COMMA(fp);
557     }
558     CLOSE_C(fp);
559     ADD_COMMA(fp);
560     /* x variable ranges */
561     OPEN_NAMED_LIST(fp, "xranges");
562     for (k=0; k<display->tcorr1.nsubset; k++) {
563       j = display->tcorr1.subset_vars.els[k];
564       vt = vartable_element_get (j, d);
565       OPEN_C(fp);
566       fprintf (fp, "%.3f, %.3f", vt->lim.min, vt->lim.max);
567       CLOSE_C(fp);
568       if (k < display->tcorr1.nsubset-1)
569         ADD_COMMA(fp);
570     }
571     CLOSE_LIST(fp);  /* tour2x1d, x ranges */
572 
573     ADD_COMMA(fp);  ADD_CR(fp);
574 
575     /* yF */
576     OPEN_NAMED_C(fp, "yF");
577     for (k=0; k<display->tcorr2.nsubset; k++) {
578       j = display->tcorr2.subset_vars.els[k];
579       fprintf (fp, "%.3f", display->tcorr2.F.vals[0][j]);
580       if (k < display->tcorr2.nsubset-1)
581         ADD_COMMA(fp);
582     }
583     CLOSE_C(fp);
584     ADD_COMMA(fp);
585     /* y variable labels */
586     OPEN_NAMED_C(fp, "ylabels");
587     for (k=0; k<display->tcorr2.nsubset; k++) {
588       j = display->tcorr2.subset_vars.els[k];
589       vt = vartable_element_get (j, d);
590       fprintf (fp, "'%s'", vt->collab_tform);
591       if (k < display->tcorr2.nsubset-1)
592         ADD_COMMA(fp);
593     }
594     CLOSE_C(fp);
595     ADD_COMMA(fp);
596     /* y variable ranges */
597     OPEN_NAMED_LIST(fp, "yranges");
598     for (k=0; k<display->tcorr2.nsubset; k++) {
599       j = display->tcorr2.subset_vars.els[k];
600       vt = vartable_element_get (j, d);
601       OPEN_C(fp);
602       fprintf (fp, "%.3f, %.3f", vt->lim.min, vt->lim.max);
603       CLOSE_C(fp);
604       if (k < display->tcorr2.nsubset-1)
605         ADD_COMMA(fp);
606     }
607     CLOSE_LIST(fp);  /* tour2x1d, y ranges */
608 
609     CLOSE_LIST(fp);  /* tour2x1d params */
610   }
611   /*  ADD_COMMA(fp); */
612 
613   /* sticky labels */
614   describe_sticky_labels (fp, d, cpanel, gg);
615 
616   /* edges: source, dest, color, glyph type and size, hidden,
617      sticky labels (not adding missing at the moment)
618   */
619   if (d->idTable != NULL && e != (GGobiData *) NULL && e->edge.n > 0) {
620     endpointsd *endpoints;
621     gint a, b;
622 
623     endpoints = resolveEdgePoints(e, d);
624 
625     /* if edges are not displayed, no need to pass them along */
626     if (endpoints &&
627         (display->options.edges_undirected_show_p ||
628          display->options.edges_arrowheads_show_p ||
629 	 display->options.edges_directed_show_p))
630     {
631       ADD_COMMA(fp);
632       OPEN_NAMED_LIST(fp, "edges");
633 
634       for (i=0; i<e->edge.n; i++) {
635         /*
636          * This hides missings if missings_show_p is turned off;
637          * I don't think we're handling missings the same way for
638          * nodes and edges, even in ggobi.
639          */
640         if (!splot_plot_edge (i, d, e, sp, display, gg))
641           continue;
642 
643         OPEN_LIST(fp);  /* one edge */
644 
645         /* source and destination */
646         edge_endpoints_get (i, &a, &b, d, endpoints, e);
647         fprintf (fp, "src=%d,", a);
648         fprintf (fp, "dest=%d,", b);
649 
650         /* color, glyph type, glyph size */
651         fprintf (fp, "color=%d,", e->color_now.els[i]);
652         fprintf (fp, "ltype=%d,", e->glyph_now.els[i].type);
653         fprintf (fp, "lwd=%d,", e->glyph_now.els[i].size);
654 
655         /* hiddenness */
656         fprintf (fp, "hidden=%d",
657           splot_hidden_edge (i, d, e, sp, display, gg));
658 
659         CLOSE_LIST(fp);  /* one edge */
660         if (i < e->edge.n-1)
661           ADD_COMMA(fp);
662       }
663       /* sticky labels */
664       describe_sticky_labels (fp, e, cpanel, gg);
665     }
666     CLOSE_LIST(fp);  /* edges */
667     /*ADD_COMMA(fp); */ ADD_CR(fp);
668   }
669 
670   CLOSE_LIST(fp); /* plot */
671 }
672 
673 void
describe_scatterplot_display(FILE * fp,ggobid * gg,displayd * display,dspdescd * desc)674 describe_scatterplot_display (FILE *fp, ggobid *gg, displayd *display,
675 			      dspdescd *desc)
676 {
677   splotd *sp = (splotd *) display->splots->data;
678 
679   fprintf (fp, "nplots=1");
680   ADD_COMMA(fp); ADD_CR(fp);
681   OPEN_NAMED_LIST(fp, "plots");
682 
683   describe_scatterplot_plot (fp, gg, display, sp, desc,
684     display->cpanel.pmode);
685 
686   CLOSE_LIST(fp);  /* plots */
687 }
688 
689 
690 void
describe_scatmat_display(FILE * fp,ggobid * gg,displayd * display,dspdescd * desc)691 describe_scatmat_display (FILE *fp, ggobid *gg, displayd *display,
692 		      dspdescd *desc)
693 {
694   GList *l;
695   splotd *sp;
696   gint ncols, *cols;
697   ProjectionMode projection;
698   GGobiData *d = display->d;
699   gint i, j, nplotted_vars, *plotted_vars;
700   GtkTableChild *child;
701   GtkWidget *da;
702 
703   cols = (gint *) g_malloc(d->ncols * sizeof(gint));
704   ncols = GGOBI_EXTENDED_DISPLAY_GET_CLASS(display)->plotted_vars_get(display, cols, d, gg);
705 
706   fprintf (fp, "nplots=%d", ncols * ncols);
707   ADD_COMMA(fp); ADD_CR(fp);
708   OPEN_NAMED_LIST(fp, "plots");
709 
710   /* This output relies on the idea that we'll use
711      par(mfcol=, mfrow=) to lay out the plots in composite displays,
712      rather than using splom or any other utility. */
713 
714   plotted_vars = (gint *) g_malloc (d->ncols * sizeof (gint));
715   nplotted_vars =
716     GGOBI_EXTENDED_DISPLAY_GET_CLASS (display)->plotted_vars_get (display,
717       plotted_vars, d, gg);
718 
719   for (i=0; i<nplotted_vars; i++) {
720     for (j=0; j<nplotted_vars; j++) {
721 
722       for (l = (GTK_TABLE (display->table))->children; l; l = l->next) {
723         child = (GtkTableChild *) l->data;
724         if (child->top_attach==i && child->left_attach==j) {
725           da = child->widget;
726           sp = (splotd *) g_object_get_data (G_OBJECT (da), "splotd");
727           projection = (sp->p1dvar != -1) ? P1PLOT : XYPLOT;
728           describe_scatterplot_plot (fp, gg, display, sp, desc, projection);
729           if (i != (nplotted_vars-1) || j != (nplotted_vars-1))
730             ADD_COMMA(fp);
731           break;
732         }
733       }
734     }
735   }
736 
737   CLOSE_LIST(fp);  /* plots */
738   g_free(cols);
739 }
740 
741 
742 void
describe_parcoords_display(FILE * fp,ggobid * gg,displayd * display,dspdescd * desc)743 describe_parcoords_display (FILE *fp, ggobid *gg, displayd *display,
744 		      dspdescd *desc)
745 {
746   GList *l;
747   splotd *sp;
748   gint j, ncols;
749 
750   ncols = g_list_length (display->splots);
751   fprintf (fp, "nplots=%d", ncols);
752   ADD_COMMA(fp); ADD_CR(fp);
753   OPEN_NAMED_LIST(fp, "plots");
754 
755   /* We seem to be working through the plots row-wise, but I don't
756   think that's something we can count on.  I hope we can make use of
757   the axis labels to figure out which plot belongs where.  Otherwise,
758   I'll have to add a position indicator to each plot. */
759 
760   j = 0;
761   for (l = display->splots; l; l = l->next) {
762     sp = (splotd *) l->data;
763     describe_scatterplot_plot (fp, gg, display, sp, desc, P1PLOT);
764     j++;
765     if (j < ncols)
766       ADD_COMMA(fp);
767   }
768 
769   CLOSE_LIST(fp);  /* plots */
770 }
771 
772 
773 void
describe_time_series_display(FILE * fp,ggobid * gg,displayd * display,dspdescd * desc)774 describe_time_series_display (FILE *fp, ggobid *gg, displayd *display,
775 		      dspdescd *desc)
776 {
777   GList *l;
778   splotd *sp;
779   gint ncols;
780 
781   ncols = g_list_length (display->splots);
782 
783   fprintf (fp, "nplots=%d", ncols);
784   ADD_COMMA(fp); ADD_CR(fp);
785   OPEN_NAMED_LIST(fp, "plots");
786 
787   for (l = display->splots; l; l = l->next) {
788     sp = (splotd *) l->data;
789     describe_scatterplot_plot (fp, gg, display, sp, desc, XYPLOT);
790     if (l->next)
791       ADD_COMMA(fp);
792   }
793 
794   CLOSE_LIST(fp);  /* plots */
795 }
796 
797 void
describe_barchart_plot(FILE * fp,ggobid * gg,displayd * display,splotd * sp,dspdescd * desc)798 describe_barchart_plot (FILE *fp, ggobid *gg, displayd *display,
799    splotd *sp, dspdescd *desc)
800 {
801   GGobiData *d = display->d;
802   barchartSPlotd *bsp = GGOBI_BARCHART_SPLOT (sp);
803   vartabled *vtx = vartable_element_get (sp->p1dvar, d);
804   gint i, m, level, counter;
805 
806   OPEN_LIST(fp);  /* plot; unlabelled */
807   if (vtx->vartype == categorical) {
808     if (bsp->bar->is_spine)
809       fprintf (fp, "type='spineplot'");
810     else
811       fprintf (fp, "type='barplot'");
812   } else {
813     fprintf (fp, "type='histogram'");
814   }
815   ADD_COMMA(fp);
816 
817 
818   OPEN_NAMED_LIST(fp, "points");
819   /* x coordinates */
820   OPEN_NAMED_C(fp, "x");
821   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
822     i = d->rows_in_plot.els[m];
823     fprintf (fp, "%g", d->tform.vals[i][sp->p1dvar]);
824     if (m < d->nrows_in_plot-1)
825       ADD_COMMA(fp);
826     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
827   }
828   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
829 
830   /* color */
831   OPEN_NAMED_C(fp, "color");
832   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
833     i = d->rows_in_plot.els[m];
834     fprintf (fp, "%d", d->color_now.els[i]);
835     if (m < d->nrows_in_plot-1)
836       ADD_COMMA(fp);
837     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
838   }
839   CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
840 
841   /* hiddenness */
842   OPEN_NAMED_C(fp, "hidden");
843   for (m=0, counter=1; m<d->nrows_in_plot; m++, counter++) {
844     i = d->rows_in_plot.els[m];
845     fprintf (fp, "%d", d->hidden_now.els[i]);
846     if (m < d->nrows_in_plot-1)
847       ADD_COMMA(fp);
848     if (counter % MAX_PER_ROW == 0) ADD_CR(fp);
849   }
850   CLOSE_C(fp);
851   // ADD_COMMA(fp);
852   ADD_CR(fp);
853 
854   CLOSE_LIST(fp);  /* points */
855   ADD_COMMA(fp);
856   ADD_CR(fp);
857 
858   /* parameters */
859   OPEN_NAMED_LIST(fp, "params");
860   /* Variable name */
861   fprintf (fp, "label='%s',", vtx->collab_tform);
862 
863 
864   if (vtx->vartype == categorical) {
865     gchar *catname;
866 
867     /* level names */
868     OPEN_NAMED_C(fp, "levelnames");
869     for (i = 0; i < bsp->bar->nbins; i++) {
870       level = checkLevelValue (vtx, (gdouble) bsp->bar->bins[i].value);
871       catname = g_strdup_printf ("%s",
872                                  (level ==
873                                   -1) ? "missing" : vtx->level_names[level]);
874       fprintf (fp, "'%s'", catname);
875       if (i < bsp->bar->nbins-1)
876         ADD_COMMA(fp);
877       if (i % MAX_PER_ROW == 0) ADD_CR(fp);
878     }
879     CLOSE_C(fp); ADD_COMMA(fp); ADD_CR(fp);
880 
881     /* level values */
882     OPEN_NAMED_C(fp, "levelvalues");
883     for (i = 0; i < bsp->bar->nbins; i++) {
884       level = checkLevelValue (vtx, (gdouble) bsp->bar->bins[i].value);
885       fprintf (fp, "%d", level);
886       if (i < bsp->bar->nbins-1)
887         ADD_COMMA(fp);
888       if (i % MAX_PER_ROW == 0) ADD_CR(fp);
889     }
890     CLOSE_C(fp);
891     // ADD_COMMA(fp);
892     ADD_CR(fp);
893   } else {
894     /* breaks */
895     OPEN_NAMED_C(fp, "breaks");
896     for (i = 0; i < bsp->bar->nbins; i++) {
897       fprintf (fp, "%.3f", bsp->bar->breaks[i]);
898       if (i < (bsp->bar->nbins-1))
899         ADD_COMMA(fp);
900     }
901     CLOSE_C(fp);
902     // ADD_COMMA(fp);
903     ADD_CR(fp);
904   }
905 
906   CLOSE_LIST(fp);  /* params */
907   // ADD_COMMA(fp);
908   ADD_CR(fp);
909 
910   CLOSE_LIST(fp); /* plot */
911 }
912 
describe_barchart_display(FILE * fp,ggobid * gg,displayd * display,dspdescd * desc)913 void describe_barchart_display (FILE *fp, ggobid *gg, displayd *display,
914 		      dspdescd *desc)
915 {
916   splotd *sp = (splotd *) display->splots->data;
917 
918   fprintf (fp, "nplots=1");
919   ADD_COMMA(fp); ADD_CR(fp);
920   OPEN_NAMED_LIST(fp, "plots");
921 
922   describe_barchart_plot (fp, gg, display, sp, desc);
923 
924   CLOSE_LIST(fp);  /* plots */
925 }
926 
927 
928 void
desc_setup(dspdescd * desc)929 desc_setup (dspdescd *desc)
930 {
931   GtkWidget *entry;
932 
933   entry = (GtkWidget *)
934     g_object_get_data(G_OBJECT(desc->window), "TITLE");
935   if (desc->title) g_free(desc->title);
936   desc->title = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
937 /*
938   entry = (GtkWidget *)
939     g_object_get_data(G_OBJECT(desc->window), "FILENAME");*/
940   if (desc->filename) g_free(desc->filename);
941   //desc->filename = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
942   desc->filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(desc->window));
943 }
944 
945 void
desc_write(PluginInstance * inst)946 desc_write (PluginInstance *inst)
947 {
948   ggobid *gg = inst->gg;
949   dspdescd *desc = dspdescFromInst (inst);
950   FILE *fp;
951   displayd *display = gg->current_display;
952 
953   if (display == (displayd *) NULL) {
954     quick_message ("There is no current display", false);
955     return;
956   }
957 
958   desc_setup (desc);
959 
960   if ((fp = fopen(desc->filename, "w")) == NULL) {
961     gchar *message = g_strdup_printf ("'%s' can not be opened for writing",
962 				      desc->filename);
963     quick_message (message, false);
964     g_free (message);
965     return;
966   }
967 
968   /* Just handle a single display, the current one */
969   OPEN_NAMED_LIST (fp, "display");
970 
971   fprintf (fp, "version='%s',", VERSION);
972 
973   /* describe the colorscheme here, once for all (potential) displays */
974   describe_colorscheme (fp, gg);
975 
976   if (desc->title)
977     fprintf (fp, "title='%s',", desc->title);
978 
979   /* A display could report its own name, but I don't know if it can */
980   if (GGOBI_IS_SCATTERPLOT_DISPLAY(display)) {
981     fprintf (fp, "type='scatterplot',");
982     describe_scatterplot_display (fp, gg, display, desc);
983   } else if (GGOBI_IS_SCATMAT_DISPLAY(display)) {
984     gint ncols, *cols;
985     GGobiData *d = display->d;
986     fprintf (fp, "type='scatmat',");
987     /* ncols: display is symmetric */
988     cols = (gint *) g_malloc(d->ncols * sizeof(gint));
989     ncols = GGOBI_EXTENDED_DISPLAY_GET_CLASS(display)->plotted_vars_get(display, cols, d, gg);
990     fprintf (fp, "ncols = %d,", ncols);
991     g_free(cols);
992     describe_scatmat_display (fp, gg, display, desc);
993   } else if (GGOBI_IS_PAR_COORDS_DISPLAY(display)) {
994     fprintf (fp, "type='parcoords',");
995     fprintf (fp, "ncols = %d,", g_list_length (display->splots));
996     describe_parcoords_display (fp, gg, display, desc);
997   } else if (GGOBI_IS_TIME_SERIES_DISPLAY(display)) {
998     fprintf (fp, "type='timeseries',");
999     fprintf (fp, "ncols = %d,", g_list_length (display->splots));
1000     describe_time_series_display (fp, gg, display, desc);
1001   } else if (GGOBI_IS_BARCHART_DISPLAY(display)) {
1002     fprintf (fp, "type='barchart',");  /* barchart or histogram */
1003     describe_barchart_display (fp, gg, display, desc);
1004   /*
1005     -- is_histogram and is_spine are attributes of the plot, not the
1006        display : sp->bar->is_histogram, etc.
1007     -- this will call describe_barchart_plot
1008     -- other useful attributes: nbins, breaks
1009   */
1010   }
1011 
1012   ADD_COMMA(fp);
1013   ADD_CR(fp);
1014 
1015   /* Add a few booleans describing the display */
1016   fprintf (fp, "showMissing=%d,", display->d->missings_show_p);
1017   fprintf (fp, "showPoints=%d,", display->options.points_show_p);
1018   fprintf (fp, "showDirectedEdges=%d,",
1019     display->options.edges_directed_show_p);
1020   fprintf (fp, "showUndirectedEdges=%d,",
1021     display->options.edges_undirected_show_p);
1022   fprintf (fp, "showArrowheads=%d",
1023     display->options.edges_arrowheads_show_p);
1024 
1025   CLOSE_LIST(fp);
1026   ADD_CR(fp);
1027 
1028   fclose(fp);
1029 
1030   //gtk_widget_hide(desc->window);
1031   /* Put a message in the status bar saying it was done. */
1032 }
1033