/*
   File:        mapshape.h
   Author:      Andrew W. Moore
   Created:     Mon Mar 22 05:44:03 EST 1999
   Description: Header for Density Map

   Copyright 1999, The Auton Lab
*/


#ifndef MAPSHAPE_H
#define MAPSHAPE_H
#include "amgr.h"
#include "imat.h"
#include "command.h"
#include "hrect.h"
#include "agbox.h"
#include "utils.h"

typedef struct mapshape
{
  hrect *data_bound;
  hrect *ag_bound;
  int agrows;
  int agcols;
} mapshape;

mapshape *mk_default_mapshape(int size);

void fprintf_mapshape(FILE *s,char *m1,mapshape *x,char *m2);

void pmapshape(mapshape *x);

/* What's a distance metric?

   In this code we assume that the squared distance(point1,point2) =

     M-1
     ____
     \       point1[i] - point2[i]
      \    ( --------------------- )^2
      /            metric[i]
     /___
     i=0
*/

dyv *mk_default_metric_for_hrect(hrect *hr);

/* Given that the data is distributed so that hr is its bounding box,
   this function makes a reasonable distance metric for it.

   all_equal_metric TRUE means metric[i] = 1.0
   all_equal_metric FALSE means metric[i] = width_of_ith_dimension

   MAKES and returns the metric. Eventually someone will have to free
   it with free_dyv(metric) */
dyv *mk_metric_for_hrect(hrect *hr,bool all_equal_metric);

/* PRE: Two dimensional */
hrect *mk_ag_bounds_for_metric_and_bounding_box(dyv *metric,hrect *hr);

mapshape *mk_mapshape_for_drawing(dyv *metric,hrect *bounds);

mapshape *mk_mapshape_from_hrect(hrect *bounds);

mapshape *mk_mapshape_for_comparing(dyv *metric,hrect *bounds);

mapshape *mk_copy_mapshape(mapshape *ms);

void free_mapshape(mapshape *ms);

bool mapshape_matches_dmap(mapshape *ms,dym *dmap);

void dym_add_constant(dym *dmap,double delta);

void normalize_dmap(dym *dmap);

void mapshape_rowcol_to_datapoint(mapshape *ms,int row,int col,
                                  double *r_x,double *r_y);

void mapshape_rowcol_to_agcoords(mapshape *ms,int row,int col,
				 double *r_x,double *r_y);

void mapshape_agcoord_to_rowcol(mapshape *ms,double x,double y,
				int *r_row,int *r_col);

void mapshape_datapoint_to_rowcol(mapshape *ms,double x,double y,
				int *r_row,int *r_col);

void mapshape_datapoint_to_agcoords(mapshape *ms,double x,double y,
				    double *r_agx,double *r_agy);

void mapshape_agcoords_to_datapoint(mapshape *ms,double agx,double agy,
				    double *r_x,double *r_y);

dyv *mk_datapoint_from_rowcol(mapshape *ms,int row,int col);

dym *mk_dmap_dym(mapshape *ms);

imat *mk_agmap_from_dmap_and_thresh(dym *dmap,double thresh);

dyv *mk_dmap_dyv_from_all_dym_rows(dym *x);

double dmap_frac_to_thresh(dym *dmap,double frac);

imat *mk_agmap_from_dmap_and_frac(dym *dmap,double frac);

void render_agmap(mapshape *ms,imat *agmap);

void render_dmap(mapshape *ms,dym *dmap,int dmap_type,double frac);

void regular_render_dmap(mapshape *ms,dym *dmap,double frac);

void animate_dmap(mapshape *ms,dym *dmap);

dym *mk_dmap_from_filename(char *fname);

void save_dmap(char *fname,dym *dmap);

dyv *mk_cumulative_dyv(dyv *v);

/* PRE: dyv is sorted in ascending order.
   POST: dyv_ref(dv,result) <= x and dyv_ref(dv,result+1) >= x if x <
         dyv_max(dv).
         if ( x >= dyv_max(dv) then result = dyv_size(dv)-1.
*/
int sorted_dyv_search(dyv *dv,double x);
    
int index_from_cumulative(dyv *c);

dym *mk_generate_x_from_dmap(mapshape *ms,dym *dmap,int num_points);

void save_dmap_sample(mapshape *ms,char *fname,dym *dmap,int num_points);

void smooth_dmap(dym *dmap);

dyv *mk_dmap_dyv_from_mouse(mapshape *ms);

void ag_dmap_dyv_dot(mapshape *ms,dyv *x);

void ag_dmap_dyv_line(mapshape *ms,dyv *x1,dyv *x2);

dym *mk_dmap_from_data(mapshape *ms,dym *data);

dym *mk_dmap_from_smoothed_data(mapshape *ms,dym *data,int num_smooths);

void score_dmap(dym *dmap,dym *true_dmap,
		double *r_sum_abs_prob_diff,
		double *r_sum_sqd_prob_diff,
		double *r_kl_divergence,
		double *r_sum_true_entropy);

double dmap_kl_score(dym *dmap,dym *true_dmap);

void report_score_dmap(dym *dmap,dym *true_dmap);

void rsd_help(dym *dmap,dym *true_dmap,char *message);

int best_grid_dmap_num_smooths(mapshape *ms,dym *true_dmap,dym *x);

void compare_score_dmap(mapshape *ms,dym *dmap,dym *true_dmap,dym *x);

hrect *mk_hrect_2(double xlo,double ylo,double xhi,double yhi);

hrect *mk_hrect_defined_by_dmap_indexes(mapshape *ms,
					int ilo,int jlo,int ihi,int jhi);

/********** DMAP TYPES ***********/

int num_dmap_types(void);

char *dmap_type_to_name(int dmap_type);

/* Returns -1 if no such dmap type */
int name_to_dmap_type(char *name);

int dmap_type_from_args(char *key,int argc,char *argv[],int default_dmap_type);

int dmap_type_from_command(command *c,char *key,int default_dmap_type);

dyv *mk_sorted_dmap_dyv_from_all_dym_rows(dym *dmap);

dyv *mk_sensible_dmap_threshes(dym *dmap,ivec **r_colors);

imat *mk_color_agmap_from_dmap(dym *dmap,dyv *threshes,ivec *colors);

void render_dmap_using_color(mapshape *ms,dym *dmap,dyv *dmap_threshes,
			     ivec *colors);

void render_color_dmap(mapshape *ms,dym *dmap);

imat *mk_locmax_binmap(dym *dmap);

imat *mk_ridge_binmap(dym *dmap);

void smooth_binmap(imat *binmap);

void shrink_binmap_delta(imat *binmap,int di,int dj);

void shrink_binmap(imat *binmap);

void insert_binmap_into_agmap(imat *agmap,imat *binmap,int agcol);

void render_peak_dmap(mapshape *ms,dym *dmap);

void render_ridge_dmap(mapshape *ms,dym *dmap);

void render_dmap(mapshape *ms,dym *dmap,int dmap_type,double frac);

#define REGULAR_DMAP 0
#define ANIMATE_DMAP 1
#define COLOR_DMAP 2
#define PEAK_DMAP 3
#define RIDGE_DMAP 4
#define GRAYSCALE_DMAP 5
#define GOOD_DMAP 6
#define NUM_DMAP_TYPES 7

void ms_dot(mapshape *ms,double x,double y);

void ms_mark(mapshape *ms,double x,double y,int marktype);

void ms_line(mapshape *ms,double x1,double y1,double x2,double y2);

void ms_rectangle(mapshape *ms,double x1,double y1,double x2,double y2);

void ms_hrect(mapshape *ms,hrect *hr);

void ms_hrect_colored(mapshape *ms,hrect *hr,int agcol);

void ms_box(mapshape *ms,double x1,double y1,double x2,double y2);

void ms_hrect_box(mapshape *ms,hrect *hr);

void ms_hrect_box_colored(mapshape *ms,hrect *hr,int agcol);

int ms_get_xy(mapshape *ms,double *r_x,double *r_y);

void ms_dyv(mapshape *ms,dyv *x,int marktype);

void ms_dyv_colored(mapshape *ms,dyv *x,int marktype,int agcol);

void ms_point_in_dym_colored(mapshape *ms,dym *x,int row,
			     int marktype,int agcol);

void ms_dym_colored(mapshape *ms,dym *x,int marktype,int agcol);

void ms_disc(mapshape *ms,double x,double y,double ag_rad);

void ms_circle(mapshape *ms,double x,double y,double ag_rad);

void ms_dyv_line(mapshape *ms,dyv *x,dyv *y);

void ms_print(mapshape *ms,double x,double y,char *string);

void ms_metric_circle(mapshape *ms,dyv *metric,dyv *center,double radius);

void ms_metric_circle_colored(mapshape *ms,dyv *metric,dyv *center,
			      double radius,int agcol);

/* Returns NULL if right button pressed */
dyv *mk_query_from_ms(mapshape *ms);

/* Returns NULL if right button pressed */
dyv *mk_query_and_radius_from_ms(mapshape *ms,dyv *metric,double *radius);

void ms_string(mapshape *ms,double x,double y,char *s);

void ms_string_colored(mapshape *ms,double x,double y,char *s,int agcol);

void ms_dyv_string_colored(mapshape *ms,dyv *x,char *s,int agcol);

void ms_point_in_dym_colored_string(mapshape *ms,dym *x,int row,char *s,
				    int agcol);

void ms_line_between_dym_rows(mapshape *ms,dym *x1,dym *x2,
			      int row1,int row2,int agcol);


void render_heights(mapshape *ms,dym *heights,int dmap_type);

string_array *mk_labels_for_color_bands(dyv *dmap_threshes);

hrect *mk_hrect_from_agbox(agbox *ag);

mapshape *mk_mapshape_from_hrect_and_agbox(hrect *hr,agbox *ag);

/* Renders the heights and draws in axis labels, height key and
   title. Returns the mapshape it used in case you want to draw
   anything on the map with the ms_dot etc commands */
mapshape *mk_heights_mapshape(hrect *hr,dym *heights,
			      char *x_attname,char *y_attname,char *z_attname);

/* Renders the heights and draws in axis labels, height key and
   title. Returns the mapshape it used in case you want to draw
   anything on the map with the ms_dot etc commands */
mapshape *mk_multi_heights_mapshape(hrect *hr,dym_array *heights,
				    char *x_attname,char *y_attname,
				    char *z_attname,
				    string_array *z_valnames);

#endif /* #ifndef MAPSHAPE_H */
