Using Muldoon

Here are some examples for how to use some of the functionality of Muldoon.

[41]:
%matplotlib inline
%config InlineBackend.figure_format='retina'
%load_ext autoreload
%autoreload 2

import numpy as np
import matplotlib.pyplot as plt

from numpy.random import normal

from scipy.stats import median_abs_deviation as mad

from muldoon.met_timeseries import MetTimeseries, PressureTimeseries, TemperatureTimeseries
from muldoon.utils import modified_lorentzian, fit_vortex, write_out_plot_data
from muldoon.read_data import *


The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload

Make Seconds Since Midnight Plot

[42]:
filename="WE__0089___________DER_PS__________________P01.CSV"
time = make_seconds_since_midnight(filename)
plt.title("Demo: Make Seconds Since Midnight")
plt.xlabel("Item Number")
plt.ylabel("Time (Hours)")
plt.plot(time)
Processing file: WE__0089___________DER_PS__________________P01.CSV
===================================================================
[42]:
[<matplotlib.lines.Line2D at 0x7fb5999a9bd0>]
../_images/examples_Using_Muldoon_4_2.png

Read Data Function

[43]:
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)
ax2 = ax.twinx()

# Read Temperature (ATS) Data
ATSfilename='https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_calibrated_env/sol_0000_0089/sol_0010/WE__0010___________CAL_ATS_________________P01.xml'
temperature_time, temperature = read_Perseverance_ATS_data(ATSfilename, which_ATS=1, end=5)
ax.scatter(temperature_time, temperature)

# Read Pressure (PS) Data
PSfilename="https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_derived_env/sol_0000_0089/sol_0001/WE__0001___________DER_PS__________________P02.xml"
pressure_time, pressure = read_Perseverance_PS_data(PSfilename, end=5)
ax2.scatter(pressure_time, pressure, color='orange')

# Read Wind (WS) Data
WSfilename='https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_derived_env/sol_0180_0299/sol_0190/WE__0190___________DER_WS__________________P02.xml'
wind_time, wind = read_Perseverance_WS_data(WSfilename, end=5)
ax2.scatter(wind_time, wind, color='red')
Processing label: https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_calibrated_env/sol_0000_0089/sol_0010/WE__0010___________CAL_ATS_________________P01.xml
Found a Header structure: HEADER
Found a Table_Delimited structure: TABLE
===================================================================
Processing label: https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_derived_env/sol_0000_0089/sol_0001/WE__0001___________DER_PS__________________P02.xml
Found a Header structure: HEADER
Found a Table_Delimited structure: TABLE
===================================================================
Processing label: https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_derived_env/sol_0180_0299/sol_0190/WE__0190___________DER_WS__________________P02.xml
Found a Header structure: HEADER
Found a Table_Delimited structure: TABLE
===================================================================
[43]:
<matplotlib.collections.PathCollection at 0x7fb598598400>
../_images/examples_Using_Muldoon_6_2.png

Plot Data Function


[44]:
# Reads and plots Temperature vs Time
plot_Perseverance_ATS_data(ATSfilename)

# Reads and plots Pressure vs Time
plot_Perseverance_PS_data(PSfilename)

# Reads and plots Wind vs Time
plot_Perseverance_WS_data(WSfilename)

Processing label: https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_calibrated_env/sol_0000_0089/sol_0010/WE__0010___________CAL_ATS_________________P01.xml
Found a Header structure: HEADER
Found a Table_Delimited structure: TABLE
===================================================================
../_images/examples_Using_Muldoon_8_1.png
Processing label: https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_derived_env/sol_0000_0089/sol_0001/WE__0001___________DER_PS__________________P02.xml
Found a Header structure: HEADER
Found a Table_Delimited structure: TABLE
===================================================================
../_images/examples_Using_Muldoon_8_3.png
Processing label: https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_derived_env/sol_0180_0299/sol_0190/WE__0190___________DER_WS__________________P02.xml
Found a Header structure: HEADER
Found a Table_Delimited structure: TABLE
===================================================================
../_images/examples_Using_Muldoon_8_5.png

Testing Pressure Time Series


[45]:
# Create time-series
time = np.linspace(-10, 10, 1000)
baseline = 0.
slope = 1.
t0 = 0.
DeltaP = 1.
Gamma = 0.5

right_answer = np.array([baseline, slope, t0, DeltaP, Gamma])

profile = modified_lorentzian(time, baseline, slope, t0, DeltaP, Gamma) + normal(scale=slope/20., size=len(time))
mt = PressureTimeseries(time, profile)

Detrended Data Graph Demonstration


[46]:
# Detrend
window_size = Gamma
detrended_pressure = mt.detrend_timeseries_boxcar(window_size)
print(np.std(mt.detrended_data))
print(np.isclose(np.std(mt.detrended_data), 0.1, atol=0.1))

plt.scatter(mt.time, mt.data, marker='.')
plt.scatter(mt.time, mt.detrended_data, marker='.')
0.05237482150437607
True
[46]:
<matplotlib.collections.PathCollection at 0x7fb598802b30>
../_images/examples_Using_Muldoon_12_2.png
[47]:
# Test time-series write-out
write_str = write_out_plot_data(mt.time, mt.data, yerr=np.std(mt.data)*np.ones_like(mt.data),
                                x_label="Time", y_label="Pressure", test_mode=True)

Plot Profiling Demonstration


[48]:
# plt.plot(mt.time, profile)
conv = mt.apply_lorentzian_matched_filter(2.*mt.sampling, 1./np.pi)
mx_ind = np.argmax(mt.convolution)

print(mt.convolution[mx_ind], np.abs(mt.time[mx_ind]), 2.*mt.sampling)
plt.plot(mt.time, mt.convolution, color="purple")
plt.plot(mt.time, profile, color="green")
plt.plot(mt.convolution, color="orange")
# Make sure convolution returns a strong peak at the right time
print((np.abs(mt.time[mx_ind])))
9.960900121027885 0.03003003003003002 0.040040040040040026
0.03003003003003002
../_images/examples_Using_Muldoon_15_1.png

Find Vortices Demonstration


[49]:
vortices = mt.find_vortices(detection_threshold=2)
plt.plot(mt.convolution)
plt.axvline(mt.peak_indices[0] - 3.*mt.peak_widths[0])
plt.axvline(mt.peak_indices[0] + 3.*mt.peak_widths[0])

# Make sure the max peak in the convolution is the right one
assert(mt.time[mt.peak_indices[0]] < Gamma)
../_images/examples_Using_Muldoon_17_0.png
[50]:
# Test find_vortices
vortices = mt.find_vortices(detection_threshold=7)
plt.plot(mt.time, mt.data)
plt.axvline(mt.time[mt.peak_indices[0] - 3*int(mt.peak_widths[0])])
plt.axvline(mt.time[mt.peak_indices[0] + 3*int(mt.peak_widths[0])])
[50]:
<matplotlib.lines.Line2D at 0x7fb598ae4250>
../_images/examples_Using_Muldoon_18_1.png

Vortex Fit Demonstration


[51]:
plt.scatter(vortices[0]["time"], vortices[0]["data"])

# Test vortex fit
old_popt, old_unc = fit_vortex(vortices[0], [0., 1., 0., 1., 0.01],
                          [[-1, -1, np.min(vortices[0]["time"]), 0, 0],
                           [1, 1, np.max(vortices[0]["time"]), 2, 1]], sigma=vortices[0]["scatter"])
assert(np.max(np.abs(old_popt - right_answer)/old_unc) < 3.)

plt.plot(vortices[0]["time"], modified_lorentzian(vortices[0]["time"], *old_popt))
[51]:
[<matplotlib.lines.Line2D at 0x7fb596342650>]
../_images/examples_Using_Muldoon_20_1.png
[52]:
init_params = mt._determine_init_params(vortices[0])
bounds = mt._determine_bounds(vortices[0], init_params)
popt, unc = fit_vortex(vortices[0], init_params, bounds, sigma=vortices[0]["scatter"])
assert(np.max(np.abs(popt - right_answer)/unc) < 3.)

print(np.max(np.abs(popt - right_answer)/unc))
1.223916561695807

Fit All Vortices Demonstration


[53]:
# Test fit all vortices

# Create time-series
time = np.linspace(-10, 10, 1000)
baseline = 0.
slope = 1.
t0 = 0.
DeltaP = 1.
Gamma = 0.5

right_answer = np.array([baseline, slope, t0, DeltaP, Gamma])

profile = modified_lorentzian(time, baseline, slope, t0, DeltaP, Gamma) + normal(scale=slope/20., size=len(time))
mt = PressureTimeseries(time, profile)
window_size = Gamma
detrended_pressure = mt.detrend_timeseries_boxcar(window_size)

conv = mt.apply_lorentzian_matched_filter(2.*mt.sampling, 1./np.pi)
vortices = mt.find_vortices(detection_threshold=7)

popts, uncs = mt.fit_all_vortices()
print(np.max(np.abs(popts[0] - right_answer)/uncs[0]))
assert(np.max(np.abs(popts[0] - right_answer)/uncs[0]) < 5.)
1.1426068795027213

Condition Fit/Per-Panel Write-Out Demonstration


[54]:
# Make plot showing how the data are conditioned and write out the data in each panel
mt.make_conditioned_data_figure(write_filename="./test_");
../_images/examples_Using_Muldoon_25_0.png

Further Time-Series Demonstration (With Added Noise/Interference to Data)


[55]:
# Create time-series
time = np.linspace(-10, 10, 1000)
baseline = 0.
slope = 1.
t0 = 0.
DeltaP = 1.
Gamma = 0.5

DeltaT = -10.

right_answer = np.array([baseline, slope, t0, DeltaP, Gamma])
temp_right_answer = np.array([baseline, slope, t0, DeltaT, Gamma])

profile = modified_lorentzian(time, baseline, slope, t0, DeltaP, Gamma) + normal(scale=slope/20., size=len(time))
mt = PressureTimeseries(time, profile)

# Add in some nasty sine wave action
red_noise_period = Gamma
temp_profile = modified_lorentzian(time, *temp_right_answer) +\
    normal(scale=slope, size=len(time)) + DeltaT/10.*np.sin(2*np.pi/red_noise_period*time)
tt = TemperatureTimeseries(time, temp_profile,
                           popts=[right_answer],
                           uncs=[np.array([0, 0, 0, 0, 0])])
plt.scatter(tt.time, tt.data)

plt.axvline(tt.popts[0][2])
[55]:
<matplotlib.lines.Line2D at 0x7fb599905540>
../_images/examples_Using_Muldoon_27_1.png

Retrieve Vortices Demonstration


[56]:
tt.retrieve_vortices()
plt.scatter(tt.vortices[0]["time"], tt.vortices[0]["data"])
print(len(tt.vortices[0]["time"]))
150
../_images/examples_Using_Muldoon_29_1.png

Vortex Normal Linear Regression Demonstration


[57]:
# Fit vortex using normal linear regression
# baseline, slope, t0, DeltaT, Gamma
temp_baseline = np.mean(tt.vortices[0]["data"])
temp_avg_slope = (tt.vortices[0]["data"][-1] - tt.vortices[0]["data"][0])/\
    (tt.vortices[0]["time"][-1] - tt.vortices[0]["time"][0])
max_excursion = -np.abs(np.max(tt.vortices[0]["data"]) - np.min(tt.vortices[0]["data"]))

sigma = mad(tt.vortices[0]["data"])

init_params = [temp_baseline, temp_avg_slope, t0, max_excursion, Gamma]
bounds = [[np.min(tt.vortices[0]["data"]), -3.*np.abs(temp_avg_slope), np.min(tt.vortices[0]["time"]),
           -3.*np.abs(max_excursion), 0.],
          [np.max(tt.vortices[0]["data"]),  3.*np.abs(temp_avg_slope), np.max(tt.vortices[0]["time"]),
            0., 3.*Gamma]]

popt, unc = fit_vortex(tt.vortices[0], init_params, bounds)
# print(popt)
# print(unc)
# print(temp_right_answer)

plt.scatter(tt.vortices[0]["time"], tt.vortices[0]["data"])
plt.plot(tt.vortices[0]["time"], modified_lorentzian(tt.vortices[0]["time"], *popt), lw=3, color='orange')
[57]:
[<matplotlib.lines.Line2D at 0x7fb5988aa1a0>]
../_images/examples_Using_Muldoon_31_1.png
[58]:
# Fit vortex using Gaussian processes - https://george.readthedocs.io/en/latest/tutorials/model/

Temperature Time Series Demonstration


[59]:
time, temperature = read_Perseverance_ATS_data(ATSfilename, which_ATS=1)
tt = TemperatureTimeseries(time, temperature)
plt.scatter(tt.time, tt.data, marker='.')
Processing label: https://pds-atmospheres.nmsu.edu/PDS/data/PDS4/Mars2020/mars2020_meda/data_calibrated_env/sol_0000_0089/sol_0010/WE__0010___________CAL_ATS_________________P01.xml
Found a Header structure: HEADER
Found a Table_Delimited structure: TABLE
===================================================================
[59]:
<matplotlib.collections.PathCollection at 0x7fb5987e5000>
../_images/examples_Using_Muldoon_34_2.png
[60]:
###                     Currently experience div-by-zero error                     ###

# Detrend
# window_size = 1. # 1 hour
# detrended_temperature = tt.detrend_timeseries_boxcar(window_size)
# plt.scatter(tt.time, tt.detrended_data, marker='.')