rickshaw graph x,y pair with y to be string - graph

I am using rickshaw graph to visualize my time series.
In the tutorial, we need data pair (x, y), where y has to be type double or int to plot like:
var data = [ { x: -1893456000, y: 92228531 }, { x: -1577923200, y: 106021568 }, { x: -1262304000, y: 123202660 } ];
is there anyway I can put string at y, like
var data = [ { x: -1893456000, y: "ID12" }, { x: -1577923200, y: "ID10" }, { x: -1262304000, y: "ID8" } ];
because I want to use the example http://code.shutterstock.com/rickshaw/examples/hover.html
to show the timeseries of IDs when mouse over.
Thanks

I dont think it works this way. But what you can do is, use a numeric Y value (eg 12 for ID12) and use a yFormatter in your hoverDetail:
var hoverDetail = new Rickshaw.Graph.HoverDetail({graph: graph,
xFormatter: function(x) {return x},
yFormatter: function(y) {return "ID"+y}
});
I think this should do the Trick

Related

Increase size of one of the series in R highchart

I'm trying to show a line and % changes in a single highchart plot, but the changes are very little and It can't be seen in the plot. I made a simplified code to show my problem:
a <- c(300,200, 400, 10, 40, 80)
b <- c(0.8, 2, -2, -1.5, -1.1, 2)
d<-cbind(a,b)
dt <- seq(as.Date("2018-01-01"), as.Date("2018-01-06"), by = "days")
ts <- xts(d, dt )
highchart(type="stock") %>%
hc_add_series(ts$a,
type = "line",
color="black") %>%
hc_add_series(ts$b,
type = "lollipop",
color="red")
I need to increase the size of "ts$b" in the plot, how can I do it? I also tried with two axis, but It seems doesn't solve the problem.
I see two solutions to achieve that.
The first you mentioned - using two yAxis and manipulating their height and top distance.
Example JS code:
yAxis: [{
height: '90%',
opposite: false
},
{
visible: false,
top: '83%',
height: '15%',
}
]
Demo:
https://jsfiddle.net/BlackLabel/0826r7sh/
Another way is using a modified logarithmic axis. Negative values can't be plotted on a log axis, because by nature, the axis will only show positive values. In that case you need to use a custom extension according to the following thread:
Highcharts negative logarithmic scale solution stopped working
(function(H) {
H.addEvent(H.Axis, 'afterInit', function() {
const logarithmic = this.logarithmic;
if (logarithmic && this.options.custom.allowNegativeLog) {
// Avoid errors on negative numbers on a log axis
this.positiveValuesOnly = false;
// Override the converter functions
logarithmic.log2lin = num => {
const isNegative = num < 0;
let adjustedNum = Math.abs(num);
if (adjustedNum < 10) {
adjustedNum += (10 - adjustedNum) / 10;
}
const result = Math.log(adjustedNum) / Math.LN10;
return isNegative ? -result : result;
};
logarithmic.lin2log = num => {
const isNegative = num < 0;
let result = Math.pow(10, Math.abs(num));
if (result < 10) {
result = (10 * (result - 1)) / (10 - 1);
}
return isNegative ? -result : result;
};
}
});
}(Highcharts));
.
yAxis: {
type: 'logarithmic',
custom: {
allowNegativeLog: true
}
},
Demo
https://jsfiddle.net/BlackLabel/nw6osucm/

heatmapGridSeries overlay over line chart

I came Across heatmapGridSeries in lightning chart , I just want to know if this is possible.
Please Check above image , I have lineseries with one axis.. and i want this color bands above the line series with opacity.
For example
if I add value to the heatmapGridSeries from 0 to 100 , it should automatically show orange.. from 100 to 200 it should show green and so on.
Can be done, but shouldn't be a very practical usage case for heatmaps.
Paletted/gradient series background or bands should give nicer results.
Here's a snippet that looks like your picture (without the line series), and also adds a single Band so you can see how they behave a bit differently.
Transparency can be added after R,G,B.
const {
lightningChart,
LUT,
PalettedFill,
ColorRGBA,
emptyLine,
SolidFill,
AxisScrollStrategies,
} = lcjs
const chart = lightningChart().ChartXY()
const line = chart.addLineSeries()
const heatmap = chart.addHeatmapScrollingGridSeries({
scrollDimension: 'columns',
resolution: 1,
step: {
x: 1,
y: 1,
},
})
const transparency = 100
heatmap
.setFillStyle(new PalettedFill({
lut: new LUT({
steps: [
{value: 0, color: ColorRGBA(255,127,39, transparency)},
{value: 1, color: ColorRGBA(181,230,29, transparency)},
{value: 2, color: ColorRGBA(112,146,190, transparency)},
{value: 3, color: ColorRGBA(255,242,0, transparency)},
{value: 4, color: ColorRGBA(237,28,36, transparency)}
]
})
}))
.setPixelInterpolationMode('disabled')
.setWireframeStyle(emptyLine)
chart.getDefaultAxisX().setInterval(-10, 0).setScrollStrategy(AxisScrollStrategies.progressive)
line.add({x:0,y:0})
let x = 1
setInterval(() => {
const y = Math.random()
const p = {x, y}
line.add(p)
const iColor = x % 5
heatmap.addIntensityValues([[iColor]])
x += 1
}, 1000)
<script src="http://unpkg.com/#arction/lcjs#3.1.0/dist/lcjs.iife.js"></script>

What does spread operator in type declaration do in Flow?

If I have two objects of partially matching shapes like
const point2d = { x: 0, y: 0 };
const point3d = { x: 0, y: 0, z: 0 };
then the valid type declaration in Flow would be
type Point2D = { x: number, y: number };
type Point3D = Point2D & { z: number };
At first, I tried to use the object spread operator and hit a problem quite soon because notation like
type Point3D = { ...Point2D, z: number };
is passed as valid but does not achieve the goal because in the end both x and y properties are missing from the Point3D type.
For example, I can do this with spread notation (which is wrong):
type Point2D = { x: number, y: number };
type Point3D = { ...Point2D, z: number };
const point2d: Point2D = { x: 0, y: 0 };
const point3d: Point3D = { y: 0, z: 0 }; // No errors
but cannot miss the x property in object declaration with type intersection notation:
type Point2D = { x: number, y: number };
type Point3D = Point2D & { z: number };
const point2d: Point2D = { x: 0, y: 0 };
const point3d: Point3D = { y: 0, z: 0 }; // Cannot assign object literal to `point3d` because property `x` is missing in object literal [1] but exists in `Point2D` [2].
Note that both cases are not exact shapes.
Is Flow's behavior in case of spread notation intentional in this case? Am I missing something?
See this issue.
The short version is that you can resolve basically all of these sorts of issues by making your objects exact. In general I've found that you'll have a much easier time with object types when making them exact as a rule unless you really don't want them to be exact for some reason. Also, $ReadOnly where applicable. Try

class vs type in Flow

In Flow, why would one use a class versus a type?
type Point = {x: number; y: number};
class Point = {x: number; y: number};
In your example, a type is all you need.
But if you want to define methods, you'll want to use a class.
class Point {
x: number;
y: number;
constructor(x, y) {this.x = x; this.y = y;}
distance_from_origin(): number { /* code goes here */ }
angle_from_origin(): number { /* code goes here */ }
}
p: Point = new Point(2, 3);
d = p.distance_from_origin()
Types are a flow features for compile-time checking, to help you catch errors in your code. They are entirely stripped from the code before running it.
Classes aren't a Flow feature at all (Although Flow understands classes - every class you create also defines a Flow type) - they're a feature of ES6, the next version of JavaScript. Babel, the same program that strips Flow types from your code to make it valid JavaScript, can also convert your classes to ES5-compatible code.
Classes provide nominal typing, while object types provide structural typing.
Suppose I wanted to introduce a Vector type with x and y fields. When I go to create my add(p: Point, v: Vector): Point function, structural typing proves inadequate, e.g.
type Point = {x: number, y: number};
type Vector = {x: number, y: number};
function add(p: Point, v: Vector): Point {
return {x: p.x + v.x, y: p.y + v.y};
}
const p1: Point = {x:0, y:5};
const p2: Point = {x:2, y:3};
const v: Vector = add(p1, p2); // This is not an error in Flow
Contrast that against the nominally typed version with classes:
class Point { x: number; y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
class Vector { x: number; y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
function add(p: Point, v: Vector): Point {
return new Point(p.x + v.x, p.y + v.y);
}
const p1: Point = new Point(0, 5);
const p2: Point = new Point(2, 3);
const v: Vector = add(p1, p2); // Error: p2 isn't a Vector
(In reality you'd probably attach add as a method on the point class, but I've left it separate for parallel structure with the object type example.)
Note that you can use a tag field to get some semblance of nominal typing from object types, e.g.
type Point = { tag: "point", x: number y: number };
type Vector = { tag: "vector", x: number, y: number };
If your class doesn't have any methods, then I would suggest that this is the way to go.
As seen in the documentation, flow treats objects and classes differently. (And even if you are transpiring to ES5, flow checking happens before that.)
A class is compared by name. An object type is compared by structure.
In fact, the type alias is just a shorter way of writing the type structure annotation. It is like a variable containing the longer expression.
type A = {wow: number}
type B = {wow: number}
let a:A = {wow: 1}
let b:B = {wow: 2}
; [a, b] = [b, a] // fine
console.log(a, b) // > { wow: 2 } { wow: 1 }
class C {
constructor (x: number) { this.wow = x }
wow: number
}
class D {
constructor (x: number) { this.wow = x }
wow: number
}
let c:C = new C(3)
let d:D = new D(4)
c = d // ERROR: D This type is incompatible with C
d = b // ERROR: object type This type is incompatible with D
As you can see, two classes with identical structure are not compatible.
NOTE: There are ways to make different classes compatible, eg Union Types or Interfaces

Object spread operator in Flow

I want to copy an object while changing only a single property. Without Flow, I could do this using the object spread operator like this:
class Point { x: number = 10; y: number = 10; }
const p1 = new Point();
const p2 = {...p1, y: 5};
But when I add type annotations to p1 and p2 like this:
const p1 = new Point();
const p2 = {...p1, y: 5};
I get the following error:
11: const p2:Point = {...p1, y: 5};
^^^^^^^^^^^^^ object literal. This type is incompatible with
11: const p2:Point = {...p1, y: 5};
^^^^^ Point
How would I achieve this type of operation in a type safe way in Flow?
As an example, in Elm, I can do this:
p2 = { p1 | y = 5 }
There must be some equivalent in Flow.
When you use object spread, you don't get an exact copy of an object. Instead, you get a plain object with all source object's properties copied. So, Flow is right here, p2 is not Point. Try this instead:
type Point = { x: number, y: number };
const p1: Point = { x: 10, y: 10 };
const p2: Point = { ...p1, y: 5 };
Explanation: class does not work because it uses nominal typing but type works because that uses structural typing.
If you (really) need a class instead of a type alias you can simulate the Elm syntax p2 = { p1 | y = 5 } by defining a constructor with only one argument
export class Point {
x: number = 10;
y: number = 10;
constructor(fields?: { x: number, y: number }) {
Object.assign(this, fields)
}
}
const p1 = new Point()
const p2: Point = new Point({...p1, y: 5})

Resources