diff --git a/AmrPicture.H b/AmrPicture.H index 851f609..cad844c 100644 --- a/AmrPicture.H +++ b/AmrPicture.H @@ -143,7 +143,8 @@ class AmrPicture { void CreateImage(const amrex::FArrayBox &fab, unsigned char *imagedata, int datasizeh, int datasizev, Real globalMin, Real globalMax, Palette *palptr, - const amrex::FArrayBox *vfracFab, const Real vfeps); + const amrex::FArrayBox *vfracFab, const Real vfeps, + bool logScale = false); void CreateScaledImage(XImage **ximage, int scale, unsigned char *imagedata, unsigned char *scaledimagedata, diff --git a/AmrPicture.cpp b/AmrPicture.cpp index 3373f72..1c6bea6 100644 --- a/AmrPicture.cpp +++ b/AmrPicture.cpp @@ -614,7 +614,7 @@ void AmrPicture::APChangeContour(Amrvis::ContourType prevCType) { CreateImage(*(sliceFab[iLevel]), imageData[iLevel], dataSizeH[iLevel], dataSizeV[iLevel], minUsing, maxUsing, palPtr, - vffp, vfeps); + vffp, vfeps, pltAppStatePtr->GetLogScale()); bool bCreateMask(iLevel == minDrawnLevel); CreateScaledImage(&(xImageArray[iLevel]), pltAppStatePtr->CurrentScale() * amrex::CRRBetweenLevels(iLevel, maxAllowableLevel, @@ -880,7 +880,7 @@ void AmrPicture::APMakeImages(Palette *palptr) { } CreateImage(*(sliceFab[iLevel]), imageData[iLevel], dataSizeH[iLevel], dataSizeV[iLevel], - minUsing, maxUsing, palPtr, vffp, vfeps); + minUsing, maxUsing, palPtr, vffp, vfeps, pltAppStatePtr->GetLogScale()); bool bCreateMask(iLevel == minDrawnLevel); CreateScaledImage(&(xImageArray[iLevel]), pltAppStatePtr->CurrentScale() * amrex::CRRBetweenLevels(iLevel, maxAllowableLevel, @@ -904,15 +904,29 @@ void AmrPicture::APMakeImages(Palette *palptr) { void AmrPicture::CreateImage(const FArrayBox &fab, unsigned char *imagedata, int datasizeh, int datasizev, Real globalMin, Real globalMax, Palette *palptr, - const FArrayBox *vfracFab, const Real vfeps) + const FArrayBox *vfracFab, const Real vfeps, + bool logScale) { int jdsh, jtmp1; int dIndex, iIndex; Real oneOverGDiff; - if((globalMax - globalMin) < FLT_MIN) { - oneOverGDiff = 0.0; + Real logGlobalMin, logGlobalMax; + bool useLogScale = logScale && globalMin > 0.0 && globalMax > 0.0; + + if(useLogScale) { + logGlobalMin = std::log10(globalMin); + logGlobalMax = std::log10(globalMax); + if((logGlobalMax - logGlobalMin) < FLT_MIN) { + oneOverGDiff = 0.0; + } else { + oneOverGDiff = 1.0 / (logGlobalMax - logGlobalMin); + } } else { - oneOverGDiff = 1.0 / (globalMax - globalMin); + if((globalMax - globalMin) < FLT_MIN) { + oneOverGDiff = 0.0; + } else { + oneOverGDiff = 1.0 / (globalMax - globalMin); + } } const Real *dataPoint = fab.dataPtr(); bool bCartGrid(dataServicesPtr->AmrDataRef().CartGrid()); @@ -943,9 +957,14 @@ void AmrPicture::CreateImage(const FArrayBox &fab, unsigned char *imagedata, } else if(dPoint < globalMin) { // clip imagedata[iIndex] = paletteStart; } else { - imagedata[iIndex] = (unsigned char) - ((((dPoint - globalMin) * oneOverGDiff) * csm1) ); - // ^^^^^^^^^^^^^^^^^^ Real data + if(useLogScale && dPoint > 0.0) { + Real logDPoint = std::log10(dPoint); + imagedata[iIndex] = (unsigned char) + ((((logDPoint - logGlobalMin) * oneOverGDiff) * csm1) ); + } else { + imagedata[iIndex] = (unsigned char) + ((((dPoint - globalMin) * oneOverGDiff) * csm1) ); + } imagedata[iIndex] += paletteStart; } } @@ -966,9 +985,14 @@ void AmrPicture::CreateImage(const FArrayBox &fab, unsigned char *imagedata, } else if(dPoint < globalMin) { // clip imagedata[iIndex] = paletteStart; } else { - imagedata[iIndex] = (unsigned char) - ((((dPoint - globalMin) * oneOverGDiff) * csm1) ); - // ^^^^^^^^^^^^^^^^^^ Real data + if(useLogScale && dPoint > 0.0) { + Real logDPoint = std::log10(dPoint); + imagedata[iIndex] = (unsigned char) + ((((logDPoint - logGlobalMin) * oneOverGDiff) * csm1) ); + } else { + imagedata[iIndex] = (unsigned char) + ((((dPoint - globalMin) * oneOverGDiff) * csm1) ); + } imagedata[iIndex] += paletteStart; } if(dVFPoint < vfeps) { // set to body color @@ -1686,7 +1710,7 @@ void AmrPicture::CreateFrames(Amrvis::AnimDirection direction) { } CreateImage(imageFab, frameImageData, dataSizeH[maxDrawnLevel], dataSizeV[maxDrawnLevel], - minUsing, maxUsing, palPtr, vffp, vfeps); + minUsing, maxUsing, palPtr, vffp, vfeps, pltAppStatePtr->GetLogScale()); // this cannot be deleted because it belongs to the XImage unsigned char *frameScaledImageData; diff --git a/Docs/Amrvis.tex b/Docs/Amrvis.tex index e610fd8..54ffd34 100644 --- a/Docs/Amrvis.tex +++ b/Docs/Amrvis.tex @@ -197,6 +197,13 @@ \subsubsection{Interface Windows and Regions} drawn around the corresponding data point in the Data Image Area (the color data image). +\item[XY Plot Window] This window displays 1D line plots of data values +and is created when holding shift while using the middle or right mouse buttons +to draw lines across the data view. The plot shows the variation of the selected +quantity along the line. Multiple line plots can be overlaid in the same +window for comparison. The window includes controls for animation through +time steps, displaying the plots from multiple files at the same position. + \item[Animation Control Area] This area contains controls for animating through data files and through planes in 3D. It is in the lower right part of the Data View Window below the Palette Area. It also shows @@ -316,11 +323,15 @@ \subsubsection{Mouse Controls} in the isometric view, translating the image in the isometric view (with the shift button pressed), and clicking a point for its data value. -\item [Middle Button] Placing horizontal planar cutting lines in the -orthogonal image views and rotating around the eye point in the isometric view. +\item [Middle Button] Creating horizontal 1D line plots by holding shift while clicking +and dragging to draw a horizontal line across the data view. When the button is released, +a separate XY plot window opens showing the data values along that line (X-direction plot +at the selected Y position). In 3D, this also rotates around the eye point in the isometric view. -\item [Right Button] Placing vertical planar cutting lines in the -orthogonal image views and zooming the isometric view (pull or push the mouse). +\item [Right Button] Creating vertical 1D line plots by holding shift while clicking +and dragging to draw a vertical line across the data view. When the button is released, +a separate XY plot window opens showing the data values along that line (Y-direction plot +at the selected X position). In 3D, this also zooms the isometric view (pull or push the mouse). \end{description} diff --git a/Palette.H b/Palette.H index 9b35f38..b2ae388 100644 --- a/Palette.H +++ b/Palette.H @@ -72,13 +72,14 @@ class Palette { PaletteType GetPaletteType() { return paletteType; } amrex::Vector GetTransferArray() { return transferArray; } int ReadSeqPalette(const string &fileName, bool bRedraw = true); - void DrawPalette(Real palMin, Real palMax, const string &numberFormat); + void DrawPalette(Real palMin, Real palMax, const string &numberFormat, bool logScale = false); void SetWindow(Window drawPaletteHere); void SetWindowPalette(const string &palName, Window newPalWindow, bool bRedraw = true); void ChangeWindowPalette(const string &palName, Window newPalWindow); void ExposePalette(); void RedrawPalette(); + void RedrawPalette(bool logScale); void SetReserveSystemColors(int reservesystemcolors); void SetFormat(const string &newFormat); Colormap GetColormap() const { return colmap; } diff --git a/Palette.cpp b/Palette.cpp index d38bb7c..d1a6487 100644 --- a/Palette.cpp +++ b/Palette.cpp @@ -10,6 +10,7 @@ #include #include +#include using std::cout; using std::cerr; using std::endl; @@ -173,9 +174,14 @@ void Palette::RedrawPalette() { DrawPalette(pmin, pmax, defaultFormat); // use defaults } +// ------------------------------------------------------------------- +void Palette::RedrawPalette(bool logScale) { + DrawPalette(pmin, pmax, defaultFormat, logScale); // use defaults with log scale +} + // ------------------------------------------------------------------- -void Palette::DrawPalette(Real palMin, Real palMax, const string &numberFormat) { +void Palette::DrawPalette(Real palMin, Real palMax, const string &numberFormat, bool logScale) { int i, cy, palOffsetY(14); XWindowAttributes winAttribs; Display *display(gaPtr->PDisplay()); @@ -329,10 +335,23 @@ void Palette::DrawPalette(Real palMin, Real palMax, const string &numberFormat) char palString[128]; for(i = 0; i < dataList.size(); ++i) { XSetForeground(display, gc, AVWhitePixel()); - dataList[i] = palMin + (dataList.size() - 1 - i) * - (palMax - palMin) / (dataList.size() - 1); - if(i == 0) { - dataList[i] = palMax; // to avoid roundoff + if(logScale && palMin > 0.0 && palMax > 0.0) { + // Log scale: interpolate in log space + Real logMin = std::log10(palMin); + Real logMax = std::log10(palMax); + Real logVal = logMin + (dataList.size() - 1 - i) * + (logMax - logMin) / (dataList.size() - 1); + dataList[i] = std::pow(10.0, logVal); + if(i == 0) { + dataList[i] = palMax; // to avoid roundoff + } + } else { + // Linear scale (original behavior) + dataList[i] = palMin + (dataList.size() - 1 - i) * + (palMax - palMin) / (dataList.size() - 1); + if(i == 0) { + dataList[i] = palMax; // to avoid roundoff + } } sprintf(palString, numberFormat.c_str(), dataList[i]); XDrawString(display, palPixmap, gc, palWidth + 4, diff --git a/PltApp.H b/PltApp.H index 9cabf91..1ec7920 100644 --- a/PltApp.H +++ b/PltApp.H @@ -249,6 +249,7 @@ private: void DirtyFrames(); void DoRubberBanding(Widget, XtPointer, XtPointer); void DoBoxesButton(Widget, XtPointer, XtPointer); + void DoLogScaleButton(Widget, XtPointer, XtPointer); void DoCGSmoothing(Widget, XtPointer, XtPointer); void DoCGShowBody(Widget, XtPointer, XtPointer); void DoAnimBackStep(); @@ -348,7 +349,7 @@ class AVXGrab { public: AVXGrab(Display *display) : bIsGrabbed(true), cachedDisplay(display) { XSync(cachedDisplay, False); - XGrabServer(display); + //XGrabServer(display); XSync(cachedDisplay, False); } diff --git a/PltApp.cpp b/PltApp.cpp index 1b1cd4b..72719a8 100644 --- a/PltApp.cpp +++ b/PltApp.cpp @@ -26,6 +26,7 @@ #include #include +#include #include @@ -1060,6 +1061,18 @@ void PltApp::PltAppInit(bool bSubVolume) { XmStringFree(label_str); AddStaticCallback(wid, XmNvalueChangedCallback, &PltApp::DoBoxesButton); + // Toggle log scale colorbar + label_str = XmStringCreateSimple(const_cast("l")); + wid = XtVaCreateManagedWidget("Log Scale", + xmToggleButtonGadgetClass, wMenuPulldown, + XmNmnemonic, 'L', + XmNset, pltAppState->GetLogScale(), + XmNaccelerator, "L", + XmNacceleratorText, label_str, + NULL); + XmStringFree(label_str); + AddStaticCallback(wid, XmNvalueChangedCallback, &PltApp::DoLogScaleButton); + if(amrData.CartGrid()) { // cart grid smoothing label_str = XmStringCreateSimple(const_cast("s")); @@ -3370,6 +3383,20 @@ void PltApp::DoBoxesButton(Widget, XtPointer, XtPointer) { } +// ------------------------------------------------------------------- +void PltApp::DoLogScaleButton(Widget, XtPointer, XtPointer) { + if(animating2d) { + ResetAnimation(); + DirtyFrames(); + } + pltAppState->SetLogScale( ! pltAppState->GetLogScale()); + pltPaletteptr->RedrawPalette(pltAppState->GetLogScale()); + for(int np(0); np < Amrvis::NPLANES; ++np) { + amrPicturePtrArray[np]->APMakeImages(pltPaletteptr); + } +} + + // ------------------------------------------------------------------- void PltApp::DoCGSmoothing(Widget, XtPointer, XtPointer) { if(animating2d) { diff --git a/PltAppState.H b/PltAppState.H index 2fa98b3..6516dc3 100644 --- a/PltAppState.H +++ b/PltAppState.H @@ -81,6 +81,10 @@ public: bool GetCGSmoothing() const { return cgSmoothing; } void SetCGSmoothing(bool smoothing) { cgSmoothing = smoothing; } + // ------------------------ log scale + bool GetLogScale() const { return logScale; } + void SetLogScale(bool useLogScale) { logScale = useLogScale; } + // ------------------------ number format string GetFormatString() const { return formatString; } void SetFormatString(const string &newformat) { formatString = newformat; } @@ -139,6 +143,7 @@ private: int currentDerivedNumber; bool showBoxes; bool cgSmoothing; + bool logScale; amrex::Amrvis::ContourType currentContourType; int nContours; amrex::Amrvis::MinMaxRangeType currentMinMaxType; diff --git a/PltAppState.cpp b/PltAppState.cpp index 3fba850..48f5625 100644 --- a/PltAppState.cpp +++ b/PltAppState.cpp @@ -68,6 +68,7 @@ PltAppState::PltAppState(int numFrames, int numDerived) } } cgSmoothing = false; + logScale = false; } @@ -88,6 +89,7 @@ PltAppState &PltAppState::operator=(const PltAppState &rhs) { currentDerivedNumber = rhs.currentDerivedNumber; showBoxes = rhs.showBoxes; cgSmoothing = rhs.cgSmoothing; + logScale = rhs.logScale; currentContourType = rhs.currentContourType; nContours = rhs.nContours; currentMinMaxType = rhs.currentMinMaxType;