Exercise 3 - Time Series Analysis#
📅 Due Date: December 1, 2025 at 18:00
Aim: To analyze oceanographic time series data using harmonic analysis and filtering techniques with real mooring CTD and velocity data.
Context: This exercise uses real oceanographic mooring data to teach time series analysis, harmonic fitting, and data filtering skills in Python.
Goals: At the end of this exercise, you will be able to:
Load and manipulate time series data using xarray and netCDF4
Understand oceanographic time coordinate systems and data conversion
Perform harmonic analysis using scipy.optimize.curve_fit
Fit semi-diurnal tidal harmonics (M2 tide) to CTD and velocity data
Calculate and interpret tidal ellipses from velocity data
Apply TEOS-10 oceanographic calculations (absolute salinity, conservative temperature)
Implement time series filtering using rolling averages (boxcar filters)
Create clear time series plots and tidal ellipse visualizations
Required Outputs: Four figures showing harmonic fits, residuals, tidal ellipse, and filtering effects.
Step 1: Accept GitHub Classroom Assignment#
📝 Accept Assignment: Exercise 3 - Time Series Analysis
Click the link above to start the assignment. You may need to create a GitHub account or link your existing account to your name.
Your assignment repository will be automatically created with:
src/assignment.ipynb- Main exercise notebook with automated testingmodules/tools.py- Helper functions for harmonic analysistests/- Automated tests that run when you submitrequirements.txt- All required Python packages including scipy and gsw
Step 2: Setup Your Environment#
Important
If you completed Exercise 2 successfully, your environment should already be set up! Just clone this new assignment and install its requirements.
Quick Setup (For Students Who Completed Exercise 2)#
Clone your assignment repository (get URL from GitHub Classroom)
Navigate to the folder and activate your virtual environment
Install new packages:
pip install -r requirements.txt(includes scipy, gsw)Open in VS Code:
File → Open Folder→ Select assignment folderStart working: Open
src/assignment.ipynb
First-Time Setup or Troubleshooting#
For complete setup instructions, troubleshooting, and help, see:
Exercise 1 Setup Guide - Complete instructions for git, Python, virtual environments, and VS Code
Python Installation Guide - Platform-specific installation help
Python Tips & Troubleshooting - Debugging and error solutions
Step 3: Complete the Exercise#
Work through the assignment notebook systematically. Look for # TODO: and # YOUR CODE HERE sections and fill them in.
What You’ll Do#
Update your information (name, date, student ID)
Load and analyze CTD time series data - salinity, temperature, pressure
Implement TEOS-10 calculations - absolute salinity and conservative temperature
Perform harmonic analysis - fit M2 tidal harmonics to salinity and velocity data
Create tidal ellipse plots - visualize velocity patterns
Apply time series filtering - implement boxcar filters and compare results
Create 4 required figures:
Figure 1: CTD salinity harmonic fit and residuals
Figure 2: Velocity harmonic fits and residuals (U and V components)
Figure 3: Tidal ellipse from velocity analysis
Figure 4: Effect of time series filtering
Answer analysis questions about tidal harmonics and filtering
Key Python Concepts You’ll Learn#
Time coordinate conversion: Converting datetime to fractional days
Harmonic analysis: Using scipy.optimize.curve_fit for tidal fitting
TEOS-10 calculations: Using gsw package for oceanographic standards
Time series filtering: Implementing rolling averages with xarray
Tidal ellipse analysis: Understanding velocity vector patterns
Residual analysis: Evaluating model fit quality
💡 Pro Tips for Success#
🎯 Before You Start:
Run the first few cells to make sure everything imports correctly
Check that data files load successfully
Verify scipy and gsw packages are installed
🔬 While Working:
Understanding harmonic fitting: The M2 tide has a period of 12.42 hours
Time conversion: Use the fractional days approach, not integer days
Data quality: Remove invalid/outlier data points before fitting
Filtering concepts: Understand what time scales you’re removing vs preserving
🆘 When Things Go Wrong:
# Common fixes:
# If harmonic fitting fails:
print(f"Data range: {data.min():.2f} to {data.max():.2f}")
print(f"NaN values: {np.isnan(data).sum()}")
# If tidal ellipse looks wrong:
print(f"U amplitude: {amplitude_uvel:.3f}")
print(f"V amplitude: {amplitude_vvel:.3f}")
print(f"Phase difference: {phase_vvel - phase_uvel:.3f}")
Step 4: Submission and Grading#
Automatic Testing#
Your work is tested automatically when you submit! The assignment includes:
✅ TEOS-10 calculations - Absolute salinity and conservative temperature computed
✅ Harmonic fitting - M2 tidal harmonics fitted to CTD and velocity data
✅ Figure creation - All 4 required figures generated with proper naming
✅ Data validation - Proper time series data loading and processing
✅ Filtering implementation - Time series filtering applied correctly
Submit Your Work#
Important
GitHub Classroom automatically collects your submission when you push to your repository. No separate submission step required - just commit and push your changes!
Option A: VS Code Source Control (Recommended)
Open the Source Control panel (Ctrl+Shift+G)
Stage your changes by clicking the + button next to
src/assignment.ipynbAdd a commit message: “Complete Exercise 3”
Click Commit then Sync Changes
Option B: Command Line
git add src/assignment.ipynb figures/
git commit -m "Complete Exercise 3"
git push origin main
Grading#
This assignment uses a tiered PASS system:
✅ PASS (Basic Requirements):
All required figures created (4 time series and ellipse plots)
All automated tests pass (harmonic fitting, filtering working)
Personal information completed
Code executes without errors
Analysis questions answered
🌟 PASS PLUS (Professional!): All PASS requirements PLUS:
Clear interpretation of tidal harmonic results in analysis answers
Thoughtful discussion of filtering effects and time scales
Well-formatted figures with appropriate labels and legends
Insightful answers about TEOS-10 vs practical salinity differences
❌ FAIL Conditions:
Missing required outputs (figures, analysis, or code sections)
Test failures (invalid harmonic fits, incorrect filtering)
Code execution errors
Template placeholders not replaced
Tip
Multiple attempts allowed! You can revise and resubmit until the deadline. Each commit triggers new automated tests.
Troubleshooting Common Issues#
1. Harmonic Fitting Problems#
Issue: curve_fit fails or gives unrealistic results
Solutions:
Check for NaN or infinite values in your data
Verify time coordinates are in fractional days, not integer days
Remove outlier data points (e.g., salinity < 19 PSU)
Check initial parameter guesses are reasonable
2. Time Coordinate Issues#
Issue: Time conversion produces unexpected results
Solution: Use the fractional seconds approach:
time_in_days = (data.time - data.time[0]).astype('timedelta64[s]') / np.timedelta64(1, 's') / 86400
Not the integer days approach which rounds to midnight.
3. TEOS-10 Calculation Errors#
Issue: gsw functions fail or give unrealistic values
Solutions:
Verify pressure, latitude, longitude values are reasonable
Check that practical salinity is in expected range (30-40 PSU)
Ensure coordinates are in correct format (decimal degrees)
4. Blank or Empty Figures#
Issue: Saved figures are blank/white or much smaller than expected
Problem: plt.show() is called before plt.savefig(), which clears the figure from memory
Solutions:
Always save before showing: Move
plt.savefig()beforeplt.show()
# Correct order:
plt.savefig('my_figure.png')
plt.show()
Use figure objects when available: Some plots create
figobjects - usefig.savefig()instead:
fig, ax = plt.subplots()
# ... plotting code ...
fig.savefig('my_figure.png') # Use fig.savefig(), not plt.savefig()
plt.show()
When no fig object exists: Use
plt.savefig()but ensure it comes beforeplt.show()
5. For Other Issues#
See Exercise 1 troubleshooting section for:
Virtual environment problems
Package installation issues
Git and submission problems
VS Code kernel selection issues