Skip to content

Improve PixelBreath#373

Merged
psomhorst merged 8 commits intomainfrom
fix_skip_pixel
May 26, 2025
Merged

Improve PixelBreath#373
psomhorst merged 8 commits intomainfrom
fix_skip_pixel

Conversation

@psomhorst
Copy link
Copy Markdown
Contributor

PixelBreath skipped entire pixels if only a single breath in a period could not be matched. However, in longer datasets, it is better to skip a few breaths than to fail entirely.

Also, PixelBreath chose single pixel lag based on the maximum cross correlation within 0.75 breaths. This works well if the signal is long and regular, but less so for shorter or slightly irregular data. In this update, PixelBreath detects peaks in the cross correlation signal, and finds the peak that is closest. Only if two peaks have equal distance, the highest value is used.

These issues are difficult to test, other than during real life analysis. No additional tests have been added.


# if there are multiple candidates, take the one with the highest cross correlation
if len(candidates) == 1:
lag = candidates[0]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would lag = candidates[0] always select the highest cross correlation or is the first in the list of candidates not necessarily always the highest?

Copy link
Copy Markdown
Contributor Author

@psomhorst psomhorst May 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect only 1 or 2 candidates ever, because the search space is two breath lengths around the peak of the global timing.

Let's say a breath is 50 frames long. If there is no lag, there will be a peak at -50 (one breath ahead), 0 (the current breath) and 50 (the next breath). The peak detection won't detect peaks that are at the edges due to prominence requirement (peaks have to stick out a minimum above their surroundings; without surroundings, they are not detected). So in that case, only the middle one (at 0) will be detected.

If lag is very low, then the edge peaks still won't be detected, and only the peak near 0 will be detected, due to prominence requirements.

In the case there is more lag, let's say 15, there will be a peak at -35 and 15 (the one at -85 and 65 are outside the search space). The peak at 15 is closest, so that one will be chosen.

The extreme case is when the lag is exactly half the breath (a phase shift of 180 degrees). There is a peak at -25 and one at 25. The timing does not inform us on which one is most probably the related one. In that case, we choose the one with the highest peak, because that indicates better cross correlation between those peaks.

# take the lag with the highest cross correlation
lag = candidates[np.argmax(xcorr[np.searchsorted(lags, candidates)])]
else:
msg = "Too many peaks found in cross correlation."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my understanding, you would expect 2 peaks if the lag is similar to left as to right, correct? What could be an explanation for more than 2 peaks found?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There can never be more than two. The candidates indicate peaks with the shortest distance to 0. This can either be a peak before 0 or after 0. So unless scipy.find_peaks makes a mistake, this should never trigger. However, just to be sure, I do check for a length of 2.

@psomhorst psomhorst merged commit 79bee6d into main May 26, 2025
3 checks passed
@psomhorst psomhorst deleted the fix_skip_pixel branch May 26, 2025 12:27
@psomhorst psomhorst restored the fix_skip_pixel branch May 26, 2025 12:33
@psomhorst psomhorst mentioned this pull request May 26, 2025
@psomhorst psomhorst deleted the fix_skip_pixel branch May 26, 2025 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants