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 testing

  • modules/tools.py - Helper functions for harmonic analysis

  • tests/ - Automated tests that run when you submit

  • requirements.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)#

  1. Clone your assignment repository (get URL from GitHub Classroom)

  2. Navigate to the folder and activate your virtual environment

  3. Install new packages: pip install -r requirements.txt (includes scipy, gsw)

  4. Open in VS Code: File Open Folder → Select assignment folder

  5. Start working: Open src/assignment.ipynb

First-Time Setup or Troubleshooting#

For complete setup instructions, troubleshooting, and help, see:

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#

  1. Update your information (name, date, student ID)

  2. Load and analyze CTD time series data - salinity, temperature, pressure

  3. Implement TEOS-10 calculations - absolute salinity and conservative temperature

  4. Perform harmonic analysis - fit M2 tidal harmonics to salinity and velocity data

  5. Create tidal ellipse plots - visualize velocity patterns

  6. Apply time series filtering - implement boxcar filters and compare results

  7. 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

  8. 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)

  1. Open the Source Control panel (Ctrl+Shift+G)

  2. Stage your changes by clicking the + button next to src/assignment.ipynb

  3. Add a commit message: “Complete Exercise 3”

  4. 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() before plt.show()

# Correct order:
plt.savefig('my_figure.png')
plt.show()
  • Use figure objects when available: Some plots create fig objects - use fig.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 before plt.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