Introduction to the “light” exposure data module of pyActigraphy¶
There shall be light!
Photo by Jonathan Borba on Unsplash
Disclaimer¶
The development of the pyActigraphy module for analysing light exposure data was led and financially supported by members of the Daylight Academy Project The role of daylight for humans (led by Mirjam Münch, Manuel Spitschan). The module is part of the Human Light Exposure Database. For more information about the project, please see https://daylight.academy/projects/state-of-light-in-humans/.
Introduction¶
Many actigraphy devices also record light exposure data. As light is a strong zeitgeber, it is likely that any circadian analysis, if light itself is not its primary focus, will at least control for interindividual differences in light exposure.
This is where the “light” module of pyActigraphy comes into play. It provides access to light exposure data recorded by several devices and light-specific metrics.
This first introduction tutorial presents how to:
access light exposure data from various actigraphy devices
visualize light exposure data using the plotly package
NB(1): there are many visualization packages available in Python (matplotlib, seaborn, plotly, etc). Feel free to use the one you like the most. Plotly is used here for convenience as it is part of pyActigraphy dependencies and thus automatically installed when installing pyActigraphy.
NB(2): by default, the light exposure data are automatically log-transformed (log10+1) upon reading the recording with pyActigraphy.
How to get some help?¶
In pyActigraphy, the inline documentation of a variable or a function can easily be access through the help
command.
Imports and input data¶
First, let’s import the necessary packages:
[1]:
import pyActigraphy
[2]:
import plotly.graph_objects as go
[3]:
import os
Now, in the context of this tutorial, we will use as input data a sample file recorded by a ActTrust device (Condor Instrument), located in the test directory of the pyActigraphy package itself.
[4]:
fpath = os.path.join(
os.path.dirname(pyActigraphy.__file__),
'tests','data',
'test_sample_atr.txt'
)
Reading such a file with pyActigraphy is easy:
[5]:
raw = pyActigraphy.io.read_raw_atr(fpath)
For more information about the various file formats that can be read by pyActigraphy or about the information that can be retrieved via this raw
object, please see this tutorial.
How to access light exposure data¶
Light exposure data can be accessed through the light
attribute of the raw
object:
[6]:
raw.light
[6]:
<pyActigraphy.light.light.LightRecording at 0x155a78550>
This command returns an object (LightRecording
) that both contains the light exposure data and gives you access to various light-specific metrics. More information about the `LightRecording
<https://ghammad.github.io/pyActigraphy/LightRecording.html>`__ class.
Some devices record light data via different sensors, providing thus multiple channels. To see the list of available channels:
[7]:
raw.light.get_channel_list()
[7]:
Index(['LIGHT', 'AMB LIGHT', 'RED LIGHT', 'GREEN LIGHT', 'BLUE LIGHT',
'IR LIGHT', 'UVA LIGHT', 'UVB LIGHT'],
dtype='object')
In this example case, multiple light channels are available. To access the light data, it is possible to either get a single channel directly:
[8]:
raw.light.get_channel('RED LIGHT')
[8]:
DATE/TIME
1918-01-01 09:00:00 1.719000
1918-01-01 09:01:00 1.643650
1918-01-01 09:02:00 1.630530
1918-01-01 09:03:00 1.625312
1918-01-01 09:04:00 1.619406
...
1918-01-05 08:55:00 0.000000
1918-01-05 08:56:00 0.000000
1918-01-05 08:57:00 0.000000
1918-01-05 08:58:00 0.000000
1918-01-05 08:59:00 0.000000
Freq: T, Name: RED LIGHT, Length: 5760, dtype: float64
Or get multiple channels at once:
[9]:
raw.light.get_channels(['RED LIGHT', 'GREEN LIGHT', 'BLUE LIGHT'])
[9]:
RED LIGHT | GREEN LIGHT | BLUE LIGHT | |
---|---|---|---|
DATE/TIME | |||
1918-01-01 09:00:00 | 1.719000 | 1.874424 | 1.590953 |
1918-01-01 09:01:00 | 1.643650 | 1.803730 | 1.516932 |
1918-01-01 09:02:00 | 1.630530 | 1.802500 | 1.514415 |
1918-01-01 09:03:00 | 1.625312 | 1.790074 | 1.495544 |
1918-01-01 09:04:00 | 1.619406 | 1.786822 | 1.493319 |
... | ... | ... | ... |
1918-01-05 08:55:00 | 0.000000 | 0.000000 | 0.000000 |
1918-01-05 08:56:00 | 0.000000 | 0.000000 | 0.004321 |
1918-01-05 08:57:00 | 0.000000 | 0.004321 | 0.004321 |
1918-01-05 08:58:00 | 0.000000 | 0.004321 | 0.004321 |
1918-01-05 08:59:00 | 0.000000 | 0.004321 | 0.004321 |
5760 rows × 3 columns
Or access the underlying data (pandas.DataFrame) and select the requested channel:
[10]:
raw.light.data.loc[:,['UVA LIGHT','UVB LIGHT']]
[10]:
UVA LIGHT | UVB LIGHT | |
---|---|---|
DATE/TIME | ||
1918-01-01 09:00:00 | 0.0 | 0.0 |
1918-01-01 09:01:00 | 0.0 | 0.0 |
1918-01-01 09:02:00 | 0.0 | 0.0 |
1918-01-01 09:03:00 | 0.0 | 0.0 |
1918-01-01 09:04:00 | 0.0 | 0.0 |
... | ... | ... |
1918-01-05 08:55:00 | 0.0 | 0.0 |
1918-01-05 08:56:00 | 0.0 | 0.0 |
1918-01-05 08:57:00 | 0.0 | 0.0 |
1918-01-05 08:58:00 | 0.0 | 0.0 |
1918-01-05 08:59:00 | 0.0 | 0.0 |
5760 rows × 2 columns
NB: remember that, in both cases, the light exposure data are automatically log-transformed (log10+1).
How to visualize light exposure data¶
In this tutorial, the python package “plotly” is used to display graphics. However, feel free to use your favourite graphic library.
First, let’s create the graphic layout:
[11]:
layout = go.Layout(
title="Light exposure data",
xaxis=dict(title="Date time"),
yaxis=dict(title="$log_{10}(\mathrm{Light~intensity})+1~\mathrm{[microwatt/cm^2]}$"),
showlegend=False
)
And plot the (red) light data:
[12]:
fig1 = go.Figure(
data=[go.Scatter(
x=raw.light.get_channel('RED LIGHT').index.astype(str),
y=raw.light.get_channel('RED LIGHT'),
name='Red light')
],
layout=layout
)
[13]:
fig1.show()
Since all the recorded light channels are readily available, displaying multiple channels is easy:
[14]:
layout.update(showlegend=True);
[15]:
fig2 = go.Figure(
data=[
go.Scatter(
x=raw.light.get_channel('RED LIGHT').index.astype(str),
y=raw.light.get_channel('RED LIGHT'),
name='Red light',
line={'color':'red'}
),
go.Scatter(
x=raw.light.get_channel('BLUE LIGHT').index.astype(str),
y=raw.light.get_channel('BLUE LIGHT'),
opacity=.75,
name='Blue light',
line={'color':'blue'}
),
go.Scatter(
x=raw.light.get_channel('GREEN LIGHT').index.astype(str),
y=raw.light.get_channel('GREEN LIGHT'),
opacity=.5,
name='Green light',
line={'color':'green'}
)
],
layout=layout
)
[16]:
fig2.show()
Et voilà! For now…