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