Created
March 31, 2020 14:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pro Visualization_Using_Sun_Position | |
cd, 'C:\SYSTEM\PROG\IDL\Satellite_Angle' | |
dim = [360, 180] | |
lon1D = fltarr(dim[0]) | |
lat1D = fltarr(dim[1]) | |
valZenith2D = fltarr(dim[0], dim[1]) | |
valAzimuth2D = fltarr(dim[0], dim[1]) | |
lon1D = -180.0 + findgen(dim[0]) | |
lat1D = 90.0 - findgen(dim[1]) | |
for day = 1L, 1 do begin | |
for hour = 0L, 24 do begin | |
for iCount = 0L, dim[0] - 1 do begin | |
SunPosition, day, hour, lat1D, lon1D[iCount], zenith, azimuth | |
valZenith2D[iCount, *] = zenith[*] | |
valAzimuth2D[iCount, *] = azimuth[*] | |
endfor | |
print, min(valZenith2D, /nan), mean(valZenith2D, /nan), max(valZenith2D, /nan) | |
help, valZenith2D | |
print, min(valAzimuth2D, /nan), mean(valAzimuth2D, /nan), max(valAzimuth2D, /nan) | |
help, valAzimuth2D | |
cnLat = 0 | |
cnLon = 0 | |
ROI = [-90, 90, -180, 180] | |
dtDateYmdH = string(day, "_", hour, format='(i3.3, a1, i2.2)') | |
print, dtDateYmdH | |
psName = "Img01_" + dtDateYmdH | |
mainName = "Solar Zenith Angle : " + dtDateYmdH | |
fnMakePsPlot, lon1D, lat1D, valZenith2D, dim, cnLat, cnLon, ROI, psName, mainName, 0, 180, 30, 33 | |
psName = "Img02_" + dtDateYmdH | |
mainName = "Azimuth Angle : " + dtDateYmdH | |
fnMakePsPlot, lon1D, lat1D, valAzimuth2D, dim, cnLat, cnLon, ROI, psName, mainName, -180, 180, 30, 33 | |
endfor | |
endfor | |
com = "convert -loop 0 -delay 100 "+ "./FIG/Img01_*.png" + " " + "./GIF/Img01.gif" | |
spawn, /hide, com | |
com = "convert -loop 0 -delay 100 "+ "./FIG/Img02_*.png" + " " + "./GIF/Img02.gif" | |
spawn, /hide, com | |
end | |
;==================================================================== | |
; Subroutine : Function Make Postscript to Png Graph | |
;==================================================================== | |
pro fnMakePsPlot, lon1D, lat1D, val2D, dim, cnLat, cnLon, ROI, psName, mainName, zmin, zmax, interval, color_table | |
set_plot, "ps" | |
device, filename = psName + ".ps", decomposed=0, bits=8, /color, xsize=16, ysize = 12, /inches, font_size = 13, /Helvetica | |
!p.font = 0 & !p.charsize = 2.0 & !p.charthick = 1.6 & !p.multi = [0,1,1] & !p.background = 255 | |
xvert = [0.1, 0.1, -0.1, -0.1 ,0.1] | |
yvert = [-0.1, 0.1, 0.1, -0.1, -0.1] | |
usersym, xvert, yvert, /fill | |
start_color = 0 & end_color = 255 & colorn = end_color - start_color + 1 | |
cgloadct, color_table | |
latmin = ROI(0) & latmax= ROI(1) & lonmin = ROI(2) & lonmax= ROI(3) | |
cgMAP_SET, cnLat, cnLon, /CYLINDRICAL $ | |
, limit = [latmin, lonmin, latmax, lonmax] $ | |
, position = [0.1, 0.1, 0.8, 0.85], /noborder | |
for i = 0L, dim[0] - 1 do begin | |
for j = 0L, dim[1] - 1 do begin | |
nLon = lon1D[i] | |
nLat = lat1D[j] | |
nVal = val2D[i, j] | |
if (lonmin gt nLon or nLon gt lonmax or finite(nLon, /nan) eq 1) then continue | |
if (latmin gt nLat or nLat gt latmax or finite(nLat, /nan) eq 1) then continue | |
if (finite(nVal, /nan) eq 1) then continue | |
plots, nLon, nLat, psym = 8, symsize = 5, color = BYTSCL(nVal, zmin, zmax) | |
endfor | |
endfor | |
cgColorbar, NColors = 255, BOTTOM = 1 $ | |
, Divisions = 5, COLOR = "black" $ | |
, Position = [0.2, 0.90, 0.8, 0.94] $ | |
, Range = [zmin, zmax] $ | |
, CHARSIZE = 1.5,CHARthick = 2 $ | |
, VERTICAL = 1, RIGHT = 1 | |
cgLoadct, 2 | |
contour, val2D, lon1D, lat1D, /overplot, C_THICK = 2 $ | |
, LEVELS = zmin + findgen(10) * interval $ | |
, C_LABELS = zmin + findgen(10) * interval $ | |
, C_CHARSIZE = 1.5, C_CHARTHICK = 2 $ | |
, C_COLORS = BYTSCL(zmin + findgen(10) * interval, zmin, zmax) | |
cgMAP_CONTINENTS, /coast, /countries, COLOR = "black" | |
lats = [-90:90:30] | |
lons = [-180:360:60] | |
lats_names = strarr(n_elements(lats)) | |
lons_names = strarr(n_elements(lons)) | |
for i = 0L, n_elements(lats) - 1 do begin | |
if (lats[i] gt 0) then begin | |
lats_names[i] = textoidl(string(lats[i]) + "\circN") | |
endif else if (lats[i] eq 0) then begin | |
lats_names[i] = textoidl(string(lats[i]) + "\circ") | |
endif else begin | |
lats_names[i] = textoidl(string(-lats[i]) + "\circS") | |
endelse | |
endfor | |
for i = 0L,n_elements(lons) - 1 do begin | |
if (lons[i] gt 0) then begin | |
lons_names[i] = textoidl(string(lons[i]) + "\circE") | |
endif else if (lons[i] eq 0) then begin | |
lons_names[i] = textoidl(string(lons[i]) + "\circ") | |
endif else begin | |
lons_names[i] = textoidl(string(-lons[i]) + "\circW") | |
endelse | |
endfor | |
cgMap_grid, color = "black", charsize = 1.8, thick = 2.5, lats = lats, latnames = lats_names, lons = lons, lonnames = lons_names $ | |
, linestyle = 1, bthick = 300, /box_axes, /no_grid | |
cgText, 0.45, 0.95, mainName, /normal, charsize = 2, CHARTHICK = 2, color = "black", alignment = 0.5 | |
device, /close_file | |
com = "convert -flatten -background white " + psName + ".ps" + " " + "./FIG/" + file_basename(psName, ".ps") + ".png" | |
spawn, /hide, com | |
; file_delete, ps_name + ".ps" | |
return | |
end | |
pro SunPosition,day,time,lat,lon,zenith,azimuth,solfac,sunrise=sunrise, $ | |
sunset=sunset,local=local,latsun=latsun,lonsun=lonsun | |
;+ | |
; ROUTINE: SunPosition | |
; | |
; PURPOSE: Compute solar position information as a function of | |
; geographic coordinates, date and time. | |
; | |
; USEAGE: zensun,day,time,lat,lon,zenith,azimuth,solfac,sunrise,sunset, | |
; local=local | |
; | |
; INPUT: | |
; day Julian day (positive scalar or vector) | |
; (spring equinox = 80) | |
; (summer solstice= 171) | |
; (fall equinox = 266) | |
; (winter solstice= 356) | |
; | |
; time Universal Time in hours (scalar or vector) | |
; | |
; lat geographic latitude of point on earth's surface (degrees) | |
; | |
; lon geographic longitude of point on earth's surface (degrees) | |
; | |
; OUTPUT: | |
; | |
; zenith solar zenith angle (degrees) | |
; | |
; azimuth solar azimuth (degrees) | |
; Azimuth is measured clockwise from due north | |
; | |
; solfac Solar flux multiplier. SOLFAC=cosine(ZENITH)/RSUN^2 | |
; where rsun is the current earth-sun distance in | |
; astronomical units. | |
; | |
; NOTE: SOLFAC is negative when the sun is below the horizon | |
; | |
; | |
; KEYWORD INPUT: | |
; | |
; local if set, TIME is specified as a local time and SUNRISE | |
; and SUNSET are output in terms of local time | |
; | |
; NOTE: "local time" is defined as UT + local_offset | |
; where local_offset is fix((lon+sign(lon)*7.5)/15) | |
; with -180 < lon < 180 | |
; | |
; Be aware, there are no fancy provisions for | |
; day-light savings time and other such nonsense. | |
; | |
; KEYWORD OUTPUT: | |
; | |
; sunrise Time of sunrise (hours) | |
; sunset Time of sunset (hours) | |
; | |
; latsun the latitude of the sub-solar point (fairly constant over day) | |
; Note that daily_minimum_zenith=abs(latsun-lat) | |
; | |
; lonsun the longitude of the sub-solar point | |
; Note that at 12 noon local time (lon-lonsun)/15. is the | |
; number of minutes by which the sun leads the clock. | |
; | |
;; Often used lat, lon | |
; | |
; Santa Barbara: 34.410,-119.727 | |
; SGP Cart Site: 36.605,-97.485 | |
; North Slope: 69.318,-151.015 | |
; Palmer Station: -64.767,-64.067 | |
; | |
;; EXAMPLE 1: Compute the solar flux at Palmer Station for day 283 | |
; | |
; time=findgen(1+24*60)/60 | |
; zensun,283,time,-64.767,-64.067,z,a,sf | |
; solflx=sf*s | |
; plot,time,solflx | |
; | |
; where s is the TOA solar irradiance at normal incidence: | |
; | |
; s=1618.8 ; W/m2/micron for AVHRR1 GTR100 | |
; s= 976.9 ; W/m2/micron for AVHRR2 GTR100 | |
; s=1685.1 ; W/m2/micron for 410nm GTR100 | |
; s= 826.0 ; W/m2/micron for 936nm GTR100 | |
; s=1.257e17 ; photons/cm2/s PAR GTR100 | |
; s=1372.9 ; w/m2 total broadband | |
; | |
; | |
;; EXAMPLE 2: Find time of sunrise and sunset for current day | |
; | |
; doy=julday()-julday(1,0,1994) | |
; zensun,doy,12,34.456,-119.813,z,a,s,sunrise=sr,sunset=ss,/local &$ | |
; zensun,doy,[sr,.5*(sr+ss),ss],34.456,-119.813,z,az,/local &$ | |
; print,'sunrise: '+hms(3600*sr)+ ' PST azimuth angle: ',az(0) &$ | |
; print,'sunset: '+hms(3600*ss)+ ' PST azimuth angle: ',az(2) &$ | |
; print,'zenith: '+hms(1800*(ss+sr))+ ' PST zenith angle: ',z(1) | |
; | |
; AUTHOR: Paul Ricchiazzi 23oct92 | |
; Earth Space Research Group, UCSB | |
; | |
; REVISIONS: | |
; | |
; jan94: use spline fit to interpolate on EQT and DEC tables | |
; jan94: output SUNRISE and SUNSET, allow input/output in terms of local time | |
; jan97: declare eqtime and decang as floats. previous version | |
; this caused small offsets in the time of minimum solar zenith | |
;- | |
; PROCEDURE: | |
; | |
; 1. Calculate the subsolar point latitude and longitude, based on | |
; DAY and TIME. Since each year is 365.25 days long the exact | |
; value of the declination angle changes from year to year. For | |
; precise values consult THE AMERICAN EPHEMERIS AND NAUTICAL | |
; ALMANAC published yearly by the U.S. govt. printing office. The | |
; subsolar coordinates used in this code were provided by a | |
; program written by Jeff Dozier. | |
; | |
; 2. Given the subsolar latitude and longitude, spherical geometry is | |
; used to find the solar zenith, azimuth and flux multiplier. | |
; | |
; eqt = equation of time (minutes) ; solar longitude correction = -15*eqt | |
; dec = declination angle (degrees) = solar latitude | |
; | |
; LOWTRAN v7 data (25 points) | |
; The LOWTRAN solar position data is characterized by only 25 points. | |
; This should predict the subsolar angles within one degree. For | |
; increased accuracy add more data points. | |
; | |
;nday=[ 1., 9., 21., 32., 44., 60., 91., 121., 141., 152.,$ | |
; 160., 172., 182., 190., 202., 213., 244., 274., 305., 309.,$ | |
; 325., 335., 343., 355., 366.] | |
; | |
;eqt=[ -3.23, -6.83,-11.17,-13.57,-14.33,-12.63, -4.2, 2.83, 3.57, 2.45,$ | |
; 1.10, -1.42, -3.52, -4.93, -6.25, -6.28,-0.25, 10.02, 16.35, 16.38,$ | |
; 14.3, 11.27, 8.02, 2.32, -3.23] | |
; | |
;dec=[-23.07,-22.22,-20.08,-17.32,-13.62, -7.88, 4.23, 14.83, 20.03, 21.95,$ | |
; 22.87, 23.45, 23.17, 22.47, 20.63, 18.23, 8.58, -2.88,-14.18,-15.45,$ | |
; -19.75,-21.68,-22.75,-23.43,-23.07] | |
; | |
; Analemma information from Jeff Dozier | |
; This data is characterized by 74 points | |
; | |
if n_params() eq 0 then begin | |
xhelp,'zensun' | |
return | |
endif | |
nday=[ 1.0, 6.0, 11.0, 16.0, 21.0, 26.0, 31.0, 36.0, 41.0, 46.0,$ | |
51.0, 56.0, 61.0, 66.0, 71.0, 76.0, 81.0, 86.0, 91.0, 96.0,$ | |
101.0, 106.0, 111.0, 116.0, 121.0, 126.0, 131.0, 136.0, 141.0, 146.0,$ | |
151.0, 156.0, 161.0, 166.0, 171.0, 176.0, 181.0, 186.0, 191.0, 196.0,$ | |
201.0, 206.0, 211.0, 216.0, 221.0, 226.0, 231.0, 236.0, 241.0, 246.0,$ | |
251.0, 256.0, 261.0, 266.0, 271.0, 276.0, 281.0, 286.0, 291.0, 296.0,$ | |
301.0, 306.0, 311.0, 316.0, 321.0, 326.0, 331.0, 336.0, 341.0, 346.0,$ | |
351.0, 356.0, 361.0, 366.0] | |
eqt=[ -3.23, -5.49, -7.60, -9.48,-11.09,-12.39,-13.34,-13.95,-14.23,-14.19,$ | |
-13.85,-13.22,-12.35,-11.26,-10.01, -8.64, -7.18, -5.67, -4.16, -2.69,$ | |
-1.29, -0.02, 1.10, 2.05, 2.80, 3.33, 3.63, 3.68, 3.49, 3.09,$ | |
2.48, 1.71, 0.79, -0.24, -1.33, -2.41, -3.45, -4.39, -5.20, -5.84,$ | |
-6.28, -6.49, -6.44, -6.15, -5.60, -4.82, -3.81, -2.60, -1.19, 0.36,$ | |
2.03, 3.76, 5.54, 7.31, 9.04, 10.69, 12.20, 13.53, 14.65, 15.52,$ | |
16.12, 16.41, 16.36, 15.95, 15.19, 14.09, 12.67, 10.93, 8.93, 6.70,$ | |
4.32, 1.86, -0.62, -3.23] | |
dec=[-23.06,-22.57,-21.91,-21.06,-20.05,-18.88,-17.57,-16.13,-14.57,-12.91,$ | |
-11.16, -9.34, -7.46, -5.54, -3.59, -1.62, 0.36, 2.33, 4.28, 6.19,$ | |
8.06, 9.88, 11.62, 13.29, 14.87, 16.34, 17.70, 18.94, 20.04, 21.00,$ | |
21.81, 22.47, 22.95, 23.28, 23.43, 23.40, 23.21, 22.85, 22.32, 21.63,$ | |
20.79, 19.80, 18.67, 17.42, 16.05, 14.57, 13.00, 11.33, 9.60, 7.80,$ | |
5.95, 4.06, 2.13, 0.19, -1.75, -3.69, -5.62, -7.51, -9.36,-11.16,$ | |
-12.88,-14.53,-16.07,-17.50,-18.81,-19.98,-20.99,-21.85,-22.52,-23.02,$ | |
-23.33,-23.44,-23.35,-23.06] | |
; | |
; compute the subsolar coordinates | |
; | |
tt=((fix(day)+time/24.-1.) mod 365.25) +1. ;; fractional day number | |
;; with 12am 1jan = 1. | |
if n_elements(tt) gt 1 then begin | |
eqtime=tt-tt ;; this used to be day-day, caused | |
decang=eqtime ;; error in eqtime & decang when a | |
ii=sort(tt) ;; single integer day was input | |
eqtime(ii)=spline(nday,eqt,tt(ii))/60. | |
decang(ii)=spline(nday,dec,tt(ii)) | |
endif else begin | |
eqtime=spline(nday,eqt,tt)/60. | |
decang=spline(nday,dec,tt) | |
endelse | |
latsun=decang | |
if keyword_set(local) then begin | |
lonorm=((lon + 360 + 180 ) mod 360 ) - 180. | |
tzone=fix((lonorm+7.5)/15) | |
index = where(lonorm lt 0, cnt) | |
if (cnt gt 0) then tzone(index) = fix((lonorm(index)-7.5)/15) | |
ut=(time-tzone+24.) mod 24. ; universal time | |
noon=tzone+12.-lonorm/15. ; local time of noon | |
endif else begin | |
ut=time | |
noon=12.-lon/15. ; universal time of noon | |
endelse | |
lonsun=-15.*(ut-12.+eqtime) | |
; compute the solar zenith, azimuth and flux multiplier | |
t0=(90.-lat)*!dtor ; colatitude of point | |
t1=(90.-latsun)*!dtor ; colatitude of sun | |
p0=lon*!dtor ; longitude of point | |
p1=lonsun*!dtor ; longitude of sun | |
zz=cos(t0)*cos(t1)+sin(t0)*sin(t1)*cos(p1-p0) ; up \ | |
xx=sin(t1)*sin(p1-p0) ; east-west > rotated coor | |
yy=sin(t0)*cos(t1)-cos(t0)*sin(t1)*cos(p1-p0) ; north-south / | |
azimuth=atan(xx,yy)/!dtor ; solar azimuth | |
zenith=acos(zz)/!dtor ; solar zenith | |
rsun=1.-0.01673*cos(.9856*(tt-2.)*!dtor) ; earth-sun distance in AU | |
solfac=zz/rsun^2 ; flux multiplier | |
if n_elements(time) eq 1 then begin | |
angsun=6.96e10/(1.5e13*rsun) ; solar disk half-angle | |
;angsun=0. | |
arg=-(sin(angsun)+cos(t0)*cos(t1))/(sin(t0)*sin(t1)) | |
sunrise = arg - arg | |
sunset = arg - arg + 24. | |
index = where(abs(arg) le 1, cnt) | |
if (cnt gt 0) then begin | |
dtime=acos(arg(index))/(!dtor*15) | |
sunrise(index)=noon-dtime-eqtime(index) | |
sunset(index)=noon+dtime-eqtime(index) | |
endif | |
endif | |
return | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment