From 85396e8c6c70f8ff6dd4f469a75cf2215c7620be Mon Sep 17 00:00:00 2001 From: BANG XIANG YONG Date: Tue, 1 Jun 2021 12:19:30 +0100 Subject: [PATCH 1/4] wip(signal_proc): introduce basic agents for common signal processing --- agentMET4FOF/signal_processing.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 agentMET4FOF/signal_processing.py diff --git a/agentMET4FOF/signal_processing.py b/agentMET4FOF/signal_processing.py new file mode 100644 index 00000000..ebe031a4 --- /dev/null +++ b/agentMET4FOF/signal_processing.py @@ -0,0 +1 @@ +# define FFT agent here \ No newline at end of file From b963e14c1adfb685a41337620f0d558875cdd07c Mon Sep 17 00:00:00 2001 From: BANG XIANG YONG Date: Tue, 1 Jun 2021 14:00:21 +0100 Subject: [PATCH 2/4] wip(signal_processing): example of FFT agent --- agentMET4FOF/signal_processing.py | 48 ++++++++++++++++++- .../signal_processing/fft_example.py | 28 +++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 agentMET4FOF_tutorials/signal_processing/fft_example.py diff --git a/agentMET4FOF/signal_processing.py b/agentMET4FOF/signal_processing.py index ebe031a4..4f78ef43 100644 --- a/agentMET4FOF/signal_processing.py +++ b/agentMET4FOF/signal_processing.py @@ -1 +1,47 @@ -# define FFT agent here \ No newline at end of file +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +from scipy import fftpack + +from agentMET4FOF.agents import AgentMET4FOF + +matplotlib.use("Agg") # for sending plots as images + +class FFT_Agent(AgentMET4FOF): + """ + Buffers the received signal and apply fft on the collected signal upon reaching the `buffer_size` limit. + The buffer then empties and the fft spectrum data and its plot are sent out on `default` and `plot` channel respectively. + + Parameters + ---------- + s_freq : int + Actual sampling frequency for plotting the x-axis + """ + + def init_parameters(self, s_freq=1): + self.s_freq = s_freq + + def on_received_message(self, message): + single_measurement = message["data"] + agent_from = message["from"] + self.buffer.store(data=single_measurement, agent_from=agent_from) + + if self.buffer.buffer_filled(agent_from): + # extract collected signal from buffer + buffered_sig = self.buffer[agent_from] + + # apply fft and convert to amplitudes + sig_fft = fftpack.fft(buffered_sig) + power_amp = np.abs(sig_fft) ** 2 + + # get the corresponding frequencies + sample_freq = fftpack.fftfreq(len(buffered_sig), d=1/self.s_freq) + self.send_output(power_amp) + self.send_plot(self.plot_fft(power_amp, sample_freq)) + self.buffer_clear(agent_from) + + def plot_fft(self, amplitudes, sample_freq): + N = len(amplitudes) + fig = plt.figure() + plt.plot(sample_freq[1:N//2], amplitudes[1:N//2]) + return fig diff --git a/agentMET4FOF_tutorials/signal_processing/fft_example.py b/agentMET4FOF_tutorials/signal_processing/fft_example.py new file mode 100644 index 00000000..62815233 --- /dev/null +++ b/agentMET4FOF_tutorials/signal_processing/fft_example.py @@ -0,0 +1,28 @@ +from agentMET4FOF.agents import AgentNetwork, SineGeneratorAgent, MonitorAgent +from agentMET4FOF.signal_processing import FFT_Agent + + +def main(): + # start agent network server + agentNetwork = AgentNetwork(backend="mesa") + # init agents + gen_agent = agentNetwork.add_agent(agentType=SineGeneratorAgent) + fft_agent = agentNetwork.add_agent(agentType=FFT_Agent, buffer_size=50, s_freq=100) + monitor_agent = agentNetwork.add_agent(agentType=MonitorAgent) + + # connect agents : We can connect multiple agents to any particular agent + agentNetwork.bind_agents(gen_agent, fft_agent) + + # connect + agentNetwork.bind_agents(gen_agent, monitor_agent) + agentNetwork.bind_agents(fft_agent, monitor_agent, channel=["plot"]) + + # set all agents states to "Running" + agentNetwork.set_running_state() + + # allow for shutting down the network after execution + return agentNetwork + + +if __name__ == "__main__": + main() \ No newline at end of file From 7dc341159380c0f62d38c5b6d653312c00094b27 Mon Sep 17 00:00:00 2001 From: BANG XIANG YONG Date: Tue, 1 Jun 2021 14:00:21 +0100 Subject: [PATCH 3/4] wip(signal_proc): example of FFT agent --- agentMET4FOF/signal_processing.py | 48 ++++++++++++++++++- .../signal_processing/fft_example.py | 28 +++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 agentMET4FOF_tutorials/signal_processing/fft_example.py diff --git a/agentMET4FOF/signal_processing.py b/agentMET4FOF/signal_processing.py index ebe031a4..4f78ef43 100644 --- a/agentMET4FOF/signal_processing.py +++ b/agentMET4FOF/signal_processing.py @@ -1 +1,47 @@ -# define FFT agent here \ No newline at end of file +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +from scipy import fftpack + +from agentMET4FOF.agents import AgentMET4FOF + +matplotlib.use("Agg") # for sending plots as images + +class FFT_Agent(AgentMET4FOF): + """ + Buffers the received signal and apply fft on the collected signal upon reaching the `buffer_size` limit. + The buffer then empties and the fft spectrum data and its plot are sent out on `default` and `plot` channel respectively. + + Parameters + ---------- + s_freq : int + Actual sampling frequency for plotting the x-axis + """ + + def init_parameters(self, s_freq=1): + self.s_freq = s_freq + + def on_received_message(self, message): + single_measurement = message["data"] + agent_from = message["from"] + self.buffer.store(data=single_measurement, agent_from=agent_from) + + if self.buffer.buffer_filled(agent_from): + # extract collected signal from buffer + buffered_sig = self.buffer[agent_from] + + # apply fft and convert to amplitudes + sig_fft = fftpack.fft(buffered_sig) + power_amp = np.abs(sig_fft) ** 2 + + # get the corresponding frequencies + sample_freq = fftpack.fftfreq(len(buffered_sig), d=1/self.s_freq) + self.send_output(power_amp) + self.send_plot(self.plot_fft(power_amp, sample_freq)) + self.buffer_clear(agent_from) + + def plot_fft(self, amplitudes, sample_freq): + N = len(amplitudes) + fig = plt.figure() + plt.plot(sample_freq[1:N//2], amplitudes[1:N//2]) + return fig diff --git a/agentMET4FOF_tutorials/signal_processing/fft_example.py b/agentMET4FOF_tutorials/signal_processing/fft_example.py new file mode 100644 index 00000000..62815233 --- /dev/null +++ b/agentMET4FOF_tutorials/signal_processing/fft_example.py @@ -0,0 +1,28 @@ +from agentMET4FOF.agents import AgentNetwork, SineGeneratorAgent, MonitorAgent +from agentMET4FOF.signal_processing import FFT_Agent + + +def main(): + # start agent network server + agentNetwork = AgentNetwork(backend="mesa") + # init agents + gen_agent = agentNetwork.add_agent(agentType=SineGeneratorAgent) + fft_agent = agentNetwork.add_agent(agentType=FFT_Agent, buffer_size=50, s_freq=100) + monitor_agent = agentNetwork.add_agent(agentType=MonitorAgent) + + # connect agents : We can connect multiple agents to any particular agent + agentNetwork.bind_agents(gen_agent, fft_agent) + + # connect + agentNetwork.bind_agents(gen_agent, monitor_agent) + agentNetwork.bind_agents(fft_agent, monitor_agent, channel=["plot"]) + + # set all agents states to "Running" + agentNetwork.set_running_state() + + # allow for shutting down the network after execution + return agentNetwork + + +if __name__ == "__main__": + main() \ No newline at end of file From 6a9171d4d25330fee8cef940367c85e9cda5de29 Mon Sep 17 00:00:00 2001 From: BANG XIANG YONG Date: Tue, 1 Jun 2021 14:02:17 +0100 Subject: [PATCH 4/4] wip(signal_proc): add basic label to plot --- agentMET4FOF/signal_processing.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/agentMET4FOF/signal_processing.py b/agentMET4FOF/signal_processing.py index 4f78ef43..0c6d557e 100644 --- a/agentMET4FOF/signal_processing.py +++ b/agentMET4FOF/signal_processing.py @@ -44,4 +44,6 @@ def plot_fft(self, amplitudes, sample_freq): N = len(amplitudes) fig = plt.figure() plt.plot(sample_freq[1:N//2], amplitudes[1:N//2]) + plt.xlabel("Frequency (Hz)") + plt.ylabel("Power Amplitude") return fig