From 29f6950ec05180eb3109be342d39a0e03fa6f2d3 Mon Sep 17 00:00:00 2001
From: sbiri <sbiri@noc.ac.uk>
Date: Tue, 30 Mar 2021 12:06:58 +0100
Subject: [PATCH] - fixed sea ice concentration mask - added qmeth, L options
 as input - added option to add noise to spd, T, sst, Td/rh

---
 toy_ASFC.py | 121 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 80 insertions(+), 41 deletions(-)

diff --git a/toy_ASFC.py b/toy_ASFC.py
index 996d7ac..0a56c67 100644
--- a/toy_ASFC.py
+++ b/toy_ASFC.py
@@ -1,10 +1,12 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 """
 example of running AirSeaFluxCode with
 1. R/V data (data_all.csv) or
 2. one day era5 hourly data (era5_r360x180.nc)
 compute fluxes
-output NetCDF4
-and statistics in stats.txt
+output NetCDF4 or csv
+and statistics in "outS".txt
 
 @author: sbiri
 """
@@ -23,7 +25,7 @@ def reject_outliers(data, m=2):
     return x
 
 
-def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth):
+def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth, qmIn, LIn, stdIn):
     """
     Example routine of how to run AirSeaFluxCode with the test data given
     and save output either as .csv or NetCDF
@@ -62,9 +64,13 @@ def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth):
         lon = np.asarray(inDt["Longitude"])
         lat = np.asarray(inDt["Latitude"])
         spd = np.asarray(inDt["Wind speed"])
+        spd = spd+np.random.normal(0, stdIn[0], spd.shape)
         t = np.asarray(inDt["Air temperature"])
+        t = t+np.random.normal(0, stdIn[1], t.shape)
         sst = np.asarray(inDt["SST"])
+        sst = sst+np.random.normal(0, stdIn[2], sst.shape)
         rh = np.asarray(inDt["RH"])
+        rh = rh+np.random.normal(0, stdIn[3], rh.shape)
         p = np.asarray(inDt["P"])
         sw = np.asarray(inDt["Rs"])
         hu = np.asarray(inDt["zu"])
@@ -74,7 +80,7 @@ def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth):
         #%% run AirSeaFluxCode
         res = AirSeaFluxCode(spd, t, sst, lat=lat, hum=['rh', rh], P=p,
                              hin=hin, Rs=sw, tol=tolIn, gust=gustIn,
-                             cskin=cskinIn, meth=meth, L="ecmwf", n=30)
+                             cskin=cskinIn, meth=meth, qmeth=qmIn, L=LIn, n=30)
         flg = res["flag"]
 
     elif (inF == 'era5_r360x180.nc'):
@@ -86,12 +92,15 @@ def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth):
         lsm = np.array(fid.variables["lsm"])
         icon = np.array(fid.variables["siconc"])
         lsm = np.where(lsm > 0, np.nan, 1) # reverse 0 on land 1 over ocean
-        icon = np.where(icon < 0, np.nan, 1)
+        icon = np.where(icon == 0, 1, np.nan) # keep only ice-free regions
         msk = lsm*icon
         T = np.array(fid.variables["t2m"])*msk
+        T = T+np.random.normal(0, stdIn[1], T.shape)
         Td = np.array(fid.variables["d2m"])*msk
+        Td = Td+np.random.normal(0, stdIn[3], T.shape)
         sst = np.array(fid.variables["sst"])
         sst = np.where(sst < -100, np.nan, sst)*msk
+        sst = sst+np.random.normal(0, stdIn[2], sst.shape)
         p = np.array(fid.variables["msl"])*msk/100 # to set hPa
         lw = np.array(fid.variables["strd"])*msk/60/60
         sw = np.array(fid.variables["ssrd"])*msk/60/60
@@ -99,6 +108,7 @@ def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth):
         v = np.array(fid.variables["v10"])
         fid.close()
         spd = np.sqrt(np.power(u, 2)+np.power(v, 2))*msk
+        spd = spd+np.random.normal(0, stdIn[0], spd.shape)
         del u, v, fid
         hin = np.array([10, 2, 2])
         latIn = np.tile(lat, (len(lon), 1)).T.reshape(len(lon)*len(lat))
@@ -109,7 +119,7 @@ def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth):
         flg = np.empty((len(tim),len(lon)*len(lat)), dtype="object")
         # reshape input and run code
         for x in range(len(tim)):
-            temp = AirSeaFluxCode(spd.reshape(len(tim), len(lon)*len(lat))[x, :],
+            a = AirSeaFluxCode(spd.reshape(len(tim), len(lon)*len(lat))[x, :],
                                T.reshape(len(tim), len(lon)*len(lat))[x, :],
                                sst.reshape(len(tim), len(lon)*len(lat))[x, :],
                                lat=latIn,
@@ -119,11 +129,11 @@ def toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth):
                                Rs=sw.reshape(len(tim), len(lon)*len(lat))[x, :],
                                Rl=lw.reshape(len(tim), len(lon)*len(lat))[x, :],
                                gust=gustIn, cskin=cskinIn, tol=tolIn,
-                               qmeth='Buck2', meth=meth, n=30, L="ecmwf")
-            a = temp.loc[:,"tau":"rh"]
-            a = a.to_numpy()
-            flg[x, :] = temp["flag"]
-            res[x, :, :] = a
+                               meth=meth, qmeth=qmIn, n=30, L=LIn)
+            temp = a.loc[:,"tau":"rh"]
+            temp = temp.to_numpy()
+            flg[x, :] = a["flag"]
+            res[x, :, :] = temp
             del a, temp
             n = np.shape(res)
             res = np.asarray([res[:, :, i]*msk.reshape(n[0], n[1])
@@ -505,6 +515,17 @@ else:
     meth = meth #[meth]
 ext = meth+"_"
 #------------------------------------------------------------------------------
+qmIn = input("Give prefered method for specific humidity: \n")
+if (qmIn == ''):
+    qmIn = 'Buck2' # default
+while qmIn not in ["HylandWexler", "Hardy", "Preining", "Wexler",
+                   "GoffGratch", "WMO", "MagnusTetens", "Buck", "Buck2",
+                   "WMO2018", "Sonntag", "Bolton", "IAPWS", "MurphyKoop"]:
+    print("method unknown")
+    meth = input("Give prefered method: \n")
+else:
+    qmIn = qmIn
+#------------------------------------------------------------------------------
 gustIn = input("Give gustiness option (to use default press enter): \n")
 if (gustIn == ''):
     gustIn = None
@@ -520,8 +541,8 @@ cskinIn = input("Give cool skin option (to use default press enter): \n")
 if (cskinIn == ''):
     cskinIn = None
     if ((cskinIn == None) and (meth == "S80" or meth == "S88" or meth == "LP82"
-                             or meth == "YT96" or meth == "UA" or
-                             meth == "LY04")):
+                               or meth == "YT96" or meth == "UA"
+                               or meth == "LY04")):
         cskinIn = 0
         ext = ext+'noskin_'
     elif ((cskinIn == None) and (meth == "C30" or meth == "C35"
@@ -542,6 +563,21 @@ else:
     tolIn = eval(tolIn)
 ext = ext+'tol'+tolIn[0]
 #------------------------------------------------------------------------------
+LIn = input("Give prefered method for L (S80 or ecmwf): \n")
+if (LIn == ''):
+    LIn = 'ecmwf' # default
+elif LIn not in ["S80", "ecmwf"]:
+    LIn = 'ecmwf' # default
+else:
+    LIn = LIn
+#------------------------------------------------------------------------------
+stdIn = input("Give noise std for spd, T, SST and Td/rh \n (e.g. [0.01, 0, 0, 0]"
+              " adds noise only to spd): \n")
+if (stdIn == ''):
+    stdIn = [0, 0, 0, 0] # no noise added
+else:
+    stdIn = eval(stdIn)
+#------------------------------------------------------------------------------
 outF = input("Give path and output file name: \n")
 if ((outF == '') and (inF == "data_all.csv")):
     outF = "out_"+inF[:-4]+"_"+ext+".csv"
@@ -568,37 +604,38 @@ elif (outS[-4:] != '.txt'):
 #------------------------------------------------------------------------------
 print("\n run_ASFC.py, started for method "+meth)
 
-res, lon, lat = toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth)
+res, lon, lat = toy_ASFC(inF, outF, outS, gustIn, cskinIn, tolIn, meth, qmIn,
+                         LIn, stdIn)
 print("run_ASFC.py took ", np.round((time.perf_counter()-start_time)/60, 2),
       "minutes to run")
 
 #%% generate flux plots
-if (inF == 'era5_r360x180.nc'):
-    cm = plt.cm.get_cmap('RdYlBu')
-    ttl = ["tau (Nm$^{-2}$)", "shf (Wm$^{-2}$)", "lhf (Wm$^{-2}$)"]
-    for i in range(3):
-        plt.figure()
-        plt.contourf(lon, lat,
-                     np.nanmean(res[:, :, i], axis=0).reshape(len(lat),
-                                                              len(lon)),
-                     100, cmap=cm)
-        plt.colorbar()
-        plt.tight_layout()
-        plt.xlabel("Longitude")
-        plt.ylabel("Latitude")
-        plt.title(meth+', '+ttl[i])
-        plt.savefig('./'+ttl[i][:3]+'_'+ext+'.png', dpi=300, bbox_inches='tight')
-elif (inF == "data_all.csv"):
-    ttl = ["tau (Nm$^{-2}$)", "shf (Wm$^{-2}$)", "lhf (Wm$^{-2}$)"]
-    for i in range(3):
-        plt.figure()
-        plt.plot(res[ttl[i][:3]],'.c', markersize=1)
-        plt.title(meth)
-        plt.xlabel("points")
-        plt.ylabel(ttl[i])
-        plt.savefig('./'+ttl[i][:3]+'_'+ext+'.png', dpi=300, bbox_inches='tight')
+# if (inF == 'era5_r360x180.nc'):
+#     cm = plt.cm.get_cmap('RdYlBu')
+#     ttl = ["tau (Nm$^{-2}$)", "shf (Wm$^{-2}$)", "lhf (Wm$^{-2}$)"]
+#     for i in range(3):
+#         plt.figure()
+#         plt.contourf(lon, lat,
+#                      np.nanmean(res[:, :, i], axis=0).reshape(len(lat),
+#                                                               len(lon)),
+#                      100, cmap=cm)
+#         plt.colorbar()
+#         plt.tight_layout()
+#         plt.xlabel("Longitude")
+#         plt.ylabel("Latitude")
+#         plt.title(meth+', '+ttl[i])
+#         plt.savefig('./'+ttl[i][:3]+'_'+ext+'.png', dpi=300, bbox_inches='tight')
+# elif (inF == "data_all.csv"):
+#     ttl = ["tau (Nm$^{-2}$)", "shf (Wm$^{-2}$)", "lhf (Wm$^{-2}$)"]
+#     for i in range(3):
+#         plt.figure()
+#         plt.plot(res[ttl[i][:3]],'.c', markersize=1)
+#         plt.title(meth)
+#         plt.xlabel("points")
+#         plt.ylabel(ttl[i])
+#         plt.savefig('./'+ttl[i][:3]+'_'+ext+'.png', dpi=300, bbox_inches='tight')
 
-#%% generate txt file with statistic
+#%% generate txt file with statistics
 if ((cskinIn == None) and (meth == "S80" or meth == "S88" or meth == "LP82"
                            or meth == "YT96" or meth == "UA" or
                            meth == "LY04")):
@@ -615,12 +652,14 @@ elif np.all(gustIn == None):
 elif ((np.size(gustIn) < 3) and (gustIn == 0)):
     gust = [0, 0, 0]
 if (tolIn == None):
-    tolIn = ['flux', 0.01, 1, 1]
+    tolIn = ['all', 0.01, 0.01, 1e-05, 1e-3, 0.1, 0.1]
 
 
 print("Input summary", file=open('./'+outS, 'a'))
 print('input file name: {}, \n method: {}, \n gustiness: {}, \n cskin: {},'
-      ' \n tolerance: {}'.format(inF, meth, gustIn, cskinIn, tolIn),
+      ' \n tolerance: {}, \n qmethod: {}, \n L: {}'.format(inF, meth, gustIn,
+                                                           cskinIn, tolIn,
+                                                           qmIn, LIn),
       file=open('./'+outS, 'a'))
 ttl = np.asarray(["tau  ", "shf  ", "lhf  ", "L    ", "cd   ", "cdn  ",
                   "ct   ", "ctn  ", "cq   ", "cqn  ", "tsrv ", "tsr  ",
-- 
GitLab