Pie Chart entries outside slices have different position offsets - swift

The Charts library I'm using: Daniel Gindi - Charts
If you look at the above image, the position offset of entries outside each slice are variable both in distance from the slice as well as in alignment.
What I want:
Align the entry text to be at the center outside the slice. [Look at 1 & 3]
Keep all the slice texts equidistant from the slice. [Look at 3 & 6]
What I tried so far:
I tried to play with valueLinePart1Length and valueLinePart2Length, but this just helped a little, didn't solve the problem completely. Also I went through all the variables of PieChartDataSet.
Still haven't figured out how to fix this, can someone point out am I missing something or how to fix the issue.
Edit: Added code
let values: [Double] = [16, 6, 1, 3]
let chartEntries: [PieChartDataEntry] = pieChartEntries(for: values)
let pieChartDataSet = PieChartDataSet(values: chartEntries, label: nil)
pieChartDataSet.sliceSpace = 2
pieChartDataSet.colors = colors
pieChartDataSet.valueLineWidth = 0
pieChartDataSet.valueLinePart1Length = 0.4
pieChartDataSet.valueLinePart2Length = 0
pieChartDataSet.valueTextColor = .black
pieChartDataSet.yValuePosition = .outsideSlice
pieChartDataSet.valueLineVariableLength = false
let pieChartData = PieChartData(dataSet: pieChartDataSet)
pieChart.data = pieChartData

change the yValuePosition to .insideSlice

Related

iOS Charts Github :: Spacing

I'm using ios-charts to build a line chart and have been customizing it's design. However I'm having some issues with changing some settings/designs right now. This is what it currently looks like.
I can't seem to add vertical spacing between the legend and the graphs x axis labels. They are too close together.
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom // Emphasis
xAxis.labelFont = UIFont.systemFont(ofSize: 12, weight: .regular)
xAxis.axisLineWidth = 1
xAxis.axisMinimum = 239
xAxis.axisMaximum = 249
//xAxis.yOffset = 15 // ONLY ADDS TOP SPACE
// Legend
chartView.rightAxis.enabled = false // remove from the right side
chartView.legend.font = UIFont.systemFont(ofSize: 12, weight: .regular)
chartView.legend.yEntrySpace = 10
chartView.legend.formSize = 10
chartView.legend.yOffset = 10 // ONLY ADDS BOTTOM SPACE
Setting the verticalAlignment to VerticalAlignment.top (it is VerticalAlignment.bottom by default) should use the yOffset as the top space.
You can use this parameter:
chartView.legend.yOffset

swift metal: creating compute pass cycles

I'm implementing a gaussian subtract function that extracts features of 2d gaussian like objects from an input image. The algorithm is as follows:
inputImageX -> contrast image and threshold to 255 -> stack of sigma(n) blurred B intermittent 2D arrays -> stack of input- B(n) intermittent 2d arrays as C -> max value + index of C(n) 2D arrays as D -> draw circle with sigma(n) for all in B -> repeat cycle from C until maxvalue reaches 0.
I found some MTLFunction objects for 2D gaussian blur, and can create my own shaders for the subtract, max value and create circle shaders, but I am unsure how the MTLTexture2D objects can be cycle across multiple passes of the algorithm without writing redundant looking code in my filter class.
Can anyone point me to a link where I can figure if:
1- i can use a custom struct like a 2Dmatrix x n dimensional object to pass and apply the gaussian filter per dim 3 layer
2- How to create this cycle on the MTLPipelineState object so that each buffer between C and D uses the previously generated image
Here is the answer. I was trying to reinvent the wheel but found that there is a nifty metal performance shader called MPSImageKeyPoints which does all of the above nicely. The code is below, it works, just make sure you instantiate your own MTLDevice, MTLCommandQueue and MPSImageKeyPoint, as well as MTLTextures
// Start with converting the image
let inputTexture = getMTLTexture(from: getCGImage(from: image)!)
// Create a texture descriptor to get the buffer for transforming into a format compatible with MPSImageKeyPoints
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .r8Unorm, width: self.width, height: self.height, mipmapped: false)
textureDescriptor.usage = [.shaderRead, .shaderWrite]
let keyPoints = self.device.makeTexture(descriptor: textureDescriptor)
let imageConversionBuffer = self.commandQueue!.makeCommandBuffer()!
self.imageConversion!.encode(commandBuffer: imageConversionBuffer, sourceTexture: inputTexture, destinationTexture: keyPoints!)
imageConversionBuffer.commit()
imageConversionBuffer.waitUntilCompleted()
// Use the find key points with w*h star and 0.8 min value threshold
let maxpoints = self.width*self.height
let keyPointCountBuffer = self.device.makeBuffer(length: MemoryLayout<Int>.stride, options: .cpuCacheModeWriteCombined)
let keyPointDataBuffer = self.device.makeBuffer(length: MemoryLayout<MPSImageKeypointData>.stride*maxpoints, options: .cpuCacheModeWriteCombined)
let keyPointBuffer = self.commandQueue!.makeCommandBuffer()
self.findKeyPoints!.encode(to: keyPointBuffer!, sourceTexture: keyPoints!, regions: &self.filterRegion, numberOfRegions: 1, keypointCount: keyPointCountBuffer!, keypointCountBufferOffset: 0, keypointDataBuffer: keyPointDataBuffer!, keypointDataBufferOffset: 0)
// Finally run the filter
keyPointBuffer!.commit()
keyPointBuffer!.waitUntilCompleted()
// Extract the blobs
let starCount = keyPointCountBuffer!.contents().bindMemory(to: Int.self, capacity: 1)
print("Found \(starCount.pointee) stars")
let coordinatePointer = keyPointDataBuffer!.contents().bindMemory(to: MPSImageKeypointData.self, capacity: starCount.pointee)
let coordinateBuffer = UnsafeBufferPointer(start: coordinatePointer, count: starCount.pointee)
let coordinates = Array(coordinateBuffer)
var results = [[Int]]()
for i in 0..<starCount.pointee {
let coordinate = coordinates[i].keypointCoordinate
results.append([Int(coordinate[0]), Int(coordinate[1])])
}

Render multiple BarChartDataSets using danielgindi/Charts

I'm trying to create a bar chart using danielgindi/Charts (based on MPAndroidChart). I would like to use multiple data sets, but when I try to provide multiple sets to the BarChartView no bars are rendered.
let barView = BarChartView()
let set1 = BarChartDataSet()
set1.addEntry(BarChartDataEntry(x: 1, y: 1))
let set2 = BarChartDataSet()
set2.addEntry(BarChartDataEntry(x: 2, y: 2))
barView.data = BarChartData(dataSets: [set1, set2])
contentView = barView
In the above example, I would expect two bars to be displayed. However, no bars will appear at all.
If I provide only one data set, the chart will render as expected.
barView.data = BarChartData(dataSets: [set1])
The problem is that with multiple groups, the position of the bars on the x-axis will change. However, the axis minimum and maximum values do not automatically resize to fit the new data. They must be resized manually. For example:
let groupSpace = 0.3
let barSpace = 0.0
let groupWidth = barData.groupWidth(groupSpace: groupSpace, barSpace: barSpace)
columnView.xAxis.axisMinimum = 0
columnView.xAxis.axisMaximum = groupWidth * numOfEntriesPerSet
columnView.groupBars(fromX: 0, groupSpace: groupSpace, barSpace: barSpace)

How do I complete remove the draw value on bar chart using iOS charts with swift 3

I am trying to remove the bottom draw values (in black) on my X axis. I tried self.chartActual.drawValueAboveBarEnabled = false but all that does is move the values to below the top of the bar. I also tried self.chartActual.xAxis.drawLabelsEnabled = false but that hides my top labels.
How do I remove the drawvalue on the X axis using ios-charts?
let datamore = BarChartData()
let ds12 = BarChartDataSet(values: dataEntries, label: nil)
datamore.addDataSet(ds12)
datamore.setDrawValues(false)
I needed the last line AFTER adding the data.

How to setup up iOS charts y-axis with min, max value and a fixed step between the grid lines?

I'm just in the learning phase of using ios-charts. I like to change the x-axis grid to fixed values.
My plotted y-values are just int numbers like 1, 2, 3,..., 10. Nevertheless, the left y-axis shows values like 6.3, 9.1, etc., depending on my zoom level.
The second question is, how to set up the x-axis in order to show the labels 1,5,10,15,....40?
Is there any way to influence the step size like e.g. in Excel?
// zoom y-axis to min/max value
lineChart.leftAxis.customAxisMin = max(0.0, lineChart.data!.yMin - 1.0)
lineChart.leftAxis.customAxisMax = min(10.0, lineChart.data!.yMax + 1.0)
lineChart.leftAxis.startAtZeroEnabled = false
Chart (min = 6.0 and max = 10.0): The grid start at 6.3 instead of 6.0.
Chart (min = 7.0 and max = 10.0): The grid starts as expected with 7.0.
What's going wrong here?
I solved the issue just by setting the correct labelCount.
// zoom y-axis to min/max value
lineChart.leftAxis.customAxisMin = max(0.0, lineChart.data!.yMin - 1.0)
lineChart.leftAxis.customAxisMax = min(10.0, lineChart.data!.yMax + 1.0)
lineChart.leftAxis.labelCount = Int(lineChart.leftAxis.customAxisMax lineChart.leftAxis.customAxisMin)
lineChart.leftAxis.startAtZeroEnabled = false
Swift 4.2 and above:
startAtZeroEnabled - This property is deprecated - Use axisMinimum instead.
open var axisMinValue: Double
{
get { return axisMinimum }
set { axisMinimum = newValue }
}
lineChartView.leftAxis.axisMinimum = 0
lineChartView.leftAxis.axisMaximum = 10.0