<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Plotting utilities
xarrayutils provides a bunch of small functions to adjust matplotlib plots.
Setting multiple y axes to the same values range
Sometimes it is beneficial if the amplitude of a signal can be compared directly. If the mean of the signal is shifted, setting the absolute y limits doesnt work. same_y_range provides a quick fix.
Step1:  These are hard to compare with regard to their amplitude.
Step2:  Now we can clearly see the different amplitude. 
shaded line plots
Step3:  Thats pretty cool (xarray is generally awesome!), but what if we have several of these datasets (e.g. climate models with several members each)?
Step4:  Ok that is not great. We can color each dataset with a different color...
Step5:  But if you supply more models this ends up looking too busy. xarrayutils.plotting.shaded_line_plot give a quick alternative to show the spread of the members with a line and shaded envelope
Step6:  In the default setting, this plots the mean along the dimension member as a line and the ranges indicate 1 standard deviation (dark shading) and 3 standard deviations (light shading). The transparency and spread values can be customized.
We can confirm this by tracing the shading with some more lines
Step7:  Lets add shading for 2, 3, and 5 standard deviations with different increasing alpha values (increasing alpha for increased transparency).
Step8:  Additionally shaded_line_plot offers a different mode to determine the spread, using quantiles.
Step9:  The default spreads value is [0.5, 0.8] which means the outer shading indicates the 25th and 75th percentile, and the inner one the 10th and 90th percentile. You can customize this just like before.
Step10:  Here the lines indicate the 50th quantile (approximate median), and the shadings indicate the range between the 25th and 75th percentile (dark) and the full range between 0th and 100th percentile (light
Scale axis with two different linear scales
A widely used plot in oceanography is a North South section through an ocean basin. Lets plot an oxygen section in the central pacific from the World Ocean Atlas
Step11:  You can see that there is a lot more structure to the oxygen field in the upper ~1000m, and less below. Yet the plot is visually dominated by the deep ocean. We can focus on the upper ocean by compressing the values below 1000 m using linear_piecewise_scale.
Step12:  Now you can see the uppr ocean structure more clearly, without completely cutting out the deep ocean. We can adjust the cut (the point of the y-axis where the different linear scales meet) and the scale (higher numbers mean a stronger compression of the deep ocean).
Step13:  We could also compress the upper ocean using the scaled_half argument. Here upper means values larger than cut are compressed and lower means values smaller than cut are compressed instead
Step14:  You can apply all of the above to the x-axis as well, using th axis keyword.
Step15:  This would put the focus on the southen hemisphere.
<ASSISTANT_TASK:>
Python Code:
import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
%load_ext autoreload
%autoreload 2
fig, axarr = plt.subplots(ncols=2, nrows=2)
# plot the same signal scaled and shifted or both
axarr.flat[0].plot(np.random.rand(10))
axarr.flat[1].plot((np.random.rand(10)*5)-16)
axarr.flat[2].plot((np.random.rand(10))-16)
axarr.flat[3].plot((np.random.rand(10)*5))
Explanation: Plotting utilities
xarrayutils provides a bunch of small functions to adjust matplotlib plots.
Setting multiple y axes to the same values range
Sometimes it is beneficial if the amplitude of a signal can be compared directly. If the mean of the signal is shifted, setting the absolute y limits doesnt work. same_y_range provides a quick fix.
End of explanation
from xarrayutils.plotting import same_y_range
fig, axarr = plt.subplots(ncols=2, nrows=2)
# plot the same signal scaled and shifted or both
axarr.flat[0].plot(np.random.rand(10))
axarr.flat[1].plot((np.random.rand(10)*5)-16)
axarr.flat[2].plot((np.random.rand(10))-16)
axarr.flat[3].plot((np.random.rand(10)*5))
same_y_range(axarr)
Explanation: These are hard to compare with regard to their amplitude.
End of explanation
from xarrayutils.plotting import shaded_line_plot
# build test dataset with noisy members
x = np.linspace(0,2*np.pi, 10)
y = np.sin(x)
y_full = np.stack([y+np.random.rand(len(y))*2-0.5 for e in range(6)])
da = xr.DataArray(y_full, coords=[('member',range(6)),('time',x)])
da.plot(hue='member');
Explanation: Now we can clearly see the different amplitude. 
shaded line plots
End of explanation
x = np.linspace(0,2*np.pi, 10)
y = np.sin(x+2)
y_full = np.stack([y+np.random.rand(len(y))*2-0.5 for e in range(6)])
da2 = xr.DataArray(y_full, coords=[('member',range(6)),('time',x)])
da.plot(hue='member')
da2.plot(hue='member');
Explanation: Thats pretty cool (xarray is generally awesome!), but what if we have several of these datasets (e.g. climate models with several members each)?
End of explanation
da.plot(hue='member', color='C0')
da2.plot(hue='member', color='C1');
Explanation: Ok that is not great. We can color each dataset with a different color...
End of explanation
shaded_line_plot(da, 'member', color='C0');
shaded_line_plot(da2, 'member', color='C1');
Explanation: But if you supply more models this ends up looking too busy. xarrayutils.plotting.shaded_line_plot give a quick alternative to show the spread of the members with a line and shaded envelope:
End of explanation
shaded_line_plot(da, 'member', color='C0')
(da.mean('member') + da.std('member') / 2).plot(color='k', ls='--')
(da.mean('member') + da.std('member') * 3 / 2).plot(color='k', ls='-.')
Explanation: In the default setting, this plots the mean along the dimension member as a line and the ranges indicate 1 standard deviation (dark shading) and 3 standard deviations (light shading). The transparency and spread values can be customized.
We can confirm this by tracing the shading with some more lines
End of explanation
shaded_line_plot(da, 'member', spreads=[2,3,5], alphas=[0.1, 0.3, 0.4], color='C0');
shaded_line_plot(da2, 'member',spreads=[2,3,5], alphas=[0.2, 0.5, 0.6], color='C1');
Explanation: Lets add shading for 2, 3, and 5 standard deviations with different increasing alpha values (increasing alpha for increased transparency).
End of explanation
shaded_line_plot(da, 'member', spread_style='quantile', color='C0');
da.quantile(0.25,'member').plot(color='k', ls='--')
da.quantile(0.1,'member').plot(color='k', ls='--')
Explanation: Additionally shaded_line_plot offers a different mode to determine the spread, using quantiles.
End of explanation
shaded_line_plot(da, 'member', spread_style='quantile', spreads=[0.5,1], color='C0');
shaded_line_plot(da2, 'member',spread_style='quantile', spreads=[0.5,1], color='C1');
Explanation: The default spreads value is [0.5, 0.8] which means the outer shading indicates the 25th and 75th percentile, and the inner one the 10th and 90th percentile. You can customize this just like before.
End of explanation
woa_path = 'https://data.nodc.noaa.gov/thredds/dodsC/ncei/woa/oxygen/all/1.00/woa18_all_o00_01.nc'
woa = xr.open_dataset(woa_path, decode_times=False)
o2 = woa[['o_an']].squeeze(drop=True).o_an
o2.sel(lon=-180, method='nearest').plot(robust=True)
plt.gca().invert_yaxis()
Explanation: Here the lines indicate the 50th quantile (approximate median), and the shadings indicate the range between the 25th and 75th percentile (dark) and the full range between 0th and 100th percentile (light
Scale axis with two different linear scales
A widely used plot in oceanography is a North South section through an ocean basin. Lets plot an oxygen section in the central pacific from the World Ocean Atlas
End of explanation
from xarrayutils.plotting import linear_piecewise_scale
o2.sel(lon=-180, method='nearest').plot(robust=True)
ax = plt.gca()
ax.invert_yaxis()
linear_piecewise_scale(1000, 5)
#indicate the point between the different scalings
ax.axhline(1000, color='0.5', ls='--')
# Rearange the yticks
ax.set_yticks([0, 250, 500, 750, 1000, 3000, 5000]);
Explanation: You can see that there is a lot more structure to the oxygen field in the upper ~1000m, and less below. Yet the plot is visually dominated by the deep ocean. We can focus on the upper ocean by compressing the values below 1000 m using linear_piecewise_scale.
End of explanation
o2.sel(lon=-180, method='nearest').plot(robust=True)
ax = plt.gca()
ax.invert_yaxis()
linear_piecewise_scale(500, 20)
#indicate the point between the different scalings
ax.axhline(500, color='0.5', ls='--')
# Rearange the yticks
ax.set_yticks([0, 125, 250, 375, 500, 2000, 4000, 6000]);
Explanation: Now you can see the uppr ocean structure more clearly, without completely cutting out the deep ocean. We can adjust the cut (the point of the y-axis where the different linear scales meet) and the scale (higher numbers mean a stronger compression of the deep ocean).
End of explanation
o2.sel(lon=-180, method='nearest').plot(robust=True)
ax = plt.gca()
ax.invert_yaxis()
linear_piecewise_scale(1000, 2, scaled_half='lower')
#indicate the point between the different scalings
ax.axhline(1000, color='0.5', ls='--')
# Rearange the yticks
ax.set_yticks([0, 1000, 2000, 3000, 4000, 5000, 6000]);
Explanation: We could also compress the upper ocean using the scaled_half argument. Here upper means values larger than cut are compressed and lower means values smaller than cut are compressed instead
End of explanation
o2.sel(lon=-180, method='nearest').plot(robust=True)
ax = plt.gca()
ax.invert_yaxis()
linear_piecewise_scale(0, 2, axis='x')
#indicate the point between the different scalings
ax.axvline(0, color='0.5', ls='--')
Explanation: You can apply all of the above to the x-axis as well, using th axis keyword.
End of explanation
ax.get_xscale()
Explanation: This would put the focus on the southen hemisphere.
End of explanation
<END_TASK>