fix overlapping x axis ticks

Gnuplot does not handle long x-axis ticks very good.
It should know how wide the labels are and could adapt
the increment size accordingly, but it doesn't.
Fixed by explicitly defining the increment for x-axis
labels.
This commit is contained in:
2019-11-01 19:13:11 +01:00
parent 7c122b5753
commit c83d0a3e1e
6 changed files with 147 additions and 59 deletions

View File

@@ -24,9 +24,10 @@ public class GnuplotFileGenerator {
final XAxisSettings xAxis = settings.getxAxisSettings(); final XAxisSettings xAxis = settings.getxAxisSettings();
if (xAxis.isxDataTime()) { if (xAxis.isxDataTime()) {
appendfln(result, "set xdata time"); appendfln(result, "set xdata time");
appendln(result, XAxisTimeTicks.computeXTimeIncrements(settings));
appendfln(result, "set format x \"%s\"", xAxis.getFormatX());
} }
appendfln(result, "set xtics nomirror rotate by %d", xAxis.getRotateXAxisLabel()); appendfln(result, "set xtics nomirror rotate by %d", xAxis.getRotateXAxisLabel());
appendfln(result, "set format x \"%s\"", xAxis.getFormatX());
appendfln(result, "set xlabel \"%s\"", xAxis.getXlabel()); appendfln(result, "set xlabel \"%s\"", xAxis.getXlabel());
appendfln(result, "set xrange [\"%s\":\"%s\"]", xAxis.getFrom(), xAxis.getTo()); appendfln(result, "set xrange [\"%s\":\"%s\"]", xAxis.getFrom(), xAxis.getTo());
@@ -76,10 +77,10 @@ public class GnuplotFileGenerator {
appendln(result, "set tmargin 3"); // margin 3 -> 57px - marker (1) appendln(result, "set tmargin 3"); // margin 3 -> 57px - marker (1)
appendln(result, "set bmargin 4"); // margin 4 -> 76 appendln(result, "set bmargin 4"); // margin 4 -> 76
appendfln(result, "set tics font \",%d\"", YAxisTicks.TICKS_FONT_SIZE); appendfln(result, "set tics font \",%d\"", GnuplotSettings.TICKS_FONT_SIZE);
appendln(result, YAxisTicks.computeYTicks(settings, dataSeries)); appendln(result, YAxisTicks.computeYTicks(settings, dataSeries));
} else { } else {
appendfln(result, "set tics font \",%d\"", YAxisTicks.TICKS_FONT_SIZE); appendfln(result, "set tics font \",%d\"", GnuplotSettings.TICKS_FONT_SIZE);
appendln(result, YAxisTicks.computeYTicks(settings, dataSeries)); appendln(result, YAxisTicks.computeYTicks(settings, dataSeries));
} }

View File

@@ -13,6 +13,7 @@ public class GnuplotSettings {
public final static int GNUPLOT_BOTTOM_MARGIN = 76; // The bottom margin configured for gnuplot public final static int GNUPLOT_BOTTOM_MARGIN = 76; // The bottom margin configured for gnuplot
public final static int GNUPLOT_TOP_BOTTOM_MARGIN = GNUPLOT_TOP_MARGIN + GNUPLOT_BOTTOM_MARGIN; public final static int GNUPLOT_TOP_BOTTOM_MARGIN = GNUPLOT_TOP_MARGIN + GNUPLOT_BOTTOM_MARGIN;
public final static int GNUPLOT_LEFT_RIGHT_MARGIN = GNUPLOT_LEFT_MARGIN+GNUPLOT_RIGHT_MARGIN; public final static int GNUPLOT_LEFT_RIGHT_MARGIN = GNUPLOT_LEFT_MARGIN+GNUPLOT_RIGHT_MARGIN;
public static final int TICKS_FONT_SIZE = 12;
private String terminal = "png"; private String terminal = "png";
private int height = 1200; private int height = 1200;

View File

@@ -185,6 +185,7 @@ public class Plotter {
gnuplotSettings.getxAxisSettings().setRotateXAxisLabel(rotateX); gnuplotSettings.getxAxisSettings().setRotateXAxisLabel(rotateX);
gnuplotSettings.getxAxisSettings().setFrom(formattedMinDate); gnuplotSettings.getxAxisSettings().setFrom(formattedMinDate);
gnuplotSettings.getxAxisSettings().setTo(formattedMaxDate); gnuplotSettings.getxAxisSettings().setTo(formattedMaxDate);
gnuplotSettings.getxAxisSettings().setDateTimeRange(dateTimeRange);
} }
private static CsvSummary toCsvDeduplicated(final GroupResult groupResult, final Path tmpDir, private static CsvSummary toCsvDeduplicated(final GroupResult groupResult, final Path tmpDir,

View File

@@ -1,76 +1,86 @@
package org.lucares.recommind.logs; package org.lucares.recommind.logs;
import org.lucares.pdb.api.DateTimeRange;
public class XAxisSettings { public class XAxisSettings {
// set xdata time // set xdata time
private boolean xDataTime = true; private boolean xDataTime = true;
// set format for x-axis
private String formatX = "%Y-%m-%d\\n%H:%M:%S";
// set xlabel // set format for x-axis
private String xlabel = "Time"; private String formatX = "%Y-%m-%d\\n%H:%M:%S";
// set xtics rotation in degree // set xlabel
private int rotateXAxisLabel = 0; private String xlabel = "Time";
private String from; // set xtics rotation in degree
private String to; private int rotateXAxisLabel = 0;
public boolean isxDataTime() { private String from;
return xDataTime; private String to;
}
public void setxDataTime(boolean xDataTime) { private DateTimeRange dateTimeRange;
this.xDataTime = xDataTime;
}
public String getFormatX() { public boolean isxDataTime() {
return formatX; return xDataTime;
} }
public void setFormatX(String formatX) { public void setxDataTime(boolean xDataTime) {
this.formatX = formatX; this.xDataTime = xDataTime;
} }
public String getXlabel() { public String getFormatX() {
return xlabel; return formatX;
} }
public void setXlabel(String xlabel) { public void setFormatX(String formatX) {
this.xlabel = xlabel; this.formatX = formatX;
} }
public int getRotateXAxisLabel() { public String getXlabel() {
return rotateXAxisLabel; return xlabel;
} }
public void setRotateXAxisLabel(int rotateXAxisLabel) { public void setXlabel(String xlabel) {
this.rotateXAxisLabel = rotateXAxisLabel; this.xlabel = xlabel;
} }
public String getFrom() { public int getRotateXAxisLabel() {
return from; return rotateXAxisLabel;
} }
public void setFrom(String from) { public void setRotateXAxisLabel(int rotateXAxisLabel) {
this.from = from; this.rotateXAxisLabel = rotateXAxisLabel;
} }
public String getTo() { public String getFrom() {
return to; return from;
} }
public void setTo(String to) { public void setFrom(String from) {
this.to = to; this.from = from;
} }
@Override public String getTo() {
public String toString() { return to;
return "XAxisSettings [xDataTime=" + xDataTime + ", formatX=" + formatX }
+ ", xlabel=" + xlabel + ", rotateXAxisLabel="
+ rotateXAxisLabel + ", from=" + from + ", to=" + to + "]"; public void setTo(String to) {
} this.to = to;
}
public void setDateTimeRange(DateTimeRange dateTimeRange) {
this.dateTimeRange = dateTimeRange;
}
public DateTimeRange getDateTimeRange() {
return dateTimeRange;
}
@Override
public String toString() {
return "XAxisSettings [xDataTime=" + xDataTime + ", formatX=" + formatX + ", xlabel=" + xlabel
+ ", rotateXAxisLabel=" + rotateXAxisLabel + ", from=" + from + ", to=" + to + ", dateTimeRange="+dateTimeRange+"]";
}
} }

View File

@@ -0,0 +1,76 @@
package org.lucares.recommind.logs;
import java.util.concurrent.TimeUnit;
import org.lucares.collections.LongList;
import org.lucares.pdb.api.DateTimeRange;
public class XAxisTimeTicks {
public static String computeXTimeIncrements(GnuplotSettings settings) {
DateTimeRange dateTimeRange = settings.getxAxisSettings().getDateTimeRange();
final long startEpochMilli = dateTimeRange.getStartEpochMilli();
final long endEpochMilli = dateTimeRange.getEndEpochMilli();
final long rangeInMs = endEpochMilli - startEpochMilli + 1;
int widthInPx = settings.getWidth() - GnuplotSettings.GNUPLOT_LEFT_RIGHT_MARGIN;
final long maxLabels = widthInPx / (GnuplotSettings.TICKS_FONT_SIZE * 8);
final long tickIncrement = roundToTickIncrement(rangeInMs / maxLabels);
return "set xtics "+ tickIncrement/1000.0;
}
private static long roundToTickIncrement(long milliseconds) {
LongList increments = LongList.of(
100,
200,
500,
TimeUnit.SECONDS.toMillis(1),
TimeUnit.SECONDS.toMillis(2),
TimeUnit.SECONDS.toMillis(5),
TimeUnit.SECONDS.toMillis(10),
TimeUnit.SECONDS.toMillis(15),
TimeUnit.SECONDS.toMillis(30),
TimeUnit.MINUTES.toMillis(1),
TimeUnit.MINUTES.toMillis(2),
TimeUnit.MINUTES.toMillis(5),
TimeUnit.MINUTES.toMillis(10),
TimeUnit.MINUTES.toMillis(15),
TimeUnit.MINUTES.toMillis(30),
TimeUnit.HOURS.toMillis(1),
TimeUnit.HOURS.toMillis(2),
TimeUnit.HOURS.toMillis(3),
TimeUnit.HOURS.toMillis(6),
TimeUnit.HOURS.toMillis(12),
TimeUnit.HOURS.toMillis(18),
TimeUnit.DAYS.toMillis(1),
TimeUnit.DAYS.toMillis(2),
TimeUnit.DAYS.toMillis(3),
TimeUnit.DAYS.toMillis(4),
TimeUnit.DAYS.toMillis(5),
TimeUnit.DAYS.toMillis(6),
TimeUnit.DAYS.toMillis(7),
TimeUnit.DAYS.toMillis(14),
TimeUnit.DAYS.toMillis(30),
TimeUnit.DAYS.toMillis(90),
TimeUnit.DAYS.toMillis(180),
TimeUnit.DAYS.toMillis(365),
TimeUnit.DAYS.toMillis(365*2),
TimeUnit.DAYS.toMillis(365*5),
TimeUnit.DAYS.toMillis(365*10),
TimeUnit.DAYS.toMillis(365*20)
);
for ( int i = 0; i < increments.size(); i++) {
if (increments.get(i) > milliseconds) {
return increments.get(i);
}
}
return TimeUnit.DAYS.toMillis(365*10);
}
}

View File

@@ -13,7 +13,6 @@ import java.util.concurrent.TimeUnit;
class YAxisTicks { class YAxisTicks {
static final int TICKS_FONT_SIZE = 12;
public static String computeYTicks(final GnuplotSettings settings, final Collection<DataSeries> dataSeries) { public static String computeYTicks(final GnuplotSettings settings, final Collection<DataSeries> dataSeries) {
String result = ""; String result = "";
@@ -91,7 +90,7 @@ private static String computeLinearYTicks(final long height, final long yRangeMi
final long plotHeight = height - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN; // sum of top/bottom margin, see final long plotHeight = height - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN; // sum of top/bottom margin, see
// marker (1) // marker (1)
final long maxLabels = plotHeight / (TICKS_FONT_SIZE * 5); final long maxLabels = plotHeight / (GnuplotSettings.TICKS_FONT_SIZE * 5);
final long range = yRangeMax - yRangeMin; final long range = yRangeMax - yRangeMin;
final long msPerLabel = roundToLinearLabelSteps(range / maxLabels); final long msPerLabel = roundToLinearLabelSteps(range / maxLabels);