{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "alz1UDNNOuZz", "pycharm": { "name": "#%% md\n" } }, "source": [ "# enDAQ Custom Analysis\n", "\n", "## Introduction\n", "\n", "This notebook and accompanying webinar was developed and released by the [enDAQ team](https://endaq.com/). This is the fifth \"chapter\" of our series on *Python for Mechanical Engineers*:\n", "\n", "1. [Get Started with Python](https://colab.research.google.com/drive/1_pcGtgJleapV9tz5WfuRuqfWryjqhPHy#scrollTo=ikUJITDDIp19)\n", " * Blog: [Get Started with Python: Why and How Mechanical Engineers Should Make the Switch](https://blog.endaq.com/get-started-with-python-why-how-mechanical-engineers-should-make-the-switch)\n", "2. [Introduction to NumPy & Pandas for Data Analysis](https://colab.research.google.com/drive/1O-VwAdRoSlcrineAk0Jkd_fcw7mFGHa4#scrollTo=ce97q1ZcBiwj)\n", "3. [Introduction to Plotly for Plotting Data](https://colab.research.google.com/drive/1pag2pKQQW5amWgRykAH8uMAPqHA2yUfU)\n", "4. [Introduction of the enDAQ Library](https://colab.research.google.com/drive/1WAtQ8JJC_ny0fki7eUABACMA-isZzKB6)\n", " - There are lots of examples in this!\n", "5. **More Examples! (Today's Webinar)**\n", " - Frequency Analysis (FFTs and PSDs)\n", " - Simple Shock Response Spectrums\n", " - Peak Analysis\n", " - Preview `endaq.batch`\n", "\n", "To sign up for future webinars and watch previous ones, [visit our webinars page](https://endaq.com/pages/shock-vibration-webinars). " ] }, { "cell_type": "markdown", "metadata": { "id": "X8lRVbCJY9Ou" }, "source": [ "## Installation\n", "[Available on PyPi](https://pypi.org/project/endaq/) via:\n", "> `pip install endaq`\n", "\n", "For the most recent features that are still under development, you can also use pip to install endaq directly from GitHub:\n", "> `pip install git+https://github.com/MideTechnology/endaq-python.git@development`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "AflWp1TZY7_g", "outputId": "5a338696-def0-41ca-842a-7ddbe526d835" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[K |████████████████████████████████| 71 kB 3.0 MB/s \n", "\u001b[K |████████████████████████████████| 11.3 MB 13.0 MB/s \n", "\u001b[K |████████████████████████████████| 62 kB 749 kB/s \n", "\u001b[K |████████████████████████████████| 38.1 MB 1.3 MB/s \n", "\u001b[K |████████████████████████████████| 93 kB 1.0 MB/s \n", "\u001b[K |████████████████████████████████| 83 kB 1.0 MB/s \n", "\u001b[K |████████████████████████████████| 25.3 MB 51.8 MB/s \n", "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", "google-colab 1.0.0 requires pandas~=1.1.0; python_version >= \"3.0\", but you have pandas 1.3.4 which is incompatible.\n", "google-colab 1.0.0 requires requests~=2.23.0, but you have requests 2.26.0 which is incompatible.\n", "datascience 0.10.6 requires folium==0.2.1, but you have folium 0.8.3 which is incompatible.\n", "albumentations 0.1.12 requires imgaug<0.2.7,>=0.2.5, but you have imgaug 0.2.9 which is incompatible.\u001b[0m\n", "\u001b[K |████████████████████████████████| 79.9 MB 1.2 MB/s \n", "\u001b[?25h" ] } ], "source": [ "!pip install -q endaq\n", "!pip install -q kaleido #this is for rendering images with plotly\n", "exit() #needed in Colab because they pre-load some libraries, wouldn't be neccessary if running locally" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "bFBAOHiQaHuh" }, "outputs": [], "source": [ "import endaq\n", "\n", "endaq.plot.utilities.set_theme(theme='endaq')\n", "\n", "import plotly.express as px\n", "import plotly.graph_objects as go\n", "import plotly.io as pio; pio.renderers.default = \"iframe\"\n", "import pandas as pd\n", "import numpy as np\n", "import scipy" ] }, { "cell_type": "markdown", "metadata": { "id": "eqF9ah--amWu" }, "source": [ "## PSDs & FFTs" ] }, { "cell_type": "markdown", "metadata": { "id": "GfIQqEudaqHj" }, "source": [ "### Simple Sine Wave" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 424 }, "id": "r4Gh0He1aluG", "outputId": "a9e0cca7-512e-4a54-954d-6c3b0d46f15b" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0.8g @ 2 Hz1g @ 3 Hz0.6g @ 5 Hz0.5g @ 4 & 6 Hz0.3g @ 7 Hz
0.000.0000000.0000000.0000000.0000000.000000
0.010.1002670.1873810.1854100.3084070.127734
0.020.1989520.3681250.3526710.5831500.231154
0.030.2945000.5358270.4854100.7946870.290575
0.040.3854030.6845470.5706340.9211770.294686
..................
1.95-0.470228-0.809017-0.600000-0.951057-0.242705
1.96-0.385403-0.684547-0.570634-0.921177-0.294686
1.97-0.294500-0.535827-0.485410-0.794687-0.290575
1.98-0.198952-0.368125-0.352671-0.583150-0.231154
1.99-0.100267-0.187381-0.185410-0.308407-0.127734
\n", "

200 rows × 5 columns

\n", "
" ], "text/plain": [ " 0.8g @ 2 Hz 1g @ 3 Hz 0.6g @ 5 Hz 0.5g @ 4 & 6 Hz 0.3g @ 7 Hz\n", "0.00 0.000000 0.000000 0.000000 0.000000 0.000000\n", "0.01 0.100267 0.187381 0.185410 0.308407 0.127734\n", "0.02 0.198952 0.368125 0.352671 0.583150 0.231154\n", "0.03 0.294500 0.535827 0.485410 0.794687 0.290575\n", "0.04 0.385403 0.684547 0.570634 0.921177 0.294686\n", "... ... ... ... ... ...\n", "1.95 -0.470228 -0.809017 -0.600000 -0.951057 -0.242705\n", "1.96 -0.385403 -0.684547 -0.570634 -0.921177 -0.294686\n", "1.97 -0.294500 -0.535827 -0.485410 -0.794687 -0.290575\n", "1.98 -0.198952 -0.368125 -0.352671 -0.583150 -0.231154\n", "1.99 -0.100267 -0.187381 -0.185410 -0.308407 -0.127734\n", "\n", "[200 rows x 5 columns]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "time = np.linspace(0,2,200,endpoint=False)\n", "\n", "sine_waves = pd.DataFrame(index=time)\n", "sine_waves['0.8g @ 2 Hz'] = 0.8*np.sin(2*np.pi*2 * time)\n", "sine_waves['1g @ 3 Hz'] = np.sin(2*np.pi*3 * time)\n", "sine_waves['0.6g @ 5 Hz'] = 0.6*np.sin(2*np.pi*5 * time)\n", "sine_waves['0.5g @ 4 & 6 Hz'] = 0.5*np.sin(2*np.pi*4 * time) + 0.5*np.sin(2*np.pi*6 * time)\n", "sine_waves['0.3g @ 7 Hz'] = 0.3*np.sin(2*np.pi*7 * time)\n", "\n", "sine_waves" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "J__cGuBQa_xl", "outputId": "ee98e97e-3fcd-48a0-9d67-b654d1e16fe2" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(sine_waves)\n", "fig.update_layout(\n", " title_text='Comparison of Fabricated Sine Waves',\n", " yaxis_title_text='Acceleration (g)',\n", " xaxis_title_text='Time (s)',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "bu5z5Vradrq5" }, "source": [ "Now to compute the PSD on this using `endaq.calc.psd.welch()`, [see docs](https://docs.endaq.com/en/latest/endaq/calc.html#endaq.calc.psd.welch)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "F0AVpLRTcE5J" }, "outputs": [], "source": [ "psd = endaq.calc.psd.welch(sine_waves, bin_width=0.5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "Y0IH7D6GdAOv", "outputId": "a3a5fbd3-9bfe-4a82-b112-27bbb3d627df" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(psd)\n", "fig.update_layout(\n", " title_text='Comparison of the PSD of Two Fabricated Sine Waves',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "8zqwljuynNLj" }, "source": [ "PSDs are the more appropriate way to analyze vibration data for a number of reasons ([see blog](https://blog.endaq.com/why-the-power-spectral-density-psd-is-the-gold-standard-of-vibration-analysis)) but we typically see people want to see the FFT because it's units are easier to intuitively understand.\n", "\n", "In my experience the best way to do this is to compute a PSD using our function with a few modifications:\n", "- Use scaling as `parseval` which means it is `g^2` instead of `g^2/Hz`\n", "- Use a boxcar window so in effect there is no windowing \n", "- Define a very fine bin width\n", "- Set the overlap between FFTs to 0 (not necessary if the bin width is small enough)\n", "- Scale from g^2 as RMS to g-peak via `**2 * (2**0.5)`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 615 }, "id": "qfBH6R5HeCYt", "outputId": "77fc4b52-d4cb-4277-8165-0ecd0e66f723" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.7/dist-packages/scipy/signal/spectral.py:1966: UserWarning:\n", "\n", "nperseg = 1000 is greater than input length = 200, using nperseg = 200\n", "\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fft = endaq.calc.psd.welch(\n", " sine_waves, \n", " scaling='parseval',\n", " window='boxcar',\n", " noverlap=0,\n", " bin_width=0.1, \n", ")\n", "fft = fft**0.5 * (2**0.5) #scale from g^2 as RMS to g-peak\n", "\n", "fig = px.line(fft)\n", "fig.update_layout(\n", " title_text='Comparison of the FFT (from PSD) of Two Fabricated Sine Waves',\n", " yaxis_title_text='Acceleration (g)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " legend_title_text='',\n", " template='endaq_light'\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "eYrBP2h7tTRz" }, "source": [ "### Real Sine Wave\n", "\n", "Let's load a IDE file with `get_doc` [docs](https://docs.endaq.com/en/latest/endaq/ide.html#endaq.ide.get_doc)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 582 }, "id": "wbjU1U2CkZFF", "outputId": "40625d03-3346-45c9-a2f1-8b49a6e05e8b" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 channelnametypeunitsstartenddurationsamplesrate
08.0X (100g)Accelerationg00:00.021800:25.053200:25.03141265755000.07 Hz
18.1Y (100g)Accelerationg00:00.021800:25.053200:25.03141265755000.07 Hz
28.2Z (100g)Accelerationg00:00.021800:25.053200:25.03141265755000.07 Hz
380.0X (40g)Accelerationg00:00.021800:25.054700:25.03281009343985.00 Hz
480.1Y (40g)Accelerationg00:00.021800:25.054700:25.03281009343985.00 Hz
580.2Z (40g)Accelerationg00:00.021800:25.054700:25.03281009343985.00 Hz
636.0Pressure/Temperature:00PressurePa00:00.021700:25.070200:25.0485271.06 Hz
736.1Pressure/Temperature:01Temperature°C00:00.021700:25.070200:25.0485271.06 Hz
870.0XQuaternionq00:00.028400:24.068200:24.0397242499.35 Hz
970.1YQuaternionq00:00.028400:24.068200:24.0397242499.35 Hz
1070.2ZQuaternionq00:00.028400:24.068200:24.0397242499.35 Hz
1170.3WQuaternionq00:00.028400:24.068200:24.0397242499.35 Hz
1259.0Control Pad PressurePressurePa00:00.025100:25.039900:25.014825210.02 Hz
1359.1Control Pad TemperatureTemperature°C00:00.025100:25.039900:25.014825210.02 Hz
1459.2Relative HumidityRelative HumidityRH00:00.025100:25.039900:25.014825210.02 Hz
1576.0LuxLightIll00:00.000000:25.027800:25.02781003.96 Hz
1676.1UVLightIndex00:00.000000:25.027800:25.02781003.96 Hz
\n" ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "doc = endaq.ide.get_doc('https://info.endaq.com/hubfs/100Hz_shake_cal.ide')\n", "endaq.ide.get_channel_table(doc)" ] }, { "cell_type": "markdown", "metadata": { "id": "1ejugSmhWodN" }, "source": [ "Now get the actual data out of one channel with `to_pandas()` [docs](https://docs.endaq.com/en/latest/endaq/ide.html#endaq.ide.to_pandas).\n", "\n", "Then generate a plot with `rolling_min_max_envelope()` ([docs](https://docs.endaq.com/en/latest/endaq/plot.html#endaq.plot.rolling_min_max_envelope)) that will instead of plotting all data points make a shaded plot which will look identical to plotting all points but be more responsive and faster (not entirely necessary on this dataset, but becomes so with larger ones)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "GKiFMxNDepSc", "outputId": "c8866b05-64d9-46f9-c0e3-9aeab3e3e9d9" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "accel = endaq.ide.to_pandas(doc.channels[80], time_mode='seconds')\n", "accel = accel-accel.median() #remove DC offset\n", "endaq.plot.rolling_min_max_envelope(\n", " accel, \n", " plot_as_bars=True,\n", " desired_num_points=1000, \n", " opacity=0.7\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "QjTBIQBEXIPW" }, "source": [ "Here we'll plot the raw data around the peak event with `around_peak()` [docs](https://docs.endaq.com/en/latest/endaq/plot.html#endaq.plot.around_peak)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "L_mco-b6v8s2", "outputId": "73cb641b-360b-45d7-a4ef-dc6294cab28f" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "endaq.plot.around_peak(accel, num=500)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "HEllo_SOe4_M", "outputId": "97c449c8-c1cf-4163-f93a-38587a49d2dd" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fft = endaq.calc.psd.welch(\n", " accel[4.5:9.5], #just do it in time of first dwell\n", " scaling='parseval',\n", " window='boxcar',\n", " noverlap=0,\n", " bin_width=0.5, \n", ")\n", "fft = fft**0.5 * (2**0.5) #scale from g^2 as RMS to g-peak\n", "\n", "fig = px.line(fft[:500])\n", "fig.update_layout(\n", " title_text='FFT (from PSD) of Real World 10.3g Sine Wave',\n", " yaxis_title_text='Acceleration (g)',\n", " xaxis_title_text='Frequency (Hz)',\n", " legend_title_text='',\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "p6xZVN152WKG" }, "source": [ "### Comparing FFT Options" ] }, { "cell_type": "markdown", "metadata": { "id": "lnSl5_5iHBH1" }, "source": [ "#### FFT Option Overview\n", "There are a lot of different ways to compute a FFT in Python. I've been using Welch's method so far but I want to compare that to some other more \"direct\" methods. So let's compare them! First let's conveniently wrap our manipulation of Welch's method PSD into a FFT inside a function." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Zc7xT_qtqiuE" }, "outputs": [], "source": [ "def welch_fft(df, bin_width=0.5):\n", " fft = endaq.calc.psd.welch(df, bin_width=bin_width, scaling='parseval', window='boxcar', noverlap=0)\n", " return fft**0.5 * (2**0.5) #scale from g^2 as RMS to g-peak " ] }, { "cell_type": "markdown", "metadata": { "id": "km7MAPk6q-qz" }, "source": [ "Now let's wrap something around [Numpy's FFT functions](https://numpy.org/doc/stable/reference/routines.fft.html) for a real discrete Fourier transform.\n", "\n", "Notice here we actually have phase information! So we'll return that too." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "lqzGHhbJIQPF" }, "outputs": [], "source": [ "def numpy_fft(df):\n", " \"\"\"\n", " Using Numpy's rfft functions compute a discrete Fourier Transform\n", " \"\"\"\n", " freq = np.fft.rfftfreq(len(df), d=endaq.calc.utils.sample_spacing(df))\n", " df_fft = pd.DataFrame(\n", " np.fft.rfft(df.to_numpy(), axis=0),\n", " index=pd.Series(freq, name=\"frequency (Hz)\"),\n", " columns=df.columns\n", " )\n", " \n", " df_mag = df_fft.apply(np.abs, raw=True) / len(df_fft)\n", " df_phase = df_fft.apply(np.angle, raw=True)\n", "\n", " return df_mag, df_phase" ] }, { "cell_type": "markdown", "metadata": { "id": "env80d2NrsQ8" }, "source": [ "Now we will use the [FFTW algorithm](http://www.fftw.org/) which is available in the [pyFFTW library](https://hgomersall.github.io/pyFFTW/index.html) under a GPL license (which makes it potentially difficult for us to use because we use the more permissive MIT license).\n", "\n", "First let's download it." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "FuwBAXmhqXwR", "outputId": "e2ddc969-5957-42d9-cdb8-d67458acf5de" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[K |████████████████████████████████| 2.6 MB 5.3 MB/s \n", "\u001b[?25h" ] } ], "source": [ "!pip install -q pyfftw" ] }, { "cell_type": "markdown", "metadata": { "id": "M70BmBjKsRvV" }, "source": [ "Now let's use it in a function which allows for a drop-in replacement to the Numpy code. This algorithm is generally regarded as the fastest for computing discrete Fourier transforms - so we'll put it to the test!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "srLXpoPorZAG" }, "outputs": [], "source": [ "import pyfftw\n", "\n", "def fftw_fft(df):\n", " \"\"\"\n", " Using the FFTW algorithm, compute a discrete Fourier Transform\n", " \"\"\"\n", " freq = pyfftw.interfaces.numpy_fft.rfftfreq(len(df), d=endaq.calc.utils.sample_spacing(df))\n", " df_fft = pd.DataFrame(\n", " pyfftw.interfaces.numpy_fft.rfft(df.to_numpy(), axis=0),\n", " index=pd.Series(freq, name=\"frequency (Hz)\"),\n", " columns=df.columns\n", " )\n", " \n", " df_mag = df_fft.apply(np.abs, raw=True) / len(df_fft)\n", " df_phase = df_fft.apply(np.angle, raw=True)\n", "\n", " return df_mag, df_phase " ] }, { "cell_type": "markdown", "metadata": { "id": "KOynQZSisidB" }, "source": [ "Now let's see a FFT result with this library. Note though this will be relatively large to plot..." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "6pzSvrHxI9Bl", "outputId": "fce36862-4d55-4d97-f2ab-2102ed867b86" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fft, phase = fftw_fft(accel[4.5:9.5])\n", "\n", "fig = px.line(fft[80:120])\n", "fig.update_layout(\n", " title_text='FFT using FFTW of Real World 10.3g Sine Wave',\n", " yaxis_title_text='Acceleration (g)',\n", " xaxis_title_text='Frequency (Hz)',\n", " legend_title_text='',\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "L2VL8eTrs_g8" }, "source": [ "Remember one of the benefits of the DFT is to get phase. Although not particularly useful for this dataset let's plot it, notice the shift for the Z axis at the drive frequency." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "GSuYz4-hszDk", "outputId": "8d8b4ae2-b8ec-47e3-cd8c-c29bd1d8cabb" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(phase[80:120])\n", "fig.update_layout(\n", " title_text='Phase using FFTW of Real World 10.3g Sine Wave',\n", " yaxis_title_text='Phase Angle (radians)',\n", " xaxis_title_text='Frequency (Hz)',\n", " legend_title_text='',\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "LolKO3WatUyp" }, "source": [ "#### FFT Option Comparison\n", "\n", "Now let's do the fun part to compare the three approaches! First let's make a sine wave with a bit over 1M points." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "tssZjfjm2n5l" }, "outputs": [], "source": [ "time = np.linspace(0,200,2**20,endpoint=False)\n", "\n", "sine_waves = pd.DataFrame(index=time)\n", "sine_waves['10g @ 100 Hz'] = 10*np.sin(2*np.pi*100 * time)\n", "sine_waves['8g @ 99 Hz'] = 8*np.sin(2*np.pi*99 * time)\n", "sine_waves['6g @ 100.25 Hz'] = 6*np.sin(2*np.pi*100.25 * time)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "0fkEAlQ625ep", "outputId": "efd41b92-6f9f-4cd5-f153-74283d8627d0" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(sine_waves[:0.01])\n", "fig.update_layout(\n", " title_text='Comparison of Fabricated Sine Waves',\n", " yaxis_title_text='Acceleration (g)',\n", " xaxis_title_text='Time (s)',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "iiJz3UOItXSx" }, "outputs": [], "source": [ "from time import process_time\n", "import timeit\n", "pyfftw.forget_wisdom() #FFTW will be faster on subsequent runs\n", "\n", "lengths = [2**14, 16411, 2**17, 131101, 2**20, 1000003]\n", "\n", "ffts = pd.DataFrame()\n", "times = pd.DataFrame()\n", "def melt_fft(fft,name,L):\n", " fft = fft.reset_index().melt(id_vars='frequency (Hz)')\n", " fft['Algo'] = name\n", " fft['Length'] = L\n", " return fft\n", "\n", "def time_fft(func):\n", " return np.array(timeit.repeat(func, number=1, repeat=10)).mean()\n", "\n", "def time_pyfftw(x, threads=1):\n", " pyfftw.forget_wisdom()\n", " rfft = pyfftw.builders.rfft(x, threads=threads, auto_align_input=True)\n", " rfft()\n", " return np.array(timeit.repeat(lambda: rfft(), number=1, repeat=10)).mean()\n", "\n", "for L in lengths:\n", " x = sine_waves.iloc[:L, 0].to_numpy()\n", "\n", " t1 = process_time() \n", " wfft_bin = welch_fft(sine_waves.iloc[:L], bin_width=0.5)\n", "\n", " t2 = process_time() \n", " wfft = welch_fft(sine_waves.iloc[:L], bin_width=1/(L*endaq.calc.utils.sample_spacing(sine_waves)))\n", "\n", " t3 = process_time() \n", " nfft, phase = numpy_fft(sine_waves.iloc[:L])\n", "\n", " t4 = process_time() \n", " fftw, phase = fftw_fft(sine_waves.iloc[:L])\n", "\n", " t5 = process_time() \n", "\n", " times_t = pd.DataFrame(\n", " {'Welch w/ 0.5 Hz Bin':t2-t1,\n", " 'Welch': t3-t2,\n", " 'Numpy':t4-t3,\n", " 'FFTW':t5-t4,\n", " 'Numpy - No OH': time_fft(lambda: np.fft.rfft(x)),\n", " 'FFTW - No OH': time_pyfftw(x, threads=1)\n", " },\n", " index=pd.Series([L],name='Length')\n", " )\n", " times = pd.concat([times,times_t.reset_index().melt(id_vars='Length')])\n", "\n", " wfft_bin = melt_fft(wfft_bin.copy(),'Welch w/ 0.5 Hz Bin',L)\n", " wfft = melt_fft(wfft.copy(),'Welch',L)\n", " nfft = melt_fft(nfft.copy(),'Numpy',L)\n", " fftw = melt_fft(fftw.copy(),'FFTW',L)\n", "\n", " ffts = pd.concat([ffts,wfft_bin,wfft,nfft,fftw]) " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "HZ_uATCOBlR8", "outputId": "3334a780-7558-4487-ebe9-46cdb640db00" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "times['str_len'] = times['Length'].astype('str')\n", "fig = px.bar(\n", " times,\n", " x='str_len',\n", " y='value',\n", " color='variable',\n", " log_y=True,\n", " barmode='group',\n", " labels={'value':'Computation Time (s)','str_len':'Array Length','variable':''}\n", ")\n", "fig.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "n0rf6gV_GX5W", "outputId": "9b9454bb-cad5-4002-bacc-68612a6385e0" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.scatter(\n", " times,\n", " x='str_len',\n", " y='value',\n", " color='variable',\n", " log_y=True,\n", " log_x=True,\n", " labels={'value':'Computation Time (s)','str_len':'Array Length','variable':''}\n", ")\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "5bXza1s0Ep-Q" }, "source": [ "So what does this mean!? FFTW is the fastest as expected, but only if we first structure the data in a more efficient way. But typically you will not have the data structured in this \"optimal\" way for FFTW which means the time it takes to restructure it is real.\n", "\n", "Long story short for *this audience*, using Welch's method is fastest!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "id": "jbZ29eYh6oHM", "outputId": "feba9a15-8328-4076-9bcc-d6b6910bbf9f" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(\n", " ffts[(ffts['frequency (Hz)']>95) & (ffts['frequency (Hz)']<105)],\n", " x='frequency (Hz)',\n", " y='value',\n", " color='Algo',\n", " facet_col='Length',\n", " facet_row='variable',\n", " title='FFTs: Acceleration (g) vs Frequency (Hz)',\n", " labels={'value':'','frequency (Hz)':''}\n", "\n", ")\n", "fig.for_each_annotation(lambda a: a.update(text=a.text.split(\"=\")[-1]))\n", "fig.update_layout(width=1200,height=1000)\n", "fig.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "42Kw_P5-_2Or" }, "outputs": [], "source": [ "fig.write_html('FFT-compare.html',include_plotlyjs='cdn')" ] }, { "cell_type": "markdown", "metadata": { "id": "wjpMqggm0yCA" }, "source": [ "When comparing the actual FFT results we notice that Welch's with a fixed frequency bin width gives us identical results regardless of the time duration we use - **and these are the \"right\" or at least expected result**." ] }, { "cell_type": "markdown", "metadata": { "id": "5Ax16PzO4-SI" }, "source": [ "### Random Vibration (NAVMAT PSD)\n", "\n", "Let's look at the NAVMAT PSD which is as follows: \n", "![](https://info.endaq.com/hubfs/navmat-psd.png)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 455 }, "id": "lKxs7l64fAUs", "outputId": "9c5e02ee-ec19-425e-80e0-32d8affe38c7" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RandomAdd 2g @ 100 HzAdd 2g @ 200 HzAdd 2g @ 400 Hz
Time (s)
0.000000-8.698490e-07-8.698490e-07-8.698490e-07-8.698490e-07
0.0000388.459350e-074.793334e-029.583830e-021.914556e-01
0.0000761.871620e-069.583932e-021.914566e-013.811528e-01
0.0001143.444110e-061.436908e-012.866355e-015.673498e-01
0.0001536.051080e-061.914608e-013.811570e-017.483369e-01
...............
9.9998473.435810e-02-1.571110e-01-3.468213e-01-7.140265e-01
9.9998863.562460e-02-1.080109e-01-2.509046e-01-5.315224e-01
9.9999241.458970e-02-8.125498e-02-1.768794e-01-3.665897e-01
9.9999621.604150e-02-3.183180e-02-7.967766e-02-1.751775e-01
10.000000-2.424250e-04-2.424250e-04-2.424250e-04-2.424250e-04
\n", "

262144 rows × 4 columns

\n", "
" ], "text/plain": [ " Random Add 2g @ 100 Hz Add 2g @ 200 Hz Add 2g @ 400 Hz\n", "Time (s) \n", "0.000000 -8.698490e-07 -8.698490e-07 -8.698490e-07 -8.698490e-07\n", "0.000038 8.459350e-07 4.793334e-02 9.583830e-02 1.914556e-01\n", "0.000076 1.871620e-06 9.583932e-02 1.914566e-01 3.811528e-01\n", "0.000114 3.444110e-06 1.436908e-01 2.866355e-01 5.673498e-01\n", "0.000153 6.051080e-06 1.914608e-01 3.811570e-01 7.483369e-01\n", "... ... ... ... ...\n", "9.999847 3.435810e-02 -1.571110e-01 -3.468213e-01 -7.140265e-01\n", "9.999886 3.562460e-02 -1.080109e-01 -2.509046e-01 -5.315224e-01\n", "9.999924 1.458970e-02 -8.125498e-02 -1.768794e-01 -3.665897e-01\n", "9.999962 1.604150e-02 -3.183180e-02 -7.967766e-02 -1.751775e-01\n", "10.000000 -2.424250e-04 -2.424250e-04 -2.424250e-04 -2.424250e-04\n", "\n", "[262144 rows x 4 columns]" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "navmat = pd.read_csv('https://info.endaq.com/hubfs/navmat-p-9492.csv',delimiter='\\t',header=None,index_col=0,names=['Random'])\n", "navmat.index.name='Time (s)'\n", "\n", "navmat['Add 2g @ 100 Hz'] = navmat.Random + 2*np.sin(2*np.pi*100 * navmat.index)\n", "navmat['Add 2g @ 200 Hz'] = navmat.Random + 2*np.sin(2*np.pi*200 * navmat.index)\n", "navmat['Add 2g @ 400 Hz'] = navmat.Random + 2*np.sin(2*np.pi*400 * navmat.index)\n", "navmat" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "SaSgOjo3fBHU", "outputId": "b89e3fed-a9c9-4482-8f8a-d7af2f5ea47a" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "endaq.plot.rolling_min_max_envelope(navmat, plot_as_bars=True, desired_num_points=500, opacity=0.8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "q7_bjFkfhCnD", "outputId": "e6c61719-9499-4082-ff67-6626361cbf20" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "endaq.plot.around_peak(navmat, num=1000)" ] }, { "cell_type": "markdown", "metadata": { "id": "SkceNo4Sicue" }, "source": [ "#### FFTs" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "b6n5WUGMieEI", "outputId": "67b46696-1f17-4e78-ce54-cd5d4aa679e5" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fft = welch_fft(navmat, bin_width=1)\n", "\n", "fig = px.line(fft[20:2000])\n", "fig.update_layout(\n", " title_text='NAVMAT P-9492 FFT (1 Hz Bin Width)',\n", " yaxis_title_text='Acceleration (g)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " yaxis_type='log',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "wziSme2mjPX6" }, "source": [ "Now let's demonstrate the trouble with FFTs by varying the length of time we'll use and the bin width/resolution in the FFT." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 424 }, "id": "mxheXppNjWeI", "outputId": "66837774-7f4d-4da7-f0b3-ea10b6113224" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
frequency (Hz)variablevalueTimeBin Width
020.000229Random0.2885491.01/T
121.000240Random0.1692841.01/T
222.000252Random0.0993241.01/T
323.000263Random0.1011531.01/T
424.000275Random0.1008441.01/T
..................
7871950.319916Add 2g @ 400 Hz0.38832910.010
7881960.321557Add 2g @ 400 Hz0.36970810.010
7891970.323197Add 2g @ 400 Hz0.33536510.010
7901980.324838Add 2g @ 400 Hz0.37849710.010
7911990.326478Add 2g @ 400 Hz0.34698210.010
\n", "

104548 rows × 5 columns

\n", "
" ], "text/plain": [ " frequency (Hz) variable value Time Bin Width\n", "0 20.000229 Random 0.288549 1.0 1/T\n", "1 21.000240 Random 0.169284 1.0 1/T\n", "2 22.000252 Random 0.099324 1.0 1/T\n", "3 23.000263 Random 0.101153 1.0 1/T\n", "4 24.000275 Random 0.100844 1.0 1/T\n", ".. ... ... ... ... ...\n", "787 1950.319916 Add 2g @ 400 Hz 0.388329 10.0 10\n", "788 1960.321557 Add 2g @ 400 Hz 0.369708 10.0 10\n", "789 1970.323197 Add 2g @ 400 Hz 0.335365 10.0 10\n", "790 1980.324838 Add 2g @ 400 Hz 0.378497 10.0 10\n", "791 1990.326478 Add 2g @ 400 Hz 0.346982 10.0 10\n", "\n", "[104548 rows x 5 columns]" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bins = ['1/T', 1, 10]\n", "times = [1.0, 10]\n", "\n", "ffts = pd.DataFrame()\n", "for bin in bins:\n", " for time in times:\n", " bin_t = bin\n", " if bin=='1/T':\n", " bin_t = 1/time\n", " fft = welch_fft(navmat[:time], bin_width=bin_t)\n", " fft = fft[20:2000].reset_index().melt(id_vars='frequency (Hz)')\n", " fft['Time'] = time\n", " fft['Bin Width'] = bin\n", "\n", " ffts = pd.concat([ffts,fft])\n", "\n", "ffts " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 621 }, "id": "Ae-7ZIMwktyY", "outputId": "d422b438-7833-4684-a535-30b3fc98e3e4" }, "outputs": [ { "data": { "image/svg+xml": [ "2510025100020.0010.010.112510025100022510025100020.0010.010.11RandomAdd 2g @ 100 HzAdd 2g @ 200 HzAdd 2g @ 400 HzFFTs: Acceleration (g) vs Frequency (Hz)Bin Width=1/TBin Width=1Bin Width=10Time=10.0Time=1.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(\n", " ffts,\n", " x='frequency (Hz)',\n", " y='value',\n", " color='variable',\n", " log_y=True,\n", " log_x=True,\n", " facet_row='Time',\n", " facet_col='Bin Width',\n", " title='FFTs: Acceleration (g) vs Frequency (Hz)',\n", " labels={'value':'',\n", " 'frequency (Hz)':'',\n", " 'variable':''}\n", "\n", ")\n", "fig.update_layout(width=800,height=600)\n", "fig.show(renderer='svg')" ] }, { "cell_type": "markdown", "metadata": { "id": "a8Pq8N_OrGIt" }, "source": [ "Our peaks stay consistent around the 2g we'd expect... but what is happening with the other frequency content!?" ] }, { "cell_type": "markdown", "metadata": { "id": "ejhLHC5LhjY-" }, "source": [ "#### PSDs" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "Rtl_6IXkfPDE", "outputId": "f109dbdc-3259-43aa-8cc1-3682a4b0745a" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "psd = endaq.calc.psd.welch(navmat,bin_width=1)\n", "\n", "fig = px.line(psd[20:2000])\n", "fig.update_layout(\n", " title_text='NAVMAT P-9492 PSD (1 Hz Bin Width)',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " yaxis_type='log',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "DImBck5Wn87q" }, "source": [ "Now let's do the same comparison of PSDs" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "swn6aldon7Vc" }, "outputs": [], "source": [ "psds = pd.DataFrame()\n", "for bin in bins:\n", " for time in times:\n", " bin_t = bin\n", " if bin=='1/T':\n", " bin_t = 1/time\n", " psd = endaq.calc.psd.welch(\n", " navmat[:time], bin_width=bin_t)\n", " psd = psd[20:2000].reset_index().melt(id_vars='frequency (Hz)')\n", " psd['Time'] = time\n", " psd['Bin Width'] = bin\n", "\n", " psds = pd.concat([psds,psd])\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 621 }, "id": "qKX3y9xyoQ5y", "outputId": "0589caaf-9fd7-4304-f35d-6b0acac68dcb" }, "outputs": [ { "data": { "image/svg+xml": [ "251002510002100μ0.011251002510002251002510002100μ0.011RandomAdd 2g @ 100 HzAdd 2g @ 200 HzAdd 2g @ 400 HzPSDs: Acceleration (g^2/Hz) vs Frequency (Hz)Bin Width=1/TBin Width=1Bin Width=10Time=10.0Time=1.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(\n", " psds,\n", " x='frequency (Hz)',\n", " y='value',\n", " color='variable',\n", " log_y=True,\n", " log_x=True,\n", " facet_row='Time',\n", " facet_col='Bin Width',\n", " title='PSDs: Acceleration (g^2/Hz) vs Frequency (Hz)',\n", " labels={'value':'',\n", " 'frequency (Hz)':'',\n", " 'variable':''}\n", "\n", ")\n", "fig.update_layout(width=800,height=600)\n", "fig.show(renderer='svg')" ] }, { "cell_type": "markdown", "metadata": { "id": "j-8mf3x6sb9g" }, "source": [ "The peak at those sine tones decrease **yet** the bin width was wider and that sine tone was at one single frequency... so it is less dense. But then the other random/broadband levels are consistent regardless of our length of time or frequency resolution." ] }, { "cell_type": "markdown", "metadata": { "id": "BJUWzIUWs1vU" }, "source": [ "#### PSD Frequency Resolution and Octave Spacing" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "h4xbwf4k9WqQ", "outputId": "ac3ac1b5-7035-4eab-d35e-d282249383bd" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "psd_coarse = endaq.calc.psd.welch(navmat,bin_width=10)\n", "\n", "fig = px.line(psd_coarse[20:2000])\n", "fig.update_layout(\n", " title_text='NAVMAT P-9492 PSD (10 Hz Bin Width)',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " yaxis_type='log',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "nxU8l7H7aH7C" }, "source": [ "Convert to an octave spaced PSD with `to_octave()` [docs](https://docs.endaq.com/en/latest/endaq/calc.html#endaq.calc.psd.to_octave)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 615 }, "id": "hHkHG_hy7-O5", "outputId": "f4742d32-a478-408a-fc03-c3d0ffe056be" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.7/dist-packages/endaq/calc/psd.py:161: RuntimeWarning:\n", "\n", "empty frequency bins in re-binned PSD; original PSD's frequency spacing is too coarse\n", "\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "psd = endaq.calc.psd.welch(navmat,bin_width=1)\n", "oct_psd = endaq.calc.psd.to_octave(psd,fstart=20,octave_bins=3)\n", "\n", "fig = px.line(oct_psd[:2000])\n", "fig.update_layout(\n", " title_text='NAVMAT P-9492 PSD 1/3 Octave',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " yaxis_type='log',\n", " legend_title_text='',\n", " template='endaq_light'\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "9XNWqvofiO6A" }, "source": [ "#### Cumulative Sum from PSD" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "NKFiDLehfQ18", "outputId": "8e199d71-2c66-4964-ffc3-0f620581d763" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "cum_rms = endaq.calc.psd.welch(navmat,bin_width=1, scaling='parseval').cumsum()**0.5\n", "\n", "fig = px.line(cum_rms[10:2000])\n", "fig.update_layout(\n", " title_text='NAVMAT P-9492 PSD with Added Sine Tone',\n", " yaxis_title_text='Cumulative Acceleration RMS (g)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "icuesEzlvXQe" }, "source": [ "### Random Vibration Examples" ] }, { "cell_type": "markdown", "metadata": { "id": "AhFmnVQgwFU_" }, "source": [ "#### Bearing\n", "The first example was the topic of our blog on [top 12 vibration metrics](https://blog.endaq.com/top-vibration-metrics-to-monitor-how-to-calculate-them)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "HRXaJk1b7t0y" }, "outputs": [], "source": [ "bearing = pd.read_csv('https://info.endaq.com/hubfs/Plots/bearing_data.csv', index_col=0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "P4ElVKjgyP_j", "outputId": "64fa17fd-2980-4890-966f-6b2a40258d5f" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "endaq.plot.rolling_min_max_envelope(bearing, plot_as_bars=True, desired_num_points=500, opacity=0.8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "SVxhZB_ivpKf", "outputId": "96d1f222-8be5-43b9-d1a1-c5d7cac60daf" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "psd = endaq.calc.psd.welch(bearing,bin_width=10)\n", "\n", "fig = px.line(psd)\n", "fig.update_layout(\n", " title_text='Bearing Vibration',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " yaxis_type='log',\n", " legend_title_text='',\n", " template='endaq_light'\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "GfqH4MUR4vin" }, "source": [ "#### Car Engine\n", "During a morning commute (many years ago) I mounted an enDAQ sensor to the car's engine." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "yGCEOwp8yIR3" }, "outputs": [], "source": [ "engine = endaq.ide.to_pandas(endaq.ide.get_doc('https://info.endaq.com/hubfs/data/Commute.ide').channels[8])\n", "engine = endaq.calc.filters.butterworth(engine,low_cutoff=1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "QoS4EnbZzqVZ", "outputId": "54fe70f5-8653-4e61-88a3-3bdbb31b2c22" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "endaq.plot.rolling_min_max_envelope(engine, plot_as_bars=True, desired_num_points=500, opacity=0.8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "_kFUezF3zwAH", "outputId": "ab7ba339-36e9-4e56-a31d-fc5b5e51a882" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "psd = endaq.calc.psd.welch(engine,bin_width=1)\n", "\n", "fig = px.line(psd)\n", "fig.update_layout(\n", " title_text='VIbration of an Engine',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " xaxis_title_text='Frequency (Hz)',\n", " xaxis_type='log',\n", " yaxis_type='log',\n", " legend_title_text='',\n", " template='endaq_light'\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "2nRuY9kDaaTd" }, "source": [ "Here we'll use the `octave_spectrogram()` ([see docs](https://docs.endaq.com/en/latest/endaq/plot.html#endaq.plot.octave_spectrogram)) to generate a spectrogram with log spaced frequency bins." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 615 }, "id": "VHud1LUvz8Yg", "outputId": "7a5cd098-74e2-4f80-b6ea-a3d452334c4b" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.7/dist-packages/endaq/calc/psd.py:161: RuntimeWarning:\n", "\n", "empty frequency bins in re-binned PSD; original PSD's frequency spacing is too coarse\n", "\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "data, fig = endaq.plot.octave_spectrogram(engine[['Z']], window=2, bins_per_octave=24, freq_start= 20, max_freq=100)\n", "fig.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "Qyw8YO3-7dTm", "outputId": "0f2aa778-40d8-4f96-f1c9-30c7a05ed64b" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "data = 10 ** (data/10)\n", "\n", "fig = px.line(data[data.index<500].idxmax())\n", "fig.update_layout(\n", " title_text=\"Moving Peak Frequency\",\n", " xaxis_title_text=\"\",\n", " yaxis_title_text=\"Peak Frequency (Hz)\",\n", " showlegend=False\n", ")\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "3HX_lcOoALlE" }, "source": [ "## Quick Poll - What FFT Support Should We Add?\n", "\n", "Remember this is an open source library you can view, comment and \"react\" to feature requests and bug reports. [Here is an \"issue\" created to document this need to add some FFT support](https://github.com/MideTechnology/endaq-python/issues/77)." ] }, { "cell_type": "markdown", "metadata": { "id": "qRmlwPIL9H0q" }, "source": [ "## Simple Shock Response Spectrums\n", "We'll look at two datasets in our [blog on pseudo velocity](https://blog.endaq.com/shock-analysis-response-spectrum-srs-pseudo-velocity-severity)." ] }, { "cell_type": "markdown", "metadata": { "id": "kHcLoeCX4TJF" }, "source": [ "### Punching Bag" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "eX1trxDt7-F0" }, "outputs": [], "source": [ "punch = endaq.ide.to_pandas(endaq.ide.get_doc('https://info.endaq.com/hubfs/data/Punching-Bag.ide').channels[8], time_mode='seconds')\n", "punch = punch - punch.median()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "YQlt4Ot2467H", "outputId": "a1b4ad56-df3f-4d49-9015-389f26a1acfe" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "endaq.plot.rolling_min_max_envelope(punch, plot_as_bars=True, desired_num_points=500, opacity=0.8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "_rOVlHKW4oKN", "outputId": "86a5f0c0-2822-4be4-d26d-9f003fea0a56" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = endaq.plot.around_peak(punch, num=1000, leading_ratio=0.2)\n", "fig.update_layout(\n", " xaxis_title_text='',\n", " yaxis_title_text='Acceleration (g)',\n", " legend_title_text=''\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "8qHf-OC85oAK" }, "source": [ "First determine the frequency bins to calculate it at." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "W0JSBEyX5HmU" }, "outputs": [], "source": [ "freqs = endaq.calc.utils.logfreqs(punch[29:30], bins_per_octave=12)" ] }, { "cell_type": "markdown", "metadata": { "id": "ruLzy4PF5qnp" }, "source": [ "Now perform the shock response spectrum calculation for those frequencies." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "fyB0VVTU5PUN" }, "outputs": [], "source": [ "srs_punch = endaq.calc.shock.shock_spectrum(punch[29:30], freqs=freqs, damp=0.05, mode='srs')" ] }, { "cell_type": "markdown", "metadata": { "id": "D9pthy3B5uFY" }, "source": [ "Now plot!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "i24MklqJ5Yv-", "outputId": "c1f08a14-f476-487b-9b25-d1c993537620" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(srs_punch)\n", "fig.update_layout(\n", " title_text='Shock Response Spectrum (SRS) of Punching Bag',\n", " xaxis_title_text=\"Natural Frequency (Hz)\",\n", " yaxis_title_text=\"Peak Acceleration (g)\",\n", " legend_title_text='',\n", " xaxis_type=\"log\",\n", " yaxis_type=\"log\",\n", " )" ] }, { "cell_type": "markdown", "metadata": { "id": "KGwFHnO95yU0" }, "source": [ "Repeat for the PVSS." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "c4_keEh75z-p" }, "outputs": [], "source": [ "pvss_punch = endaq.calc.shock.shock_spectrum(punch[29:30], freqs=freqs, damp=0.05, mode='pvss')\n", "pvss_punch = pvss_punch*9.81*39.37 #convert to in/s" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "My-wq_nk5-sl", "outputId": "068e8749-8917-4842-be9c-793b129669aa" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(pvss_punch)\n", "fig.update_layout(\n", " title_text='Psuedo Velocity Shock Spectrum (PVSS) of Punching Bag',\n", " xaxis_title_text=\"Natural Frequency (Hz)\",\n", " yaxis_title_text=\"Psuedo Velocity (in/s)\",\n", " legend_title_text='',\n", " xaxis_type=\"log\",\n", " yaxis_type=\"log\",\n", " )" ] }, { "cell_type": "markdown", "metadata": { "id": "dYKMz2cS6Mg_" }, "source": [ "### MIL-S-901D Barge Shock" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "2ETfjuc_6MhG" }, "outputs": [], "source": [ "barge = pd.read_csv('https://info.endaq.com/hubfs/data/mil-s-901d-barge.csv', names=['Time (s)','Accel (g)']).set_index('Time (s)')\n", "barge = barge - barge.median()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "ngM1QP1E6MhG", "outputId": "372f6bf2-4494-4667-d1a1-424beb30ceb2" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "endaq.plot.rolling_min_max_envelope(barge, plot_as_bars=True, desired_num_points=500, opacity=0.8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "zwBlVVmk6MhG", "outputId": "c5523022-3d13-4f04-e9b9-3063a5a0b4df" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = endaq.plot.around_peak(barge, num=1000, leading_ratio=0.2)\n", "fig.update_layout(\n", " xaxis_title_text='',\n", " yaxis_title_text='Acceleration (g)',\n", " showlegend=False\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "ZxdXb1WI6MhG" }, "source": [ "First determine the frequency bins to calculate it at. Here though we will specify an initial frequency of one lower than the duration." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "sWuIfde06MhH", "outputId": "2c31f6d2-089d-4d39-acf5-ca9de80740da" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.7/dist-packages/endaq/calc/utils.py:54: RuntimeWarning:\n", "\n", "the data's duration is too short to accurately represent an initial frequency of 1.000 Hz\n", "\n" ] } ], "source": [ "freqs = endaq.calc.utils.logfreqs(barge, init_freq=1, bins_per_octave=12)" ] }, { "cell_type": "markdown", "metadata": { "id": "UYPBDYsP6MhH" }, "source": [ "Now perform the shock response spectrum calculation for those frequencies." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pohvWwO16MhH" }, "outputs": [], "source": [ "srs_barge = endaq.calc.shock.shock_spectrum(barge, freqs=freqs, damp=0.05, mode='srs')" ] }, { "cell_type": "markdown", "metadata": { "id": "MHribsbi6MhH" }, "source": [ "Now plot!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "Z_H4Cxb76MhH", "outputId": "27662eea-3126-4d9d-e189-0f4fdda534af" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(srs_barge)\n", "fig.update_layout(\n", " title_text='Shock Response Spectrum (SRS) of MIL-S-901 Barge',\n", " xaxis_title_text=\"Natural Frequency (Hz)\",\n", " yaxis_title_text=\"Peak Acceleration (g)\",\n", " legend_title_text='',\n", " xaxis_type=\"log\",\n", " yaxis_type=\"log\",\n", " )" ] }, { "cell_type": "markdown", "metadata": { "id": "8Wv5Tdvb6MhH" }, "source": [ "Repeat for the PVSS." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "iFingnF76MhH" }, "outputs": [], "source": [ "pvss_barge = endaq.calc.shock.shock_spectrum(barge, freqs=freqs, damp=0.05, mode='pvss')\n", "pvss_barge = pvss_barge*9.81*39.37 #convert to in/s" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "AmaR8_sr6MhH", "outputId": "ea822561-b056-4f1b-dad1-79251e780177" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(pvss_barge)\n", "fig.update_layout(\n", " title_text='Psuedo Velocity Shock Spectrum (PVSS) of MIL-S-901 Barge',\n", " xaxis_title_text=\"Natural Frequency (Hz)\",\n", " yaxis_title_text=\"Psuedo Velocity (in/s)\",\n", " legend_title_text='',\n", " xaxis_type=\"log\",\n", " yaxis_type=\"log\",\n", " )" ] }, { "cell_type": "markdown", "metadata": { "id": "hWda1MD48TQp" }, "source": [ "### Compare" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "YTx0tcMD8onu" }, "outputs": [], "source": [ "srs_punch = srs_punch[['Z (100g)']].reset_index().melt(id_vars='frequency (Hz)')\n", "srs_punch['variable'] = 'Punching Bag (80g Peak)'\n", "\n", "srs_barge = srs_barge.reset_index().melt(id_vars='frequency (Hz)')\n", "srs_barge['variable'] = 'MIL-S-901 (600g Peak)'\n", "\n", "srs_combined = pd.concat([srs_punch, srs_barge])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "J4IvNtCD9MwQ", "outputId": "4e87c1f8-c7bc-4d6f-c516-ca0c26586ce7" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(\n", " srs_combined,\n", " x='frequency (Hz)',\n", " y='value',\n", " color='variable'\n", ")\n", "fig.update_layout(\n", " title_text='Shock Response Spectrum (SRS) Comparison',\n", " xaxis_title_text=\"Natural Frequency (Hz)\",\n", " yaxis_title_text=\"Peak Acceleration (g)\",\n", " legend_title_text='',\n", " xaxis_type=\"log\",\n", " yaxis_type=\"log\",\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "l56H-qew95F1" }, "outputs": [], "source": [ "pvss_punch = pvss_punch[['Z (100g)']].reset_index().melt(id_vars='frequency (Hz)')\n", "pvss_punch['variable'] = 'Punching Bag (80g Peak)'\n", "\n", "pvss_barge = pvss_barge.reset_index().melt(id_vars='frequency (Hz)')\n", "pvss_barge['variable'] = 'MIL-S-901 (600g Peak)'\n", "\n", "pvss_combined = pd.concat([pvss_punch, pvss_barge])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "b3IHc2hH-BlC", "outputId": "24a5c818-986b-49cd-91fb-37e8c82526fc" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(\n", " pvss_combined,\n", " x='frequency (Hz)',\n", " y='value',\n", " color='variable'\n", ")\n", "fig.update_layout(\n", " title_text='Psuedo Velocity Shock Spectrum (PVSS) Comparison',\n", " xaxis_title_text=\"Natural Frequency (Hz)\",\n", " yaxis_title_text=\"Psuedo Velocity (in/s)\",\n", " legend_title_text='',\n", " xaxis_type=\"log\",\n", " yaxis_type=\"log\",\n", " )" ] }, { "cell_type": "markdown", "metadata": { "id": "3e-Sqc839KwT" }, "source": [ "## Peak Finding" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "nrkplCzz9NUo" }, "outputs": [], "source": [ "bumps = endaq.ide.to_pandas(endaq.ide.get_doc('https://info.endaq.com/hubfs/data/Robotic-Bumps.ide').channels[80], time_mode='seconds')\n", "bumps = bumps - bumps.median()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "z-RWEAq_9-zg", "outputId": "42cdd54f-3992-4330-afe0-7fc0f0704c0b" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = endaq.plot.rolling_min_max_envelope(bumps, plot_as_bars=True, desired_num_points=500, opacity=0.8)\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "Y8QUlCsE_PtM" }, "source": [ "Now we'll use [SciPy's find_peaks](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html) function to isolate the major events." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "tuxtb-ul-ANi" }, "outputs": [], "source": [ "peak_times, _ = scipy.signal.find_peaks(\n", " x = bumps['Y (40g)'].abs(),\n", " distance = 5 / endaq.calc.utils.sample_spacing(bumps), #spaced 5 seconds apart\n", " height = 8\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "DZj9esZD-cbv" }, "source": [ "Let's add them to the previous plot!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "f81Rh8WRAD2U", "outputId": "1f663af7-f9e8-4427-c334-631de412dff3" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig.add_trace(go.Scatter(\n", " x=bumps.iloc[peak_times].index,\n", " y=bumps.iloc[peak_times]['Y (40g)'],\n", " name='Peaks',\n", " mode='markers',\n", " marker_size=10,\n", " marker_color='#D72D2D'\n", "))\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "UABjVqNp-ftw" }, "source": [ "Now let's plot the peak event with the identified peak." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "EmJFHdOxBOAq", "outputId": "de6adb21-4476-434a-e726-4af40154a9b0" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = endaq.plot.around_peak(bumps, num=1000, leading_ratio=0.2)\n", "fig.update_layout(\n", " xaxis_title_text='',\n", " yaxis_title_text='Acceleration (g)',\n", " legend_title_text=''\n", ")\n", "fig.add_trace(go.Scatter(\n", " x=[bumps.iloc[peak_times[2]].name],\n", " y=[bumps.iloc[peak_times[2]]['Y (40g)']],\n", " name='Peak',\n", " mode='markers',\n", " marker_size=10,\n", " marker_color='#D72D2D'\n", "))\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "fAY9yhSW_Gy7" }, "source": [ "### PVSS of Full Time History" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "OJD2QG7RFf8q" }, "outputs": [], "source": [ "freqs = endaq.calc.utils.logfreqs(bumps, init_freq=1, bins_per_octave=12)\n", "pvss_bumps = endaq.calc.shock.shock_spectrum(bumps, freqs=freqs, damp=0.05, mode='pvss')\n", "pvss_bumps = pvss_bumps*9.81*39.37 #convert to in/s" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "m4ACF6lW_UsN", "outputId": "77195543-f760-4f52-8c0f-783422462359" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(pvss_bumps)\n", "fig.update_layout(\n", " title_text='Psuedo Velocity Shock Spectrum (PVSS) of Robotic \"Bumps\"',\n", " xaxis_title_text=\"Natural Frequency (Hz)\",\n", " yaxis_title_text=\"Psuedo Velocity (in/s)\",\n", " legend_title_text='',\n", " xaxis_type=\"log\",\n", " yaxis_type=\"log\",\n", " )" ] }, { "cell_type": "markdown", "metadata": { "id": "cMjIA8WkBp_Z" }, "source": [ "You may be surprised to see the X axis actually had higher peak velocities than the Y axis because of where the frequency content lies!" ] }, { "cell_type": "markdown", "metadata": { "id": "X1mWVqb4CEFS" }, "source": [ "### Loop Through All Peaks" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "i9yq9-1t_sDj" }, "outputs": [], "source": [ "pvss_all = pd.DataFrame()\n", "\n", "for peak in peak_times:\n", " freqs = endaq.calc.utils.logfreqs(bumps.iloc[peak-1000:peak+4000], init_freq=1, bins_per_octave=12)\n", " pvss = endaq.calc.shock.shock_spectrum(bumps.iloc[peak-1000:peak+4000], freqs=freqs, damp=0.05, mode='pvss')*9.81*39.37 #convert to in/s\n", " pvss = pvss.reset_index().melt(id_vars='frequency (Hz)')\n", " pvss['Peak'] = np.abs(bumps.iloc[peak]['Y (40g)'])\n", " pvss['Time'] = bumps.index[peak]\n", "\n", " pvss_all = pd.concat([pvss_all,pvss])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "WmhpLZGTCz8z", "outputId": "2bb346b9-2ac4-4924-8fec-86cdd7c8d4b4" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "pvss_all['Peak'] = np.round(pvss_all['Peak'],1)\n", "fig = px.line(\n", " pvss_all,\n", " x='frequency (Hz)',\n", " y='value',\n", " facet_col='variable',\n", " color='Peak',\n", " hover_data=['value','Time'],\n", " log_x=True,\n", " log_y=True,\n", " title='Comparison of PVSS for Each Event',\n", " labels={'value':'Peak Pseudo Velocity (in/s)','frequency (Hz)':''}\n", ")\n", "fig.for_each_annotation(lambda a: a.update(text=a.text.split(\"=\")[-1]))\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "KZjxQvH1HA0g" }, "source": [ "Notice how the peak at 23.5g has a pseudo velocity about 1/2 that compared to the peak at virtually all the other events, including the one at 12.8g." ] }, { "cell_type": "markdown", "metadata": { "id": "T4DzMpJjItv9" }, "source": [ "## Preview of Batch\n", "\n", "This is currently available, [see docs](https://docs.endaq.com/en/latest/endaq/batch.html), but we are working on a few bug fixes and improved functionality. This module allows you to batch process many *IDE* (only works for our sensors for now).\n", "\n", "In a separate document I first executed the following code to gather all the .IDE files I wanted to analyze (I hide the actual folder name).\n", "~~~python\n", "import glob\n", "directory = r\"C:\\Users\\shanly\\enDAQ-Notebooks\\...\"+\"\\\\\"\n", "\n", "files = glob.glob(directory+\"*.ide*\") #get all the files in that directory with a .ide extension\n", "~~~\n", "\n", "Then with this list of files, I performed the batch operation with the following.\n", "~~~python\n", "calc_output = (\n", " endaq.batch.GetDataBuilder(accel_highpass_cutoff=1)\n", " .add_psd(freq_bin_width=1)\n", " .add_metrics()\n", " .aggregate_data(files)\n", ")\n", "file_data = calc_output.dataframes\n", "~~~\n", "\n", "Then I saved the output dataframes of interest to pickles that I will load next!\n", "~~~python\n", "file_data['psd'].to_pickle('batch_psd.pkl', protocol=4)\n", "file_data['metrics'].to_pickle('batch_metrics.pkl', protocol=4)\n", "~~~\n", "\n", "Note that I obscured the actual filenames (that would have contained the path) with these lines prior to saving.\n", "~~~python\n", "file_data['metrics'].filename = file_data['metrics'].filename.str.split('\\\\').str[-1].str.split('.IDE').str[0]\n", "file_data['psd'].filename = file_data['psd'].filename.str.split('\\\\').str[-1].str.split('.IDE').str[0]\n", "~~~" ] }, { "cell_type": "markdown", "metadata": { "id": "k5V24PxRMIrx" }, "source": [ "### Metrics" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 424 }, "id": "-_XlaHFcJXge", "outputId": "25882b62-871c-4527-a612-8b3fe2fd49d1" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
filenamecalculationaxisvalueserial numberstart time
0DAQ11409_000061RMS AccelerationX (40g)0.050146114092021-10-27 17:33:19.722259
1DAQ11409_000061RMS VelocityX (40g)44.938216114092021-10-27 17:33:19.722259
2DAQ11409_000061RMS DisplacementX (40g)5.836992114092021-10-27 17:33:19.722259
3DAQ11409_000061Peak Absolute AccelerationX (40g)0.906830114092021-10-27 17:33:19.722259
4DAQ11409_000061Peak Pseudo Velocity Shock SpectrumX (40g)0.002361114092021-10-27 17:33:19.722259
.....................
148258DAQ11409_005795RMS Angular VelocityX1.541428114092021-11-16 19:52:53.617858
148259DAQ11409_005795RMS Angular VelocityY0.344340114092021-11-16 19:52:53.617858
148260DAQ11409_005795RMS Angular VelocityZ0.057123114092021-11-16 19:52:53.617858
148261DAQ11409_005795Average TemperaturePressure/Temperature:0015.580078114092021-11-16 19:52:53.617858
148262DAQ11409_005795Average TemperatureControl Pad Pressure89.527103114092021-11-16 19:52:53.617858
\n", "

148263 rows × 6 columns

\n", "
" ], "text/plain": [ " filename ... start time\n", "0 DAQ11409_000061 ... 2021-10-27 17:33:19.722259\n", "1 DAQ11409_000061 ... 2021-10-27 17:33:19.722259\n", "2 DAQ11409_000061 ... 2021-10-27 17:33:19.722259\n", "3 DAQ11409_000061 ... 2021-10-27 17:33:19.722259\n", "4 DAQ11409_000061 ... 2021-10-27 17:33:19.722259\n", "... ... ... ...\n", "148258 DAQ11409_005795 ... 2021-11-16 19:52:53.617858\n", "148259 DAQ11409_005795 ... 2021-11-16 19:52:53.617858\n", "148260 DAQ11409_005795 ... 2021-11-16 19:52:53.617858\n", "148261 DAQ11409_005795 ... 2021-11-16 19:52:53.617858\n", "148262 DAQ11409_005795 ... 2021-11-16 19:52:53.617858\n", "\n", "[148263 rows x 6 columns]" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "metrics = pd.read_pickle('https://info.endaq.com/hubfs/data/batch_metrics.pkl')\n", "metrics" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "9WLryPTyKfjI", "outputId": "59c72c3e-4f51-4750-f9fb-40fa202c8cb1" }, "outputs": [ { "data": { "text/plain": [ "array(['RMS Acceleration', 'RMS Velocity', 'RMS Displacement',\n", " 'Peak Absolute Acceleration',\n", " 'Peak Pseudo Velocity Shock Spectrum', 'RMS Angular Velocity',\n", " 'Average Temperature'], dtype=object)" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "metrics.calculation.unique()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 617 }, "id": "lFp9yt78MNQ5", "outputId": "0f24e8fc-263a-4e14-a277-fdabdcb4e6b8" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.scatter(\n", " metrics[metrics.calculation.isin(['RMS Acceleration', \n", " 'RMS Displacement',\n", " 'Peak Absolute Acceleration'])],\n", " x='start time',\n", " y='value',\n", " facet_col='calculation',\n", " facet_col_wrap=1,\n", " color='axis',\n", " labels={'value':'',\n", " 'start time':'',\n", " 'axis':''\n", " },\n", " hover_data=['filename']\n", ")\n", "fig.update_layout(height=600)\n", "fig.for_each_annotation(lambda a: a.update(text=a.text.split(\"=\")[-1]))\n", "fig.update_yaxes(matches=None)\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "hJg3X6I6OA-N" }, "source": [ "### PSDs" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 424 }, "id": "_Iokbw5kMUkZ", "outputId": "0d0d3439-bab7-4216-96fd-1a9e742e3b64" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
filenameaxisfrequency (Hz)valueserial numberstart time
0DAQ11409_000061X (40g)0.0000007.402487e-10114092021-10-27 17:33:19.722259
1DAQ11409_000061Y (40g)0.0000002.419061e-08114092021-10-27 17:33:19.722259
2DAQ11409_000061Z (40g)0.0000004.245836e-09114092021-10-27 17:33:19.722259
3DAQ11409_000061Resultant0.0000002.917670e-08114092021-10-27 17:33:19.722259
4DAQ11409_000061X (40g)1.0035054.808626e-09114092021-10-27 17:33:19.722259
.....................
2876195DAQ11409_005795Resultant124.4489577.143454e-08114092021-11-16 19:52:53.617858
2876196DAQ11409_005795X (40g)125.4525781.768300e-08114092021-11-16 19:52:53.617858
2876197DAQ11409_005795Y (40g)125.4525783.348997e-09114092021-11-16 19:52:53.617858
2876198DAQ11409_005795Z (40g)125.4525785.949278e-08114092021-11-16 19:52:53.617858
2876199DAQ11409_005795Resultant125.4525788.052478e-08114092021-11-16 19:52:53.617858
\n", "

2876200 rows × 6 columns

\n", "
" ], "text/plain": [ " filename axis ... serial number start time\n", "0 DAQ11409_000061 X (40g) ... 11409 2021-10-27 17:33:19.722259\n", "1 DAQ11409_000061 Y (40g) ... 11409 2021-10-27 17:33:19.722259\n", "2 DAQ11409_000061 Z (40g) ... 11409 2021-10-27 17:33:19.722259\n", "3 DAQ11409_000061 Resultant ... 11409 2021-10-27 17:33:19.722259\n", "4 DAQ11409_000061 X (40g) ... 11409 2021-10-27 17:33:19.722259\n", "... ... ... ... ... ...\n", "2876195 DAQ11409_005795 Resultant ... 11409 2021-11-16 19:52:53.617858\n", "2876196 DAQ11409_005795 X (40g) ... 11409 2021-11-16 19:52:53.617858\n", "2876197 DAQ11409_005795 Y (40g) ... 11409 2021-11-16 19:52:53.617858\n", "2876198 DAQ11409_005795 Z (40g) ... 11409 2021-11-16 19:52:53.617858\n", "2876199 DAQ11409_005795 Resultant ... 11409 2021-11-16 19:52:53.617858\n", "\n", "[2876200 rows x 6 columns]" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psd = pd.read_pickle('https://info.endaq.com/hubfs/data/batch_psd.pkl')\n", "psd" ] }, { "cell_type": "markdown", "metadata": { "id": "rMyNW3qqOhNj" }, "source": [ "Now we want to aggregate this see how things changed over time. So we'll round the frequency values and focus on one axis. For readability we'll also make a new column that will display time into the test in days." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 424 }, "id": "Tu5mIGeKOa7n", "outputId": "df875eb0-edd4-4217-df91-c33821b850f4" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
filenameaxisfrequency (Hz)valueserial numberstart timeTest Day
1DAQ11409_000061Y (40g)0.02.419061e-08114092021-10-27 17:33:19.7222590.000
5DAQ11409_000061Y (40g)1.02.557175e-07114092021-10-27 17:33:19.7222590.000
9DAQ11409_000061Y (40g)2.02.522567e-06114092021-10-27 17:33:19.7222590.000
13DAQ11409_000061Y (40g)3.01.247001e-06114092021-10-27 17:33:19.7222590.000
17DAQ11409_000061Y (40g)4.07.596711e-08114092021-10-27 17:33:19.7222590.000
........................
2876181DAQ11409_005795Y (40g)121.01.037411e-08114092021-11-16 19:52:53.61785820.097
2876185DAQ11409_005795Y (40g)122.06.082880e-09114092021-11-16 19:52:53.61785820.097
2876189DAQ11409_005795Y (40g)123.05.461760e-09114092021-11-16 19:52:53.61785820.097
2876193DAQ11409_005795Y (40g)124.04.885745e-09114092021-11-16 19:52:53.61785820.097
2876197DAQ11409_005795Y (40g)125.03.348997e-09114092021-11-16 19:52:53.61785820.097
\n", "

719050 rows × 7 columns

\n", "
" ], "text/plain": [ " filename axis ... start time Test Day\n", "1 DAQ11409_000061 Y (40g) ... 2021-10-27 17:33:19.722259 0.000\n", "5 DAQ11409_000061 Y (40g) ... 2021-10-27 17:33:19.722259 0.000\n", "9 DAQ11409_000061 Y (40g) ... 2021-10-27 17:33:19.722259 0.000\n", "13 DAQ11409_000061 Y (40g) ... 2021-10-27 17:33:19.722259 0.000\n", "17 DAQ11409_000061 Y (40g) ... 2021-10-27 17:33:19.722259 0.000\n", "... ... ... ... ... ...\n", "2876181 DAQ11409_005795 Y (40g) ... 2021-11-16 19:52:53.617858 20.097\n", "2876185 DAQ11409_005795 Y (40g) ... 2021-11-16 19:52:53.617858 20.097\n", "2876189 DAQ11409_005795 Y (40g) ... 2021-11-16 19:52:53.617858 20.097\n", "2876193 DAQ11409_005795 Y (40g) ... 2021-11-16 19:52:53.617858 20.097\n", "2876197 DAQ11409_005795 Y (40g) ... 2021-11-16 19:52:53.617858 20.097\n", "\n", "[719050 rows x 7 columns]" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psd['frequency (Hz)'] = np.round(psd['frequency (Hz)'] ,0) \n", "psd['start time'] = pd.to_datetime(psd['start time'])\n", "psd['Test Day'] = psd['start time']-psd['start time'].iloc[0]\n", "psd['Test Day'] = np.round(psd['Test Day'].dt.total_seconds()/60/60/24,3)\n", "\n", "psd_y = psd[psd.axis=='Y (40g)'].copy()\n", "psd_y" ] }, { "cell_type": "markdown", "metadata": { "id": "_riFQQb1pnGc" }, "source": [ "#### 2D Waterfall\n", "Let's see how the PSD changes over time in a 2D plot with a bunch of lines (one per time). To help with the visualization we first need to get a bunch of colors to map to." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "nn5t5AYrsqhJ" }, "outputs": [], "source": [ "from plotly import colors\n", "num_colors = len(psd_y[psd_y['Test Day']<1]['Test Day'].unique())\n", "color_steps = colors.sample_colorscale(px.colors.sequential.Turbo, num_colors)" ] }, { "cell_type": "markdown", "metadata": { "id": "4bIWPS0Ws9gz" }, "source": [ "Now we can make the plot!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 817 }, "id": "3SkuF9QQqK_s", "outputId": "e372b22f-cd22-4968-ce89-470852456a29" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(\n", " psd_y[psd_y['Test Day']<1],\n", " x='frequency (Hz)',\n", " y='value',\n", " color='Test Day',\n", " hover_data=['filename','start time'],\n", " color_discrete_sequence = color_steps\n", ")\n", "fig.update_layout(\n", " xaxis_title_text='Frequency (Hz)',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " legend_title_text='',\n", " legend_y=-0.7,\n", " height=800,\n", " xaxis_type='log',\n", " yaxis_type='log',\n", " template='endaq_light'\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "mGMAzBlepqcL" }, "source": [ "#### 3D Waterfall\n", "I know everyone wants to see the 3D view..." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "0TvFwjsTtRvA", "outputId": "061ffcf0-0b0e-47f0-9a87-6d78efe69bda" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line_3d(\n", " psd_y[psd_y['Test Day']<1],\n", " x='frequency (Hz)',\n", " z='value',\n", " y='Test Day',\n", " color='Test Day',\n", " hover_data=['filename','start time'],\n", " color_discrete_sequence = color_steps,\n", " log_x=True,\n", " log_z=True,\n", " labels={'value':'Acceleration (g^2/Hz)','frequency (Hz)':'Frequency (Hz)'}\n", ")\n", "fig.update_layout(\n", " title_text='3D Waterfall Plot',\n", " showlegend = False,\n", " margin=dict(l=20, r=20, t=20, b=20),\n", " template='endaq_light'\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Cf3O514N8Js6" }, "outputs": [], "source": [ "fig.write_html('3d-waterfall.html',include_plotlyjs='cdn')" ] }, { "cell_type": "markdown", "metadata": { "id": "SrqlEq3pRQxw" }, "source": [ "#### Animation\n", "This let's us create animations which I'll first do on the first day's worth of data." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "YlHvF4gVPieA", "outputId": "0d90a57c-55e4-4e96-eb6d-24ff99a89d90" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(\n", " psd_y[psd_y['Test Day']<1],\n", " x='frequency (Hz)',\n", " y='value',\n", " animation_frame='Test Day',\n", " hover_data=['filename','start time']\n", ")\n", "fig.update_layout(\n", " xaxis_title_text='Frequency (Hz)',\n", " yaxis_title_text='Acceleration (g^2/Hz)',\n", " legend_title_text='',\n", " xaxis_type='log',\n", " yaxis_type='log',\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "iFv3nr5DPBhj" }, "source": [ "That's pretty cool! But we'll notice that the animation moves outside the initial bounds pretty quickly. So let's first find an easy way to calculate these metrics of max/min/median per frequency bin." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 509 }, "id": "z55S6RjuSJLQ", "outputId": "85f246c6-6f29-4362-f3eb-439c53e437bc" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
start time2021-10-27 17:33:19.7222592021-10-27 17:38:21.1017152021-10-27 17:43:22.4824522021-10-27 17:48:23.8706052021-10-27 17:53:25.2546992021-10-27 17:58:26.6389772021-10-27 18:03:28.0098572021-10-27 18:08:29.3890682021-10-27 18:13:30.7757562021-10-27 18:18:32.1466972021-10-27 18:23:33.5141292021-10-27 18:28:34.8937682021-10-27 18:33:36.2686462021-10-27 18:38:37.6575012021-10-27 18:43:39.0368042021-10-27 18:48:40.4316102021-10-27 18:53:41.8124692021-10-27 18:58:43.1904902021-10-27 19:03:44.5748902021-10-27 19:08:45.9547722021-10-27 19:13:47.3428952021-10-27 19:18:48.7198482021-10-27 19:23:50.0963432021-10-27 19:28:51.4765012021-10-27 19:33:52.8562012021-10-27 19:38:54.2391962021-10-27 19:43:55.6224362021-10-27 19:48:57.0171812021-10-27 19:53:58.4018552021-10-27 19:58:59.7861932021-10-27 20:04:01.1824952021-10-27 20:09:02.5738522021-10-27 20:14:03.9646602021-10-27 20:19:05.5600892021-10-27 20:24:06.9494932021-10-27 20:29:08.3415522021-10-27 20:34:09.7370912021-10-27 20:39:11.1294252021-10-27 20:44:12.7134702021-10-27 20:49:14.100280...2021-11-16 16:35:08.2461852021-11-16 16:40:12.4549562021-11-16 16:45:16.6629022021-11-16 16:50:20.8655392021-11-16 16:55:25.0785212021-11-16 17:00:29.3117372021-11-16 17:05:33.5187072021-11-16 17:10:37.7325432021-11-16 17:15:41.9676812021-11-16 17:20:46.1733392021-11-16 17:25:50.5851742021-11-16 17:30:54.8143612021-11-16 17:35:59.0422052021-11-16 17:41:03.2597352021-11-16 17:46:07.4860532021-11-16 17:51:11.6971742021-11-16 17:56:15.9344482021-11-16 18:01:20.1568292021-11-16 18:06:24.3807672021-11-16 18:11:28.6036682021-11-16 18:16:32.8357842021-11-16 18:21:37.0549922021-11-16 18:26:41.7786252021-11-16 18:31:45.9855952021-11-16 18:36:50.2034302021-11-16 18:41:54.4235532021-11-16 18:46:58.6312862021-11-16 18:52:02.8399352021-11-16 18:57:07.0762322021-11-16 19:02:11.2961422021-11-16 19:07:15.5284112021-11-16 19:12:19.7420042021-11-16 19:17:23.9863282021-11-16 19:22:28.2190852021-11-16 19:27:32.4388732021-11-16 19:32:36.6621092021-11-16 19:37:40.9121092021-11-16 19:42:45.1522522021-11-16 19:47:49.3796992021-11-16 19:52:53.617858
frequency (Hz)
0.02.419061e-086.961451e-092.694621e-080.0000040.0000080.0000030.0000030.0000030.0000010.0000020.0000040.0000050.0000080.0000030.0000020.0000030.0000020.0000020.0000050.0000020.0000010.0000039.199357e-070.0000031.518771e-060.0000020.0000022.163578e-060.0000080.0000020.0000043.760117e-068.331635e-070.0000022.212025e-061.235489e-062.958984e-061.301514e-061.982634e-060.000005...0.0000033.022666e-064.218103e-060.0000083.078788e-060.0000022.032640e-067.642987e-062.100572e-063.379650e-062.492302e-069.384487e-062.791448e-062.543345e-060.0000022.078568e-068.132484e-072.838021e-060.0000044.413651e-060.0000026.958460e-060.0000052.259085e-062.582262e-068.285179e-060.0000047.115846e-061.923488e-061.178528e-060.0000051.850663e-075.758527e-084.356333e-081.326678e-083.523284e-083.401198e-089.321506e-082.072132e-075.329716e-08
1.02.557175e-078.999609e-081.926265e-070.0000340.0000550.0000410.0000370.0000200.0000220.0000160.0000450.0000520.0000490.0000390.0000260.0000320.0000110.0000270.0000510.0000380.0000070.0000151.105532e-050.0000361.671067e-050.0000230.0000261.953543e-050.0000870.0000310.0000414.049195e-051.907499e-050.0000322.385972e-051.026427e-052.749858e-051.615311e-052.693152e-050.000080...0.0000572.867848e-055.494686e-050.0000591.791955e-050.0000253.726021e-057.125737e-052.376242e-053.463165e-052.879028e-054.655712e-057.107180e-054.406466e-050.0000654.128956e-051.860609e-054.077474e-050.0000338.258510e-050.0000147.395578e-050.0000572.943697e-053.235613e-051.141953e-040.0001035.089320e-053.296615e-052.210161e-050.0000581.788990e-066.666895e-074.819046e-076.939725e-073.583268e-078.923644e-071.693514e-065.189828e-063.352921e-07
2.02.522567e-066.889837e-072.332143e-060.0002080.0002980.0002020.0001040.0001180.0001020.0000770.0001930.0002660.0002510.0001460.0001300.0001450.0000730.0001500.0002300.0001550.0000440.0000974.346807e-050.0001996.920640e-050.0000990.0001049.560500e-050.0005490.0001160.0002473.122200e-041.225986e-040.0001191.170403e-044.953305e-051.380503e-041.002347e-041.661748e-040.000339...0.0002341.086385e-043.531844e-040.0002711.440112e-040.0001482.247540e-043.794856e-041.091585e-041.625495e-042.139703e-042.784456e-043.102676e-042.197761e-040.0002482.685322e-047.470985e-052.238129e-040.0002085.037352e-040.0000945.531540e-040.0004721.668488e-041.696425e-045.673354e-040.0005133.158666e-041.340000e-041.496420e-040.0003831.414038e-054.116737e-063.061537e-063.137081e-062.238157e-063.732002e-068.260310e-062.382195e-053.364408e-06
3.01.247001e-063.708911e-071.238390e-060.0001220.0001550.0001510.0000530.0000660.0000590.0000410.0001160.0001330.0001480.0000810.0000590.0000730.0000370.0000560.0001240.0000730.0000260.0000693.026884e-050.0001044.267918e-050.0000570.0000436.355741e-050.0002160.0000540.0001321.861895e-046.389375e-050.0000797.598246e-054.548199e-056.775841e-056.932025e-058.357926e-050.000180...0.0001376.661549e-052.033306e-040.0001781.262726e-040.0000821.100094e-041.730692e-045.929123e-051.030920e-041.313220e-042.379084e-041.730239e-041.114687e-040.0001041.285181e-043.582072e-051.165774e-040.0001161.988762e-040.0000672.372616e-040.0002521.024006e-041.111846e-042.714036e-040.0002222.389278e-049.763413e-058.946194e-050.0001498.732022e-062.575371e-061.443267e-061.056115e-061.322230e-062.146535e-064.270818e-061.430278e-052.720061e-06
4.07.596711e-083.332906e-082.693014e-070.0000260.0000260.0000320.0000230.0000200.0000270.0000120.0000330.0000230.0000340.0000200.0000140.0000180.0000090.0000190.0000360.0000240.0000080.0000229.036514e-060.0000251.038904e-050.0000170.0000131.145624e-050.0000390.0000130.0000383.526670e-051.801536e-050.0000191.389114e-056.302247e-062.129335e-051.779139e-051.426981e-050.000043...0.0000591.420008e-052.916908e-050.0000331.532318e-050.0000161.920946e-055.402916e-051.619829e-054.107995e-052.308721e-056.647677e-055.163262e-052.292783e-050.0000373.134771e-058.408034e-062.837890e-050.0000284.000348e-050.0000185.138282e-050.0000512.366792e-052.534139e-057.182962e-050.0000815.186834e-052.924370e-052.360597e-050.0000561.866866e-061.077818e-066.921128e-072.991976e-071.100801e-074.083279e-073.597081e-071.828241e-064.625317e-07
......................................................................................................................................................................................................................................................
122.04.794718e-081.403580e-091.555955e-090.0000020.0000130.0000170.0000020.0000030.0000030.0000020.0000020.0000060.0000040.0000020.0000040.0000090.0000210.0000200.0000190.0000070.0000080.0000066.404928e-060.0000121.515504e-050.0000120.0000031.431891e-050.0000080.0000040.0000032.263224e-061.028560e-050.0000024.241913e-064.873168e-061.225941e-063.019433e-061.951890e-060.000002...0.0000122.195231e-052.106803e-050.0000121.830445e-050.0000101.882487e-052.267166e-055.221777e-062.167978e-051.289279e-051.664051e-051.671418e-055.891856e-060.0000151.482488e-051.265719e-051.252918e-050.0000152.233010e-050.0000081.701158e-050.0000074.759324e-061.749558e-056.335562e-060.0000062.069402e-051.063007e-057.831063e-060.0000116.039101e-094.662815e-093.121494e-095.535294e-099.558629e-095.412999e-091.458804e-081.983171e-086.082880e-09
123.01.851752e-081.599072e-092.228003e-090.0000020.0000030.0000030.0000020.0000020.0000010.0000010.0000020.0000020.0000020.0000010.0000010.0000030.0000020.0000030.0000030.0000010.0000010.0000032.084756e-060.0000044.710479e-060.0000020.0000036.170386e-060.0000030.0000020.0000032.033750e-062.567449e-060.0000021.504151e-061.682195e-061.000708e-061.408385e-061.328178e-060.000002...0.0000034.974716e-064.804490e-060.0000064.564517e-060.0000034.870139e-068.099777e-062.389564e-064.807188e-062.969390e-064.548254e-065.288451e-062.222343e-060.0000043.728426e-063.989563e-064.845033e-060.0000056.873294e-060.0000025.049589e-060.0000052.686271e-065.196398e-064.537091e-060.0000056.886131e-063.704323e-062.606997e-060.0000035.848638e-092.652969e-093.802013e-093.680023e-097.588366e-093.352630e-091.334295e-081.356523e-085.461760e-09
124.01.526794e-081.904395e-093.012694e-090.0000030.0000020.0000040.0000040.0000020.0000010.0000020.0000050.0000030.0000020.0000010.0000010.0000020.0000010.0000030.0000050.0000080.0000010.0000035.319471e-070.0000027.423440e-070.0000010.0000021.331505e-060.0000030.0000010.0000021.107081e-061.698859e-060.0000017.515144e-075.368396e-077.445584e-078.629774e-071.665465e-060.000002...0.0000031.273982e-061.744378e-060.0000032.006455e-060.0000011.867671e-063.270818e-061.444862e-061.950836e-061.375152e-063.053077e-063.156415e-061.976571e-060.0000031.392365e-069.572028e-071.487826e-060.0000032.841553e-060.0000022.921201e-060.0000051.717473e-063.548734e-063.188935e-060.0000023.984916e-061.677965e-062.226348e-060.0000036.599701e-093.184131e-094.878153e-094.554283e-094.333788e-094.143943e-096.197127e-091.149195e-084.885745e-09
125.01.554448e-082.240702e-092.165436e-090.0000030.0000030.0000040.0000030.0000020.0000020.000003NaN0.0000090.0000050.0000050.0000020.0000060.0000020.0000080.0000190.0000080.0000030.0000041.340032e-060.0000051.828251e-060.0000020.0000021.030046e-060.0000030.0000030.0000011.376330e-061.444470e-06NaN1.055394e-063.712440e-07NaN1.261323e-069.890634e-070.000003...0.0000021.289565e-061.452126e-060.0000021.357979e-060.0000011.266668e-062.451592e-063.529851e-071.686731e-067.846670e-072.801990e-062.365513e-068.005016e-070.0000021.181413e-061.090871e-062.218299e-060.0000032.916531e-060.0000012.456790e-060.0000012.894886e-071.862269e-069.910348e-07NaN2.436740e-069.076316e-077.792794e-070.0000024.828801e-093.057908e-092.959562e-092.461398e-095.281825e-094.169273e-096.557761e-095.647898e-093.348997e-09
126.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN0.0000041.284312e-060.0000041.629573e-060.0000020.0000018.839285e-070.0000020.000003NaN8.535060e-076.206068e-07NaN8.059833e-071.717251e-07NaN6.507064e-075.962763e-070.000002...NaN3.593515e-074.812013e-070.0000013.284124e-07NaN2.777564e-076.396569e-07NaN6.206701e-07NaN6.462563e-076.047255e-07NaNNaN3.570359e-073.670580e-076.375746e-070.0000029.608136e-07NaN5.880341e-07NaNNaN4.747024e-07NaNNaN8.688151e-07NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
\n", "

127 rows × 5703 columns

\n", "
" ], "text/plain": [ "start time 2021-10-27 17:33:19.722259 ... 2021-11-16 19:52:53.617858\n", "frequency (Hz) ... \n", "0.0 2.419061e-08 ... 5.329716e-08\n", "1.0 2.557175e-07 ... 3.352921e-07\n", "2.0 2.522567e-06 ... 3.364408e-06\n", "3.0 1.247001e-06 ... 2.720061e-06\n", "4.0 7.596711e-08 ... 4.625317e-07\n", "... ... ... ...\n", "122.0 4.794718e-08 ... 6.082880e-09\n", "123.0 1.851752e-08 ... 5.461760e-09\n", "124.0 1.526794e-08 ... 4.885745e-09\n", "125.0 1.554448e-08 ... 3.348997e-09\n", "126.0 NaN ... NaN\n", "\n", "[127 rows x 5703 columns]" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psd_pivot = psd_y.pivot(index='frequency (Hz)', columns='start time', values='value')\n", "psd_pivot" ] }, { "cell_type": "markdown", "metadata": { "id": "8GYaR8ymSYeB" }, "source": [ "In this format computing the metric per frequency bin is pretty easy:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "PcCCP1ZDSVGZ", "outputId": "7b2c58b1-0815-40d6-8949-059c868770aa" }, "outputs": [ { "data": { "text/plain": [ "frequency (Hz)\n", "0.0 0.000018\n", "1.0 0.000155\n", "2.0 0.000933\n", "3.0 0.000521\n", "4.0 0.000139\n", " ... \n", "122.0 0.000059\n", "123.0 0.000016\n", "124.0 0.000011\n", "125.0 0.000019\n", "126.0 0.000005\n", "Length: 127, dtype: float64" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "psd_pivot.max(axis=1)" ] }, { "cell_type": "markdown", "metadata": { "id": "Vqu9BupZSdft" }, "source": [ "Now we can loop through and add these lines to our animation and update it." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "FvBppfdqSHmi" }, "outputs": [], "source": [ "def add_line(df_stat,name,dash,color):\n", " fig.add_trace(go.Scatter(\n", " x=df_stat.index,\n", " y=df_stat.values,\n", " name=name,\n", " line_width=3,\n", " line_dash=dash,\n", " line_color=color\n", "))\n", "\n", "#Add max, min, median\n", "for stat,dash,quant in zip(['Max','Min','Median'],\n", " [None,None,'dash'],\n", " [1.0,0.0,0.5]):\n", " df_stat = psd_pivot.quantile(quant, axis=1)\n", " add_line(df_stat,stat,dash,'#6914F0')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 542 }, "id": "5xBmy-JMOt9f", "outputId": "ece91abf-853b-4f3f-e55b-e8117e885fc5" }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", "
\n", "\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig.update_layout(\n", " legend_y=-0.7\n", ")\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "_yF7lipoFZKB" }, "source": [ "## That's a Wrap!\n", "\n", "Hopefully you have enough to get started but if not remember we do [offer services](https://endaq.com/collections/shock-vibration-consulting-analysis-services)! And we will be working on more and more documentation and examples!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "YBoG151tPRSm" }, "outputs": [], "source": [] } ], "metadata": { "colab": { "collapsed_sections": [], "name": "Webinar-enDAQ-Custom-Analysis.ipynb", "provenance": [], "toc_visible": true }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 4 }