Skip to content

Commit 8029c1e

Browse files
authored
Merge pull request #1112 from PCMDI/zhan391
Code changes to implement PSA1 and PSA2 mode varibility analysis
2 parents 431dd6b + 74504b1 commit 8029c1e

File tree

8 files changed

+55
-21
lines changed

8 files changed

+55
-21
lines changed

doc/jupyter/Demo/basic_mov_param.py.in

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ varModel = 'psl'
2323
ModUnitsAdjust = (True, 'divide', 100.0) # Pa to hPa
2424
msyear = 1900
2525
meyear = 2005
26-
eofn_mod = 1
2726

2827
# OBSERVATIONS SETTINGS
2928
reference_data_path = '$INPUT_DIR$/obs4MIPs_PCMDI_monthly/NOAA-ESRL-PSD/20CR/mon/psl/gn/v20210727/psl_mon_20CR_PCMDI_gn_187101-201212.nc'
@@ -32,7 +31,6 @@ varOBS = 'psl'
3231
ObsUnitsAdjust = (True, 'divide', 100.0) # Pa to hPa; or (False, 0, 0)
3332
osyear = 1900
3433
oeyear = 2005
35-
eofn_obs = 1
3634

3735
# DIRECTORY WHERE TO PUT RESULTS
3836
results_dir = os.path.join(

doc/jupyter/Demo/basic_mov_param_sst.py.in

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ varModel = 'ts'
2525
ModUnitsAdjust = (True, "subtract", 273.15) # degK to degC
2626
msyear = 1900
2727
meyear = 2005
28-
eofn_mod = 1
2928

3029
# OBSERVATIONS SETTINGS
3130
reference_data_path = '$INPUT_DIR$/obs4MIPs_PCMDI_monthly/MOHC/HadISST-1-1/mon/ts/gn/v20210727/ts_mon_HadISST-1-1_PCMDI_gn_187001-201907.nc'
@@ -34,7 +33,6 @@ varOBS = 'ts'
3433
ObsUnitsAdjust = (True, "subtract", 273.15) # degK to degC
3534
osyear = 1900
3635
oeyear = 2005
37-
eofn_obs = 1
3836

3937
# DIRECTORY WHERE TO PUT RESULTS
4038
results_dir = os.path.join(

pcmdi_metrics/io/regions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ def load_regions_specs() -> dict:
3939
"NAM": {"domain": {"latitude": (20.0, 90), "longitude": (-180, 180)}},
4040
"NAO": {"domain": {"latitude": (20.0, 80), "longitude": (-90, 40)}},
4141
"SAM": {"domain": {"latitude": (-20.0, -90), "longitude": (0, 360)}},
42+
"PSA1": {"domain": {"latitude": (-20.0, -90), "longitude": (0, 360)}},
43+
"PSA2": {"domain": {"latitude": (-20.0, -90), "longitude": (0, 360)}},
4244
"PNA": {"domain": {"latitude": (20.0, 85), "longitude": (120, 240)}},
4345
"NPO": {"domain": {"latitude": (20.0, 85), "longitude": (120, 240)}},
4446
"PDO": {"domain": {"latitude": (20.0, 70), "longitude": (110, 260)}},

pcmdi_metrics/variability_mode/lib/argparse_functions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ def AddParserArgument(P):
3333
"- NAM: Northern Annular Mode\n"
3434
"- NAO: Northern Atlantic Oscillation\n"
3535
"- SAM: Southern Annular Mode\n"
36+
"- PSA1: Pacific–South American pattern 1\n"
37+
"- PSA2: Pacific–South American pattern 2\n"
3638
"- PNA: Pacific North American Pattern\n"
3739
"- PDO: Pacific Decadal Oscillation\n"
3840
"- NPO: North Pacific Oscillation\n"
@@ -224,6 +226,8 @@ def VariabilityModeCheck(mode, P):
224226
"NAM",
225227
"NAO",
226228
"SAM",
229+
"PSA1",
230+
"PSA2",
227231
"PNA",
228232
"PDO",
229233
"NPO",

pcmdi_metrics/variability_mode/lib/eof_analysis.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,22 @@ def arbitrary_checking(mode, eof_Nth):
155155
elif mode == "SAM":
156156
if eof_Nth.sel({lat_key: slice(-60, -90)}).mean().item() >= 0:
157157
reverse_sign = True
158+
elif mode == "PSA1":
159+
if (
160+
eof_Nth.sel({lat_key: slice(-59.5, -64.5), lon_key: slice(207.5, 212.5)})
161+
.mean()
162+
.item()
163+
>= 0
164+
):
165+
reverse_sign = True
166+
elif mode == "PSA2":
167+
if (
168+
eof_Nth.sel({lat_key: slice(-57.5, -62.5), lon_key: slice(277.5, 282.5)})
169+
.mean()
170+
.item()
171+
>= 0
172+
):
173+
reverse_sign = True
158174
else: # Minimum sign control part was left behind for any future usage..
159175
if not np.isnan(eof_Nth[-1, -1].item()):
160176
if eof_Nth[-1, -1].item() >= 0:

pcmdi_metrics/variability_mode/lib/lib_variability_mode.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import pcmdi_metrics
1515
from pcmdi_metrics.io import get_time, select_subset, xcdat_open
16-
from pcmdi_metrics.utils import apply_landmask
16+
from pcmdi_metrics.utils import apply_landmask, check_monthly_time_axis
1717

1818

1919
def tree():
@@ -67,6 +67,9 @@ def read_data_in(
6767
# Open data file
6868
ds = xcdat_open(path)
6969

70+
# Data QC check -- time axis check
71+
check_monthly_time_axis(ds)
72+
7073
# Time subset
7174
ds_time_subsetted = subset_time(ds, syear, eyear, debug=debug)
7275
data_timeseries = ds_time_subsetted[var_in_data]

pcmdi_metrics/variability_mode/lib/plot_map.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def plot_map(
5757
projection = "Lambert"
5858
elif mode in ["NAM"]:
5959
projection = "Stereo_north"
60-
elif mode in ["SAM"]:
60+
elif mode in ["SAM", "PSA1", "PSA2"]:
6161
projection = "Stereo_south"
6262
else:
6363
sys.exit("Projection for " + mode + "is not defined.")

pcmdi_metrics/variability_mode/variability_modes_driver.py

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
## EOF2 based variability modes
1616
- NPO: North Pacific Oscillation (2nd EOFs of PNA domain)
1717
- NPGO: North Pacific Gyre Oscillation (2nd EOFs of PDO domain)
18+
- PSA2: Pacific South America Mode (2nd EOFs of SAM domain)
19+
20+
## EOF3 based variability modes
21+
- PSA3: Pacific South America Mode (3rd EOFs of SAM domain)
1822
1923
## Reference:
2024
Lee, J., K. Sperber, P. Gleckler, C. Bonfils, and K. Taylor, 2019:
@@ -175,25 +179,34 @@
175179
eofn_obs = param.eofn_obs
176180
eofn_mod = param.eofn_mod
177181

182+
if mode in ["NAM", "NAO", "SAM", "PNA", "PDO", "AMO"]:
183+
eofn_expected = 1
184+
elif mode in ["NPGO", "NPO", "PSA1"]:
185+
eofn_expected = 2
186+
elif mode in ["PSA2"]:
187+
eofn_expected = 3
188+
else:
189+
raise ValueError(
190+
f"Mode '{mode}' is not defiend with associated expected EOF number"
191+
)
192+
178193
if eofn_obs is None:
179-
if mode in ["NAM", "NAO", "SAM", "PNA", "PDO", "AMO"]:
180-
eofn_obs = 1
181-
elif mode in ["NPGO", "NPO"]:
182-
eofn_obs = 2
183-
else:
184-
raise ValueError(f"{eofn_obs} is not given for {mode}")
194+
eofn_obs = eofn_expected
185195
else:
186196
eofn_obs = int(eofn_obs)
197+
if eofn_obs != eofn_expected:
198+
raise ValueError(
199+
f"Observation EOF number ({eofn_obs}) does not match expected EOF number ({eofn_expected}) for mode {mode}"
200+
)
187201

188202
if eofn_mod is None:
189-
if mode in ["NAM", "NAO", "SAM", "PNA", "PDO", "AMO"]:
190-
eofn_mod = 1
191-
elif mode in ["NPGO", "NPO"]:
192-
eofn_mod = 2
193-
else:
194-
raise ValueError(f"{eofn_mod} is not given for {mode}")
203+
eofn_mod = eofn_expected
195204
else:
196205
eofn_mod = int(eofn_mod)
206+
if eofn_mod != eofn_expected:
207+
raise ValueError(
208+
f"Model EOF number ({eofn_mod}) does not match expected EOF number ({eofn_expected}) for mode {mode}"
209+
)
197210

198211
print("eofn_obs:", eofn_obs)
199212
print("eofn_mod:", eofn_mod)
@@ -830,7 +843,7 @@
830843
# Conventional EOF approach as supplementary
831844
# - - - - - - - - - - - - - - - - - - - - - - - - -
832845
if ConvEOF:
833-
eofn_mod_max = 3
846+
eofn_mod_max = max(3, eofn_mod)
834847

835848
# EOF analysis
836849
debug_print("conventional EOF analysis start", debug)
@@ -976,15 +989,15 @@
976989
debug=debug,
977990
)
978991
plot_map(
979-
mode + "_teleconnection",
992+
f"{mode}_teleconnection",
980993
f"{mip.upper()} {model} ({run}) - EOF{n + 1}",
981994
msyear,
982995
meyear,
983996
season,
984997
# eof_lr(longitude=(lon1_global, lon2_global)),
985998
eof_lr,
986999
frac,
987-
output_img_file + "_teleconnection",
1000+
f"{output_img_file}_teleconnection",
9881001
debug=debug,
9891002
)
9901003

0 commit comments

Comments
 (0)