Real-time IOD monitoring at IOD Monitor

Questions and comments may be addressed to Saji N. Hameed by email (saji'at-mark'u-aizu.ac.jp) or from my ResearchGate page

Satellite SST from the microwave channel

Downloading MW OISST

To download data and to obtain further information about Microwave Optimally Interpolated SST, go here

After you register, you can use the following ruby snippet to help download data for the desired period (add your email address at the appropriate location in the snippet).

require './mw_sst'

url = "ftp://ftp.remss.com/sst/daily/mw/v05.0/bmaps/"
uid = "put your email address here"
pas = uid

mw_sst = MW_SST.new(url,uid,pas)

# Get Final SST
mw_sst.out_path = "./Data"
#sper = Time.new(2018,1,1)
#eper = Time.new(2018,12,31)
sper = Time.new(2019,1,1)
eper = Time.new(2019,9,27)
mw_sst.get_sst(sper,eper)

The ruby program mw_sst.rb is documented below:

require 'date'

def days_in_month(year, month)
  Date.new(year, month, -1).day
end

class MW_SST
  attr_reader :url, :out_path
  def initialize(url,uid,passwd)
    @url = url
    @uid = uid
    @pas = passwd
  end
  def out_path=(dir)
    @out_path=dir
  end
  def get_sst(sper,eper)
    get_data(sper,eper,"0")
  end
  def get_rtsst(sper,eper)
    get_data(sper,eper,"rt")
  end
private
  def secs_per_day
    1*24*60*60
  end
  def get_data(sper,eper,ext)
    tim = sper
    Dir.chdir(out_path) do

      while(tim <= eper)
        yr  = tim.year
        yr = ext if ext=="rt"
        dy  = "%03d" % tim.yday
        fnm = "mw.fusion.#{yr}.#{dy}.v05.#{ext}.gz"
        puts tim.strftime("Getting data for %m/%d/%Y") unless File.exists?(fnm)
        tim+= secs_per_day # should be here,
                           # otherwise next will hang
        next if File.exists?(fnm)
        puts `wget --user=#{@uid} --password=#{@pas} #{url}/#{yr}/#{fnm}`
      end

    end # back to present directory
  end
end

## Processing and reformatting MW OISST to netcdf

The NCL driver script for dealing with MW SST

load "./mw_sst.ncl"

dat_dir = "./Data"
pre_dir = dat_dir

smo     = 1
sdy     = 1
emo     = 9
edy     = 28
;emo     = 12
;edy     = 31
use_prelm_file = False
opt     = False
; opt@pre_smo =
; opt@pre_sdy =
; extract and write can only be used to write one year at a time
opt@overwrite = True
do yr=2019,2019
  pp(extract_and_write(dat_dir,pre_dir,yr,smo,emo,sdy,edy,use_prelm_file,opt))
  sleep(1)
end do

The NCL library for dealing with MW SST

load "$SysE/lib/ncl/helper_libs.ncl"
load "$SysE/lib/ncl/syse_db.ncl"

function oisst_lat(nlat)
begin
  dlat = 180.0/nlat
  ilat = ispan(1,nlat,1)
  lat  = dlat*ilat - (90.0+dlat/2.0)
  lat!0 = "lat"
  lat&lat = lat
  lat@units = "degrees_north"
  return(lat)
end

function oisst_lon(nlon)
begin
  ilon = ispan(1,nlon,1)
  dlon = 360.0/nlon
  lon  = dlon*ilon - (dlon/2.0)
  lon!0 = "lon"
  lon&lon = lon
  lon@units = "degrees_east"
  return(lon)
end

function formatted_day(yr,mo,dy)
begin
  return(sprinti("%0.3i",day_of_year(yr,mo,dy)))
end

function daily_time(y1,m1,d1,d2)
begin
  yd1 = day_of_year(y1,m1,d1)
  yd2 = day_of_year(y1,m1,d2)
  ndy = yd2-yd1+1
  tim = new(ndy,"double")
  tim@units = "days since 1900-01-01"
  stim = tointeger(ut_inv_calendar(y1,m1,d1,0,0,0,tim@units,0))
  etim = tointeger(ut_inv_calendar(y1,m1,d2,0,0,0,tim@units,0))
  if ndy .gt. 1
    tim = ispan(stim,etim,1)*1.d0
  else
    tim = stim*1.d0
  end if
  tim!0 = "time"
  tim&time = tim
  return(tim)
end

function read_mw_oisst(fname,nlat,nlon)
begin
  sst_rec =0
  msk_rec = 2
  scl_sst = 0.15
  off_sst = -3.0

  ; mask bits and meanings
  lnd = 0
  ice = 1
  ird = 2
  mwd = 3
  bad = 4
  lnd = 7-lnd
  bad = 7-bad

  pp("unzip "+fname+".gz")
  system("gunzip "+fname+".gz")
  data = tofloat(fbindirread(fname,sst_rec,(/nlat,nlon/),"ubyte"))
  tmask = getbitsone(fbindirread(fname,msk_rec,(/nlat,nlon/),"ubyte"))
  system("gzip "+fname)
  pp("zip "+fname)

  ; apply the mask to scale good data
  sst = where(data .le. 250, data*scl_sst+off_sst, 255)
  ; Mask land and bad data
  sst = where(tmask(:,:,bad) .eq. 1, 255, sst)
  sst = where(tmask(:,:,lnd) .eq. 1, 255, sst)
  sst@_FillValue = 255
  return(sst)
end

function write_mw_oisst(var,vname,yr,opt)
begin
  dataSrc="MW"
  clb = syse_del_dly_mean(dataSrc,vname,(/yr,yr/),True)
  return(syse_put_dly_mean(dataSrc,vname,var,opt))
end

function get_mon_data(dir_fnl,dir_pre,yr,mon,sdy,fnl_dy,use_prelm_file,nlat,nlon,opt)
begin
  lat0 = oisst_lat(nlat)
  lon0 = oisst_lon(nlon)
  ; typical file name :: "mw_ir.fusion.2002.152.v05.0"
  ndy = fnl_dy-sdy+1
  vtmp = new( (/ndy,nlat,nlon/), "float")
  k = 0
  do idy=sdy,fnl_dy
    form_day = formatted_day(yr,mon,idy)
    fname=dir_fnl+"/mw.fusion."+yr+"."+form_day+".v05.0"
    if use_prelm_file
      psmo = opt@psmo
      psdy = opt@psdy
      abort("not yet implemented:: pls modify code")
      if (mon .eq. psmo) .and. (idy .ge. psdy)
        fname=dir_fnl+"/mw.fusion."+yr+"."+form_day+".nc"
      end if
      if (mon .gt. psmo) .and. (idy .ge. 1)
        fname=dir_fnl+"/mw.fusion."+yr+"."+form_day+".nc"
      end if
    end if
    vtmp(k,:,:)=read_mw_oisst(fname,nlat,nlon)
    k = k+1
  end do
  add_dimensions(vtmp,(/"time","lat","lon"/))
  vtmp&time = daily_time(yr,mon,sdy,fnl_dy)
  vtmp&lat = lat0
  vtmp&lon = lon0
  return(vtmp)
end

function get_data(dir_fnl,dir_pre,yr,smo,emo,sdy,edy,use_prelm_file,opt)
begin
  nlat = 720
  nlon = 1440
  lat0 = oisst_lat(nlat)
  lon0 = oisst_lon(nlon)
  first_day = day_of_year(yr,smo,sdy)
  last_day  = day_of_year(yr,emo,edy)
  num_of_days = last_day - first_day + 1
  num_of_months = emo-smo+1
  lt1 = -30
  lt2 = 30
  ln1 = 30
  ln2 = 135
  ind_lat = lat0({lt1:lt2})
  ind_lon = lon0({ln1:ln2})
  nlt = dimsizes(ind_lat)
  nln = dimsizes(ind_lon)
  var = new( (/num_of_days,nlt,nln/), float, -999)

   ; Read data for first month
  fnl_dy = days_in_month(yr,smo)
  if smo .eq. emo
    fnl_dy = edy
  end if
  ibg = 0 ; start index
  ien = ibg+(fnl_dy-sdy) 
  tmp = get_mon_data(dir_fnl,dir_pre,yr,smo,sdy,fnl_dy,use_prelm_file,nlat,nlon,opt)
  var(ibg:ien,:,:)  = tmp(:,{lt1:lt2},{ln1:ln2})
  delete(tmp) ; because tmp may change size of its 1st dimension in next step

  ; For the special case of smo and emo being equal, return var right away
  if smo .eq. emo
    return(var)
  end if

  if num_of_months .gt. 2 ; note the condition is not 'ge', but 'gt'
    ; if the above condition is not met, go to last loop
    ; Read data for second to last but one month
    do imo = smo+1,emo-1
      ibg = ien+1
      fnl_dy = days_in_month(yr,imo)
      ien = ibg+fnl_dy-1
      tmp = get_mon_data(dir_fnl,dir_pre,yr,imo,1,fnl_dy,use_prelm_file,nlat,nlon,opt)
      var(ibg:ien,:,:)  = tmp(:,{lt1:lt2},{ln1:ln2})
      delete(tmp)
    end do
  end if
 ; Read data for last month
  ibg = ien+1
  ien = ibg+edy-1
  tmp = get_mon_data(dir_fnl,dir_pre,yr,emo,1,edy,use_prelm_file,nlat,nlon,opt)
  var(ibg:ien,:,:)  = tmp(:,{lt1:lt2},{ln1:ln2})
  return(var)
end

function extract_and_write(dir_fnl,dir_pre,yr,smo,emo,sdy,edy,use_prelm_file,opt)
begin
  var = get_data(dir_fnl,dir_pre,yr,smo,emo,sdy,edy,use_prelm_file,opt)
  var&time@calendar = "standard"
  var@source="MWSST from REMSS at 25km resolution"
  wopt = True
  if isatt(opt,"overwrite")
    wopt@overwrite = True
  end if
  iret=write_mw_oisst(var,"sst",yr,wopt)
  return(iret)
end