RampdemReader.cxx
1 // RampdemReader.cxx :
3 //
4 // More code stolen from Stephen's Antarctica.cxx
5 // that will read in Rampdem data to use with
6 // UsefulAdu5Pat.cxx to locate sources on the continent
7 //
8 //
10 
11 
12 #include <iostream>
13 #include <fstream>
14 #include <vector>
15 #include <algorithm>
16 #include <cstring>
17 #include "TMath.h"
18 #include "RampdemReader.h"
19 #include "AnitaGeomTool.h"
20 #include "TProfile2D.h"
21 #include "TGaxis.h"
22 #include "TStyle.h"
23 #include "TColor.h"
24 
25 
26 
27 // Typedefs for parsing the surface data
28 typedef std::vector<std::vector<short> > VecVec;
29 typedef std::map<RampdemReader::dataSet, VecVec > DataMap;
30 static DataMap bedMap2Data;
31 typedef std::map<RampdemReader::dataSet, Double_t> HeaderMap;
32 
33 static HeaderMap numXs;
34 static HeaderMap numYs;
35 static HeaderMap noDatas;
36 static HeaderMap minXs;
37 static HeaderMap minYs;
38 static HeaderMap maxXs;
39 static HeaderMap maxYs;
40 static HeaderMap cellSizes;
41 
42 
43 // static functions to read in the data / generic fill histogram function.
44 static const VecVec& getDataIfNeeded(RampdemReader::dataSet dataSet);
45 
46 
47 
48 
49 //Variables for conversion between polar stereographic coordinates and lat/lon.
50 // Conversion equations from ftp://164.214.2.65/pub/gig/tm8358.2/TM8358_2.pdf
51 
52 // scale factor at pole corresponding to 71 deg S latitude of true scale (used in both BEDMAP and RAMP DEM)
53 static double scale_factor=0.97276901289;
54 
55 static double ellipsoid_inv_f = 298.257223563; //of Earth
56 
57 // static double ellipsoid_b = R_EARTH*(1-(1/ellipsoid_inv_f)); // Unused.
58 
59 static double eccentricity = sqrt((1/ellipsoid_inv_f)*(2-(1/ellipsoid_inv_f)));
60 
61 static double a_bar = pow(eccentricity,2)/2 + 5*pow(eccentricity,4)/24 + pow(eccentricity,6)/12 + 13*pow(eccentricity,8)/360;
62 
63 static double b_bar = 7*pow(eccentricity,4)/48 + 29*pow(eccentricity,6)/240 + 811*pow(eccentricity,8)/11520;
64 
65 static double c_bar = 7*pow(eccentricity,6)/120 + 81*pow(eccentricity,8)/1120;
66 
67 static double d_bar = 4279*pow(eccentricity,8)/161280;
68 
69 static double c_0 = (2*R_EARTH / sqrt(1-pow(eccentricity,2))) * pow(( (1-eccentricity) / (1+eccentricity) ),eccentricity/2);
70 
71 // Varies with latitude, defined here for 71 deg S...
72 // static double R_factor = scale_factor*c_0 * pow(( (1 + eccentricity*sin(71*TMath::RadToDeg())) / (1 - eccentricity*sin(71*TMath::RadToDeg())) ),eccentricity/2) * tan((TMath::Pi()/4) - (71*TMath::RadToDeg())/2);
73 
74 // static double nu_factor = R_factor / cos(71*TMath::RadToDeg());
75 
76 
77 
78 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
106  fgInstance=this;
107 }
108 
109 
115 
116 
117 
125  //static function
126  return (fgInstance) ? (RampdemReader*) fgInstance : new RampdemReader();
127 }
128 
129 
130 
131 
132 
133 
134 
135 
136 
137 
138 
139 
148 Double_t RampdemReader::Surface(Double_t lon,Double_t lat) {
149  return (SurfaceAboveGeoid(lon,lat) + Geoid(lat));
150 }
151 
152 
153 
154 
155 
164 Double_t RampdemReader::BilinearInterpolatedSurfaceAboveGeoid(Double_t lon, Double_t lat, RampdemReader::dataSet dataSet) {
165 
166  Double_t easting, northing;
167  LonLatToEastingNorthing(lon, lat, easting, northing);
168  return BilinearInterpolatedSurfaceAboveGeoidEastingNorthing(easting, northing, dataSet);
169 }
170 
179 Double_t RampdemReader::BilinearInterpolatedSurfaceAboveGeoidEastingNorthing(Double_t easting, Double_t northing, RampdemReader::dataSet dataSet) {
180 
181  getDataIfNeeded(dataSet);
182  const VecVec& surface_elevation = bedMap2Data[dataSet];
183 
184  Int_t x_min = minXs[dataSet];
185  Int_t y_min = minYs[dataSet];
186  Int_t cell_size = cellSizes[dataSet];
187 
188  Double_t non_integer_e_coord = (easting - x_min) / cell_size;
189  Double_t non_integer_n_coord = (-1*northing - y_min) / cell_size;
190 
191  Int_t e1 = floor(non_integer_e_coord);
192  Int_t n1 = floor(non_integer_n_coord);
193  Int_t e2 = e1 + 1;
194  Int_t n2 = n1 + 1;
195 
196  // std::cout << e1 << "\t" << e2 << "\t\t" << n1 << "\t" << n2 << std::endl;
197 
198  double q11, q12, q21, q22;
199 
200  Int_t nCols_surface = dataSet == rampdem ? numYs[dataSet] : numXs[dataSet];
201  Int_t nRows_surface = dataSet == rampdem ? numXs[dataSet] : numYs[dataSet];
202  bool e1Good = e1 >= 0 && e1 <nCols_surface;
203  bool e2Good = e2 >= 0 && e2 <nCols_surface;
204  bool n1Good = n1 >= 0 && n1 <nRows_surface;
205  bool n2Good = n2 >= 0 && n2 <nRows_surface;
206 
207  if(dataSet==rampdem){
208  q11 = e1Good && n1Good ? double(surface_elevation[e1][n1]) : -9999;
209  q12 = e1Good && n2Good ? double(surface_elevation[e1][n2]) : -9999;
210  q21 = e2Good && n1Good ? double(surface_elevation[e2][n1]) : -9999;
211  q22 = e2Good && n2Good ? double(surface_elevation[e2][n2]) : -9999;
212  }
213  else{
214  q11 = e1Good && n1Good ? double(surface_elevation[n1][e1]) : -9999;
215  q12 = e1Good && n2Good ? double(surface_elevation[n1][e2]) : -9999;
216  q21 = e2Good && n1Good ? double(surface_elevation[n2][e1]) : -9999;
217  q22 = e2Good && n2Good ? double(surface_elevation[n2][e2]) : -9999;
218  }
219 
220  double easting1 = e1*cell_size + x_min;
221  double easting2 = e2*cell_size + x_min;
222  double northing1 = -n1*cell_size - y_min;
223  double northing2 = -n2*cell_size - y_min;
224 
225  // this image is very helpful to visualize what's going on here
226  // https://en.wikipedia.org/wiki/Bilinear_interpolation#/media/File:Comparison_of_1D_and_2D_interpolation.svg
227  // need to do three linear interpolations...
228  double dEasting = easting - easting1;
229  double dNorthing = northing - northing1;
230  double deltaEasting = easting2 - easting1;
231  double deltaNorthing = northing2 - northing1;
232 
233  double q11_q21_interp = q11 + dEasting*(q21 - q11)/(deltaEasting);
234  double q12_q22_interp = q12 + dEasting*(q22 - q12)/(deltaEasting);
235  double bilinearlyInterpolatedSurface = q11_q21_interp + dNorthing*(q12_q22_interp - q11_q21_interp)/(deltaNorthing);
236  return bilinearlyInterpolatedSurface;
237 }
238 
239 
240 
249 Double_t RampdemReader::SurfaceAboveGeoid(Double_t lon, Double_t lat, RampdemReader::dataSet dataSet) {
250 
251  Double_t easting, northing;
252  LonLatToEastingNorthing(lon, lat, easting, northing);
253  return SurfaceAboveGeoidEN(easting, northing, dataSet);
254 }
255 
256 
265 Double_t RampdemReader::SurfaceAboveGeoidEN(Double_t Easting, Double_t Northing, RampdemReader::dataSet dataSet)
266 {
267  getDataIfNeeded(dataSet);
268  const VecVec& surface_elevation = bedMap2Data[dataSet];
269 
270  Int_t nCols_surface = dataSet == rampdem ? numYs[dataSet] : numXs[dataSet];
271  Int_t nRows_surface = dataSet == rampdem ? numXs[dataSet] : numYs[dataSet];
272 
273  Double_t surface=0;
274 
275  Int_t e_coord_surface=0;
276  Int_t n_coord_surface=0;
277  EastingNorthingToEN(Easting,Northing,e_coord_surface,n_coord_surface, dataSet);
278 
279  if(e_coord_surface >= nCols_surface || e_coord_surface <0){
280 // std::cerr<<"[RampdemReader::surfaceAboveGeoid] Error! Trying to access x-element "<<e_coord_surface<<" of the RAMP DEM data! (Longitude, latitude = "<<lon<<", "<<lat<<")\n";
281  return -9999;
282  }
283  else if(n_coord_surface >= nRows_surface || n_coord_surface <0){
284  // std::cerr<<"[RampdemReader::surfaceAboveGeoid] Error! Trying to access y-element "<<n_coord_surface<<" of the RAMP DEM data! (Longitude, latitude = "<<lon<<", "<<lat<<")\n";
285  return -9999;
286  }
287  else{
288  if(dataSet==rampdem){
289  surface = double(surface_elevation[e_coord_surface][n_coord_surface]);
290  }
291  else{
292  surface = double(surface_elevation[n_coord_surface][e_coord_surface]);
293  }
294  }
295 
296  return surface;
297 }
298 
299 
300 
301 
302 
303 
311 Double_t RampdemReader::Geoid(Double_t latitude) {
312  return (GEOID_MIN*GEOID_MAX/sqrt(pow(GEOID_MIN,2)-(pow(GEOID_MIN,2)-pow(GEOID_MAX,2))*pow(cos(latitude*TMath::DegToRad()),2)));
313 }
314 
315 
316 
317 
318 
319 
327 
328  // std::cerr << __PRETTY_FUNCTION__ << std::endl;
329 
330  char calibDir[FILENAME_MAX];
331  char *calibEnv=getenv("ANITA_CALIB_DIR");
332  if(!calibEnv) {
333  char *utilEnv=getenv("ANITA_UTIL_INSTALL_DIR");
334  if(!utilEnv){
335  sprintf(calibDir,"calib");
336  }
337  else{
338  sprintf(calibDir,"%s/share/anitaCalib",utilEnv);
339  }
340  }
341  else {
342  strncpy(calibDir,calibEnv,FILENAME_MAX);
343  }
344 
345  char dem_filename[FILENAME_MAX];
346  char header_filename[FILENAME_MAX];
347 
348  std::ifstream dem_data;
349  std::ifstream dem_header;
350 
351  sprintf(dem_filename,"%s/ramp1kmdem_wgs_v2.bin",calibDir);
352  sprintf(header_filename,"%s/ramp1kmdem_wgs_v2.hdr",calibDir);
353 
354  /*
355  Open header and binary files.
356  Check to make sure the opening was successful, and return
357  error code 1 if it wasn't.
358  */
359 
360  dem_header.open(header_filename);
361  if (!dem_header.is_open()){
362  std::cerr << "[RampdemReader::readRAMPDEM] Error! Could not open header file " << header_filename
363  << "! Exiting method.\n";
364  return 1;
365  }
366 
367  dem_data.open(dem_filename, std::ios::in | std::ios::binary );
368  if (!dem_data.is_open()){
369  std::cerr << "[RampdemReader::readRAMPDEM] Error! Could not open binary data file " << dem_filename
370  << "! Exiting method.\n";
371  return 1;
372  }
373 
374 
375  // Read the header.
376  // An equals sign preceeds each interesting number, so we can ignore everything up to that.
377 
378  double cell_size, x_min, x_max, y_min, y_max, min_value, max_value, mean, std_deviation;
379  int nRows_surface, nCols_surface, nBytes_surface;
380  dem_header.ignore( 5000, '=');
381  dem_header >> cell_size;
382  dem_header.ignore( 5000, '=');
383  dem_header >> nRows_surface;
384  dem_header.ignore( 5000, '=');
385  dem_header.ignore( 5000, '=');
386  dem_header >> nCols_surface;
387  dem_header.ignore( 5000, '=');
388  dem_header >> nBytes_surface;
389  dem_header.ignore( 5000, '=');
390  dem_header >> x_min;
391  dem_header.ignore( 5000, '=');
392  dem_header >> min_value;
393  dem_header.ignore( 5000, '=');
394  dem_header >> x_max;
395  dem_header.ignore( 5000, '=');
396  dem_header >> max_value;
397  dem_header.ignore( 5000, '=');
398  dem_header >> y_min;
399  dem_header.ignore( 5000, '=');
400  dem_header >> mean;
401  dem_header.ignore( 5000, '=');
402  dem_header >> y_max;
403  dem_header.ignore( 5000, '=');
404  dem_header >> std_deviation;
405 
406  numXs[RampdemReader::rampdem] = nRows_surface;
407  numYs[RampdemReader::rampdem] = nCols_surface;
408  minXs[RampdemReader::rampdem] = x_min;
409  minYs[RampdemReader::rampdem] = y_min;
410  maxXs[RampdemReader::rampdem] = x_max;
411  maxYs[RampdemReader::rampdem] = y_max;
412  cellSizes[RampdemReader::rampdem] = cell_size;
413  noDatas[RampdemReader::rampdem] = -9999; // by hand
414 
415  // emptry VecVec is now initially put in by the getDataIfNeeded function
416  // bedMap2Data[RampdemReader::rampdem] = VecVec();
417 
418  VecVec& surface_elevation = bedMap2Data[RampdemReader::rampdem];
419 
420  /* Now that we know the size of the grid, allocate the memory to store it. */
421  surface_elevation = std::vector< std::vector<short> >(nCols_surface, std::vector<short>(nRows_surface, 0 ) );
422 
423  /* Read in the data and store it to the vector. */
424  short temp_data=0;
425  for (unsigned int row_index=0; row_index < surface_elevation[0].size(); ++row_index){
426  for (unsigned int column_index=0; column_index < surface_elevation.size(); ++column_index){
427  if (!dem_data.read( (char *)&temp_data, sizeof(short) )){
428  std::cerr << "[RampdemReader::readRAMPDEM] Error! Read from data file failed! Row " << row_index
429  << ", column " << column_index << ".\n";
430  return 2;
431  }
432  flipEndian(temp_data);
433  surface_elevation[column_index][row_index] = temp_data;
434  }
435  }
436  if(dem_data.read((char*)&temp_data, sizeof(short))){
437  std::cerr << "[RampdemReader::readRAMPDEM] Error! I could read a value (" << temp_data
438  << ") from the data file after I thought that it was empty!.\n";
439  return 2;
440  }
441 
442  dem_header.close();
443  dem_data.close();
444 
445  return 0;
446 }
447 
448 
449 
450 
458 Double_t RampdemReader::Area(Double_t latitude, RampdemReader::dataSet dataSet) {
459 
460  getDataIfNeeded(dataSet);
461  Double_t cell_size = cellSizes[dataSet];
462 
463  Double_t lat_rad = -latitude * TMath::DegToRad();
464 
465  return (pow(cell_size* ((1 + sin(71*TMath::DegToRad())) / (1 + sin(lat_rad))),2));
466 }
467 
468 
469 
481 // void RampdemReader::LonLattoEN(Double_t lon, Double_t lat, int& e_coord, int& n_coord) {
482 void RampdemReader::LonLattoEN(Double_t lon, Double_t lat, int& e_coord, int& n_coord, RampdemReader::dataSet dataSet) {
483 
484  getDataIfNeeded(dataSet);
485 
486  Double_t easting=0;
487  Double_t northing=0;
488 
489  LonLatToEastingNorthing(lon,lat,easting,northing);
490  EastingNorthingToEN(easting,northing,e_coord,n_coord, dataSet);
491 
492 }
493 
494 
495 
496 
497 
498 
508 void RampdemReader::EastingNorthingToEN(Double_t easting,Double_t northing,Int_t &e_coord,Int_t &n_coord, RampdemReader::dataSet dataSet){
509 
510  getDataIfNeeded(dataSet);
511 
512  Int_t x_min = minXs[dataSet];
513  Int_t y_min = minYs[dataSet];
514  Int_t cell_size = cellSizes[dataSet];
515 
516  e_coord = (int)((easting - x_min) / cell_size);
517  n_coord = (int)((-1*northing - y_min) / cell_size);
518 
519  // std::cout << easting << "\t" << northing << "\t" << e_coord << "\t" << n_coord << std::endl;
520 }
521 
522 
523 
524 
525 
526 
527 
536 void RampdemReader::LonLatToEastingNorthing(Double_t lon,Double_t lat,Double_t &easting,Double_t &northing){
537 
538  Double_t lon_rad = lon * TMath::DegToRad(); //convert to radians
539  Double_t lat_rad = -lat * TMath::DegToRad();
540 
541  const double R_factor = scale_factor*c_0 * pow(( (1 + eccentricity*sin(lat_rad)) / (1 - eccentricity*sin(lat_rad)) ),eccentricity/2) * tan((TMath::Pi()/4) - lat_rad/2);
542 
543  easting = R_factor * sin(lon_rad);
544  northing = R_factor * cos(lon_rad);
545 
546 }
547 
548 
549 
550 
551 
562 void RampdemReader::ENtoLonLat(Int_t e_coord, Int_t n_coord, Double_t& lon, Double_t& lat, RampdemReader::dataSet dataSet) {
563  //
564 
565  getDataIfNeeded(dataSet);
566  Double_t x_min = minXs[dataSet];
567  Double_t y_min = minYs[dataSet];
568  Double_t cell_size = cellSizes[dataSet];
569 
570  Double_t isometric_lat=0;
571  Double_t easting = x_min+(cell_size*(e_coord+0.5)); //Add offset of 0.5 to get coordinates of middle of cell instead of edges.
572  Double_t northing = -1*(y_min+(cell_size*(n_coord+0.5)));
573 
574  //first set longitude
575 
576  if (northing!=0)
577  lon = atan(easting/northing);
578  else
579  lon = 90*TMath::DegToRad();
580 
581 
582  if (easting > 0 && lon < 0) //adjust sign of longitude
583  lon += TMath::Pi();
584  else if (easting < 0 && lon > 0)
585  lon -= TMath::Pi();
586  else if (easting == 0 && northing < 0)
587  lon += TMath::Pi();
588 
589  //now find latitude
590  double R_factor = 0;
591  if (easting != 0)
592  R_factor = TMath::Abs(easting/sin(lon));
593  else if (easting == 0 && northing != 0)
594  R_factor = TMath::Abs(northing);
595  else {
596  lat = 0; //at the pole, set lat=0 degrees
597  lon = lon*TMath::RadToDeg();
598  return;
599  } //else
600 
601  isometric_lat = (TMath::Pi()/2) - 2*atan(R_factor/(scale_factor*c_0));
602 
603  lat = isometric_lat + a_bar*sin(2*isometric_lat) + b_bar*sin(4*isometric_lat) + c_bar*sin(6*isometric_lat) + d_bar*sin(8*isometric_lat);
604 
605  lon = lon * TMath::RadToDeg(); //convert to degrees
606  lat = -lat*TMath::RadToDeg(); //convert to degrees, with -90 degrees at the south pole
607  return;
608 } //method ENtoLonLat
609 
610 
611 
612 
613 
614 
623 void RampdemReader::EastingNorthingToLonLat(Double_t easting,Double_t northing,Double_t &lon,Double_t &lat){
624 
625  double lon_rad = atan2(easting,northing);
626  lon = lon_rad * TMath::RadToDeg();
627  double R_factor = sqrt(easting*easting+northing*northing);
628  double isometric_lat = (TMath::Pi()/2) - 2*atan(R_factor/(scale_factor*c_0));
629  lat = isometric_lat + a_bar*sin(2*isometric_lat) + b_bar*sin(4*isometric_lat) + c_bar*sin(6*isometric_lat) + d_bar*sin(8*isometric_lat);
630  lat = -lat*TMath::RadToDeg(); //convert to degrees, with -90 degrees at the south pole
631  return;
632 }
633 
634 
635 
636 
637 
638 
639 
651 TProfile2D *RampdemReader::rampMap(int coarseness, int set_log_scale, UInt_t &xBins, UInt_t &yBins){
652 
653  TProfile2D* theHist = getMap(RampdemReader::rampdem, coarseness);
654 
655  xBins = theHist->GetNbinsX();
656  yBins = theHist->GetNbinsY();
657 
658  if(set_log_scale){
659  for(UInt_t bx = 1; bx <= xBins; bx++){
660  for(UInt_t by = 1; by <= yBins; by++){
661  double val = theHist->GetBinContent(bx, by);
662  val += 1000; // avoid negative numbers
663  theHist->SetBinContent(bx, by, TMath::Log10(val));
664  }
665  }
666  }
667 
668  theHist->SetStats(0);
669 
670  return theHist;
671 
672 }
673 
674 
675 
676 
694 TProfile2D *RampdemReader::rampMapPartial(int coarseness,
695  double centralLon, double centralLat, double rangeMetres,
696  Int_t &xBins, Int_t &yBins,
697  Double_t &xMin, Double_t &xMax,
698  Double_t &yMin,Double_t &yMax){
699 
700 
701  TProfile2D* theHist = getMapPartial(RampdemReader::rampdem, coarseness, centralLon, centralLat, rangeMetres);
702  xBins = theHist->GetNbinsX();
703  yBins = theHist->GetNbinsY();
704  xMin = theHist->GetXaxis()->GetBinLowEdge(1);
705  xMax = theHist->GetXaxis()->GetBinLowEdge(xBins+1);
706  yMin = theHist->GetYaxis()->GetBinLowEdge(1);
707  yMax = theHist->GetYaxis()->GetBinLowEdge(yBins+1);
708 
709  return theHist;
710 
711 }
712 
713 
714 
715 
716 
717 
718 TGaxis *RampdemReader::distanceScale(Double_t xMin,Double_t xMax,Double_t yMin,Double_t yMax){
719  //here xmin, xmax etc are the positions in easting/northing of the distance scale
720  if(xMax<=xMin && yMax<=yMin) {
721  std::cerr << "size ordering wrong: xMin " << xMin << " xMax " << xMax << " yMin " << yMin << " yMax " << yMax << std::endl;
722  return NULL;
723  }
724 
725  TGaxis *theAxis = new TGaxis(xMin,yMin,xMax,yMax,0,sqrt((xMax-xMin)/1e3*(xMax-xMin)/1e3-(yMax-yMin)/1e3*(yMax-yMin)/1e3),2,"");
726  theAxis->SetTitle("km");
727 
728  return theAxis;
729 }
730 
731 
732 
742 void RampdemReader::getMapCoordinates(double &xMin, double &yMin,
743  double &xMax, double &yMax,
744  RampdemReader::dataSet dataSet){
745 
746 
747 
748  getDataIfNeeded(dataSet);
749  xMin = minXs[dataSet];
750  yMin = minYs[dataSet];
751  xMax = maxXs[dataSet];
752  yMax = maxYs[dataSet]+cellSizes[dataSet];
753 
754 }
755 
756 
757 
758 
766 void RampdemReader::getNumXY(Int_t& numX, Int_t&numY,
767  RampdemReader::dataSet dataSet){
768 
769  getDataIfNeeded(dataSet);
770  numX = numXs[dataSet];
771  numY = numYs[dataSet];
772 
773 }
774 
775 
776 
777 
778 
779 
780 
781 
782 
783 
785 //
786 // BEDMAP 2 STUFF
787 //
789 
790 
791 
792 
800 static const char* dataSetToString(RampdemReader::dataSet dataSet){
801 
802  switch(dataSet){
803  case RampdemReader::rampdem:
804  return "rampdem";
805  case RampdemReader::bed:
806  return "bed";
807  // case RampdemReader::coverage:
808  // return "coverage";
809  // case RampdemReader::grounded_bed_uncertainty:
810  // return "grounded_bed_uncertainty";
811  case RampdemReader::icemask_grounded_and_shelves:
812  return "icemask_grounded_and_shelves";
813  // case RampdemReader::lakemask_vostok:
814  // return "lakemask_vostok";
815  // case RampdemReader::rockmask:
816  // return "rockmask";
817  case RampdemReader::surface:
818  return "surface";
819  case RampdemReader::thickness:
820  return "thickness";
821  // case RampdemReader::bedmap2_thickness_uncertainty_5km:
822  // return "bedmap2_thickness_uncertainty_5km";
823  default:
824  std::cerr << "Error in " << __FILE__ << ", unknown RampdemReader::dataSet requested" << std::endl;
825  return NULL;
826  }
827 }
828 
829 
830 
838 const char* RampdemReader::dataSetToAxisTitle(RampdemReader::dataSet dataSet){
839  // from the bedmap2 readme
840 
841  switch(dataSet){
842  case RampdemReader::rampdem:
843  return "Surface height (m)";
844  case RampdemReader::bed:
845  return "Bed height (m)";
846  // case RampdemReader::coverage:
847  // return "Ice coverage data";
848  // case RampdemReader::grounded_bed_uncertainty:
849  // return "Bed Uncertainty Grid (m)";
850  case RampdemReader::icemask_grounded_and_shelves:
851  return "Grounding line and floating ice shelves";
852  // case RampdemReader::lakemask_vostok:
853  // return "lakemask_vostok";
854  // case RampdemReader::rockmask:
855  // return "Rock Outcrops (m)";
856  case RampdemReader::surface:
857  return "Surface height (m)";
858  case RampdemReader::thickness:
859  return "Ice thickness (m)";
860  // case RampdemReader::bedmap2_thickness_uncertainty_5km:
861  // return "Ice thickness uncertainty";
862  default:
863  std::cerr << "Error in " << __FILE__ << ", unknown RampdemReader::dataSet requested" << std::endl;
864  return NULL;
865 
866  }
867 }
868 
869 
870 
871 
872 
882 static const VecVec& getDataIfNeeded(RampdemReader::dataSet dataSet){
883 
884 
885  // If we haven't initialized the map with empty vectors, do it here
886  if(bedMap2Data.size()==0){
887  bedMap2Data[RampdemReader::rampdem] = VecVec();
888  bedMap2Data[RampdemReader::bed] = VecVec();
889  // bedMap2Data[RampdemReader::coverage] = VecVec();
890  // bedMap2Data[RampdemReader::grounded_bed_uncertainty] = VecVec();
891  bedMap2Data[RampdemReader::icemask_grounded_and_shelves] = VecVec();
892  // bedMap2Data[RampdemReader::lakemask_vostok] = VecVec();
893  // bedMap2Data[RampdemReader::rockmask] = VecVec();
894  bedMap2Data[RampdemReader::surface] = VecVec();
895  bedMap2Data[RampdemReader::thickness] = VecVec();
896  }
897 
898 
899  DataMap::iterator it = bedMap2Data.find(dataSet);
900  if(it==bedMap2Data.end()){
901  std::cerr << "Error in " << __FILE__ << ", unable to find requested data set!" << std::endl;
902  // std::cerr << it->first << std::endl;
903  }
904 
905  VecVec& data = it->second;
906 
907  // special case for old rampdem data...
908  if(dataSet==RampdemReader::rampdem){
909  if(data.size()==0){
911  }
912  return data;
913  }
914 
915 
916  if(data.size() == 0){
917  const char* anitaEnv = "ANITA_UTIL_INSTALL_DIR";
918  const char* anitaUtilInstallDir = getenv(anitaEnv);
919  if(anitaUtilInstallDir==NULL){
920  std::cerr << "Error in " << __FILE__ << ", could not find environment variable " << anitaEnv << std::endl;
921  }
922 
923 
924  // Start with the anita install directory...
925  std::string fileName(anitaUtilInstallDir);
926  // ... append the calib subdir
927  fileName.append("/share/anitaCalib/bedmap2_bin/bedmap2_");
928 
929  // append the appropriate filename
930  const char* dataName = dataSetToString(dataSet);
931  fileName.append(dataName);
932 
933  // Header file suffix
934  std::string headName = fileName;
935  headName.append(".hdr");
936 
937 
938  // Open header file
939  std::ifstream header(headName.c_str());
940  if(!header.is_open()){
941  std::cerr << "Error! Unable to open file " << headName << std::endl;
942  std::cerr << "The BEDMAP2 data set is large and not bundled with anitaEventCorrelator by default." << std::endl;
943  std::cerr << "To download the BEDMAP2 data set and have it installed in the proper place, run the script anitaEventCorrelator/downloadBEDMAP2subset.sh" << std::endl;
944  std::cerr << "If you have a slow internet connection, beware, the total size of the files is ~50MB." << std::endl;
945  std::cerr << "See https://github.com/anitaNeutrino/subsetOfBedmap2Data for more information." << std::endl;
946  }
947  else{
948 
949  // Parse and store variables
950  do{
951  std::string key, value;
952  header >> key >> value;
953 
954  // Think these are all we care about...
955  if(key=="ncols"){
956  numXs[dataSet] = atoi(value.c_str());
957  }
958  else if(key=="nrows"){
959  numYs[dataSet] = atoi(value.c_str());
960  }
961  else if(key=="NODATA_value"){
962  noDatas[dataSet] = atoi(value.c_str());
963  }
964  else if(key=="xllcorner"){
965  minXs[dataSet]= atoi(value.c_str());
966  }
967  else if(key=="yllcorner"){
968  minYs[dataSet] = atoi(value.c_str());
969  }
970  else if(key=="cellsize"){
971  cellSizes[dataSet] = atoi(value.c_str());
972  }
973  // std::cout << key << "\t" << value << "\t" << header.eof() << std::endl;
974  } while(!header.eof());
975 
976 
977  // Calculate other edge points.
978  maxXs[dataSet] = minXs[dataSet] + numXs[dataSet]*cellSizes[dataSet];
979  maxYs[dataSet] = minYs[dataSet] + numYs[dataSet]*cellSizes[dataSet];
980 
981  // Now get data file...
982  fileName.append(".flt");
983  FILE* fBedMap2 = fopen(fileName.c_str(), "r");
984  if(fBedMap2==NULL){
985  std::cerr << "Error in " << __FILE__ << ", could not open file " << fileName << std::endl;
986  }
987  else{
988  // int nCols = bedMap2Headers[HeaderKey(dataSet, "nrows")];
989  // int nRows = bedMap2Headers[HeaderKey(dataSet, "ncols")];
990 
991  const int numX = numXs[dataSet];
992  const int numY = numYs[dataSet];
993 
994  std::vector<float> tempData(numX, 0);
995 
996  for(int y=0; y < numY; y++){
997  fread(&tempData[0], sizeof(float), numX, fBedMap2);
998  data.push_back(std::vector<short>(numX, 0));
999 
1000  for(int x = 0; x < numX; x++){
1001  data.at(y).at(x) = short(tempData.at(x));
1002  }
1003  }
1004 
1005  fclose(fBedMap2);
1006  }
1007  }
1008  }
1009  return data;
1010 }
1011 
1012 
1013 
1014 
1015 
1016 
1026 TProfile2D* RampdemReader::fillThisHist(TProfile2D* theHist, RampdemReader::dataSet dataSet){
1027 
1028  const VecVec& data = getDataIfNeeded(dataSet);
1029  if(data.size() > 0){
1030  Double_t cellSize = cellSizes[dataSet];
1031 
1032  Int_t xBins = numXs[dataSet];
1033  Int_t yBins = numYs[dataSet];
1034 
1035  Double_t xMin = minXs[dataSet];
1036  Double_t yMin = minYs[dataSet];
1037 
1038  // Double_t xMax = maxXs[dataSet];
1039  // Double_t yMax = maxYs[dataSet];
1040  Double_t noData = noDatas[dataSet];
1041 
1042  if(dataSet==RampdemReader::rampdem){
1043  for(UInt_t yBin=0; yBin < data.at(0).size(); yBin++){
1044  for(UInt_t xBin=0; xBin < data.size(); xBin++){
1045 
1046  theHist->Fill(xMin + double(xBin)*cellSize,
1047  -(yMin + double(yBin)*cellSize),
1048  data.at(xBin).at(yBin));
1049  }
1050  }
1051  }
1052  else{
1053  for(Int_t yBin=0; yBin < yBins; yBin++){
1054  for(Int_t xBin=0; xBin < xBins; xBin++){
1055  if(data[yBin][xBin] != noData){
1056  theHist->Fill(xMin + double(xBin)*cellSize,
1057  -(yMin + double(yBin)*cellSize),
1058  data[yBin][xBin]);
1059  }
1060  }
1061  }
1062  }
1063  }
1064  theHist->SetStats(0);
1065 
1066  return theHist;
1067 
1068 }
1069 
1070 
1071 
1072 
1081 TProfile2D* RampdemReader::getMap(RampdemReader::dataSet dataSet, int coarseness){
1082 
1083  getDataIfNeeded(dataSet);
1084 
1085  Int_t xBins = numXs[dataSet];
1086  Int_t yBins = numYs[dataSet];
1087 
1088  Double_t xMin = minXs[dataSet];
1089  Double_t yMin = minYs[dataSet];
1090 
1091  Double_t xMax = maxXs[dataSet];
1092  Double_t yMax = maxYs[dataSet];
1093  Double_t cellSize = cellSizes[dataSet];
1094 
1095  TString hName = TString::Format("h_%s_%d", dataSetToString(dataSet), coarseness);
1096  TProfile2D * theHist = new TProfile2D(hName, "",
1097  xBins/coarseness, xMin, xMax,
1098  yBins/coarseness, yMin, yMax+cellSize);
1099 
1100  fillThisHist(theHist, dataSet);
1101  theHist->SetDirectory(0);
1102  return theHist;
1103 
1104 }
1105 
1106 
1107 
1108 
1109 
1110 
1111 
1112 
1124 TProfile2D* RampdemReader::getMapPartial(RampdemReader::dataSet dataSet, int coarseness,
1125  double centralLon, double centralLat, double rangeMetres){
1126 
1127  Int_t central_e_coord,central_n_coord;
1128  LonLattoEN(centralLon, centralLat, central_e_coord, central_n_coord, dataSet);
1129 
1130  Double_t central_easting,central_northing;
1131  LonLatToEastingNorthing(centralLon, centralLat, central_easting, central_northing);
1132 
1133  Int_t max_e_coord, max_n_coord;
1134  EastingNorthingToEN(central_easting + rangeMetres, central_northing + rangeMetres,
1135  max_e_coord, max_n_coord, dataSet);
1136 
1137  Int_t min_e_coord, min_n_coord;
1138  EastingNorthingToEN(central_easting - rangeMetres, central_northing - rangeMetres,
1139  min_e_coord, min_n_coord, dataSet);
1140 
1141  if(max_e_coord<min_e_coord){
1142  Int_t swap_e = max_e_coord;
1143  max_e_coord = min_e_coord;
1144  min_e_coord = swap_e;
1145  }
1146  if(max_n_coord<min_n_coord){
1147  Int_t swap_n = max_n_coord;
1148  max_n_coord = min_n_coord;
1149  min_n_coord = swap_n;
1150  }
1151 
1152  Int_t thisXBins = (max_e_coord-min_e_coord)/coarseness;
1153  Int_t thisYBins = (max_n_coord-min_n_coord)/coarseness;
1154 
1155  // std::cout << thisXBins << "\t" << thisYBins << std::endl;
1156  // std::cout << max_e_coord << "\t" << min_e_coord << std::endl;
1157  // std::cout << max_n_coord << "\t" << min_n_coord << std::endl;
1158  double thisXMin = central_easting - rangeMetres;
1159  double thisXMax = central_easting + rangeMetres;
1160  double thisYMin = central_northing - rangeMetres;
1161  double thisYMax = central_northing + rangeMetres;
1162 
1163  TString histName = TString::Format("h_%s_partial_%d", dataSetToString(dataSet), coarseness);
1164  TProfile2D *theHist = new TProfile2D(histName,"",
1165  thisXBins, thisXMin, thisXMax,
1166  thisYBins, thisYMin, thisYMax);
1167 
1168  fillThisHist(theHist, dataSet);
1169 
1170  return theHist;
1171 
1172 }
1173 
1174 
1175 
1186 Bool_t RampdemReader::isOnContinent(Double_t lon, Double_t lat){
1187  const VecVec& data = getDataIfNeeded(RampdemReader::surface);
1188  int e_coord, n_coord;
1189  LonLattoEN(lon, lat, e_coord, n_coord, RampdemReader::surface);
1190  // std::cout << lon << "\t" << lat << e_coord << "\t" << n_coord << std::endl;
1191 
1192  Bool_t isOnContinent = false;
1193  if(n_coord >= 0 && n_coord < numYs[RampdemReader::surface] &&
1194  e_coord >= 0 && e_coord < numXs[RampdemReader::surface]){
1195 
1196  if(data.at(n_coord).at(e_coord)!=noDatas[RampdemReader::surface]){
1197  isOnContinent = true;
1198  }
1199 
1200  }
1201  return isOnContinent;
1202 }
1203 
1204 
1215 Bool_t RampdemReader::isOnIceShelf(Double_t lon, Double_t lat){
1216  const VecVec& data = getDataIfNeeded(RampdemReader::icemask_grounded_and_shelves);
1217  int e_coord, n_coord;
1218  LonLattoEN(lon, lat, e_coord, n_coord, RampdemReader::icemask_grounded_and_shelves);
1219  // std::cout << lon << "\t" << lat << e_coord << "\t" << n_coord << std::endl;
1220 
1221  Bool_t iceShelf = false;
1222  if(n_coord >= 0 && n_coord < numYs[RampdemReader::icemask_grounded_and_shelves] &&
1223  e_coord >= 0 && e_coord < numXs[RampdemReader::icemask_grounded_and_shelves]){
1224 
1225  double val = data.at(n_coord).at(e_coord);
1226 
1227  // if(val!=noDatas[RampdemReader::icemask_grounded_and_shelves] && val!=0){
1228  if(val==1){
1229  iceShelf = true;
1230  }
1231  }
1232  return iceShelf;
1233 }
1234 
1235 
1236 
1237 
1248 Double_t RampdemReader::iceThickness(Double_t lon, Double_t lat){
1249  const VecVec& data = getDataIfNeeded(RampdemReader::thickness);
1250  int e_coord, n_coord;
1251  LonLattoEN(lon, lat, e_coord, n_coord, RampdemReader::thickness);
1252  // std::cout << lon << "\t" << lat << e_coord << "\t" << n_coord << std::endl;
1253 
1254  Double_t thickness = 0;
1255  if(n_coord >= 0 && n_coord < numYs[RampdemReader::thickness] &&
1256  e_coord >= 0 && e_coord < numXs[RampdemReader::thickness]){
1257 
1258  thickness = data.at(n_coord).at(e_coord);
1259  }
1260  return thickness;
1261 }
static TProfile2D * rampMapPartial(int coarseness_factor, double centralLon, double centralLat, double rangeMetres, Int_t &xBins, Int_t &yBins, Double_t &xMin, Double_t &xMax, Double_t &yMin, Double_t &yMax) __attribute__((deprecated))
static Double_t BilinearInterpolatedSurfaceAboveGeoid(Double_t longitude, Double_t latitude, RampdemReader::dataSet=rampdem)
static Double_t SurfaceAboveGeoidEN(Double_t Easting, Double_t Northing, RampdemReader::dataSet=rampdem)
static void getNumXY(Int_t &numX, Int_t &numY, RampdemReader::dataSet dataSet=rampdem)
static TProfile2D * rampMap(int coarseness_factor, int set_log_scale, UInt_t &xBins, UInt_t &yBins) __attribute__((deprecated))
static TProfile2D * getMap(RampdemReader::dataSet dataSet, int coarseness_factor)
static int readRAMPDEM()
static TProfile2D * getMapPartial(RampdemReader::dataSet dataSet, int coarseness, double centralLon, double centralLat, double rangeMetres)
static Double_t SurfaceAboveGeoid(Double_t longitude, Double_t latitude, RampdemReader::dataSet=rampdem)
static Double_t iceThickness(Double_t lon, Double_t lat)
static RampdemReader * Instance() __attribute__((deprecated))
Instance generator.
static void getMapCoordinates(double &xMin, double &yMin, double &xMax, double &yMax, RampdemReader::dataSet=rampdem)
static Double_t Surface(Double_t longitude, Double_t latitude)
static void LonLattoEN(Double_t lon, Double_t lat, int &e_coord, int &n_coord, RampdemReader::dataSet=rampdem)
static RampdemReader * fgInstance
Pointer to instance.
static Double_t Area(Double_t latitude, RampdemReader::dataSet=rampdem)
static Bool_t isOnContinent(Double_t lon, Double_t lat)
static void EastingNorthingToEN(Double_t easting, Double_t northing, Int_t &e_coord, Int_t &n_coord, RampdemReader::dataSet=rampdem)
static Double_t BilinearInterpolatedSurfaceAboveGeoidEastingNorthing(Double_t easting, Double_t northing, RampdemReader::dataSet=rampdem)
static const char * dataSetToAxisTitle(RampdemReader::dataSet dataSet)
static TProfile2D * fillThisHist(TProfile2D *theHist, RampdemReader::dataSet dataSet)
static void ENtoLonLat(Int_t e_coord, Int_t n_coord, Double_t &lon, Double_t &lat, RampdemReader::dataSet=rampdem)
static Bool_t isOnIceShelf(Double_t lon, Double_t lat)
static void LonLatToEastingNorthing(Double_t lon, Double_t lat, Double_t &easting, Double_t &northing)
static void EastingNorthingToLonLat(Double_t easting, Double_t northing, Double_t &lon, Double_t &lat)
static Double_t Geoid(Double_t latitude)