diff --git a/CHANGELOG.md b/CHANGELOG.md index fe8ad6c5c2..cc63e94d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,11 +38,14 @@ update the Unreleased link so that it compares against the latest release tag. - Equalizer now reports the correct equation and values used to perform the adjustment. [#3987](https://github.com/USGS-Astrogeology/ISIS3/issues/3987) - Map2cam now works correctly when specifying bands for input cubes. [#3856](https://github.com/USGS-Astrogeology/ISIS3/issues/3856) + - mro/hideal2pds app now writes the correct SAMPLE_BIT_MASK values to the output label. [#3978](https://github.com/USGS-Astrogeology/ISIS3/issues/3978) + - For Histograms in ISIS, updated the math for calculating what bin data should be placed in and the min/max values of each bin to be more intuitive. In addition, the output of hist and cnethist were changed to display the min/max values of each bin instead of the middle pixel's DN. [#3882](https://github.com/USGS-Astrogeology/ISIS3/issues/3882) + ### Added - - - A Gui Helper gear was added to hist to fill in the minimum and maximum parameters with what would have been automatically calculated. [#3880](https://github.com/USGS-Astrogeology/ISIS3/issues/3880) + + - A Gui Helper gear was added to hist to fill in the minimum and maximum parameters with what would have been automatically calculated. [#3880](https://github.com/USGS-Astrogeology/ISIS3/issues/3880) ## [4.2.0] - 2020-07-27 diff --git a/isis/src/base/apps/bit2bit/main.cpp b/isis/src/base/apps/bit2bit/main.cpp index f0077d04b5..bd2bdd8e8b 100644 --- a/isis/src/base/apps/bit2bit/main.cpp +++ b/isis/src/base/apps/bit2bit/main.cpp @@ -7,7 +7,7 @@ #include "Cube.h" #include "Process.h" -using namespace std; +using namespace std; using namespace Isis; void populate(Buffer &in, Buffer &out); @@ -15,28 +15,28 @@ void populate(Buffer &in, Buffer &out); void IsisMain(){ UserInterface &ui = Application::GetUserInterface(); - + //We will process by line ProcessByLine p; Cube* cubeptr = p.SetInputCube("FROM"); - + // Histogram* histptr = (cubeptr -> Histogram()); double max = ui.GetDouble("MAXVAL"); double min = ui.GetDouble("MINVAL"); - + /* A histogram is made from the input cube, as the default min of the bit2bit output is at .5% of the data range, and the default max is at 99.5% - */ + */ Histogram* histptr = cubeptr -> histogram(); - + double maxper = histptr -> Percent(ui.GetDouble("MAXPER")); double minper = histptr -> Percent(ui.GetDouble("MINPER")); double validMin = Isis::ValidMinimum; double validMax = Isis::ValidMaximum; - - + + // Set properties MIN,MAX, and PixelType for output cube CubeAttributeOutput outputProperties; @@ -60,26 +60,26 @@ void IsisMain(){ } else { outputProperties.setPixelType(Real); - } + } if(ui.GetBoolean("STATS")) { //! Run extended statistics Cube* ocubeptr = p.SetOutputCube (ui.GetFileName("TO"),outputProperties, cubeptr->sampleCount(),cubeptr->lineCount(), cubeptr->bandCount()); - + p.StartProcess(populate); - + Histogram* ohistptr = (ocubeptr -> histogram(1,validMin,validMax)); int iLrs = histptr -> LrsPixels(); int iHrs = histptr -> HrsPixels(); int iNull = histptr -> NullPixels(); int oLrs = ohistptr -> LrsPixels(); int oHrs = ohistptr -> HrsPixels(); - int oNull = ohistptr -> NullPixels(); + int oNull = ohistptr -> NullPixels(); double invalid_pi = (( (histptr -> TotalPixels()) - (histptr -> ValidPixels()))*100.0) / ((histptr -> TotalPixels())*1.0); - double invalid_po = (( (ohistptr -> TotalPixels()) - (ohistptr -> ValidPixels()))*100.0) / ((ohistptr -> TotalPixels())*1.0); - + double invalid_po = (( (ohistptr -> TotalPixels()) - (ohistptr -> ValidPixels()))*100.0) / ((ohistptr -> TotalPixels())*1.0); + p.EndProcess(); //!Write bit2bit summary to the screen @@ -95,7 +95,7 @@ void IsisMain(){ cout << " HRS:\t\t" << oHrs << endl; cout << " NULL:\t\t" << oNull << endl; cout << " Invalid Pixel %:\t\t" << invalid_po << endl<< endl; - + //!Write bit2bit summary to print.prt logfile PvlGroup results("bit2bit_Results"); results += PvlKeyword ("INPUT_LRS",toString(iLrs)); @@ -109,16 +109,16 @@ void IsisMain(){ results += PvlKeyword ("OUTPUT_NULL",toString(oNull)); results += PvlKeyword ("OUTPUT_INVALID_PERCENT",toString(invalid_po)); Application::Log(results); - + delete histptr; - delete ohistptr; + delete ohistptr; } else{ //! run minimal statistics (runs faster) int iLrs = histptr -> LrsPixels(); int iHrs = histptr -> HrsPixels(); int iNull = histptr -> NullPixels(); double invalid_pi = (( (histptr -> TotalPixels()) - (histptr -> ValidPixels()))*100.0) / ((histptr -> TotalPixels())*1.0); - + p.EndProcess(); //!Write bit2bit summary to the screen @@ -131,7 +131,7 @@ void IsisMain(){ cout << " Data Range:\t\t"; cout << validMin << " < x < " << validMax << endl; - + //!Write bit2bit summary to print.prt logfile PvlGroup results("bit2bit_Results"); results += PvlKeyword ("INPUT_LRS",toString(iLrs)); @@ -141,7 +141,7 @@ void IsisMain(){ results += PvlKeyword ("OUTPUT_MIN",toString(validMin)); results += PvlKeyword ("OUTPUT_MAX",toString(validMax)); Application::Log(results); - + delete histptr; } } diff --git a/isis/src/base/apps/gaussstretch/main.cpp b/isis/src/base/apps/gaussstretch/main.cpp index eed8bf3a72..801f0e605b 100644 --- a/isis/src/base/apps/gaussstretch/main.cpp +++ b/isis/src/base/apps/gaussstretch/main.cpp @@ -17,16 +17,22 @@ void IsisMain() { double gsigma = Isis::Application::GetUserInterface().GetDouble("GSIGMA"); for(int i = 0; i < icube->bandCount(); i++) { - Histogram hist = *(icube->histogram(i + 1)); - double mean = (hist.Maximum() + hist.Minimum()) / 2.0; - double stdev = (hist.Maximum() - hist.Minimum()) / (2.0 * gsigma); - stretch.push_back(new GaussianStretch(hist, mean, stdev)); + Histogram *hist = icube->histogram(i + 1); + double mean = (hist->Maximum() + hist->Minimum()) / 2.0; + double stdev = (hist->Maximum() - hist->Minimum()) / (2.0 * gsigma); + stretch.push_back(new GaussianStretch(*hist, mean, stdev)); } p.StartProcess(gauss); for(int i = 0; i < icube->bandCount(); i++) delete stretch[i]; - stretch.clear(); p.EndProcess(); + + while(!stretch.empty()) { + delete stretch.back(); + stretch.pop_back(); + } + + stretch.clear(); } // Processing routine for the pca with one input cube @@ -36,4 +42,3 @@ void gauss(Buffer &in, Buffer &out) { out[i] = stretch[in.Band(i)-1]->Map(in[i]); } } - diff --git a/isis/src/base/apps/hist/hist.xml b/isis/src/base/apps/hist/hist.xml index cd1937f56c..3e04c85f0f 100644 --- a/isis/src/base/apps/hist/hist.xml +++ b/isis/src/base/apps/hist/hist.xml @@ -84,6 +84,12 @@ Updated logic such that min/max values are no longer calculated from .cub if values are provided by the user. Fixes #3881. + + Added "Pixels Below Min" and "Pixels Above Max" to the CSV output and changed how the data is + outputted. Originally, the CSV output and the GUI histogram would use the DN value in the + middle of a bin to represent that bin. That is, the CSV output used to have a "DN" value that + was the bin's middle pixel DN. This was not intuitive to users. Removed the "DN" value and added "MinInclusive" and "MaxExclusive" to the CSV so that bins are represented by their min/max values. These changes were also reflected in the histrogram creation. The x-axis is now based off of the min value of a bin instead of the middle value. These changes were made alongside changes made to Histogram and cnethist. + Re-added the ability to set number of bins without setting min/max values after the last update. Follow-on to #3881. diff --git a/isis/src/base/apps/hist/main.cpp b/isis/src/base/apps/hist/main.cpp index 3b9b6ee69a..a242c2346e 100644 --- a/isis/src/base/apps/hist/main.cpp +++ b/isis/src/base/apps/hist/main.cpp @@ -7,6 +7,7 @@ #include "CubePlotCurve.h" #include "Histogram.h" +#include "ImageHistogram.h" #include "HistogramItem.h" #include "HistogramPlotWindow.h" #include "LineManager.h" @@ -33,7 +34,7 @@ void IsisMain() { Cube *icube = p.SetInputCube("FROM"); UserInterface &ui = Application::GetUserInterface(); - if(!ui.WasEntered("TO") && !ui.IsInteractive()) { + if (!ui.WasEntered("TO") && !ui.IsInteractive()) { QString msg = "The [TO] parameter must be entered"; throw IException(IException::User, msg, _FILEINFO_); } @@ -66,10 +67,12 @@ void IsisMain() { hist = new Histogram(ui.GetDouble("MINIMUM"), ui.GetDouble("MAXIMUM"), nbins); } else { - hist = new Histogram(*icube, 1, p.Progress()); if (ui.WasEntered("NBINS")){ - hist->SetBins(ui.GetInteger("NBINS")); + hist = new ImageHistogram(*icube, 1, p.Progress(), 1, 1, Null, Null, ui.GetInteger("NBINS")); + } + else { + hist = new ImageHistogram(*icube, 1, p.Progress()); } } @@ -88,46 +91,53 @@ void IsisMain() { p.Progress()->CheckStatus(); } - if(!ui.IsInteractive() || ui.WasEntered("TO") ) { + if (!ui.IsInteractive() || ui.WasEntered("TO") ) { // Write the results QString outfile = ui.GetFileName("TO"); ofstream fout; fout.open(outfile.toLatin1().data()); - fout << "Cube: " << ui.GetFileName("FROM") << endl; - fout << "Band: " << icube->bandCount() << endl; - fout << "Average: " << hist->Average() << endl; - fout << "Std Deviation: " << hist->StandardDeviation() << endl; - fout << "Variance: " << hist->Variance() << endl; - fout << "Median: " << hist->Median() << endl; - fout << "Mode: " << hist->Mode() << endl; - fout << "Skew: " << hist->Skew() << endl; - fout << "Minimum: " << hist->Minimum() << endl; - fout << "Maximum: " << hist->Maximum() << endl; + fout << "Cube: " << ui.GetFileName("FROM") << endl; + fout << "Band: " << icube->bandCount() << endl; + fout << "Average: " << hist->Average() << endl; + fout << "Std Deviation: " << hist->StandardDeviation() << endl; + fout << "Variance: " << hist->Variance() << endl; + fout << "Median: " << hist->Median() << endl; + fout << "Mode: " << hist->Mode() << endl; + fout << "Skew: " << hist->Skew() << endl; + fout << "Minimum: " << hist->Minimum() << endl; + fout << "Maximum: " << hist->Maximum() << endl; fout << endl; - fout << "Total Pixels: " << hist->TotalPixels() << endl; - fout << "Valid Pixels: " << hist->ValidPixels() << endl; - fout << "Null Pixels: " << hist->NullPixels() << endl; - fout << "Lis Pixels: " << hist->LisPixels() << endl; - fout << "Lrs Pixels: " << hist->LrsPixels() << endl; - fout << "His Pixels: " << hist->HisPixels() << endl; - fout << "Hrs Pixels: " << hist->HrsPixels() << endl; + fout << "Total Pixels: " << hist->TotalPixels() << endl; + fout << "Valid Pixels: " << hist->ValidPixels() << endl; + fout << "Pixels Below Min: " << hist->UnderRangePixels() << endl; + fout << "Pixels Above Max: " << hist->OverRangePixels() << endl; + fout << "Null Pixels: " << hist->NullPixels() << endl; + fout << "Lis Pixels: " << hist->LisPixels() << endl; + fout << "Lrs Pixels: " << hist->LrsPixels() << endl; + fout << "His Pixels: " << hist->HisPixels() << endl; + fout << "Hrs Pixels: " << hist->HrsPixels() << endl; // Write histogram in tabular format fout << endl; fout << endl; - fout << "DN,Pixels,CumulativePixels,Percent,CumulativePercent" << endl; + fout << "MinInclusive,MaxExclusive,Pixels,CumulativePixels,Percent,CumulativePercent" << endl; Isis::BigInt total = 0; double cumpct = 0.0; + double low; + double high; - for(int i = 0; i < hist->Bins(); i++) { - if(hist->BinCount(i) > 0) { + for (int i = 0; i < hist->Bins(); i++) { + if (hist->BinCount(i) > 0) { total += hist->BinCount(i); double pct = (double)hist->BinCount(i) / hist->ValidPixels() * 100.; cumpct += pct; - fout << hist->BinMiddle(i) << ","; + hist->BinRange(i, low, high); + + fout << low << ","; + fout << high << ","; fout << hist->BinCount(i) << ","; fout << total << ","; fout << pct << ","; @@ -137,10 +147,10 @@ void IsisMain() { fout.close(); } // If we are in gui mode, create a histogram plot - if(ui.IsInteractive()) { + if (ui.IsInteractive()) { // Set the title for the dialog QString title; - if(ui.WasEntered("TITLE") ) { + if (ui.WasEntered("TITLE") ) { title = ui.GetString("TITLE"); } else { @@ -153,19 +163,19 @@ void IsisMain() { ui.TheGui()); // Set the xaxis title if they entered one - if(ui.WasEntered("XAXIS") ) { + if (ui.WasEntered("XAXIS") ) { QString xaxis(ui.GetString("XAXIS")); plot->setAxisLabel(QwtPlot::xBottom, xaxis.toLatin1().data()); } // Set the yLeft axis title if they entered one - if(ui.WasEntered("FREQAXIS") ) { + if (ui.WasEntered("FREQAXIS") ) { QString yaxis(ui.GetString("FREQAXIS")); plot->setAxisLabel(QwtPlot::yRight, yaxis.toLatin1().data()); } // Set the yRight axis title if they entered one - if(ui.WasEntered("PERCENTAXIS") ) { + if (ui.WasEntered("PERCENTAXIS") ) { QString y2axis(ui.GetString("PERCENTAXIS") ); plot->setAxisLabel(QwtPlot::yLeft, y2axis.toLatin1().data()); } @@ -174,13 +184,16 @@ void IsisMain() { QVector binCountData; QVector cumPctData; double cumpct = 0.0; - for(int i = 0; i < hist->Bins(); i++) { - if(hist->BinCount(i) > 0) { - binCountData.append(QPointF(hist->BinMiddle(i), hist->BinCount(i) ) ); - - double pct = (double)hist->BinCount(i) / hist->ValidPixels() * 100.; + double low; + double high; + for (int i = 0; i < hist->Bins(); i++) { + if (hist->BinCount(i) > 0) { + hist->BinRange(i, low, high); + binCountData.append(QPointF(low, hist->BinCount(i) ) ); + + double pct = (double)hist->BinCount(i) / hist->ValidPixels() * 100.0; cumpct += pct; - cumPctData.append(QPointF(hist->BinMiddle(i), cumpct) ); + cumPctData.append(QPointF(low, cumpct) ); } } @@ -199,21 +212,13 @@ void IsisMain() { cdfCurve->setYAxis(QwtPlot::yLeft); cdfCurve->setPen(*pen); - //These are all variables needed in the following for loop. - //---------------------------------------------- QVector intervals(binCountData.size() ); -// double maxYValue = DBL_MIN; -// double minYValue = DBL_MAX; -// // --------------------------------------------- -// - for(int y = 0; y < binCountData.size(); y++) { + for (int y = 0; y < binCountData.size(); y++) { intervals[y].interval = QwtInterval(binCountData[y].x(), binCountData[y].x() + hist->BinSize()); intervals[y].value = binCountData[y].y(); -// if(values[y] > maxYValue) maxYValue = values[y]; -// if(values[y] < minYValue) minYValue = values[y]; } QPen percentagePen(Qt::red); @@ -226,10 +231,6 @@ void IsisMain() { plot->add(histCurve); plot->add(cdfCurve); -// plot->fillTable(); - -// plot->setScale(QwtPlot::yLeft, 0, maxYValue); -// plot->setScale(QwtPlot::xBottom, hist.Minimum(), hist.Maximum()); QLabel *label = new QLabel(" Average = " + QString::number(hist->Average()) + '\n' + "\n Minimum = " + QString::number(hist->Minimum()) + '\n' + @@ -272,7 +273,7 @@ void helperButtonCalcMinMax() { line.SetLine(i); inCube.read(line); cubeStats.AddData(line.DoubleBuffer(), line.size()); - } + } inCube.close(); @@ -283,4 +284,3 @@ void helperButtonCalcMinMax() { ui.PutDouble("MAXIMUM", cubeStats.Maximum()); } - diff --git a/isis/src/base/apps/hist/tsts/default/Makefile b/isis/src/base/apps/hist/tsts/default/Makefile index 89268ffcf8..26600023b1 100644 --- a/isis/src/base/apps/hist/tsts/default/Makefile +++ b/isis/src/base/apps/hist/tsts/default/Makefile @@ -7,6 +7,7 @@ histTruth.txt.IGNORELINES = Cube histTruthNbins.txt.IGNORELINES = Cube TEMP = $(OUTPUT)/histTruth.txt TEMPNBINS = $(OUTPUT)/histTruthNbins.txt +TEMPMINMAX = $(OUTPUT)/histTruthMinMax.txt include $(ISISROOT)/make/isismake.tsts @@ -18,3 +19,7 @@ commands: # Test with setting nbins $(APPNAME) from=$(INPUT)/isisTruth.cub nbins=25\ to=$(TEMPNBINS) > /dev/null; + + # Test with a min and max + $(APPNAME) from=$(INPUT)/isisTruth.cub\ + to=$(TEMPMINMAX) minimum=0 maximum=255 nbins=255> /dev/null; diff --git a/isis/src/base/apps/isis2raw/main.cpp b/isis/src/base/apps/isis2raw/main.cpp index 74cbed6491..06ac54df0e 100644 --- a/isis/src/base/apps/isis2raw/main.cpp +++ b/isis/src/base/apps/isis2raw/main.cpp @@ -34,7 +34,7 @@ void IsisMain() { // Applies the input to output stretch options if(ui.GetString("STRETCH") == "LINEAR") { -// if(ui.GetString("BITTYPE") != "32BIT") + // if(ui.GetString("BITTYPE") != "32BIT") p.SetInputRange(); } if(ui.GetString("STRETCH") == "MANUAL") { @@ -68,7 +68,7 @@ void IsisMain() { p.SetOutputType(Isis::Real); pixType = NONE; } - + if (ui.GetString("STRETCH") != "NONE" || ui.GetString("BITTYPE") != "32BIT") { checkRange(ui, min, max); } diff --git a/isis/src/base/apps/stretch/main.cpp b/isis/src/base/apps/stretch/main.cpp index 564d5680e5..37dcf08b52 100644 --- a/isis/src/base/apps/stretch/main.cpp +++ b/isis/src/base/apps/stretch/main.cpp @@ -42,8 +42,9 @@ void IsisMain() { pairs = ui.GetString("PAIRS"); } - if(ui.GetBoolean("USEPERCENTAGES")) + if(ui.GetBoolean("USEPERCENTAGES")) { str.Parse(pairs, inCube->histogram()); + } else str.Parse(pairs); diff --git a/isis/src/base/objs/Cube/Cube.cpp b/isis/src/base/objs/Cube/Cube.cpp index 5273e29e74..723cb677e8 100644 --- a/isis/src/base/objs/Cube/Cube.cpp +++ b/isis/src/base/objs/Cube/Cube.cpp @@ -40,7 +40,7 @@ #include "CubeTileHandler.h" #include "Endian.h" #include "FileName.h" -#include "Histogram.h" +#include "ImageHistogram.h" #include "IException.h" #include "LineManager.h" #include "Message.h" @@ -106,7 +106,7 @@ namespace Isis { * * @param fileName Name of the cube file to open. Environment * variables in the filename will be automatically expanded. - * @param label PVL label object representing the new Cube label + * @param label PVL label object representing the new Cube label * @param isd JSON object containing Ale compatible ISD * @param access Defines how the cube will be opened. Either read-only * "r" or read-write "rw". @@ -118,7 +118,7 @@ namespace Isis { close(); open(fileName.toString(), access); } - + /** * Initialize Cube data from a PVL label and JSON ISD. * @@ -132,15 +132,15 @@ namespace Isis { void Cube::fromIsd(const FileName &fileName, FileName &labelFile, FileName &isdFile, QString access) { std::ifstream isdStream(isdFile.expanded().toStdString()); std::ifstream labelStream(labelFile.expanded().toStdString()); - + Pvl label; nlohmann::json isd; - + isdStream >> isd; labelStream >> label; - + fromIsd(fileName, label, isd, access); - reopen("rw"); + reopen("rw"); } //! Destroys the Cube object. @@ -1435,7 +1435,7 @@ namespace Isis { } Progress progress; - Histogram *hist = new Histogram(*this, band, &progress); + Histogram *hist = new ImageHistogram(*this, band, &progress); LineManager line(*this); // This range is for throwing out data; the default parameters are OK always diff --git a/isis/src/base/objs/Cube/Cube.h b/isis/src/base/objs/Cube/Cube.h index 595d9683e5..3bd4fa0494 100644 --- a/isis/src/base/objs/Cube/Cube.h +++ b/isis/src/base/objs/Cube/Cube.h @@ -173,7 +173,7 @@ namespace Isis { public: Cube(); Cube(const FileName &fileName, QString access = "r"); - + virtual ~Cube(); /** @@ -285,10 +285,10 @@ namespace Isis { virtual QString fileName() const; Format format() const; virtual Histogram *histogram(const int &band = 1, - QString msg = "Gathering histogram"); + QString msg = "Gathering histogram"); virtual Histogram *histogram(const int &band, const double &validMin, - const double &validMax, - QString msg = "Gathering histogram"); + const double &validMax, + QString msg = "Gathering histogram"); Pvl *label() const; int labelSize(bool actual = false) const; int lineCount() const; diff --git a/isis/src/base/objs/Cube/unitTest.cpp b/isis/src/base/objs/Cube/unitTest.cpp index fe1bbde4f4..e64734ca63 100644 --- a/isis/src/base/objs/Cube/unitTest.cpp +++ b/isis/src/base/objs/Cube/unitTest.cpp @@ -206,7 +206,7 @@ int main(int argc, char *argv[]) { catch (IException &e) { e.print(); } - + // Check error for histogram object on a closed cube try { // out has already been closed @@ -216,9 +216,9 @@ int main(int argc, char *argv[]) { { e.print(); } - + cerr << endl; - + // Test statistics object on a single band, 1 by default cerr << "Testing statistics method, band 1 ... " << endl; Statistics *bandOneStats = in.statistics(); @@ -248,7 +248,7 @@ int main(int argc, char *argv[]) { catch (IException &e) { e.print(); } - + // Check error for statistics object on a closed cube try { // out has already been closed @@ -294,7 +294,7 @@ int main(int argc, char *argv[]) { boundaryTestCube.create("IsisCube_boundary"); Report(boundaryTestCube); LineManager boundaryLine(boundaryTestCube); - + for(boundaryLine.begin(); !boundaryLine.end(); boundaryLine++) { for(int i = 0; i < boundaryLine.size(); i++) { boundaryLine[i] = 1.0; @@ -353,7 +353,7 @@ int main(int argc, char *argv[]) { // Read after the bands start in the cube. readBrick.SetBasePosition(1, 1, 4); boundaryTestCube.read(readBrick); - + if (readBrick[0] != 1.0) { cerr << "\t\t Value inside cube boundary was not 1.0." << endl; return 1; @@ -461,8 +461,8 @@ int main(int argc, char *argv[]) { } cerr << endl; boundaryTestCube.close(); - - + + // Test cube where its chunk size is the same as its buffer shape cerr << "Testing one line BSQ cube (where chunk dimensions == buffer shape) ... " << endl; cerr << "Constructing cube ... " << endl << endl; @@ -472,7 +472,7 @@ int main(int argc, char *argv[]) { bsqOneLineTestCube.create("IsisCube_bsqOneLine"); Report(bsqOneLineTestCube); LineManager oneLine(bsqOneLineTestCube); - + // our cube will be 1, 2, 3 // 2, 3, 4 // 3, 4, 5 @@ -483,10 +483,10 @@ int main(int argc, char *argv[]) { bsqOneLineTestCube.write(oneLine); } bsqOneLineTestCube.close(); - + // Simulate reading of an S x 1 x B cube Brick readLineBrick(3, 1, 1, bsqOneLineTestCube.pixelType()); - + // Test reading repeated ascending virtual bands cerr << "Testing reading ascending repeating virtual bands (1, 2, 2, 3)... " << endl; virtualBands.clear(); @@ -501,7 +501,7 @@ int main(int argc, char *argv[]) { bsqOneLineTestCube.read(readLineBrick); for (int i = 0; i < readLineBrick.size(); i++) { if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) { - cerr << "Virtual bands accessed incorrectly at brick band " + cerr << "Virtual bands accessed incorrectly at brick band " << readLineBrick.Band() << endl; return 1; } @@ -509,7 +509,7 @@ int main(int argc, char *argv[]) { } cerr << endl; bsqOneLineTestCube.close(); - + // Test reading skipped ascending virtual bands cerr << "Testing reading skipped ascending virtual bands (1, 3, 3)... " << endl; virtualBands.clear(); @@ -523,7 +523,7 @@ int main(int argc, char *argv[]) { bsqOneLineTestCube.read(readLineBrick); for (int i = 0; i < readLineBrick.size(); i++) { if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) { - cerr << "Virtual bands accessed incorrectly at virtual band " + cerr << "Virtual bands accessed incorrectly at virtual band " << virtualBands[readLineBrick.Band() - 1] << endl; return 1; } @@ -531,7 +531,7 @@ int main(int argc, char *argv[]) { } cerr << endl; bsqOneLineTestCube.close(); - + // Test reading outside boundaries cerr << "Testing reading outside of cube boundaries with virtual bands (1, 5)... " << endl; virtualBands.clear(); @@ -545,14 +545,14 @@ int main(int argc, char *argv[]) { for (int i = 0; i < readLineBrick.size(); i++) { if (readLineBrick.Band() == 1) { if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) { - cerr << "Virtual bands accessed incorrectly at virtual band " + cerr << "Virtual bands accessed incorrectly at virtual band " << virtualBands[readLineBrick.Band() - 1] << endl; return 1; } } else { if (readLineBrick[i] != Null) { - cerr << "Value outside cube boundary at virtual band " + cerr << "Value outside cube boundary at virtual band " << virtualBands[readLineBrick.Band() - 1] << endl; } } @@ -560,7 +560,7 @@ int main(int argc, char *argv[]) { } cerr << endl; bsqOneLineTestCube.close(); - + // Test reading descending bands cerr << "Testing reading descending virtual bands (3, 1, 3)... " << endl; virtualBands.clear(); @@ -574,7 +574,7 @@ int main(int argc, char *argv[]) { bsqOneLineTestCube.read(readLineBrick); for (int i = 0; i < readLineBrick.size(); i++) { if (readLineBrick[i] != (i + virtualBands[readLineBrick.Band()-1].toInt())) { - cerr << "Virtual bands accessed incorrectly at virtual band " + cerr << "Virtual bands accessed incorrectly at virtual band " << virtualBands[readLineBrick.Band() - 1] << endl; return 1; } @@ -582,8 +582,8 @@ int main(int argc, char *argv[]) { } cerr << endl; bsqOneLineTestCube.close(); - - + + // Test creating a bsq cube that exceeds 1GB sample size limit to test CubeBsqHandler cerr << "Testing creating large BSQ where samples exceed 1GB chunk size limit ... " << endl; cerr << "Constructing cube ... " << endl << endl; @@ -597,10 +597,10 @@ int main(int argc, char *argv[]) { cerr << endl; largebsqTestCube.close(); - - + + // Test bsq cube that has a linecount > maximum chunk line size to test CubeBsqHandler - cerr << "Testing creating BSQ cube where size of sample pixels exceeds cube's lineCount ... " + cerr << "Testing creating BSQ cube where size of sample pixels exceeds cube's lineCount ... " << endl; cerr << "Constructing cube ... " << endl << endl; Cube bsqTestCube; @@ -609,11 +609,11 @@ int main(int argc, char *argv[]) { bsqTestCube.setFormat(Cube::Bsq); bsqTestCube.create("IsisCube_bsq"); Report(bsqTestCube); - + cerr << endl; bsqTestCube.close(); - - + + // Check errors cerr << "Testing errors ... " << endl; try { diff --git a/isis/src/base/objs/GaussianStretch/unitTest.cpp b/isis/src/base/objs/GaussianStretch/unitTest.cpp index eaec92da43..9c5d61ae91 100644 --- a/isis/src/base/objs/GaussianStretch/unitTest.cpp +++ b/isis/src/base/objs/GaussianStretch/unitTest.cpp @@ -2,6 +2,7 @@ #include #include "GaussianStretch.h" #include "Histogram.h" +#include "ImageHistogram.h" #include "IException.h" #include "Preference.h" @@ -9,7 +10,7 @@ using namespace std; int main(int argc, char *argv[]) { Isis::Preference::Preferences(true); - Isis::Histogram hist(0, 99, 100); + Isis::Histogram *hist = new Isis::ImageHistogram(0, 99, 100); cout << setprecision(14); @@ -19,8 +20,8 @@ int main(int argc, char *argv[]) { data[i] = i; } - hist.AddData(data, numData); - Isis::GaussianStretch g(hist, 49.5, 14.0); + hist->AddData(data, numData); + Isis::GaussianStretch g(*hist, 49.5, 14.0); for(int i = 0; i < numData; i++) { cout << data[i] << " " << g.Map(data[i]) << endl; } diff --git a/isis/src/base/objs/Histogram/Histogram.cpp b/isis/src/base/objs/Histogram/Histogram.cpp index d8d60c2638..65519b098c 100644 --- a/isis/src/base/objs/Histogram/Histogram.cpp +++ b/isis/src/base/objs/Histogram/Histogram.cpp @@ -22,7 +22,6 @@ */ #include "Histogram.h" -#include "Brick.h" #include "ControlMeasure.h" #include "ControlNet.h" #include "ControlPoint.h" @@ -50,74 +49,10 @@ namespace Isis { Histogram::Histogram(double minimum, double maximum, int nbins) { SetValidRange(minimum, maximum); - //SetBinRange(minimum, maximum); SetBins(nbins); } - /** - * Constructs a histogram object using a cube. This constructor computes - * the minimum, maximum for the binning range and number of bins - * automatically. All statistics will still be collected, though data at - * either end of the histogram will be put into one bin in order to attempt to - * achieve better histogram statistics. - * - * TODO: progress needs to be a bool. - * - * @param cube The cube to used to determine min/max and bins - * @param statsBand The band number the histogram will be collected from - * @param progress The Progress object to be used to output the percent - * processed information - * @param startSample The sample to start reading cube data from - * @param startLine The line to start reading cube data from - * @param endSample The sample to stop reading cube data at (Null for nsamps) - * @param endLine The line to stop reading cube data at (Null for nlines) - * @param bins The number of histogram bins to create (0 for automatic) - * @param addCubeData True to fill the histogram with data in addition to - * initializing the binning ranges. - */ - Histogram::Histogram(Cube &cube, int statsBand, Progress *progress, - double startSample, double startLine, - double endSample, double endLine, - int bins, bool addCubeData) { - - InitializeFromCube(cube, statsBand, progress, bins, startSample, startLine, - endSample, endLine); - - if (addCubeData) { - Brick cubeDataBrick((int)(endSample - startSample + 1), - 1, 1, cube.pixelType()); - - // if band == 0, then we're gathering data for all bands. - int startBand = statsBand; - int endBand = statsBand; - - if (statsBand == 0) { - startBand = 1; - endBand = cube.bandCount(); - } - - if (progress != NULL) { - progress->SetText("Gathering histogram"); - progress->SetMaximumSteps( - (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1)); - progress->CheckStatus(); - } - - for (int band = startBand; band <= endBand; band++) { - for (int line = (int)startLine; line <= endLine; line++) { - cubeDataBrick.SetBasePosition(qRound(startSample), line, band); - cube.read(cubeDataBrick); - AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size()); - if (progress != NULL) { - progress->CheckStatus(); - } - } - } - } - } - - /** * Constructs a histogram from a control netowrk * @@ -138,9 +73,8 @@ namespace Isis { //set the ranges rangesFromNet(net,statFunc); - //add all the data to the now setup histogram - addMeasureDataFromNet(net,statFunc); + addMeasureDataFromNet(net, statFunc); } @@ -163,32 +97,17 @@ namespace Isis { } //get the range of the data - - rangesFromNet(net,statFunc); - - //stretch the domain so that it is an even multiple of binWidth - //for some reason Histogram makes the end points of the bin range be at the center of - //bins. Thus the +/-0.5 forces it to point the bin range at the ends of the bins. - //SetBinRange(binWidth*( floor(this->ValidMinimum()/binWidth )+0.5), - // binWidth*(ceil( this->ValidMaximum()/binWidth )-0.5) ); - - //Keep an eye on this to see if it breaks anything. Also, I need to create //a dataset to give this constructor for the unit test. - //tjw: SetValidRange is moved into SetBinRange - //SetValidRange(binWidth*floor(this->ValidMinimum()/binWidth), - // binWidth*ceil(this->ValidMaximum()/binWidth)); - //from the domain of the data and the requested bin width calculate the number of bins double domain = this->ValidMaximum() - this->ValidMinimum(); - int nBins = int ( ceil(domain/binWidth) ); + int nBins = int ( ceil(domain/binWidth) ) - 1; SetBins(nBins); - //add all the data to the now setup histogram - addMeasureDataFromNet(net,statFunc); + addMeasureDataFromNet(net, statFunc); } @@ -215,7 +134,6 @@ namespace Isis { const ControlMeasure *measure = point->GetMeasure(j); if (measure->IsIgnored()) continue; - this->AddData((measure->*statFunc)()); } } @@ -266,129 +184,6 @@ namespace Isis { //set up the histogram ranges SetValidRange(min, max); - //SetBinRange(min, max); - } - - - void Histogram::InitializeFromCube(Cube &cube, int statsBand, - Progress *progress, int nbins, double startSample, double startLine, - double endSample, double endLine) { - - // Make sure band is valid, 0 is valid (means all bands) - if ( (statsBand < 0) || (statsBand > cube.bandCount() ) ) { - string msg = "Cannot gather histogram for band [" + IString(statsBand) + - "]"; - throw IException(IException::Programmer, msg, _FILEINFO_); - } - - // We need to find the min/max DN value for our histogram bins to be the - // correct size. - double minDnValue = Null; - double maxDnValue = Null; - - if (cube.pixelType() == UnsignedByte) { - // If we can discretely store every data point, then we can use the - // possible extent of the data range as our min/max dn values. - if (nbins == 0) { - minDnValue = 0.0 * cube.multiplier() + cube.base(); - maxDnValue = 255.0 * cube.multiplier() + cube.base(); - nbins = 256; - } - } - else if (cube.pixelType() == UnsignedWord) { - if (nbins == 0) { - minDnValue = 0.0 * cube.multiplier() + cube.base(); - maxDnValue = 65535.0 * cube.multiplier() + cube.base(); - nbins = 65536; - } - } - else if (cube.pixelType() == SignedWord) { - if (nbins == 0) { - minDnValue = -32768.0 * cube.multiplier() + cube.base(); - maxDnValue = 32767.0 * cube.multiplier() + cube.base(); - nbins = 65536; - } - } - // 32-bit data covers too big of a range of values to use - // the min and max possible values to set our value range. - // So, just set the number of bins and then later we will - // compute the min and max value in the actual cube. - else if (cube.pixelType() == UnsignedInteger || - cube.pixelType() == SignedInteger || - cube.pixelType() == Real) { - if (nbins == 0) { - nbins = 65536; - } - } - else { - IString msg = "Unsupported pixel type"; - throw IException(IException::Programmer, msg, _FILEINFO_); - } - - if (startSample == Null) - startSample = 1.0; - - if (endSample == Null) - endSample = cube.sampleCount(); - - if (startLine == Null) - startLine = 1.0; - - if (endLine == Null) - endLine = cube.lineCount(); - - // If we still need our min/max DN values, find them. - if (minDnValue == Null || maxDnValue == Null) { - - Brick cubeDataBrick((int)(endSample - startSample + 1), - 1, 1, cube.pixelType() ); - Statistics stats; - - // if band == 0, then we're gathering stats for all bands. I'm really - // not sure that this is correct, a good idea or called from anywhere... - // but I don't have time to track down the use case. - int startBand = statsBand; - int endBand = statsBand; - - if (statsBand == 0) { - startBand = 1; - endBand = cube.bandCount(); - } - - if (progress != NULL) { - - progress->SetText("Computing min/max for histogram"); - progress->SetMaximumSteps( - (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1) ); - progress->CheckStatus(); - } - - for (int band = startBand; band <= endBand; band++) { - for (int line = (int)startLine; line <= endLine; line++) { - - cubeDataBrick.SetBasePosition(qRound(startSample), line, band); - cube.read(cubeDataBrick); - stats.AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size()); - - if (progress != NULL) { - progress->CheckStatus(); - } - } - } - - if (stats.ValidPixels() == 0) { - minDnValue = 0.0; - maxDnValue = 1.0; - } - else { - minDnValue = stats.Minimum(); - maxDnValue = stats.Maximum(); - } - } - - // Set the bins and range - SetValidRange(minDnValue, maxDnValue); - SetBins(nbins); } @@ -396,7 +191,7 @@ namespace Isis { Histogram::~Histogram() { } - //2015-08-24, Tyler Wilson: Added Statistics::SetValidRange call to SetBinRange + //2015-08-24, Tyler Wilson: Added Statistics::SetValidRange call to SetValidRange //So the two functions do not have to be called together when setting //up a histogram @@ -462,8 +257,8 @@ namespace Isis { index = 0; } else { - index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) * - (data[i] - BinRangeStart() ) + 0.5); + index = (int) floor( ((double) nbins / (BinRangeEnd() - BinRangeStart())) * + (data[i] - BinRangeStart()) ); } if (index < 0) index = 0; if (index >= nbins) index = nbins - 1; @@ -490,8 +285,8 @@ namespace Isis { index = 0; } else { - index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart() ) * - (data - BinRangeStart() ) + 0.5); + index = (int) floor( ((double) nbins / (BinRangeEnd() - BinRangeStart())) * + (data - BinRangeStart()) ); } if (index < 0) index = 0; if (index >= nbins) index = nbins - 1; @@ -522,8 +317,8 @@ namespace Isis { index = 0; } else { - index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) * - (data[i] - BinRangeStart()) + 0.5); + index = (int) floor( ((double) nbins / (BinRangeEnd() - BinRangeStart())) * + (data[i] - BinRangeStart()) ); } if (index < 0) index = 0; if (index >= nbins) index = nbins - 1; @@ -591,7 +386,7 @@ namespace Isis { } } - return BinMiddle( (int)p_bins.size() - 1); + return BinMiddle( (int) p_bins.size() - 1); } @@ -653,8 +448,8 @@ namespace Isis { throw IException(IException::Programmer, message, _FILEINFO_); } - double binSize = (BinRangeEnd() - BinRangeStart()) / (double)(p_bins.size() - 1); - low = BinRangeStart() - binSize / 2.0 + binSize * (double) index; + double binSize = (BinRangeEnd() - BinRangeStart()) / (double) p_bins.size(); + low = BinRangeStart() + binSize * (double) index; high = low + binSize; } diff --git a/isis/src/base/objs/Histogram/Histogram.h b/isis/src/base/objs/Histogram/Histogram.h index 5f6c33ddb6..c7fbb6d4d7 100644 --- a/isis/src/base/objs/Histogram/Histogram.h +++ b/isis/src/base/objs/Histogram/Histogram.h @@ -81,10 +81,16 @@ namespace Isis { * #1673. * @history 2018-07-27 Jesse Mapel - Added support for initializing a histogram from * signed and unsigned word cubes. References #971. + * @history 2020-06-11 Kaitlyn Lee - Changed how to detemine which bin a pixel/measure falls + * into in AddData(). Changed how the bin range is calculated in + * BinRange(). The math for these functions were incorrect and not + * intuitive. These changes were made alongside changes made + * to cnethist and hist. */ class Histogram : public Statistics { public: + Histogram() = default; Histogram(double minimum, double maximum, int bins = 1024); Histogram(Cube &cube, int statsBand, Progress *progress = NULL, @@ -101,9 +107,9 @@ namespace Isis { void SetBins(const int bins); void Reset(); - void AddData(const double *data, const unsigned int count); - void AddData(const double data); - void RemoveData(const double *data, const unsigned int count); + virtual void AddData(const double *data, const unsigned int count); + virtual void AddData(const double data); + virtual void RemoveData(const double *data, const unsigned int count); double Median() const; double Mode() const; @@ -111,7 +117,7 @@ namespace Isis { double Skew() const; BigInt BinCount(const int index) const; - void BinRange(const int index, double &low, double &high) const; + virtual void BinRange(const int index, double &low, double &high) const; double BinMiddle(const int index) const; double BinSize() const; int Bins() const; @@ -127,17 +133,14 @@ namespace Isis { void SetValidRange(const double minimum = Isis::ValidMinimum, const double maximum = Isis::ValidMaximum); - private: - void InitializeFromCube(Cube &cube, int statsBand, Progress *progress, - int nbins = 0, double startSample = Null, double startLine = Null, - double endSample = Null, double endLine = Null); - - void addMeasureDataFromNet(ControlNet &net, double(ControlMeasure::*statFunc)() const); - void rangesFromNet(ControlNet &net, double(ControlMeasure::*statFunc)() const); - + protected: //! The array of counts. std::vector p_bins; + + private: double p_binRangeStart, p_binRangeEnd; + void addMeasureDataFromNet(ControlNet &net, double(ControlMeasure::*statFunc)() const); + void rangesFromNet(ControlNet &net, double(ControlMeasure::*statFunc)() const); }; }; diff --git a/isis/src/base/objs/Histogram/Histogram.truth b/isis/src/base/objs/Histogram/Histogram.truth index 4412b086b5..dbc834a18d 100644 --- a/isis/src/base/objs/Histogram/Histogram.truth +++ b/isis/src/base/objs/Histogram/Histogram.truth @@ -1,24 +1,24 @@ -Median: 2 -Mode: 2 -Skew: 0 -Percent(0.5): 1 -Percent(99.5): 3 -Bins: 21 +Median: 2.5 +Mode: 2.5 +Skew: -1.83712 +Percent(0.5): 1.5 +Percent(99.5): 3.5 +Bins: 20 BinSize: 1 -BinMiddle: -10 -BinRange(0,low): -10.5 -BinRange(0,high): -9.5 +BinMiddle: -9.5 +BinRange(0,low): -10 +BinRange(0,high): -9 BinCount(0): 0 -BinRange(20,low): 9.5 -BinRange(20,high): 10.5 +BinRange(20,low): 9 +BinRange(20,high): 10 BinCount(20): 0 Average: 4 -Median: 5 -Mode: 5 -Skew: -1.73205 -Percent(0.5): 2 -Percent(99.5): 5 +Median: 5.5 +Mode: 5.5 +Skew: -2.59808 +Percent(0.5): 2.5 +Percent(99.5): 5.5 BinCount(0): 0 BinCount(20): 0 @@ -49,16 +49,16 @@ Bin Range: (0.00973653,0.421463) Average: 0.128848 Std Deviation: 0.0848166 Variance: 0.00719386 -Median: 0.118086 -Mode: 0.074746 -Skew: 0.380683 -Percent(0.5): 0.00973653 -Percent(99.5): 0.421463 +Median: 0.107251 +Mode: 0.0639111 +Skew: 0.763918 +Percent(0.5): 0.0205714 +Percent(99.5): 0.410628 Minimum: 0.00973653 Maximum: 0.421463 -# Bins: 20 +# Bins: 19 BinWidth: 0.0216698 -MaxBinCount: 9 +MaxBinCount: 10 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -98,7 +98,7 @@ Percent(0.5): -1.79769e+308 Percent(99.5): -1.79769e+308 Minimum: -1.79769e+308 Maximum: -1.79769e+308 -# Bins: 20 +# Bins: 19 BinWidth: 0.00963103 MaxBinCount: 0 @@ -139,14 +139,14 @@ Bin Range: (0.00973653,0.421463) Average: 0.128848 Std Deviation: 0.0848166 Variance: 0.00719386 -Median: 0.110158 -Mode: 0.0699892 -Skew: 0.661099 -Percent(0.5): 0.00973653 -Percent(99.5): 0.421463 +Median: 0.105137 +Mode: 0.0247997 +Skew: 0.838696 +Percent(0.5): 0.0147576 +Percent(99.5): 0.416442 Minimum: 0.00973653 Maximum: 0.421463 -# Bins: 42 +# Bins: 41 BinWidth: 0.0100421 MaxBinCount: 6 @@ -188,7 +188,7 @@ Percent(0.5): -1.79769e+308 Percent(99.5): -1.79769e+308 Minimum: -1.79769e+308 Maximum: -1.79769e+308 -# Bins: 42 +# Bins: 41 BinWidth: 0.00446316 MaxBinCount: 0 @@ -215,376 +215,37 @@ Sum Square: 0 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Constructor3: -Histogram(icube,1) Real - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (-1e+20,1e+20) -Bin Range: (-1e+20,1e+20) -Average: 0 -Std Deviation: 3.10109e+19 -Variance: 9.61674e+38 -Median: 1.5259e+15 -Mode: 1.5259e+15 -Skew: -0.000147616 -Percent(0.5): -1e+20 -Percent(99.5): 1e+20 -Minimum: -1e+20 -Maximum: 1e+20 -# Bins: 65536 -BinWidth: 3.0518e+15 -MaxBinCount: 5292 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -++++++++++++++++++ Statistics Counters ++++++++++++++++++ - -Total pixels: 15876 -Valid pixels: 7056 -Over Range pixels: 0 -Under Range pixels: 0 -Null pixels: 1764 -Lis pixels: 1764 -His pixels: 1764 -Lrs pixels: 1764 -Hrs pixels: 1764 -Out of range pixels: 0 -Minimum: -1e+20 -Maximum: 1e+20 -Valid Minimum: -1e+20 -Valid Maximum: 1e+20 -Sum: 0 -Sum Square: 6.78461e+42 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Resetting bin range to (70,110) - -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (70,110) -Bin Range: (70,110) -Average: -1.79769e+308 -Std Deviation: -1.79769e+308 -Variance: -1.79769e+308 -Median: -1.79769e+308 -Mode: -1.79769e+308 -Skew: -1.79769e+308 -Percent(0.5): -1.79769e+308 -Percent(99.5): -1.79769e+308 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -# Bins: 65536 -BinWidth: 0.000610361 -MaxBinCount: 0 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -++++++++++++++++++ Statistics Counters ++++++++++++++++++ - -Total pixels: 0 -Valid pixels: 0 -Over Range pixels: 0 -Under Range pixels: 0 -Null pixels: 0 -Lis pixels: 0 -His pixels: 0 -Lrs pixels: 0 -Hrs pixels: 0 -Out of range pixels: 0 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -Valid Minimum: 70 -Valid Maximum: 110 -Sum: 0 -Sum Square: 0 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Constructor3: -Histogram(icube,1) SignedWord - +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (-1.00049e+20,1e+20) -Bin Range: (-1.00049e+20,1e+20) -Average: -1.14471e+15 -Std Deviation: 3.10107e+19 -Variance: 9.61663e+38 -Median: -1.52627e+15 -Mode: -1.52627e+15 -Skew: 3.69133e-05 -Percent(0.5): -1e+20 -Percent(99.5): 1e+20 -Minimum: -1e+20 -Maximum: 1e+20 -# Bins: 65536 -BinWidth: 3.05255e+15 -MaxBinCount: 5292 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -++++++++++++++++++ Statistics Counters ++++++++++++++++++ - -Total pixels: 15876 -Valid pixels: 7056 -Over Range pixels: 0 -Under Range pixels: 0 -Null pixels: 1764 -Lis pixels: 1764 -His pixels: 1764 -Lrs pixels: 1764 -Hrs pixels: 1764 -Out of range pixels: 0 -Minimum: -1e+20 -Maximum: 1e+20 -Valid Minimum: -1.00049e+20 -Valid Maximum: 1e+20 -Sum: -8.07705e+18 -Sum Square: 6.78453e+42 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Resetting bin range to (70,110) - -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (70,110) -Bin Range: (70,110) -Average: -1.79769e+308 -Std Deviation: -1.79769e+308 -Variance: -1.79769e+308 -Median: -1.79769e+308 -Mode: -1.79769e+308 -Skew: -1.79769e+308 -Percent(0.5): -1.79769e+308 -Percent(99.5): -1.79769e+308 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -# Bins: 65536 -BinWidth: 0.000610361 -MaxBinCount: 0 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -++++++++++++++++++ Statistics Counters ++++++++++++++++++ - -Total pixels: 0 -Valid pixels: 0 -Over Range pixels: 0 -Under Range pixels: 0 -Null pixels: 0 -Lis pixels: 0 -His pixels: 0 -Lrs pixels: 0 -Hrs pixels: 0 -Out of range pixels: 0 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -Valid Minimum: 70 -Valid Maximum: 110 -Sum: 0 -Sum Square: 0 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Constructor3: -Histogram(icube,1) UnsignedWord - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (-1.00009e+20,1.0004e+20) -Bin Range: (-1.00009e+20,1.0004e+20) -Average: 3.33468e+19 -Std Deviation: 5.35272e+19 -Variance: 2.86516e+39 -Median: 1.52627e+15 -Mode: 1.52627e+15 -Skew: 1.86888 -Percent(0.5): -1e+20 -Percent(99.5): 1.0004e+20 -Minimum: -1e+20 -Maximum: 1.0004e+20 -# Bins: 65536 -BinWidth: 3.05255e+15 -MaxBinCount: 5292 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -++++++++++++++++++ Statistics Counters ++++++++++++++++++ - -Total pixels: 15876 -Valid pixels: 10584 -Over Range pixels: 0 -Under Range pixels: 0 -Null pixels: 1764 -Lis pixels: 1764 -His pixels: 0 -Lrs pixels: 1764 -Hrs pixels: 0 -Out of range pixels: 0 -Minimum: -1e+20 -Maximum: 1.0004e+20 -Valid Minimum: -1.00009e+20 -Valid Maximum: 1.0004e+20 -Sum: 3.52943e+23 -Sum Square: 4.20915e+43 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Resetting bin range to (70,110) - -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (70,110) -Bin Range: (70,110) -Average: -1.79769e+308 -Std Deviation: -1.79769e+308 -Variance: -1.79769e+308 -Median: -1.79769e+308 -Mode: -1.79769e+308 -Skew: -1.79769e+308 -Percent(0.5): -1.79769e+308 -Percent(99.5): -1.79769e+308 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -# Bins: 65536 -BinWidth: 0.000610361 -MaxBinCount: 0 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -++++++++++++++++++ Statistics Counters ++++++++++++++++++ - -Total pixels: 0 -Valid pixels: 0 -Over Range pixels: 0 -Under Range pixels: 0 -Null pixels: 0 -Lis pixels: 0 -His pixels: 0 -Lrs pixels: 0 -Hrs pixels: 0 -Out of range pixels: 0 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -Valid Minimum: 70 -Valid Maximum: 110 -Sum: 0 -Sum Square: 0 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Constructor3: -Histogram(icube,1) UnsignedByte +Constructor4: +Histogram(double mim, double max,int nbins) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Data Vector a: +[ -1.79769e+308 -1.79769e+308 -1.79769e+308 -1.79769e+308 -1.79769e+308 1 2 2 3 ] -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (-1.00791e+20,1.00791e+20) -Bin Range: (-1.00791e+20,1.00791e+20) -Average: 2.96443e+17 -Std Deviation: 3.10605e+19 -Variance: 9.64757e+38 -Median: 3.95257e+17 -Mode: 3.95257e+17 -Skew: -0.00954403 -Percent(0.5): -1e+20 -Percent(99.5): 1e+20 -Minimum: -1e+20 -Maximum: 1e+20 -# Bins: 256 -BinWidth: 7.90514e+17 -MaxBinCount: 5292 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -++++++++++++++++++ Statistics Counters ++++++++++++++++++ - -Total pixels: 15876 -Valid pixels: 7056 -Over Range pixels: 0 -Under Range pixels: 0 -Null pixels: 5292 -Lis pixels: 0 -His pixels: 0 -Lrs pixels: 0 -Hrs pixels: 3528 -Out of range pixels: 0 -Minimum: -1e+20 -Maximum: 1e+20 -Valid Minimum: -1.00791e+20 -Valid Maximum: 1.00791e+20 -Sum: 2.0917e+21 -Sum Square: 6.80698e+42 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Resetting bin range to (70,110) - -+++++++++++++++++++ Histogram Members +++++++++++++++++++ - -Stats Range: (70,110) -Bin Range: (70,110) -Average: -1.79769e+308 -Std Deviation: -1.79769e+308 -Variance: -1.79769e+308 -Median: -1.79769e+308 -Mode: -1.79769e+308 -Skew: -1.79769e+308 -Percent(0.5): -1.79769e+308 -Percent(99.5): -1.79769e+308 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -# Bins: 256 -BinWidth: 0.156863 -MaxBinCount: 0 - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++ Statistics Counters ++++++++++++++++++ -Total pixels: 0 -Valid pixels: 0 +Total pixels: 9 +Valid pixels: 4 Over Range pixels: 0 Under Range pixels: 0 -Null pixels: 0 -Lis pixels: 0 -His pixels: 0 -Lrs pixels: 0 -Hrs pixels: 0 +Null pixels: 1 +Lis pixels: 1 +His pixels: 1 +Lrs pixels: 1 +Hrs pixels: 1 Out of range pixels: 0 -Minimum: -1.79769e+308 -Maximum: -1.79769e+308 -Valid Minimum: 70 -Valid Maximum: 110 -Sum: 0 -Sum Square: 0 +Minimum: 1 +Maximum: 3 +Valid Minimum: -10 +Valid Maximum: 10 +Sum: 8 +Sum Square: 18 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Constructor4: -Histogram(double mim, double max,int nbins) - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Data Vector a: -[ -1.79769e+308 -1.79769e+308 -1.79769e+308 -1.79769e+308 -1.79769e+308 1 2 2 3 ] - - +++++++++++++++++++ Histogram Members +++++++++++++++++++ Stats Range: (-10,10) @@ -592,23 +253,30 @@ Bin Range: (-10,10) Average: 2 Std Deviation: 0.816497 Variance: 0.666667 -Median: 0 -Mode: 0 -Skew: 7.34847 +Median: 4 +Mode: 4 +Skew: -7.34847 Percent(0.5): 0 -Percent(99.5): 5 +Percent(99.5): 4 Minimum: 1 Maximum: 3 # Bins: 5 -BinWidth: 5 +BinWidth: 4 MaxBinCount: 3 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +**********************Data Vector A Histogram********************** +Bin 0: [-10,-6], Count = 0 +Bin 1: [-6,-2], Count = 0 +Bin 2: [-2,2], Count = 1 +Bin 3: [2,6], Count = 3 +Bin 4: [6,10], Count = 0 +******************************************************************* + Data Vector b: [ -9 -7 -5 -0.5 2.3 5.5 7.1 8.2 8.3 ] - ++++++++++++++++++ Statistics Counters ++++++++++++++++++ Total pixels: 9 @@ -637,32 +305,32 @@ Bin Range: (-10,10) Average: 1.1 Std Deviation: 6.76794 Variance: 45.805 -Median: 0 -Mode: -5 -Skew: 0.487593 -Percent(0.5): -10 -Percent(99.5): 10 +Median: 4 +Mode: 8 +Skew: -1.28547 +Percent(0.5): -8 +Percent(99.5): 8 Minimum: -9 Maximum: 8.3 # Bins: 5 -BinWidth: 5 -MaxBinCount: 2 +BinWidth: 4 +MaxBinCount: 3 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ **********************Data Vector B Histogram********************** -Bin 0: [-12.5,-7.5], Count = 1 -Bin 1: [-7.5,-2.5], Count = 2 -Bin 2: [-2.5,2.5], Count = 2 -Bin 3: [2.5,7.5], Count = 2 -Bin 4: [7.5,12.5], Count = 2 +Bin 0: [-10,-6], Count = 2 +Bin 1: [-6,-2], Count = 1 +Bin 2: [-2,2], Count = 1 +Bin 3: [2,6], Count = 2 +Bin 4: [6,10], Count = 3 ******************************************************************* Removing: -9,-7,-5 **********************Data Vector B Histogram********************** -Bin 0: [-12.5,-7.5], Count = 0 -Bin 1: [-7.5,-2.5], Count = 0 -Bin 2: [-2.5,2.5], Count = 2 -Bin 3: [2.5,7.5], Count = 2 -Bin 4: [7.5,12.5], Count = 2 +Bin 0: [-10,-6], Count = 0 +Bin 1: [-6,-2], Count = 0 +Bin 2: [-2,2], Count = 1 +Bin 3: [2,6], Count = 2 +Bin 4: [6,10], Count = 3 ******************************************************************* +++++++++++++++++++ Histogram Members +++++++++++++++++++ @@ -672,11 +340,11 @@ Bin Range: (-10,10) Average: 5.15 Std Deviation: 3.55514 Variance: 12.639 -Median: 5 -Mode: 0 -Skew: 0.126577 +Median: 4 +Mode: 8 +Skew: 0.970427 Percent(0.5): 0 -Percent(99.5): 10 +Percent(99.5): 8 Minimum: **PROGRAMMER ERROR** Minimum is invalid since you removed data. Changing BinRange for b-vector's histogram... @@ -716,7 +384,7 @@ Percent(99.5): -1.79769e+308 Minimum: -1.79769e+308 Maximum: -1.79769e+308 # Bins: 5 -BinWidth: 2.5 +BinWidth: 2 MaxBinCount: 0 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/isis/src/base/objs/Histogram/unitTest.cpp b/isis/src/base/objs/Histogram/unitTest.cpp index 9b57169fc9..3bf4a88bbb 100644 --- a/isis/src/base/objs/Histogram/unitTest.cpp +++ b/isis/src/base/objs/Histogram/unitTest.cpp @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) { // Old unit test begins here Isis::Preference::Preferences(true); - Isis::Histogram h(-10.0, 10.0, 21); + Isis::Histogram h(-10.0, 10.0, 20); double low, high; try { @@ -59,10 +59,10 @@ int main(int argc, char *argv[]) { cout << "BinRange(0,low): " << low << endl; cout << "BinRange(0,high): " << high << endl; cout << "BinCount(0): " << h.BinCount(0) << endl; - h.BinRange(20, low, high); + h.BinRange(19, low, high); cout << "BinRange(20,low): " << low << endl; cout << "BinRange(20,high): " << high << endl; - cout << "BinCount(20): " << h.BinCount(20) << endl; + cout << "BinCount(20): " << h.BinCount(19) << endl; cout << endl; h.RemoveData(a, 3); @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) { cout << "Percent(0.5): " << h.Percent(0.5) << endl; cout << "Percent(99.5): " << h.Percent(99.5) << endl; cout << "BinCount(0): " << h.BinCount(0) << endl; - cout << "BinCount(20): " << h.BinCount(20) << endl; + cout << "BinCount(20): " << h.BinCount(19) << endl; cout << endl; } catch(Isis::IException &e) { @@ -168,7 +168,7 @@ int main(int argc, char *argv[]) { try { - hist1 = new Isis::Histogram(net, &Isis::ControlMeasure::GetResidualMagnitude,20); + hist1 = new Isis::Histogram(net, &Isis::ControlMeasure::GetResidualMagnitude, 19); cout << endl; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); - } - - histogramMembers(histcube); - statCounters(histcube); - cout << "Resetting bin range to (70,110)" << endl; - histcube ->SetValidRange(70,110); - histogramMembers(histcube); - statCounters(histcube); - delete(histcube); - cout << endl; - - } - catch (Isis::IException &e) { - - e.print(); - - } - - - try { - - Isis::FileName cubeFile("$ISISTESTDATA/isis/src/base/unitTestData/isisTruth_Signed16Bit.cub"); - Isis::Cube icube; - icube.open(cubeFile.expanded()); - Isis::Histogram *histcube; - histcube = new Isis::Histogram(icube, 1); - - cout << endl; - - cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); - } - - histogramMembers(histcube); - statCounters(histcube); - cout << "Resetting bin range to (70,110)" << endl; - histcube ->SetValidRange(70,110); - histogramMembers(histcube); - statCounters(histcube); - delete(histcube); - cout << endl; - - } - catch (Isis::IException &e) { - - e.print(); - - } - - - try { - - Isis::FileName cubeFile("$ISISTESTDATA/isis/src/base/unitTestData/isisTruth_Unsigned16Bit.cub"); - Isis::Cube icube; - icube.open(cubeFile.expanded()); - Isis::Histogram *histcube; - histcube = new Isis::Histogram(icube, 1); - - cout << endl; - - cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); - } - - histogramMembers(histcube); - statCounters(histcube); - cout << "Resetting bin range to (70,110)" << endl; - histcube ->SetValidRange(70,110); - histogramMembers(histcube); - statCounters(histcube); - delete(histcube); - cout << endl; - - } - catch (Isis::IException &e) { - - e.print(); - - } - - - try { - - Isis::FileName cubeFile("$ISISTESTDATA/isis/src/base/unitTestData/isisTruth_8Bit.cub"); - Isis::Cube icube; - icube.open(cubeFile.expanded()); - Isis::Histogram *histcube; - histcube = new Isis::Histogram(icube, 1); - - cout << endl; - - cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); - } - - histogramMembers(histcube); - statCounters(histcube); - cout << "Resetting bin range to (70,110)" << endl; - histcube ->SetValidRange(70,110); - histogramMembers(histcube); - statCounters(histcube); - delete(histcube); - cout << endl; - - } - catch (Isis::IException &e) { - - e.print(); - - } - double low1 = -10; double high1 = 10; int nbins = 5; @@ -430,13 +265,17 @@ int main(int argc, char *argv[]) { arrayDisplay(a,9); cout << endl; + statCounters(ahist); histogramMembers(ahist); + cout << "**********************Data Vector A Histogram**********************" << endl; + histDisplay(ahist); + cout << "*******************************************************************" << endl; + cout << endl; cout << "Data Vector b: " << endl; arrayDisplay(b,9); cout << endl; - cout << endl; statCounters(bhist); histogramMembers(bhist); diff --git a/isis/src/base/objs/ImageHistogram/ImageHistogram.cpp b/isis/src/base/objs/ImageHistogram/ImageHistogram.cpp new file mode 100644 index 0000000000..4c32892be1 --- /dev/null +++ b/isis/src/base/objs/ImageHistogram/ImageHistogram.cpp @@ -0,0 +1,346 @@ +/** + * @file + * $Revision: 1.4 $ + * $Date: 2008/08/15 22:03:32 $ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#include "ImageHistogram.h" + +#include "Brick.h" +#include "ControlNet.h" +#include "ControlMeasure.h" + +#include +#include +#include +#include + +using namespace std; + +namespace Isis { + + /** + * Constructs a histogram object. Only data between the minimum and maximum + * will be binned, and the bin range will be from the minimum to the maximum. + * + * @param minimum Minimum value for binning the data into the histogram. + * @param maximum Maximum value for binning the data into the histogram. + * @param nbins The number of bins to use + */ + ImageHistogram::ImageHistogram(double minimum, double maximum, int nbins) : + Histogram(minimum, maximum, nbins) { + } + + + /** + * Constructs a histogram object using a cube. This constructor computes + * the minimum, maximum for the binning range and number of bins + * automatically. All statistics will still be collected, though data at + * either end of the histogram will be put into one bin in order to attempt to + * achieve better histogram statistics. + * + * TODO: progress needs to be a bool. + * + * @param cube The cube to used to determine min/max and bins + * @param statsBand The band number the histogram will be collected from + * @param progress The Progress object to be used to output the percent + * processed information + * @param startSample The sample to start reading cube data from + * @param startLine The line to start reading cube data from + * @param endSample The sample to stop reading cube data at (Null for nsamps) + * @param endLine The line to stop reading cube data at (Null for nlines) + * @param bins The number of histogram bins to create (0 for automatic) + * @param addCubeData True to fill the histogram with data in addition to + * initializing the binning ranges. + */ + ImageHistogram::ImageHistogram(Cube &cube, int statsBand, Progress *progress, + double startSample, double startLine, + double endSample, double endLine, + int bins, bool addCubeData) { + InitializeFromCube(cube, statsBand, progress, bins, startSample, startLine, + endSample, endLine); + + if (addCubeData) { + Brick cubeDataBrick((int)(endSample - startSample + 1), + 1, 1, cube.pixelType()); + + // if band == 0, then we're gathering data for all bands. + int startBand = statsBand; + int endBand = statsBand; + + if (statsBand == 0) { + startBand = 1; + endBand = cube.bandCount(); + } + + if (progress != NULL) { + progress->SetText("Gathering histogram"); + progress->SetMaximumSteps( + (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1)); + progress->CheckStatus(); + } + + for (int band = startBand; band <= endBand; band++) { + for (int line = (int)startLine; line <= endLine; line++) { + cubeDataBrick.SetBasePosition(qRound(startSample), line, band); + cube.read(cubeDataBrick); + AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size()); + if (progress != NULL) { + progress->CheckStatus(); + } + } + } + } + } + + void ImageHistogram::InitializeFromCube(Cube &cube, int statsBand, + Progress *progress, int nbins, double startSample, double startLine, + double endSample, double endLine) { + // Make sure band is valid, 0 is valid (means all bands) + if ( (statsBand < 0) || (statsBand > cube.bandCount() ) ) { + string msg = "Cannot gather histogram for band [" + IString(statsBand) + + "]"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + // We need to find the min/max DN value for our histogram bins to be the + // correct size. + double minDnValue = Null; + double maxDnValue = Null; + + if (cube.pixelType() == UnsignedByte) { + // If we can discretely store every data point, then we can use the + // possible extent of the data range as our min/max dn values. + if (nbins == 0) { + minDnValue = 0.0 * cube.multiplier() + cube.base(); + maxDnValue = 255.0 * cube.multiplier() + cube.base(); + nbins = 256; + } + } + else if (cube.pixelType() == UnsignedWord) { + if (nbins == 0) { + minDnValue = 0.0 * cube.multiplier() + cube.base(); + maxDnValue = 65535.0 * cube.multiplier() + cube.base(); + nbins = 65536; + } + } + else if (cube.pixelType() == SignedWord) { + if (nbins == 0) { + minDnValue = -32768.0 * cube.multiplier() + cube.base(); + maxDnValue = 32767.0 * cube.multiplier() + cube.base(); + nbins = 65536; + } + } + // 32-bit data covers too big of a range of values to use + // the min and max possible values to set our value range. + // So, just set the number of bins and then later we will + // compute the min and max value in the actual cube. + else if (cube.pixelType() == UnsignedInteger || + cube.pixelType() == SignedInteger || + cube.pixelType() == Real) { + if (nbins == 0) { + nbins = 65536; + } + } + else { + IString msg = "Unsupported pixel type"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + if (startSample == Null) + startSample = 1.0; + + if (endSample == Null) + endSample = cube.sampleCount(); + + if (startLine == Null) + startLine = 1.0; + + if (endLine == Null) + endLine = cube.lineCount(); + + // If we still need our min/max DN values, find them. + if (minDnValue == Null || maxDnValue == Null) { + + Brick cubeDataBrick((int)(endSample - startSample + 1), + 1, 1, cube.pixelType() ); + Statistics stats; + + // if band == 0, then we're gathering stats for all bands. I'm really + // not sure that this is correct, a good idea or called from anywhere... + // but I don't have time to track down the use case. + int startBand = statsBand; + int endBand = statsBand; + + if (statsBand == 0) { + startBand = 1; + endBand = cube.bandCount(); + } + + if (progress != NULL) { + + progress->SetText("Computing min/max for histogram"); + progress->SetMaximumSteps( + (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1) ); + progress->CheckStatus(); + } + + for (int band = startBand; band <= endBand; band++) { + for (int line = (int)startLine; line <= endLine; line++) { + + cubeDataBrick.SetBasePosition(qRound(startSample), line, band); + cube.read(cubeDataBrick); + stats.AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size()); + + if (progress != NULL) { + progress->CheckStatus(); + } + } + } + + if (stats.ValidPixels() == 0) { + minDnValue = 0.0; + maxDnValue = 1.0; + } + else { + minDnValue = stats.Minimum(); + maxDnValue = stats.Maximum(); + } + } + + // Set the bins and range + SetValidRange(minDnValue, maxDnValue); + SetBins(nbins); + } + + //! Destructs a histogram object. + ImageHistogram::~ImageHistogram() { + } + + /** + * Add an array of doubles to the histogram counters. This method can be + * invoked multiple times. For example, once for each line in a cube, before + * obtaining statistics and histogram information. + * + * @param data Pointer to array of double to add. + * @param count Number of doubles to process. + */ + void ImageHistogram::AddData(const double *data, + const unsigned int count) { + Statistics::AddData(data, count); + + int nbins = p_bins.size(); + int index; + for (unsigned int i = 0; i < count; i++) { + if (IsValidPixel(data[i]) && InRange(data[i]) ) { + if (BinRangeStart() == BinRangeEnd() ) { + index = 0; + } + else { + index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) * + (data[i] - BinRangeStart() ) + 0.5); + } + if (index < 0) index = 0; + if (index >= nbins) index = nbins - 1; + p_bins[index] += 1; + } + } + } + + /** + * Add a single double data to the histogram. Of course this can be invoke multiple times. + * e.g. once for each residual in a network for instance. + * + * @param data a single observation to be added to the histogram + */ + void ImageHistogram::AddData(const double data) { + Statistics::AddData(data); + + int nbins = p_bins.size(); + int index; + if (IsValidPixel(data) && InRange(data) ) { + if (BinRangeStart() == BinRangeEnd() ) { + index = 0; + } + else { + index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart() ) * + (data - BinRangeStart() ) + 0.5); + } + if (index < 0) index = 0; + if (index >= nbins) index = nbins - 1; + p_bins[index] += 1; + } + } + + /** + * Remove an array of doubles from the histogram counters. Note that this + * invalidates the absolute minimum and maximum. They will no longer be + * useable. + * @see Stats + * + * @param data Pointer to array of doubles to remove. + * @param count number of doubles to process. + */ + void ImageHistogram::RemoveData(const double *data, + const unsigned int count) { + Statistics::RemoveData(data, count); + + int nbins = p_bins.size(); + int index; + for (unsigned int i = 0; i < count; i++) { + if (IsValidPixel(data[i]) ) { + + if (BinRangeStart() == BinRangeEnd() ) { + index = 0; + } + else { + index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) * + (data[i] - BinRangeStart()) + 0.5); + } + if (index < 0) index = 0; + if (index >= nbins) index = nbins - 1; + p_bins[index] -= 1; + } + } + } + + /** + * Returns the left edge and right edge values of a bin. That is the range of + * data the bin covers. + * + * @throws iException The programmer has passed in an index outside of 0 + * to Bins()-1. + * + * @param index Index of the desired bin 0 to Bins()-1. + * @param low The value at the left edge of the requested bin. + * @param high The value at the right edge of the requested bin. + */ + void ImageHistogram::BinRange(const int index, + double &low, double &high) const { + if ( (index < 0) || (index >= (int)p_bins.size() ) ) { + + QString message = Message::ArraySubscriptNotInRange(index); + throw IException(IException::Programmer, message, _FILEINFO_); + } + + double binSize = (BinRangeEnd() - BinRangeStart()) / (double)(p_bins.size() - 1); + low = BinRangeStart() - binSize / 2.0 + binSize * (double) index; + high = low + binSize; + } +} diff --git a/isis/src/base/objs/ImageHistogram/ImageHistogram.h b/isis/src/base/objs/ImageHistogram/ImageHistogram.h new file mode 100644 index 0000000000..058a6bdc98 --- /dev/null +++ b/isis/src/base/objs/ImageHistogram/ImageHistogram.h @@ -0,0 +1,81 @@ +/** + * @file + * $Revision: 1.3 $ + * $Date: 2008/08/15 22:03:32 $ + * + * Unless noted otherwise, the portions of Isis written by the USGS are + * public domain. See individual third-party library and package descriptions + * for intellectual property information, user agreements, and related + * information. + * + * Although Isis has been used by the USGS, no warranty, expressed or + * implied, is made by the USGS as to the accuracy and functioning of such + * software and related material nor shall the fact of distribution + * constitute any such warranty, and no responsibility is assumed by the + * USGS in connection therewith. + * + * For additional information, launch + * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html + * in a browser or see the Privacy & Disclaimers page on the Isis website, + * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on + * http://www.usgs.gov/privacy.html. + */ +#ifndef ImageHistogram_h +#define ImageHistogram_h + +#include "Cube.h" +#include "Message.h" +#include "IException.h" +#include "Progress.h" +#include "Histogram.h" +#include "ImageHistogram.h" + +namespace Isis { + class ControlNet; + class ControlMeasure; + /** + * @brief Container of a cube histogram + * + * This class is used to accumulate an image histogram on double arrays. In + * particular, it is highly useful for obtaining a histogram on cube data. + * Parameters which can be computed are the 1) median, 2) mode, and 3) skew. + * The histogram consists of a fixed set of distinct bins. When an object is + * created the programmer must provide a minimum and maximum which defines how + * data is further placed in the bins. The minimum is mapped to the middle + * of the first bin [0] and the maximum is mapped to the middle of the + * last bin [Bins()-1]. There are a set of methods which return bin information + * such as 1) count, 2) size, 3) middle value, 4) range, and 5) maximum bin + * count. + * + * @ingroup Statistics + * + * @author 2020-09-22 Adam Paquette + * + * @internal + */ + + class ImageHistogram : public Histogram { + public: + ImageHistogram(double minimum, double maximum, + int bins = 1024); + ImageHistogram(Cube &cube, int statsBand, Progress *progress = NULL, + double startSample = 1.0, double startLine = 1.0, + double endSample = Null, double endLine = Null, int bins = 0, + bool addCubeData = false); + + ~ImageHistogram(); + + virtual void AddData(const double *data, const unsigned int count); + virtual void AddData(const double data); + virtual void RemoveData(const double *data, const unsigned int count); + + virtual void BinRange(const int index, double &low, double &high) const; + + private: + void InitializeFromCube(Cube &cube, int statsBand, + Progress *progress, int nbins, double startSample, double startLine, + double endSample, double endLine); + }; +}; + +#endif diff --git a/isis/src/base/objs/ImageHistogram/ImageHistogram.truth b/isis/src/base/objs/ImageHistogram/ImageHistogram.truth new file mode 100644 index 0000000000..92ea9f7c9d --- /dev/null +++ b/isis/src/base/objs/ImageHistogram/ImageHistogram.truth @@ -0,0 +1,360 @@ + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Constructor3: +Histogram(icube,1) Real + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (-1e+20,1e+20) +Bin Range: (-1e+20,1e+20) +Average: 0 +Std Deviation: 3.10109e+19 +Variance: 9.61674e+38 +Median: 1.5259e+15 +Mode: 1.5259e+15 +Skew: -0.000147616 +Percent(0.5): -1e+20 +Percent(99.5): 1e+20 +Minimum: -1e+20 +Maximum: 1e+20 +# Bins: 65536 +BinWidth: 3.0518e+15 +MaxBinCount: 5292 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 15876 +Valid pixels: 7056 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 1764 +Lis pixels: 1764 +His pixels: 1764 +Lrs pixels: 1764 +Hrs pixels: 1764 +Out of range pixels: 0 +Minimum: -1e+20 +Maximum: 1e+20 +Valid Minimum: -1e+20 +Valid Maximum: 1e+20 +Sum: 0 +Sum Square: 6.78461e+42 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Resetting bin range to (70,110) + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (70,110) +Bin Range: (70,110) +Average: -1.79769e+308 +Std Deviation: -1.79769e+308 +Variance: -1.79769e+308 +Median: -1.79769e+308 +Mode: -1.79769e+308 +Skew: -1.79769e+308 +Percent(0.5): -1.79769e+308 +Percent(99.5): -1.79769e+308 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +# Bins: 65536 +BinWidth: 0.000610361 +MaxBinCount: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 0 +Valid pixels: 0 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 0 +Lis pixels: 0 +His pixels: 0 +Lrs pixels: 0 +Hrs pixels: 0 +Out of range pixels: 0 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +Valid Minimum: 70 +Valid Maximum: 110 +Sum: 0 +Sum Square: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Constructor3: +Histogram(icube,1) SignedWord + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (-1.00049e+20,1e+20) +Bin Range: (-1.00049e+20,1e+20) +Average: -1.14471e+15 +Std Deviation: 3.10107e+19 +Variance: 9.61663e+38 +Median: -1.52627e+15 +Mode: -1.52627e+15 +Skew: 3.69133e-05 +Percent(0.5): -1e+20 +Percent(99.5): 1e+20 +Minimum: -1e+20 +Maximum: 1e+20 +# Bins: 65536 +BinWidth: 3.05255e+15 +MaxBinCount: 5292 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 15876 +Valid pixels: 7056 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 1764 +Lis pixels: 1764 +His pixels: 1764 +Lrs pixels: 1764 +Hrs pixels: 1764 +Out of range pixels: 0 +Minimum: -1e+20 +Maximum: 1e+20 +Valid Minimum: -1.00049e+20 +Valid Maximum: 1e+20 +Sum: -8.07705e+18 +Sum Square: 6.78453e+42 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Resetting bin range to (70,110) + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (70,110) +Bin Range: (70,110) +Average: -1.79769e+308 +Std Deviation: -1.79769e+308 +Variance: -1.79769e+308 +Median: -1.79769e+308 +Mode: -1.79769e+308 +Skew: -1.79769e+308 +Percent(0.5): -1.79769e+308 +Percent(99.5): -1.79769e+308 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +# Bins: 65536 +BinWidth: 0.000610361 +MaxBinCount: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 0 +Valid pixels: 0 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 0 +Lis pixels: 0 +His pixels: 0 +Lrs pixels: 0 +Hrs pixels: 0 +Out of range pixels: 0 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +Valid Minimum: 70 +Valid Maximum: 110 +Sum: 0 +Sum Square: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Constructor3: +Histogram(icube,1) UnsignedWord + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (-1.00009e+20,1.0004e+20) +Bin Range: (-1.00009e+20,1.0004e+20) +Average: 3.33468e+19 +Std Deviation: 5.35272e+19 +Variance: 2.86516e+39 +Median: 1.52627e+15 +Mode: 1.52627e+15 +Skew: 1.86888 +Percent(0.5): -1e+20 +Percent(99.5): 1.0004e+20 +Minimum: -1e+20 +Maximum: 1.0004e+20 +# Bins: 65536 +BinWidth: 3.05255e+15 +MaxBinCount: 5292 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 15876 +Valid pixels: 10584 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 1764 +Lis pixels: 1764 +His pixels: 0 +Lrs pixels: 1764 +Hrs pixels: 0 +Out of range pixels: 0 +Minimum: -1e+20 +Maximum: 1.0004e+20 +Valid Minimum: -1.00009e+20 +Valid Maximum: 1.0004e+20 +Sum: 3.52943e+23 +Sum Square: 4.20915e+43 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Resetting bin range to (70,110) + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (70,110) +Bin Range: (70,110) +Average: -1.79769e+308 +Std Deviation: -1.79769e+308 +Variance: -1.79769e+308 +Median: -1.79769e+308 +Mode: -1.79769e+308 +Skew: -1.79769e+308 +Percent(0.5): -1.79769e+308 +Percent(99.5): -1.79769e+308 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +# Bins: 65536 +BinWidth: 0.000610361 +MaxBinCount: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 0 +Valid pixels: 0 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 0 +Lis pixels: 0 +His pixels: 0 +Lrs pixels: 0 +Hrs pixels: 0 +Out of range pixels: 0 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +Valid Minimum: 70 +Valid Maximum: 110 +Sum: 0 +Sum Square: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Constructor3: +Histogram(icube,1) UnsignedByte + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (-1.00791e+20,1.00791e+20) +Bin Range: (-1.00791e+20,1.00791e+20) +Average: 2.96443e+17 +Std Deviation: 3.10605e+19 +Variance: 9.64757e+38 +Median: 3.95257e+17 +Mode: 3.95257e+17 +Skew: -0.00954403 +Percent(0.5): -1e+20 +Percent(99.5): 1e+20 +Minimum: -1e+20 +Maximum: 1e+20 +# Bins: 256 +BinWidth: 7.90514e+17 +MaxBinCount: 5292 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 15876 +Valid pixels: 7056 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 5292 +Lis pixels: 0 +His pixels: 0 +Lrs pixels: 0 +Hrs pixels: 3528 +Out of range pixels: 0 +Minimum: -1e+20 +Maximum: 1e+20 +Valid Minimum: -1.00791e+20 +Valid Maximum: 1.00791e+20 +Sum: 2.0917e+21 +Sum Square: 6.80698e+42 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Resetting bin range to (70,110) + ++++++++++++++++++++ Histogram Members +++++++++++++++++++ + +Stats Range: (70,110) +Bin Range: (70,110) +Average: -1.79769e+308 +Std Deviation: -1.79769e+308 +Variance: -1.79769e+308 +Median: -1.79769e+308 +Mode: -1.79769e+308 +Skew: -1.79769e+308 +Percent(0.5): -1.79769e+308 +Percent(99.5): -1.79769e+308 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +# Bins: 256 +BinWidth: 0.156863 +MaxBinCount: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++ Statistics Counters ++++++++++++++++++ + +Total pixels: 0 +Valid pixels: 0 +Over Range pixels: 0 +Under Range pixels: 0 +Null pixels: 0 +Lis pixels: 0 +His pixels: 0 +Lrs pixels: 0 +Hrs pixels: 0 +Out of range pixels: 0 +Minimum: -1.79769e+308 +Maximum: -1.79769e+308 +Valid Minimum: 70 +Valid Maximum: 110 +Sum: 0 +Sum Square: 0 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + diff --git a/isis/src/base/objs/ImageHistogram/Makefile b/isis/src/base/objs/ImageHistogram/Makefile new file mode 100644 index 0000000000..f122bc8822 --- /dev/null +++ b/isis/src/base/objs/ImageHistogram/Makefile @@ -0,0 +1,7 @@ +ifeq ($(ISISROOT), $(BLANK)) +.SILENT: +error: + echo "Please set ISISROOT"; +else + include $(ISISROOT)/make/isismake.objs +endif \ No newline at end of file diff --git a/isis/src/base/objs/ImageHistogram/unitTest.cpp b/isis/src/base/objs/ImageHistogram/unitTest.cpp new file mode 100644 index 0000000000..40b362e11f --- /dev/null +++ b/isis/src/base/objs/ImageHistogram/unitTest.cpp @@ -0,0 +1,284 @@ +#include +#include +#include "QRegularExpression" +#include "ImageHistogram.h" +#include "IException.h" +#include "Preference.h" +#include "LineManager.h" +#include "ControlNet.h" +#include "ControlMeasure.h" +#include "Progress.h" +#include "IException.h" +#include "FileName.h" +using namespace std; +#include +#include +#include +#include + +void arrayDisplay(double *array, int size ); +void histogramMembers(Isis::ImageHistogram *h); +void statCounters(Isis::ImageHistogram *h); +void histDisplay(Isis::ImageHistogram *h); + +int main(int argc, char *argv[]) { + try { + + Isis::FileName cubeFile("$ISISTESTDATA/isis/src/base/unitTestData/isisTruth.cub"); + Isis::Cube icube; + icube.open(cubeFile.expanded()); + Isis::ImageHistogram *histcube; + histcube = new Isis::ImageHistogram(icube, 1); + + cout << endl; + + cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); + } + + histogramMembers(histcube); + statCounters(histcube); + cout << "Resetting bin range to (70,110)" << endl; + histcube ->SetValidRange(70,110); + histogramMembers(histcube); + statCounters(histcube); + delete(histcube); + cout << endl; + + } + catch (Isis::IException &e) { + + e.print(); + + } + + + try { + + Isis::FileName cubeFile("$ISISTESTDATA/isis/src/base/unitTestData/isisTruth_Signed16Bit.cub"); + Isis::Cube icube; + icube.open(cubeFile.expanded()); + Isis::ImageHistogram *histcube; + histcube = new Isis::ImageHistogram(icube, 1); + + cout << endl; + + cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); + } + + histogramMembers(histcube); + statCounters(histcube); + cout << "Resetting bin range to (70,110)" << endl; + histcube ->SetValidRange(70,110); + histogramMembers(histcube); + statCounters(histcube); + delete(histcube); + cout << endl; + + } + catch (Isis::IException &e) { + + e.print(); + + } + + + try { + + Isis::FileName cubeFile("$ISISTESTDATA/isis/src/base/unitTestData/isisTruth_Unsigned16Bit.cub"); + Isis::Cube icube; + icube.open(cubeFile.expanded()); + Isis::ImageHistogram *histcube; + histcube = new Isis::ImageHistogram(icube, 1); + + cout << endl; + + cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); + } + + histogramMembers(histcube); + statCounters(histcube); + cout << "Resetting bin range to (70,110)" << endl; + histcube ->SetValidRange(70,110); + histogramMembers(histcube); + statCounters(histcube); + delete(histcube); + cout << endl; + + } + catch (Isis::IException &e) { + + e.print(); + + } + + + try { + + Isis::FileName cubeFile("$ISISTESTDATA/isis/src/base/unitTestData/isisTruth_8Bit.cub"); + Isis::Cube icube; + icube.open(cubeFile.expanded()); + Isis::ImageHistogram *histcube; + histcube = new Isis::ImageHistogram(icube, 1); + + cout << endl; + + cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" <AddData(lm.DoubleBuffer(),lm.size()); + } + + histogramMembers(histcube); + statCounters(histcube); + cout << "Resetting bin range to (70,110)" << endl; + histcube ->SetValidRange(70,110); + histogramMembers(histcube); + statCounters(histcube); + delete(histcube); + cout << endl; + + } + catch (Isis::IException &e) { + + e.print(); + + } +} + +//Simple function for outputting a sorted vector + +void arrayDisplay(double *array, int size ){ + + vector v(size); + + for (int i=0; i < size; i++ ) + v[i]= array[i]; + + sort (v.begin(),v.end() ); + + cout << "[ " ; + for (std::vector::iterator it = v.begin(); it != v.end(); it++) + cout << *it << " "; + + cout << "]" << endl; + + } + +void histDisplay(Isis::ImageHistogram *h){ + + double low, high; + + for (int i = 0; i < h->Bins(); i++){ + + h->BinRange(i,low,high); + cout <<"Bin " << i << ": [" << low << "," << high << "], Count = " << h->BinCount(i) + << endl; + } + +} + + +void histogramMembers(Isis::ImageHistogram *h){ + + try{ + cout << endl; + cout << "+++++++++++++++++++ Histogram Members +++++++++++++++++++" << endl; + cout << endl; + cout << "Stats Range: (" << h->ValidMinimum() << "," << h->ValidMaximum() << ")" + << endl; + cout << "Bin Range: (" << h->BinRangeStart() <<","<< h->BinRangeEnd()<<")" + << endl; + cout << "Average: "; cout << h-> Average() << endl; + cout << "Std Deviation: "; cout << h->StandardDeviation() << endl; + cout << "Variance: "; cout << h->Variance() <Median() << endl; + cout << "Mode: "; cout << h->Mode() << endl; + cout << "Skew: "; cout << h->Skew() << endl; + cout << "Percent(0.5): "; cout << h->Percent(0.5) << endl; + cout << "Percent(99.5): "; cout << h->Percent(99.5) << endl; + cout << "Minimum: "; cout << h-> Minimum() << endl; + cout << "Maximum: "; cout << h-> Maximum() << endl; + cout << "# Bins: "; cout << h->Bins() << endl; + cout << "BinWidth: "; cout << h->BinSize() << endl; + cout << "MaxBinCount: "; cout << h->MaxBinCount() << endl; + cout << endl; + cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + } + catch(Isis::IException &e){ + + e.print(); + } + + + +} + + +void statCounters(Isis::ImageHistogram *h){ + + cout << endl; + cout << "++++++++++++++++++ Statistics Counters ++++++++++++++++++" << endl; + cout << endl; + cout << "Total pixels: " << h->TotalPixels() << endl; + cout << "Valid pixels: " << h->ValidPixels() << endl; + cout << "Over Range pixels: " << h->OverRangePixels() << endl; + cout << "Under Range pixels: " << h->UnderRangePixels() << endl; + cout << "Null pixels: " << h->NullPixels() << endl; + cout << "Lis pixels: " << h->LisPixels() << endl; + cout << "His pixels: " << h->HisPixels() << endl; + cout << "Lrs pixels: " << h->LrsPixels() << endl; + cout << "Hrs pixels: " << h->HrsPixels() << endl; + cout << "Out of range pixels: " << h->OutOfRangePixels() << endl; + cout << "Minimum: " << h->Minimum() << endl; + cout << "Maximum: " << h->Maximum() << endl; + cout << "Valid Minimum: " << h->ValidMinimum() << endl; + cout << "Valid Maximum: " << h->ValidMaximum() << endl; + cout << "Sum: " << h->Sum() << endl; + cout << "Sum Square: " << h->SumSquare() << endl; + cout << endl; + cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + + + +} diff --git a/isis/src/base/objs/Stretch/Stretch.cpp b/isis/src/base/objs/Stretch/Stretch.cpp index a16f37379b..f453a2d555 100644 --- a/isis/src/base/objs/Stretch/Stretch.cpp +++ b/isis/src/base/objs/Stretch/Stretch.cpp @@ -53,9 +53,9 @@ namespace Isis { /** * Constructs a Stretch object with default mapping of special pixel values to - * themselves and a provided name. - * - * @param name Name to use for Stretch + * themselves and a provided name. + * + * @param name Name to use for Stretch */ Stretch::Stretch(QString name) : Blob(name, "Stretch") { p_null = Isis::NULL8; @@ -433,11 +433,11 @@ namespace Isis { /** - * Read saved Stretch data from a Cube into this object. - * - * This is called by Blob::Read() and is the actual data reading function - * ultimately called when running something like cube->read(stretch); - * + * Read saved Stretch data from a Cube into this object. + * + * This is called by Blob::Read() and is the actual data reading function + * ultimately called when running something like cube->read(stretch); + * * @param is input stream containing the saved Stretch information */ void Stretch::ReadData(std::istream &is) { @@ -475,8 +475,8 @@ namespace Isis { /** * Get the Type of Stretch. This is only used by the AdvancedStretchTool. - * - * @return QString Type of Stretch. + * + * @return QString Type of Stretch. */ QString Stretch::getType(){ return p_type; @@ -485,8 +485,8 @@ namespace Isis { /** * Set the Type of Stretch. This is only used by the AdvancedStretchTool. - * - * @param stretchType The type of stretch. + * + * @param stretchType The type of stretch. */ void Stretch::setType(QString stretchType){ // check to see if valid input @@ -498,16 +498,16 @@ namespace Isis { * Initializes for writing stretch to cube blob */ void Stretch::WriteInit() { - p_nbytes = Text().toStdString().size(); + p_nbytes = Text().toStdString().size(); } /** - * Writes the stretch information to a cube. - * - * This is called by Blob::write() and is ultimately the function - * called when running something like cube->write(stretch); - * + * Writes the stretch information to a cube. + * + * This is called by Blob::write() and is ultimately the function + * called when running something like cube->write(stretch); + * * @param os output stream to write the stretch data to. */ void Stretch::WriteData(std::fstream &os) { @@ -515,5 +515,3 @@ namespace Isis { } } // end namespace isis - - diff --git a/isis/src/base/objs/Stretch/Stretch.h b/isis/src/base/objs/Stretch/Stretch.h index 5da48bbe74..8ba116c791 100644 --- a/isis/src/base/objs/Stretch/Stretch.h +++ b/isis/src/base/objs/Stretch/Stretch.h @@ -25,6 +25,7 @@ #include #include #include "Pvl.h" +#include "ImageHistogram.h" #include "Histogram.h" #include "Blob.h" @@ -69,7 +70,7 @@ namespace Isis { * input side is a perentage. Fixed Input and Output getters * to check both sides of boundry condition for valid data * @history 2020-02-27 Kristin Berry - Updated to inherit from Blob so Stretches can be - * saved and restored from cubes. + * saved and restored from cubes. */ class Stretch : public Isis::Blob { private: @@ -182,8 +183,8 @@ namespace Isis { return p_pairs; }; - QString getType(); - void setType(QString type); + QString getType(); + void setType(QString type); double Input(const int index) const; double Output(const int index) const; @@ -205,4 +206,3 @@ namespace Isis { }; #endif - diff --git a/isis/src/base/objs/Stretch/unitTest.cpp b/isis/src/base/objs/Stretch/unitTest.cpp index 05fba2d851..592c2494b0 100644 --- a/isis/src/base/objs/Stretch/unitTest.cpp +++ b/isis/src/base/objs/Stretch/unitTest.cpp @@ -6,7 +6,7 @@ #include "Stretch.h" #include "IException.h" #include "Preference.h" -#include "Histogram.h" +#include "ImageHistogram.h" using namespace Isis; using namespace std; @@ -91,8 +91,8 @@ int main() { // test the Parse for when inputs are %'s cout << endl << "Testing new Parse that takes %'s for input side of pairs" << endl; - Histogram temp(0.0, 100.0, 101); - Histogram *h = &temp; + ImageHistogram temp(0.0, 100.0, 101); + ImageHistogram *h = &temp; for(double i = 0.0; i <= 100.0; i++) { h->AddData(&i, 1); } diff --git a/isis/src/control/apps/cnethist/cnethist.xml b/isis/src/control/apps/cnethist/cnethist.xml index a57d7b2e08..860d03cf73 100644 --- a/isis/src/control/apps/cnethist/cnethist.xml +++ b/isis/src/control/apps/cnethist/cnethist.xml @@ -17,6 +17,11 @@ Original version + + Removed "ResidualMagnitude" from the CSV output and added "ResidualMagnitudeMin" and "ResidualMagnitudeMax". This way, the bins are represented by the min/max values of the + bins instead of the DN of the pixel in the middle of the bin. These changes were also + reflected in the histrogram creation. The x-axis is now based off of the min value of a bin instead of the middle value. These changes were made alongside changes made to Histogram and hist. + diff --git a/isis/src/control/apps/cnethist/main.cpp b/isis/src/control/apps/cnethist/main.cpp index 22bd9af0de..d744562816 100644 --- a/isis/src/control/apps/cnethist/main.cpp +++ b/isis/src/control/apps/cnethist/main.cpp @@ -9,6 +9,7 @@ #include "FileList.h" #include "Process.h" #include "Histogram.h" +#include "ImageHistogram.h" #include "UserInterface.h" #include "Progress.h" #include "LineManager.h" @@ -39,7 +40,7 @@ void IsisMain() { HistogramPlotWindow *plot=NULL; //setup plot tile and axis labels (if any) - if(ui.IsInteractive()) { + if(ui.IsInteractive()) { // Set the title for the dialog QString title; if(ui.WasEntered("TITLE")) { @@ -70,24 +71,24 @@ void IsisMain() { } QString yaxis = ""; - plot->setAxisLabel(QwtPlot::yRight, yaxis); + plot->setAxisLabel(QwtPlot::yRight, yaxis); } //open text report file (if any) - ofstream fout; - if(!ui.IsInteractive() || ui.WasEntered("TO")) { + ofstream fout; + if(!ui.IsInteractive() || ui.WasEntered("TO")) { // Write the results if(!ui.WasEntered("TO")) { QString msg = "The [TO] parameter must be entered"; throw IException(IException::User, msg, _FILEINFO_); } - QString outfile = ui.GetFileName("TO"); + QString outfile = ui.GetFileName("TO"); fout.open(outfile.toLatin1().data()); } //loop throught the control nets writing reports and drawing histograms as needed - for (int i=0;iAverage() << endl; @@ -121,21 +122,26 @@ void IsisMain() { fout << "Minimum: " << hist->Minimum() << endl; fout << "Maximum: " << hist->Maximum() << endl; fout << "Total Measures: " << hist->TotalPixels() << endl; - + // Write histogram in tabular format fout << endl; - fout << "ResidualMagnitude,MeasuresInBin,CumulativeMeasures,Percent,CumulativePercent" << endl; + fout << "ResidualMagnitudeMin,ResidualMagnitudeMax,MeasuresInBin,CumulativeMeasures,Percent,CumulativePercent" << endl; Isis::BigInt total = 0; double cumpct = 0.0; + double low; + double high; for(int j = 0; j < hist->Bins(); j++) { if(hist->BinCount(j) > 0) { total += hist->BinCount(j); double pct = (double)hist->BinCount(j) / hist->ValidPixels() * 100.; cumpct += pct; - - fout << hist->BinMiddle(j) << ","; + + hist->BinRange(j, low, high); + + fout << low << ","; + fout << high << ","; fout << hist->BinCount(j) << ","; fout << total << ","; fout << pct << ","; @@ -152,9 +158,12 @@ void IsisMain() { if(ui.IsInteractive()) { //Transfer data from histogram to the plotcurve QVector binCountData; + double low; + double high; for(int j = 0; j < hist->Bins(); j++) { if(hist->BinCount(j) > 0) { - binCountData.append(QPointF(hist->BinMiddle(j), hist->BinCount(j))); + hist->BinRange(j, low, high); + binCountData.append(QPointF(low, hist->BinCount(j))); } } @@ -164,13 +173,13 @@ void IsisMain() { QString baseName = FileName(fList[i]).baseName(); histCurve->setTitle(baseName); - + QPen *pen = new QPen(curveColor(i)); pen->setWidth(2); histCurve->setYAxis(QwtPlot::yLeft); - histCurve->setPen(*pen); + histCurve->setPen(*pen); histCurve->setMarkerSymbol(QwtSymbol::NoSymbol); - + histCurve->setData(new QwtPointSeriesData(binCountData)); plot->add(histCurve); diff --git a/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp b/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp index cec80c1f6c..4ec30a67c4 100644 --- a/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp +++ b/isis/src/control/apps/cnetwinnow/cnetwinnow.cpp @@ -17,7 +17,7 @@ #include "ControlMeasure.h" #include "ControlPoint.h" #include "PvlGroup.h" -#include "Histogram.h" +#include "ImageHistogram.h" #include "IException.h" #include "IString.h" #include "Progress.h" diff --git a/isis/src/control/apps/findfeatures/ImageSource.cpp b/isis/src/control/apps/findfeatures/ImageSource.cpp index 3c0d8e792a..a6a09dafbf 100644 --- a/isis/src/control/apps/findfeatures/ImageSource.cpp +++ b/isis/src/control/apps/findfeatures/ImageSource.cpp @@ -42,6 +42,7 @@ #include "FileName.h" #include "GenericTransform.h" #include "Histogram.h" +#include "ImageHistogram.h" #include "IException.h" #include "ImageSource.h" #include "IString.h" @@ -380,7 +381,7 @@ cv::Mat ImageSource::getGeometryMapping(ImageSource &match, } Histogram *ImageSource::getHistogram(Cube &cube) const { - QScopedPointer hist(new Histogram(cube, 1)); + QScopedPointer hist(new ImageHistogram(cube, 1)); LineManager line(cube); for(int i = 1; i <= cube.lineCount(); i++) { diff --git a/isis/src/lro/apps/lromakeflat/main.cpp b/isis/src/lro/apps/lromakeflat/main.cpp index edea5a44b5..16d622b076 100644 --- a/isis/src/lro/apps/lromakeflat/main.cpp +++ b/isis/src/lro/apps/lromakeflat/main.cpp @@ -48,6 +48,7 @@ #include "FileList.h" #include "Histogram.h" +#include "ImageHistogram.h" #include "IException.h" #include "LineManager.h" #include "PvlGroup.h" @@ -347,7 +348,7 @@ void getCubeListNormalization(Matrix2d &matrix, int cubeWidth, int frameHeight, string err = "This percentage will yield less than 1 line. This is not enough to normalize. \n"; throw IException(IException::User, err, _FILEINFO_); } - Histogram hist = Histogram(tmp, 1, &g_prog, startSample, startLine, endSample, endLine, 0, true); + Histogram hist = ImageHistogram(tmp, 1, &g_prog, startSample, startLine, endSample, endLine, 0, true); int frame = cubeLine/frameLineCount; double normalizationAverage = hist.Average(); matrix[listIndex][frame] = normalizationAverage; diff --git a/isis/src/mro/apps/hideal2pds/main.cpp b/isis/src/mro/apps/hideal2pds/main.cpp index 203f45603b..2f25e47a42 100644 --- a/isis/src/mro/apps/hideal2pds/main.cpp +++ b/isis/src/mro/apps/hideal2pds/main.cpp @@ -12,7 +12,7 @@ #include "IString.h" #include "iTime.h" #include "FileName.h" -#include "Histogram.h" +#include "ImageHistogram.h" #include "LineManager.h" #include "Longitude.h" #include "OriginalLabel.h" @@ -37,7 +37,7 @@ void updatePdsLabelRootObject(PvlObject *isisCubeLab, Pvl &pdsLabel, UserInterface &ui, Camera *cam); void IsisMain() { // Get user interface and create a ProcessExportPds object - UserInterface &ui = Application::GetUserInterface(); + UserInterface &ui = Application::GetUserInterface(); ProcessExportPds p; Process pHist; double *band_min, *band_max; @@ -51,25 +51,25 @@ void IsisMain() { .findGroup("OriginalInstrument")["InstrumentId"][0]; if (origInstrument != "HIRISE") { QString msg = "Input cube must from a HiRISE image. The original " - "InstrumentId = [" + origInstrument + "InstrumentId = [" + origInstrument + "] is unsupported by hideal2pds."; throw IException(IException::Io, msg, _FILEINFO_); } QString instrumentId = isisCubeLab->findObject("IsisCube") .findGroup("Instrument")["InstrumentId"][0]; if (instrumentId != "IdealCamera") { - QString msg = "Input cube must be IdealCamera. InstrumentId = [" + QString msg = "Input cube must be IdealCamera. InstrumentId = [" + instrumentId + "] is unsupported by hideal2pds."; throw IException(IException::Io, msg, _FILEINFO_); } QString target = isisCubeLab->findObject("IsisCube") .findGroup("Instrument")["TargetName"][0]; if (target.toUpper() != "MARS") { - QString msg = "Input cube must from a HiRise image. The target = [" + QString msg = "Input cube must from a HiRise image. The target = [" + target + "] is unsupported by hideal2pds."; throw IException(IException::Io, msg, _FILEINFO_); } - + band_min = new double[inputCube->bandCount()]; band_max = new double[inputCube->bandCount()]; @@ -78,7 +78,7 @@ void IsisMain() { if (ui.GetString("TYPE").compare("AUTOMATIC") == 0) { // Set up a histogram for this band. This call sets the input range // by making an initial stats pass to find the data min and max - Histogram hist(*inputCube, band, pHist.Progress()); + ImageHistogram hist(*inputCube, band, pHist.Progress()); // Loop and accumulate histogram pHist.Progress()->SetText("Gathering Histogram"); @@ -137,7 +137,7 @@ void IsisMain() { p.SetOutputLrs(LOW_REPR_SATU2); p.SetOutputHis(HIGH_INSTR_SATU2); p.SetOutputHrs(HIGH_REPR_SATU2); - break; + break; default: p.SetOutputType(UnsignedWord); @@ -167,7 +167,7 @@ void IsisMain() { QString isisLabelFile = ui.GetFileName("FROM"); // Translate the keywords from the input cube label that go in the PDS label - PvlToPvlTranslationManager cubeLab(*(inputCube->label()), + PvlToPvlTranslationManager cubeLab(*(inputCube->label()), "$ISISROOT/appdata/translations/MroHiriseIdealPdsExportCubeLabel.trn"); cubeLab.Auto(pdsLabel); @@ -178,7 +178,7 @@ void IsisMain() { PvlObject origLabelObj = origBlob.ReturnLabels(); origLabelObj.setName("OriginalLabelObject"); origLabel.addObject(origLabelObj); - PvlToPvlTranslationManager orig(origLabel, + PvlToPvlTranslationManager orig(origLabel, "$ISISROOT/appdata/translations/MroHirisePdsRdrOriginalLabel.trn"); orig.Auto(pdsLabel); @@ -194,14 +194,14 @@ void IsisMain() { updatePdsLabelRootObject(isisCubeLab, pdsLabel, ui, cam); // Export each of the spice tables and update table keywords in PDS file - // + // // *** NOTE *** // This could change the start byte/line values for the tables that have // already been set in the labels by the ExportTable call. This is not // a problem since our tables are detached. However, it could be a // problem if we decide to allow attached PDS products in the future. QString pdsTableFile = ""; - pdsTableFile = outPdsFile.baseName() + "_INSTRUMENT_POINTING_TABLE.dat"; + pdsTableFile = outPdsFile.baseName() + "_INSTRUMENT_POINTING_TABLE.dat"; Table instRotationTable = cam->instrumentRotation()->Cache("InstrumentPointing"); p.ExportTable(instRotationTable, pdsTableFile); PvlObject isisTableLab = instRotationTable.Label(); @@ -225,9 +225,9 @@ void IsisMain() { tableKeyword.setName("CK_TABLE_ORIGINAL_SIZE"); instPtTabLab += tableKeyword; - pdsTableFile = outPdsFile.baseName() + "_INSTRUMENT_POSITION_TABLE.dat"; + pdsTableFile = outPdsFile.baseName() + "_INSTRUMENT_POSITION_TABLE.dat"; Table instPositionTable = cam->instrumentPosition()->Cache("InstrumentPosition"); - p.ExportTable(instPositionTable, pdsTableFile); + p.ExportTable(instPositionTable, pdsTableFile); isisTableLab = instPositionTable.Label(); PvlObject &instPosTabLab = pdsLabel.findObject("INSTRUMENT_POSITION_TABLE"); tableKeyword = isisTableLab.findKeyword("CacheType"); @@ -243,9 +243,9 @@ void IsisMain() { tableKeyword.setName("SPK_TABLE_ORIGINAL_SIZE"); instPosTabLab += tableKeyword; - pdsTableFile = outPdsFile.baseName() + "_BODY_ROTATION_TABLE.dat"; + pdsTableFile = outPdsFile.baseName() + "_BODY_ROTATION_TABLE.dat"; Table bodyRotationTable = cam->bodyRotation()->Cache("BodyRotation"); - p.ExportTable(bodyRotationTable, pdsTableFile); + p.ExportTable(bodyRotationTable, pdsTableFile); isisTableLab = bodyRotationTable.Label(); PvlObject &bodyRotTabLab = pdsLabel.findObject("BODY_ROTATION_TABLE"); tableKeyword = isisTableLab.findKeyword("TimeDependentFrames"); @@ -265,16 +265,16 @@ void IsisMain() { tableKeyword.setName("SOLAR_LONGITUDE"); } else { - tableKeyword = PvlKeyword("SOLAR_LONGITUDE", + tableKeyword = PvlKeyword("SOLAR_LONGITUDE", toString(cam->solarLongitude().force360Domain() - .positiveEast(Angle::Degrees)), + .positiveEast(Angle::Degrees)), "DEGREES"); } bodyRotTabLab += tableKeyword; - pdsTableFile = outPdsFile.baseName() + "_SUN_POSITION_TABLE.dat"; + pdsTableFile = outPdsFile.baseName() + "_SUN_POSITION_TABLE.dat"; Table sunPositionTable = cam->sunPosition()->Cache("SunPosition"); - p.ExportTable(sunPositionTable, pdsTableFile); + p.ExportTable(sunPositionTable, pdsTableFile); isisTableLab = sunPositionTable.Label(); PvlObject &sunPosTabLab = pdsLabel.findObject("SUN_POSITION_TABLE"); tableKeyword = isisTableLab.findKeyword("CacheType"); @@ -290,7 +290,7 @@ void IsisMain() { tableKeyword.setName("SPK_TABLE_ORIGINAL_SIZE"); sunPosTabLab += tableKeyword; - // Read in the proper keyword types (Real, Enum, String, Integer, etc) for + // Read in the proper keyword types (Real, Enum, String, Integer, etc) for // each PvlKeyword so that the PDS labels have proper format PvlFormat *formatter = pdsLabel.format(); @@ -312,25 +312,25 @@ void IsisMain() { p.StartProcess(outputStream); p.EndProcess(); outputStream.close(); - + delete [] band_min; delete [] band_max; } /** - * This method uses a Histogram object to find the minimum and maximum DN - * values of the input cube. These values are used by the Process object - * to set the input range. - * - * @param inputCube Pointer to the inputCube - * + * This method uses a Histogram object to find the minimum and maximum DN + * values of the input cube. These values are used by the Process object + * to set the input range. + * + * @param inputCube Pointer to the inputCube + * * @return A pair whose first value is the minimum DN of the input cube and * second value is the maximum DN of the input cube. */ pair inputRange(Cube *inputCube) { Process histProcess; int band = 1; - Histogram hist(*inputCube, band, histProcess.Progress()); + ImageHistogram hist(*inputCube, band, histProcess.Progress()); // Loop and accumulate histogram histProcess.Progress()->SetText("Gathering Histogram to Find Input Range"); @@ -351,24 +351,24 @@ pair inputRange(Cube *inputCube) { } /** - * This method updates the values of the keywords in the IMAGE object of - * the pds label file. - * - * The DESCRIPTION keyword is added. - * - * If the input cube has an AlphaCube group that indicates a crop has - * been performed, SOURCE_LINE_SAMPLES, SOURCE_LINES, FIRST_LINE_SAMPLE, - * and FIRST_LINE keywords are added. - * - * The values for CENTER_FILTER_WAVELENGTH and BAND_WIDTH are updated. - * - * @param inputCubeLab PvlObject pointer to the input cube labels - * @param pdsLabel Pvl of the output PDS labels + * This method updates the values of the keywords in the IMAGE object of + * the pds label file. + * + * The DESCRIPTION keyword is added. + * + * If the input cube has an AlphaCube group that indicates a crop has + * been performed, SOURCE_LINE_SAMPLES, SOURCE_LINES, FIRST_LINE_SAMPLE, + * and FIRST_LINE keywords are added. + * + * The values for CENTER_FILTER_WAVELENGTH and BAND_WIDTH are updated. + * + * @param inputCubeLab PvlObject pointer to the input cube labels + * @param pdsLabel Pvl of the output PDS labels */ void updatePdsLabelImageObject(PvlObject *isisCubeLab, Pvl &pdsLabel) { // Add the image description to the IMAGE object in the label of the PDS product PvlObject &image = pdsLabel.findObject("IMAGE"); - image += PvlKeyword("DESCRIPTION", + image += PvlKeyword("DESCRIPTION", "HiRISE mosaicked product, not map projected"); // Add AlphaCube values to the IMAGE object @@ -446,31 +446,31 @@ void updatePdsLabelImageObject(PvlObject *isisCubeLab, Pvl &pdsLabel) { /** - * This method updates the values of the keywords in the ROOT object of - * the pds label file. - * - * The RATIONALE_DESC keyword is updated if the user entered this - * parameter. - * - * The PRODUCT_VERSION_ID is added based on the user entered parameter. - * - * The NOT_APPLICABLE_CONSTANT keyword is added. - * - * The SOFTWARE_NAME keyword is determined and added. - * - * The SHAPE_MODEL keyword from the Kernels group of the input cube is - * added with the path removed. - * - * The NaifKeywords values are added if the Object exists in the input - * cube. Otherwise, the corresponding values are calculated and added - * to the pds labels. These values are added: BODY_FRAME_CODE, - * IDEAL_FOCAL_LENGTH, IDEAL_PIXEL_PITCH, IDEAL_TRANSX, IDEAL_TRANSY, + * This method updates the values of the keywords in the ROOT object of + * the pds label file. + * + * The RATIONALE_DESC keyword is updated if the user entered this + * parameter. + * + * The PRODUCT_VERSION_ID is added based on the user entered parameter. + * + * The NOT_APPLICABLE_CONSTANT keyword is added. + * + * The SOFTWARE_NAME keyword is determined and added. + * + * The SHAPE_MODEL keyword from the Kernels group of the input cube is + * added with the path removed. + * + * The NaifKeywords values are added if the Object exists in the input + * cube. Otherwise, the corresponding values are calculated and added + * to the pds labels. These values are added: BODY_FRAME_CODE, + * IDEAL_FOCAL_LENGTH, IDEAL_PIXEL_PITCH, IDEAL_TRANSX, IDEAL_TRANSY, * IDEAL_TRANSS, and IDEAL_TRANSL. The BODY_RADII keyword is split into - * A_AXIS_RADIUS, B_AXIS_RADIUS, and C_AXIS_RADIUS - * - * @param inputCubeLab PvlObject pointer to the input cube labels - * @param pdsLabel Pvl of the output PDS labels - * @param ui UserInterface reference, so that the user entered + * A_AXIS_RADIUS, B_AXIS_RADIUS, and C_AXIS_RADIUS + * + * @param inputCubeLab PvlObject pointer to the input cube labels + * @param pdsLabel Pvl of the output PDS labels + * @param ui UserInterface reference, so that the user entered * RATIONALE_DESC and PRODUCT_VERSION_ID parameters can be * read in. * @param cam Pointer to the Camera object created from the input cube. @@ -480,13 +480,13 @@ void updatePdsLabelRootObject(PvlObject *isisCubeLab, Pvl &pdsLabel, // Replace INSTRUMENT_ID value in the output labels PvlKeyword instId("INSTRUMENT_ID", "HIRISE_IDEAL_CAMERA"); pdsLabel.addKeyword(instId, PvlContainer::Replace); - + // Add user-entered keywords to ROOT object in the label of the PDS product if(ui.WasEntered("RATIONALE_DESC")) { PvlKeyword rationale("RATIONALE_DESC", ui.GetAsString("RATIONALE_DESC")); pdsLabel.addKeyword(rationale, PvlContainer::Replace); } - else if ( !pdsLabel.hasKeyword("RATIONALE_DESC") + else if ( !pdsLabel.hasKeyword("RATIONALE_DESC") || QString(pdsLabel["RATIONALE_DESC"]) == "NULL" ){ QString msg = "Unable to export HiRise product to PDS without " "RationaleDescription value. The input cube value for this " @@ -515,11 +515,11 @@ void updatePdsLabelRootObject(PvlObject *isisCubeLab, Pvl &pdsLabel, .hasKeyword("ImageJitterCorrected")) { jitter = toInt(isisCubeLab->findObject("IsisCube") .findGroup("Instrument")["ImageJitterCorrected"][0]); - pdsLabel += PvlKeyword("IMAGE_JITTER_CORRECTED", toString((int)jitter)); + pdsLabel += PvlKeyword("IMAGE_JITTER_CORRECTED", toString((int)jitter)); } else { pdsLabel += PvlKeyword("IMAGE_JITTER_CORRECTED", "UNK"); - } + } // Add Isis Kernels group keywords to the ROOT object QString shapeModel = isisCubeLab->findObject("IsisCube").findGroup("Kernels") @@ -527,9 +527,9 @@ void updatePdsLabelRootObject(PvlObject *isisCubeLab, Pvl &pdsLabel, FileName shapeModelFileNoPath(shapeModel); pdsLabel += PvlKeyword("SHAPE_MODEL", shapeModelFileNoPath.name()); - // PRODUCT_ID and SOURCE_PRODUCT_ID should be keywords added when creating the + // PRODUCT_ID and SOURCE_PRODUCT_ID should be keywords added when creating the // mosaic input cube. - + // Add NaifKeywords Object values to the ROOT object QString radiiName = "BODY" + QString::number(cam->naifBodyCode()) + "_RADII"; PvlObject naifKeywordGroup = cam->getStoredNaifKeywords(); @@ -621,12 +621,12 @@ void updatePdsLabelRootObject(PvlObject *isisCubeLab, Pvl &pdsLabel, /** * This method updates the values of the keywords in the Time Parameters - * Group of the pds label file. - * - * The PRODUCT_CREATION_TIME keyword is determined and added to the PDS - * labels. - * - * @param pdsLabel Pvl of the output PDS labels + * Group of the pds label file. + * + * The PRODUCT_CREATION_TIME keyword is determined and added to the PDS + * labels. + * + * @param pdsLabel Pvl of the output PDS labels */ void updatePdsLabelTimeParametersGroup(Pvl &pdsLabel) { // Calculate and add PRODUCT_CREATION_TIME to the TIME_PARAMETERS group @@ -639,5 +639,3 @@ void updatePdsLabelTimeParametersGroup(Pvl &pdsLabel) { PvlGroup &timeParam = pdsLabel.findGroup("TIME_PARAMETERS"); timeParam += PvlKeyword("PRODUCT_CREATION_TIME", tmpDateTime.UTC()); } - - diff --git a/isis/src/mro/apps/hinoise/main.cpp b/isis/src/mro/apps/hinoise/main.cpp index 4816ac4639..4d84fff98c 100644 --- a/isis/src/mro/apps/hinoise/main.cpp +++ b/isis/src/mro/apps/hinoise/main.cpp @@ -682,10 +682,9 @@ void GetValuesFromHistogram(QString psHistFile, double & pdLisPer, double & pdMa iStartIndex++; for (int i=iStartIndex; i dCumPer) { - pdMaxDN = IString(csvArr[0]).ToDouble(); + pdMaxDN = (IString(csvArr[0]).ToDouble() + IString(csvArr[1]).ToDouble()) / 2.0; } } } - diff --git a/isis/src/mro/apps/hirdrgen/main.cpp b/isis/src/mro/apps/hirdrgen/main.cpp index b09c45c377..655d1b2802 100644 --- a/isis/src/mro/apps/hirdrgen/main.cpp +++ b/isis/src/mro/apps/hirdrgen/main.cpp @@ -3,7 +3,7 @@ #include #include -#include "Histogram.h" +#include "ImageHistogram.h" #include "iTime.h" #include "IString.h" #include "JP2Encoder.h" @@ -61,7 +61,7 @@ void IsisMain() { if (ui.GetString("TYPE").compare("AUTOMATIC") == 0) { // Set up a histogram for this band. This call sets the input range // by making an initial stats pass to find the data min and max - Histogram hist(*icube, band, pHist.Progress()); + ImageHistogram hist(*icube, band, pHist.Progress()); // Loop and accumulate histogram pHist.Progress()->SetText("Gathering Histogram"); diff --git a/isis/src/qisis/objs/HistogramTool/HistogramTool.cpp b/isis/src/qisis/objs/HistogramTool/HistogramTool.cpp index ede924d9a4..88c4eea714 100644 --- a/isis/src/qisis/objs/HistogramTool/HistogramTool.cpp +++ b/isis/src/qisis/objs/HistogramTool/HistogramTool.cpp @@ -11,6 +11,7 @@ #include "Brick.h" #include "CubePlotCurve.h" +#include "ImageHistogram.h" #include "Histogram.h" #include "HistogramItem.h" #include "HistogramPlotWindow.h" @@ -189,7 +190,7 @@ namespace Isis { Cube *cube = activeViewport->cube(); int band = activeViewport->grayBand(); - Histogram hist(*cube, band); + ImageHistogram hist(*cube, band); //If the rubber band is a line if (rubberBandTool()->currentMode() == RubberBandTool::LineMode) { @@ -458,4 +459,3 @@ namespace Isis { } } } - diff --git a/isis/src/qisis/objs/ScatterPlotTool/ScatterPlotData.cpp b/isis/src/qisis/objs/ScatterPlotTool/ScatterPlotData.cpp index a440776c71..230d25a511 100644 --- a/isis/src/qisis/objs/ScatterPlotTool/ScatterPlotData.cpp +++ b/isis/src/qisis/objs/ScatterPlotTool/ScatterPlotData.cpp @@ -35,7 +35,7 @@ namespace Isis { int endLine = qRound(lineRange.maxValue()); ASSERT(xCube->lineCount() == yCube->lineCount()); - Histogram *xCubeHist = new Histogram(*xCube, xCubeBand, NULL, + ImageHistogram *xCubeHist = new ImageHistogram(*xCube, xCubeBand, NULL, sampleRange.minValue(), lineRange.minValue(), sampleRange.maxValue(), lineRange.maxValue(), xBinCount, true); @@ -43,7 +43,7 @@ namespace Isis { m_xCubeMax = xCubeHist->Maximum(); - Histogram *yCubeHist = new Histogram(*yCube, yCubeBand, NULL, + ImageHistogram *yCubeHist = new ImageHistogram(*yCube, yCubeBand, NULL, sampleRange.minValue(), lineRange.minValue(), sampleRange.maxValue(), lineRange.maxValue(), yBinCount, true); @@ -485,4 +485,3 @@ namespace Isis { return indices; } } - diff --git a/isis/tests/statsTests.cpp b/isis/tests/statsTests.cpp index a5527064c2..c5376b149b 100644 --- a/isis/tests/statsTests.cpp +++ b/isis/tests/statsTests.cpp @@ -6,7 +6,7 @@ #include "Cube.h" #include "FileName.h" -#include "Histogram.h" +#include "ImageHistogram.h" #include "Pvl.h" #include "SpecialPixel.h" @@ -48,13 +48,13 @@ class stats_MockHist : public ::testing::Test { void SetUp() override { mockCube = nullptr; - Histogram *testBand1Stats = new Histogram(-10, 10, 21); + ImageHistogram *testBand1Stats = new ImageHistogram(-10, 10, 21); for (int val = -10; val <=10; val++) { testBand1Stats->AddData(val); } testBand1Stats->AddData(0.0); - Histogram *testBand2Stats = new Histogram(-10, 10, 21); + ImageHistogram *testBand2Stats = new ImageHistogram(-10, 10, 21); testBand2Stats->AddData(Null); testBand2Stats->AddData(Lrs); testBand2Stats->AddData(Lis); @@ -146,7 +146,7 @@ TEST_F(stats_MockHist, TestStats) { } TEST(stats, ValidMinimum) { - Histogram *testStats = new Histogram(-1000,1000); + ImageHistogram *testStats = new ImageHistogram(-1000,1000); MockCube *mockCube = new MockCube(); EXPECT_CALL(*mockCube, bandCount()) @@ -173,7 +173,7 @@ TEST(stats, ValidMinimum) { } TEST(stats, ValidMaximum) { - Histogram *testStats = new Histogram(-1000,1000); + ImageHistogram *testStats = new ImageHistogram(-1000,1000); MockCube *mockCube = new MockCube(); EXPECT_CALL(*mockCube, bandCount())