Technical Notes#
This chapter provides a technical back-story for this oceanography Jupyter Book. Both this chapter and the chapter on Documentation enable us to provide useful explanatory material while reducing clutter in the science narrative.
Shallow profiler section#
Study site locations#
The regional cabled array (RCA) maintains three shallow profiler sites in the northeast Pacific Ocean.
Site name Abbreviation Latitude Longitude
------------------ ------------ -------- ---------
Oregon Offshore OOF 44.37415 -124.95648
Oregon Slope Base OSB 44.52897 -125.38966
Axial Base AXB 45.83049 -129.75326
needed: map image
Data dictionary d{}
, comparing sensors using ChartTwoSensors()
#
The epipelargosy
chapter begins by building a data dictionary d{}
keys are sensor names (‘temp’, ‘ph’ etcetera)
All sensor names are given in the
data
chapter
d[key] is a 5-element tuple
First two elements are XArray DataFrames
d[key][0] is sensor data as a function of time
d[key][1] is depth as a function of (the same) time
Elements [2] and [3] are the expected numerical range of the sensor data
Element [4] is a string: Default plot color for this sensor
Note that if one treats a profile as an ‘instantaneous’ event at some characteristic time: The sensor value can be recast in terms of the depth dimension/coordinate.
Data dictionary values
[0] DataArray: sensor data values, dimension = 'time'
[1] DataArray: sensor depths z, dimension = 'time'
[2] low-end expected data range
[3] high-end expected data range
[4] color for this sensor
print(d['ph'][0], d['ph'][1])
for a in list(d['ph'][0].attrs.keys()): del d['ph'][0].attrs[a]
for a in list(d['ph'][1].attrs.keys()): del d['ph'][1].attrs[a]
print(d['ph'][0], d['ph'][1])
Profile data from two sensors can be compared on a single chart using ChartTwoSensors()
found in the charts.py
module.
There are three sites that support shallow profilers
Each site has a platform tethered at 200 meters depth
Each platform has a winch that (nine times daily) allows the profiler to rise to near the surface and descend again
As a result we have sensor profiles from the instruments affixed to the profiler
We have pressure / depth data as well so we can produce profile charts
These have depth as the vertical access and sensor reading on the horizontal axis
We also have a set of instruments attached to the platform
This maintains a fairly constant depth although it is subject to two types of depth-variability
First type: Tides (typically a couple of meters)
Second type: Strong currents (e.g. during a storm) drag the platform laterally
Because it is tethered: The net effect is the platform is pushed deeper
This can also affect the profiler
To further reduce clutter there are Python modules available as well: shallowprofiler.py
and so forth.
From the imported shallowprofiler.py
module we have available sensors
: A list of lists.
Each entry is [sensor_name, instrument_name]
so for example sensors[4]
is ['temperature', 'ctd']
.
To see the entirety: sensors
.
The data volume across many sensors get fairly large. There are multiple ways to approach not bogging down the Jupyter/IPython environment:
Work at full time resolution in a narrow time window (e.g. one month)
Work at a reduced time resolution
With instrument and sensor names sorted (with spectral irradiance a special case) the next step
is to build a data dictionary called d
with keys corresponding to sensor (data) types:
conductivity
, temperature
, pco2
etcetera. The corresponding value for each sensor
key is a five-tuple indexed [0], [1], …, [4].
0: XArray DataArray: sensor data
1: XArray DataArray: sensor depth (meters, negative down) corresponding to data
2: float: Default charting lower limit for data
3: float: Default charting upper limit for data
4: string: Default chart color e.g. "blue"
Topic overview#
Data: Table below, see also the Data chapter
OOI abbrev |
sensors |
remark |
instrument; sensor abbreviations |
---|---|---|---|
ctdpf |
5 |
CTD: includes a variety of sensors |
ctd; salinity, temperature, pressure, density, conductivity |
pco2 |
1 |
carbonate chemistry, midnight and noon descent only |
pco2; pco2 |
phsen |
1 |
pH, midnight and noon descent only |
ph; ph |
nutnr |
2 |
nitrate, dark samples; midnight and noon ascent only |
nitrate; nitrate, …?… |
flort |
3 |
Fluorometer triplet: chlorophyll-A, FDOM, backscatter |
fluor; chlora, fdom, backscatter |
parad |
1 |
photosynthetically available radiation ‘PAR’ |
par; par |
velpt |
3 |
water velocity in three dimensions |
vel; north, east, up |
spkir |
7 |
spectral irradiance |
spkir; spkir412nm, etcetera 443, 490, 510, 555, 620, 683 |
optaa |
86 |
spectrophotometer ascent noon/midnight |
sp; sp00 … sp85 |
Profiler timing metadata
Nine daily profiles: 7 regular + 2 special: noon/midnight variants
Basic charts: Depth vs { A, B, C, … }
Noon/Midnight charts: pCO2 (Descent), pH (Descent), Nitrate (Ascent), Spectral Irradiance (Ascent)
Basic charts: Depth vs { A, B, C, … }
Noon/Midnight charts: pCO2 (Descent), pH (Descent), Nitrate (Ascent), Spectral Irradiance (Ascent)
Turbulence
Most direct resource is variation with depth of observed lateral currents (see
vel
sensor)
Comparatives
Ascent versus Descent
Platform versus Profiler when Profiler is at rest near the Platform
Profiler versus Discrete Sample CTD casts during maintenance cruises
BioOptics
FDOM/CDOM and Chlorophyll
Spectral Irradiance
Spectrophotometer
Visualization in practice
Interactivity: Sliders, Widgets
Visualizing in 3D
Saving charts as
.png
imagesCreating chart animations
Developing the data dictionary: sensor profiles#
There are two types of data we are concerned with here: Sensor data and profile metadata. The sensor data from the profiler are viewed in relation to depth, hence ‘profile charts’. In order to generate these we need to know when the profiler is starting and ending an ascent; as well as a descent and a rest period when it is parked on the platform at 200 meters.
Profile metadata is read using the function ReadProfileMetadata(filename)
where the filename
describes the site and the time period of interest. The data are held in a pandas Dataframe.
The data structure sensors
is a list of 2-element lists. The first element is a sensor name
and the second is the corresponding instrument that carries the sensor.
sensors[3] = ['salinity', 'ctd']
The data structure ranges
is a dictionary of expected upper and lower bounds for each sensor.
The keys are sensor names as found in sensors
; values are tuples.
ranges['salinity'] = (31, 35)
The data structure standard_deviations
is a dictionary of standard deviation ranges, also tuples.
standard_deviations['salinity'] = (.0, .4)
The data structure colors
is a dictionary of colors associated with sensors in charts.
colors['salinity'] = 'cyan'
The data structure sensor_names
is a dictionary of expanded sensor names more suited
to chart labels.
sensor_names['salinity'] = 'Salinity'
from shallowprofiler import *
from charts import *
# profiles is a pandas DataFrame treated as a global resource
# The directory tree for the Jupyter Book:
#
# book/chapters/rob/<notebooks.ipynb> (where this notebook resides)
# /rca/profiles/osb/january2022.csv
# /oos
# /axb
#
# The resulting DataFrame has columns r0t, r0z, r1t, r1z, a0t, a0z, a1t, a1z, d0t, d0z, d1t, d1z
# corresponding to rest / ascent / descent <start - end> <depth> <time>
#
profiles = ReadProfileMetadata()
# Let's look at some typical ascent and descent timestamps
print('First slow ascent start time is local midnight:', profiles['a0t'][3], 'UTC')
print()
print("9 ascent intervals:")
for i in range(9):
print(profiles['a1t'][i] - profiles['a0t'][i], ' depths:', profiles['a0z'][i], 'to', profiles['a1z'][i], 'meters')
print()
print("9 descent intervals:")
for i in range(9):
print(profiles['d1t'][i] - profiles['d0t'][i], ' depths:', profiles['d0z'][i], 'to', profiles['d1z'][i], 'meters')
print()
print("9 rest intervals:")
for i in range(9):
print(profiles['r1t'][i] - profiles['r0t'][i], ' depths:', profiles['r0z'][i], 'to', profiles['r1z'][i], 'meters')
print()
Jupyter Notebook running Python 3
First slow ascent start time is local midnight: 2022-01-01 07:17:00 UTC
9 ascent intervals:
0 days 01:10:00 depths: -191.0 to -19.0 meters
0 days 00:38:00 depths: -194.0 to -105.0 meters
0 days 01:10:00 depths: -196.0 to -24.0 meters
0 days 01:13:00 depths: -194.0 to -12.0 meters
0 days 01:10:00 depths: -193.0 to -23.0 meters
0 days 01:10:00 depths: -199.0 to -29.0 meters
0 days 00:20:00 depths: -203.0 to -163.0 meters
0 days 01:10:00 depths: -197.0 to -21.0 meters
0 days 01:12:00 depths: -191.0 to -12.0 meters
9 descent intervals:
0 days 00:39:00 depths: -19.0 to -194.0 meters
0 days 00:23:00 depths: -105.0 to -196.0 meters
0 days 00:39:00 depths: -24.0 to -196.0 meters
0 days 01:42:00 depths: -12.0 to -192.0 meters
0 days 00:39:00 depths: -23.0 to -198.0 meters
0 days 00:39:00 depths: -29.0 to -203.0 meters
0 days 00:14:00 depths: -163.0 to -202.0 meters
0 days 00:39:00 depths: -21.0 to -192.0 meters
0 days 01:36:00 depths: -12.0 to -191.0 meters
9 rest intervals:
0 days 00:22:00 depths: -191.0 to -191.0 meters
0 days 00:26:00 depths: -194.0 to -194.0 meters
0 days 01:09:00 depths: -196.0 to -196.0 meters
0 days 00:41:00 depths: -196.0 to -194.0 meters
0 days 00:55:00 depths: -192.0 to -193.0 meters
0 days 00:31:00 depths: -198.0 to -199.0 meters
0 days 00:26:00 depths: -203.0 to -203.0 meters
0 days 01:51:00 depths: -202.0 to -197.0 meters
0 days 00:41:00 depths: -192.0 to -191.0 meters
From this we can infer:
We are inspecting the nine profile runs from 01-JAN-2022 at the Oregon Slope Base site
There are a couple of profiles (2 and 7 in the list of 9) that did not run full scope
Ascents stopped below 100 meters so ignore these
Profiles 4 and 9 correspond to midnight and noon (slower) profiles
Times are UTC: 7 (PST) or 8 (PDT) hours ahead of local
Ascent time is about 70 minutes (for both normal and slow profiles)
Typical ascent depth range is 174.4 meters
Ascent speed is therefore 4.15 cm per second
Using an 8-second sample average window would give a vertical sampling of 0.3322 meters / downsample
This is about 525 samples per profile
Descent time (normal profiles) is about 39 minutes
Slow profile descent time is about 100 minutes
Rest periods are of less interest
They do give an opportunity to track profiler instruments against platform instruments
For example: Is a change in salinity reflected in both sensors?
Rest times prior to normal profiles seem to vary in duration (under one hour)
Rest times prior to midnight/noon profiles seem longer (more than one hour)
Rest depths vary by a couple meters start to end as one would expect from tides etcetera