ENSO
Purpose:
Compute and plot the ENSO variability and nin3.4 index.
Acknowledgment:
This notebook builds on work by John Krasting (https://github.com/jkrasting/mar/blob/main/src/gfdlnb/notebooks/ocean/ENSO.ipynb) and a tutorial provided by the Project Pythia (https://foundations.projectpythia.org/core/xarray/enso-xarray.html)
[1]:
%load_ext autoreload
%autoreload 2
[2]:
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
import matplotlib
import numpy as np
import xarray as xr
import momlevel as ml
import xwavelet as xw
from mom6_tools.jobqueue import get_cluster
from mom6_tools.MOM6grid import MOM6grid
from mom6_tools.m6toolbox import cime_xmlquery
from mom6_tools.m6toolbox import add_global_attrs
from mom6_tools.enso import plot_enso_obs
from mom6_tools.m6toolbox import geoslice
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import yaml, os, intake, pickle
[3]:
# Read in the yaml file
diag_config_yml_path = "diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[4]:
caseroot = diag_config_yml['Case']['CASEROOT']
casename = cime_xmlquery(caseroot, 'CASE')
DOUT_S = cime_xmlquery(caseroot, 'DOUT_S')
if DOUT_S:
OUTDIR = cime_xmlquery(caseroot, 'DOUT_S_ROOT')+'/ocn/hist/'
else:
OUTDIR = cime_xmlquery(caseroot, 'RUNDIR')
print('Output directory is:', OUTDIR)
print('Casename is:', casename)
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[4], line 2
1 caseroot = diag_config_yml['Case']['CASEROOT']
----> 2 casename = cime_xmlquery(caseroot, 'CASE')
3 DOUT_S = cime_xmlquery(caseroot, 'DOUT_S')
4 if DOUT_S:
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/mom6_tools/m6toolbox.py:47, in cime_xmlquery(caseroot, varname)
45 """run CIME's xmlquery for varname in the directory caseroot, return the value"""
46 try:
---> 47 value = subprocess.check_output(
48 ["./xmlquery", "-N", "--value", varname],
49 stderr=subprocess.STDOUT,
50 cwd=caseroot,
51 )
52 except subprocess.CalledProcessError:
53 value = subprocess.check_output(
54 ["./xmlquery", "--value", varname], stderr=subprocess.STDOUT, cwd=caseroot
55 )
File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
418 empty = b''
419 kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
422 **kwargs).stdout
File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
500 kwargs['stdout'] = PIPE
501 kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
504 try:
505 stdout, stderr = process.communicate(input, timeout=timeout)
File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
967 if self.text_mode:
968 self.stderr = io.TextIOWrapper(self.stderr,
969 encoding=encoding, errors=errors)
--> 971 self._execute_child(args, executable, preexec_fn, close_fds,
972 pass_fds, cwd, env,
973 startupinfo, creationflags, shell,
974 p2cread, p2cwrite,
975 c2pread, c2pwrite,
976 errread, errwrite,
977 restore_signals,
978 gid, gids, uid, umask,
979 start_new_session)
980 except:
981 # Cleanup if the child failed starting.
982 for f in filter(None, (self.stdin, self.stdout, self.stderr)):
File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
1861 if errno_num != 0:
1862 err_msg = os.strerror(errno_num)
-> 1863 raise child_exception_type(errno_num, err_msg, err_filename)
1864 raise child_exception_type(err_msg)
FileNotFoundError: [Errno 2] No such file or directory: '/glade/work/gmarques/cesm.cases/G/g.e30_a07c_cesm.GJRAv4.TL319_t232_wgx3_hycom1_N75.2025.130/'
[5]:
# The following parameters must be set accordingly
# create an empty class object
class args:
pass
args.infile = OUTDIR
args.native = casename+diag_config_yml['Fnames']['native']
args.static = casename+diag_config_yml['Fnames']['static']
args.geom = casename+diag_config_yml['Fnames']['geom']
args.year_shift = 0 #1957 # Option to shift by args.year_shift years
args.casename = casename
args.label = diag_config_yml['Case']['SNAME']
args.savefigs = False
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[5], line 6
3 class args:
4 pass
----> 6 args.infile = OUTDIR
7 args.native = casename+diag_config_yml['Fnames']['native']
8 args.static = casename+diag_config_yml['Fnames']['static']
NameError: name 'OUTDIR' is not defined
[6]:
# read grid info
geom_file = OUTDIR+'/'+args.geom
if os.path.exists(geom_file):
grd = MOM6grid(OUTDIR+'/'+args.static, geom_file, xrformat=True)
else:
grd = MOM6grid(OUTDIR+'/'+args.static, xrformat=True)
try:
depth = grd.depth_ocean
except:
depth = grd.deptho
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[6], line 2
1 # read grid info
----> 2 geom_file = OUTDIR+'/'+args.geom
3 if os.path.exists(geom_file):
4 grd = MOM6grid(OUTDIR+'/'+args.static, geom_file, xrformat=True)
NameError: name 'OUTDIR' is not defined
[7]:
parallel, cluster, client = get_cluster(6, cluster_class='PBSCluster')
client
Starting a dask cluster: PBSCluster
Requesting 6 workers...
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[7], line 1
----> 1 parallel, cluster, client = get_cluster(6, cluster_class='PBSCluster')
2 client
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/mom6_tools/jobqueue.py:300, in get_cluster(nw, cluster_class, args, config, **kwargs)
297 print('Requesting {} workers... \n'.format(nw))
298 if is_jobqueue_cluster:
299 # dask.config.set({'distributed.dashboard.link': '/proxy/{port}/status'})
--> 300 cluster = cluster_class(**kwargs)
301 cluster.scale(nw)
302 else:
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/dask_jobqueue/core.py:656, in JobQueueCluster.__init__(self, n_workers, job_cls, loop, security, shared_temp_directory, silence_logs, name, asynchronous, dashboard_address, host, scheduler_options, scheduler_cls, interface, protocol, config_name, **job_kwargs)
653 self._job_kwargs = job_kwargs
655 worker = {"cls": self.job_cls, "options": self._job_kwargs}
--> 656 if "processes" in self._job_kwargs and self._job_kwargs["processes"] > 1:
657 worker["group"] = [
658 "-" + str(i) for i in range(self._job_kwargs["processes"])
659 ]
661 self._dummy_job # trigger property to ensure that the job is valid
TypeError: '>' not supported between instances of 'NoneType' and 'int'
Load model data
[8]:
def preprocess(ds):
''' Return a dataset desired variables'''
variables = ['tos']
return ds[variables]
[9]:
print('\n Reading dataset...')
# load data
%time ds = xr.open_mfdataset(OUTDIR+'/'+args.native, parallel=True, \
combine="nested", concat_dim="time", \
preprocess=preprocess).chunk({"time": 12})
Reading dataset...
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
File <timed exec>:1
NameError: name 'OUTDIR' is not defined
[10]:
# Add the latitude and longitude as new coordinates to the pv DataArray
ds = ds.assign_coords({
"latitude": (("yh", "xh"), grd.geolat.data),
"longitude": (("yh", "xh"), grd.geolon.data),
"areacello": (("yh", "xh"), grd.areacello.fillna(0.).data)
})
#ds
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[10], line 2
1 # Add the latitude and longitude as new coordinates to the pv DataArray
----> 2 ds = ds.assign_coords({
3 "latitude": (("yh", "xh"), grd.geolat.data),
4 "longitude": (("yh", "xh"), grd.geolon.data),
5 "areacello": (("yh", "xh"), grd.areacello.fillna(0.).data)
6 })
7 #ds
NameError: name 'ds' is not defined
[11]:
# Nino3.4 SST
nino34 = geoslice(ds.tos,y=(-5,5),x=(-170,-120),
xcoord="longitude", ycoord="latitude")
#nino34
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[11], line 2
1 # Nino3.4 SST
----> 2 nino34 = geoslice(ds.tos,y=(-5,5),x=(-170,-120),
3 xcoord="longitude", ycoord="latitude")
4 #nino34
NameError: name 'ds' is not defined
Check the nino3.4 region
[12]:
fig = plt.figure(figsize=(12, 6))
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180))
ax.coastlines()
ax.gridlines()
nino34.isel(time=0).plot(
ax=ax, transform=ccrs.PlateCarree(), vmin=-2, vmax=30, cmap='coolwarm'
)
ax.set_extent((120, 300, 10, -10))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[12], line 5
3 ax.coastlines()
4 ax.gridlines()
----> 5 nino34.isel(time=0).plot(
6 ax=ax, transform=ccrs.PlateCarree(), vmin=-2, vmax=30, cmap='coolwarm'
7 )
8 ax.set_extent((120, 300, 10, -10))
NameError: name 'nino34' is not defined
Compute index
[13]:
gb = nino34.groupby('time.month')
nino34_anom = gb - gb.mean(dim='time')
index_nino34_model = nino34_anom.weighted(nino34.areacello).mean(dim=['yh', 'xh'])
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[13], line 1
----> 1 gb = nino34.groupby('time.month')
2 nino34_anom = gb - gb.mean(dim='time')
3 index_nino34_model = nino34_anom.weighted(nino34.areacello).mean(dim=['yh', 'xh'])
NameError: name 'nino34' is not defined
[14]:
index_nino34_model_rolling_mean = index_nino34_model.rolling(time=5, center=True).mean()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[14], line 1
----> 1 index_nino34_model_rolling_mean = index_nino34_model.rolling(time=5, center=True).mean()
NameError: name 'index_nino34_model' is not defined
[15]:
index_nino34_model.plot(size=8)
index_nino34_model_rolling_mean.plot()
plt.legend(['anomaly', '5-month running mean anomaly'])
plt.title('SST anomaly over the Niño 3.4 region');
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[15], line 1
----> 1 index_nino34_model.plot(size=8)
2 index_nino34_model_rolling_mean.plot()
3 plt.legend(['anomaly', '5-month running mean anomaly'])
NameError: name 'index_nino34_model' is not defined
[16]:
std_dev_model = nino34.std()
#std_dev_model
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[16], line 1
----> 1 std_dev_model = nino34.std()
2 #std_dev_model
NameError: name 'nino34' is not defined
[17]:
# normalize by std
normalized_index_nino34_model_rolling_mean = index_nino34_model_rolling_mean / std_dev_model
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[17], line 2
1 # normalize by std
----> 2 normalized_index_nino34_model_rolling_mean = index_nino34_model_rolling_mean / std_dev_model
NameError: name 'index_nino34_model_rolling_mean' is not defined
[18]:
#Apply the Conditions to Create the New Data Array
# Define conditions
conditions = [
normalized_index_nino34_model_rolling_mean >= 0.4,
normalized_index_nino34_model_rolling_mean <= -0.4
]
x = normalized_index_nino34_model_rolling_mean.time.data
# Define corresponding values
values = [1, -1]
# Apply conditions
index = np.select(conditions, values, default=0)
# Create DataArray
nino34_index = xr.DataArray(
index,
coords=[('time',x)],
name='nino34_index'
)
# Add the DataArray to the Dataset
normalized_index_nino34_model_rolling_mean['nino34_index'] = nino34_index
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[18], line 4
1 #Apply the Conditions to Create the New Data Array
2 # Define conditions
3 conditions = [
----> 4 normalized_index_nino34_model_rolling_mean >= 0.4,
5 normalized_index_nino34_model_rolling_mean <= -0.4
6 ]
8 x = normalized_index_nino34_model_rolling_mean.time.data
9 # Define corresponding values
NameError: name 'normalized_index_nino34_model_rolling_mean' is not defined
Shift time coordinate to align with forcing dataset (optional)
[19]:
if args.year_shift > 0:
time = normalized_index_nino34_model_rolling_mean.time.data
shifted_time = [t.replace(year=t.year + args.year_shift) for t in time]
# Convert back to xarray coordinate if needed
time_shifted = xr.DataArray(shifted_time, dims=["time"], name="shifted_time")
normalized_index_nino34_model_rolling_mean['time'] = time_shifted
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[19], line 1
----> 1 if args.year_shift > 0:
2 time = normalized_index_nino34_model_rolling_mean.time.data
3 shifted_time = [t.replace(year=t.year + args.year_shift) for t in time]
AttributeError: type object 'args' has no attribute 'year_shift'
[20]:
fig = plt.figure(figsize=(12, 6))
plt.fill_between(
normalized_index_nino34_model_rolling_mean.time.data,
normalized_index_nino34_model_rolling_mean.where(
normalized_index_nino34_model_rolling_mean >= 0.4
),
0.4,
color='red',
alpha=0.9,
)
plt.fill_between(
normalized_index_nino34_model_rolling_mean.time.data,
normalized_index_nino34_model_rolling_mean.where(
normalized_index_nino34_model_rolling_mean <= -0.4
),
-0.4,
color='blue',
alpha=0.9,
)
normalized_index_nino34_model_rolling_mean.plot(color='black')
plt.axhline(0, color='black', lw=0.5)
plt.axhline(0.4, color='black', linewidth=0.5, linestyle='dotted')
plt.axhline(-0.4, color='black', linewidth=0.5, linestyle='dotted')
plt.title('Case {}, Niño 3.4 Index'.format(args.label));
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[20], line 4
1 fig = plt.figure(figsize=(12, 6))
3 plt.fill_between(
----> 4 normalized_index_nino34_model_rolling_mean.time.data,
5 normalized_index_nino34_model_rolling_mean.where(
6 normalized_index_nino34_model_rolling_mean >= 0.4
7 ),
8 0.4,
9 color='red',
10 alpha=0.9,
11 )
12 plt.fill_between(
13 normalized_index_nino34_model_rolling_mean.time.data,
14 normalized_index_nino34_model_rolling_mean.where(
(...)
19 alpha=0.9,
20 )
22 normalized_index_nino34_model_rolling_mean.plot(color='black')
NameError: name 'normalized_index_nino34_model_rolling_mean' is not defined
<Figure size 1200x600 with 0 Axes>
[21]:
description = 'Nino 3.4 index'
attrs = {'description': description,
}
add_global_attrs(normalized_index_nino34_model_rolling_mean,attrs)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[21], line 4
1 description = 'Nino 3.4 index'
2 attrs = {'description': description,
3 }
----> 4 add_global_attrs(normalized_index_nino34_model_rolling_mean,attrs)
NameError: name 'normalized_index_nino34_model_rolling_mean' is not defined
[22]:
print('Saving netCDF files...')
os.makedirs('ncfiles', exist_ok=True)
normalized_index_nino34_model_rolling_mean.to_netcdf('ncfiles/'+str(args.casename)+'_nino34_index.nc')
Saving netCDF files...
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[22], line 3
1 print('Saving netCDF files...')
2 os.makedirs('ncfiles', exist_ok=True)
----> 3 normalized_index_nino34_model_rolling_mean.to_netcdf('ncfiles/'+str(args.casename)+'_nino34_index.nc')
NameError: name 'normalized_index_nino34_model_rolling_mean' is not defined
Compute composite
[23]:
nino34 = nino34.weighted(nino34.areacello).mean(("yh","xh"))
nino34 = nino34.load()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[23], line 1
----> 1 nino34 = nino34.weighted(nino34.areacello).mean(("yh","xh"))
2 nino34 = nino34.load()
NameError: name 'nino34' is not defined
[24]:
result_model = xw.Wavelet(nino34, scaled=True)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[24], line 1
----> 1 result_model = xw.Wavelet(nino34, scaled=True)
NameError: name 'nino34' is not defined
[25]:
fig = result_model.composite()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[25], line 1
----> 1 fig = result_model.composite()
NameError: name 'result_model' is not defined
[26]:
# save composite into a pickle file
fname = "ncfiles/" + str(args.casename)+'_nino34_composite.pkl'
with open(fname, "wb") as file:
pickle.dump(result_model, file)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[26], line 2
1 # save composite into a pickle file
----> 2 fname = "ncfiles/" + str(args.casename)+'_nino34_composite.pkl'
3 with open(fname, "wb") as file:
4 pickle.dump(result_model, file)
AttributeError: type object 'args' has no attribute 'casename'
[27]:
# This is how the pickle file can be loaded and plotted
#with open("../result_model.pkl", "rb") as file:
# loaded_obj = pickle.load(file)
#fig = loaded_obj.composite()
ENSO in OiSSTv2
[28]:
# load obs-based sst from oce-catalog
catalog = intake.open_catalog(diag_config_yml['oce_cat'])
obs = catalog['oisstv2-tx2_3v2'].to_dask()
obs = obs.assign_coords({
"areacello": (("yh", "xh"), grd.areacello.fillna(0.).data)
})
obs
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[28], line 2
1 # load obs-based sst from oce-catalog
----> 2 catalog = intake.open_catalog(diag_config_yml['oce_cat'])
3 obs = catalog['oisstv2-tx2_3v2'].to_dask()
4 obs = obs.assign_coords({
5 "areacello": (("yh", "xh"), grd.areacello.fillna(0.).data)
6 })
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/__init__.py:186, in open_catalog(uri, **kwargs)
179 raise ValueError(
180 f"Unknown catalog driver '{driver}'. "
181 "Do you need to install a new driver from the plugin directory? "
182 "https://intake.readthedocs.io/en/latest/plugin-directory.html\n"
183 f"Current registry: {list(sorted(registry))}"
184 )
185 try:
--> 186 return registry[driver](uri, **kwargs)
187 except VersionError:
188 # warn that we are switching to V2? The file will be read twice
189 return from_yaml_file(uri, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/local.py:617, in YAMLFileCatalog.__init__(self, path, text, autoreload, **kwargs)
615 self.filesystem = kwargs.pop("fs", None)
616 self.access = "name" not in kwargs
--> 617 super(YAMLFileCatalog, self).__init__(**kwargs)
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/base.py:128, in Catalog.__init__(self, entries, name, description, metadata, ttl, getenv, getshell, persist_mode, storage_options, user_parameters)
126 self.updated = time.time()
127 self._entries = entries if entries is not None else self._make_entries_container()
--> 128 self.force_reload()
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/base.py:186, in Catalog.force_reload(self)
184 """Imperative reload data now"""
185 self.updated = time.time()
--> 186 self._load()
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/local.py:652, in YAMLFileCatalog._load(self, reload)
650 logger.warning("Use of '!template' deprecated - fixing")
651 text = text.replace("!template ", "")
--> 652 self.parse(text)
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/local.py:730, in YAMLFileCatalog.parse(self, text)
728 # Second, we validate the schema and semantics
729 context = dict(root=self._dir)
--> 730 result = CatalogParser(data, context=context, getenv=self.getenv, getshell=self.getshell)
731 if result.errors:
732 raise exceptions.ValidationError(
733 "Catalog '{}' has validation errors:\n\n{}"
734 "".format(self.path, "\n".join(result.errors)),
735 result.errors,
736 )
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/local.py:342, in CatalogParser.__init__(self, data, getenv, getshell, context)
340 self.getenv = getenv
341 self.getshell = getshell
--> 342 self._data = self._parse(data)
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/local.py:565, in CatalogParser._parse(self, data)
561 if (data.get("version", None) or data.get("metadata", {}).get("version", None) or 1) > 1:
562 raise VersionError("Not a V1 Catalog; perhaps use intake.open_catalog")
564 return dict(
--> 565 plugin_sources=self._parse_plugins(data),
566 data_sources=self._parse_data_sources(data),
567 metadata=data.get("metadata", {}),
568 name=data.get("name"),
569 description=data.get("description"),
570 )
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/catalog/local.py:400, in CatalogParser._parse_plugins(self, data)
397 elif "module" in plugin_source:
398 import intake
--> 400 intake.import_name(plugin_source["module"])
401 elif "dir" in plugin_source:
402 self.error(
403 "The key 'dir', and in general the feature of registering "
404 "plugins from a directory of Python scripts outside of "
405 "sys.path, is no longer supported. Use 'module'.",
406 plugin_source,
407 )
File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/intake/utils.py:27, in import_name(name)
25 modname = name.split(":", 1)[0]
26 logger.debug("Importing: '%s'" % modname)
---> 27 mod = importlib.import_module(modname)
28 if ":" in name:
29 end = name.split(":")[1]
File ~/.asdf/installs/python/3.10.20/lib/python3.10/importlib/__init__.py:126, in import_module(name, package)
124 break
125 level += 1
--> 126 return _bootstrap._gcd_import(name[level:], package, level)
File <frozen importlib._bootstrap>:1050, in _gcd_import(name, package, level)
File <frozen importlib._bootstrap>:1027, in _find_and_load(name, import_)
File <frozen importlib._bootstrap>:1004, in _find_and_load_unlocked(name, import_)
ModuleNotFoundError: No module named 'intake_xarray'
[29]:
plot_enso_obs(obs)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[29], line 1
----> 1 plot_enso_obs(obs)
NameError: name 'obs' is not defined