/*
   File:          ongr.c
   Author:        Andrew W. Moore
   Created:       August 19th 1992

   Description:   Some simple graph-drawing
*/

#include <stdio.h>
#include <math.h>
#include "ongr.h" /* Header for simple graph drawing */

color_string *mk_empty_color_string(void)
{
  color_string *cst = AM_MALLOC(color_string);
  cst -> string = mk_copy_string("");
  cst -> colors = mk_ivec(0);
  return cst;
}

void append_to_color_string(color_string *cst,char *s,int color)
{
  char *new_string = mk_printf("%s%s",cst->string,s);
  int i;

  free_string(cst->string);
  cst->string = new_string;
  for ( i = 0 ; i < (int)strlen(s) ; i++ )
    add_to_ivec(cst->colors,color);
}

int color_string_length(color_string *cst)
{
  return ivec_size(cst->colors);
}

char color_string_char_ref(color_string *cst,int i)
{
  if ( i < 0 || i >= color_string_length(cst) )
    my_error("color_string_ref");
  return cst->string[i];
}

int color_string_color_ref(color_string *cst,int i)
{
  return ivec_ref(cst->colors,i);
}

void ag_print_color_string(double x,double y,color_string *cst)
{
  int old_color = ag_pen_color();
  int this_color = old_color;
  int i;
  for ( i = 0 ; i < color_string_length(cst) ; i++ )
  {
    char c = color_string_char_ref(cst,i);
    int color = color_string_color_ref(cst,i);
    char buff[100];
    if ( color != this_color )
    {
      ag_set_pen_color(color);
      this_color = color;
    }
    sprintf(buff,"%c",c);
    ag_print(x+AG_CHAR_WIDTH*i,y,buff);
  }

  if ( this_color != old_color )
    ag_set_pen_color(old_color);
}

void print_and_shrink_color_string(agbox *agb,color_string *cst)
{
  double x = agbox_top_left_print_coord(agb,XCOMP);
  double y = agbox_top_left_print_coord(agb,YCOMP);
  ag_print_color_string(x,y,cst);
  shrink_agbox_for_printing(agb);
}
 
void free_color_string(color_string *cst)
{
  free_string(cst->string);
  free_ivec(cst->colors);
  AM_FREE(cst,color_string);
}

void color_key_append_to_color_string(color_string *cst,string_array *labels,int index)
{
  char *s = string_array_ref(labels,index);
  if ( s != NULL )
  {
    int color = color_code_to_ag_color(index);
    if ( color_string_length(cst) > 0 )
      append_to_color_string(cst," ",color);

    append_to_color_string(cst,s,color);
  }
}

void color_key_append_to_color_string_special_color(color_string *cst,string_array *labels,int index,int color)
{
  char *s = string_array_ref(labels,index);
  if ( s != NULL )
  {
    if ( color_string_length(cst) > 0 )
      append_to_color_string(cst," ",color);

    append_to_color_string(cst,s,color);
  }
}

int string_length(char *s)
{
  return ( s == NULL ) ? 0 : (int) strlen(s);
}

int string_array_ref_size(string_array *sa,int i)
{
  return string_length(string_array_ref(sa,i));
}

void print_color_key_and_shrink(agbox *agb,string_array *labels)
{
  int num_prints = 0;
  int max_prints = 10;
  int index = 0;
  int chars_in_frame = (int) floor(agbox_width(agb,XCOMP) / AG_CHAR_WIDTH);
  int num_labels = string_array_size(labels);

  while ( index < num_labels && num_prints < max_prints )
  {
    color_string *cst = mk_empty_color_string();
    color_key_append_to_color_string(cst,labels,index);
    index += 1;
    while ( index < num_labels && 
            1 + color_string_length(cst) + string_array_ref_size(labels,index) < chars_in_frame )
    {
      color_key_append_to_color_string(cst,labels,index);
      index += 1;
    }
    if ( color_string_length(cst) > 0 )
    {
      print_and_shrink_color_string(agb,cst);
      num_prints += 1;
    }
    free_color_string(cst);
  }

  if ( index < num_labels )
    print_and_shrink(agb,"...");
}

void print_color_key_and_shrink_special_colors(agbox *agb,string_array *labels,ivec *colors)
{
  int num_prints = 0;
  int max_prints = 10;
  int index = 0;
  int chars_in_frame = (int) floor(agbox_width(agb,XCOMP) / AG_CHAR_WIDTH);
  int num_labels = string_array_size(labels);

  while ( index < num_labels && num_prints < max_prints )
  {
    color_string *cst = mk_empty_color_string();
    color_key_append_to_color_string_special_color(cst,labels,index,ivec_ref(colors,index));
    index += 1;
    while ( index < num_labels && 
            1 + color_string_length(cst) + string_array_ref_size(labels,index) < chars_in_frame )
    {
      color_key_append_to_color_string_special_color(cst,labels,index,ivec_ref(colors,index));
      index += 1;
    }
    if ( color_string_length(cst) > 0 )
    {
      print_and_shrink_color_string(agb,cst);
      num_prints += 1;
    }
    free_color_string(cst);
  }

  if ( index < num_labels )
    print_and_shrink(agb,"...");
}


agbox *map_image_box(map *mp)
{
  return mp->image;
}

agbox *map_inner_box(map *mp)
{
  return mp->inner;
}

agbox *map_outer_box(map *mp)
{
  return mp->outer;
}

double map_ylo(map *mp)
{
  return agbox_ylo(map_image_box(mp));
}

double map_xlo(map *mp)
{
  return agbox_xlo(map_image_box(mp));
}

double map_yhi(map *mp)
{
  return agbox_yhi(map_image_box(mp));
}

double map_xhi(map *mp)
{
  return agbox_xhi(map_image_box(mp));
}

double map_width(map *mp,int comp)
{
  return agbox_width(map_image_box(mp),comp);
}

double map_ref(map *mp,int comp,int hilo)
{
  return agbox_ref(map_image_box(mp),comp,hilo);
}

void map_image_set(map *mp,int comp,int hilo,double v)
{
  agbox_set(map_image_box(mp),comp,hilo,v);
}

double map_inner_ref(map *mp,int comp,int hilo)
{
  return agbox_ref(map_inner_box(mp),comp,hilo);
}

double map_inner_width(map *mp,int comp)
{
  return agbox_width(map_inner_box(mp),comp);
}

double map_outer_ref(map *mp,int comp,int hilo)
{
  return agbox_ref(map_outer_box(mp),comp,hilo);
}

double map_outer_width(map *mp,int comp)
{
  return agbox_width(map_outer_box(mp),comp);
}

map *mk_map(agbox *inner,agbox *outer,agbox *image)
{
  map *mp = AM_MALLOC(map);
  mp -> inner = mk_copy_agbox(inner);
  mp -> outer = mk_copy_agbox(outer);
  mp -> image = mk_copy_agbox(image);
  return mp;
}

void free_map(map *mp)
{
  free_agbox(mp->inner);
  free_agbox(mp->outer);
  free_agbox(mp->image);
  AM_FREE(mp,map);
}

map *mk_map_from_frame_and_image(agbox *ag_frame,agbox *image_frame)
{
#ifdef FIGS_FOR_PAPER
  double x_lo_indent = 100.0;
  double y_lo_indent = 100.0;
  double x_hi_indent = 60.0;
  double y_hi_indent = 20.0;
#else

  double x_lo_indent = real_min(agbox_width(ag_frame,XCOMP)/4,(2 + CH_IN_NUM) * AG_CHAR_WIDTH);
  double x_hi_indent = real_min(agbox_width(ag_frame,XCOMP)/20,AG_CHAR_WIDTH/2);
  double y_lo_indent = real_min(agbox_width(ag_frame,YCOMP)/6,AG_CHAR_HEIGHT * 3.0);
  double y_hi_indent = real_min(agbox_width(ag_frame,YCOMP)/20,AG_CHAR_HEIGHT * 1.5);

#endif

  agbox *inner = mk_agbox(agbox_xlo(ag_frame)+x_lo_indent,
                          agbox_ylo(ag_frame)+y_lo_indent,
                          agbox_xhi(ag_frame)-x_hi_indent,
                          agbox_yhi(ag_frame)-y_hi_indent);
  map *mp = mk_map(inner,ag_frame,image_frame);
  free_agbox(inner);
  return mp;
}

map *mk_map_from_frame_and_limits(agbox *ag_frame,double xlo,double ylo,double xhi,double yhi)
{
  agbox *image = mk_agbox(xlo,ylo,xhi,yhi);
  map *mp = mk_map_from_frame_and_image(ag_frame,image);
  free_agbox(image);
  return mp;
}

double map_i2a(map *mp,double v,int component)
{
  double z = agbox_abs2rel(map_image_box(mp),v,component);
  double a = agbox_rel2abs(map_inner_box(mp),z,component);
  return a;
}

double map_i2a_x(map *mp,double x)
{
  return map_i2a(mp,x,XCOMP);
}

double map_i2a_y(map *mp,double y)
{
  return map_i2a(mp,y,YCOMP);
}

void ongr_line(map *mp,double x1,double y1,double x2,double y2)
{
  ag_line(map_i2a_x(mp,x1),map_i2a_y(mp,y1),map_i2a_x(mp,x2),map_i2a_y(mp,y2));
}

void ongr_box(map *mp,double x1,double y1,double x2,double y2)
{
  ag_box(map_i2a_x(mp,x1),map_i2a_y(mp,y1),map_i2a_x(mp,x2),map_i2a_y(mp,y2));
}

void ongr_rectangle(map *mp,double x1,double y1,double x2,double y2)
{
  ag_rectangle(map_i2a_x(mp,x1),map_i2a_y(mp,y1),map_i2a_x(mp,x2),map_i2a_y(mp,y2));
}

void ongr_mark(map *mp,double x,double y,int marktype)
{
  ag_mark(map_i2a_x(mp,x),map_i2a_y(mp,y),marktype);
}

void ongr_print(map *mp,double x,double y,char *string)
{
  ag_print(map_i2a_x(mp,x),map_i2a_y(mp,y),string);
}

dyv *mk_marks(int comp,double start,double end,double ag_length)
{
  double lo,hi,delta;
  int i = 0;
  dyv *marks = mk_dyv(0);
  double v;
  double min_ag_gap_between_marks = (comp == XCOMP) ? 60.0 : 25.0;
  sensible_limits(start,end,&lo,&hi,&delta);
  
  while ( i < 10 && ag_length * delta / (hi - lo) < min_ag_gap_between_marks )
  {
    delta *= 2.0;
    i += 1;
  }

  v = lo;
  i = 0;

  while ( v <= end && i < 200 )
  {
    if ( v >= start )
      add_to_dyv(marks,v);
    i += 1;
    v = lo + i * delta;
  }

  return marks;
}

void compute_axis_basic_details(map *mp,int comp,
                                double *start_x,double *start_y,double *end_x,double *end_y)
{
  *start_x = map_xlo(mp);
  *start_y = map_ylo(mp);
  *end_x = (comp == YCOMP) ? map_xlo(mp) : map_xhi(mp);
  *end_y = (comp == YCOMP) ? map_yhi(mp) : map_ylo(mp);
}

void compute_axis_real_mark_details(map *mp,int comp,dym **r_mark_locs,
                                    string_array **r_mark_names,
                                    double *r_rel_agx,double *r_rel_agy)
{
  double start = map_ref(mp,comp,LO);
  double end = map_ref(mp,comp,HI);
  double ag_length = map_inner_width(mp,comp);
  dyv *marks = mk_marks(comp,start,end,ag_length);
  int num_marks = dyv_size(marks);
  int i;

  *r_mark_locs = mk_dym(num_marks,2);
  *r_mark_names = mk_string_array(0);

  for ( i = 0 ; i < num_marks ; i++ )
  {
    char mark[100];
    double v = dyv_ref(marks,i);

    if ( comp == XCOMP )
    {
      dym_set(*r_mark_locs,i,0,v);
      dym_set(*r_mark_locs,i,1,map_ylo(mp));
    }
    else
    {
      dym_set(*r_mark_locs,i,0,map_xlo(mp));
      dym_set(*r_mark_locs,i,1,v);
    }

    sprintf(mark,"%g", fabs(v) < 1.0e-15 ? 0.0 : v); /*fix bad rounding*/
    add_to_string_array(*r_mark_names,mark);
  }

  if ( comp == YCOMP )
  {
#ifdef FIGS_FOR_PAPER
    *r_rel_agx = -100.0;
    *r_rel_agy = -0.5 * AG_CHAR_HEIGHT;
#else
    *r_rel_agx = -(CH_IN_NUM) * AG_CHAR_WIDTH;
    *r_rel_agy = -0.5 * AG_CHAR_HEIGHT;
#endif
  }
  else
  {
    *r_rel_agx = -CH_IN_NUM/2.0 * AG_CHAR_WIDTH;
    *r_rel_agy = -2 * AG_CHAR_HEIGHT;
  }

  free_dyv(marks);
}

void ag_vertical_cross(double x,double y,double radius)
{
  ag_line(x-radius,y,x+radius,y);
  ag_line(x,y-radius,x,y+radius);
}

void draw_axis_marks(map *mp,dym *mark_locs,string_array *mark_names,
                     double rel_agx,double rel_agy)
{
  int i;

  for ( i = 0 ; i < dym_rows(mark_locs) ; i++ )
  {
    char *mark = string_array_ref(mark_names,i);
    if(mark)
    {
      double x = dym_ref(mark_locs,i,0);
      double y = dym_ref(mark_locs,i,1);
      double agx = map_i2a_x(mp,x);
      double agy = map_i2a_y(mp,y);

      ag_set_pen_color(AG_RED);
      ag_vertical_cross(agx,agy,real_min(6.0,0.05*agbox_min_width(map_inner_box(mp))));
      agx += rel_agx;
      agy += rel_agy;
      ag_set_pen_color(AG_BLACK);
      ag_print(agx,agy,mark);
    }
  }
}

void draw_map_real_axis(map *mp,int comp)
{
  int color = ag_pen_color();
  double start_x,start_y,end_x,end_y;
  double rel_agx,rel_agy;
  dym *mark_locs;
  string_array *mark_names;

  ag_set_pen_color(AG_RED);

  compute_axis_basic_details(mp,comp,&start_x,&start_y,&end_x,&end_y);
  compute_axis_real_mark_details(mp,comp,&mark_locs,&mark_names,&rel_agx,&rel_agy);

  ongr_line(mp,start_x,start_y,end_x,end_y);

  draw_axis_marks(mp,mark_locs,mark_names,rel_agx,rel_agy);

  ag_set_pen_color(color);
  free_dym(mark_locs);
  free_string_array(mark_names);
}

void compute_axis_hist_mark_details(map *mp,int comp,string_array *mark_names,
                                    dym **r_mark_locs,double *r_rel_agx,double *r_rel_agy)
{
  int i;
  int num_marks = string_array_size(mark_names);

  *r_mark_locs = mk_dym(num_marks,2);

  for ( i = 0 ; i < num_marks ; i++ )
  {
    double z = (i + 0.5) / num_marks;
    double v = map_ref(mp,comp,LO) + map_width(mp,comp) * z;
    
    if ( comp == XCOMP )
    {
      dym_set(*r_mark_locs,i,0,v);
      dym_set(*r_mark_locs,i,1,map_ylo(mp));
    }
    else
    {
      dym_set(*r_mark_locs,i,0,map_xlo(mp));
      dym_set(*r_mark_locs,i,1,v);
    }
  }

  if ( comp == YCOMP )
  {
    *r_rel_agx = -(CH_IN_NUM) * AG_CHAR_WIDTH;
    *r_rel_agy = -0.5 * AG_CHAR_HEIGHT;
  }
  else
  {
    *r_rel_agx = -CH_IN_NUM/2.0 * AG_CHAR_WIDTH;
    *r_rel_agy = -2 * AG_CHAR_HEIGHT;
  }
}


void draw_map_hist_axis(map *mp,int comp,string_array *mark_names)
{
  int color = ag_pen_color();
  double start_x,start_y,end_x,end_y;
  double rel_agx,rel_agy;
  dym *mark_locs;

  ag_set_pen_color(AG_RED);

  compute_axis_basic_details(mp,comp,&start_x,&start_y,&end_x,&end_y);
  compute_axis_hist_mark_details(mp,comp,mark_names,&mark_locs,&rel_agx,&rel_agy);

  ongr_line(mp,start_x,start_y,end_x,end_y);

  draw_axis_marks(mp,mark_locs,mark_names,rel_agx,rel_agy);

  ag_set_pen_color(color);
  free_dym(mark_locs);
}


void draw_map_label(map *mp,int comp,char *label)
{
  double x,y;
  check_comp(comp);
  if ( comp == YCOMP )
  {
    x = map_outer_ref(mp,XCOMP,LO) + AG_CHAR_WIDTH/2.0;
    y = map_outer_ref(mp,YCOMP,HI) - AG_CHAR_HEIGHT;
  }
  else
  {
#ifdef FIGS_FOR_PAPER
    x = 200.0;
#else
    x = map_outer_ref(mp,XCOMP,HI) - AG_CHAR_WIDTH * (int)strlen(label);
#endif
    y = map_outer_ref(mp,YCOMP,LO) + AG_CHAR_HEIGHT/2.0;
  }
  ag_print(x,y,label);
}

void maybe_draw_map_label(map *mp,int comp,char *label)
{
  if ( label != NULL )
    draw_map_label(mp,comp,label);
}

void draw_agbox_rectangle(agbox *agb)
{
  ag_rectangle(agbox_xlo(agb),agbox_ylo(agb),
               agbox_xhi(agb),agbox_yhi(agb));
}

void draw_map_real_axes(map *mp)
{
  int color = ag_pen_color();
  ag_set_pen_color(AG_GREEN);
  draw_agbox_rectangle(map_outer_box(mp));
  ag_set_pen_color(color);
  draw_map_real_axis(mp,XCOMP);
  draw_map_real_axis(mp,YCOMP);
}

/* marktype can be -1 meaning "just join...no special marks" */
void plot_graphic_in_frame(map *mp,dyv *x,dyv *y,bool join,int marktype,int amut_col)
{
  int i;
  double last_x = -77.7;
  double last_y = -77.7;
  int color = ag_pen_color();
  int size = dyv_size(x);

  ag_set_pen_color(amut_col);

  for ( i = 0 ; i < size ; i++ )
  {
    double tx = dyv_ref(x,i);
    double ty = dyv_ref(y,i);

    if ( marktype >= 0 )
      ongr_mark(mp,tx,ty,marktype);

    if ( join && i > 0 )
      ongr_line(mp,last_x,last_y,tx,ty);

    last_x = tx;
    last_y = ty;
  }
  ag_set_pen_color(color);
}

int Amut_cols[] = { AG_BLUE , AG_RED , AG_BLACK , AG_GREEN , AG_PURPLE ,
		  AG_CYAN , AG_GRAY , AG_DARKGREEN , AG_MAGENTA , AG_YELLOW ,
		  AG_DARKRED , AG_OLIVE , AG_DARKBLUE };

/* Returns an ag_color associated with code. code can be as large as
   you like but after about 12, it wraps around. Use this if you want, say,
   different bars in a chart to have different colors. You simply use
   color_code_to_ag_color(i) as the color of the i'th bar. */
int color_code_to_ag_color(int color_code)
{
  int numcols = sizeof(Amut_cols)/sizeof(int);
  int index = color_code % numcols;
  return Amut_cols[index];
}

void ongr_framed_box(map *mp,double x1,double y1,double x2,double y2,int col)
{
  int old_col = ag_pen_color();
  ag_set_pen_color(col);
  ongr_box(mp,x1,y1,x2,y2);
  ag_set_pen_color(AG_BLACK);
  ongr_rectangle(mp,x1,y1,x2,y2);
  ag_set_pen_color(old_col);
}
void ongr_unframed_box(map *mp,double x1,double y1,double x2,double y2,int col)
{
  int old_col = ag_pen_color();
  ag_set_pen_color(col);
  ongr_box(mp,x1,y1,x2,y2);
  ag_set_pen_color(old_col);
}

/* Draws a histogram with N bars where N = dym_rows(freqs)
   Each bar is compartmented into K subbars, on top of each other, where
   K = dym_cols(freqs) and the j'th subcomponent of the i'th bar has
   height = dym_ref(freqs,i,j) and is on top of the j-1'th subcomponent. 
   The i'th bar is centered on x=xlo + (i+0.5) * (xhi - xlo) / num_bars */
void ongr_plot_hist(map *mp,dym *freqs,bool ratio)
{
  int i;
  int num_bars = dym_rows(freqs);
  int num_classes = dym_cols(freqs);
  double xlo = map_xlo(mp);
  double xhi = map_xhi(mp);
  double bar_width = 0.9 * (xhi - xlo) / num_bars;

  for ( i = 0 ; i < num_bars ; i++ )
  {
    double xmid = xlo + (i + 0.5) * (xhi - xlo) / num_bars;
    double x1 = xmid - bar_width/2;
    double x2 = xmid + bar_width/2;
    int j;
    double sumy = 0.0;
    double total_sum_y = real_max(1e-5,dym_sum_row(freqs,i));

    for ( j = 0 ; j < num_classes ; j++ )
    {
      double y1 = sumy;
      double dy = dym_ref(freqs,i,j) / ((ratio) ? (total_sum_y/100.0) : 1.0);
      double y2 = sumy + dy;
      int amut_col = color_code_to_ag_color(j);
      ongr_framed_box(mp,x1,y1,x2,y2,amut_col);
      sumy = y2;
    }
  }
}

/* ARTUR: Draws the grid described in imat (just like a
          bitmap). It's like a quilt of little squares scaled
          so that the (i,j)'th square has color im[i][j] */
/*
  Preconditions: 
   imat_rows(im)>0, imat_cols(im)>0, 
   dyv_size(xtics)==imat_cols(im)+1, dyv_ref(xtics,i) monotonically
     nondecreasing with i
   dyv_size(ytics)==imat_rows(im)+1, dyv_ref(ytics,i) monotonically
     nondecreasing with i
   ideally, -1 =< imat_ref(im,i,j) <= (whatever the max color id is)
     (-1 represents transparent entries)
*/    
void ongr_render_imat(map *mp, imat *im, dyv *xtics, dyv *ytics)
{

  int nx = imat_cols(im);
  int ny = imat_rows(im);
  if( nx <= 0 || ny <= 0 )
    my_error("ongr_render_imat: invalid imat dimensions");
  else if( xtics != NULL && dyv_size(xtics) != (nx+1) )
    my_errorf("ongr_render_imat: dyv_size(xtics)=%d, should be %d",dyv_size(xtics),nx+1);
  else if( ytics != NULL && dyv_size(ytics) != (ny+1) )
    my_errorf("ongr_render_imat: dyv_size(ytics)=%d, should be %d",dyv_size(ytics),ny+1);
  else
  {
    bool free_xtics = FALSE;
    bool free_ytics = FALSE;
    double xlo = map_xlo(mp);
    double xhi = map_xhi(mp);
    double ylo = map_ylo(mp);
    double yhi = map_yhi(mp);
    double x1, x2, y1, y2;
    double ticlo, tichi;
    int i,j;
    int col;
    if( xtics == NULL )
    {
      xtics = mk_default_tics_dyv( xlo, xhi, nx );
      free_xtics = TRUE;
    }
    if( ytics == NULL )
    {
      ytics = mk_default_tics_dyv( ylo, yhi, ny );
      free_ytics = TRUE;
    }
    for(i=0;i<nx;i++)
    {
      ticlo = dyv_ref(xtics,i);
      tichi = dyv_ref(xtics,i+1);
      if( tichi > xlo && ticlo < xhi )
      {
        bool keep_y_going = FALSE;
        x1 = (ticlo>=xlo) ? ticlo : xlo ;
        x2 = (tichi<=xhi) ? tichi : xhi ;
        for(j=0;j<ny;j++)
        {
          if( !keep_y_going )
            ticlo = dyv_ref(ytics,j);
          tichi = dyv_ref(ytics,j+1);
          if( tichi > ylo && ticlo < yhi )
          {            
            col = imat_ref(im,j,i);
            if( (j+1)<ny && imat_ref(im,j+1,i)==col )
              keep_y_going = TRUE;
            else
            {
              keep_y_going = FALSE;
              if( col >= 0 ) /* negative entries are rendered transparent! */
              {
                y1 = (ticlo>=ylo) ? ticlo : ylo ;
                y2 = (tichi<=yhi) ? tichi : yhi ;
                ongr_unframed_box(mp,x1,y1,x2,y2,col);
              }
            }
          }
        }
      }
     
    }
    if( free_xtics )
    {
      free_dyv(xtics);
      xtics = NULL;
    }
    if( free_ytics )
    {
      free_dyv(ytics);
      ytics = NULL;
    }
  }
  return;
}

/*------- these two below are here just for the debugging purposes ------- */
map *mk_stupid_map(void)
{
  agbox *f= mk_agbox(0.0,0.0,512.0,512.0);
  map *m = mk_map_from_frame_and_limits(f,0.0,0.0,512.0,512.0);
  free_agbox(f);
  return(m);
}

void really_render_stupid_imat(imat *im)
{
  map *m = mk_stupid_map();
  /* agbox *ag = mk_agbox(0.0,0.0,512.0,512.0); */
  ongr_render_imat(m,im,NULL,NULL);
  free_map(m);
  /* free_agbox(ag); */
  return;
}
