# Waveform Characterization

**URL:** <https://discourse.julialang.org/t/waveform-characterization/20654>\
**Category:** Signal and Image Processing\
**Tags:** question\
**Created:** [February 11, 2019, 6:55am UTC](https://discourse.julialang.org/t/waveform-characterization/20654 "2019-02-11T06:55:18Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![bomber8013](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bomber8013/32/7927_2.png) [@bomber8013](https://discourse.julialang.org/u/bomber8013)\
**Post date:** [February 11, 2019, 6:55am UTC](https://discourse.julialang.org/t/waveform-characterization/20654/1 "2019-02-11T06:55:18Z")

</div>

I am developing a library for basic waveform characterization. Linked [WaveformAnalysis.jl](https://github.com/bomber8013/WaveformAnalysis.jl)

I have a few of the functions done pretty well done in the most efficient way I can think of. I am getting hung up right now with my “pulses” function which will simultaneously measure all of the pulse widths for the given polarity. I am trying to have a more finessed way of handling all the edge cases for a captured waveform. The simplest case (to me) is to count all the positive and negative crosses in the waveform, then subtract either the positives from the negatives for looking for negative pulses or subtracting the positive crosses from the negative crosses to get the positive pulses.

The trouble comes when there are not an equal number of detected edges. I have the incomplete function pasted below: (incomplete because it is missing code to handle negative pulses)

Edit: I think I came up with a good solution, pasted below

```julia
function detectcrosses(x::Vector{T}, thresh::T, edge::Edge) where {T <: Real}
    events = (edge == Rising ? x .>= thresh : x .<= thresh)
    findall(events .& (.~events >> 1))
end

pulses(x::Vector{T}, thresh::T, pol::Polarity) where T <: Real = 
    measurepulses(detectcrosses(x, thresh, Rising), detectcrosses(x, thresh, Falling), pol)

function measurepulses(poscrosses::Vector{T}, negcrosses::Vector{T}, pol::Polarity) where T <: Int64
    if !isempty(poscrosses) && !isempty(negcrosses)
        if pol == ActiveHigh
            alignedges!(poscrosses, negcrosses)
            negcrosses .- poscrosses
        else
            alignedges!(negcrosses, poscrosses)
            poscrosses .- negcrosses
        end
    else
        nothing
    end
end

```

for more context, please take a look at my code in src/WaveformAnalysis.jl. Any additional feedback is welcome for my code not pertaining to my exact question as I am a relatively new Julia coder.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 11, 2019, 7:35am UTC](https://discourse.julialang.org/t/waveform-characterization/20654/2 "2019-02-11T07:35:23Z")

</div>

> [@bomber8013](#):
>
> The trouble comes

It is unclear what you are asking for. Please clarify the actual question, and create a minimal _self-contained_ example.

> [@Please read: make it easier to help you](https://discourse.julialang.org/t/psa-make-it-easier-to-help-you/14757):
>
> Welcome to the Julia Discourse! We are enthusiastic about helping Julia programmers, both beginner and experienced. This public service announcement (PSA) outlines best practices when asking for help. Following these points makes it easier for us to help you and more likely you’ll get a prompt, useful answer. Keywords are highlighted to make it easier to refer to specific points. Choose a descriptive title that captures the key part of your question, eg “plots with multiple axes” instead of …

---

<div class="post-metadata">

**Author:** ![bomber8013](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bomber8013/32/7927_2.png) [@bomber8013](https://discourse.julialang.org/u/bomber8013)\
**Post date:** [February 11, 2019, 8:40am UTC](https://discourse.julialang.org/t/waveform-characterization/20654/3 "2019-02-11T08:40:59Z")

</div>

Thank you for the tips. I am also pretty new at posting to forums in general. The actual question is, is there a more elegant way to align my detected positive and negative edges, then perform the proper subtraction to get either positive pulse width or negative pulse widths. More elegant than brute forcing every conceivable case other than the simplest.

---

<div class="post-metadata">

**Author:** ![MA\_Laforge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ma_laforge/32/385_2.png) [@MA\_Laforge](https://discourse.julialang.org/u/MA_Laforge)\
**Post date:** [July 25, 2019, 10:45pm UTC](https://discourse.julialang.org/t/waveform-characterization/20654/4 "2019-07-25T22:45:57Z")

</div>

Nice vectorized code. Very Matlab-ish… bet maybe even more SKILL/OCEAN-like in my opinion.

### Comments

Your solution looks pretty good. If I understood correctly, after detecting the crosses, you then run those through `alignedges!` to strip off leading edges if they are in the wrong direction.

I myself would have instead detected the first rising edge, then would have run my algorithm from that point on (or vice-versa when looking for negative pulses).

…but that’s not really that important: because at least `alignedges!` only runs on the “crosses” data (which is much more sparse than the original x-vector).

### Julian solution

Although I find creating vecorized code is very elegant in its own way, I personally prefer writing these “base” algorithms with `for` loops. Julia does not get performance enhancements by using vectorized code. In fact, you are probably adding redundant operations when writing code in this “macroscopic fashion”

Though ok for getting a quick-and-dirty first cut, I would personally re-write these “crosses” functions with for loops, and let users of the functions use them in their own quick-and-dirty, one-off algorithms.

Of course, feel free to ignore this suggestion - especially if the performance you get is sufficient for the problems you are trying to solve.

### Alternative (existing) solution

FYI: If I understand what you are trying to do, I think you would be very interested in my CData.jl module:  
 → [GitHub - ma-laforge/CData.jl: C-Data Parametric Analysis/Visualization Suite](https://github.com/ma-laforge/CData.jl)

It is simply a dummy module that pulls in other (not-yet-registered) modules that make data processing of simulation & measurement results much easier to handle. CData.jl includes such things as:

- _ **MDDatasets.jl** _: Handles multi-dimensional data sets & operations on them (Particularly effective when analyzing results from large parametric sweeps of Voltage, Temperature, datarate, etc).
- _ **SignalProcessing.jl** _: Step/pulse responses, Fourier transform/series, PRBS sequences, …:
- _ **CircuitAnalysis.jl** _: Basic circuit analysis tools.
- _ **NetwAnalysis.jl** _: S/Z/Y/H/G/ABCD parameters, …
- _ **InspectDR.jl** _: Efficient/interactive Julia/Gtk plots (Great for bode plots & Smith charts)
- _ **SpiceData.jl** _: Pure-Julia SPICE data file reader
- _ **LibPSF.jl** _: Pure-Julia implementation of 3rd party .psf reader
- _ **PSFWrite.jl** _: Pure-Julia .psf writer

There are examples of things similar to what you are doing in the `SignalProcessing.jl` `sample/` subdirectory.

In particular, I make use of xcross, ycross, delay measurement functions, etc.

You can check out some of the plots it can generate:  
 → [FileRepo/SignalProcessing/sampleplots/README.md at master · ma-laforge/FileRepo · GitHub](https://github.com/ma-laforge/FileRepo/blob/master/SignalProcessing/sampleplots/README.md)

_**PS: `CData.jl` solutions support arbitrary time steps by keeping (t, v(t)) values together in a single data structure (called `DataF1`). That way, you can directly deal with outputs from modern circuit simulators.**_
