MUSE Pipeline Reference Manual  2.1.1
muse_geo_plot.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2013-2014 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #include <muse.h>
23 #include <cairo.h>
24 #include <cairo-pdf.h>
25 #include <string.h>
26 
27 /*----------------------------------------------------------------------------*/
57 /*----------------------------------------------------------------------------*/
58 
61 #define PRINT_USAGE(rc) \
62  fprintf(stderr, "Usage: %s [ -f format ] [ -s xscale yscale ] " \
63  "GEOMETRY_TABLE OUTPUT_PLOT\n", argv[0]); \
64  cpl_end(); return (rc);
65 
66 int main(int argc, char **argv)
67 {
68  cpl_init(CPL_INIT_DEFAULT);
70 
71  if (argc <= 2) {
72  /* filename is needed at least */
73  PRINT_USAGE(1);
74  }
75 
76  /* argument processing */
77  char *tiname = NULL, /* input table */
78  *oname = NULL; /* output plot */
79  enum eformats {
80  PLOT_FORMAT_PDF = 0,
81  PLOT_FORMAT_PNG
82  };
83  unsigned char oformat = PLOT_FORMAT_PDF;
84  double xscale = 4.,
85  yscale = 4.;
86  int i;
87  for (i = 1; i < argc; i++) {
88  if (strncmp(argv[i], "-f", 3) == 0) {
89  /* skip to next arg to get start value */
90  i++;
91  if (i < argc) {
92  if (!strncmp(argv[i], "pdf", 4)) {
93  oformat = PLOT_FORMAT_PDF;
94  } else if (!strncmp(argv[i], "png", 4)) {
95  oformat = PLOT_FORMAT_PNG;
96  } else {
97  PRINT_USAGE(3);
98  }
99  } else {
100  PRINT_USAGE(2);
101  }
102  } else if (strncmp(argv[i], "-s", 3) == 0) {
103  if (++i + 1 < argc) {
104  xscale = atof(argv[i++]);
105  yscale = atof(argv[i]);
106  if (xscale <= 0 || yscale <= 0) {
107  PRINT_USAGE(5);
108  }
109  } else {
110  PRINT_USAGE(4);
111  }
112  } else if (strncmp(argv[i], "-", 1) == 0) { /* unallowed options */
113  PRINT_USAGE(9);
114  } else {
115  if (tiname && oname) {
116  break; /* we have the required name, skip the rest */
117  }
118  if (!tiname) {
119  tiname = argv[i]; /* set the name for the input table */
120  } else {
121  oname = argv[i]; /* set the name for the output plot */
122  }
123  }
124  } /* for i (all arguments) */
125  if (!tiname) {
126  PRINT_USAGE(1);
127  }
128 
129  cpl_table *table = cpl_table_load(tiname, 1, 1);
130  if (!table) {
131  PRINT_USAGE(10);
132  }
133  /* check the critical table columns */
134  if (!cpl_table_has_column(table, MUSE_GEOTABLE_X) ||
135  !cpl_table_has_column(table, MUSE_GEOTABLE_Y) ||
136  !cpl_table_has_column(table, MUSE_GEOTABLE_WIDTH) ||
137  !cpl_table_has_column(table, MUSE_GEOTABLE_ANGLE)) {
138  cpl_table_delete(table);
139  PRINT_USAGE(11);
140  }
141 
142  /* extrema for the size calculation and translation, with some safety margin */
143  double wmax = cpl_table_get_column_max(table, MUSE_GEOTABLE_WIDTH),
144  xmin = cpl_table_get_column_min(table, MUSE_GEOTABLE_X) - wmax / 2.,
145  ymin = cpl_table_get_column_min(table, MUSE_GEOTABLE_Y) - 2,
146  xmax = cpl_table_get_column_max(table, MUSE_GEOTABLE_X) + wmax / 2.,
147  ymax = cpl_table_get_column_max(table, MUSE_GEOTABLE_Y) + 2,
148  sx = xmax - xmin + 1,
149  sy = ymax - ymin + 1;
150  printf("Using scaling of %.3f in x- and %.3f in y-direction\n", xscale, yscale);
151  double xt = -xmin,
152  yt = -ymax;
153  printf("Translating coordinates by %.3f in x- and %.3f in y-direction\n "
154  "(extrema: %f / %f ... %f / %f)\n", xt, yt, xmin, ymin, xmax, ymax);
155 
156  /* create the cairo objects */
157  cairo_status_t rc = CAIRO_STATUS_SUCCESS;
158  cairo_surface_t *cs;
159  if (oformat == PLOT_FORMAT_PDF) { /* PDF surface and output */
160  cs = cairo_pdf_surface_create(oname, xscale * sx, yscale * sy);
161  rc = cairo_surface_status(cs);
162  if (rc != CAIRO_STATUS_SUCCESS) {
163  fprintf(stderr, "opening PDF (\"%s\") returned %d!\n", oname, rc);
164  rc = 50;
165  } else {
166  fprintf(stdout, "writing PDF to \"%s\"\n", oname);
167  }
168  } else { /* image surface and PNG output */
169  cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
170  xscale * sx, yscale * sy);
171  }
172  cairo_t *cr = cairo_create(cs);
173  /* fill with greyish background */
174  cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
175  cairo_paint(cr);
176  /* set up scaling and origin */
177  cairo_scale(cr, xscale, -yscale);
178  cairo_translate(cr, xt, yt);
179 #if 0 /* coordinate transform debugging */
180  cairo_matrix_t *cm = cpl_calloc(1, sizeof(cairo_matrix_t));
181  cairo_get_matrix(cr, cm);
182  cairo_status_t cstat = cairo_status(cr);
183  fprintf(stderr, "cm = %p, cstat = %d/%s, size is %f,%f\n",
184  cm, cstat, cairo_status_to_string(cstat), xscale * sx, yscale * sy);
185  double xtt = xmin, ytt = ymin + 2;
186  cairo_matrix_transform_point(cm, &xtt, &ytt);
187  fprintf(stderr, "%f,%f is transformed to %f,%f\n", xmin, ymin + 2, xtt, ytt);
188  xtt = xmin, ytt = ymax - 2;
189  cairo_matrix_transform_point(cm, &xtt, &ytt);
190  fprintf(stderr, "%f,%f is transformed to %f,%f\n", xmin, ymax - 2, xtt, ytt);
191  xtt = xmax, ytt = ymin + 2;
192  cairo_matrix_transform_point(cm, &xtt, &ytt);
193  fprintf(stderr, "%f,%f is transformed to %f,%f\n", xmax, ymin + 2, xtt, ytt);
194  xtt = xmax, ytt = ymax - 2;
195  cairo_matrix_transform_point(cm, &xtt, &ytt);
196  fprintf(stderr, "%f,%f is transformed to %f,%f\n", xmax, ymax - 2, xtt, ytt);
197  cpl_free(cm);
198 #endif
199 
200  /* mark the origin (x,y) = (0,0) */
201  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
202  cairo_save(cr);
203  cairo_move_to(cr, -1000., 0.);
204  cairo_rel_line_to(cr, +5000, 0.);
205  cairo_scale(cr, 1., 1. / yscale); /* stroke 1 pixel high */
206  cairo_stroke(cr);
207  cairo_restore(cr);
208  cairo_save(cr);
209  cairo_move_to(cr, 0., -1000);
210  cairo_rel_line_to(cr, 0., +5000);
211  cairo_scale(cr, 1. / xscale, 1.); /* stroke 1 pixel wide */
212  cairo_stroke(cr);
213  cairo_restore(cr);
214 #if 0 /* mark origin with a bit dot */
215  cairo_save(cr);
216  cairo_scale(cr, 1. / xscale, 1. / yscale);
217  cairo_set_source_rgb(cr, 0.0, 0.0, 0.9);
218  cairo_arc(cr, 0, 0, 5., 0, CPL_MATH_2PI);
219  cairo_fill(cr);
220  cairo_restore(cr);
221 #endif
222 
223  /* loop through all table rows and draw the stuff */
224  int n = cpl_table_get_nrow(table);
225  for (i = 0; i < n; i++) {
226  double x = cpl_table_get(table, MUSE_GEOTABLE_X, i, NULL),
227  y = cpl_table_get(table, MUSE_GEOTABLE_Y, i, NULL),
228  width = cpl_table_get(table, MUSE_GEOTABLE_WIDTH, i, NULL),
229  angrad = cpl_table_get(table, MUSE_GEOTABLE_ANGLE, i, NULL)
230  * CPL_MATH_RAD_DEG;
231  unsigned short ifu = cpl_table_get_int(table, MUSE_GEOTABLE_FIELD, i, NULL);
232  if ((ifu - 0) % 3 == 0) { /* e.g. IFU 21 */
233  cairo_set_source_rgba(cr, 0.2, 0.2, 0.4, 0.5); /* blueish-grey */
234  } else if ((ifu - 1) % 3 == 0) { /* e.g. IFU 22 */
235  cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.5);
236  } else if ((ifu - 2) % 3 == 0) { /* e.g. IFU 23 */
237  cairo_set_source_rgba(cr, 1.0, 0.843, 0.0, 0.5); /* gold = #FFD700 */
238  } else {
239  cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.5);
240  }
241 #if 0
242  printf("ifu %hu slicesky %hu angle %f\n",
243  ifu, cpl_table_get_int(table, MUSE_GEOTABLE_SKY, i, NULL),
244  angrad * CPL_MATH_DEG_RAD);
245 #endif
246  /* in the cairo rectangle function, x/y define the top left corner! */
247  cairo_save(cr);
248  cairo_translate(cr, x, y);
249  cairo_rotate(cr, angrad);
250  cairo_rectangle(cr, -width / 2., -0.5, width, 1.);
251  cairo_fill(cr);
252  /* Mark the reference slice. We want a really fine line, so this doesn't *
253  * work with cairo_rectangle() function, but we need to draw vertical *
254  * and horizontal lines separately, with different linewidths. */
255  if (y == 0.0) {
256  cairo_set_source_rgba(cr, 0.0, 0.0, 0.9, 0.8);
257  cairo_move_to(cr, - width / 2., - 0.5);
258  cairo_set_line_width(cr, 1. / yscale);
259  cairo_rel_line_to(cr, width, 0.);
260  cairo_set_line_width(cr, 1. / xscale);
261  cairo_rel_line_to(cr, 0., 1.);
262  cairo_set_line_width(cr, 1. / yscale);
263  cairo_rel_line_to(cr, -width, 0.);
264  cairo_close_path(cr);
265  cairo_stroke(cr);
266  } /* if y == 0.0 (reference slice) */
267  cairo_restore(cr);
268  } /* for i (all table rows) */
269 
270  if (oformat == PLOT_FORMAT_PNG) {
271  cairo_surface_write_to_png(cs, oname);
272  if (rc != CAIRO_STATUS_SUCCESS) {
273  fprintf(stderr, "writing PNG (\"%s\") returned %d!\n", oname, rc);
274  rc = 50;
275  } else {
276  fprintf(stdout, "written PNG to \"%s\"\n", oname);
277  }
278  } /* if PNG */
279  cairo_destroy(cr);
280  cairo_surface_destroy(cs);
281  cairo_debug_reset_static_data();
282  cpl_table_delete(table);
283  cpl_errorstate_dump(0,0,0);
284  cpl_memory_dump();
285  cpl_end();
286  return rc;
287 }
288 
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.