in src/infertypes.ts [100:141]
export function scale_pixels_range(scale: any, extents: [number, number]): ScaleDomainRange {
/**
* Converts scale range in pixels back to domain (aka inverts the scale)
*/
console.assert(scale, "No scale provided to `scale_pixels_range`");
console.assert(extents, "No extents provided to `scale_pixels_range`", extents);
const scaleToNorm = d3.scaleLinear().domain(scale.range()).range([0, 1]);
const normalized = [scaleToNorm(extents[0]), scaleToNorm(extents[1])] as [number, number];
switch (scale.hip_type as ParamType) {
case ParamType.CATEGORICAL:
const domain: Array<string> = scale.domain();
const firstIdx = Math.ceil(Math.min(normalized[0], normalized[1]) * (domain.length - 1));
const lastIdx = Math.floor(Math.max(normalized[0], normalized[1]) * (domain.length - 1) + 1);
return {
"type": scale.hip_type,
"brush_extents_normalized": normalized,
"values": domain.slice(firstIdx, lastIdx),
};
case ParamType.NUMERIC:
case ParamType.NUMERICLOG:
case ParamType.NUMERICPERCENTILE:
case ParamType.TIMESTAMP:
const pxlRange: Array<number> = scale.range();
// Small hack to make sure we can always select the extrema
// (considering loss of precision in computations, especially for logscale)
for (var i = 0; i < 2; ++i) {
if (extents[i] == Math.min(...pxlRange)) {
--extents[i];
}
if (extents[i] == Math.max(...pxlRange)) {
++extents[i];
}
}
const range = [scale.invert(extents[0]), scale.invert(extents[1])] as [number, number];
return {
"type": scale.hip_type,
"brush_extents_normalized": normalized,
"range": range,
"include_infnans": extents[0] <= scale(Infinity) && scale(Infinity) <= extents[1]
};
}
}