Source code for pycif.plugins.obsoperators.standard.transforms.utils.check_adjtltest
import os
from logging import info
import numpy as np
import pandas as pd
[docs]
def check_adjtltest(self, period_order, mapper, transform_pipe):
df = None
# Check the adjoint for each transformations
for ddi, transform, direction in period_order:
if transform not in self.data_adj \
or transform not in self.data_tl \
or direction != "forward":
continue
data_tl = self.data_tl[transform]
data_adj = self.data_adj[transform]
dx_in = 0
dx_out = 0
if ddi not in data_tl:
continue
for trid in mapper[transform]["inputs"]:
# Skip if data not in adj or tl datastore
if ddi not in data_tl or ddi not in data_adj:
continue
if data_tl[ddi]["inputs"].get(trid, {}) == {} \
and data_adj[ddi]["inputs"].get(trid, {}) == {}:
continue
for di in mapper[transform]["subsimus"][ddi]["inputs"][trid]:
for precursor in mapper[transform]["precursors"][trid]:
# Get value from dump2input transform if force_dump
precursor_name = getattr(
transform_pipe, precursor).plugin.name
if precursor_name == "dump2inputs":
if precursor in self.data_tl \
and precursor in self.data_adj:
tl = self.data_tl[precursor][di][
"outputs"][trid][di][transform]
adj = self.data_adj[precursor][di][
"outputs"][trid][di][transform]
else:
continue
else:
tl = data_tl[ddi]["inputs"][trid][di][precursor]
adj = data_adj[ddi]["inputs"][trid][di][precursor]
# Loop over precursor sub-simulations
subsimus_in = mapper[precursor]["subsimus"]
for precursor_di in subsimus_in:
# Skip if subsimu not in precursor subsimulations
if di not in subsimus_in[precursor_di]['outputs'].get(trid, []):
continue
tl_precursor = tl[precursor_di]
adj_precursor = adj[precursor_di]
# Deal with sparse data
if isinstance(tl_precursor, pd.DataFrame) \
and isinstance(adj_precursor, pd.DataFrame):
tl_precursor = tl_precursor["maindata"]
adj_precursor = adj_precursor["maindata"]
if "incr" not in tl_precursor or "adj_out" not in adj_precursor:
continue
data_tl_in = tl_precursor["incr"]
data_adj_in = adj_precursor.get(
"delta_adj_out", adj_precursor["adj_out"])
dx_in += np.float64((data_tl_in * data_adj_in).sum())
for trid in mapper[transform]["outputs"]:
if ddi not in data_tl or ddi not in data_adj:
continue
if trid not in data_tl[ddi]["outputs"] \
or trid not in data_adj[ddi]["outputs"]:
continue
for di in mapper[transform]["subsimus"][ddi]["outputs"][trid]:
for successor in mapper[transform]["successors"][trid]:
# Get value from loadfromoutputs transform if force_loadin
successor_name = getattr(
transform_pipe, successor).plugin.name
if successor_name == "loadfromoutputs" \
and successor in self.data_tl \
and successor in self.data_adj:
if di not in self.data_tl[successor] \
or di not in self.data_adj[successor]:
continue
tl = self.data_tl[successor][di]["inputs"][trid][di][
transform]
adj = self.data_adj[successor][di]["inputs"][trid][di][
transform]
else:
tl = data_tl[ddi]["outputs"][trid][di][successor]
adj = data_adj[ddi]["outputs"][trid][di][successor]
# Loop over successor sub-simulations
subsimus_in = mapper[successor]["subsimus"]
for successor_di in subsimus_in:
# Skip if subsimu not in successor subsimulations
if di not in subsimus_in[successor_di]['inputs'].get(trid, []):
continue
tl_successor = tl[successor_di]
adj_successor = adj[successor_di]
# Deal with sparse data
if isinstance(tl_successor, pd.DataFrame) \
and isinstance(adj_successor, pd.DataFrame):
tl_successor = tl_successor["maindata"]
adj_successor = adj_successor["maindata"]
if "incr" not in tl_successor or "adj_out" not in adj_successor:
continue
data_tl_out = tl_successor["incr"]
data_adj_out = adj_successor["adj_out"]
dx_out += np.float64(
(data_tl_out * data_adj_out).sum())
# Duplicate input / output for toobsvect and fromcontrol
transf_name = getattr(transform_pipe, transform).plugin.name
if transf_name == "toobsvect":
dx_out = dx_in
elif transf_name == "fromcontrol":
dx_in = dx_out
if dx_in == dx_out == 0:
continue
diff = (
(dx_in / dx_out - 1) / np.finfo(np.float64).eps
if dx_out != 0 else np.nan
)
df_tr = pd.DataFrame(
data=[[transform, transf_name, ddi, dx_in, dx_out, diff]],
columns=["id", "name", "date", "dx_in", "dx_out", "diff"]
)
df = df_tr if df is None else pd.concat([df, df_tr], ignore_index=True)
df["date"] = df["date"].map(lambda x: x.isoformat(sep=" "))
df["dx_in"] = df["dx_in"].map(lambda x: f"{x:.15f}")
df["dx_out"] = df["dx_out"].map(lambda x: f"{x:.15f}")
df["diff"] = df["diff"].map(lambda x: f"{x:.1E}")
df.columns = ["transform_ID", "transform_name", "sub-simulation",
"<dx|H*(H(dx))>", "<H(dx)|H(dx)>", "difference"]
df_str = df.to_string(index=False)
# Write to logfile
info("check transforms results:\n" + df_str)
adjtl_log = os.path.join(self.workdir, "check_transforms.log")
with open(adjtl_log, "w") as f:
f.write(df_str)