void IsisMain() { QString projName; Process pHist; Cube *icube = pHist.SetInputCube("FROM"); // Check to see if the input cube looks like a HiRISE RDR if (icube->bandCount() > 3) { QString msg = "Input file [" + Application::GetUserInterface().GetFileName("FROM") + "] does not appear to be a HiRISE RDR product. Number of " + "bands is greater than 3"; throw IException(IException::Programmer, msg, _FILEINFO_); } // Setup to get a histogram for each band g_min = new double[icube->bandCount()]; g_max = new double[icube->bandCount()]; UserInterface &ui = Application::GetUserInterface(); // Determine if the data is to be converted to JPEG2000 IString enctype = ui.GetString("ENCODING_TYPE"); enctype.DownCase(); for (int band = 1; band <= icube->bandCount(); ++band) { 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()); // Loop and accumulate histogram pHist.Progress()->SetText("Gathering Histogram"); pHist.Progress()->SetMaximumSteps(icube->lineCount()); pHist.Progress()->CheckStatus(); LineManager line(*icube); for (int i = 1; i <= icube->lineCount(); i++) { line.SetLine(i, band); icube->read(line); hist.AddData(line.DoubleBuffer(), line.size()); pHist.Progress()->CheckStatus(); } // get the requested cumulative percentages g_min[band-1] = ui.GetDouble("MINPER") == 0.0 ? hist.Minimum() : hist.Percent(ui.GetDouble("MINPER")); g_max[band-1] = ui.GetDouble("MAXPER") == 100.0 ? hist.Maximum() : hist.Percent(ui.GetDouble("MAXPER")); } else { g_min[band-1] = ui.GetDouble("MIN"); g_max[band-1] = ui.GetDouble("MAX"); } } // Find the minimum min and maximum max for all bands double minmin = g_min[0]; double maxmax = g_max[0]; for (int band = 1; band < icube->bandCount(); ++band) { if (g_min[band] < minmin) minmin = g_min[band]; if (g_max[band] > maxmax) maxmax = g_max[band]; } pHist.EndProcess(); // Set up for writing the data to a PDS formatted file ProcessExportPds p; Cube *icube2 = p.SetInputCube("FROM"); if (enctype.Equal("jp2")) { g_jp2buf = new char* [icube2->bandCount()]; FileName lblFile(ui.GetFileName("TO")); QString lblFileName = lblFile.path() + "/" + lblFile.baseName() + ".lbl"; p.SetDetached(lblFileName); p.setFormat(ProcessExport::JP2); } // Set the output pixel type and the special pixel values int nbits = ui.GetInteger("BITS"); if (nbits == 8) { if (enctype.Equal("jp2")) { for (int i = 0; i < icube2->bandCount(); i++) { g_jp2buf[i] = new char[icube2->sampleCount()]; } } g_oType = Isis::UnsignedByte; p.SetOutputType(g_oType); p.SetOutputRange(VALID_MIN1, VALID_MAX1); p.SetOutputNull(NULL1); p.SetOutputLis(LOW_INSTR_SAT1); p.SetOutputLrs(LOW_REPR_SAT1); p.SetOutputHis(HIGH_INSTR_SAT1); p.SetOutputHrs(HIGH_REPR_SAT1); } else if (nbits == 16) { if (enctype.Equal("jp2")) { for (int i = 0; i < icube2->bandCount(); i++) { g_jp2buf[i] = new char[icube2->sampleCount()*2]; } } g_oType = UnsignedWord; p.SetOutputType(g_oType); p.SetOutputRange(VALID_MINU2, VALID_MAXU2); p.SetOutputNull(NULLU2); p.SetOutputLis(LOW_INSTR_SATU2); p.SetOutputLrs(LOW_REPR_SATU2); p.SetOutputHis(HIGH_INSTR_SATU2); p.SetOutputHrs(HIGH_REPR_SATU2); } else { if (enctype.Equal("jp2")) { for (int i = 0; i < icube2->bandCount(); i++) { g_jp2buf[i] = new char[icube2->sampleCount()*2]; } } g_oType = UnsignedWord; p.SetOutputType(g_oType); p.SetOutputRange(3.0, pow(2.0, (double)(nbits)) - 1.0 - 2.0); p.SetOutputNull(0); p.SetOutputLrs(1); p.SetOutputLis(2); p.SetOutputHis(pow(2.0, (double)(nbits)) - 1.0 - 1.0); p.SetOutputHrs(pow(2.0, (double)(nbits)) - 1.0); } p.SetOutputEndian(Isis::Msb); p.SetInputRange(minmin, maxmax); // Get the PDS label from the process ProcessExportPds::PdsFileType type; if (enctype.Equal("jp2")) { type = ProcessExportPds::JP2Image; } else { type = ProcessExportPds::Image; } Pvl &pdsLabel = p.StandardPdsLabel(type); // Translate the keywords from the input cube label that go in the PDS label PvlTranslationManager cubeLab(*(icube2->label()), "$mro/translations/hirisePdsRdrCubeLabel.trn"); cubeLab.Auto(pdsLabel); // Translate the keywords from the original EDR PDS label that go in // this RDR PDS label OriginalLabel origBlob; icube2->read(origBlob); Pvl origLabel; PvlObject origLabelObj = origBlob.ReturnLabels(); origLabelObj.setName("OriginalLabelObject"); origLabel.addObject(origLabelObj); PvlTranslationManager orig(origLabel, "$mro/translations/hirisePdsRdrOriginalLabel.trn"); orig.Auto(pdsLabel); // Add labels to the PDS product that could not be handled by the translater if (ui.WasEntered("RATIONALE_DESC")) { pdsLabel.addKeyword( PvlKeyword("RATIONALE_DESC", ui.GetString("RATIONALE_DESC")), Pvl::Replace); } // Add PRODUCT_CREATION_TIME time_t startTime = time(NULL); struct tm *tmbuf = gmtime(&startTime); char timestr[80]; strftime(timestr, 80, "%Y-%m-%dT%H:%M:%S", tmbuf); QString dateTime = (QString) timestr; iTime tmpDateTime(dateTime); PvlGroup &timeParam = pdsLabel.findGroup("TIME_PARAMETERS"); timeParam += PvlKeyword("PRODUCT_CREATION_TIME", tmpDateTime.UTC()); // Add the N/A constant keyword to the ROOT pdsLabel += PvlKeyword("NOT_APPLICABLE_CONSTANT", toString(-9998)); // Add SOFTWARE_NAME to the ROOT QString sfname; sfname.clear(); sfname += "Isis " + Application::Version() + " " + Application::GetUserInterface().ProgramName(); pdsLabel += PvlKeyword("SOFTWARE_NAME", sfname); // Add the PRODUCT_VERSION_ID from the user parameter VERSION pdsLabel += PvlKeyword("PRODUCT_VERSION_ID", ui.GetString("VERSION")); // Add MRO:CCD_FLAG, MRO:BINNING, MRO:TDI // As pulled from the input Isis cube, the values are in CPMM order, so // convert them to CCD order PvlKeyword ccdFlag("MRO:CCD_FLAG"); PvlKeyword &cpmmFlag = origLabel.findObject("OriginalLabelObject"). findGroup("INSTRUMENT_SETTING_PARAMETERS"). findKeyword("MRO:POWERED_CPMM_FLAG"); PvlKeyword ccdBin("MRO:BINNING"); PvlKeyword &cpmmBin = icube2->label()->findObject("IsisCube"). findGroup("Mosaic")["cpmmSummingFlag"]; PvlKeyword ccdTdi("MRO:TDI"); PvlKeyword &cpmmTdi = icube2->label()->findObject("IsisCube"). findGroup("Mosaic")["cpmmTdiFlag"]; PvlKeyword ccdSpecial("MRO:SPECIAL_PROCESSING_FLAG"); PvlKeyword &cpmmSpecial = icube2->label()->findObject("IsisCube"). findGroup("Mosaic")["SpecialProcessingFlag"]; for (int ccd = 0; ccd < 14; ++ccd) { const unsigned int cpmmByCcd[] = {0, 1, 2, 3, 5, 8, 10, 11, 12, 13, 6, 7, 4, 9}; ccdFlag.addValue(cpmmFlag[cpmmByCcd[ccd]]); ccdBin.addValue(cpmmBin[cpmmByCcd[ccd]] != "Null" ? cpmmBin[cpmmByCcd[ccd]] : "-9998"); ccdTdi.addValue(cpmmTdi[cpmmByCcd[ccd]] != "Null" ? cpmmTdi[cpmmByCcd[ccd]] : "-9998"); IString tmp = cpmmSpecial[cpmmByCcd[ccd]]; tmp.Trim("\""); ccdSpecial.addValue(tmp.ToQt()); } if (!pdsLabel.hasGroup("INSTRUMENT_SETTING_PARAMETERS")) { pdsLabel.addGroup(PvlGroup("INSTRUMENT_SETTING_PARAMETERS")); } pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdFlag; pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdBin; pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdTdi; pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdSpecial; // Add/modify projection info if there is a projection if (pdsLabel.hasObject("IMAGE_MAP_PROJECTION")) { PvlObject &mapObject = pdsLabel.findObject("IMAGE_MAP_PROJECTION"); mapObject += PvlKeyword("^DATA_SET_MAP_PROJECTION", "DSMAP.CAT"); // Add the HiRISE comment to the CENTER_LATITUDE keyword PvlKeyword &clat = mapObject["CENTER_LATITUDE"]; clat.addComment("/* NOTE: CENTER_LATITUDE and CENTER_LONGITUDE describe the location */"); clat.addComment("/* of the center of projection, which is not necessarily equal to the */"); clat.addComment("/* location of the center point of the image. */"); if (mapObject.hasKeyword("CENTER_LATITUDE")) { PvlKeyword ¢erLat = mapObject["CENTER_LATITUDE"]; // if (centerLat[0] == "N/A") centerLat = -9998; if (centerLat[0] == "N/A") mapObject.deleteKeyword("CENTER_LATITUDE"); } if (mapObject.hasKeyword("CENTER_LONGITUDE")) { PvlKeyword ¢erLon = mapObject["CENTER_LONGITUDE"]; // if (centerLon[0] == "N/A") centerLon = -9998; if (centerLon[0] == "N/A") mapObject.deleteKeyword("CENTER_LONGITUDE"); } if (mapObject.hasKeyword("REFERENCE_LATITUDE")) { PvlKeyword &refLat = mapObject["REFERENCE_LATITUDE"]; // if (refLat[0] == "N/A") refLat = -9998; if (refLat[0] == "N/A") mapObject.deleteKeyword("REFERENCE_LATITUDE"); } if (mapObject.hasKeyword("REFERENCE_LONGITUE")) { PvlKeyword &refLon = mapObject["REFERENCE_LONGITUDE"]; // if (refLon[0] == "N/A") refLon = -9998; if (refLon[0] == "N/A") mapObject.deleteKeyword("REFERENCE_LONGITUDE"); } if (mapObject.hasKeyword("FIRST_STANDARD_PARALLEL")) { PvlKeyword &firstSP = mapObject["FIRST_STANDARD_PARALLEL"]; // if (firstSP[0] == "N/A") firstSP = -9998; if (firstSP[0] == "N/A") mapObject.deleteKeyword("FIRST_STANDARD_PARALLEL"); } if (mapObject.hasKeyword("SECOND_STANDARD_PARALLEL")) { PvlKeyword &secondSP = mapObject["SECOND_STANDARD_PARALLEL"]; // if (secondSP[0] == "N/A") secondSP = -9998; if (secondSP[0] == "N/A") mapObject.deleteKeyword("SECOND_STANDARD_PARALLEL"); } // For Equirectangular ONLY // Modify the radii in the pds label to use the radius at the center latitude // instead of the target radii from NAIF if (mapObject["MAP_PROJECTION_TYPE"][0] == "EQUIRECTANGULAR") { Projection *proj = ProjectionFactory::CreateFromCube(*icube2); PvlGroup &mapping = icube2->label()->findGroup("MAPPING", Pvl::Traverse); double radius = proj->LocalRadius((double)mapping["CenterLatitude"]) / 1000.0; mapObject["A_AXIS_RADIUS"].setValue(toString(radius), "KM"); mapObject["B_AXIS_RADIUS"].setValue(toString(radius), "KM"); mapObject["C_AXIS_RADIUS"].setValue(toString(radius), "KM"); } projName = mapObject["MAP_PROJECTION_TYPE"][0]; } // Calculate the min/max per band keywords // These come from the input real DN and are converted to the PDS file DN // The input to output mapping is opposite from the one above double slope = (p.GetOutputMaximum() - p.GetOutputMinimum()) / (maxmax - minmin); double intercept = p.GetOutputMaximum() - slope * maxmax; PvlKeyword minimum("MRO:MINIMUM_STRETCH", toString(slope * g_min[0] + intercept)); PvlKeyword maximum("MRO:MAXIMUM_STRETCH", toString(slope * g_max[0] + intercept)); for (int band = 1; band < icube2->bandCount(); ++band) { minimum += toString(slope * g_min[band] + intercept); maximum += toString(slope * g_max[band] + intercept); } if (enctype.Equal("jp2")) { // Add keywords to the PDS JP2 IMAGE object PvlObject &imagejp2 = pdsLabel.findObject("UNCOMPRESSED_FILE").findObject("IMAGE"); // Add the HiRISE specific description of the IMAGE object imagejp2 += PvlKeyword("DESCRIPTION", "HiRISE projected and mosaicked product"); // Add the SCALLING_FACTOR and OFFSET keywords imagejp2.addKeyword(PvlKeyword("SCALING_FACTOR", toString(slope)), Pvl::Replace); imagejp2.addKeyword(PvlKeyword("OFFSET", toString(intercept)), Pvl::Replace); // Reformat some keyword units in the image object // This is lame, but PDS units are difficult to work with, so for now??? PvlKeyword &oldFilterNamejp2 = imagejp2["FILTER_NAME"]; PvlKeyword newFilterName("FILTER_NAME"); for (int val = 0; val < oldFilterNamejp2.size(); ++val) { QString filtname(oldFilterNamejp2[val].toUpper()); if (filtname == "BLUEGREEN") filtname = "BLUE-GREEN"; else if (filtname == "NEARINFRARED") filtname = "NEAR-INFRARED"; newFilterName.addValue(filtname); } imagejp2.addKeyword(newFilterName, Pvl::Replace); PvlKeyword &oldCenterjp2 = imagejp2["CENTER_FILTER_WAVELENGTH"]; PvlKeyword newCenter("CENTER_FILTER_WAVELENGTH"); for (int val = 0; val < oldCenterjp2.size(); ++val) { if (((IString)(oldCenterjp2.unit(val))).UpCase() == "NANOMETERS") { newCenter.addValue(oldCenterjp2[val], "NM"); } else { newCenter.addValue(oldCenterjp2[val], oldCenterjp2.unit(val)); } } imagejp2.addKeyword(newCenter, Pvl::Replace); PvlKeyword &oldBandWidthjp2 = imagejp2["BAND_WIDTH"]; PvlKeyword newBandWidth("BAND_WIDTH"); for (int val = 0; val < oldBandWidthjp2.size(); ++val) { if (((IString)(oldBandWidthjp2.unit(val))).UpCase() == "NANOMETERS") { newBandWidth.addValue(oldBandWidthjp2[val], "nm"); } else { newBandWidth.addValue(oldBandWidthjp2[val], oldBandWidthjp2.unit(val)); } } imagejp2.addKeyword(newBandWidth, Pvl::Replace); // Add the min/max per band keywords imagejp2 += minimum; imagejp2 += maximum; // Modify the default SAMPLE_BIT_MASK keyword placed there by the // ProcessExportPds if (nbits != 8 && nbits != 16) { imagejp2.addKeyword(PvlKeyword("SAMPLE_BIT_MASK", toString((int)pow(2.0, (double)ui.GetInteger("BITS")) - 1)), Pvl::Replace); } } else { // Add keywords to the PDS IMAGE object PvlObject &image = pdsLabel.findObject("IMAGE"); // Add the HiRISE specific description of the IMAGE object image += PvlKeyword("DESCRIPTION", "HiRISE projected and mosaicked product"); /** * Calculate the SCALING_FACTOR and OFFSET keywords * Set these so the unsigned 16bit PDS disk values can be converted back * to the correct values Isis had * These keywords are used to map stored/disk values to the correct values so, * the input(x axis) values are the unsigned Xbit values from the PDS file */ // ??? unneccessary calculation - this is done by ProcessExportPds class. double slope = (maxmax - minmin) / (p.GetOutputMaximum() - p.GetOutputMinimum()); double intercept = maxmax - slope * p.GetOutputMaximum(); image.addKeyword(PvlKeyword("SCALING_FACTOR", toString(slope)), Pvl::Replace); image.addKeyword(PvlKeyword("OFFSET", toString(intercept)), Pvl::Replace); // Reformat some keyword units in the image object // This is lame, but PDS units are difficult to work with, so for now PvlKeyword &oldFilterName = image["FILTER_NAME"]; PvlKeyword newFilterName("FILTER_NAME"); for (int val = 0; val < oldFilterName.size(); ++val) { QString filtname(oldFilterName[val].toUpper()); if (filtname == "BLUEGREEN") filtname = "BLUE-GREEN"; else if (filtname == "NEARINFRARED") filtname = "NEAR-INFRARED"; newFilterName.addValue(filtname); } image.addKeyword(newFilterName, Pvl::Replace); PvlKeyword &oldCenter = image["CENTER_FILTER_WAVELENGTH"]; PvlKeyword newCenter("CENTER_FILTER_WAVELENGTH"); for (int val = 0; val < oldCenter.size(); ++val) { if (((IString)(oldCenter.unit(val))).UpCase() == "NANOMETERS") { newCenter.addValue(oldCenter[val], "NM"); } else { newCenter.addValue(oldCenter[val], oldCenter.unit(val)); } } image.addKeyword(newCenter, Pvl::Replace); PvlKeyword &oldBandWidth = image["BAND_WIDTH"]; PvlKeyword newBandWidth("BAND_WIDTH"); for (int val = 0; val < oldBandWidth.size(); ++val) { if (((IString)(oldBandWidth.unit(val))).UpCase() == "NANOMETERS") { newBandWidth.addValue(oldBandWidth[val], "NM"); } else { newBandWidth.addValue(oldBandWidth[val], oldBandWidth.unit(val)); } } image.addKeyword(newBandWidth, Pvl::Replace); // Add the min/max per band keywords image += minimum; image += maximum; // Modify the default SAMPLE_BIT_MASK keyword placed there by the // ProcessExportPds if (nbits != 8 && nbits != 16) { image.addKeyword(PvlKeyword("SAMPLE_BIT_MASK", toString((int)pow(2.0, (double)ui.GetInteger("BITS")) - 1)), Pvl::Replace); } } // Modify the units in the viewing_parameters group // if (pdsLabel.hasGroup("VIEWING_PARAMETERS")) { // PvlGroup &viewGroup = pdsLabel.findGroup("VIEWING_PARAMETERS"); // PvlKeyword &incidence = viewGroup["INCIDENCE_ANGLE"]; // IString tstr = incidence.unit(); // if (tstr.UpCase() == "DEG") incidence.setValue((QString)incidence, "deg"); // PvlKeyword &emission = viewGroup["EMISSION_ANGLE"]; // tstr = emission.unit(); // if (tstr.UpCase() == "DEG") emission.setValue((QString)emission, "deg"); // PvlKeyword &phase = viewGroup["PHASE_ANGLE"]; // tstr = phase.unit(); // if (tstr.UpCase() == "DEG") phase.setValue((QString)phase, "deg"); // PvlKeyword &solarLon = viewGroup["SOLAR_LONGITUDE"]; // tstr = solarLon.unit(); q // if (tstr.UpCase() == "DEG") solarLon.setValue((QString)solarLon, "deg"); // PvlKeyword &localTime = viewGroup["LOCAL_TIME"]; // tstr = localTime.unit(); // if (tstr.UpCase() == "LOCALDAY/24") localTime.setValue((QString)localTime, "local day/24"); // } // Add a keyword type (i.e., QString, bool, int...) file to the PDS label Pvl PvlFormat *formatter = pdsLabel.format(); formatter->add("$mro/translations/hirisePdsRdrExtras.typ"); // Add an output format template (group, object, & keyword output order) to // the PDS PVL if (projName == "EQUIRECTANGULAR") { if (enctype.Equal("jp2")) { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrEquiJP2.pft"); } else { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrEqui.pft"); } } else { if (enctype.Equal("jp2")) { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrPolarJP2.pft"); } else { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrPolar.pft"); } } // Open the output PDS file and dump the label and cube data if (enctype.Equal("jp2")) { p.OutputDetachedLabel(); g_jp2Encoder = new JP2Encoder(ui.GetFileName("TO"), icube2->sampleCount(), icube2->lineCount(), icube2->bandCount(), g_oType); g_jp2Encoder->OpenFile(); g_jp2ns = icube2->sampleCount(); g_jp2nb = icube2->bandCount(); g_jp2band = 0; p.StartProcess(writeJP2Image); p.EndProcess(); delete g_jp2Encoder; for (int i = 0; i < icube2->bandCount(); i++) { delete [] g_jp2buf[i]; } } else { FileName outFile(ui.GetFileName("TO")); ofstream oCube(outFile.expanded().toAscii().data()); p.OutputLabel(oCube); p.StartProcess(oCube); oCube.close(); p.EndProcess(); } delete [] g_min; delete [] g_max; }
void IsisMain() { Process p; Cube *icube = p.SetInputCube("FROM"); // Setup the histogram UserInterface &ui = Application::GetUserInterface(); Histogram hist(*icube,1,p.Progress()); if (ui.WasEntered("MINIMUM")) { hist.SetValidRange(ui.GetDouble("MINIMUM"),ui.GetDouble("MAXIMUM")); } if (ui.WasEntered("NBINS")) { hist.SetBins(ui.GetInteger("NBINS")); } // Loop and accumulate histogram p.Progress()->SetText("Gathering Histogram"); p.Progress()->SetMaximumSteps(icube->Lines()); p.Progress()->CheckStatus(); LineManager line(*icube); for (int i=1; i<=icube->Lines(); i++) { line.SetLine(i); icube->Read(line); hist.AddData(line.DoubleBuffer(),line.size()); p.Progress()->CheckStatus(); } if(!ui.IsInteractive() || ui.WasEntered("TO")) { // Write the results if (!ui.WasEntered("TO")) { string msg = "The [TO] parameter must be entered"; throw iException::Message(iException::User,msg,_FILEINFO_); } string outfile = ui.GetFilename("TO"); ofstream fout; fout.open (outfile.c_str()); fout << "Cube: " << ui.GetFilename("FROM") << endl; fout << "Band: " << icube->Bands() << 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; // Write histogram in tabular format fout << endl; fout << endl; fout << "DN,Pixels,CumulativePixels,Percent,CumulativePercent" << endl; Isis::BigInt total = 0; double cumpct = 0.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) << ","; fout << hist.BinCount(i) << ","; fout << total << ","; fout << pct << ","; fout << cumpct << endl; } } fout.close(); } // If we are in gui mode, create a histogram plot if (ui.IsInteractive()) { // Set the title for the dialog string title; if (ui.WasEntered("TITLE")) { title = ui.GetString("TITLE"); } else { title = "Histogram Plot for " + Filename(ui.GetAsString("FROM")).Name(); } // Create the QHistogram, set the title & load the Isis::Histogram into it Qisis::HistogramToolWindow *plot = new Qisis::HistogramToolWindow(title.c_str(), ui.TheGui()); // Set the xaxis title if they entered one if (ui.WasEntered("XAXIS")) { string xaxis(ui.GetString("XAXIS")); plot->setAxisLabel(QwtPlot::xBottom,xaxis.c_str()); } // Set the yLeft axis title if they entered one if (ui.WasEntered("Y1AXIS")) { string yaxis(ui.GetString("Y1AXIS")); plot->setAxisLabel(QwtPlot::yLeft,yaxis.c_str()); } // Set the yRight axis title if they entered one if (ui.WasEntered("Y2AXIS")) { string y2axis(ui.GetString("Y2AXIS")); plot->setAxisLabel(QwtPlot::yRight,y2axis.c_str()); } //Transfer data from histogram to the plotcurve std::vector<double> xarray,yarray,y2array; double cumpct = 0.0; for (int i=0; i<hist.Bins(); i++) { if (hist.BinCount(i) > 0) { xarray.push_back(hist.BinMiddle(i)); yarray.push_back(hist.BinCount(i)); double pct = (double)hist.BinCount(i) / hist.ValidPixels() * 100.; cumpct += pct; y2array.push_back(cumpct); } } Qisis::HistogramItem *histCurve = new Qisis::HistogramItem(); histCurve->setColor(Qt::darkCyan); histCurve->setTitle("Frequency"); Qisis::PlotToolCurve *cdfCurve = new Qisis::PlotToolCurve(); cdfCurve->setStyle(QwtPlotCurve::Lines); cdfCurve->setTitle("Percentage"); QPen *pen = new QPen(Qt::red); pen->setWidth(2); histCurve->setYAxis(QwtPlot::yLeft); cdfCurve->setYAxis(QwtPlot::yRight); cdfCurve->setPen(*pen); //These are all variables needed in the following for loop. //---------------------------------------------- QwtArray<QwtDoubleInterval> intervals(xarray.size()); QwtArray<double> values(yarray.size()); double maxYValue = DBL_MIN; double minYValue = DBL_MAX; // --------------------------------------------- for(unsigned int y = 0; y < yarray.size(); y++) { intervals[y] = QwtDoubleInterval(xarray[y], xarray[y] + hist.BinSize()); values[y] = yarray[y]; if(values[y] > maxYValue) maxYValue = values[y]; if(values[y] < minYValue) minYValue = values[y]; } histCurve->setData(QwtIntervalData(intervals, values)); cdfCurve->setData(&xarray[0],&y2array[0],xarray.size()); 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' + "\n Maximum = " + QString::number(hist.Maximum()) + '\n' + "\n Stand. Dev.= " + QString::number(hist.StandardDeviation()) + '\n' + "\n Variance = " + QString::number(hist.Variance()) + '\n' + "\n Median = " + QString::number(hist.Median()) + '\n' + "\n Mode = " + QString::number(hist.Mode()) +'\n' + "\n Skew = " + QString::number(hist.Skew()), plot); plot->getDockWidget()->setWidget(label); plot->showWindow(); } p.EndProcess(); }