00001
00007 #ifndef __PLOT_SPECIFICATION_H__
00008 #define __PLOT_SPECIFICATION_H__
00009
00010 #include <utility>
00011 #include <string>
00012 using std::string;
00013
00014
00015 #include "../src/matriximagefactory.h"
00016 #include "../src/pointermap.h"
00017 #include "../src/allocatingpointer.h"
00018 #include "../src/tnt_gnuplot.h"
00019 #include "../src/msg.h"
00020 #include "../src/parammap.h"
00021 #include "../src/stringutils.h"
00022 #include "../src/matrixhistogram.h"
00023 #include "../src/histogramimage.h"
00024 #include "../src/scale.h"
00025
00026
00027
00028
00029
00033 template<class Color>
00034 Color lookup_color
00035 (const ParamMap& params, const string& basename, const Color& default_val)
00036 {
00037
00038
00039 const string R_param = basename+"_R";
00040 const string G_param = basename+"_G";
00041 const string B_param = basename+"_B";
00042 const double R = params.get_with_default(R_param.c_str(), default_val.red());
00043 const double G = params.get_with_default(G_param.c_str(), default_val.green());
00044 const double B = params.get_with_default(B_param.c_str(), default_val.blue());
00045 return Color(R,G,B);
00046 }
00047
00048
00049
00052 template<class SubRegion>
00053 SubRegion lookup_subregion
00054 (const ParamMap& params, const SubRegion& default_val)
00055 {
00056 const int s_c = params.get_with_default("start_c", -1);
00057 const int s_r = params.get_with_default("start_r", -1);
00058 const int e_c = params.get_with_default("end_c", -1);
00059 const int e_r = params.get_with_default("end_r", -1);
00060
00061 if (s_c<0 || s_r<0 || e_c<0 || e_r<0)
00062 return default_val;
00063 return SubRegion(-s_c,-s_r,-e_c,-e_r);
00064 }
00065
00066
00067
00068 namespace Plot {
00069
00070
00071
00076 template<class ParamMapType>
00077 ParamMapType* PlotSpec_params(const string& child_name,
00078 ParamMapType& parent,
00079 const string& strength_name="",
00080 const string& color_name="",
00081 const string& confidence_name="")
00082 {
00083
00084
00085 ParamMapType* p = dynamic_cast<ParamMapType*>(parent.new_child(child_name));
00086 PlotSpec_child_map(*p,"Strength",strength_name);
00087 PlotSpec_child_map(*p,"Color",color_name);
00088 PlotSpec_child_map(*p,"Confidence",confidence_name);
00089 PlotSpec_child_map(*p,"Histogram","",false);
00090 return p;
00091 }
00092
00093
00094
00097 template<class ParamMapType>
00098 ParamMapType* PlotSpec_child_map(ParamMapType& parent, const string& childname, const string& matrixname="",
00099 bool setmatrixname=true)
00100 {
00101 ParamMapType* c = dynamic_cast<ParamMapType*>(parent.new_child(childname,true)); assert(c);
00102 if (setmatrixname) c->set_local("name",matrixname);
00103 return c;
00104 }
00105
00106
00115 template <class Matrix, class String=string, class ScaleType=Scale::Linear<>,
00116 class MatrixTableType=PointerMap<Matrix>,
00117 class ParameterMapType=ParamMap >
00118 class PlotSpecification {
00119 typedef const String cStr;
00120 typedef ParameterMapType ParamMapType;
00121 typedef Histo::OneDHistogram<> Histogram;
00122 typedef Plot::RGBPixel<> ColorType;
00123
00124 public:
00125 typedef MatrixTableType MatrixTable;
00126
00127 private:
00128
00132 PlotSpecification(cStr& objectname, const MatrixTable& maptable, cStr& name, ParamMapType* params_)
00133 : plotname(name), objname(objectname), params(params_,true), maps(&maptable) { }
00134
00135 public:
00137 typedef Boundary::AAArbitraryRectangle<double,int> SubRegion;
00138
00147 const Matrix* reference_mapptr() const {
00148 assert (maps->begin()!=maps->end());
00149 return maps->begin()->second;
00150 }
00151
00153 template <class DerivedFromParamMap>
00154 PlotSpecification(cStr& objectname, const MatrixTable& maptable, cStr& name, DerivedFromParamMap& parentparams,
00155 const string& strength_name="", const string& color_name="", const string& confidence_name="")
00156 : plotname(name), objname(objectname),
00157 params(PlotSpec_params(name,parentparams,strength_name,color_name,confidence_name),true),
00158 maps(&maptable) { }
00159
00160 ~PlotSpecification() { }
00161
00163 const string name() const { return plotname; }
00164
00167 const string objectname() const { return objname; }
00168
00169 bool save_matrix (const string filebase, const MatrixTable* tempmaps=0,
00170 const SubRegion* overriding_region=0) const;
00171 bool gnuplot_image(const string filebase, const MatrixTable* tempmaps=0,
00172 const SubRegion* overriding_region=0) const;
00173 Plot::MatrixImage<>* bitmap_image(const double master_scale=-1, const SubRegion* reference=0, const MatrixTable* tempmaps=0,
00174 const SubRegion* overriding_region=0,
00175 const int border_width=-1, const string overriding_colorspec="") const;
00176 Plot::AARImage<>* bitmap_histogram(const double master_scale, const ParamMap& defaults, const SubRegion* reference,
00177 const MatrixTable* tempmaps=0, const string& name="Histogram") const;
00178
00179
00180 static void message(Msg::MessageLevel m, const string& s, const bool terminate=True) {
00181
00182 const bool nonnull = (mhp!=0 && (*mhp));
00183 if (nonnull) (**mhp)(m,s,terminate);
00184 }
00185
00188 template <class T>
00189 T lookup_param(const string& name, const T& default_val) const
00190 { return lookup_param(*params,name.c_str(),default_val); }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 template <class T>
00206 T lookup_param(const ParamMap& params1, const string& name, const T& default_val,
00207 const ParamMap* params2=0, const ParamMap* params3=0) const {
00208 const T p1=params1.get_with_default(name.c_str(),default_val);
00209 if (p1!=default_val || !params2) return p1;
00210
00211 const T p2=params2->get_with_default(name.c_str(),default_val);
00212 if (p2!=default_val || !params3) return p2;
00213
00214 return params3->get_with_default(name.c_str(),default_val);
00215 }
00216
00217
00218 ParamMapType& param_map() { return *(params.valueptr()); }
00219 const ParamMapType& param_map() const { return *params; }
00220
00221 private:
00222 Plot::AARImage<>* histogram_image(const double master_scale,
00223 const SubRegion* reference,
00224 const ParamMap& histoparams,
00225 const Histogram& histo) const;
00226
00227 double compute_size_scale(const double master_scale, const double specified_scale,
00228 const SubRegion& paramregion, const SubRegion* reference) const;
00229
00231 const Matrix* map_getptr(const string& name, const MatrixTable* tempmaps=0, bool warn=true) const {
00232 if (name=="") return 0;
00233 const Matrix* p = (tempmaps ? tempmaps->getptr(name) : 0);
00234 const Matrix* pp = (p? p : maps->getptr(name) );
00235 if (warn && !pp && name!=lastwarning && name!=previouswarning) {
00236 message(Msg::Warning, "Could not find map matrix named '" + name
00237 + "' when plotting " + plotname + " for " + objname );
00238 previouswarning=lastwarning;
00239 lastwarning=name;
00240 }
00241 return pp;
00242 }
00243
00244
00245
00246
00247 const Matrix* map_getptr(const ParamMap& params, const MatrixTable* tempmaps=0,
00248 bool warn=true, const string& paramname="name") const
00249 { return map_getptr(lookup_param(params, paramname, string()),tempmaps, warn); }
00250
00251 String plotname, objname;
00252
00253 OwningPointer<ParamMapType> params;
00254 const MatrixTable* maps;
00255
00259 mutable string lastwarning,previouswarning;
00260
00261 static Msg::LevelHandler<>** mhp;
00262 };
00263
00264
00265
00266 template <class Matrix,class String,class ScaleType,class MatrixTableType,class ParameterMapType>
00267 Msg::LevelHandler<>**
00268 PlotSpecification<Matrix,String,ScaleType,MatrixTableType,ParameterMapType>::
00269 mhp=&(Msg::LevelHandler<>::default_instance());
00270
00271
00272
00282 template <class Matrix,class String,class ScaleType,class MatrixTableType,class ParameterMapType>
00283 bool
00284 PlotSpecification<Matrix,String,ScaleType,MatrixTableType,ParameterMapType>::
00285 gnuplot_image(const string filebase, const MatrixTable* tempmaps,
00286 const SubRegion* overriding_region) const
00287 {
00288 const string outname = (filebase=="" ? "" : filebase+"_"+objectname()+"_"+name()+".ps");
00289 const string title = objectname() + " " + name();
00290 const Matrix* s = map_getptr(params->get_child("Strength"), tempmaps);
00291 const Matrix* c = map_getptr(params->get_child("Color"), tempmaps);
00292 const SubRegion paramregion = lookup_subregion(*params,SubRegion());
00293 const SubRegion subregion = (overriding_region? *overriding_region : paramregion);
00294 typedef typename Matrix::value_type T;
00295 typedef mat::MatrixInterface<T> BaseMatrixType;
00296 typedef mat::MatrixAdapter<BaseMatrixType> MatrixWindow;
00297
00298 const string messages = (s? mat::gnuplot(MatrixWindow(*s,1.0,subregion),title,outname) :
00299 (c? mat::gnuplot(MatrixWindow(*c,1.0,subregion),title,outname) : string()));
00300
00301 if (messages != "") {
00302 message(Msg::Warning, "Gnuplot wrapper for " + title + ": " + messages);
00303 return false;
00304 }
00305
00306 return true;
00307 }
00308
00309
00310
00315 template <class Matrix,class String,class ScaleType,class MatrixTableType,class ParameterMapType>
00316 bool
00317 PlotSpecification<Matrix,String,ScaleType,MatrixTableType,ParameterMapType>::
00318 save_matrix(const string filebase, const MatrixTable* tempmaps,
00319 const SubRegion* overriding_region) const
00320 {
00321
00322 const string outname = (filebase=="" ? "" : filebase+".matrix");
00323 const string title = objectname() + " " + name();
00324 const Matrix* s = map_getptr(params->get_child("Strength"), tempmaps);
00325 const Matrix* c = map_getptr(params->get_child("Color"), tempmaps);
00326 const SubRegion paramregion = lookup_subregion(*params,SubRegion());
00327 const SubRegion subregion = (overriding_region? *overriding_region : paramregion);
00328 typedef typename Matrix::value_type T;
00329 typedef mat::MatrixInterface<T> BaseMatrixType;
00330 typedef mat::MatrixAdapter<BaseMatrixType> MatrixWindow;
00331
00332 std::ofstream matrixfile(outname.c_str());
00333 if (!matrixfile) {
00334 message(Msg::Warning, "Could not open matrix file " + outname);
00335 return false;
00336 }
00337 if (!c && !s){
00338 message(Msg::Warning, "Nothing to plot");
00339 return true;
00340 }
00341 MatrixWindow submatrix((s? *s : *c),1.0,subregion);
00342
00343
00344 matrixfile
00345 << "# Created from " << title << std::endl
00346 << "# name: " << name() << std::endl
00347 << "# type: matrix" << std::endl
00348 << "# rows: " << submatrix.nrows() << std::endl
00349 << "# columns: " << submatrix.ncols() << std::endl;
00350
00351 stream_output(MatrixWindow((s? *s : *c),1.0,subregion),matrixfile);
00352
00353 return true;
00354 }
00355
00356
00357
00363 template <class Matrix,class String,class ScaleType,class MatrixTableType,class ParameterMapType>
00364 double
00365 PlotSpecification<Matrix,String,ScaleType,MatrixTableType,ParameterMapType>::
00366 compute_size_scale(const double master_scale, const double specified_scale,
00367 const SubRegion& paramregion, const SubRegion* reference) const
00368 {
00369 if (!reference) return specified_scale;
00370
00371 if (master_scale>0) {
00372 const double height = (!paramregion.isinfinite()? paramregion.height() : reference_mapptr()->nrows());
00373 const double width = (!paramregion.isinfinite()? paramregion.width() : reference_mapptr()->ncols());
00374 const int hfactor = int(master_scale*reference->height()/height);
00375 const int wfactor = int(master_scale*reference->width()/width);
00376 const int factor = std::min(hfactor,wfactor);
00377 if (factor>0) return factor;
00378 }
00379
00380 return specified_scale;
00381 }
00382
00383
00384
00388 template <class T>
00389 struct normalized_difference_fnobj : public std::binary_function<T, T, T> {
00390 T operator()(const T& x, const T& y) const { return 0.5+0.5*(x-y); }
00391 };
00392
00393
00400 template <class Matrix,class String,class ScaleType,class MatrixTableType,class ParameterMapType>
00401 Plot::MatrixImage<>*
00402 PlotSpecification<Matrix,String,ScaleType,MatrixTableType,ParameterMapType>::
00403 bitmap_image(const double master_scale, const SubRegion* reference,
00404 const MatrixTable* tempmaps, const SubRegion* overriding_region,
00405 const int border_width, const string overriding_colorspec) const
00406 {
00407
00408 const Tristate paper_based = lookup_param(*params,"ppm_paper_based_colors", False);
00409 const double subplot_hue = lookup_param(*params,"ppm_subplot_hue", 0.0);
00410 const string colorspec =(overriding_colorspec!=""? overriding_colorspec :
00411 lookup_param(*params,"colorspec", string("RYW")));
00412 const ColorType bordercolor = lookup_color(*params,"ppm_bg", AARImage<>::default_border);
00413 const int border = (border_width>=0 ? border_width : lookup_param(*params,"ppm_border", 1));
00414 const ParamMap& strength = params->get_child("Strength");
00415 const ParamMap& color = params->get_child("Color");
00416 const ParamMap& confidence = params->get_child("Confidence");
00417 const SubRegion paramregion = lookup_subregion(*params,SubRegion());
00418 const SubRegion subregion = (overriding_region? *overriding_region : paramregion);
00419 const double size_scale = compute_size_scale(master_scale,lookup_param(*params,"size_scale", 1.0),
00420 paramregion,reference);
00421
00422 Plot::ColorLookupFactory<>::result_type* clu =
00423 Plot::ColorLookupFactory<>(paper_based,subplot_hue)(colorspec);
00424 typedef typename Matrix::value_type T;
00425 typedef mat::MatrixInterface<T> BaseMatrixType;
00426 const Plot::MatrixImageFactory<BaseMatrixType,T,ScaleType>
00427 factory(paper_based,size_scale,border,subregion,clu,bordercolor);
00428
00429
00430
00431 typedef normalized_difference_fnobj<T> RefFunType;
00432 typedef mat::MatrixInterfaceBinaryAdapter<BaseMatrixType,RefFunType> BinFunAdapter;
00433 typedef mat::MatrixInterfaceAdapter<BaseMatrixType> MatAdapter;
00434 const BaseMatrixType* strengthptr = map_getptr(strength, tempmaps);
00435 const BaseMatrixType* refptr = map_getptr("__StrengthReference", tempmaps,false);
00436 const BinFunAdapter* strength_ref = 0;
00437 if (strengthptr && refptr) {
00438 strength_ref = new BinFunAdapter(*strengthptr,*refptr,RefFunType());
00439 assert (strength_ref);
00440 strengthptr = strength_ref;
00441 }
00442
00443
00444 Plot::MatrixImage<>* img =
00445 factory(strengthptr,
00446 ScaleType( lookup_param(strength, "value_scale", 1.0),
00447 lookup_param(strength, "value_offset",0.0)),
00448 map_getptr(color, tempmaps),
00449 ScaleType( lookup_param(color, "value_scale", 1.0),
00450 lookup_param(color, "value_offset",0.0)),
00451 map_getptr(confidence, tempmaps),
00452 ScaleType( lookup_param(confidence, "value_scale", 1.0),
00453 lookup_param(confidence, "value_offset",0.0)) );
00454
00455 delete clu;
00456 delete strength_ref;
00457
00458
00459
00460
00461 return img;
00462 }
00463
00464
00465
00467 template <class Matrix,class String,class ScaleType,class MatrixTableType,class ParameterMapType>
00468 Plot::AARImage<>*
00469 PlotSpecification<Matrix,String,ScaleType,MatrixTableType,ParameterMapType>::
00470 bitmap_histogram(const double master_scale, const ParamMap& defaults,
00471 const SubRegion* reference, const MatrixTable* tempmaps,
00472 const string& name) const
00473 {
00474 const ParamMap& histoparams = params->get_child(name);
00475
00476
00477 const Matrix* str_mat = map_getptr(params->get_child("Strength"), tempmaps);
00478
00479
00480 const ParamMap& colorparams = params->get_child("Color");
00481 const string bin_name = lookup_param(histoparams,"name",string(),&defaults,&colorparams);
00482
00483
00484
00485 const Matrix* bin_mat = map_getptr(bin_name, tempmaps, false);
00486 const bool enabled = lookup_param(histoparams,"ppm_histograms",True);
00487 if (!enabled || !bin_mat) return 0;
00488
00489 const int num_bins = lookup_param(histoparams,"num_bins", 24 );
00490 const bool cyclic = lookup_param(histoparams,"cyclic", True);
00491 ScaleType scale(num_bins);
00492
00493 if (!str_mat) {
00494 typedef mat::MatrixInterfaceConstant<float> ConstantMatrix;
00495 ConstantMatrix const_one(1.0,bin_mat->nrows(),bin_mat->ncols());
00496 return histogram_image(master_scale, reference, histoparams,
00497 Histogram(Histo::matrix_histogram(*bin_mat,const_one,num_bins,scale,cyclic)));
00498 }
00499 else
00500 return histogram_image(master_scale, reference, histoparams,
00501 Histogram(Histo::matrix_histogram(*bin_mat,*str_mat, num_bins,scale,cyclic)));
00502 }
00503
00504
00505
00506 template <class Matrix,class String,class ScaleType,class MatrixTableType,class ParameterMapType>
00507 Plot::AARImage<>*
00508 PlotSpecification<Matrix,String,ScaleType,MatrixTableType,ParameterMapType>::
00509 histogram_image(const double master_scale, const SubRegion* reference,
00510 const ParamMap& histoparams, const Histogram& histo) const
00511 {
00512 const ColorType bordercolor = lookup_color(histoparams,"ppm_bg", AARImage<>::default_border);
00513 const double range = lookup_param(histoparams,"range_end", 0.25);
00514 const bool vertical = lookup_param(histoparams,"vertical", True);
00515 const double aspect_ratio = lookup_param(histoparams,"aspect_ratio",0.25);
00516 const int border = lookup_param(histoparams,"ppm_border", 1 );
00517 const string hcolorspec = lookup_param(histoparams,"histo_colorspec",string(""));
00518 const string colorspec =(hcolorspec!=""? hcolorspec :
00519 lookup_param(histoparams,"colorspec", string("Hue")));
00520 const double subplot_hue = lookup_param(histoparams,"ppm_subplot_hue", 0.0);
00521 const Tristate paper_based = lookup_param(histoparams,"ppm_paper_based_colors", False);
00522 const ColorType histobg = lookup_color(histoparams,"ppm_line", ColorType());
00523 const double psize_scale = lookup_param(*params,"size_scale", 1.0);
00524 const SubRegion fakesubregion = SubRegion(0,0,
00525 histo.num_bins()*(vertical? aspect_ratio : 1.0),
00526 histo.num_bins()*(vertical? 1.0 : aspect_ratio));
00527 const double size_scale = compute_size_scale(master_scale,psize_scale,fakesubregion,reference);
00528
00529 OwningPointer<Plot::ColorLookupFactory<>::result_type> clu
00530 (Plot::ColorLookupFactory<>(paper_based,subplot_hue)(colorspec),true);
00531
00532 return new
00533 Plot::OneDHistogramImage<>(histo,vertical,size_scale,aspect_ratio,
00534 range,border,*clu,bordercolor,histobg);
00535 }
00536
00537
00538 }
00539 #endif