Skip to content

Commit f20d2d1

Browse files
committed
Added a heatmap function for all Collections. It requires an O(n) scan to determine the row locations, but doesn't require copying in to a RAC (which would also be O(n), *and* consume memory to boot).
Allows direct heat-mapping of Strings (is that useful?). It would be nice if all charts did this and namespaced it under ".plots" or something (see ".lazy" in the Swift stdlib).
1 parent 725ba00 commit f20d2d1

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

Sources/SwiftPlot/Heatmap.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,31 @@ extension Sequence where Element: Sequence {
165165
}
166166
}
167167

168+
extension Collection {
169+
170+
/// Returns a heatmap of this collection's values, generated by slicing rows with the given width.
171+
/// - parameters:
172+
/// - width: The width of the heatmap to generate. Must be greater than 0.
173+
/// - interpolator: A function or `KeyPath` which maps values to a continuum between 0 and 1.
174+
/// - returns: A heatmap plot of the collection's values.
175+
/// - complexity: O(n). Consider though, that rendering a heatmap or copying to a `RamdomAccessCollection`
176+
/// is also at least O(n), and this does not copy the data.
177+
public func heatmap(width: Int, interpolator: Interpolator<Element>) -> Heatmap<[SubSequence]> {
178+
precondition(width > 0, "Cannot build a histogram with zero or negative width")
179+
var rows = [SubSequence]()
180+
var rowStart = startIndex
181+
while rowStart != endIndex {
182+
guard let rowEnd = index(rowStart, offsetBy: width, limitedBy: endIndex) else {
183+
rows.append(self[rowStart..<endIndex])
184+
break
185+
}
186+
rows.append(self[rowStart..<rowEnd])
187+
rowStart = rowEnd
188+
}
189+
return rows.heatmap(interpolator: interpolator)
190+
}
191+
}
192+
168193
extension RandomAccessCollection {
169194

170195
/// Returns a heatmap of this collection's values, generated by slicing rows with the given width.

Tests/SwiftPlotTests/Heatmap/heatmap.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ final class HeatmapTests: SwiftPlotTestCase {
3232
for _ in 0..<10_000 { d.append(.random(in: 0..<255)) }
3333
// var hm3 = d.heatmap(width: 100, interpolator: .linear)
3434

35-
var hm3 = Array("THIS IS SWIFPLOT!!!! Woo let's see what this looks like :)")
36-
.heatmap(height: 1, interpolator: .linearByKeyPath(\.asciiValue!))
35+
var hm3 = "THIS IS SWIFPLOT!!!! Woo let's see what this looks like :)"
36+
.heatmap(width: 5, interpolator: .linearByKeyPath(\.asciiValue!))
3737
// var hm3 = Array(stride(from: Float(0), to: 1, by: 0.001)).heatmap(width: 10, interpolator: .linear)
38+
// var hm3 = "😘 you too".utf8.heatmap(width: 5, interpolator: .linear)
3839
hm3.colorMap = .viridis
3940

4041

0 commit comments

Comments
 (0)