How to split a dataframe containing voltage over time value, so that it can store values of each waveform/bit separately

Viewed 66

I have several csv files which have data of voltage over time and each csv files are approximately 7000 rows and the data looks like this:

Time(us) Voltage (V)
0       32.96554106
0.5     32.9149649
1       32.90484966
1.5     32.86438874
2       32.8542735
2.5     32.76323642
3       32.74300595
3.5     32.65196886
4       32.58116224
4.5     32.51035562
5       32.42943376
5.5     32.38897283
6       32.31816621
6.5     32.28782051
7       32.26759005
7.5     32.21701389
8       32.19678342
8.5     32.16643773
9       32.14620726
9.5     32.08551587
10      32.04505495
10.5    31.97424832
11      31.92367216
11.5    31.86298077
12      31.80228938
12.5    31.78205891
13      31.73148275
13.5    31.69102183
14      31.68090659
14.5    31.67079136
15      31.64044567
15.5    31.59998474
16      31.53929335
16.5    31.51906288

I read the csv file with pandas dataframe and after plotting a figure in matplotlib with data from one csv file, the figure looks like below. Voltage over time

I would like to split every single square waveform/bit and store the corresponding voltage values for each bit separately. So the resulting voltage values of each bit would be stored in a row and should look like this: enter image description here enter image description here

I don't have any idea how to do that. I guess I have to write a function where I have to assign a threshold value that, if the voltage values are going down for maybe 20 steps of time than capture all the values or if the voltage level is going up for 20 steps of time than capture all the voltage values. Could someone help?

1 Answers

If you get the gradient of your Voltage (here using diff as the time is regularly spaced), this gives you the following:

gradient

You can thus easily use a threshold (I tested with 2) to identify the peak starts. Then pivot your data:

# get threshold of gradient
m = df['Voltage (V)'].diff().gt(2)
# group start = value above threshold preceded by value below threshold
group = (m&~m.shift(fill_value=False)).cumsum().add(1)

df2 = (df
 .assign(id=group,
         t=lambda d: d['Time (us)'].groupby(group).apply(lambda s: s-s.iloc[0])
         )
 .pivot(index='id', columns='t', values='Voltage (V)')
)

output:

t       0.0        0.5        1.0        1.5        2.0        2.5    \
id                                                                     
1   32.965541  32.914965  32.904850  32.864389  32.854273  32.763236   
2   25.045314  27.543777  29.182444  30.588462  31.114454  31.984364   
3   25.166697  27.746081  29.415095  30.719960  31.326873  32.125977   
4   25.277965  27.877579  29.536477  30.912149  31.367334  32.206899   
5   25.379117  27.978732  29.667975  30.780651  31.670791  32.338397   
6   25.631998  27.634814  28.959909  30.173737  30.659268  31.053762   
7   23.528030  26.137759  27.948386  29.253251  30.244544  30.649153   
8   23.639297  26.380525  28.464263  29.971432  30.902034  31.458371   
9   23.740449  26.542369  28.707028  30.295120  30.881803  31.862981   
10  23.871948  26.673867  28.889103  30.305235  31.185260  31.873096   
11  24.387824  26.694097  28.342880  29.678091  30.315350  31.134684   

...

t       748.5      749.0  
id                        
1         NaN        NaN  
2         NaN        NaN  
3         NaN        NaN  
4         NaN        NaN  
5         NaN        NaN  
6   21.059913  21.161065  
7         NaN        NaN  
8         NaN        NaN  
9         NaN        NaN  
10        NaN        NaN  
11        NaN        NaN  

[11 rows x 1499 columns]

plot:

df2.T.plot()

aligned curves

Related