Hopefully this isn't considered too off-topic. I'm working in industry these days and came up with a solution to a signal processing problem we'd been facing. I'd like to get a sense as to whether said solution has been published before or if there are alternatives I should look at, but I'm having trouble searching for this particular signal scenario. I'll describe the signal structure below, and would appreciate any input on how I should be searching the literature.
So I have two signals: one that is pure noise (noise_only
), and one that is very similar noise plus a target signal of interest (noise_plus_target
). In each signal, the noise is actually made up of multiple somewhat-frequency-distinct signals, and the same set of said noise signals contribute to each observed signals additively but with different weights between the two. In theory, we should be able to use information from the noise_only
signal to help remove the noise from the noise_plus_target
signal, and I've come up with a method to achieve this, but I want to know what other solutions might have been already published for this kind of scenario.
In R, code for generating fake signals that match the characteristics of my real signals would be:
library(tidyverse)
# define a function to generate simple sinusoid given time and hz
sine = function(time,hz) sin(time*(2*pi)*hz)
#define a function to scale values to 0:1
scale01 = function(x) (x - min(x)) / diff(range(x))
#specify sample rate
sample_rate = 10 #in Hz
max_time = 30
#construct a tibble
latent_signals = tibble(
#specify sampling times (in seconds)
time = seq(0,max_time,1/sample_rate) #30s of data
#construct some latent noise signals, each at a decently separated Hz
, noise1 = sine(time,1/11)
, noise2 = sine(time,1/3)
, noise3 = sine(time,1)
#specify a target signal that will be hidden in the noise
# This could take any shape; here I've chosen a bump midway
# through the timeseries
, target = scale01(dnorm(time,mean=max_time/2,sd=3))
)
#show the latent signals
latent_signals %>%
tidyr::pivot_longer(
cols = -time
) %>%
ggplot()+
facet_grid(
name ~ .
)+
geom_line(
mapping = aes(
x = time
, y = value
)
)
#combine the latent signals into two observed signals, with different weights
# for each and the latent target only in one
latent_signals %>%
dplyr::mutate(
noise_only =
noise1*runif(1,.5,1.5) +
noise2*runif(1,.5,1.5) +
noise3*runif(1,.5,1.5)
, noise_plus_target =
noise1*runif(1,.5,1.5) +
noise2*runif(1,.5,1.5) +
noise3*runif(1,.5,1.5) +
target
) %>%
dplyr::select(
time
, contains('_')
) ->
observed_signals
#show the observed signals
observed_signals %>%
tidyr::pivot_longer(
cols = -time
) %>%
ggplot()+
facet_grid(
name ~ .
)+
geom_line(
mapping = aes(
x = time
, y = value
)
)
```