Use GEEngine for loop to solve 'collection query aborted after accumulating over 5000 elements' - charts

I have 279 points (https://code.earthengine.google.com/?asset=projects/ee-zhaominyan/assets/2_29UMT), and need to get the surface reflectance of each points from Sentinel-2 for a very long period (around 1076 images in the image collection for this long periods). I found that if I use the typical approach, which control the number of elements under 5000 elements, this will make me process the same thing for 63 times. I am not pretty good at GEEngine, so does anyone know how to write a 'for-loop' to batch export the chart?
This is my code right now:
function maskS2clouds(image) {
var qa = image.select('QA60')
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
qa.bitwiseAnd(cirrusBitMask).eq(0))
return image.updateMask(mask)
.select("B.*")
.copyProperties(image, ["system:time_start"])
}
var tiles = ['29UMT'];
var shp1 = ee.FeatureCollection('projects/ee-zhaominyanpaper2/assets/2_29UMT')
Map.addLayer(shp1.draw({color: '0000FF', pointRadius: 1}),{},'29UMA')
var tiles = ['29UMT'];
// for a specific gemetry used before
var collection = ee.ImageCollection("COPERNICUS/S2_SR")
.filterDate('2022-04-02', '2022-07-30')
.filter(ee.Filter.inList('MGRS_TILE', tiles))
var count = collection.size();
print(count,'Count')
var collectioncloud = collection.map(maskS2clouds)
var chart =ui. Chart.image.seriesByRegion({
imageCollection: collectioncloud,
regions: shp1,
reducer: ee.Reducer.mean(),
band: 'B2',
scale: 10,
xProperty: 'system:time_start',
seriesProperty:'FID_'
})

Related

Matching Torch STFT with Accelerate

Im trying to re-implement Torch's STFT code in Swift with Accelerate / vDSP, to produce a Log Mel Spectrogram by post processing the STFT so I can use the Mel Spectrogram as an input for a CoreML port of OpenAI's Whisper
Pytorch's native STFT / Mel code produces this Spectrogram (its clipped due to importing raw float 32s into Photoshop lol)
and mine:
Obviously the two things to notice are the values, and the lifted frequency components.
The STFT Docs here https://pytorch.org/docs/stable/generated/torch.stft.html
X[ω,m]=
k=0
∑
win_length-1
​
window[k] input[m×hop_length+k] * exp(−j * (2π⋅ωk) /win_length)
I believe Im properly handling window[k] input[m×hop_length+k] but I'm a bit lost as to how to calculate the exponent and what -J is referring to in the documentation, and how to convert the final exponential in vDSP. Also, if its a sum, how do I get the 200 elements I need!?
My Log Mel Spectrogram
My code follows:
func processData(audio: [Int16]) -> [Float]
{
assert(self.sampleCount == audio.count)
var audioFloat:[Float] = [Float](repeating: 0, count: audio.count)
vDSP.convertElements(of: audio, to: &audioFloat)
vDSP.divide(audioFloat, 32768.0, result: &audioFloat)
// Up to this point, Python and swift are numerically identical
// insert numFFT/2 samples before and numFFT/2 after so we have a extra numFFT amount to process
// TODO: Is this stricly necessary?
audioFloat.insert(contentsOf: [Float](repeating: 0, count: self.numFFT/2), at: 0)
audioFloat.append(contentsOf: [Float](repeating: 0, count: self.numFFT/2))
// Split Complex arrays holding the FFT results
var allSampleReal = [[Float]](repeating: [Float](repeating: 0, count: self.numFFT/2), count: self.melSampleCount)
var allSampleImaginary = [[Float]](repeating: [Float](repeating: 0, count: self.numFFT/2), count: self.melSampleCount)
// Step 2 - we need to create 200 x 3000 matrix of STFTs - note we appear to want to output complex numbers (?)
for (m) in 0 ..< self.melSampleCount
{
// Slice numFFTs every hop count (barf) and make a mel spectrum out of it
// audioFrame ends up holding split complex numbers
var audioFrame = Array<Float>( audioFloat[ (m * self.hopCount) ..< ( (m * self.hopCount) + self.numFFT) ] )
// Copy of audioFrame original samples
let audioFrameOriginal = audioFrame
assert(audioFrame.count == self.numFFT)
// Split Complex arrays holding a single FFT result of our Audio Frame, which gets appended to the allSample Split Complex arrays
var sampleReal:[Float] = [Float](repeating: 0, count: self.numFFT/2)
var sampleImaginary:[Float] = [Float](repeating: 0, count: self.numFFT/2)
sampleReal.withUnsafeMutableBytes { unsafeReal in
sampleImaginary.withUnsafeMutableBytes { unsafeImaginary in
vDSP.multiply(audioFrame,
hanningWindow,
result: &audioFrame)
var complexSignal = DSPSplitComplex(realp: unsafeReal.bindMemory(to: Float.self).baseAddress!,
imagp: unsafeImaginary.bindMemory(to: Float.self).baseAddress!)
audioFrame.withUnsafeBytes { unsafeAudioBytes in
vDSP.convert(interleavedComplexVector: [DSPComplex](unsafeAudioBytes.bindMemory(to: DSPComplex.self)),
toSplitComplexVector: &complexSignal)
}
// Step 3 - creating the FFT
self.fft.forward(input: complexSignal, output: &complexSignal)
}
}
// We need to match: https://pytorch.org/docs/stable/generated/torch.stft.html
// At this point, I'm unsure how to continue?
// let twoπ = Float.pi * 2
// let freqstep:Float = Float(16000 / (self.numFFT/2))
//
// var w:Float = 0.0
// for (k) in 0 ..< self.numFFT/2
// {
// let j:Float = sampleImaginary[k]
// let sample = audioFrame[k]
//
// let exponent = -j * ( (twoπ * freqstep * Float(k) ) / Float((self.numFFT/2)))
//
// w += powf(sample, exponent)
// }
allSampleReal[m] = sampleReal
allSampleImaginary[m] = sampleImaginary
}
// We now have allSample Split Complex holding 3000 200 dimensional real and imaginary FFT results
// We create flattened 3000 x 200 array of DSPSplitComplex values
var flattnedReal:[Float] = allSampleReal.flatMap { $0 }
var flattnedImaginary:[Float] = allSampleImaginary.flatMap { $0 }

getting a 100% between two numbers?

I happen to have a timer which keeps track of two different points.
When I start, both are at zero.
when the button is pressed, one of them, let's call it A, keeps on incrementing by 1 every second.
If I press the button again, the state will switch and B variable will now start adding a point every second.
Let's say I have A at 10 and B at 30.
I would like to calculate the % between them.
For this specific case, I'd like a print out that A = 25% and B = 75%.
This is my code so far:
var total = A + B
var BPercentage = total - B / 100
var AestPercentage = A/B*100
var damo = 00.00
damo = 100/Double(total/B)
print(damo)
None of these seem to work.
Perhaps something like the following?
var total = A + B
var bPercentage = (B / total) * 100
var aPercentage = (A / total) * 100
var percentageDiff = abs(aPercentage - bPercentage)

Detect overlaping if enumerating nodes

I would like to know how should I detect overlapping nodes while enumerating them? Or how should I make that every random generated position in Y axis is at least some points higher or lower.
This is what I do:
1 - Generate random number between -400 and 400
2 - Add those into array
3 - Enumerate and add nodes to scene with generated positions like this:
var leftPositions = [CGPoint]()
for _ in 0..<randRange(lower: 1, upper: 5){
leftPositions.append(CGPoint(x: -295, y: Helper().randomBetweenTwoNumbers(firstNumber: leftSparkMinimumY, secondNumber: leftSparkMaximumY)))
}
leftPositions.enumerated().forEach { (index, point) in
let leftSparkNode = SKNode()
leftSparkNode.position = point
leftSparkNode.name = "LeftSparks"
let leftSparkTexture = SKTexture(imageNamed: "LeftSpark")
LeftSpark = SKSpriteNode(texture: leftSparkTexture)
LeftSpark.name = "LeftSparks"
LeftSpark.physicsBody = SKPhysicsBody(texture: leftSparkTexture, size: LeftSpark.size)
LeftSpark.physicsBody?.categoryBitMask = PhysicsCatagory.LeftSpark
LeftSpark.physicsBody?.collisionBitMask = PhysicsCatagory.Bird
LeftSpark.physicsBody?.contactTestBitMask = PhysicsCatagory.Bird
LeftSpark.physicsBody?.isDynamic = false
LeftSpark.physicsBody?.affectedByGravity = false
leftSparkNode.addChild(LeftSpark)
addChild(leftSparkNode)
}
But like this sometimes they overlap each other because the generated CGPoint is too close to the previous one.
I am trying to add some amount of triangles to the wall and those triangles are rotated by 90°
To describe in image what I want to achieve:
And I want to avoid thing like this:
Your approach to this is not the best, i would suggest only storing the Y values in your position array and check against those values to make sure your nodes will not overlap. The following will insure no two sparks are within 100 points of each other. You may want to change that value depending on your node's actual height or use case.
Now, obviously if you end up adding too many sparks within an 800 point range, this just will not work and cause an endless loop.
var leftPositions = [Int]()
var yWouldOverlap = false
for _ in 0..<randRange(lower: 1, upper: 5){
//Moved the random number generator to a function
var newY = Int(randY())
//Start a loop based on the yWouldOverlap Bool
repeat{
yWouldOverlap = false
//Nested loop to range from +- 100 from the randomly generated Y
for p in newY - 100...newY + 100{
//If array already contains one of those values
if leftPosition.contains(p){
//Set the loop Bool to true, get a new random value, and break the nested for.
yWouldOverlap = true
newY = Int(randY())
break
}
}
}while(yWouldOverlap)
//If we're here, the array does not contain the new value +- 100, so add it and move on.
leftPositions.append(newY)
}
func randY() -> CGFloat{
return Helper().randomBetweenTwoNumbers(firstNumber: leftSparkMinimumY, secondNumber: leftSparkMaximumY)
}
And here is a different version of your following code.
for (index,y) in leftPositions.enumerated() {
let leftSparkNode = SKNode()
leftSparkNode.position = CGPoint(x:-295,y:CGFloat(y))
leftSparkNode.name = "LeftSparks\(index)" //All node names should be unique
let leftSparkTexture = SKTexture(imageNamed: "LeftSpark")
LeftSpark = SKSpriteNode(texture: leftSparkTexture)
LeftSpark.name = "LeftSparks"
LeftSpark.physicsBody = SKPhysicsBody(texture: leftSparkTexture, size: LeftSpark.size)
LeftSpark.physicsBody?.categoryBitMask = PhysicsCatagory.LeftSpark
LeftSpark.physicsBody?.collisionBitMask = PhysicsCatagory.Bird
LeftSpark.physicsBody?.contactTestBitMask = PhysicsCatagory.Bird
LeftSpark.physicsBody?.isDynamic = false
LeftSpark.physicsBody?.affectedByGravity = false
leftSparkNode.addChild(LeftSpark)
addChild(leftSparkNode)
}

Making A DCT in a for loop faster

I need to run a DCT on multiple signals (time slices of the same audio signal).
My current code looks like this:
var ci = Array(stride(from: Float(0), to: Float(y.count), by: Float(p)))
var c = Array<Float>(repeating:0.0, count:y.count)
for (index,value) in ci.enumerated() {
var i = index
var v = Int(value)
var newArray = Array(y[v...(v+Int(p)-1)])
let DCTSetup = vDSP_DCT_CreateSetup(nil, vDSP_Length(newArray.count), vDSP_DCT_Type.II)
var nac = Array<Float>(repeating:0.0, count:newArray.count)
vDSP_DCT_Execute(DCTSetup!, &newArray, &nac)
//c.append(contentsOf: nac)
c.insert(contentsOf: nac, at: v)
}
//c.removeFirst()
But this is taking ages. So for a 10 second audio sample it takes well over 60 seconds.
Is there a way of doing a DCT on multiple signal quickly? (I have made up an array of each sample appended to the other for this computation).
Hope you can help,
Best,
Feras A.

How to make y-axis not start at zero?

I know there is a chart.leftAxis.startAtZeroEnabled = false option but it's not working for me.
I'm making a line graph to track Instagram Followers over time and I have data points that vary very little so I need the y-axis adjusted so that the changes are enabled, but it
Here is the code I have for the graph:
let chart = LineChartView(frame: chart1View.bounds)
let dayTrackerUnits = trackerCrawler.thisWeeksPoints()
var xVals : [Int] = []
var yVals : [ChartDataEntry] = []
var minimum = 1000000000
var maximum = 0
for i in 0..<dayTrackerUnits.count {
xVals.append(i)
yVals.append(ChartDataEntry(value: Double(dayTrackerUnits[i].followerCount), xIndex: i))
if dayTrackerUnits[i].followerCount < minimum {
minimum = dayTrackerUnits[i].followerCount
}
if dayTrackerUnits[i].followerCount > maximum {
maximum = dayTrackerUnits[i].followerCount
}
}
print(yVals)
let chartDataSet = LineChartDataSet(yVals: yVals, label: "Followers")
chartDataSet.setColor(GlobalStyles.sharedStyles.instagramBlue())
chartDataSet.lineWidth = 2.0
chartDataSet.circleRadius = 5.0
chartDataSet.circleColors = [GlobalStyles.sharedStyles.instagramBlue()]
chartDataSet.drawValuesEnabled = false
chartDataSet.drawVerticalHighlightIndicatorEnabled = true
let data = LineChartData(xVals: xVals, dataSet: chartDataSet)
chart.data = data
chart.delegate = self
chart.leftAxis.startAtZeroEnabled = false
chart.rightAxis.startAtZeroEnabled = false
print("min: \(minimum), max: \(maximum)")
chart.rightAxis.enabled = false
chart1View.addSubview(chart)
left1Label.text = "Followers"
I'd like to set the yAxisMinimum to minimum and the yAxisMaximum to maximum but the graph won't display how I want.
Any suggestions?
You can just use customAxisMin/Max to limit its range.
BTW, you have to make sure your data values does not contains 0. It seems like your data has 0, that's why it always start from 0. It has a small algorithm to calculate the axis range in computeAxisValues in y axis renderer.