I used CorePlot to implement real-time plotting but I have two different data in different sampling rate.
My ECG sampling rate is 250Hz and Resp sampling rate is 50Hz. I want to do the real-time plotting in the same graph.
At first, I tried to modify the array in different count, but when it goes to numberForPlot
function, the error happened. It seems like the recordIndex
should be the same count.
How should I do? Should I modify the CorePlot method? Or just modify my code?
Thank you!
func plotChartTest(ecg:[Int], resp:[Int], packNum: Int){
if (packNum == 1){
...
self.newGraph.addPlot(respLinePlot)
self.newGraph.addPlot(ecgLinePlot)
// Add some initial data
for i in 0 ..< tempEcgArray.count {
let x = Double(i) * 0.01
let y = 0.0
//let y = Double(fecg[i])/65535.0 + 0.05
let dataPoint: plotDataType = [.X: x, .Y:y]
self.ecgDataForPlot.append(dataPoint)
//ecgContentArray.append(dataPoint)
}
//self.ecgDataForPlot = ecgContentArray
for i in 0 ..< tempRespArray.count {
let x = Double(i) * 0.01
let y = 0.0
let dataPoint: plotDataType = [.X: x, .Y: y]
self.respDataForPlot.append(dataPoint)
}
// self.respDataForPlot = respContentArray
}
if (currentIndex % 50 == 0){
let i = 0
respDataForPlot.removeAtIndex(currentIndex+i)
respDataForPlot.insert([.X: Double(currentIndex+i)*0.01, .Y: Double(resp[i])/65535.0], atIndex: currentIndex+i)
respLinePlot.deleteDataInIndexRange(NSMakeRange(currentIndex+i, 1))
respLinePlot.insertDataAtIndex(UInt(currentIndex+i), numberOfRecords: 1)
}
for i in 0 ..< 5{
ecgDataForPlot.removeAtIndex(currentIndex+i)
ecgDataForPlot.insert([.X: Double(currentIndex+i)*0.01, .Y: Double(ecg[i])/65535.0], atIndex: currentIndex+i)
ecgLinePlot.deleteDataInIndexRange(NSMakeRange(currentIndex+i, 1))
ecgLinePlot.insertDataAtIndex(UInt(currentIndex+i), numberOfRecords: 1)
}
currentIndex = currentIndex + 5
}
// MARK: - Plot Data Source Methods
//Set the number of data points the plot has
func numberOfRecordsForPlot(plot: CPTPlot) -> UInt
{
let plotID = plot.identifier as! String
if (plotID == "ECG"){
return UInt(self.ecgDataForPlot.count)
}
else if (plotID == "RESP"){
return UInt(self.respDataForPlot.count)
}
return 0
}
//Returns the data point for each plot by using the plot identifier set above
func numberForPlot(plot: CPTPlot, field: UInt, recordIndex: UInt) -> AnyObject?
{
let plotField = CPTScatterPlotField(rawValue: Int(field))
let plotID = plot.identifier as! String
print("ID: \(plotID), Index: \(recordIndex)")
if let respNum = self.respDataForPlot[Int(recordIndex)][plotField!], let ecgNum = self.ecgDataForPlot[Int(recordIndex)][plotField!]{
if (plotField! == .Y) && (plotID == "RESP") {
return respNum as NSNumber
}
else {
return ecgNum as NSNumber
}
}
else {
return nil
}
}
In the datasource numberForPlot()
function, only unwrap the datapoint for a single plot. Since the data arrays have different lengths, the lookup will fail for the shorter array when plotting the longer one.
if (plotID == "ECG") {
if let ecgNum = self.ecgDataForPlot[Int(recordIndex)][plotField!] {
return ecgNum as NSNumber
}
else {
return 0 as NSNumber
}
}
else if (plotID == "RESP") {
if let respNum = self.respDataForPlot[Int(recordIndex)][plotField!] {
return respNum as NSNumber
}
else {
return 0 as NSNumber
}
}
else {
return 0 as NSNumber
}