Skip to content
This repository was archived by the owner on Feb 1, 2024. It is now read-only.

Commit 1876952

Browse files
author
Mark Miesch
authored
Merge pull request #12 from JCSDA-internal/release/1.1.0
Release/1.1.0
2 parents 2637df1 + d375472 commit 1876952

File tree

10 files changed

+479
-208
lines changed

10 files changed

+479
-208
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
application:
2+
3+
# Application to use
4+
application name: da_block_convergence
5+
6+
# JEDI EDA log file to read
7+
log file: /gpfsm/dnb31/drholdaw/JediWF/fv3-jedi-tools-testing/<block log file>
8+
9+
# Number of members in the EDA
10+
members: 4
11+
12+
# Yscale for figures (log or linear)
13+
yscale: linear
14+
15+
# Output format for plots (png or pdf)
16+
plot format: pdf

src/Workflows/Generic/Diagnostics/field_plot.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ application:
77
fields file: /gpfsm/dnb31/drholdaw/JediWF/fv3-jedi-tools-testing/inc.3denvar.latlon.%Y%m%d_%H%M%Sz.nc4
88

99
# Name of the field as it appears in the file
10-
field name: t
10+
field names:
11+
- t
12+
13+
# Path where figure should be saved
14+
output path: ./Plots/
1115

1216
# Model layer to plot when the field is rank 3
1317
model layer: 50

src/fv3jeditools/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
33

4+
from .diag_da_block_convergence import *
45
from .diag_da_convergence import *
56
from .diag_field_plot import *
67
from .diag_hofx_innovations import *
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# (C) Copyright 2021 UCAR
2+
#
3+
# This software is licensed under the terms of the Apache Licence Version 2.0
4+
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5+
6+
import matplotlib.pyplot as plt
7+
import numpy as np
8+
import os
9+
import re
10+
11+
import fv3jeditools.utils as utils
12+
13+
# --------------------------------------------------------------------------------------------------
14+
## @package da_block_convergence
15+
#
16+
# This application can be triggered by using "application name: da_block_convergence"
17+
#
18+
# Configuration options:
19+
# ----------------------
20+
# log file | The log file to parse the statistics from
21+
# yscale | Whether to use log or linear scale for the yaxis
22+
# plot format | The extension used for the file name, png or pdf
23+
#
24+
#
25+
# This function takes a yaml file configuration as well as a datetime. It will plot the convergence
26+
# statistics from the log of a variational data assimilation run, provided through the yaml.
27+
# It will search for the Minimizer norm gradient, J, Jb, JoJc and GMRESR
28+
#
29+
#
30+
# --------------------------------------------------------------------------------------------------
31+
32+
def da_block_convergence(datetime, conf):
33+
34+
# Log file to parse
35+
try:
36+
log_file = conf['log file']
37+
except:
38+
utils.abort('\'log file\' must be present in the configuration')
39+
40+
# Get the number of members
41+
try:
42+
members = conf['members']
43+
except:
44+
utils.abort('\'members\' must be present in the configuration')
45+
46+
# Get output path for plots
47+
try:
48+
output_path = conf['output path']
49+
except:
50+
output_path = './'
51+
52+
# Create output path
53+
if not os.path.exists(output_path):
54+
os.makedirs(output_path)
55+
56+
# Replace datetime in logfile name
57+
isodatestr = datetime.strftime("%Y-%m-%dT%H:%M:%S")
58+
log_file = utils.stringReplaceDatetimeTemplate(isodatestr, log_file)
59+
60+
61+
# Read file and gather norm information
62+
print(" Reading convergence from ", log_file)
63+
64+
# Open the file ready for reading
65+
if os.path.exists(log_file):
66+
file = open(log_file, "r")
67+
else:
68+
utils.abort('Log file not found.')
69+
70+
71+
# Search for the type of minimizer used for the assimilation
72+
for line in file:
73+
if "Minimizer algorithm=" in line:
74+
minimizer = line.split('=')[1].rstrip()
75+
break
76+
77+
78+
# Patterns to search for from the file
79+
search_patterns = []
80+
search_patterns.append(" Norm reduction all members .")
81+
search_patterns.append(" Quadratic cost function all members: J .")
82+
83+
# Labels for the figures
84+
ylabels = []
85+
ylabels.append(minimizer+" normalized gradient reduction")
86+
ylabels.append("Quadratic cost function J ")
87+
88+
# Get all lines that match the search patterns
89+
matches = []
90+
for line in file:
91+
for search_pattern in search_patterns:
92+
reg = re.compile(search_pattern)
93+
if bool(re.match(reg, line.rstrip())):
94+
matches.append(line.rstrip())
95+
96+
# Close the file
97+
file.close()
98+
99+
# Loop over stats to be searched on
100+
maxiterations = 10000
101+
count = np.zeros(len(search_patterns), dtype=int)
102+
stats = np.zeros((members, len(search_patterns), maxiterations))
103+
for search_pattern in search_patterns:
104+
105+
index = [i for i, s in enumerate(search_patterns) if search_pattern in s]
106+
107+
# Loop over the matches and fill stats
108+
for match in matches:
109+
reg = re.compile(search_pattern)
110+
if bool(re.match(reg, match)):
111+
x = match.split()[-members:]
112+
x2 = [sub.replace(',' , '') for sub in x]
113+
for member in range(members):
114+
stats[member,index,count[index]]=x2[member]
115+
count[index] = count[index] + 1
116+
117+
118+
niter = count[0]
119+
stat = np.zeros((members, niter))
120+
121+
122+
# Create figures
123+
# --------------
124+
125+
# Scale for y-axis
126+
try:
127+
yscale = conf['yscale']
128+
except:
129+
yscale = 'linear'
130+
131+
# Format for plots
132+
try:
133+
plotformat = conf['plot format']
134+
except:
135+
plotformat = 'png'
136+
137+
for ylabel in ylabels:
138+
139+
index = [i for i, s in enumerate(ylabels) if ylabel in s]
140+
savename = ylabel.lower().strip()
141+
savename = savename.replace(" ", "-")
142+
savename = savename+"_"+datetime.strftime("%Y%m%d_%H%M%S")+"."+plotformat
143+
savename = os.path.join(output_path,savename)
144+
fig, ax = plt.subplots(figsize=(15, 7.5))
145+
for member in range(members):
146+
stat[member,0:niter] = stats[member,index,0:niter]
147+
stat_plot = stat[member,np.nonzero(stat[member,:])]
148+
iter = np.arange(1, len(stat_plot[0])+1)
149+
ax.plot(iter, stat_plot[0], linestyle='-', marker='x',label = 'member %s'%member)
150+
ax.tick_params(labelbottom=True, labeltop=False, labelleft=True, labelright=True)
151+
plt.title("JEDI variational assimilation convergence statistics | "+isodatestr)
152+
plt.legend()
153+
plt.xlabel("Iteration number")
154+
plt.ylabel(ylabel)
155+
plt.yscale(yscale)
156+
157+
print(" Saving figure as", savename, "\n")
158+
plt.savefig(savename)
159+
160+
# --------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)