I have a Columndiagram. This diagram may have Y values from 0 to very larg numbers.
My problem:
When the Y values are small (from my observation smaller than 7), the chart shows double values. (for example: 0, 0.01, 0.02 ... , 0.1), which is in my case not correct.
What I want:
force the Y Axis to use integers.
What I cannot do:
I cannot define a seperator for the Y axis and set its Step to 1. Becuase if I do it, I'll have Step= 1 even if the values are very large, which is not desirable.
Is there any workaround for it?
By default, the library decides the step (when you don't force it) with the CalculateSeparator() method (for more info see this), since the library should also allow you to plot decimal values, it can not be forced to display only integers.
A simple work around I can think of, is to force the Axis.MaxValue property.
In your case, when your values are less than 7, I would force the Axis.MaxValue to 10 (or any other value that works fine for you), then when the data in your chart is greater than 7, you can set Axis.MaxValue back to double.NaN and the library will calculate this limit by it self.
I hope it helps you.
Related
I am looking for suggestions as how to create plots similar to GitHub punch cards with JFreeChart. E.g.
I guess it's some variant of a heat map, or two dimensional histogram.
Ok, so I found XYBubbleRenderer which looks like a good starting point.
create a MatrixSeries with rows = 7, columns = 24
fill in the frequencies accordingly. I found it useful to normalise the values first to 0...1, then take the square root (smaller values have a bit better visible circles), then multiply by 0.5 (otherwise the circles are too large)
create a MatrixSeriesCollection from that
use ChartFactory.createBubbleChart
the circle outline can only be removed via plot.getRenderer.setSeriesOutlinePaint(0, new Color(0, 0, 0, 0))
ensure integer tick units on both axis
x-axis range -0.5 to 23.5, y-axis range -0.5 to 6.5 (or 0.5 to 7.5 if you use Calendar.DAY_OF_WEEK)
custom NumberTickUnit for the y-axis to use day labels instead of numbers
The result:
In addition to XYBubbleRenderer, suggested here, also consider a suitable implementation of TableCellRenderer and Icon, illustrated here.
I have a standard 50-state map built with d3 in which I'm dynamically coloring states according to various datasets. Whatever the dataset, the values are normalized on a scale of 0 to 1, where 1 corresponds to the state with the highest value. I'm looking for a way to calculate the shade of the state using the value of the normalized data point.
In the past, I've chosen a base color that I like -- say, #900 -- and set the fill of each state to that color and the opacity to the normalized value. This works okay save for two problems:
when the canvas has a background color, it requires drawing a blank white state beneath every shaded state; and
fading out colors this way can look pasty
But I really like being able to set the color dynamically rather than dealing with bins for the data and preset arrays of RGB values for the gradient. So I'm wondering if there's a better way. I can take care of conversion if an alternate color system would work better.
d3 has a baked-in HSL converter, so I tried this:
// 0 <= val <= 1
function colorize(val) {
// nudge in the extremes
val = 0.2 + 0.6 * val;
return d3.hsl(0, val, 1 - val);
}
It works okay -- This is a map of fishing jobs, which are most prevalent in Maine and Oregon -- but I suspect there's a better way. Ideas?
I like what you did actually, but if you wish to do something different, you can always do a D3 scale. For example:
var scale = d3.scale.linear().domain([rangeMin, rangeMid,
rangeMax]).range(["#Color1","#Color2","#Color3"]);
And then set each state by
return scale(dataValue);
You can set your rangeMin and rangeMax variables to be the minimum and maximum values of your data. The median number, rangeMid, that I added is optional. I would suggest using this if you would like some variety in your color. I have used this scale feature to make a word frequency heatmap that came out pretty nice. I hope that I was able to help in some way!
Note: I used this with css hex values, but I believe RGB and HSL could also work.
I have a line chart in ssrs. Whenever the highest line values are 1 or 2 instead of getting a scale of 0,1,2 which is what I want, I get 0,1,1,2,2. This dosn't make sense especially because the number values are not decimals and are unformatted.
Please help.
The Expression for the vertical axis Interval should be below expressions.
If your value is sum
=IIF(Max(Sum(Fields!Item.Value))<20,1,"Auto")
If your value is count
=IIF(Max(Count(Fields!Item.Value))<20,1,"Auto")
Note: I used 20 as the above that the Auto will work good. Make according to your requirement.
Sounds like there is formatting on the vertical axis: That it's actually trying to show 0, .5, 1.0, 1.5, & 2 but after rounding that comes out as 0,1,1,2,2
You should change the vertical axis interval from "Auto" to 1:
I understand that this is quite old post. Still I wanted to reply..
I faced the same issue on column chart when the scale was of small range....
So I used the following expression in axis properties->interval
=IIF(Max(Fields!count_Items.Value)>=6,0,1) - [note: here 0 means - Auto interval]
Hope this answer helps someone. :)
The problem here is not only the interval but also the maximum value of the range that the axis uses. You can set the value for the Interval with this type of expression IIF(Max(Sum(Fields!Item.Value))<20,1,"Auto") but the axis can still make the scale too large. It then tends to fill in with decimals or if you suppress decimals you get repeating integers.
Use a custom code like this:
Public Shared Function AxisRange(ByVal Number As Double) As String
Dim RangeString as String
If Number <=5 Then
RangeString ="5"
Else If Number <=10 Then
RangeString = "10"
Else RangeString = "Auto"
End If
Return RangeString
End Function
In the Maximum value of the range use an expression like:
=code.AxisRange(Max(Fields!Field.Value))
By doing this you force the maximum value of the range to be a similar size to the maximum value in your chart. This solves the problem.
I've got a fairly simple PathGeometry:
M567764.539,5956314.087L567815.077,5956179.775L567821.625,5956182.314L567773.425,5956311.248L567858.513,5956349.923L567950.858,5956392.466L567949.039,5956399.843L567942.252,5956396.685L567873.018,5956364.467L567799.816,5956330.421L567771.226,5956317.186L567764.539,5956314.087
Now when I query the PathGeometry.Bounds attribute for this data I get the following bounds:
567764.5625,5956180 567950.875,5956400
The expected bounds would be:
567764.539,5956179.775 567950.858,5956399.843
My main problem: the bounds are smaller than the geometry, so parts of the geometry might be outside the bounds.
I create the PathGeometry and show the bounds like this:
PathGeometry geo = PathGeometry.CreateFromGeometry(Geometry.Parse("M567764.539,5956314.087L567815.077,5956179.775L567821.625,5956182.314L567773.425,5956311.248L567858.513,5956349.923L567950.858,5956392.466L567949.039,5956399.843L567942.252,5956396.685L567873.018,5956364.467L567799.816,5956330.421L567771.226,5956317.186L567764.539,5956314.087"));
System.Diagnostics.Trace.WriteLine(geo.Bounds);
What am I doing wrong?
And, more important, how do I get the right bounds for a PathGeometry?
At some point, I would think WPF has to convert to single point for rendering, and I wonder if the value of Bounds is based off of the rendered result. In this case, you're probably seeing a precision limitation based off of the large numbers you're using. I noticed that your Y values were a factor of 10 larger than X, and coincidentally the error was also a factor of 10 larger than the error in X.
If it's possible to subtract off the min X and Y before creating the PathGeometry, I think you'll get better numbers. Assuming you're displaying the PathGeometry, you could place it in a Canvas and apply Canvas.Left/Top to your values to get the right offset on screen. To get the correct bounds, you would then add the Top/Left offsets to the result of your Bounds.
Just a reminder that there's a bit of speculation in this answer. I haven't looked at the innerworkings of Bounds, but the relative error seems to point to a conversion to and from floats.
I think you're seeing the imprecision due fact that the numbers PathGeometry is made up of large floating point numbers.
I'm not sure if you'll be able to obtain the precision that you need.
You will probably have to compare the bounds using an acceptable tolerance, like:
bool isMatch = (Math.Abs(MyPath.Bounds.X - ExpectedBounds.X) < TOLERANCE);
where you can set the TOLERANCE to 0.25 or something.
When rendering huge visuals in WPF, the visual gets distorted and more distorted with increasing coordinates. I assume that it has something to do with the floating point data types used in the render pipeline, but I'm not completely sure. Either way, I'm searching for a practical solution to solve the problem.
To demonstrate what I'm talking about, I created a sample application which just contains a custom control embedded in a ScrollViewer that draws a sine curve.
You can see here that the drawing is alright for double values <= 2^24 (in this case the horizontal coordinate value), but from that point on it gets distorted.
The distortion gets worse at 2^25 and so the distortion continues to increase with every additional bit until it just draws some vertical lines.
For performance reasons I'm just drawing the visible part of the graph, but for layouting reasons I cannot "virtualize" the control which would make this problem obsolete. The only solution I could come up with is to draw the visible part of the graph to a bitmap, and then render the bitmap at the appropriate point - but there I have again the precision problem with big values, as I cannot accurately place the bitmap at the position where I need it.
Does anybody have an idea how to solve this?
It is not WPF's fault.
Floating point numbers get less and less precise the farther from zero they are - it is a cost of stuffing enormous data range (-Inf, +Inf) into 32 (float) / 64 (double) bits of data space. Floats actually become less precise than integer at around 2^30.
64bit integers have constant spacing (1), but have limited range of −9,223,372,036,854,775,808 to +9,223,372,036,854,775,807.
You may also consider using Decimal type (which however has also limited value range).
(update: oh didnt see how old this post was... i guess i clicked the wrong filter button in stack overflow...)
The relative precision is relevant here. So just saying "look 2^24 is fine and 2^25 is not" is not enough information. You said it is a sin, thus I guess y-axis max and min never changes between those pictures. So y-axis doesnt matter. Furthermore the x-step size stays the same, i guess? But you did not tell us the sin period length or the x-step size, you chose. That is relevant here. The relative precision of the x-size steps becomes worse when you go to higher x-values, because the x-step-size becomes too small relativly to the x-value itself.
precision of c# floating point types:
https://learn.microsoft.com/de-de/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types
example:
x-step size = 1.
x = 1 (no problem)
x = 1000 (no problem)
x = >2^23 (32 bit starts to get problems with step size = 1; 64 bit no problems yet)
x = >2^52 (64 bit starts to get problems with step size = 1)