AntarcticaBackground.cxx
1 #include "AntarcticaBackground.h"
2 #include "TGraphAntarctica.h"
3 #include "TVirtualPad.h"
4 #include "TPaletteAxis.h"
5 #include "TROOT.h"
6 #include "TObjArray.h"
7 #include "TObjString.h"
8 #include "TCanvas.h"
9 #include "BaseList.h"
10 #include "TStyle.h"
11 #include "TExec.h"
12 #include "TGToolTip.h"
13 #include "TColor.h"
14 
15 
16 ClassImp(AntarcticaBackground)
17 
18 
19 
20 // simple global variable to increment integer in name so we can have as manny of these background as we like.
21 static int numAntarcticaBackgrounds = 0;
22 
23 
24 AntarcticaBackground::AntarcticaBackground(RampdemReader::dataSet dataSet, Int_t coarseness)
25  : TProfile2D(), hDummy() {
26  init(dataSet, coarseness);
27 }
28 
29 
30 AntarcticaBackground::~AntarcticaBackground(){
31  delete fPalSetter;
32  delete fPalUnsetter;
33  if(gPad){
34  SetToolTip(false);
35  gPad->Modified();
36  gPad->Update();
37  }
38  deleteGrid();
39 }
40 
41 
42 void AntarcticaBackground::init(RampdemReader::dataSet dataSet, Int_t coarseness){
43  SetDirectory(0);
44  fName = Form("%s%d", getDefaultName(), numAntarcticaBackgrounds);
45  numAntarcticaBackgrounds++;
46  fMinVal = DBL_MAX;
47  fMaxVal = -DBL_MAX;
48  fDataSet = dataSet;
49  fCoarseness = coarseness;
50  needRemakeHist = true; // force updateHist() to read in data by setting impossible coarseness
51  fDrawnSelf = false; // set by Draw(), needed by updateHist()
52  updateHist();
53 
54  fGrayScale = false;
55 
56  fGridPoints = 1000;
57  fDeltaLon = 30; // degrees
58  fDeltaLat = 5; // degrees
59  fGrid = true;
60  needRemakeGrid = true; // force updateGrid() to make grid TGraphs on first call
61  updateGrid();
62 
63  fUseToolTip = true;
64  fToolTip = NULL;
65 
66  TString palSetterName = TString::Format("%sPalSetter", fName.Data());
67  fPalSetter = new TExec(palSetterName,Form("%s->setPalette()", fName.Data()));
68  TString palUnsetterName = TString::Format("%sPalSetter", fName.Data());
69  fPalUnsetter = new TExec(palUnsetterName,Form("%s->unsetPalette()", fName.Data()));
70 
71  // Dummy histogram whose only purpose is to have a color axis, which we will steal
72  // and stay well away from out Antarctica histograms, hence the crazy axis limits
73  hDummy.SetBins(2, -9e30, -8e30, 1, -9e30, -8e30);
74  fShowColorAxis = true;
75 
76  // at some point, supporting ROOT versions < 6 is gonna be impossible...
77 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0)
78  palettes[RampdemReader::rampdem] = kLightTerrain;
79  palettes[RampdemReader::bed] = kLake; // maybe a bit intense...
80  palettes[RampdemReader::icemask_grounded_and_shelves] = kLightTerrain;
81  palettes[RampdemReader::surface] = kLightTerrain;
82  palettes[RampdemReader::thickness] = kRedBlue;
83  opacity = 1;
84 #endif
85 
86  fBases = false;
87  fDrawBasesOnTop = true;
88 }
89 
90 
91 
92 void AntarcticaBackground::setPalette(){
93 
94  // at some point, supporting ROOT versions < 6 is gonna be impossible...
95 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0)
96 
97  // here I define the color palettes tbat I want the different data sets to use when they're drawn on the background.
98  std::map<RampdemReader::dataSet, EColorPalette>::iterator it = palettes.find(fDataSet);
99 
100  if(it != palettes.end()){
101 
102  // save the old palette
103  fOldPalette.resize(gStyle->GetNumberOfColors());
104  for(UInt_t i=0; i < fOldPalette.size(); i++){
105  fOldPalette[i] = gStyle->GetColorPalette(i);
106  }
107  fOldGrayScale = TColor::IsGrayscale();
108 
109  TColor::SetGrayscale(fGrayScale);
110  gStyle->SetPalette(it->second,0,opacity);
111  }
112 #else
113  std::cerr << __PRETTY_FUNCTION__ << " requires ROOT version at least 6" << std::endl;
114 #endif
115 
116 }
117 
118 
119 void AntarcticaBackground::unsetPalette(){
120 
121  // at some point, supporting ROOT versions < 6 is gonna be impossible...
122 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0)
123  TColor::SetGrayscale(fOldGrayScale);
124  if(fOldPalette.size() > 0){
125  gStyle->SetPalette(fOldPalette.size(), &fOldPalette[0]);
126  }
127  // std::cerr << "here" << std::endl;
128 
129 #else
130  std::cerr << __PRETTY_FUNCTION__ << " requires ROOT version at least 6" << std::endl;
131 #endif
132 }
133 
134 
135 
136 
140 void AntarcticaBackground::updateHist(){
141 
142 
143  if(needRemakeHist){
144 
145  // Here I save the current drawn axis range so I can set it to be the same after updating contents
146  Int_t firstX = fXaxis.GetFirst();
147  Int_t lastX = fXaxis.GetLast();
148  Int_t firstY = fYaxis.GetFirst();
149  Int_t lastY = fYaxis.GetLast();
150 
151  Double_t lowX = fXaxis.GetBinLowEdge(firstX);
152  Double_t highX = fXaxis.GetBinUpEdge(lastX);
153  Double_t lowY = fXaxis.GetBinLowEdge(firstY);
154  Double_t highY = fXaxis.GetBinUpEdge(lastY);
155 
156  // std::cout << firstX << "\t" << lastX << "\t" << lowX << "\t" << highX << std::endl;
157 
158  // now I get the new histogram binning
159  Int_t nx, ny;
160  RampdemReader::getNumXY(nx, ny, fDataSet);
161  Double_t xMin, xMax, yMin, yMax;
162  RampdemReader::getMapCoordinates(xMin, yMin, xMax, yMax, fDataSet);
163 
164  // accounting for coarseness
165  nx /= fCoarseness;
166  ny /= fCoarseness;
167 
168 
169  // Get rid of old the AntarcticaBackground content
170  fBinEntries.Reset();
171  for(int by=0; by <= GetNbinsY() + 1; by++){
172  for(int bx=0; bx <= GetNbinsX() + 1; bx++){
173  SetBinContent(bx, by, 0);
174  }
175  }
176  // change the histogram dimensions
177  SetBins(nx, xMin, xMax, ny, yMin, yMax);
178 
179  // insert new data
180  RampdemReader::fillThisHist(this, fDataSet);
181 
182  fMinVal = DBL_MAX;
183  fMaxVal = -DBL_MAX;
184  for(int by=1; by <= GetNbinsY(); by++){
185  for(int bx=1; bx <= GetNbinsX(); bx++){
186  double val = GetBinContent(bx, by);
187  if(val < fMinVal){
188  fMinVal = val;
189  }
190  if(val > fMaxVal){
191  fMaxVal = val;
192  }
193  }
194  }
195  SetMaximum(fMaxVal);
196  SetMinimum(fMinVal);
197  fScaleMax = 0;
198  fScaleMin = 0;
199  hDummy.SetBinContent(1, fMinVal);
200  hDummy.SetBinContent(2, fMinVal);
201  hDummy.SetMaximum(fMaxVal);
202  hDummy.SetMinimum(fMinVal);
203 
204  if(fDrawnSelf){
205 
206  // now set the viewing range to the same as before if we have a gPad instance
207  fXaxis.SetRangeUser(lowX, highX);
208  fYaxis.SetRangeUser(lowY, highY);
209 
210  // and update the z-axis title if needed
211  ResetColorAxis();
212  }
213 
214  setToolTipUnits();
215  }
216 
217  // prettification
218  GetXaxis()->SetNdivisions(0, kFALSE);
219  GetYaxis()->SetNdivisions(0, kFALSE);
220 
221  needRemakeGrid = false;
222 }
223 
224 
225 
226 
227 
228 
229 Int_t AntarcticaBackground::GetCoarseness() const{
230  return fCoarseness;
231 }
232 
233 
234 
235 void AntarcticaBackground::SetToolTip(Bool_t toolTip){
236  fUseToolTip = toolTip;
237 
238  if(fToolTip && !fUseToolTip){
239  delete fToolTip;
240  fToolTip = NULL;
241  }
242  else{
243  if(!fToolTip){
244  fToolTip = new TGToolTip();
245  fToolTip->SetBackgroundColor(kWhite);
246  }
247  }
248 }
249 
250 Bool_t AntarcticaBackground::GetToolTip() const{
251  return fUseToolTip;
252 }
253 
254 
255 void AntarcticaBackground::SetCoarseness(Int_t coarseness){
256 
257  // sanity check
258  if(coarseness < 1){
259  std::cerr << "Warning in " << __PRETTY_FUNCTION__ << ", coarsenesss must be >= 1. Setting coareness = "
260  << AntarcticaBackgroundDefaults::defaultCoarseness << std::endl;
261  coarseness = AntarcticaBackgroundDefaults::defaultCoarseness;
262  }
263 
264  needRemakeHist = fCoarseness == coarseness ? false : true;
265  fCoarseness = coarseness;
266  updateHist();
267 }
268 
269 
270 RampdemReader::dataSet AntarcticaBackground::GetDataSet() const{
271  return fDataSet;
272 }
273 
274 
275 
276 void AntarcticaBackground::SetDataSet(RampdemReader::dataSet dataSet){
277 
278  needRemakeHist = dataSet == fDataSet ? false : true;
279  fDataSet = dataSet;
280  updateHist();
281 }
282 
283 
284 
285 
286 
287 
288 
289 void AntarcticaBackground::updateBases(){
290 
291  if(grBases.size()==0){
292  for(UInt_t b=0; b < BaseList::getNumBases(); b++){
293  TGraphAntarctica* gr = new TGraphAntarctica(BaseList::getBase(b));
294  // gr->SetDrawOption("*");
295  gr->SetMarkerStyle(8);
296  gr->SetMarkerColor(kMagenta);
297  gr->SetEditable(false);
298 
299  gr->SetDrawOption("p");
300  // if(fBases){
301  // gr->Draw("psame");
302  // }
303 
304  grBases.push_back(gr);
305  }
306  }
307 
308  updateGPadPrims(grBases, fBases, "p", fDrawBasesOnTop);
309 }
310 
311 
312 void AntarcticaBackground::updateGrid(){
313 
314  if(needRemakeGrid){
315 
316  const int minLat = -90 + fDeltaLat;
317  const int maxLat = -60;
318 
319  deleteGrid();
320 
321  // make circles of constant latitude
322  for(Int_t lat = minLat; lat<= maxLat; lat += fDeltaLat){
324  gr->SetLineColor(kGray);
325  const Double_t deltaLon = 360./fGridPoints;
326  for(int i=0; i < fGridPoints; i++){
327  Double_t theLat = lat;
328  Double_t theLon = i*deltaLon;
329  gr->SetPoint(gr->GetN(), theLon, theLat);
330  // std::cout << gr << "\t" << gr->GetN() << "\t" << easting << "\t" << northing << std::endl;
331  }
332  gr->SetEditable(false);
333  gr->SetTitle(Form("Grid: Lat %d", lat)); // descriptive title
334  grGrids.push_back(gr);
335  }
336 
337  // make lines of constant longitude
338  for(Int_t lon = -180; lon < 180; lon+= fDeltaLon){
340  gr->SetLineColor(kGray);
341  const Double_t deltaLat = double(maxLat - -90)/fGridPoints;
342  for(int i=0; i < fGridPoints; i++){
343  Double_t theLat = -90 + deltaLat*i;
344  Double_t theLon = lon;
345  gr->SetPoint(gr->GetN(), theLon, theLat);
346  }
347  gr->SetEditable(false);
348  gr->SetTitle(Form("Grid: Lon %d", lon)); // descriptive title
349  grGrids.push_back(gr);
350  }
351 
352  needRemakeGrid = false;
353  }
354 
355  updateGPadPrims(grGrids, fGrid, "l");
356 }
357 
358 
359 
360 
361 
362 
363 
364 
365 void AntarcticaBackground::updateGPadPrims(std::vector<TGraphAntarctica*>& grs, Bool_t drawThem, Option_t* opt, bool drawGraphsOnTop){
366 
367 
368  // for(UInt_t padInd = 0; padInd < fPads.size(); padInd++){
369  TVirtualPad* fPad = gPad;
370  if(fPad){
371  TList* prims = fPad->GetListOfPrimitives();
372 
373  if(drawThem && fDrawnSelf){
374  // Manually add the grid TGraphs into the list of pad primitives...
375  // turns out that to do this with options is slightly more complicated than I thought.
376  // You need to iterate over the links (that wrap the objects) because the links hold the options.
377  TObjLink *thisLink = prims->FirstLink();
378 
379  Int_t numThis = 0;
380  // while(thisLink->GetObject() != this){
381  while(numThis < 2){
382  thisLink = thisLink->Next();
383 
384  // Complication, now we're drawing two copies of the histogram with an exec to set the palette
385  // I need to find the second instance on the canvas
386  if(thisLink->GetObject()==this){
387  numThis++;
388  }
389  }
390 
391  // so thisLink points to this.
392  // using that info with add After.
393  TObjLink* antarcticaStuff = thisLink->Next();
394 
395  // It turns out that for such a fundamental ROOT container, TList is pretty dumb.
396  // I think I'm going to have to take all the objects out, save their associated options,
397  // and redraw them. That's becasuse there's no way to add a link with options at an arbitrary
398  // position in the list, only at the end of the list.
399 
400  // first copy the pointers...
401  std::vector<TObject*> tempObjs;
402  std::vector<TString> tempOpts;
403  while(antarcticaStuff){
404  tempObjs.push_back(antarcticaStuff->GetObject());
405  tempOpts.push_back(antarcticaStuff->GetOption());
406  antarcticaStuff = antarcticaStuff->Next();
407  }
408 
409  // now take the objects out
410  for(UInt_t i=0; i < tempObjs.size(); i++){
411  prims->RecursiveRemove(tempObjs.at(i));
412  }
413 
414 
415  // now we need to redraw them in the proper order specified by onTop
416 
417  if(drawGraphsOnTop){
418  // first, re-add the things we removed
419  for(UInt_t i=0; i < tempObjs.size(); i++){
420  prims->AddLast(tempObjs.at(i), tempOpts.at(i));
421  }
422  // then the TGraphs, with the proper options
423  for(UInt_t grInd=0; grInd < grs.size(); grInd++){
424  TGraphAntarctica* gr = grs.at(grInd);
425  prims->AddLast(gr, opt);
426  }
427  }
428  else{
429  // otherwise add the TGraphs first, with the proper options
430  for(UInt_t grInd=0; grInd < grs.size(); grInd++){
431  TGraphAntarctica* gr = grs.at(grInd);
432  prims->AddLast(gr, opt);
433  }
434  // and then re-add the things we removed
435  for(UInt_t i=0; i < tempObjs.size(); i++){
436  prims->AddLast(tempObjs.at(i), tempOpts.at(i));
437  }
438  }
439  }
440  else{
441  // Remove the TGraphsAntarcticas from the list of pad primitives
442  for(UInt_t grInd=0; grInd < grs.size(); grInd++){
443  TGraph* gr = grs.at(grInd);
444  prims->RecursiveRemove(gr);
445  }
446  }
447  fPad->Modified();
448  fPad->Update();
449  }
450  // }
451 }
452 
453 
454 
455 
456 void AntarcticaBackground::deleteGrid(){
457 
458  // Grid(false); // avoid segfault?
459  while(grGrids.size() > 0){
460 
461  TGraph* gr = grGrids.back();
462  // for(UInt_t padInd=0; padInd < fPads.size(); padInd++){
463  TVirtualPad* fPad = gPad; //fPads[padInd];
464  if(fPad){
465  TList* prims = gPad->GetListOfPrimitives();
466  // prims->Remove(gr);
467  prims->RecursiveRemove(gr);
468  }
469 
470  delete gr;
471  grGrids.pop_back();
472  }
473 
474 }
475 
476 
477 
478 
479 void AntarcticaBackground::SetGridDivisions(Int_t deltaLon, Int_t deltaLat){
480 
481  needRemakeGrid = fDeltaLon == deltaLon && fDeltaLat == deltaLat ? false : true;
482  fDeltaLon = deltaLon;
483  fDeltaLat = deltaLat;
484  updateGrid();
485 }
486 
487 
488 
494 void AntarcticaBackground::Draw(Option_t* opt){
495 
496  if(!gPad){
497  gROOT->MakeDefCanvas();
498  }
499 
500  // handle defaults
501  TString opt2 = opt;
502  if(opt2 == AntarcticaBackgroundDefaults::drawOpt){
503  opt2 = "colz";
504  fShowColorAxis = true;
505  }
506  if(opt2.Contains("z")){
507  fShowColorAxis = true;
508  }
509  else{
510  fShowColorAxis = false;
511  }
512 
513  // under no circumstances allow this to draw it's own color axis...
514  TString opt3 = opt2;
515  opt3.ReplaceAll("z", "");
516 
517  // 1st instance, no color axis
518  TProfile2D::Draw(opt3);
519 
520  fPalSetter->Draw(); // 1st exec, to set the background palette
521 
522  // Now use hDummy's palette instead, which won't be affected by rescaling
523  if(fShowColorAxis){
524  hDummy.Draw("colz same");
525  }
526  else{
527  hDummy.Draw("col");
528  }
529 
530  // 2nd instance, no color axis
531  opt3 += " same";
532  TProfile2D::Draw(opt3);
533 
534  // 2nd exec, to set the foreground palette again
535  fPalUnsetter->Draw();
536 
537 
538  // pad prettification
539  setPadMargins();
540  ResetColorAxis(true);
541  fXaxis.SetAxisColor(kWhite);
542  fYaxis.SetAxisColor(kWhite);
543  fXaxis.SetTitleOffset(9999);
544  fYaxis.SetTitleOffset(9999);
545  fXaxis.SetLabelOffset(9999);
546  fYaxis.SetLabelOffset(9999);
547 
548 
549  // force redraw
550  gPad->Update();
551  fDrawnSelf = true;
552 
553  SetBit(kMustCleanup);
554  SetBit(kCanDelete); // This means the TPad that we've drawn on owns this, and should delete it when the TPad is destroyed.
555  // (These bits are UNSET in TH2DAntarctica, which can own it's own background)
556 
557  // set up things the background owns, if requested
558  updateGrid();
559  SetToolTip(fToolTip);
560 
561 }
562 
563 
567 void AntarcticaBackground::setPadMargins(){
568  gPad->SetTopMargin(0.1);
569  gPad->SetBottomMargin(0.02);
570  gPad->SetLeftMargin(0.1);
571  gPad->SetRightMargin(0.02);
572  // gPad->SetTopMargin(0.05);
573  // gPad->SetBottomMargin(0.05);
574  // gPad->SetLeftMargin(0.05);
575  // gPad->SetRightMargin(0.1);
576  // gPad->SetRightMargin(0.05);
577  gPad->SetFrameLineColor(0);
578  gPad->SetFrameLineWidth(0);
579  gPad->SetFrameBorderSize(0);
580 
581 }
582 
583 
584 
588 void AntarcticaBackground::ResetColorAxis(bool trigger_redraw){
589 
590  if(fShowColorAxis){
591  if(trigger_redraw){
592  gPad->Modified();
593  gPad->Update();
594  }
595 
596  // now, use the Dummy histogram's color axis
597  TPaletteAxis *palette = (TPaletteAxis*) hDummy.GetListOfFunctions()->FindObject("palette");
598  if(palette){
599  palette->SetX1NDC(AntarcticaBackgroundDefaults::zAxisRightMargin);
600  palette->SetX2NDC(AntarcticaBackgroundDefaults::zAxisRightMargin + AntarcticaBackgroundDefaults::zAxisWidth);
601  palette->SetY1NDC(AntarcticaBackgroundDefaults::zAxisTopBottomMargin);
602  palette->SetY2NDC(AntarcticaBackgroundDefaults::zAxisTopBottomMargin + AntarcticaBackgroundDefaults::zAxisHeight);
603 
604  TAxis* zAxis = GetZaxis();
605  zAxis->SetTitle(RampdemReader::dataSetToAxisTitle(fDataSet));
606  zAxis->SetTitleSize(AntarcticaBackgroundDefaults::zAxisTextSize);
607  zAxis->SetLabelSize(AntarcticaBackgroundDefaults::zAxisTextSize);
608 
609  TAxis* zAxis2 = hDummy.GetZaxis();
610  zAxis2->SetTitle(RampdemReader::dataSetToAxisTitle(fDataSet));
611  zAxis2->SetTitleSize(AntarcticaBackgroundDefaults::zAxisTextSize);
612  zAxis2->SetLabelSize(AntarcticaBackgroundDefaults::zAxisTextSize);
613 
614  // std::cout << zAxis->GetTitleOffset() << std::endl;
615  zAxis2->SetTitleOffset(2);
616  if(trigger_redraw){
617  gPad->Modified();
618  gPad->Update();
619  }
620  }
621  else{
622  std::cerr << "Error in " << __PRETTY_FUNCTION__ << ", couldn't find dummy color axis! " << std::endl;
623  }
624  }
625 }
626 
627 
628 
629 // Interactive functions...
630 
631 void AntarcticaBackground::SetRampdem(bool useRampdem){
632  SetDataSet(RampdemReader::rampdem);
633 }
634 
635 Bool_t AntarcticaBackground::GetRampdem() const {
636  return fDataSet == RampdemReader::rampdem;
637 }
638 
639 void AntarcticaBackground::SetBed(bool useBed){
640  SetDataSet(RampdemReader::bed);
641 };
642 
643 Bool_t AntarcticaBackground::GetBed() const {
644  return fDataSet == RampdemReader::bed;
645 }
646 
647 void AntarcticaBackground::SetIcemask(bool useIcemask){
648  SetDataSet(RampdemReader::icemask_grounded_and_shelves);
649 }
650 
651 Bool_t AntarcticaBackground::GetIcemask() const {
652  return fDataSet == RampdemReader::icemask_grounded_and_shelves;
653 }
654 
655 void AntarcticaBackground::SetSurface(bool useSurface){
656  SetDataSet(RampdemReader::surface);
657 }
658 
659 Bool_t AntarcticaBackground::GetSurface() const {
660  return fDataSet == RampdemReader::surface;
661 }
662 
663 void AntarcticaBackground::SetThickness(bool useThickness){
664  SetDataSet(RampdemReader::thickness);
665 }
666 
667 Bool_t AntarcticaBackground::GetThickness() const {
668  return fDataSet == RampdemReader::thickness;
669 }
670 
671 void AntarcticaBackground::SetGrid(Bool_t grid){
672  fGrid = grid;
673 
674  updateGrid();
675 }
676 
677 Bool_t AntarcticaBackground::GetGrid() const {
678  return fGrid;
679 }
680 
681 
682 void AntarcticaBackground::SetShowBases(Bool_t showBases){
683  fBases = showBases;
684  updateBases();
685 }
686 
687 Bool_t AntarcticaBackground::GetShowBases() const {
688  return fBases;
689 }
690 
691 
692 void AntarcticaBackground::SetGrayScale(bool grayScale){
693  fGrayScale = grayScale;
694 }
695 
696 Bool_t AntarcticaBackground::GetGrayScale() const {
697  return fGrayScale;
698 }
699 
700 
701 void AntarcticaBackground::SetShowColorAxis(bool showColorAxis){
702  fShowColorAxis = showColorAxis;
703  if(fShowColorAxis){
704  hDummy.SetDrawOption("colz same");
705  ResetColorAxis(true);
706  }
707  else{
708  hDummy.SetDrawOption("col same");
709  }
710 }
711 
712 
713 
721 void AntarcticaBackground::ExecuteEvent(Int_t event, Int_t x, Int_t y){
722 
723  updateToolTip(event, x, y);
724  TProfile2D::ExecuteEvent(event, x, y);
725 }
726 
727 
728 
737 void AntarcticaBackground::scale(double newMin, double newMax){
738 
739  // This line prevents the empty bins in the TH2D filling the whole histogram
740  if(newMin == 0){
741  // epsilon
742  newMin += 1e-15;
743  }
744 
745  if(fScaleMax != newMax || fScaleMin != newMin){
746 
747  double currentMax = -DBL_MAX;
748  double currentMin = DBL_MAX;
749 
750  if(fScaleMax == fScaleMin){
751  // need to discover the current scale max/min
752  // not sure we can get here now?
753 
754  for(int by=1; by <= GetNbinsY(); by++){
755  for(int bx=1; bx <= GetNbinsX(); bx++){
756 
757  Int_t bin = GetBin(bx, by);
758  double binEntries = GetBinEntries(bin);
759  // cleverer way of checking this was a filled background bin
760  if(binEntries > 0){
761  double val = GetBinContent(bx, by);
762 
763  currentMin = val < currentMin ? val : currentMin;
764  currentMax = val > currentMax ? val : currentMax;
765  }
766  }
767  }
768  }
769  else{
770  currentMax = fScaleMax;
771  currentMin = fScaleMin;
772  }
773 
774  double currentDelta = currentMax - currentMin;
775  double newDelta = newMax - newMin;
776 
777  for(int by=1; by <= GetNbinsY(); by++){
778  for(int bx=1; bx <= GetNbinsX(); bx++){
779 
780  // cleverer way of checking this was a filled background bin
781  Int_t bin = GetBin(bx, by);
782  double binEntries = GetBinEntries(bin);
783 
784  if(binEntries > 0){
785 
786  double val = GetBinContent(bx, by);
787  double frac = (val - currentMin)/currentDelta;
788 
789  // if(val != 0 && currentMax - val < 100){
790  // std::cerr << val << "\t" << currentMin << "\t" << currentMax << "\t" << frac << std::endl;
791  // }
792 
793  double newVal = newMin + frac*newDelta;
794  SetBinContent(bx, by, newVal);
795  SetBinEntries(bin, 1); // otherwise TProfile scales the value
796 
797  }
798  }
799  }
800  // record new scale
801  fScaleMax = newMax;
802  fScaleMin = newMin;
803 
804  // set max/min
805  SetMaximum(newMax);
806  SetMinimum(newMin);
807 
808  // trigger re-paint of canvas
809  // --------------------------------------
810  // DO NOT CALL gPad->Update() HERE THIS
811  // BROUGHT FORTH DRAGONS FROM THE DEPTHS
812  // --------------------------------------
813  if(gPad){
814  gPad->Modified();
815  }
816  }
817 }
818 
819 
820 
821 
822 
823 void AntarcticaBackground::updateToolTip(Int_t event, Int_t x, Int_t y, const char* extraInfo){
824 
825  if(fUseToolTip){
826  Double_t easting = gPad->AbsPixeltoX(x);
827  Double_t northing = gPad->AbsPixeltoY(y);
828  Double_t val = GetBinContent(FindBin(easting, northing));
829  // gPad->AbsPixeltoX(y);
830  Double_t lon, lat;
831  RampdemReader::EastingNorthingToLonLat(easting, northing, lon, lat);
832 
833  TString theToolTipText = Form("Lon %4.2lf\nLat %4.2lf\n%4.2f%s", lon, lat, val, fToolTipUnits.Data());
834 
835  if(extraInfo!=NULL){
836  theToolTipText += TString::Format("\n%s", extraInfo);
837  }
838 
839  if(!fToolTip){
840  SetToolTip(true);
841  }
842  fToolTip->SetText(theToolTipText.Data());
843  TCanvas* theCan = gPad->GetCanvas();
844  Int_t topX = theCan->GetWindowTopX();
845  Int_t topY = theCan->GetWindowTopY();
846 
847  const int xOffset = 10;
848  const int yOffset = 10 + fToolTip->GetHeight()/2;
849 
850 
851  fToolTip->Show(topX + x + xOffset, topY + y + yOffset);
852 
853  }
854  TProfile2D::ExecuteEvent(event, x, y);
855 }
856 
857 
858 
859 
863 void AntarcticaBackground::setToolTipUnits(){
864  TString tempAxisTitle(RampdemReader::dataSetToAxisTitle(fDataSet));
865  TObjArray* tokens = tempAxisTitle.Tokenize("(");
866 
867  Bool_t gotUnits = false;
868  int nTokens = tokens->GetEntries();
869  // std::cout << tempAxisTitle << "\t" << nTokens << std::endl;
870  if(nTokens > 1){
871  TString afterOpenParen = ((TObjString*) tokens->At(1))->GetString();
872  TObjArray* tokens2 = afterOpenParen.Tokenize(")");
873  int nTokens2 = tokens2->GetEntries();
874  // std::cout << afterOpenParen << "\t" << nTokens2 << std::endl;
875  if(nTokens2 > 0){
876  fToolTipUnits = " (" + TString(((TObjString*) tokens2->At(0))->GetString()) + ")";
877  gotUnits = true;
878  }
879  // std::cout << "I set it to be " << fToolTipUnits.Data() << std::endl;
880  delete tokens2;
881  }
882  delete tokens;
883 
884  if(!gotUnits){
885  fToolTipUnits = "";
886  }
887 }
void ExecuteEvent(Int_t event, Int_t x, Int_t y)
static void getNumXY(Int_t &numX, Int_t &numY, RampdemReader::dataSet dataSet=rampdem)
virtual void Draw(Option_t *opt="")
static void getMapCoordinates(double &xMin, double &yMin, double &xMax, double &yMax, RampdemReader::dataSet=rampdem)
void scale(double newMin, double newMax)
Does not persist in ROOT!
void ResetColorAxis(bool trigger_redraw=false)
static const char * dataSetToAxisTitle(RampdemReader::dataSet dataSet)
static TProfile2D * fillThisHist(TProfile2D *theHist, RampdemReader::dataSet dataSet)
virtual void SetPoint(Int_t i, Double_t lon, Double_t lat)
static void EastingNorthingToLonLat(Double_t easting, Double_t northing, Double_t &lon, Double_t &lat)