SwiftUI IOS Dynamic CorePlot Data - core-plot

How do I implement dynamic data to my CorePlot? I'd like my graph to look like this:
How should I implement my JSON API and to decode the values to set it as X-axis?
JSON API: https://dcmicrogridiep.000webhostapp.com/datamainjson.php
This is my sample code for the CorePlot graph which uses hard coded values.
import Foundation
import SwiftUI
import CorePlot
class CalculatePlotData: ObservableObject {
var plotDataModel: PlotDataClass? = nil
func plotYEqualsX()
{
//set the Plot Parameters
plotDataModel!.changingPlotParameters.yMax = 10.0
plotDataModel!.changingPlotParameters.yMin = -5.0
plotDataModel!.changingPlotParameters.xMax = 10.0
plotDataModel!.changingPlotParameters.xMin = -5.0
plotDataModel!.changingPlotParameters.xLabel = "x"
plotDataModel!.changingPlotParameters.yLabel = "y"
plotDataModel!.changingPlotParameters.lineColor = .red()
plotDataModel!.changingPlotParameters.title = " y = x"
plotDataModel!.zeroData()
var plotData :[plotDataType] = []
for i in 0 ..< 120 {
//create x values here
let x = -2.0 + Double(i) * 0.2
//create y values here
let y = x * 8
let dataPoint: plotDataType = [.X: x, .Y: y]
plotData.append(contentsOf: [dataPoint])
}
plotDataModel!.appendData(dataPoint: plotData)
}
func ploteToTheMinusX()
{
//set the Plot Parameters
plotDataModel!.changingPlotParameters.yMax = 10
plotDataModel!.changingPlotParameters.yMin = -3.0
plotDataModel!.changingPlotParameters.xMax = 10.0
plotDataModel!.changingPlotParameters.xMin = -3.0
plotDataModel!.changingPlotParameters.xLabel = "x"
plotDataModel!.changingPlotParameters.yLabel = "y = exp(-x)"
plotDataModel!.changingPlotParameters.lineColor = .blue()
plotDataModel!.changingPlotParameters.title = "exp(-x)"
plotDataModel!.zeroData()
var plotData :[plotDataType] = []
for i in 0 ..< 60 {
//create x values here
let x = -8.0 + Double(i) * 5
//create y values here
let y = exp(-x)
let dataPoint: plotDataType = [.X: x, .Y: y]
plotData.append(contentsOf: [dataPoint])
}
plotDataModel!.appendData(dataPoint: plotData)
return
}
}

If you don't need the actual date values elsewhere in the app, you can just send the numbers in the "times" field provided by the API to the plot directly. You'll set the plot ranges based on those values and define a label formatter with the correct reference date to properly display the date values. Look at the DatePlot example app for a simple Swift example.

Related

how to show all x label charts ios?

I make a custom numbering label, everything works great. the problem is when the number of entries is less than X-axis maximum, the chart doesn't show any lines.
lineChart.data = data
let leftAxis = lineChart.leftAxis
//set constant label range
leftAxis.forceLabelsEnabled = true
leftAxis.labelCount = 4
leftAxis.axisMinimum = 0
leftAxis.axisMaximum = 4.5
leftAxis.granularity = 1
leftAxis.axisLineWidth = 0
leftAxis.valueFormatter = YAxisData()
//x axis label
let bottomAxis = lineChart.xAxis
bottomAxis.axisMinimum = 1
bottomAxis.axisMaximum = 7.0
bottomAxis.labelCount = 7
bottomAxis.forceLabelsEnabled = true
bottomAxis.granularity = 1
bottomAxis.axisLineWidth = 0
bottomAxis.valueFormatter = XAxisData()
bottomAxis.labelHeight = 30
if I changed the number of entries to 7, it works fine.
I want a way to show all x labels even if the number of entries is less than 7!

LinearRegressionWithSGD() returns NaN

I am trying to use LinearRegressionWithSGD on Million Song Data Set and my model returns NaN's as weights and 0.0 as the intercept. What might be the issue for the error ? I am using Spark 1.40 in standalone mode.
Sample data: http://www.filedropper.com/part-00000
Here is my full code:
// Import Dependencies
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.rdd.RDD
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.mllib.regression.LinearRegressionModel
import org.apache.spark.mllib.regression.GeneralizedLinearAlgorithm
import org.apache.spark.mllib.regression.LinearRegressionWithSGD
// Define RDD
val data =
sc.textFile("/home/naveen/Projects/millionSong/YearPredictionMSD.txt")
// Convert to Labelled Point
def parsePoint (line: String): LabeledPoint = {
val x = line.split(",")
val head = x.head.toDouble
val tail = Vectors.dense(x.tail.map(x => x.toDouble))
return LabeledPoint(head,tail)
}
// Find Range
val parsedDataInit = data.map(x => parsePoint(x))
val onlyLabels = parsedDataInit.map(x => x.label)
val minYear = onlyLabels.min()
val maxYear = onlyLabels.max()
// Shift Labels
val parsedData = parsedDataInit.map(x => LabeledPoint(x.label-minYear
, x.features))
// Training, validation, and test sets
val splits = parsedData.randomSplit(Array(0.8, 0.1, 0.1), seed = 123)
val parsedTrainData = splits(0).cache()
val parsedValData = splits(1).cache()
val parsedTestData = splits(2).cache()
val nTrain = parsedTrainData.count()
val nVal = parsedValData.count()
val nTest = parsedTestData.count()
// RMSE
def squaredError(label: Double, prediction: Double): Double = {
return scala.math.pow(label - prediction,2)
}
def calcRMSE(labelsAndPreds: RDD[List[Double]]): Double = {
return scala.math.sqrt(labelsAndPreds.map(x =>
squaredError(x(0),x(1))).mean())
}
val numIterations = 100
val stepSize = 1.0
val regParam = 0.01
val regType = "L2"
val algorithm = new LinearRegressionWithSGD()
algorithm.optimizer
.setNumIterations(numIterations)
.setStepSize(stepSize)
.setRegParam(regParam)
val model = algorithm.run(parsedTrainData)
I am not familiar with this specific implementation of SGD, but generally if a gradient descent solver goes to nan that means that the learning rate is too big. (in this case I think it is the stepSize variable).
Try to lower it by an order of magnitude each time until it starts to converge
I can think there are two possibilities.
stepSize is big. You should try something like 0.01, 0.03, 0.1,
0.3, 1.0, 3.0....
Your train data have NaN. If so, result will be likely NaN.

Swift string formula into a real calculation

I have several formulas stored in a Plist such as A * B. I'm trying to figure out how I could take this formula currently stored as a string in a Plist and use it as an actual calculation formula. I tried going the route of making the formula to \(A) * \(B) and then setting A and B before trying to use the formula but it did not work. Any suggestions?
example
let A = 5
let B = 2
println (formula)
actually printed out "\(A) * \(B)"
Xcode 8.3.1 • Swift 3.1
extension String {
var expression: NSExpression {
return NSExpression(format: self)
}
}
let a = 5
let b = 2
let intDictionary = ["a": a,"b": b]
var formula = "a * b"
if let timesResult = formula.expression.expressionValue(with: intDictionary, context: nil) as? Int {
print(timesResult) // 10
}
formula = "(a + b) / 2"
if let intAvgResult = formula.expression.expressionValue(with: intDictionary, context: nil) as? Int {
print(intAvgResult) // 3
}
let x = 5.0
let y = 2.0
let z = 3.0
let doubleDictionary = ["x": x, "y": y, "z": z]
formula = "(x + y + z) / 3"
if let doubleAvgResult = formula.expression.expressionValue(with: doubleDictionary, context: nil) as? Double {
print(doubleAvgResult)
}
Use NSExpression.
NSExpression *expression = [NSExpression expressionWithFormat:#"4 + 5 - 2**3"];
id value = [expression expressionValueWithObject:nil context:nil]; // => 1
Expression creation is formatted, so you can input your params as part of the equation.
More info here.
#Leo for Swift 3 (as opposed to obj-c) in Xcode 8 it would look like this:
let mathExpression = NSExpression(format: "4 + 5 - 2**3")
let mathValue = mathExpression.expressionValue(with: nil, context: nil) as? Int

UInt8 is not convertible to CGFloat error in iOS Swift

I am a beginner level programmer in iOS app development using Swift. Now I am facing the compile time issue "UInt8 is not convertible to CGFloat"
var numberOfAvatars:Int = 8
let count:Int = 1
let columns:Int = 3
let dimension:CGFloat = 84.0
var spacing:CGFloat = (avatarContentcroll.frame.size.width - columns * dimension)/(columns+1)
var scHeight:CGFloat = spacing + (numberOfAvatars/columns) * (dimension + spacing)
I've tried all the solutions out there and did many experiments. And I am not sure why still I am getting this error.
You have to do it explicitly as
var spacing:CGFloat = CGFloat((avatarContentcroll.frame.size.width) - CGFloat(columns) * (dimension))/(columns+1)
var scHeight:CGFloat = CGFloat(spacing + (CGFloat(numberOfAvatars)/CGFloat(columns)) * (dimension + spacing))
or you can try converting every expression in CGFloat
var spacing:CGFloat = ((avatarContentcroll.frame.size.width) - CGFloat(columns) * (dimension))/(columns+1)
var scHeight:CGFloat = spacing + (CGFloat(numberOfAvatars)/CGFloat(columns)) * (dimension + spacing)
You must explicitly cast your Ints as CGFloats (via as), or construct them -- like so:
var spacing:CGFloat = ((avatarContentcroll.frame.size.width) - CGFloat(columns) * (dimension))/(columns+1)
var scHeight:CGFloat = spacing + (CGFloat(numberOfAvatars)/CGFloat(columns)) * (dimension + spacing)

AVAudioRecorder through accelerate FFT into frequency - EXECUTION

My main goal: find the frequency of the noises being pulled in through AVAudioRecorder. I have followed this:
http://www.ehow.com/how_12224909_detect-blow-mic-xcode.html
I have read up on many questions on SO asking how to detect frequency. The majority of those answers say, "Use FFT!" and then the question ask-ers say, "Oh, great!".
My question is, how do you get from here:
- (void)levelTimerCallback {
[recorder updateMeters];
const double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
if (lowPassResults > sensitivitySlider.value) {
NSLog(#"Sound detected");
//What goes here so I can spit out a frequency?
}
}
Somehow magically use FFT... (I will use accelerate.h),
And wind up with "The frequency = 450.3"?
If somebody could show me the actual code that I would use to
Plug the sound from the AVAudioRecorder into Accelerate
and
How to turn the result into a frequency...
That would be greatly appreciated.
Thanks in advance.
Nothing "goes there", as the AVRecorder API does not plug into the Accelerate framework. Instead, you have to use a completely different API, the Audio Queue or RemoteIO Audio Unit API, to capture audio input, a completely different code arrangement, such as waiting for callbacks to get your data, buffer size management to get data arrays of the appropriate size to feed an FFT, then know enough DSP to post-process the FFT results for the particular kind of frequency measure for which you are looking.
Well, it turns out that something CAN "go there". Instead of using Accelerate, I bought a book on Fourier Analysis on Amazon and used it to build my own FFT. Which spits out not a single frequency but the levels of each of many frequencies, which is basically what I wanted.
Here's my FFT-computing class:
class FFTComputer: NSObject {
class func integerBitReverse(_ input:Int,binaryDigits:Int) -> Int {
return integerForReversedBooleans(booleansForInt(input, binaryDigits: binaryDigits))
}
class func integerForReversedBooleans(_ booleans:[Bool]) -> Int {
var integer = 0
var digit = booleans.count - 1
while digit >= 0 {
if booleans[digit] == true {
integer += Int(pow(Double(2), Double(digit)))
}
digit -= 1
}
return integer
}
class func Pnumber(_ k:Int,placesToMove:Int, gamma:Int) -> Int {
var booleans = booleansForInt(k, binaryDigits: gamma)
for _ in 0 ..< placesToMove {
booleans.removeLast()
booleans.insert(false, at: 0)
}
return integerForReversedBooleans(booleans)
}
class func booleansForInt(_ input:Int,binaryDigits:Int) -> [Bool] {
var booleans = [Bool]()
var remainingInput = input
var digit = binaryDigits - 1
while digit >= 0 {
let potential = Int(pow(Double(2), Double(digit)))
if potential > remainingInput {
booleans.append(false)
} else {
booleans.append(true)
remainingInput -= potential
}
digit += -1
}
return booleans
}
class func fftOfTwoRealFunctions(_ realX1:[CGFloat], realX2:[CGFloat], gamma:Int) -> (([CGFloat],[CGFloat]),([CGFloat],[CGFloat])) {
let theFFT = fft(realX1, imaginaryXin: realX2, gamma: gamma)
var R = theFFT.0
var I = theFFT.1
let N = Int(pow(2.0, Double(gamma)))
var realOut1 = [CGFloat]()
var imagOut1 = [CGFloat]()
var realOut2 = [CGFloat]()
var imagOut2 = [CGFloat]()
for n in 0..<N {
var Rback:CGFloat
var Iback:CGFloat
if n == 0 {
Rback = R[0]
Iback = I[0]
} else {
Rback = R[N-n]
Iback = I[N-n]
}
realOut1.append(CGFloat(R[n]/2 + Rback/2))
realOut2.append(CGFloat(I[n]/2 + Iback/2))
imagOut1.append(CGFloat(I[n]/2 - Iback/2))
imagOut2.append(-CGFloat(R[n]/2 - Rback/2))
}
return ((realOut1,imagOut1),(realOut2,imagOut2))
}
class func fft(_ realXin:[CGFloat], imaginaryXin:[CGFloat], gamma:Int) -> ([CGFloat],[CGFloat]) {
var realX = realXin
var imaginaryX = imaginaryXin
let N = Int(pow(2.0, Double(gamma)))
var N2 = N/2
var NU1 = gamma - 1 // Always equals (gamma - l)
var realWP:Double = 1
var imaginaryWP:Double = 0
var redoPCounter = 0
func redoP(_ k:Int, places:Int) {
let P = Pnumber(k, placesToMove:places, gamma: gamma)
let inside = (-2*Double.pi*Double(P))/Double(N)
realWP = cos(inside)
imaginaryWP = sin(inside)
}
var l = 1
while l <= gamma {
var k = 0
var I = 1
while k < N - 1 {
if redoPCounter == N2 {
redoP(k,places: NU1)
redoPCounter = 0
}
redoPCounter += 1
// Swift.print(realX.count,imaginaryX.count,k+N2)
let realT1 = (realWP*Double(realX[k + N2]))-(imaginaryWP*Double(imaginaryX[k + N2]))
let imaginaryT1 = (realWP*Double(imaginaryX[k + N2]))+(imaginaryWP*Double(realX[k + N2]))
realX[k+N2] = realX[k] - CGFloat(realT1)
imaginaryX[k+N2] = imaginaryX[k] - CGFloat(imaginaryT1)
realX[k] = realX[k] + CGFloat(realT1)
imaginaryX[k] = imaginaryX[k] + CGFloat(imaginaryT1)
k += 1
if I == N2 {
k += N2
I = 1
} else {
I += 1
}
}
N2 = N2/2
NU1 = NU1 - 1
redoPCounter = 0
realWP = 1
imaginaryWP = 0
l += 1
}
for k in 0 ..< N - 1 {
let i = integerBitReverse(k, binaryDigits:gamma)
if i > k {
let placeholderReal = realX[k]
let placeholderImaginary = imaginaryX[k]
realX[k] = realX[i]
imaginaryX[k] = imaginaryX[i]
realX[i] = placeholderReal
imaginaryX[i] = placeholderImaginary
}
}
return (realX,imaginaryX)
}
class func magnitudeAndPhasePresentations(_ realX:[CGFloat], imaginaryX:[CGFloat]) -> ([CGFloat],[CGFloat]) {
var magnitudes = [CGFloat]()
var phases = [CGFloat]()
var lastMagnitude:CGFloat = 0
var lastPhase:CGFloat = 0
for n in 0 ..< realX.count {
let real = realX[n]
let imaginary = imaginaryX[n]
if real != 0 {
lastMagnitude = sqrt(pow(real, 2)+pow(imaginary, 2))
lastPhase = atan(imaginary/real)
}
magnitudes.append(lastMagnitude)
phases.append(lastPhase)
}
return (magnitudes,phases)
}
class func magnitudePresentation(_ realX:[CGFloat], imaginaryX:[CGFloat]) -> [CGFloat] {
var magnitudes = [CGFloat]()
var lastMagnitude:CGFloat = 0
for n in 0 ..< realX.count {
let real = realX[n]
let imaginary = imaginaryX[n]
if real != 0 {
lastMagnitude = sqrt(pow(real, 2)+pow(imaginary, 2))
}
magnitudes.append(lastMagnitude)
}
return magnitudes
}
}
And to get the audio, I used Novocaine: https://github.com/alexbw/novocaine
I would recommend reading a bit about the Fourier Transform, but it really doesn't have to be that difficult to plug data from Novocaine (the mic) into an FFTComputer and get back some frequencies.
(2 to the gamma is the count of realXin. I could have just computed gamma, so if you want to change that, go ahead. Just turn the Novocaine data into an array of CGFloats, put that in realXin, put an empty array of the same size in imagXin, and enter the right gamma. Then, maybe graph the output to see the frequencies.)

Resources