#Written by Blake Burns of Blake Burns Technologies Inc.
#This work is licensed under a Creative Commons Attribution 4.0 International License
#https://creativecommons.org/licenses/by/4.0/
#Minimum Scanning
import numpy as np
import matplotlib.pyplot as plt
import random
#Change this to change the input size, it's an RNG array currently.
Array_Size = 100
#Change this to any numpy data set as you need to.
#Keep in mind changes to the data set will require changes to this code.
array = np.random.randn(Array_Size, 1)
realarr = []
slope = []
#This is the side/width of the area (changeable) it compares to making sure it's a minimum.
#0.05 is 5% which has been tested succesfully on RNG data sets.
#Ideally the size factor should have machine learning such as be changing depending on other variables.
Size_Factor = 0.025
count = 0
#This for loop converts the numpy array into a normal python3 list (not necessary and modifiable).
#This is just for simplicity.
#It also calculates the slope between the input point and the next which is invaluable.
#Using series methodologies with every data input you can successfully compute everything needed.
for item in array:
realarr.append(item)
if count + 1 == len(array):
break
else:
#This is the slope calculation.
#Here it is only the change of y since x every time on the random set changes by 1.
#(y2 - y1)/(x2 - x1) == (y2 - y1)/1 for this RNG list (can be changed).
#Of course you can use as many variables as you want ie. x not always changing by 1.
slope.append(array[count+1] - item)
count += 1
#This is where the range set around the points scanned for local minimum is.
#It operates off the Size_Factor variable described above.
var = range(int((len(realarr) + 1) * -Size_Factor), int((len(realarr) + 1) * Size_Factor)+1)
print(var)
local_min = []
#This for loop uses all possible data points to look for local minimums with the range above
for i in range(len(realarr) - 1):
count = 0
#This loop tests the range set (var) size/width and scans to check if its truly a local minumum
for k in var:
#This makes sure it's not going outside the data set
if not (i + k < 0 or i + k > len(realarr)):
#This tests to look for a minimum curve, looking at the slope before and after.
#This ensures that it is a curve that fits local minimum criteria.
if (slope[i] >= 0 and slope[i-1] <= 0):
try:
#This is the test, if it fully makes the range.
#It appends it to the local_min array if it makes it the range as the minimum.
if count == len(var) - 1:
local_min.append(i)
#If this value is larger than the chosen data point it keeps going checking for a min.
#This starts negative on the left side of the span of the range set (var) and goes to the right.
elif realarr[i + k] >= realarr[i]:
count += 1
continue
#This breaks the loop if there is another minimum and goes to the next point to keep searching.
#(Goes to line 45).
else:
break
except Exception as e:
continue
print("Number of minimums identified: " + str(len(local_min)))
print("Array of the x values of minimum locals: " + str(local_min))
arrtest2 = []
#This is a cool loop that gets the output (y) of the data input (x) for the local minimums
for min in local_min:
arrtest2.append(realarr[min][0])
print("Array of the values accessed in the y axis by the minimum locals: " + str(arrtest2))
#This is all the original data plotted
plt.plot(realarr, color="red")
#This one shows the slope computation visually
#plt.plot(local_min, color="black")
plt.show()