/
log_ticker.ts
91 lines (75 loc) · 2.84 KB
/
log_ticker.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import {TickSpec} from "./ticker"
import {AdaptiveTicker} from "./adaptive_ticker"
import {range} from "core/util/array"
import * as p from "core/properties"
export namespace LogTicker {
export type Attrs = p.AttrsOf<Props>
export type Props = AdaptiveTicker.Props
}
export interface LogTicker extends LogTicker.Attrs {}
export class LogTicker extends AdaptiveTicker {
override properties: LogTicker.Props
constructor(attrs?: Partial<LogTicker.Attrs>) {
super(attrs)
}
static init_LogTicker(): void {
this.override<LogTicker.Props>({
mantissas: [1, 5],
})
}
override get_ticks_no_defaults(data_low: number, data_high: number, _cross_loc: number, desired_n_ticks: number): TickSpec<number> {
const num_minor_ticks = this.num_minor_ticks
const minor_ticks = []
const base = this.base
const log_low = Math.log(data_low) / Math.log(base)
const log_high = Math.log(data_high) / Math.log(base)
const log_interval = log_high - log_low
let ticks: number[]
if (!isFinite(log_interval)) {
ticks = []
} else if (log_interval < 2) { // treat as linear ticker
const interval = this.get_interval(data_low, data_high, desired_n_ticks)
const start_factor = Math.floor(data_low / interval)
const end_factor = Math.ceil(data_high / interval)
ticks = range(start_factor, end_factor + 1)
.filter((factor) => factor != 0)
.map((factor) => factor*interval)
.filter((tick) => data_low <= tick && tick <= data_high)
if (num_minor_ticks > 0 && ticks.length > 0) {
const minor_interval = interval / num_minor_ticks
const minor_offsets = range(0, num_minor_ticks).map((i) => i*minor_interval)
for (const x of minor_offsets.slice(1)) {
minor_ticks.push(ticks[0] - x)
}
for (const tick of ticks) {
for (const x of minor_offsets) {
minor_ticks.push(tick + x)
}
}
}
} else {
const startlog = Math.ceil(log_low * 0.999999)
const endlog = Math.floor(log_high * 1.000001)
const interval = Math.ceil((endlog - startlog) / 9.0)
ticks = range(startlog-1, endlog+1, interval)
.map((i) => base**i)
if (num_minor_ticks > 0 && ticks.length > 0) {
const minor_interval = base**interval / num_minor_ticks
const minor_offsets = range(1, num_minor_ticks+1).map((i) => i*minor_interval)
for (const x of minor_offsets) {
minor_ticks.push(ticks[0] / x)
}
minor_ticks.push(ticks[0])
for (const tick of ticks) {
for (const x of minor_offsets) {
minor_ticks.push(tick * x)
}
}
}
}
return {
major: ticks.filter((tick) => data_low <= tick && tick <= data_high),
minor: minor_ticks.filter((tick) => data_low <= tick && tick <= data_high),
}
}
}