OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimAtCorrRemapper.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // Copyright (C) 2002 ImageLinks Inc.
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Kathy Minear
9 //
10 // Description:
11 // Takes in DNs for any number of bands
12 // Converts DNs to Radiance at the satellite values Lsat
13 // Converts Lsat to Surface Reflectance values
14 //
15 //*************************************************************************
16 // $Id: ossimAtCorrRemapper.cpp 17206 2010-04-25 23:20:40Z dburken $
17 
18 #include <cstdlib>
19 #include <cmath>
20 
23 #include <ossim/base/ossimTrace.h>
25 
26 
28 
29 static ossimTrace traceDebug("ossimAtCorrRemapper:debug");
30 
32  ossimImageSource* inputSource,
33  const ossimString& sensorType)
34  :
35  ossimImageSourceFilter (owner, inputSource), // base class
36  theTile (NULL),
37  theSurfaceReflectance (NULL),
38  theUseInterpolationFlag(false),
39  theMinPixelValue (0),
40  theMaxPixelValue (0),
41  theXaArray (0),
42  theXbArray (0),
43  theXcArray (0),
44  theBiasArray (0),
45  theGainArray (0),
46  theCalCoefArray (0),
47  theBandWidthArray (0),
48  theSensorType(sensorType)
49 {
50  //***
51  // Set the base class "theEnableFlag" to off since no adjustments have been
52  // made yet.
53  //***
54  disableSource();
55 
56  initialize();
57 }
58 
60 {
62  {
63  delete [] theSurfaceReflectance;
64  theSurfaceReflectance = NULL;
65  }
66 }
67 
69  const ossimIrect& tile_rect,
70  ossim_uint32 resLevel)
71 {
72 #if 0
73  if (traceDebug())
74  {
75  cout << "ossimAtCorrRemapper::getTile DEBUG:"
76  << "\ntile_rect: " << tile_rect << endl;
77  }
78 #endif
79 
81  {
82  cerr << "ossimAtCorrRemapper::getTile ERROR:"
83  << "\nNot initialized!"
84  << endl;
86  }
87 
88  if(!theTile.valid())
89  {
90  initialize();
91  if(!theTile)
92  {
94  }
95  }
96 
97  // Fetch tile from pointer from the input source.
99  resLevel);
100 
101  if (!inputTile.valid()) // Just in case...
102  {
104  }
105 
106  // Check for remap bypass or empty / null input tile.
107  ossimDataObjectStatus tile_status = inputTile->getDataObjectStatus();
108  if (!theEnableFlag || tile_status == OSSIM_NULL ||
109  tile_status == OSSIM_EMPTY)
110  {
111  return inputTile;
112  }
113 
114  ossim_uint32 w = tile_rect.width();
115  ossim_uint32 h = tile_rect.height();
116  ossim_uint32 tw = theTile->getWidth();
119 
120  // Set the origin of the output tile.
121  theTile->setOrigin(tile_rect.ul());
122 
123  if(w*h != tw*th)
124  {
125  theTile->setWidthHeight(w, h);
126  theTile->initialize();
128  {
129  delete [] theSurfaceReflectance;
130  theSurfaceReflectance = NULL;
131  }
132  }
133 
135  {
136  ossim_uint32 size = tw*th*bands;
137 #if 0
138  if (traceDebug())
139  {
140  cout << "ossimAtCorrRemapper::getTile DEBUG:"
141  << "\ntile_rect: " << tile_rect
142  << "\ntile width: " << tw
143  << "\ntile height: " << th
144  << "\nbands: " << bands
145  << "\nBuffer size: " << size << endl;
146  }
147 #endif
148 
149  theSurfaceReflectance = new double[size];
150  }
151 
152  ossim_uint32 buffer_index = 0;
153  ossimIpt ul = tile_rect.ul();
154  ossimIpt lr = tile_rect.lr();
155  const double MP = theTile->getMinNormalizedPix(); // Minimum normalized pix.
156  double a, b, c;
157  buffer_index = 0;
158 
159  cout << setprecision(6);
160  for (ossim_uint32 band=0; band < bands; ++band)
161  {
162  for(ossim_sint32 idxy = ul.y; idxy <= lr.y; ++idxy)
163  {
164  for(ossim_sint32 idxx = ul.x; idxx <= lr.x; ++idxx)
165  {
166  double p = inputTile->getPix(buffer_index);
167 
168  if (p>0.0)
169  {
171  {
172  a = theXaArray[band];
173  b = theXbArray[band];
174  c = theXcArray[band];
175  }
176  else
177  {
178  interpolate(ossimDpt(idxx, idxy),
179  band,
180  a,
181  b,
182  c);
183  }
184  if(theSensorType == "ls7ms")
185  {
186  double radiance_at_satellite
187  = (theGainArray[band] * p) + theBiasArray[band];
188 
189  double y = (radiance_at_satellite * a) - b;
190 
191  p = (y / (1.0 + (c * y)) );
192  }
193  else if(theSensorType == "qbms")
194  {
195  double radiance_at_satellite
196  = theCalCoefArray[band] * p / theBandWidthArray[band];
197 
198  double y = (radiance_at_satellite * a) - b;
199 
200  p = (y / (1.0 + (c * y)) );
201  }
202  else if(theSensorType == "ikms")
203  {
204 
205 
206  double radiance_at_satellite
207  = p /((theCalCoefArray[band]/1.0)/ theBandWidthArray[band]);
208  double y = (radiance_at_satellite * a) - b;
209 
210  p = (y / (1.0 + (c * y)) );
211 
212  }
213 
214  // Note that "p" should now be normalized between 0.0 and 1.0;
215 
216  // ***
217  // Since it wasn't null to start with clip / clamp between minimum
218  // normalized pixel and one(max).
219  // ***
220  p = ( p > MP ? ( p < 1.0 ? p : 1.0) : MP );
221 
222  // Scan the new tile and set the min / max.
223  if (p < theMinPixelValue[band])
224  {
225  theMinPixelValue[band] = p;
226  }
227  else if (p > theMaxPixelValue[band])
228  {
229  theMaxPixelValue[band] = p;
230  }
231 
232  theSurfaceReflectance[buffer_index] = p;
233  }
234  else
235  {
236  theSurfaceReflectance[buffer_index] = 0.0; // pixel was null...
237  }
238 
239  ++buffer_index;
240 
241  } // End of sample loop...
242 
243  } // End of line loop...
244 
245  } // End of band loop...
246 
247  // Copy the buffer to the output tile at the same time unnormalizing it.
249 
250  // Validate the output to set the tile status.
251  theTile->validate();
252 
253  return theTile;
254 }
255 
257 {
259  {
262  theTile->initialize();
263 
265  {
266  delete []theSurfaceReflectance;
267  theSurfaceReflectance = NULL;
268  }
269 
270  ossim_uint32 tw = theTile->getWidth();
273  ossim_uint32 size = tw*th*bands;
274  if (traceDebug())
275  {
276  cout << "ossimAtCorrRemapper::initialize DEBUG:"
277  << "\ntile width: " << tw
278  << "\ntile height: " << th
279  << "\nbands: " << bands
280  << "\nBuffer size: " << size << endl;
281  }
282 
283  theSurfaceReflectance = new double[size];
284 
285  setInitializedFlag(true);
287  }
288  else
289  {
290  setInitializedFlag(false);
291  setErrorStatus();
292  };
293 
294  verifyEnabled();
295 
296  if (traceDebug())
297  {
298  cout << "ossimAtCorrRemapper::initialize DEBUG:"
299  << *this
300  << endl;
301  }
302 
303 }
304 
306  const char* prefix)
307 {
308  static const char MODULE[] = "ossimAtCorrRemapper::loadState()";
309 
310  if (traceDebug()) CLOG << "entering..." << endl;
311 
313  {
314  cerr << MODULE << " ERROR:"
315  << "Not initialized..." << endl;
316  return false;
317  }
318 
320 
321  // Clear out the old values.
322  theMinPixelValue.clear();
323  theMaxPixelValue.clear();
324  theXaArray.clear();
325  theXbArray.clear();
326  theXcArray.clear();
327  theBiasArray.clear();
328  theGainArray.clear();
329  theCalCoefArray.clear();
330  theBandWidthArray.clear();
331 
332 
333  // Now resize them.
334 
335  // Start with arbitrary big number.
336  theMinPixelValue.resize(bands, 1.0);
337 
338  // Start with arbitrary small number.
339  theMaxPixelValue.resize(bands, 0.0);
340 
341 
342  theXaArray.resize(bands, 1.0);
343  theXbArray.resize(bands, 1.0);
344  theXcArray.resize(bands, 1.0);
345 
346  theBiasArray.resize(bands, 0.0);
347  theGainArray.resize(bands, 1.0);
348  theCalCoefArray.resize(bands);
349  theBandWidthArray.resize(bands);
350 
351  for(ossim_uint32 band = 0; band < bands; ++band)
352  {
353  const char* lookup = NULL;
354  ossimString band_string = ".band";
355  band_string += ossimString::toString(band+1);
356 
357  ossimString kw = AT_CORR_XA_KW;
358  kw += band_string;
359  lookup = kwl.find(prefix, kw.c_str());
360  if (lookup)
361  {
362  theXaArray[band] = atof(lookup);
363  }
364  else
365  {
366  if (traceDebug())
367  {
368  CLOG << "DEBUG:"
369  << "\nlookup failed for keyword: " << kw.c_str() << endl;
370  }
371  }
372 
373  kw = AT_CORR_XB_KW;
374  kw += band_string;
375  lookup = kwl.find(prefix, kw.c_str());
376  if (lookup)
377  {
378  theXbArray[band] = atof(lookup);
379  }
380  else
381  {
382  if (traceDebug())
383  {
384  CLOG << "DEBUG:"
385  << "\nlookup failed for keyword: " << kw.c_str()
386  << endl;
387  }
388  }
389 
390  kw = AT_CORR_XC_KW;
391  kw += band_string;
392  lookup = kwl.find(prefix, kw.c_str());
393  if (lookup)
394  {
395  theXcArray[band] = atof(lookup);
396  }
397  else
398  {
399  if (traceDebug())
400  {
401  CLOG << "DEBUG:"
402  << "\nlookup failed for keyword: " << kw.c_str()
403  << endl;
404  }
405  }
406 
407  if(theSensorType == "ls7ms")
408  {
409  kw = AT_CORR_BIAS_KW;
410  kw += band_string;
411  lookup = kwl.find(prefix, kw.c_str());
412  if (lookup)
413  {
414  theBiasArray[band] = atof(lookup);
415  }
416  else
417  {
418  if (traceDebug())
419  {
420  CLOG << "DEBUG:"
421  << "\nlookup failed for keyword: " << kw.c_str()
422  << endl;
423  }
424  }
425 
426  kw = AT_CORR_GAIN_KW;
427  kw += band_string;
428  lookup = kwl.find(prefix, kw.c_str());
429  if (lookup)
430  {
431  theGainArray[band] = atof(lookup);
432  }
433  else
434  {
435  if (traceDebug())
436  {
437  CLOG << "DEBUG:"
438  << "\nlookup failed for keyword: " << kw.c_str()
439  << endl;
440  }
441  }
442  }
443 
444  if(theSensorType == "qbms")
445  {
446  kw = AT_CORR_CALCOEF_KW;
447  kw += band_string;
448  lookup = kwl.find(prefix, kw.c_str());
449  if (lookup)
450  {
451  theCalCoefArray[band] = atof(lookup);
452  }
453  else
454  {
455  if (traceDebug())
456  {
457  CLOG << "DEBUG:"
458  << "\nlookup failed for keyword: " << kw.c_str()
459  << endl;
460  }
461  }
462 
463  kw = AT_CORR_BANDWIDTH_KW;
464  kw += band_string;
465  lookup = kwl.find(prefix, kw.c_str());
466  if (lookup)
467  {
468  theBandWidthArray[band] = atof(lookup);
469  }
470  else
471  {
472  if (traceDebug())
473  {
474  CLOG << "DEBUG:"
475  << "\nlookup failed for keyword: " << kw.c_str()
476  << endl;
477  }
478  }
479  }
480  if(theSensorType == "ikms")
481  {
482  kw = AT_CORR_CALCOEF_KW;
483  kw += band_string;
484  lookup = kwl.find(prefix, kw.c_str());
485  if (lookup)
486  {
487  theCalCoefArray[band] = atof(lookup);
488  }
489  else
490  {
491  if (traceDebug())
492  {
493  CLOG << "DEBUG:"
494  << "\nlookup failed for keyword: " << kw.c_str()
495  << endl;
496  }
497  }
498 
499  kw = AT_CORR_BANDWIDTH_KW;
500  kw += band_string;
501  lookup = kwl.find(prefix, kw.c_str());
502  if (lookup)
503  {
504  theBandWidthArray[band] = atof(lookup);
505  }
506  else
507  {
508  if (traceDebug())
509  {
510  CLOG << "DEBUG:"
511  << "\nlookup failed for keyword: " << kw.c_str()
512  << endl;
513  }
514  }
515  }
516  }
517 
518  verifyEnabled();
519 
520  if (theEnableFlag)
521  {
522  //***
523  // Call the base class to pick up the enable flag. Note that this
524  // can override the state set from verifyEnabled() method.
525  //***
526  ossimString pref;
527  if (prefix) pref += prefix;
528  pref += "atmospheric_correction.";
529 
530  }
531 
532  if (traceDebug())
533  {
534  CLOG << "DEBUG:"
535  << *this
536  << "returning..."
537  << endl;
538  }
539 
540  return true;
541 }
542 
544 {
545  // Check all the pointers...
546  if ( !theInputConnection || !theTile ||
548  {
549  disableSource();
550  return;
551  }
552 
554  if ( (theMinPixelValue.size() != bands) ||
555  (theMaxPixelValue.size() != bands) ||
556  (theXaArray.size() != bands) ||
557  (theXbArray.size() != bands) ||
558  (theXcArray.size() != bands) ||
559  (theBiasArray.size() != bands) ||
560  (theGainArray.size() != bands) ||
561  (theCalCoefArray.size() != bands) ||
562  (theBandWidthArray.size()!= bands))
563  {
564  disableSource();
565  return;
566  }
567 
568  enableSource();
569 }
570 
572 {
573  return ossimString("Atmospheric Correction Remapper");
574 }
575 
577 {
578  return theMinPixelValue;
579 }
580 
582 {
583  return theMaxPixelValue;
584 }
585 
586 void ossimAtCorrRemapper::getNormMinPixelValues(vector<double>& v) const
587 {
588  v = theMinPixelValue;
589 }
590 
591 void ossimAtCorrRemapper::getNormMaxPixelValues(vector<double>& v) const
592 {
593  v = theMaxPixelValue;
594 }
595 
597 {
598  return theSensorType;
599 }
600 
602 {
603  theSensorType = sensorType;
604 }
605 
607  int band,
608  double& a,
609  double& b,
610  double& c)const
611 {
612  a = theXaArray[band];
613  b = theXbArray[band];
614  c = theXcArray[band];
615 }
616 
618 {
619  os << "ossimAtCorrRemapper:"
620  << "\ntheEnableFlag: " << (theEnableFlag?"enabled":"disabled")
621  << endl;
622 
623  os << setprecision(15) << setiosflags(ios::fixed);
624 
625  ossim_uint32 band = 1;
626  vector<double>::const_iterator i = theMinPixelValue.begin();
627  while (i != theMinPixelValue.end())
628  {
629  os << "band[" << band << "] min: " << (*i) << endl;
630  ++i;
631  ++band;
632  }
633 
634  band = 1;
635  i = theMaxPixelValue.begin();
636  while (i != theMaxPixelValue.end())
637  {
638  os << "band[" << band << "] max: " << (*i) << endl;
639  ++i;
640  ++band;
641  }
642 
643  band = 1;
644  i = theXaArray.begin();
645  while (i != theXaArray.end())
646  {
647  os << "band[" << band << "] xa: " << (*i) << endl;
648  ++i;
649  ++band;
650  }
651 
652  band = 1;
653  i = theXbArray.begin();
654  while (i != theXbArray.end())
655  {
656  os << "band[" << band << "] xb: " << (*i) << endl;
657  ++i;
658  ++band;
659  }
660 
661  band = 1;
662  i = theXcArray.begin();
663  while (i != theXcArray.end())
664  {
665  os << "band[" << band << "] xc: " << (*i) << endl;
666  ++i;
667  ++band;
668  }
669 
670  if(theSensorType == "ls7ms")
671  {
672  band = 1;
673  i = theBiasArray.begin();
674  while (i != theBiasArray.end())
675  {
676  os << "band[" << band << "] bias: " << (*i) << endl;
677  ++i;
678  ++band;
679  }
680 
681  band = 1;
682  i = theGainArray.begin();
683  while (i != theGainArray.end())
684  {
685  os << "band[" << band << "] gain: " << (*i) << endl;
686  ++i;
687  ++band;
688  }
689  }
690  if(theSensorType == "qbms")
691  {
692  band = 1;
693  i = theCalCoefArray.begin();
694  while (i != theCalCoefArray.end())
695  {
696  os << "band[" << band << "] calcoef: " << (*i) << endl;
697  ++i;
698  ++band;
699  }
700 
701  band = 1;
702  i = theBandWidthArray.begin();
703  while (i != theBandWidthArray.end())
704  {
705  os << "band[" << band << "] bandwidth: " << (*i) << endl;
706  ++i;
707  ++band;
708  }
709  }
710  if(theSensorType == "ikms")
711  {
712  band = 1;
713  i = theCalCoefArray.begin();
714  while (i != theCalCoefArray.end())
715  {
716  os << "band[" << band << "] calcoef: " << (*i) << endl;
717  ++i;
718  ++band;
719  }
720 
721  }
722  return os;
723 }
724 
726 {
727  return hr.print(os);
728 }
729 
730 
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tile_rect, ossim_uint32 resLevel=0)
virtual ossim_uint32 getWidth() const
virtual bool isInitialized() const
virtual ossim_uint32 getNumberOfBands() const
#define CLOG
Definition: ossimTrace.h:23
vector< double > theXcArray
virtual ossim_float64 getMinNormalizedPix() const
returns normalized minimum pixel value of band zero.
virtual ostream & print(ostream &os) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
virtual void setWidthHeight(ossim_uint32 w, ossim_uint32 h)
Represents serializable keyword/value map.
bool theEnableFlag
Definition: ossimSource.h:62
const ossimString & getSensorType() const
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
ossim_uint32 height() const
Definition: ossimIrect.h:487
static ossimString toString(bool aValue)
Numeric to string methods.
virtual void disableSource()
Definition: ossimSource.cpp:89
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
virtual ossim_float64 getPix(const ossimIpt &position, ossim_uint32 band=0) const
Will return the pixel at location position.
virtual void setInitializedFlag(bool flag)
vector< double > theGainArray
virtual void initialize()
Initialize the data buffer.
vector< double > getNormMinPixelValues() const
static ossimImageDataFactory * instance()
virtual ossimString getShortName() const
yy_size_t size
vector< double > theMinPixelValue
virtual ossimDataObjectStatus validate() const
ossimImageSource * theInputConnection
unsigned int ossim_uint32
virtual void interpolate(const ossimDpt &pt, int band, double &a, double &b, double &c) const
signed int ossim_sint32
vector< double > theBandWidthArray
vector< double > theXaArray
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void enableSource()
Definition: ossimSource.cpp:84
virtual void copyNormalizedBufferToTile(ossim_float64 *buf)
Copies buf passed in to tile.
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
vector< double > theXbArray
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
virtual void setOrigin(const ossimIpt &origin)
ossimRefPtr< ossimImageData > theTile
ossim_int32 y
Definition: ossimIpt.h:142
ossimAtCorrRemapper(ossimObject *owner=NULL, ossimImageSource *inputSource=NULL, const ossimString &sensorType="")
vector< double > theCalCoefArray
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
vector< double > theBiasArray
void setSensorType(const ossimString &sensorType)
ostream & operator<<(ostream &os, const ossimAtCorrRemapper &hr)
RTTI_DEF1(ossimAtCorrRemapper, "ossimAtCorrRemapper", ossimImageSourceFilter)
ossim_int32 x
Definition: ossimIpt.h:141
ossimDataObjectStatus
Definitions for data object status.
vector< double > getNormMaxPixelValues() const
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
vector< double > theMaxPixelValue