|
94 | 94 | "id": "1672296a-1751-4fd5-a2cb-31ba03cba26d", |
95 | 95 | "metadata": {}, |
96 | 96 | "outputs": [], |
97 | | - "source": [] |
| 97 | + "source": [ |
| 98 | + "\n", |
| 99 | + "# Add experiment info to sensor data, for ease of analysis\n", |
| 100 | + "enrich = pandas.merge(data.reset_index(), experiments, left_on='experiment', right_index=True).set_index(['experiment', 'time'])\n", |
| 101 | + "enrich.head()\n", |
| 102 | + "\n" |
| 103 | + ] |
| 104 | + }, |
| 105 | + { |
| 106 | + "cell_type": "code", |
| 107 | + "execution_count": null, |
| 108 | + "id": "b133f8fb-7f6e-4e9a-9855-2861246d994d", |
| 109 | + "metadata": {}, |
| 110 | + "outputs": [], |
| 111 | + "source": [ |
| 112 | + "power_columns = list(enrich.columns[enrich.columns.str.contains('Power')])\n", |
| 113 | + "def p99(s):\n", |
| 114 | + " return s.quantile(0.99)\n", |
| 115 | + "\n", |
| 116 | + "power_stats = enrich[power_columns].agg(['min', 'max', 'median', p99])\n", |
| 117 | + "print(power_stats)\n", |
| 118 | + "\n", |
| 119 | + "for c in power_columns:\n", |
| 120 | + " s = numpy.maximum(enrich[c], 0.0)\n", |
| 121 | + " s = s / s.quantile(0.99)\n", |
| 122 | + " s = numpy.minimum(s, 1.0)\n", |
| 123 | + " enrich[c+'_Scaled'] = s\n", |
| 124 | + "\n", |
| 125 | + "scaled_power_columns = [ c+'_Scaled' for c in power_columns ]\n", |
| 126 | + "power_stats = enrich[scaled_power_columns].agg(['min', 'max', 'median', p99])\n", |
| 127 | + "power_stats" |
| 128 | + ] |
98 | 129 | }, |
99 | 130 | { |
100 | 131 | "cell_type": "code", |
|
186 | 217 | ] |
187 | 218 | }, |
188 | 219 | { |
189 | | - "cell_type": "code", |
190 | | - "execution_count": null, |
191 | | - "id": "7f333d84-042a-4a68-a2f3-5cff5b05fc89", |
192 | | - "metadata": {}, |
193 | | - "outputs": [], |
194 | | - "source": [ |
195 | | - "enrich = pandas.merge(data.reset_index(), experiments, left_on='experiment', right_index=True).set_index(['experiment', 'time'])\n", |
196 | | - "enrich.head()" |
197 | | - ] |
198 | | - }, |
199 | | - { |
200 | | - "cell_type": "code", |
201 | | - "execution_count": null, |
202 | | - "id": "35c99d2f-e049-437c-8842-6b10df5b15e2", |
| 220 | + "cell_type": "markdown", |
| 221 | + "id": "cdc83bdd-f65f-46cd-9ab8-a0a8cda9af72", |
203 | 222 | "metadata": {}, |
204 | | - "outputs": [], |
205 | 223 | "source": [ |
206 | | - "plotly.express.histogram(enrich.reset_index().sort_values('feedrate'), x='S1_OutputPower', facet_col='feedrate', color='experiment')" |
| 224 | + "## Spindle power vs different conditions" |
207 | 225 | ] |
208 | 226 | }, |
209 | 227 | { |
|
214 | 232 | "outputs": [], |
215 | 233 | "source": [ |
216 | 234 | "spindleactive = enrich[enrich['S1_OutputPower'] > 0.03]\n", |
217 | | - "import seaborn\n", |
218 | | - "\n", |
219 | | - "seaborn.displot(kind='kde', data=spindleactive, x='S1_OutputPower', hue='Machining_Process', row='feedrate', clip=(0.1, 0.250), aspect=2.0, height=4.0, common_norm=False)\n", |
220 | | - "#(spindleactive.reset_index().sort_values('Machining_Process'), x='S1_OutputPower', color='Machining_Process')\n" |
| 235 | + "import seaborn" |
221 | 236 | ] |
222 | 237 | }, |
223 | 238 | { |
|
257 | 272 | { |
258 | 273 | "cell_type": "code", |
259 | 274 | "execution_count": null, |
260 | | - "id": "88c01b43-c535-41ac-a97f-a189e456fe90", |
| 275 | + "id": "f9af841d-6ebb-454f-8fce-cbea5f8e2981", |
261 | 276 | "metadata": {}, |
262 | 277 | "outputs": [], |
263 | 278 | "source": [ |
264 | | - "experiments" |
| 279 | + "seaborn.displot(kind='kde', data=spindleactive, x='S1_OutputPower', hue='clamp_pressure', clip=(0.1, 0.250), aspect=2.0, height=4.0, common_norm=False)\n", |
| 280 | + "#(spindleactive.reset_index().sort_values('Machining_Process'), x='S1_OutputPower', color='Machining_Process')\n" |
265 | 281 | ] |
266 | 282 | }, |
267 | 283 | { |
268 | 284 | "cell_type": "code", |
269 | 285 | "execution_count": null, |
270 | | - "id": "03a06816-37c6-4229-b864-46b2d65bf500", |
| 286 | + "id": "206f74c7-f714-4871-bd8e-3feba4453fa8", |
271 | 287 | "metadata": {}, |
272 | 288 | "outputs": [], |
273 | 289 | "source": [ |
274 | | - "experiments.groupby('feedrate')['machining_finalized'].value_counts().reset_index()" |
| 290 | + "seaborn.displot(kind='kde', data=spindleactive, x='S1_OutputPower', hue='Machining_Process', row='feedrate', clip=(0.1, 0.250), aspect=2.0, height=2.0, common_norm=False)\n", |
| 291 | + "#(spindleactive.reset_index().sort_values('Machining_Process'), x='S1_OutputPower', color='Machining_Process')\n" |
| 292 | + ] |
| 293 | + }, |
| 294 | + { |
| 295 | + "cell_type": "markdown", |
| 296 | + "id": "c2e86bd4-0376-46be-a971-45c11a63eea1", |
| 297 | + "metadata": {}, |
| 298 | + "source": [ |
| 299 | + "## Time-series view" |
275 | 300 | ] |
276 | 301 | }, |
277 | 302 | { |
278 | 303 | "cell_type": "code", |
279 | 304 | "execution_count": null, |
280 | | - "id": "18caa430-ed15-4e3a-af56-3a19ac213afa", |
| 305 | + "id": "a90745b1-f9a3-4287-8640-f782fe6c2528", |
281 | 306 | "metadata": {}, |
282 | 307 | "outputs": [], |
283 | 308 | "source": [ |
284 | | - "experiments.groupby('clamp_pressure')['machining_finalized'].value_counts().reset_index()" |
| 309 | + "# TODO: show the different labeled sections in Machining_Process column\n", |
| 310 | + "# TODO: normalize powers for all axes, and plot together\n", |
| 311 | + "plot_timeseries(data, y_column='Y1_OutputPower')" |
285 | 312 | ] |
286 | 313 | }, |
287 | 314 | { |
288 | 315 | "cell_type": "code", |
289 | 316 | "execution_count": null, |
290 | | - "id": "05db06c0-fa0f-43cb-b3bd-76ea38629327", |
| 317 | + "id": "be42389a-b4a1-4721-adad-08b701f07330", |
291 | 318 | "metadata": {}, |
292 | 319 | "outputs": [], |
293 | 320 | "source": [ |
294 | | - "\n", |
295 | | - "seaborn.displot(kind='kde', data=spindleactive, x='S1_OutputPower', hue='clamp_pressure', clip=(0.1, 0.250), aspect=2.0, height=4.0, common_norm=False)\n", |
296 | | - "#(spindleactive.reset_index().sort_values('Machining_Process'), x='S1_OutputPower', color='Machining_Process')\n" |
| 321 | + "for column in scaled_power_columns:\n", |
| 322 | + " \n", |
| 323 | + " seaborn.displot(data=enrich.reset_index(), kind='kde', x=column, hue='feedrate', height=2.0, aspect=2.0)" |
297 | 324 | ] |
298 | 325 | }, |
299 | 326 | { |
300 | 327 | "cell_type": "code", |
301 | 328 | "execution_count": null, |
302 | | - "id": "4e44b6c4-2617-48ff-b44b-ef23886a9411", |
| 329 | + "id": "3a97c242-8b3d-4e26-bbbe-6211ff5b4975", |
303 | 330 | "metadata": {}, |
304 | 331 | "outputs": [], |
305 | 332 | "source": [ |
306 | | - "plotly.express.histogram(spindleactive.reset_index().sort_values('feedrate'), x='S1_OutputPower', facet_col='feedrate', color='experiment')" |
| 333 | + "spindle_active = enrich[enrich['S1_OutputPower'] > 0.01]\n", |
| 334 | + "seaborn.pairplot(data=spindle_active.reset_index(), vars=scaled_power_columns, hue='feedrate', height=3.6, aspect=1.5, diag_kws=dict(common_norm=False))" |
307 | 335 | ] |
308 | 336 | }, |
309 | 337 | { |
310 | 338 | "cell_type": "code", |
311 | 339 | "execution_count": null, |
312 | | - "id": "a90745b1-f9a3-4287-8640-f782fe6c2528", |
| 340 | + "id": "8471ed38-36a9-4938-8326-575a0e887ca8", |
313 | 341 | "metadata": {}, |
314 | 342 | "outputs": [], |
315 | 343 | "source": [ |
316 | | - "# TODO: show the different labeled sections in Machining_Process column\n", |
317 | | - "# TODO: normalize powers for all axes, and plot together\n", |
318 | | - "plot_timeseries(data, y_column='Y1_OutputPower')" |
| 344 | + "seaborn.pairplot(data=spindle_active.reset_index(), vars=scaled_power_columns, hue='machining_finalized', height=3.6, aspect=1.5, diag_kws=dict(common_norm=False))" |
319 | 345 | ] |
320 | 346 | }, |
321 | 347 | { |
|
327 | 353 | }, |
328 | 354 | "outputs": [], |
329 | 355 | "source": [ |
330 | | - "# TODO: plot time-series\n", |
331 | | - "\n", |
332 | 356 | "\n", |
333 | | - "def plot_timeseries(data, y_column = 'S1_OutputPower', x_column = 'time'):\n", |
334 | 357 | "\n", |
| 358 | + "def plot_timeseries(data, y, time_column = 'time', row_column='experiment', row_order=None):\n", |
| 359 | + " import plotly.graph_objects as go\n", |
| 360 | + " \n", |
335 | 361 | " data = data.reset_index()\n", |
336 | | - " data['time'] = data['time'] / pandas.Timedelta('1sec')\n", |
| 362 | + " # convert to seconds, Plotly default time markers are bad with Timedelta\n", |
| 363 | + " data[time_column] = data[time_column] / pandas.Timedelta('1sec')\n", |
| 364 | + "\n", |
| 365 | + " x_range = data[time_column].min(), data[time_column].max()\n", |
| 366 | + "\n", |
| 367 | + " if row_order is None:\n", |
| 368 | + " row_order = sorted(list(data[row_column].unique()))\n", |
| 369 | + " else:\n", |
| 370 | + " row_order = list(row_order)\n", |
337 | 371 | " \n", |
338 | | - " #traces = []\n", |
339 | | - " #titles = []\n", |
340 | | - " for experiment, d in data.groupby('experiment'):\n", |
| 372 | + " for experiment in row_order:\n", |
| 373 | + " df = data[data[row_column] == experiment]\n", |
| 374 | + " df = df.sort_values(time_column) # plotly lines connect badly without sorting by time\n", |
| 375 | + " \n", |
341 | 376 | " ex = experiments.loc[experiment]\n", |
342 | 377 | " describe = f\"Ex {experiment}: f={ex['feedrate']} c={ex['clamp_pressure']} t={ex['tool_condition']} f={ex['machining_finalized']} p={ex['passed_visual_inspection']}\"\n", |
| 378 | + "\n", |
| 379 | + " fig = go.Figure()\n", |
| 380 | + " fig.update_layout(title=describe, xaxis=dict(range=x_range))\n", |
| 381 | + " for column in y:\n", |
| 382 | + " fig.add_trace(go.Scatter(x=df[time_column], y=df[column], name=column))\n", |
343 | 383 | " \n", |
344 | | - " fig = plotly.express.scatter(d, x=x_column, y=y_column, title=describe)\n", |
345 | 384 | " fig.show()\n", |
346 | | - " \n", |
347 | | - " #print(ex) \n", |
348 | | - " #traces.append(trace)\n", |
349 | | - " #titles.append(describe)\n", |
350 | 385 | "\n", |
351 | | - " \n", |
| 386 | + "plot_timeseries(enrich.sort_values(['feedrate']), y=scaled_power_columns)" |
| 387 | + ] |
| 388 | + }, |
| 389 | + { |
| 390 | + "cell_type": "code", |
| 391 | + "execution_count": null, |
| 392 | + "id": "876f7376-af98-411a-af20-966a444ca9d0", |
| 393 | + "metadata": {}, |
| 394 | + "outputs": [], |
| 395 | + "source": [ |
| 396 | + "exx = experiments.sort_values(['feedrate', 'clamp_pressure', 'tool_condition'])\n", |
| 397 | + "exx" |
| 398 | + ] |
| 399 | + }, |
| 400 | + { |
| 401 | + "cell_type": "code", |
| 402 | + "execution_count": null, |
| 403 | + "id": "fa8665f0-0767-4e5b-8f35-b99c83eae49c", |
| 404 | + "metadata": {}, |
| 405 | + "outputs": [], |
| 406 | + "source": [ |
352 | 407 | "\n", |
353 | | - "plot_timeseries(data)" |
| 408 | + "plot_timeseries(data.reset_index(), y=['Y1_ActualPosition', 'X1_ActualPosition'], row_order=exx.index)\n" |
| 409 | + ] |
| 410 | + }, |
| 411 | + { |
| 412 | + "cell_type": "code", |
| 413 | + "execution_count": null, |
| 414 | + "id": "26499011-f015-47a4-ad9c-a6e23e4b0c1b", |
| 415 | + "metadata": {}, |
| 416 | + "outputs": [], |
| 417 | + "source": [ |
| 418 | + "plot_timeseries(enrich.sort_values(['feedrate']), y=['M1_CURRENT_FEEDRATE', 'S1_CurrentFeedback'])" |
| 419 | + ] |
| 420 | + }, |
| 421 | + { |
| 422 | + "cell_type": "code", |
| 423 | + "execution_count": null, |
| 424 | + "id": "9deb06d4-5327-440b-9f5d-826ce9357a15", |
| 425 | + "metadata": {}, |
| 426 | + "outputs": [], |
| 427 | + "source": [ |
| 428 | + "plot_timeseries(enrich.sort_values(['feedrate']), y=['M1_CURRENT_FEEDRATE', 'S1_OutputPower_Scaled'])\n" |
| 429 | + ] |
| 430 | + }, |
| 431 | + { |
| 432 | + "cell_type": "code", |
| 433 | + "execution_count": null, |
| 434 | + "id": "e5973658-2893-4a56-8cd1-fdd92d57ac0b", |
| 435 | + "metadata": {}, |
| 436 | + "outputs": [], |
| 437 | + "source": [ |
| 438 | + "p = enrich.sort_values(['feedrate'])\n", |
| 439 | + "p['S1_CommandVelocity_Scaled'] = p['S1_CommandVelocity'] / 50.0\n", |
| 440 | + "p['S1_Power_Calc'] = p['S1_OutputCurrent'] * p['S1_OutputVoltage']\n", |
| 441 | + "#plot_timeseries(p, y=['S1_CommandVelocity_Scaled', 'S1_OutputPower_Scaled'])\n", |
| 442 | + "plot_timeseries(p, y=['S1_OutputCurrent', 'S1_OutputPower'])" |
| 443 | + ] |
| 444 | + }, |
| 445 | + { |
| 446 | + "cell_type": "code", |
| 447 | + "execution_count": null, |
| 448 | + "id": "4f1d8383-3180-49e7-b2be-bfef897be023", |
| 449 | + "metadata": {}, |
| 450 | + "outputs": [], |
| 451 | + "source": [ |
| 452 | + "scaled_power_columns" |
| 453 | + ] |
| 454 | + }, |
| 455 | + { |
| 456 | + "cell_type": "code", |
| 457 | + "execution_count": null, |
| 458 | + "id": "b756b69a-5b3f-4c5a-b040-24356cae483c", |
| 459 | + "metadata": {}, |
| 460 | + "outputs": [], |
| 461 | + "source": [ |
| 462 | + "data['S1_CommandVelocity'].hist()" |
354 | 463 | ] |
355 | 464 | }, |
356 | 465 | { |
|
0 commit comments