'How do I find the saturation point of a curve in python?

I have a graph of the number of FRB detections against the Signal to Noise Ratio. At a certain point, the Signal to Noise ratio flattens out.

The input variable (the number of FRB detections) is defined by

N_vals = numpy.logspace(0, np.log10((10)**(11)), num = 1000)

and I have a series of arrays that correspond to outputs of the Signal to Noise Ratio (they have the same length).

So far, I have used numpy.gradient() on all the Signal-to-Noise (SNR) ratios to obtain the corresponding slope at every point.

I want to obtain the index at which the Signal-to-Noise Ratio dips below a certain threshold.

Using numpy functions designed to find the inflexion point won't work in my case as the gradient continues to increase - just very gradually.

Here is some code to illustrate my initial attempt:

import numpy as np

grad100 = np.gradient(NDM100)
grad300 = np.gradient(NDM300)
grad1000 = np.gradient(NDM1000)


#print(grad100)

grad2 = np.gradient(N2)
grad5 = np.gradient(N5)
grad10 = np.gradient(N10)

glist = [np.array(grad2), np.array(grad5), np.array(grad10), np.array(grad100), np.array(grad300), np.array(grad1000)]

indexlist = []

for g in glist:
       for i in g:
            satdex =  np.where(i == 10**(-4))[0]
            indexlist.append(satdex)

Doing this just gives me a list of empty arrays - for instance:

[array([], dtype=int64),..., array([], dtype=int64)]

Does anyone know a better way of doing this? I just want the indices corresponding to the points at which the gradient is 10**(-4) for each array. This is my 'saturation point'.

Please let me know if I need to provide more information and if so, what exactly. I'm not expecting anyone to run my code as there is a lot of it; rather, I'm after some general tips or some commentary on the structure of my code. I've attached the graph that corresponds to my data (the arrows show what I mean by the point at which the SNR flattens out).

I feel that this is a fairly simple programming problem and therefore doesn't warrant the detail that would be found in questions on error messages for example.

SNR curves with arrows indicating what I mean by 'saturation points'



Solution 1:[1]

Alright so I think I've got it. I'm attaching my code below. Obviously it's taken out of context here and won't run by itself so this is just so anyone that finds this question can see what kind of structure works. The general idea is that for a given set of curves, I find the x and y-values at which they begin to flatten out.

x = 499
N_vals2 = N_vals[500:]

grad100 = np.gradient(NDM100)
grad300 = np.gradient(NDM300)
grad1000 = np.gradient(NDM1000)

grad2 = np.gradient(N2)
grad5 = np.gradient(N5)
grad10 = np.gradient(N10)

preg_list = [grad100, grad300, grad1000, grad2, grad5, grad10]

g_list = []

for gl in preg_list:
    g_list.append(gl[500:])
    
sneg_list = [NDM100, NDM300, NDM1000, N2, N5, N10]

sn_list = []

for sl in sneg_list:
    sn_list.append(sl[500:])
    
t_list = []
gt_list = []
ic_list = []


for g in g_list:
    threshold = 0.1*np.max(g)
    thresh_array = np.full(len(g), fill_value = threshold)
    t_list.append(threshold)
    gt_list.append(thresh_array)
    
    ic = np.isclose(g, thresh_array, rtol = 0.5)
    ic_list.append(ic)
    
index_list = []
grad_list = []

for i in ic_list:
    index = np.where(i == True)
    index_list.append(index)
    
    for j in g_list:
        gval = j[index]
        grad_list.append(gval)
        
saturation_indices = []

for gl in index_list:
    first_index = gl[0][0]
    saturation_indices.append(first_index)
    
#print(saturation_indices)


saturation_points = []

sn_list_firsts = [snf[0] for snf in sn_list]


for s in saturation_indices:
    n = round(N_vals2[s], 0)
    sn_tuple = (n, s)
    saturation_points.append(sn_tuple)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1