Bug 121534

Summary: log axis tickmarks switch to linear spacing too soon
Product: [Applications] kst Reporter: Marc-Antoine Miville-Deschenes <mamd>
Component: generalAssignee: kst
Status: RESOLVED FIXED    
Severity: normal    
Priority: HI    
Version: 1.x   
Target Milestone: ---   
Platform: openSUSE   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: image showing ylog problem

Description Marc-Antoine Miville-Deschenes 2006-02-07 13:02:16 UTC
Version:            (using KDE KDE 3.5.0KDE 3.4.3)
Installed from:    SuSE RPMsMac OS X (Fink) Packages

When a plot is shown in log on the Y axis (I did not test X axis) with a
rather small range (from 10 to 300 for instance) the ticks are no longer
log-spaced but linearly-spaced. 

How to reproduce:
- Plot a curve in log-log
- reduce the size of the Y range using 'Expression' in Edit Plot -> Range
- At some point the Y axis goes from log-spaced to linearly-spaced tickmarks

Expected Behaviour
- Always have log-spaced tickmarks if in log mode
Comment 1 Marc-Antoine Miville-Deschenes 2006-02-07 13:03:49 UTC
Created attachment 14587 [details]
image showing ylog problem
Comment 2 Netterfield 2006-02-15 01:43:51 UTC
Currently, if max/min<32, the ticks end up in linear tick mode.  If it isn't too invasive, could instead happen if Max/Min < 10.  If Max/Min<10, there is no promise that there will even be 1 major tick, and so the current behavior should be preserved.

Comment 3 Andrew Walker 2006-02-22 02:21:23 UTC
My preference would be to increase it to Max/Min = 100. At present you sometimes get a single labelled tick, which marks it hard to determine what the values of the other ticks are. With Max/Min = 100 you would be assured of two labelled ticks.

Another approach would be to use the normal log labels for Max/Min > 100, switch to linear labels for Max/Min < 10, and then label some or all of the minor ticks (in a smaller font?) for 10 <= Max/Min <= 100. 
Comment 4 Andrew Walker 2006-02-28 00:41:23 UTC
SVN commit 514321 by arwalker:

CCBUG:121534 Make existing code clearer in its intent

 M  +9 -5      kst2dplot.cpp  


--- trunk/extragear/graphics/kst/src/libkstapp/kst2dplot.cpp #514320:514321
@@ -2937,15 +2937,19 @@
     auto_tick = _autoTickYLast;
   } else if (is_log) {
     if (max - min <= (double)majorDensity && max - min > 1.5) {
+      // show in logarithmic mode with major ticks nicely labelled and 9 minor ticks 
+      //  between each major label...
       auto_tick = 9;
       tick = 1.0;
     } else if (max - min >= (double)majorDensity) {
+      // show in logarithmic mode with major ticks nicely labelled and no minor ticks...  
       auto_tick = 0;
       tick = floor((max - min) / (double)majorDensity);
       if (tick == 1.0) {
         auto_tick = 9;
       }
     } else {
+      // show in "linear" mode with major ticks linearly spaced and no minor ticks...
       auto_tick = 0;
       Exp = pow(10.0, floor(log10(St)));
 
@@ -2960,16 +2964,16 @@
     // determine tick interval...
     Exp = 0;
     if (base == 60) {
-      if ((b60_ticks[0]*0.7<St) &&
-          (b60_ticks[n_b60_ticks-1]>St*0.7)) {
+      if ((b60_ticks[0]*0.7 < St) &&
+          (b60_ticks[n_b60_ticks-1] > St*0.7)) {
         Exp = 1.0;
         ticks = b60_ticks;
         autominor = b60_autominor;
         nt = n_b60_ticks;
       }
     } else if (base == 24) {
-      if ((b24_ticks[0]*0.7<St) &&
-          (b24_ticks[n_b24_ticks-1]>St*0.7)) {
+      if ((b24_ticks[0]*0.7 < St) &&
+          (b24_ticks[n_b24_ticks-1] > St*0.7)) {
         Exp = 1.0;
         ticks = b24_ticks;
         autominor = b24_autominor;
@@ -2977,7 +2981,7 @@
       }
     }
 
-    if (Exp<0.5) {
+    if (Exp < 0.5) {
       Exp = pow(10.0, floor(log10(St)));
     }
 
Comment 5 Netterfield 2006-04-04 17:31:24 UTC
The correct solution here is to go to log_2 when there is not enough dynamic range for log_10.

I guess it is ok to never go to pseudo-linear.  If the user chooses log mode, and there are no tick labels... so be it.

Comment 6 Andrew Walker 2006-05-15 19:34:00 UTC
SVN commit 541168 by arwalker:

CCBUG:121534 Allow any base for the log scale. This is not currently enabled as further testing is needed. Fix compilation.

 M  +27 -4     libkst/kstmath.h  
 M  +125 -110  libkstapp/kst2dplot.cpp  
 M  +18 -11    libkstapp/kst2dplot.h  
 M  +1 -0      libkstmath/kstbasecurve.cpp  
 M  +4 -4      libkstmath/kstbasecurve.h  
 M  +28 -26    libkstmath/kstimage.cpp  
 M  +55 -53    libkstmath/kstvcurve.cpp  
Comment 7 Andrew Walker 2006-06-14 00:08:57 UTC
SVN commit 551195 by arwalker:

BUG:121534 Go to base 2 when base 10 does not display enough valuse on the axis.

 M  +35 -8     kst2dplot.cpp  


--- trunk/extragear/graphics/kst/src/libkstapp/kst2dplot.cpp #551194:551195
@@ -756,6 +756,15 @@
 
   if (checkLRange(xmin_in, xmax_in, _xLog, _xLogBase)) {
     if (_xLog) {
+      if (_xLogBase == 10.0 && xmax_in - xmin_in < 1.5) {
+        _xLogBase = 2.0;
+        xmin_in *= 1.0/log10(2.0);
+        xmax_in *= 1.0/log10(2.0);
+      } else if (_xLogBase == 2.0 && xmax_in - xmin_in > 4.0) {
+        _xLogBase = 10.0;
+        xmin_in *= log10(2.0);
+        xmax_in *= log10(2.0);
+      }
       XMax = pow(_xLogBase, xmax_in);
       XMin = pow(_xLogBase, xmin_in);
     } else {
@@ -774,6 +783,11 @@
 
   if (checkLRange(ymin_in, ymax_in, _yLog, _yLogBase)) {
     if (_yLog) {
+      if (_yLogBase == 10.0 && ymax_in - ymin_in < 1.1) {
+        _yLogBase = 2.0;
+      } else if (_yLogBase == 2.0 && ymax_in - ymin_in > 3.5) {
+        _yLogBase = 10.0;
+      }
       YMax = pow(_yLogBase, ymax_in);
       YMin = pow(_yLogBase, ymin_in);
     } else {
@@ -1433,7 +1447,7 @@
   int accuracy = 0;
 
   // check how many decimal places we need based on the scale
-  getLScale(xmin,ymin,xmax,ymax);
+  getLScale(xmin, ymin, xmax, ymax);
   if (isXLog()) {
     xdelta = (pow(_xLogBase, xmax) - pow(_xLogBase, xmin))/double(pr.width());
   } else {
@@ -3024,17 +3038,30 @@
     tick = _tickYLast;
     auto_tick = _autoTickYLast;
   } else if (is_log) {
-    if (max - min <= (double)majorDensity && max - min > 1.5) {
-      // show in logarithmic mode with major ticks nicely labelled and 9 minor ticks 
-      //  between each major label...
-      auto_tick = 9;
+    if (max - min <= (double)majorDensity && ((_xLogBase == 10.0 && max - min > 1.5) ||
+                                              (_xLogBase ==  2.0 && max - min > 1.0))) {
+      // show in logarithmic mode with major ticks nicely labelled and the specified
+      //  number of minor ticks between each major label...
+      if (logBase == 2.0) {
+        auto_tick = 10;
+      } else if (logBase == 10.0) {
+        auto_tick = 9;
+      } else {
+        auto_tick = 5;
+      }
       tick = 1.0;
     } else if (max - min >= (double)majorDensity) {
       // show in logarithmic mode with major ticks nicely labelled and no minor ticks...  
       auto_tick = 0;
       tick = floor((max - min) / (double)majorDensity);
       if (tick == 1.0) {
-        auto_tick = 9;
+        if (logBase == 2.0) {
+          auto_tick = 10;
+        } else if (logBase == 10.0) {
+          auto_tick = 9;
+        } else {
+          auto_tick = 5;
+        }
       }
     } else {
       // show in "linear" mode with major ticks linearly spaced and no minor ticks...
@@ -3047,10 +3074,10 @@
           tick = ticks[i] * Exp;
         }
       }
-    }
+    } 
   } else {
     // determine tick interval...
-    Exp = 0;
+    Exp = 0.0;
     if (base == 60) {
       if ((b60_ticks[0]*0.7 < St) &&
           (b60_ticks[n_b60_ticks-1] > St*0.7)) {