;+ ; Procedure getnod retrieves and calibrates a total power nod scan ; pair. ; ;
This procedure will only process scans taken with the observing ; procedure "Nod". It can be used as a template for the user who may ; wish to develop more tailored calibration schemes. The spectrum is ; calibrated in Ta (K) by default. The user can calibrate to units of ; Ta* or Jy as well, via the "units" parameter. ; ;
Summary ;
Parameters ;
; The scan number is required. Either of the scans in the "Nod" ; pair can be given. Arguments to identify the IF number, ; polarization number, and feed number are optional. The default ; tracking feed number, trackfdnum, is the lowest numbered FEED ; found in the data. This feed number is interpreted as the tracking ; (source) feed for the first scan. The only other possible choice of ; trackfdnum here is 1 and the only reason to use that is if the ; lowest numbered FEED was not the tracking feed (that is not the ; usual configuration for "Nod" scans). Tracking feed in this context ; means that the source signal was in that beam during the first of ; the two "Nod" scans. ;
;
If ifnum, trackfdnum, or plnum are not supplied then the lowest ; values for each of those where data exists (all combinations may not ; have data) will be used, after using any user-supplied values. The ; value of ifnum is determined first, followed by trackfdnum and ; finally plnum. If a combination with data can not be found then ; showiftab is used to show the user what ; the set of valid combinations are. The summary line includes the ; ifnum, trackfdnum, and plnum used. ;
; Tsys and Available Units ;
; The procedure calculates Tsys based on the Tcal values and the ; data in the non-source feeds (both scans). The user can override ; this calculation by entering a zenith system temperature. The ; procedure will then correct the user-supplied Tsys for the observed ; elevation. If the data are calibrated to Ta* or Jy, then additional ; parameters are used. A zenith opacity (tau) may be specified, and ; an aperture efficiency may be specified. The user is strongly ; encouraged to enter values for these calibration parameters, but ; they will be estimated if none are provided. The user can also ; override the default Tcal by supplying a mean Tcal using the "tcal" ; keyword. ;
; Smoothing the Reference Spectra ;
; A parameter called smthoff can be used to smooth the reference ; spectrum prior to calibration. In certain conditions this technique ; can improve the signal to noise ratio, but it may degrade baseline ; shapes and artificially emphasize spectrometer glitches. Use with ; care. A value of smthoff=16 is often a good choice. ;
; Weighting of Integrations in Scan Average ;
; By default, internal averaging of integrations is weighted using ; Tsys, exposure and frequency_resolution as described in the ; dcaccum documentation. To give all integrations equal weight ; instead of the default weighting based on Tsys, use the /eqweight ; keyword. ;
; Summary Information ;
; The getnod procedure provides some information in the terminal as it ; processes data. The scan number of the first scan in the "Nod" ; pair along with the ifnum, trackfdnum, and plnum are shown, followed ; by several Tsys values. The first Tsys printed is the effective ; Tsys of the resulting spectrum, a weighted average of the Tsys ; values in the reference beams from both scans as described in donod ; The other 4 Tsys values are the individual Tsys values from the ; components of the calibration, in order: ; scan 1 beam 1, scan 1 beam 2, scan 2 beam 1, scan 2 beam 2. ;
; Using or Ignoring Flags ;
; Flags (set via flag) can be selectively ; applied or ignored using the useflag and skipflag keywords. Only one of ; those two keywords can be used at a time. ; These keywords can be used either as a boolean (/useflag or /skipflag) ; or an array of strings. The default is /useflag, meaning that all flag ; rules that have been previously set are applied when the data is ; fetched from disk. If /skipflag is set, then all flags are ignored (the ; spectrum may still contain blanked values if the values in the disk ; file have already been blanked by some other process). If useflag is a ; string or array of strings, then only those flag rules having the ; same idstring value are used to blank the data. If skipflag is a ; string or array of strings, then all flag rules except those ; with the same idstring value are used to blank the data. ;
; Dealing With Duplicate Scan Numbers ;
; Sometimes a data set may have multiple spectra with the same scan number. ; There are 3 ways to attempt to resolve such ambiguities. ; The "instance" keyword is one way. For example, if scan 23 ; appears 3 times then instance=1 refers to the second instance of scan 23 ; in the data set. The "file" keyword is useful if a ; scan is unique to a specific file and multiple files have been accessed ; using dirin. If "file" is specified and "instance" ; is also specified, then "instance" refers to the instance of that scan ; just within that file (which may be different from its instance within ; all opened files when dirin is used). The timestamp keyword is another ; way to resolve ambiguous scan numbers. The timestamp here is a string ; used essentially as a label by the monitor and control system and is ; unique to each scan. The format of the timestamp string is ; "YYYY_MM_DD_HH:MM:SS". When timestamp is given, "scan" and "instance" ; are ignored. If more than one timestamp match is found, an error is ; printed and this procedure will not continue. ; ;
Once a unique match is found to the desired scan (using instance, ; file, or timestamp) then the paired scan is identified. The match must be found ; within the same file and it must have the appropriate matching ; scan number (scan-1 if scan is the second scan in the procedure or ; scan+1 if scan is the first scan in the procedure). If those two ; rules are not sufficient to find a unique match, the matching ; scan with the closest timestamp in the appropriate direction (before ; or after depending on which procseqn is associate with scan) is used. ; Finally, the matched pair must have the appropriate procseqn. ;
; Note: if you see the message "No data found, can not continue" the
; most likely explanation is that the IF numbers are confused,
; probably due to a bad configuration (e.g. both feeds do not have
; data from the same IF and polarization). Consequently, this calibration
; routine can not calibrate that data. It is likely that all of the
; IFNUM values for this data are -1.
;
; @param scan {in}{required}{type=integer} M&C scan number
; @keyword ifnum {in}{optional}{type=integer} IF number
; (starting with 0). Defaults to the lowest value associated with data
; taking into account any user-supplied values for trackfdnum, and plnum.
; @keyword intnum {in}{optional}{type=integer} Integration number,
; defaults to all integrations.
; @keyword plnum {in}{optional}{type=integer} Polarization number
; (starting with 0). Defaults to the lowest value with data after
; determining the values of ifnum and trackfdnum if not supplied by the
; user.
; @keyword sampler {in}{optional}{type=string} sampler name, this is
; an alternative way to specify ifnum and plnum. When sampler
; name is given, ifnum and plnum must not be given. Note that data
; from the associated switched sampler will also be used.
; @keyword trackfdnum {in}{optional}{type=integer} Tracking feed
; number. Defaults to the lowest value with data after determining
; the value of ifnum if not supplied by the user and using any value
; of plnum supplied by the user.
; @keyword tau {in}{optional}{type=float} tau at zenith, if not
; supplied, it is estimated using get_tau
; tau is only used when the requested units are other than the default
; of Ta and when a user-supplied tsys value at zenith is to be used.
; @keyword tsys {in}{optional}{type=float} Tsys at zenith, this is
; converted to a Tsys at the observed elevation. If not suppled, the
; Tsys for each integration is calculated as described elsewhere.
; @keyword ap_eff {in}{optional}{type=float} Aperture efficiency, if
; not suppled, it is estimated using get_ap_eff
; ap_eff is only used when the requested units are Jy.
; @keyword smthoff {in}{optional}{type=integer} Smooth factor for
; reference spectrum, defaults to 1 (no smoothing).
; @keyword units {in}{optional}{type=string} takes the value 'Jy',
; 'Ta', or 'Ta*', defaults to 'Ta'
; @keyword tcal {in}{optional}{type=float} Cal temperature (K) to use
; in the Tsys calculation. If not supplied, the mean_tcal value from
; the header of the cal_off switching phase data in each integration
; is used. This must be a scalar, vector tcal is not yet supported.
; The resulting data container will have it's mean_tcal header value
; set to this keyword when it is set by the user.
; @keyword eqweight {in}{optional}{type=boolean} When set, all integrations
; are averaged with equal weight (1.0). Default is unset.
; @keyword quiet {in}{optional}{type=boolean} When set, the normal
; status message on successful completion is not printed. Error messages
; are not affected. Default is unset.
; @keyword keepints {in}{optional}{type=boolean} When set, the
; individual integrations are saved to the current output file
; (fileout). This keyword is ignored if a specific integration is requested
; using the intnum keyword. Default is unset.
; @keyword useflag {in}{optional}{type=boolean or string}
; Apply all or just some of the flag rules? Default is set.
; @keyword skipflag {in}{optional}{type=boolean or string} Do not apply
; any or do not apply a few of the flag rules? Default is unset.
; @keyword instance {in}{optional}{type=integer} Which occurence
; of this scan should be used. Default is 0.
; @keyword file {in}{optional}{type=string} When specified, limit the search
; for this scan (and instance) to this specific file. Default is all
; files currently opened.
; @keyword timestamp {in}{optional}{type=string} The M&C timestamp associated
; with the desired scan. When supplied, scan and instance are ignored.
; @keyword status {out}{optional}{type=integer} This keyword indicates whether
; the procedure finished as expected. A value of 1 means there were
; no problems, a value of -1 means there were problems with the
; arguments before any data was processed, and a value of 0 means that
; some of the individual integrations were processed (and possibly
; saved to the output file if keepints was set) but there was a
; problem with the final average and the contents of buffer 0 likely
; contains just the result from the last integration processed. This
; keyword is primarily of use when using getnod with another
; procedure or function.
;
; @examples
;
; ; average both polarizations from ifnum=1
; sclear
; getnod, 76, ifnum=1, plnum=0
; accum
; getnod, 76, ifnum=1, plnum=1
; accum
; ave
;
;
; @uses accumave
; @uses accumclear
; @uses calsummary
; @uses check_calib_args
; @uses data_free
; @uses dcaccum
; @uses dcscale
; @uses dcsetunits
; @uses donod
; @uses find_paired_info
; @uses find_scan_info
; @uses get_calib_data
; @uses set_data_container
; @uses showiftab
;
; @version $Id$
;-
pro getnod,scan,ifnum=ifnum,intnum=intnum,plnum=plnum,trackfdnum=trackfdnum,sampler=sampler,tau=tau,$
tsys=tsys,ap_eff=ap_eff,smthoff=smthoff,units=units,eqweight=eqweight, $
tcal=tcal,quiet=quiet,keepints=keepints,useflag=useflag,skipflag=skipflag, $
instance=instance, file=file, timestamp=timestamp, status=status
compile_opt idl2
status = -1
; basic argument checks
argsOK=check_calib_args(scan,ifnum=ifnum,intnum=intnum,plnum=plnum,fdnum=trackfdnum, $
sampler=sampler,eqweight=eqweight,units=units,quiet=quiet,keepints=keepints,useflag=useflag, $
skipflag=skipflag,instance=instance,file=file,$
timestamp=timestamp,tau=tau,ap_eff=ap_eff,/twofeeds,ret=ret,info=info)
if not argsOK then return
scan1Info = info
if size(scan1Info,/type) ne 8 then return
; check for appropriate info in the scan found
; it must be 'Nod'
if scan1Info.procedure ne 'Nod' then begin
message,"Cannot handle this scan: Procedure = " + strcompress(scan1Info.procedure,/remove_all),/info
return
end
; it must be one of a pair of scans
if scan1Info.procseqn gt 2 then begin
sProcseqn = strcompress(string(scan1Info.procseqn),/remove_all)
message,"More than two scans in this procedure - can not continue. At least : " + sProcseqn, /info
return
endif
; locate the paired scan
scan2Info = find_paired_info(scan1Info)
if size(scan2Info,/type) ne 8 then begin
message,'The other scan for this Nod procedure can not be found.',/info
return
endif
; make sure we have them in the right order
if (scan2Info.scan lt scan1Info.scan) then begin
tmp = scan2Info
scan2Info = scan1Info
scan1Info = tmp
endif
; each scan must have only 2 switching states, which must
; be CAL states
if scan1Info.n_switching_states ne 2 then begin
message,"This does not appear to be total power data - must have 2 switching states in each scan.",/info
return
endif
if scan1Info.n_cal_states ne 2 then begin
message,"This does not appear to be total power data - must have 2 cal states in each scan.",/info
return
endif
; get the requested data
scan1Data = get_calib_data(scan1Info, ret.ifnum, ret.plnum, ret.fdnum, ret.sampler, scan1count, $
intnum=intnum, useflag=useflag,skipflag=skipflag, /twofeeds)
if scan1count le 0 then begin
message,'No data found for the first scan in this pair, can not continue',/info
return
endif
scan2Data = get_calib_data(scan2Info, ret.ifnum, ret.plnum, ret.fdnum, ret.sampler, scan2count, $
intnum=intnum, useflag=useflag, skipflag=skipflag, /twofeeds)
if scan2count le 0 then begin
message,'No data found for the second scan in this pair, can not continue',/info
data_free,scan1Data
return
endif
; from this point on, sigdata and refdata contain data containers
; that must be freed whenever this routine returns to avoid memory leaks.
; find the 8 types of spectra
feed1 = scan1Info.feeds[ret.fdnum]
feed2 = scan1Info.feeds[(ret.fdnum eq 0) ? 1:0]
s1_b1_off = where(scan1Data.feed eq feed1 and scan1Data.cal_state eq 0,s1_b1_off_count)
s1_b1_on = where(scan1Data.feed eq feed1 and scan1Data.cal_state eq 1,s1_b1_on_count)
s2_b1_off = where(scan2Data.feed eq feed1 and scan2Data.cal_state eq 0,s2_b1_off_count)
s2_b1_on = where(scan2Data.feed eq feed1 and scan2Data.cal_state eq 1,s2_b1_on_count)
s1_b2_off = where(scan1Data.feed eq feed2 and scan1Data.cal_state eq 0,s1_b2_off_count)
s1_b2_on = where(scan1Data.feed eq feed2 and scan1Data.cal_state eq 1,s1_b2_on_count)
s2_b2_off = where(scan2Data.feed eq feed2 and scan2Data.cal_state eq 0,s2_b2_off_count)
s2_b2_on = where(scan2Data.feed eq feed2 and scan2Data.cal_state eq 1,s2_b2_on_count)
; final sanity checks
; Each type of data container must have the same count and that
; must be at least equal to the number of integrations to be processed
if n_elements(intnum) eq 1 then begin
nIntS1B1 = 1
nIntS1B2 = 1
nIntS2B1 = 1
nIntS2B2 = 1
expectedCount = 1
endif else begin
; use nIntegrations appropriate to the given sampler
; must be the same between scans
; scan 1, beam 1
sampIndx = (where(scan1Info.samplers eq scan1Data[s1_b1_off[0]].sampler_name))[0]
nIntS1B1 = scan1Info.n_sampints[sampIndx]
; scan 1, beam 2
sampIndx = (where(scan1Info.samplers eq scan1Data[s1_b2_off[0]].sampler_name))[0]
nIntS1B2 = scan1Info.n_sampints[sampIndx]
; scan 2, beam 1
sampIndx = (where(scan2Info.samplers eq scan2Data[s2_b1_off[0]].sampler_name))[0]
nIntS2B1 = scan2Info.n_sampints[sampIndx]
; scan 2, beam 2
sampIndx = (where(scan2Info.samplers eq scan2Data[s2_b2_off[0]].sampler_name))[0]
nIntS2B2 = scan2Info.n_sampints[sampIndx]
expectedCount = min([nIntS1B1,nIntS1B2,nIntS2B1,nIntS2B2])
maxCount = max([nIntS1B1,nIntS1B2,nIntS2B1,nIntS2B2])
if maxCount ne expectedCount then begin
; this is only OK for VEGAS
if scan1Data[0].backend ne "VEGAS" then begin
message,'The number of integrations in the two scans are not the same and this is not VEGAS data, can not continue',/info
data_free, scan1Data
data_free, scan2Data
return
endif
; and for VEGAS, they must differ by only 1
if maxCount-expectedCount gt 1 then begin
message,'The number of integrations in the two scans are incompatible, can not continue.',/info
data_free, scan1Data
data_free, scan2Data
return
endif
endif
endelse
if (s1_b1_off_count ne nIntS1B1) or (s1_b1_on_count ne nIntS1B1) or $
(s2_b1_off_count ne nIntS2B1) or (s2_b1_on_count ne nIntS2B1) or $
(s1_b2_off_count ne nIntS1B2) or (s1_b2_on_count ne nIntS1B2) or $
(s2_b2_off_count ne nIntS2B2) or (s2_b2_on_count ne nIntS2B2) then begin
message,"Unexpected number of spectra retrieved for some or all of the switching phases, can not continue.",/info
data_free, scan1Data
data_free, scan2Data
return
endif
status = 0
missing = 0
missingBeam = 0
if keyword_set(eqweight) then weight = 1.0 ; else undefined and use default weight
thisaccum = {accum_struct}
tauInts = fltarr(expectedCount)
apEffInts = tauInts
tsysInts = fltarr(expectedCount,4)
for i = 0,(expectedCount-1) do begin
donod,result,scan1Data[s1_b1_off[i]],scan1Data[s1_b1_on[i]],scan2Data[s2_b1_off[i]],scan2Data[s2_b1_on[i]],$
scan1Data[s1_b2_off[i]],scan1Data[s1_b2_on[i]],scan2Data[s2_b2_off[i]],scan2Data[s2_b2_on[i]],$
smthoff,ret_tsys,tsys=tsys,tau=tau,tcal=tcal,eqweight=eqweight,single_beam=single_beam
; convert to the desired units
dcsetunits,result,units,tau=tau,ap_eff=ap_eff,ret_tau=ret_tau,ret_ap_eff=ret_ap_eff
; these are only used in the status line at the end
tauInts[i] = ret_tau
apEffInts[i] = ret_ap_eff
tsysInts[i,*] = ret_tsys
missingBeam += keyword_set(single_beam)
dcaccum,thisaccum,result,weight=weight
if keyword_set(keepints) then begin
; re-use raw data containers to conserve space
; defer the actual keep until later
; takes 3 steps because of the nature of IDL
; data passing (value vs reference)
tmp = scan1Data[s1_b1_off[i]]
data_copy, result, tmp
scan1Data[s1_b1_off[i]] = tmp
endif
end
if keyword_set(keepints) then putchunk,scan1Data[s1_b1_off]
naccum1 = thisaccum.n
if naccum1 le 0 then begin
message,'Result is all blanked - probably all of the data were flagged',/info
; this can only happen if result is all blanked
set_data_container,result
; clean up
accumclear, thisaccum
data_free, scan1Data
data_free, scan2Data
data_free, result
return
endif
accumave,thisaccum, result, /quiet
missing = naccum1 ne expectedCount
accumclear, thisaccum
set_data_container,result
status = 1
if not keyword_set(quiet) then begin
if missing then nmiss = expectedCount-naccum1
calsummary, scan1Info.scan, result.tsys, result.units, $
tsysInts=tsysInts, tauInts=tauInts, apEffInts=apEffInts, $
missingInts=nmiss, missingBeams=missingBeam, eqweight=eqweight, $
ifnum=ret.ifnum, fdnum=ret.fdnum, plnum=ret.plnum
endif
data_free, scan1Data
data_free, scan2Data
data_free,result
end