x44a = np.array([x44, y44]) x44b = x44a[:, ~np.isnan(x44a).any(axis=0)] x4 = x44b[0] y4 = x44b[1] x55 = gc_data_HNO3_djf y55 = sites_HNO3_djf x55a = np.array([x55, y55]) x55b = x55a[:, ~np.isnan(x55a).any(axis=0)] x5 = x55b[0] y5 = x55b[1] #Regression ~ using bootstrap #ind=np.where((gc_data_HNO3_annual!=0)&(sites_HNO3_AM!=0)) #print (ind) regres_annual = rma(x1, y1, (len(x1)), 1000) print('slope annual: ', regres_annual[0]) print('Intercept annual: ', regres_annual[1]) print('slope error annual: ', regres_annual[2]) print('Intercept error annual: ', regres_annual[3]) regres_mam = rma(x2, y2, (len(x2)), 1000) print('slope mam: ', regres_mam[0]) print('Intercept mam: ', regres_mam[1]) print('slope error mam: ', regres_mam[2]) print('Intercept error mam: ', regres_mam[3]) regres_jja = rma(x3, y3, (len(x3)), 1000) print('slope jja: ', regres_jja[0]) print('Intercept jja: ', regres_jja[1]) print('slope error jja: ', regres_jja[2])
x1 = x11b[0] y1 = x11b[1] print(x1, 'x1') print(y1, 'y1') x1y1 = np.vstack([x1, y1]) z1 = gaussian_kde(x1y1)(x1y1) slope1, intercept1, r_value1, p_value1, std_err1 = stats.linregress(x1, y1) line1 = slope1 * x1 + intercept1 correlate_annual = stats.pearsonr(x1, y1) #Regression ~ using bootstrap #ind=np.where((gc_data_ammonia_annual!=0)&(sites_ammonia_AM!=0)) #print (ind) regres_annual = rma(x1, y1, (len(x1)), 1000) print('slope annual: ', regres_annual[0]) print('Intercept annual: ', regres_annual[1]) print('slope error annual: ', regres_annual[2]) print('Intercept error annual: ', regres_annual[3]) #plotting scatter plot title_list1 = 'NAEI and IASI NH$_3$ Emission Annual' fig1 = plt.figure(facecolor='White', figsize=[11, 11]) pad = 1.1 ax = plt.subplot(111) plt.title(title_list1, fontsize=20, y=1) plt.plot(x1, y1, 'o', color='black', markersize=3) xvals = np.arange(-1e3, 1e5, 5)
def cldslice(pcolno2,cldtophgt): """ Compute upper troposphere NO2 using partial columns above cloudy scenes. Determine NO2 mixing ratio by regressing NO2 partial columns against cloud-top heights over cloudy scenes. INPUT: vectors of partial columns in molec/m2 and corresponding cloud top heights in hPa. OUTPUT: NO2 volumetric mixing ratio, corresponding estimated error on the cloud-sliced NO2 value, a number to identify which filtering criteria led to loss of data in the case that the cloud-sliced NO2 value ia nan, and the mean cloud pressure of data retained after 10th and 90th percentile filtering. """ # Initialize: utmrno2=0.0 utmrno2err=0.0 error_state=0 # Define factor to convert slope of NO2 partial column vs pressure # to VMR: den2mr=np.divide((np.multiply(g,mmair)),na) # Get 10th and 90th percentiles of data population: p10=np.percentile(pcolno2,10) p90=np.percentile(pcolno2,90) # Remove outliers determined as falling outside the 10th and 90th # percentile range. Not include this or instead using 5th and 95th leads # to overestimate in cloud-sliced UT NO2 compared to the "truth": sind=np.where((pcolno2>p10)&(pcolno2<p90))[0] # Trim the data to remove ouliers: pcolno2=pcolno2[sind] cldtophgt=cldtophgt[sind] # Cloud pressure mean: mean_cld_pres=np.mean(cldtophgt) # Get number of points in vector: npoints=len(cldtophgt) # Only consider data with more than 5 points for reasonably # robust statistics. This step is added to account for data loss # removing outliers: if npoints<=10: error_state=1 utmrno2=np.nan utmrno2err=np.nan return (utmrno2, utmrno2err, error_state, mean_cld_pres) # Get cloud top height standard deviation: stdcld=np.std(cldtophgt) # Get cloud top height range: diffcld=np.nanmax(cldtophgt)-np.nanmin(cldtophgt) # Only consider scenes with a dynamic range of clouds: # (i) Cloud range: if diffcld<=140: error_state=2 utmrno2=np.nan utmrno2err=np.nan return (utmrno2, utmrno2err, error_state, mean_cld_pres) # (ii) Cloud standard deviation: if stdcld<=30: error_state=3 utmrno2=np.nan utmrno2err=np.nan return (utmrno2, utmrno2err, error_state, mean_cld_pres) # Get regression statistics: # Partial NO2 column (molec/m2) vs cloud top height (hPa): # 300 iterations of regression chosen to compromise between # statistics and computational efficiency: result=rma(cldtophgt*1e2,pcolno2,len(pcolno2),300) # Remove data with relative error > 100%: if np.absolute(np.divide(result[2], result[0]))>1.0: error_state=4 utmrno2=np.nan utmrno2err=np.nan return (utmrno2, utmrno2err, error_state, mean_cld_pres) # Account for negative values: # Set points with sum of slope and error less than zero to nan. # This is to account for noise in the data that hover near zero. if result[0]<0 and (not np.isnan(utmrno2)): if (np.add(result[0],result[2])<0): error_state=5 utmrno2=np.nan utmrno2err=np.nan return (utmrno2, utmrno2err, error_state, mean_cld_pres) # Proceed with estimating NO2 mixing ratios for retained data: #if not np.isnan(utmrno2): slope=result[0] #slope=np.multiply(slope,sf) slope_err=result[2] #slope_err=np.multiply(slope_err,sf) # Convert slope to mol/mol: utmrno2=np.multiply(slope,den2mr) # Convert error to mol/mol: utmrno2err=np.multiply(slope_err,den2mr) # Convert UT NO2 from mol/mol to ppt: utmrno2=np.multiply(utmrno2,1e+12) # Convert UT NO2 error from mol/mol to ppt utmrno2err=np.multiply(utmrno2err,1e+12) # Finally, remove outliers in the cloud-sliced NO2 # 200 pptv threshold is chosen, as far from likely range. # Scale factor applied to TROPOMI UT NO2 to account for # positive bias in free tropospheric NO2: if utmrno2>200: error_state=6 utmrno2=np.nan utmrno2err=np.nan return (utmrno2, utmrno2err, error_state, mean_cld_pres) else: return (utmrno2, utmrno2err, error_state, mean_cld_pres)
plt.subplot(2, 3, 3) cs = m.pcolor(xi, yi, np.squeeze(gcutno2), vmin=0, vmax=80, cmap='jet') m.drawparallels(np.arange(-80., 81., 45.), labels=[1, 0, 0, 0], fontsize=8) m.drawmeridians(np.arange(-180., 181., 45.), labels=[0, 0, 0, 1], fontsize=8) m.drawcoastlines() m.drawcountries() cbar = m.colorbar(cs, location='bottom', pad="10%") plt.title('True NO2 VMRs under all-sky conditions') plt.subplot(2, 3, 4) plt.plot(trueno2, gno2vmr, 'o', color='black', markersize=6) r=stats.pearsonr(trueno2[~np.isnan(gno2vmr)],\ gno2vmr[~np.isnan(gno2vmr)]) #print('Correlation = ', r[0]) result=rma(trueno2[~np.isnan(gno2vmr)],gno2vmr[~np.isnan(gno2vmr)],\ len(trueno2[~np.isnan(gno2vmr)]),1000) print(result, flush=True) xvals = np.arange(0, 100, 5) yvals = result[1] + xvals * result[0] plt.plot(xvals, yvals, '-') plt.xlim(-4, 80) plt.ylim(-4, 80) plt.xlabel('True NO2 (cloudy)') plt.ylabel('Cloud-sliced NO2') print('===== True (cloudy) vs cloud-sliced UT NO2 ====') print('R = ', r[0], flush=True) print('Slope = ', result[0]) print('Slope Err = ', result[2], flush=True) print('Intercept = ', result[1], flush=True) print('Intercept Err = ', result[3], flush=True) add2plt=("y = {a:6.2f}x + {b:6.3f}".\
def plot_data(self): # Plot the data: m = Basemap(resolution='l', projection='merc', lat_0=0, lon_0=0, llcrnrlon=self.minlon, llcrnrlat=self.minlat, urcrnrlon=self.maxlon, urcrnrlat=self.maxlat) xi, yi = m(self.X, self.Y) plt.subplot(2, 3, 1) cs = m.pcolor(xi, yi, np.squeeze(self.g_no2_vmr), vmin=0, vmax=80, cmap='jet') m.drawparallels(np.arange(-80., 81., 45.), labels=[1, 0, 0, 0], fontsize=8) m.drawmeridians(np.arange(-180., 181., 45.), labels=[0, 0, 0, 1], fontsize=8) m.drawcoastlines() m.drawcountries() cbar = m.colorbar(cs, location='bottom', pad="10%") plt.title('Cloud-sliced NO2 VMRs') plt.subplot(2, 3, 2) cs = m.pcolor(xi, yi, np.squeeze(self.true_no2), vmin=0.0, vmax=80, cmap='jet') m.drawparallels(np.arange(-80., 81., 45.), labels=[1, 0, 0, 0], fontsize=8) m.drawmeridians(np.arange(-180., 181., 45.), labels=[0, 0, 0, 1], fontsize=8) m.drawcoastlines() m.drawcountries() cbar = m.colorbar(cs, location='bottom', pad="10%") plt.title('True cloudy NO2') plt.subplot(2, 3, 3) cs = m.pcolor(xi, yi, np.squeeze(self.g_askut_no2), vmin=0, vmax=80, cmap='jet') m.drawparallels(np.arange(-80., 81., 45.), labels=[1, 0, 0, 0], fontsize=8) m.drawmeridians(np.arange(-180., 181., 45.), labels=[0, 0, 0, 1], fontsize=8) m.drawcoastlines() m.drawcountries() cbar = m.colorbar(cs, location='bottom', pad="10%") plt.title('True NO2 VMRs under all-sky conditions') plt.subplot(2, 3, 4) plt.plot(self.true_no2, self.g_no2_vmr, 'o', color='black', markersize=6) r = stats.pearsonr(self.true_no2[~np.isnan(self.g_no2_vmr)], self.g_no2_vmr[~np.isnan(self.g_no2_vmr)]) # print('Correlation = ', r[0]) result = rma(self.true_no2[~np.isnan(self.g_no2_vmr)], self.g_no2_vmr[~np.isnan(self.g_no2_vmr)], len(self.true_no2[~np.isnan(self.g_no2_vmr)]), 1000) print(result, flush=True) xvals = np.arange(0, 100, 5) yvals = result[1] + xvals * result[0] plt.plot(xvals, yvals, '-') plt.xlim(-4, 80) plt.ylim(-4, 80) plt.xlabel('True NO2 (cloudy)') plt.ylabel('Cloud-sliced NO2') print('===== True (cloudy) vs cloud-sliced UT NO2 ====') print('R = ', r[0], flush=True) print('Slope = ', result[0]) print('Slope Err = ', result[2], flush=True) print('Intercept = ', result[1], flush=True) print('Intercept Err = ', result[3], flush=True) add2plt = ("y = {a:6.2f}x + {b:6.3f}".format(a=result[0], b=result[1])) plt.text(2, 75, add2plt, fontsize=8, ha='left', va='center') # , transform=ax.transAxes) add2plt = ("R = {a:6.2f}".format(a=r[0])) plt.text(2, 65, add2plt, fontsize=8, ha='left', va='center') # , transform=ax.transAxes) plt.subplot(2, 3, 5) plt.plot(self.g_askut_no2, self.g_no2_vmr, 'o', color='black', markersize=6) r = stats.pearsonr(self.g_askut_no2[(~np.isnan(self.g_no2_vmr)) & (~np.isnan(self.g_askut_no2))], self.g_no2_vmr[(~np.isnan(self.g_no2_vmr)) & (~np.isnan(self.g_askut_no2))]) result = rma(self.g_askut_no2[(~np.isnan(self.g_no2_vmr)) & (~np.isnan(self.g_askut_no2))], self.g_no2_vmr[(~np.isnan(self.g_no2_vmr)) & (~np.isnan(self.g_askut_no2))], len(self.g_askut_no2[(~np.isnan(self.g_no2_vmr)) & (~np.isnan(self.g_askut_no2))]), 1000) xvals = np.arange(0, 100, 5) yvals = result[1] + xvals * result[0] plt.plot(xvals, yvals, '-') plt.xlim(-4, 80) plt.ylim(-4, 80) plt.xlabel('True NO2 (all-sky)') plt.ylabel('Cloud-sliced NO2') add2plt = ("y = {a:6.2f}x + {b:6.3f}". \ format(a=result[0], b=result[1])) plt.text(2, 75, add2plt, fontsize=8, \ ha='left', va='center') # , transform=ax.transAxes) add2plt = ("R = {a:6.2f}".format(a=r[0])) plt.text(2, 65, add2plt, fontsize=8, \ ha='left', va='center') # , transform=ax.transAxes) plt.subplot(2, 3, 6) plt.plot(self.g_askut_no2, self.true_no2, 'o', color='black', markersize=6) r = stats.pearsonr(self.g_askut_no2[(~np.isnan(self.true_no2)) & (~np.isnan(self.g_askut_no2))], self.true_no2[(~np.isnan(self.true_no2)) & (~np.isnan(self.g_askut_no2))]) result = rma(self.g_askut_no2[(~np.isnan(self.true_no2)) & (~np.isnan(self.g_askut_no2))], self.true_no2[(~np.isnan(self.true_no2)) & (~np.isnan(self.g_askut_no2))], len(self.g_askut_no2[(~np.isnan(self.true_no2)) & (~np.isnan(self.g_askut_no2))]), 1000) xvals = np.arange(0, 100, 5) yvals = result[1] + xvals * result[0] plt.plot(xvals, yvals, '-') plt.xlim(-4, 80) plt.ylim(-4, 80) plt.xlabel('True NO2 (all-sky)') plt.ylabel('True NO2 (cloudy)') add2plt = ("y = {a:6.2f}x + {b:6.3f}".format(a=result[0], b=result[1])) plt.text(2, 75, add2plt, fontsize=8, ha='left', va='center') add2plt = ("R = {a:6.2f}".format(a=r[0])) plt.text(2, 65, add2plt, fontsize=8, ha='left', va='center') plt.show()