1

Background: I picked up Python about a month ago, so my experience level is pretty slim. I'm pretty comfortable with VBA though years of data analysis through excel and PI Processbook.

I have 27 thermocouples that I pull data for in 1s intervals. I would like to heatmap them from hottest to coldest at a given instance in time. I've leveraged seaborn heatmaps, but the problem with those is that they compare temperatures across time as well and the aggregate of these thermocouples changes dramatically over time. See chart below:

Thermocouples Over Time

Notice how in the attached, the pink one is colder than the rest when all of them are cold, but when they all heat up, the cold spot transfers to the orange and green ones (and even the blue one for a little bit at the peak).

In excel, I would write a do loop to apply conditional formatting to each individual timestamp (row), however in Python I can't figure it out for the life of me. The following is the code that I used to develop the above chart, so I'm hoping I can modify this to make it work.

tsStartTime = pd.Timestamp(strStart_Time)
tsEndTime = pd.Timestamp(strEnd_Time)
t = np.linspace(tsStartTime.value,tsEndTime.value, 150301)
TimeAxis = pd.to_datetime(t)

fig,ax = plt.subplots(figsize=(25,5))
plt.subplots_adjust(bottom = 0.25)

x = TimeAxis

i = 1
while i < 28:
     globals()['y' + str(i)] = forceconvert_v(globals()['arTTXD' + str(i)])
     ax.plot(x,globals()['y' + str(i)])
     i += 1

I've tried to use seaborn heatmaps, but when i slice it by timestamps, the output array is size (27,) instead of (27,1), so it gets rejected.

Ultimately, I'm looking for an output that looks like this:

Time-based Heatmap

Notice how the values of 15 in the middle are blue despite being higher than the red 5s in the beginning. I didnt fill out every cell, but hopefully you get the jist of what I'm trying to accomplish.

This data is being pulled from OSISoft PI via the PIConnect library. PI leverages their own classes, but they are essentially either series or dataframes, but I can manipulate them into whatever they need to be if someone has any awesome ideas to handle this.

Here's the link to the data: https://file.io/JS0RoQvDL6AB

Thanks!

  • 1
    Hello, welcome to stack OverFlow, if possible can you give us the data you are using? – Flow Jun 13 '22 at 02:47
  • This is pretty unclear. What exactly are you having trouble with? Do you have a data frame to work with? I dont’ understand what your are “slicing by time stamp” or why you need to slice it, or conditionally “format” it. – Jody Klymak Jun 13 '22 at 05:09
  • Thanks @Jody, unfortunately that link doesnt solve the issue. I trying to visualize how hot/cold the values are relative to eachother, but only in that given instance in time. The next time I take a reading, All 27 readings might be 50 degrees hotter. A traditional heatmap would then show all of these at hot because the previous readings were cold, however i still need the coldest current reading to still visualize cold even if its hotter than the hottest previous reading. Does that make more sense? – Gilbertgrape87 Jun 13 '22 at 12:03
  • 1
    Thanks @Flow, I've edited the question to include a link to the data. This is the same data that was used to develop the line plot above. – Gilbertgrape87 Jun 13 '22 at 12:04
  • 1
    @Gilbertgrape87. That's what normalizing means - subtract the mean from each column and divide by the standard deviation. If you like you could divide by the max-min of each column. – Jody Klymak Jun 13 '22 at 12:46
  • @Jody, I agree, but I was misinterpreting what you were saying a bit. Normalization of each individual thermocouple when compared to the other thermocouples wouldn't solve anything, and that's what I thought you meant. So if I normalize the ROWS instead of the columns, this should work perfect! I'd like to flag your response as an answer, but I don't think I can do that as a comment can I? – Gilbertgrape87 Jun 13 '22 at 14:28
  • Sure, sorry, I usually arrange time column wise, and observation row-wise, but transpose as needed. I don't use pandas, so I can't readily code up an example. – Jody Klymak Jun 13 '22 at 15:01

1 Answers1

1

You are going the wrong way with globals. In this case, I suggest to use pandas.DataFrame.

What you are looking for can be produced like this:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Settings
col_number = 5
start = '1/1/2022 10:00:00'
end = '1/1/2022 10:10:00'

# prepare a data frame
index = pd.date_range(start=start, end=end,  freq="S")
columns = [f'y{i}' for i in range(col_number)] 
df = pd.DataFrame(index=index, columns=columns)

# fill in the data
for n, col in enumerate(df.columns):
    df[col] = np.array([n + np.sin(2*np.pi*i/len(df)) for i in range(len(df))])

# drawing a heatmap
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 5))

ax1.plot(df)
ax1.legend(df.columns)

ax2.imshow(df.T, aspect='auto', cmap='plasma')
ax2.set_yticks(range(len(df.columns)))
ax2.set_yticklabels(df.columns)

plt.show()

enter image description here

Here:

  1. As far as you didn't supply data to reproduce your case I use sin as illustrative values.
  2. Transposing df.T is needed to put records horizontally. Of course, we can initially write data horizontally, it's up to you.
  3. set_yticks is here to avoid troubles when changing the y-labels on the second figure.
  4. seaborn.heatmap(...) can be used as well:
import seaborn as sns
data = df.T
data.columns = df.index.strftime('%H:%M:%S')
plt.figure(figsize=(15,3))
sns.heatmap(data, cmap='plasma', xticklabels=60)

enter image description here


Update

To compare values at each point in time:

data = (data - data.min())/(data.max() - data.min())
sns.heatmap(data, cmap='plasma', xticklabels=60)

comparative heatmap

Vitalizzare
  • 4,496
  • 7
  • 13
  • 32
  • Thanks, I do like that better, I'll reconfigure as a dataframe today. However both these methods still have the problem of comparing ALL the data for the heat map rather than only comparing each instance in time against itself. The heatmap is absolute so it shows all functions getting colder overtime when what I am trying to do would result in y4 (as an example) be the same color from beginning to end because its always the hottest function. – Gilbertgrape87 Jun 13 '22 at 11:13
  • @Gilbertgrape87 _Comparing each instance in time against itself_ is a slightly broad description. It seems like Min-max feature scaling fits your description best. At least, hottest values will _be the same color from beginning to end_ in this case. – Vitalizzare Jun 13 '22 at 17:37
  • yep, this is exactly what I was looking for. I was able to incorporate this shortly after my response to Jody up above. Thanks for the followup – Gilbertgrape87 Jun 13 '22 at 22:22