#Original Function Location: /themis/lib/dav_lib/public_library/latest/spectral_tools.dvrc
/themis/lib/dav_lib/library/spectral_tools.dvrc
Source Code for Function: "norm_spec()" in "spectral_tools.dvrc" (Public)
spectral_tools_version=1.24
#1.01 version incremented for emcal rewrites
#1.02 added sma, sort_conc, sum_group_conc, summary_sma, and summary_sma_group
#1.03 minor edits to sma, sort_conc, sum_group_conc, summary_sma and summary_sma_group
#1.04 changes to sma (accepts a standard structure + resample option)
# changes to summary_sma, summary_sma_groups, now accept ranges (e.g. xlow=1, xhigh=10)
# dehyd2 changed to handle $DV_SCRIPT_FILES
#1.05 changes to sma to handle other data types than float
#1.06 added several generic spectral analysis tools
#1.07 added reform_speclib
#1.08 added i2i_tutorial and made make_band option to return a 73-pt spectrum
#1.09 dehyd modified to run on individual spectra in an XxY array
# sma - now returns elements that are all the same size as the endlib struct
# sma - modified exclude to take non-monotonically increasing values
# sma - fixed notchco2 to work on XxY arrays
#1.10 sma - added new elements to .grouped in sma output
#1.11 summary_sma(), summary_sma_group() - total rewrite, similar usage as before,
# summary_sma_group() now calls summary_sma() with a group=1 option
# modifictionas to sma() which allow for integration with new plot_sma and a bug fix
# to sum_group_conc() which now takes the precomputed covariance matrix from sma (fixes error values)
#1.12 sum_group_conc() - fixed goofy error where the number of elements was not being calculated correctly
#1.13 added tdb2struct - prc 11/2010
#1.14 sma - added nn option, which uses NNLS algorithm to fit spectra (faster and more accurate than original algorithm)
#1.15 fit_bb - added function to fit blackboides using nnls
#1.17 new versions of rad2tb2, tb2rad2, make_band - now take inst="instrument" options
# also included emissivity, cal_rad, irf_ri
#1.18 includes emcal2 and some major fixes to emssivity, cal_rad, and irf_ri
# also included r2t_swri
#1.19 fixed emcal2 to allow a list of environment temperatures, also data are now stored in x not y
#1.20 added sublib to allow the useer to subset all elements of a spectral library at once.
#1.21 fixed a bug in sma() that would not allow nn=1 to work with the surface=1 option.
#1.22 added structures to i2i() and it now works with MASTER as well.make_band() now has MASTER option as well
# modified emcal2() to have max_emiss option. Also fixed ctok() issues that were changed in emissivity
#1.23 added diffbb modeling option to fit_bb()
#1.24 bug fix to sma(); upgraded emcal2 to take new LabView spectrometer output
# norm_spec - taken from D. Rogers
# reform_speclib - created by c.edwards 8-5-10
# cal_rad - taken from /u/phil/scripts/dvinci/prc_beta.dv
# irf_ri - taken from /u/phil/scripts/dvinci/prc_beta.dv
# emissivity - taken from /u/phil/scripts/dvinci/prc_beta.dv
# tb2rad2 - taken from /u/phil/scripts/davinci/ir_analysis.dv
# rad2tb2 - taken from /u/phil/scripts/davinci/ir_analysis.dv
# make_band - taken from /u/phil/scripts/davinci/ir_analysis.dv
# make_temp_rad - taken from /u/phil/scripts/davinci/ir_analysis.dv
# i2i - taken from /u/phil/scripts/davinci/ir_analysis.dv
# i2i_tutorial - taken from /u/phil/scripts/davinci/ir_analysis.dv
# reverse_spectrum - taken from /u/phil/scripts/davinci/ir_analysis.dv
# cm2micron - taken from /u/phil/scripts/davinci/ir_analysis.dv
# read_vm - taken from /u/bandfield/josh.dvrc
# r2t_hi - taken from /u/baldridge/amb.dvrc
# r2t_lo - taken from /u/baldridge/amb.dvrc
# r2t_swri - taken from rt2_swri.dvrc - M.Osterloo
# emcal - taken from /u/baldridge/amb.dvrc
# emcal2 - created by c.edwards 3-17-11
# dehyd2 - taken from /u/cedwards/christopher.dvrc
# sublib - added by C. Edwards 4-8-2011
# sma - added by D. Rogers
# sort_conc - added by D. Rogers
# sum_group_conc - added by D. Rogers
# summary_sma - added by D. Rogers
# summary_sma_group - added by D. Rogers
# tdb2struct - added by P. Christensen
# fit_bb - added by c.edwards 1-24-2011
# sa - taken from /u/phil/scripts/atmos_rad.dv
define norm_spec(xaxis,w1,w2) {
if ($ARGC == 0) {
printf (" \n")
printf (" $1 = array of spectra to be normalized \n")
printf (" (xaxis = x-axis) default TES 73-point spectrum \n")
printf (" (w1 = wave1) default 200 cm-1 \n")
printf (" (w2 = wave2) default 1305 cm-1 \n")
printf (" \n")
return(0)
}
arry=$1
tesx=translate(xt2(),y,z)
axeis=cat(tesx[,,9:35],tesx[,,65:110],z)
wayve1=200
wayve2=1305
if(HasValue(xaxis)) {
axeis=xaxis
}
if(HasValue(w1)){
wayve1=w1
}
if(HasValue(w2)){
wayve2=w2
}
avearry=avg(arry,axis=xy)
dimarry=dim(arry)
nspecs=dimarry[1]
fspecs=create(dimarry[1],dimarry[2],dimarry[3],format=float,start=0,step=0)
for(i=1;i<=nspecs;i+=1){
strc=struct()
strc.data=arry[i]
strc.label="junk"
strc.xaxis=axeis
strc.shortlabel="shortjunk"
strc.id=0
fin1=sma(avearry,strc,wave1=wayve1,wave2=wayve2)
fspecs[i]=fin1.modeled
}
rtnstruc=struct()
rtnstruc.norm=fspecs
rtnstruc.ave=avg(fspecs,axis=xy)
rtnstruc.stddev=stddev(fspecs,axis=xy)
return(rtnstruc)
}
define reform_speclib(tes73,from,to) {
if($ARGC==0) {
printf("\n")
printf("Prepare a library from speclib.asu.edu for use with sma()\n")
printf("$1 = hdf downloaded from the spectral library tool\n\n")
printf("Optional:\n")
printf("tes = 1 crop to TES surface sensing channels only (73-point spectrum) (Default is 0)\n\n")
printf("from = direction to translate from (Default is \"y\")\n")
printf("to = direction to translate to (Default is \"x\")\n")
printf("c.edwards 8/5/2010\n\n")
return(null)
}
speclib=$1
if(dim(speclib.data)[1]==1) {
if(HasValue(from)==0) from="y"
if(HasValue(to)==0) to="x"
} else {
if(HasValue(from)==0) from="x"
if(HasValue(to)==0) to="x"
}
for(i=1;i<=length(speclib);i+=1) {
form=format(speclib[i])
if(form!="STRUCT" && form!="STRING" && form!="TEXT") {
speclib[i]=translate(speclib[i],from,to)
}
}
speclib.group=speclib.category
speclib.label=speclib.sample_name+" "+speclib.sample_id
speclib.shortlabel=speclib.sample_name
if(HasValue(tes73)==1) {
#crop to TES surface sensing channels only
speclib.xaxis=cat(speclib.xaxis[,,9:35],speclib.xaxis[,,65:110],axis=z)
speclib.data=cat(speclib.data[,,9:35],speclib.data[,,65:110],axis=z)
}
return(speclib)
}
define irf_ri(bb1, bb2, t1, t2, inst, xaxis, irf, noise_free, alice, riw1, riw2, instT, instdT) {
if(HasValue(bb1) ==0) {
printf(" Computes instrument response function (irf) and instrument radiance (ri) using\n")
printf(" two input blackbody spectra and temperatures. (Optionally uses 1 bb and an input irf)\n")
printf(" Usage: irf = irf_ri(bb1=spec1, t1=temp1, bb2=spec2, t2=temp2, inst='inst' [irf][xaxis=xaxis][noise_free=1][riw1][riw2][instT][instdT])\n")
printf(" t1 and t2 are in K\n")
printf(" Instruments supported: lab1, lab2, tes, tes5, tes73, mtes, themis, aster, tims \n")
printf(" [irf = spec] use with 1 blackbody (bb1 and t1) and a pre-existing irf\n")
printf(" [xaxis=xaxis] use xaxis instead of 'inst'\n")
printf(" Optional (for noise_free only)\n")
printf(" [noise_free = int] 0=no noise_free, 1=fit_bb noise_free, 2=fit diff bb noise_free (Default=0)\n")
printf(" [riw1 = f] wave1 for fit_bb range (default = 300)\n")
printf(" [riw2 = f] wave2 for fit_bb range (default = 300)\n")
printf(" [instT = f] set middle instrument temperature in fit_bb\n")
printf(" [instdT = f] set deviation around instrument temperature in fit_bb\n")
printf(" \n")
printf(" Ex: irf = irf_ri(bb1 = a.warmbb, bb2 = a.hotbb, t1 = ctok(a.warmbbt), t2 = ctok(a.hotbbt), inst='lab2')\n")
printf(" irf = irf_ri(bb1 = a.warmbb, bb2 = a.hotbb, t1 = ctok(a.warmbbt), t2 = ctok(a.hotbbt), inst='lab2', noise_free=1)\n")
printf(" irf = irf_ri(bb1 = a.warmbb, t1 = ctok(a.warmbbt), irf=irf_ri.irf, inst='lab2')\n")
printf("Returns .irf and .ri regardless of method used (e.g normal or noise_free)\n")
printf("p. christensen 1/20/2011\n")
return(0)
}
struc = struct()
if(HasValue(noise_free)==0) noise_free=0
# do initial tests for valid instrument or xaxis
if(HasValue(inst)) {
# user did specify an 'inst'
# test for valid values of inst
if(inst == "lab1" || inst == "lab2" || inst == "lab3" || inst == "tes" || inst == "tes5" || inst == "tes73" || inst == "mtes" || inst == "themis" || inst == "aster" || inst =="tims") {
# make the xaxis
xaxis = make_band(inst= inst)
struc.xaxis = xaxis
nbands = dim(xaxis)[3]
} else {
printf("not a valid instrument\n")
return(0)
}
} else {
# user did not specify an 'inst'
if(HasValue(xaxis)==0) {
printf("No instrument or xaxis specified\n")
return(0)
} else {
# no inst sent in, but do have an xaxis - assume it is a spectrometer
inst="spectrometer"
struc.xaxis = xaxis
}
}
struc.inst = inst
# do blackbody and temperature tests
if(HasValue(bb1)==0) {
printf("must send in at least 1 blackbody cal spectrum (and it should be in 'bb1'\n")
return(0)
} else {
lenbb1 = dim(bb1)[3]
if(HasValue(t1) == 0) {
printf("must send in at least 1 blackbody temperature (and it should be in t1)\n")
return(0)
} else {
# warn user to make sure temp is in kelvin
if(t1<200) {
printf("T1 seems low - make sure you input T in Kelvin\n")
#t1=ctok(t1)
}
struc.t1 = t1
# compute radiance of blackbody at temp t1
r1= bbr(xaxis, t1)
}
}
if(HasValue(bb2)==0) {
if(HasValue(irf) == 0) {
printf("if only send in 1 blackbody spectrum, must send in irf\n")
return(0)
}
} else {
lenbb2 = dim(bb2)[3]
if(lenbb2 != lenbb1) {
printf("length of bb1 spectrum not the same as bb2 spectrum\n")
return(0)
}
if(HasValue(t2)==0) {
printf("must send in second blackbody cal temperature\n")
return(0)
} else {
# warn user to make sure temp is in kelvin
if(t2<200) {
printf("T2 seems low - make sure you input T in Kelvin\n")
#t2 = ctok(t2)
}
struc.t2 = t2
# compute radiance of blackbody at temp t2
r2= bbr(xaxis, t2)
}
}
# test for correct sizes
lenxaxis = dim(xaxis)[3]
if(lenxaxis != lenbb1) {
printf("length of xaxis for this instrument and length of bb1 don't match\n")
return(0)
}
# compute instrument response function (irf)
if(HasValue(irf) == 0) {
irf = (bb2-bb1) / (r2 - r1)
}
# compute instrument radiance (ri)
ri = r1 - (bb1/irf)
if(noise_free == 0) {
# don't do the noise-free method
noise_free=0
struc.irf = irf
struc.ri = ri
# determine instrument temperture in default mode, even in not doing noise-free ri method
struc.noise_free_method = "none"
struc.inst_temp_method = "none"
} else if(noise_free==1 || noise_free==2){
struc.orig={}
struc.orig.ri=ri
struc.orig.irf=irf
# Compute noise free ri by fitting Planck function(s) to ri to get a noise-free ri
# and then compute a new irf using the noise-free ri with the average of the irf's
# computed from the two blackbody spectra
# the 'fit a library of bb's to ri' method
# this is the default (normal/appropriate) noise-free method
# set wavenumber range to fit over (300-2500 is default range)
if(HasValue(riw1)==0) {
riw1=300
}
if(HasValue(riw2)==0) {
riw2=2500
}
# fit a library of Planck functions to the radiance
if(noise_free==1) {
if(HasValue(instT)!=0 && HasValue(instdT)!=0) {
# use instT and instdT modes (see fit_bb documentation)
ri_struc = fit_bb(ri, xaxis, wave1=riw1, wave2=riw2, instT=instT, instdT=instdT)
struc.instT = instT
struc.instdT = instdT
} else {
# normal mode
ri_struc = fit_bb(ri, xaxis, type='inst', wave1=riw1, wave2=riw2)
}
} else if(noise_free==2) {
if(HasValue(instT)!=0 && HasValue(instdT)!=0) {
# use instT and instdT modes (see fit_bb documentation)
ri_struc = fit_bb(ri, xaxis, wave1=riw1, wave2=riw2, instT=instT, instdT=instdT, diffbb=1)
struc.instT = instT
struc.instdT = instdT
} else {
# normal mode
ri_struc = fit_bb(ri, xaxis, type='inst', wave1=riw1, wave2=riw2, diffbb=1)
}
}
nfri = ri_struc.modeled
# now go back and compute a noise-free irf
# use both blackbodies to determine irf,and then take the average
# this reduces the noise in the irf by sqrt(2)
irf1 = bb1 / (r1 - nfri)
irf2 = bb2 / (r2 - nfri)
nfirf=(irf1+irf2)/2.
# load structure
struc.irf = nfirf
struc.ri = nfri
struc.irf1 = irf1
struc.irf2 = irf2
if(noise_free==1) {
struc.noise_free_inst_temp = ri_struc.stats.avgtemp
struc.noise_free_method = "fit_bb"
} else if (noise_free==2) {
struc.noise_free_method = "fit_diffbb"
}
struc.riw1=riw1
struc.riw2=riw2
} else if (noise_free==3) {
# This version is for testing only to compare with Alice's version used in emcal
# Do not use this option !!!!
# Mimic Alice Baldridge's approach used in emcal
# do a real simple version - find ave_t from middle 1/3 of spectrum and use that
# to compute the radiance from the Planck function
bt = rad2tb2(ri, xaxis=xaxis)
nz=dim(bt)[3]
z1=int(nz*.1)
z2=int(nz*.26)
avet=avg(bt[,,z1:z2])
nfri = tb2rad2(avet, xaxis=xaxis)
struc.ri = nfri
struc.irf = irf
struc.ave_t_w1 = xaxis[,,z1]
struc.ave_t_w2 = xaxis[,,z2]
struc.noise_free_inst_temp = avet
struc.noise_free_method = "alice"
}
return(struc)
}
define cal_rad(spec, irf, ri, inst, xaxis) {
if(HasValue(spec) == 0) {
printf(" Compute calibrated radiance\n")
printf(" Usage: rad = cal_rad(spec=radiance_spectrum, irf=irf, ri=ri, inst='inst' [or xaxis=xaxis])\n")
printf(" Use inst = 'inst' mode if standard instrument, or send in xaxis\n")
printf(" Instruments supported: lab1, lab2, tes, tes5, tes73, mtes, themis, aster, tims\n")
printf(" Ex: rad = cal_rad(spec = a.data, irf = irf_ri.irf, ri = irf_ri.ri, inst='lab2')\n")
printf(" rad = cal_rad(spec = a.data, irf = irf_ri.irf, ri = irf_ri.ri, xaxis=a.xaxis)\n")
printf(" p. christensen 1/20/2011\n")
return(0)
}
struc = struct()
if(HasValue(spec) == 0) {
printf("no spectra sent in\n")
return(0)
}
if(HasValue(irf) == 0) {
printf("no instrument response function (irf) sent in\n")
return(0)
}
if(HasValue(ri) == 0) {
printf("no instrument radiance (ri) sent in\n")
return(0)
}
if(HasValue(inst) == 0) {
# user did not specify an 'inst' - must then provide an xaxis
if(HasValue(xaxis)==0) {
printf("No instrument or xaxis specified\n")
return(0)
} else {
# no inst sent in, but do have an xaxis - assume it is a spectrometer
inst = "spectrometer"
struc.xaxis = xaxis
}
} else {
# user did specify an 'inst' - test for valid values of inst
if(inst == "lab1" || inst == "lab2" || inst == "lab3" || inst == "tes" || inst == "tes5" || inst == "tes73" || inst == "mtes" || inst == "themis" || inst == "aster" || inst =="tims") {
# make the xaxis
xaxis = make_band(inst= inst)
struc.xaxis = xaxis
nbands = dim(xaxis)[3]
} else {
printf("not a valid instrument\n")
return(0)
}
}
struc.inst = inst
# test for correct sizes
lenirf = dim(irf)[3]
lenri = dim(ri)[3]
lenxaxis = dim(xaxis)[3]
if(lenxaxis != lenirf || lenxaxis != lenri || lenirf != lenri) {
printf("length of xaxis for this instrument, length of irf, and/or length of ri don't match\n")
return(0)
}
# compute calibrated radiance
radiance = (spec/irf) + ri
struc.radiance = radiance
return(struc)
}
define emissivity(inst, xaxis, wave1, wave2, filter, b1, b2, max_emiss, max_emiss_low, downwelling_e, downwelling_t, downwelling_rad, dehyd, toffset) {
# compute emissivity from calibrated spectral radiance
# resurrected - prc 12/15/2010 during Fall AGU. Name changed to 'emissivity3' (Changed back to emissivity2 1/30/2011)'
# modified from themis_emissivity prc 12/5/08
# p. christensen 2/18/02
# returns input structure with emissivity and maximum brightness temperature
# normally run this function after geometric registration has been done to align bands
if ($ARGC == 0) {
printf (" \n")
printf (" Generic script to compute emissivity from standard calibrated IR spectral radiance datasets\n")
printf (" \n")
printf (" usage: e = emissivity(radiance, inst=[lab1, lab2, tes, tes5, mtes, themis, aster, tims], [band_list]\n")
printf (" [wave1][wave2][b1][b2][filter]\n")
printf (" [max_emiss][max_emiss_low][downwelling_e][downwelling_t][downwelling_rad])\n")
printf (" returns structure with emissivity (emissivity), target_temperature (maxbtemp), and parameters used\n")
printf (" Instruments supported: lab1, lab2, tes, tes5, mtes, themis, aster, tims \n")
printf (" \n")
printf (" [downwelling_t=f] temperature of downwelling radiance (e.g. environmental chamber)\n")
printf (" [downwelling_e=f] emissivity of downwelling radiance (e.g. environmental chamber)(default=1.)\n")
printf (" [downwelling_rad=spec] spectrum of downwelling radiance\n")
printf (" [dehyd = 1] use dehy2 function\n")
printf (" [filter = n] filter size for determining max brightness temperature \n")
printf (" [max_emiss = f] optional maximum emissivity (e.g. 0.98) (default = 1.) \n")
printf (" [max_emiss_low = f] optional maximum emissivity used for low-T calc (for TES) (default = 1.) \n")
printf (" THEIMS: band_list is required (n,1,1) array of the n band numbers contained in the input radiance array)\n")
printf (" spectrometers: [wave1 = n] optional start wavenumber for brightness temperature calc (each has default) \n")
printf (" spectrometers: [wave2 = n] optional end wavenumber for brightness temperature (each has default)\n")
printf (" broadband: [b1 = n] optional start band for brightness temperature calculation\n")
printf (" broadband: [b2 = m] optional end band for brightness temperature calculation\n")
printf (" \n")
printf (" THEMIS: Default uses Band 3 through Band 9 to determine maximum brightness temp for 10-band image\n")
printf (" THEMIS: Default uses image planes 1-2 to determine maximum brightness temp for 3-band image (assumes Bands 4, 9, 10)\n")
printf (" \n")
printf (" \n")
printf (" examples: e = emissivity(rad, inst='mtes')\n")
printf (" e = emissivity(themis=1, a.spectral_qube.data, a.spectral_qube.band_bin.band_bin_band_number)\n")
printf (" (where a is RDR structure loaded using davinci 'load_pds' function)\n")
printf (" \n")
printf (" e = emissivity(themis=1, a.spectral_qube.data, a.spectral_qube.band_bin.band_bin_band_number)\n")
printf (" e = emissivity(themis=1, a.spectral_qube.data, a.spectral_qube.band_bin.band_bin_band_number, max_emiss = 0.98)\n")
printf (" e = emissivity(themis=1, rad, 1//2//3//4//5//6//7//8//9//10, b1 = 4, b2 = 8)\n")
printf (" e = emissivity(themis=1, rad, band_list)\n")
printf (" \n")
printf (" e = emissivity(a.radiance, inst='lab2', downwelling_t = ctok(a.envtemp))\n")
printf (" \n")
printf (" Notes: For THEMIS and other imagers should only be done after geometric registration. \n")
printf (" Function now sets radiance values <0. to 0. using: rad[where(rad<0.)] = 0. \n")
printf (" \n")
printf (" Generic version: p. christensen 12/08\n")
printf (" THEMIS version: p. christensen 4/02-4/03\n")
printf (" Mini-TES version: p. christensen 1/04-9/04\n")
return(0)
}
rad = $1
size=dim(rad)
struc = struct()
# check for xaxis, rather than inst
if(HasValue(inst) == 0) {
# no inst sent in
if(HasValue(xaxis)==0) {
printf("No inst or xaxis sent in - sorry\n")
return(0)
}
inst = 'spectrometer'
xaxis = xaxis
}
######## Step 1 - Step up parameters *************************
# check for spectrometer or broadband
if(inst=='lab1' || inst=='lab2' || inst=='lab3' || inst=='tes' || inst=='tes5' || inst=='mtes' || inst=='spectrometer') {
# spectrometers
if(inst=='lab1' || inst=='lab2' || inst=='lab3') {
# ASU lab spectrometers
# make xaxis
xaxis = make_band(inst=inst)
nbands = dim(xaxis)[3]
# set parameters for target temperature determination
# set default wavenumber range over which to find maximum brightness temperature
if(HasValue(wave1) == 0) {
wave1 = 500
}
if(HasValue(wave2) == 0) {
wave2 = 1700
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
max_emiss = 1.
}
if(HasValue(max_emiss_low) == 0) {
max_emiss_low = max_emiss
}
# threshold temperature and wavenumber range for
# low vs full wavenumber range to determine brightness temp
threshold_t_cold = 160.
threshold_t_warm = 170.
w1_cold = 450
w2_cold = 900
# set size of filter used to filter brightness temperature
if(HasValue(filter) == 0) {
filter = 3
}
# set up for CO2-ignore region
co2chan = 0
co2lowchan = 0
co2highchan = 0
# set up downwelling radiance
if(HasValue(downwelling_t) == 0) {
downwelling_t = 0.
}
if(HasValue(downwelling_e) == 0) {
downwelling_e = 1.
}
if(HasValue(downwelling_rad) == 0) {
downwelling_rad = 0.
}
} else if(inst=='tes') {
# from TES Data Processing User's Guide - 2006 version
# set parameters for target temperature determination
# set default wavenumber range over which to find maximum brightness temperature
xaxis = make_band(inst = "tes")
nbands = dim(xaxis)[3]
if(HasValue(wave1) == 0) {
wave1 = 300
}
if(HasValue(wave2) == 0) {
wave2 = 1350
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
max_emiss = 1.
}
if(HasValue(max_emiss_low) == 0) {
# TES processing sets max emissivity for low-T to 0,97
max_emiss_low = 0.97
}
# threshold temperature and wavenumber range for
# low vs full wavenumber range to determine brightness temp
threshold_t_cold = 215.
threshold_t_warm = 225.
w1_cold = 300
w2_cold = 500
# set size of filter used to filter brightness temperature
if(HasValue(filter) == 0) {
filter = 7
}
# set up for CO2-ignore region
# TES calibration excluded the region from '500 to 800 cm-1' (TES Data
# Processing User's Guide)
# modified from Mini-TES version to give correct index
# set up to be 500 to 800 cm-1
co2chan = maxchan(int(xaxis - 667) == 0)
co2lowchan = co2chan - 15
co2highchan = co2chan + 12
# set up downwelling radiance
downwelling_t = 0.
downwelling_e = 0.
downwelling_rad = 0.
} else if(inst=='tes5') {
# set parameters for target temperature determination
# set default wavenumber range over which to find maximum brightness temperature
xaxis = make_band(inst="tes5")
nbands = dim(xaxis)[3]
if(HasValue(wave1) == 0) {
wave1 = 300
}
if(HasValue(wave2) == 0) {
wave2 = 1350
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
max_emiss = 1.
}
if(HasValue(max_emiss_low) == 0) {
# TES processing sets max emissivity for low-T to 0,97
max_emiss_low = 0.97
}
# threshold temperature and wavenumber range for
# low vs full wavenumber range to determine brightness temp
threshold_t_cold = 215.
threshold_t_warm = 225.
w1_cold = 300
w2_cold = 500
# set size of filter used to filter brightness temperature
if(HasValue(filter) == 0) {
filter = 7
}
# set up for CO2-ignore region
# TES calibration excluded the region from '500 to 800 cm-1' (TES Data
# Processing User's Guide)
# noel's version
# modified from Mini-TES version to give correct index
# set up to be 500 to 800 cm-1
co2chan = maxchan(int(xaxis - 667) == 0)
co2lowchan = co2chan - 31
co2highchan = co2chan + 25
# set up downwelling radiance
downwelling_t = 0.
downwelling_e = 0.
downwelling_rad = 0.
} else if(inst=='mtes') {
# set parameters for target temperature determination
# set default wavenumber range over which to find maximum brightness temperature
xaxis = make_band(inst = "mtes")
nbands = dim(xaxis)[3]
if(HasValue(wave1) == 0) {
wave1 = 500
}
if(HasValue(wave2) == 0) {
wave2 = 1400
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
max_emiss = 1.
}
if(HasValue(max_emiss_low) == 0) {
max_emiss_low = max_emiss
}
# threshold temperature and wavenumber range for
# low vs full wavenumber range to determine brightness temp
threshold_t_cold = 220.
threshold_t_warm = 230.
w1_cold = 450
w2_cold = 900
# set size of filter used to filter brightness temperature
if(HasValue(filter) == 0) {
filter = 7
}
# set up for CO2-ignore region
# noel's version
# this is what is used in PRC's MER Mini-TES calibration
# modified from Mini-TES version to give correct index
# set up to be 500 to 800 cm-1
co2chan = maxchan(int(xaxis - 669) == 0)
co2lowchan = co2chan - 10
co2highchan = co2chan + 10
# set up downwelling radiance
downwelling_t = 0.
downwelling_e = 0.
downwelling_rad = 0.
} else if(inst=='spectrometer') {
# use lab2 default values
if(HasValue(wave1) == 0) {
wave1 = 500
}
if(HasValue(wave2) == 0) {
wave2 = 1700
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
max_emiss = 1.
}
if(HasValue(max_emiss_low) == 0) {
max_emiss_low = max_emiss
}
# threshold temperature and wavenumber range for
# low vs full wavenumber range to determine brightness temp
threshold_t_cold = 160.
threshold_t_warm = 170.
w1_cold = 450
w2_cold = 900
# set size of filter used to filter brightness temperature
if(HasValue(filter) == 0) {
filter = 3
}
# set up for CO2-ignore region
co2chan = 0
co2lowchan = 0
co2highchan = 0
# set up downwelling radiance
if(HasValue(downwelling_t) == 0) {
downwelling_t = 0.
}
if(HasValue(downwelling_e) == 0) {
downwelling_e = 1.
}
if(HasValue(downwelling_rad) == 0) {
downwelling_rad = 0.
}
}
######## Step 2 - Determine target temperature ##################
struc.xaxis=xaxis
# compute brightness temperature
# scale radiance to maximum emissivity (default = 1.)
tb = btemp(xaxis, rad*1./max_emiss)
# compute target (kinetic) temperature
# copy brightness temperture to work array
t1 = tb
# mask out CO2 region if desired
if(co2lowchan == 0 && co2highchan == 0) {
# do nothing if neither CO2 range set
} else {
# zero out CO2 region for finding TB
t1[,,co2lowchan:co2highchan] = 0.
}
# find maximum brightness temperatue
# first step - use full wavenumber range
# set values outside wavenumber range used to find maximum brightness temp to 0.
t1[where(xaxis < wave1)] = 0.
t1[where(xaxis > wave2)] = 0.
# filter brightness temperature to reduce noise
kernel = create(1,1,filter,start=1, step=0)
tfilt1 = convolve(t1, kernel, 1)
#tfilt1 = boxfilter(t1, filter)
# find maximum brightness temperature
max_t1 = max(tfilt1, axis=z)
nx = dim(tfilt1)[1]
ny = dim(tfilt1)[2]
pos_t1 = create(nx, ny, 1, format=int)
for(i=1; i<=nx; i+=1) {
for(j=1; j<=ny; j+=1) {
pos_t1[i,j] = maxpos(tfilt1[i,j])[3]
}
}
# second step - use cold-temperature wavenumber range
if(inst=='tes' || inst=='tes5') {
if(max_emiss == max_emiss_low) {
# don't do unnecessary work if emissivity values are the same
t2 = tb
} else {
t2 = btemp(xaxis, rad*1./max_emiss_low)
}
} else {
# this was the algorithm for mini-TES
t2 = tb
}
# mask out CO2 region if desired
if(co2lowchan == 0 && co2highchan == 0) {
# do nothing if neither CO2 range set
} else {
# zero out CO2 region for finding TB
#### this step was not done in original mtes script (emissivity()) prc 2/5/09
t2[,,co2lowchan:co2highchan] = 0.
}
# mask out wavenumber region exclude for cold case
t2[where(xaxis < w1_cold)] = 0.
t2[where(xaxis > w2_cold)] = 0.
# filter brightness temperature to reduce noise
tfilt2 = convolve(t2, kernel, 1)
#tfilt2 = boxfilter(t2, filter)
# find maximum brightness temperatue
max_t2 = max(tfilt2, axis=z)
pos_t2 = create(nx, ny, 1, format=int)
for(i=1; i<=nx; i+=1) {
for(j=1; j<=ny; j+=1) {
pos_t2[i,j] = maxpos(tfilt2[i,j])[3]
}
}
# loop through array - check each point separately
maxbtemp = max_t1 * 0.
nx = dim(maxbtemp)[1]
ny = dim(maxbtemp)[2]
for(i=1; i<=nx; i+=1) {
for(j=1; j<=ny; j+=1) {
if(max_t1[i,j] > threshold_t_warm) {
# this was a warm target
maxbtemp[i,j] = max_t1[i,j]
} else if (max_t2[i,j] < threshold_t_cold) {
# this was a cold target
maxbtemp[i,j] = max_t2[i,j]
} else {
# make smooth transition around threshold_t
maxbtemp[i,j] = (max_t1[i,j] + max_t2[i,j]) / 2.
}
}
}
# compute radiance of maximum brightness temperature
rad_bb = rad * 0.
for(j=1; j<= nx; j+=1) {
for(k=1; k<= ny; k+=1) {
if(HasValue(toffset)) {
printf("offseting target temperature by %.2f\n", toffset)
bt = maxbtemp[j,k,]+toffset
} else {
bt = maxbtemp[j,k,]
}
rad_bb[j,k,] = bbr(xaxis, bt)
#rad_bb[j,k,] = bbr(xaxis, maxbtemp[j,k,])
}
}
######## compute emissivity ##################
# include downwelling radiance if desired
if(downwelling_t == 0 && downwelling_rad == 0) {
# no downwelling radiance
printf("no downwelling radiance\n")
emiss = rad / rad_bb
} else {
# there is downwelling radiance
printf("doing downwelling radiance\n")
# compute downwelling radiance
if(downwelling_rad == 0.) {
downwelling_rad = downwelling_e * bbr(clone(xaxis,x=dim(downwelling_t)[1],y=dim(downwelling_t)[2]), downwelling_t)
}
emiss = (rad - downwelling_rad) / (rad_bb - downwelling_rad)
}
######## remove atmospheric water bands (mostly for lab measurements)
if(HasValue(dehyd)) {
emiss = dehyd2(emiss, xaxis)
struc.dehyd = dehyd
} else {
struc.dehyd = 0
}
# set bad values to 0.
emiss[where(rad<=0.)]=0.
# add items to structure that are unique to spectrometer
# keep mtes naming convention
struc.wave1 = wave1
struc.wave2 = wave2
struc.w1_cold = w1_cold
struc.w2_cold = w2_cold
struc.threshold_t_cold = threshold_t_cold
struc.threshold_t_warm = threshold_t_warm
struc.filter = filter
struc.co2chan = co2chan
struc.co2lowchan = co2lowchan
struc.co2highchan = co2highchan
struc.tb = tb
struc.tfilt1 = tfilt1
struc.tfilt2 = tfilt2
struc.max_t1 = max_t1
struc.max_t2 = max_t2
struc.pos_t1 = pos_t1
struc.pos_t2 = pos_t2
struc.rad_bb = rad_bb
struc.max_emiss_low = max_emiss_low
} else {
######## do broadband instruments ####################
# broadband instrument
# none of the broadband instruments compute downwelling radiance correction
downwelling_t = 0.
downwelling_e = 0.
downwelling_rad = 0.
if(inst=='aster') {
# assume all 5 bands are sent
if(size[3] != 5) {
printf("Not all 5 ASTER bands sent in - sorry\n")
return(0)
}
band_list = 1//2//3//4//5
if(HasValue(b1)==0) {
b1=1
}
if(HasValue(b2)==0) {
b2 = 5
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
# set to standard value used by ASTER team (prc - check 1/6/09)
max_emiss = 0.97
}
} else if(inst=='tims') {
# assume all 6 bands are sent
if(size[3] != 6) {
printf("Not all 6 TIMS bands sent in - sorry\n")
return(0)
}
band_list = 1//2//3//4//5//6
if(HasValue(b1)==0) {
b1=1
}
if(HasValue(b2)==0) {
b2 = 6
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
# set to standard value used by ASTER team (prc - check 1/6/09)
max_emiss = 0.97
}
} else if(inst=='modis') {
} else {
# default is themis
if($ARGC == 1) {
# no band list - check to make sure correct number of bands
if(size[3] != 10 && size[3] != 3) {
printf("Problem - incorrect number of bands (%d) without a band list\n", size[3])
return(0)
} else {
if(size[3] == 10) {
# sent in full image
band_list = 1//2//3//4//5//6//7//8//9//10
# set bands to use to determine max brightness temperature
if(HasValue(b1)==0) {
b1=3
}
if(HasValue(b2)==0) {
b2 = 9
}
} else {
# set up for normal 3-band nighttime image
band_list = 3//8//9
# set bands to use to determine max brightness temperature
if(HasValue(b1)==0) {
b1 = 1
}
if(HasValue(b2)==0) {
b2 = 2
}
}
}
} else if($ARGC == 2) {
# sent in a band list
band_list = $2
# set bands to use to determine max brightness temperature
if(HasValue(b1)==0) {
b1 = 1
}
if(HasValue(b2)==0) {
b2 = dim($1)[3]
}
} else {
# a problem
printf("Problem - incorrect number of arguments (%d)\n", $ARGC)
}
# set maximum emissivity values
if(HasValue(max_emiss) == 0) {
max_emiss = 1.
}
}
# set rad values < 0. to 0.
rad[where(rad<0.)] = 0.
# compute brightness temperature - adjust measured radiance assuming to corresponds to a
# maximum emissivity (default = 1.)
btemp = rad2tb2( (rad/max_emiss), band_list, inst=inst)
btemp[where(btemp<100.)] = 0.
# compute emissivity of scene
# find maximum brightness temperature - assume to be kinetic temperature
printf("\nfinding max brightness temperature using bands %d to %d, maximum emissivity = %.2f\n\n", b1, b2,max_emiss)
maxbtemp = max(btemp[,,b1:b2], axis = z)
emiss = btemp * 0.
rad_max_btemp = btemp * 0.
# compute radiance of the maximum brightness temp for all bands
rad_max_btemp = tb2rad2(maxbtemp, inst=inst)
# compute emissivity - divide by greybody
emiss = rad / rad_max_btemp
struc.band_list = band_list
struc.band1 = b1
struc.band2 = b2
struc.btemp = btemp
}
struc.downwelling_e = downwelling_e
struc.downwelling_t = downwelling_t
struc.downwelling_rad = downwelling_rad
struc.max_emiss = max_emiss
struc.emissivity = emiss
struc.target_temperature = maxbtemp
#struc.maxbtemp = maxbtemp
return(struc)
}
define rad2tb2(inst, max_emiss, lab1, lab2, lab3, tes, tes5, tes73, mtes, themis, aster, tims, modis, xaxis) {
if ($ARGC == 0) {
printf (" \n")
printf (" General routine to convert spectral radiance to temperature \n")
printf (" For spectrometers units the are W cm-2 sr-1 /cm-1\n")
printf (" For broadband radiometers the units are W cm-2 sr-1 micron-1) \n")
printf (" Temperature array returned is in same order as wavelength or wavenumber\n")
printf (" of instrument (e.g. ascending wavenumber or wavelength) \n")
printf (" Default instrument is THEMIS\n")
printf (" \n")
printf (" usage: temp = rad2tb2(radiance, inst=[lab1,lab2, lab3, tes, tes5, mtes, themis, aster, tims, modis] [max_emiss])\n")
printf (" Input 1 radiance and optional instrument (default is THEMIS)\n")
printf (" or: temp = rad2tb2(rad_array, inst='tes', 'themis', 'aster', etc)\n")
printf (" Input one radiance and instrument\n")
printf (" Returns temp[1,1,nbands]\n")
printf (" \n")
printf (" or: temp = rad2tb2(rad_array, inst=themis, aster, etc))\n")
printf (" Input array of radiances in nbands: rad_array[nx, ny, nbands] \n")
printf (" Dimension of nbands must match instrument \n")
printf (" Returns temp[nx, ny, nbands]\n")
printf (" \n")
printf (" or: temp = rad2tb2(rad_array, bandlist, inst='themis', 'aster', etc]))\n")
printf (" Input array of radiances in partial set of 1 or more bands: rad_array[nx, ny, ibands] \n")
printf (" Broadband instruments only\n")
printf (" Dimension of ibands must match # of bands in bandlist \n")
printf (" Example: temp = rad2tb2(image, cat(3,5,7,x), inst=themis) \n")
printf (" Example: temp = rad2tb2(cat(.00041, .00042, .00043,z), cat(4,5,6,x), inst='themis') \n")
printf (" Returns temp[nx, ny, ibands]\n")
printf (" \n")
printf (" [max_emiss = f] Set emissivity to value other than 1.0 (default)\n")
printf (" \n")
printf (" Note: Reads in appropriate radiance-to-temperature look-up table\n")
printf (" \n")
return(0)
}
# modified to include both 'tes=1' and 'inst="tes"' modes. prc `1/28/2011.
# changed from rad2tb2 to inst='lab1' mode, prc 12/16/2010
# For spectrometers this routine accepts:
# 1 radiance or an array of rads (z dim must equal # bands (e.g. 143 for TES))
# For broadband instrument this routine accepts:
# 1 radiance, an array of radiances, an array of radiances in all bands for the instrument,
# or an array of radiances in a subset of bands with a list of bands
# p. christenen 11/15/08 - derived from tb2rad2
# and tbtorad - p. christensen 10/2/01
if(HasValue(xaxis)) {
inst = 'spectrometer'
} else {
# check for 'old way' (tes=1) and convert to 'new way' (inst="tes")
args=cat("lab1", "lab2", "lab3", "tes", "tes5", "tes73", "mtes", "themis", "aster", "tims", "modis", axis=y)
for(i=1; i<=length(args); i+=1) {
if(HasValue(eval(args[,i]))==1) {
inst = args[,i]
}
}
}
# check for spectrometer or broadband
if(inst=='lab1' || inst=='lab2' || inst=='lab3' || inst=='tes' || inst=='tes5' || inst=='mtes' || inst=='spectrometer') {
# spectrometer
rad = $1
if(HasValue(xaxis)) {
x = xaxis
} else {
x = make_band(inst=inst)
}
nbands = dim(x)[3]
size=dim(rad)
temp = create(size[1], size[2], nbands, format=float)
# loop over x, y elements in input rad array
# function brtemp checks for temps < 0
for(i=1; i<= size[1]; i+=1) {
for(j=1; j<= size[2]; j+=1) {
if(size[3] == 1) {
# sent in 1 temp
temp[i,j] = btemp(x, rad[i,j,1])
} else {
# sent in array of rads - 1 for each band
# z dimension must match nbands
if(size[3] != nbands) {
printf("z dimension (%d) of input rad array does not match nbands (%d)\n", size[3], nbands)
return(0)
} else {
temp[i,j] = btemp(x, rad[i,j])
}
}
}
}
return(temp)
}
# read in temp_to_radiance (tem_rad)array made by 'make_temp_rad' for broadband instruments
# temp_rad arrays are dimensioned: [xaxis+nbands, ntemps, 1]
# they contain the wavelength(microns) and nbands of integrated radiance values for each temperature
# default instrument is themis
# default path set up by Chris Edwards for davinci use on multiple platforms
PATH = $DV_SCRIPT_FILES
PATHI = PATH + "/instrument_parameters"
if(inst=='aster') {
temp_rad =read(PATHI+"/temp_rad_aster.vic")
} else if(inst=='tims') {
temp_rad =read(PATHI+"/temp_rad_tims.vic")
} else if(inst=='modis') {
# not done yet
} else if(inst=='themis') {
temp_rad = read(PATHI+'/temp_rad_v4')
} else {
# default is themis
temp_rad = read(PATHI+'/temp_rad_v4')
}
# set up the broadband instruments
nbands = dim(temp_rad)[1] - 1
ntemps = dim(temp_rad)[2]
start_temp = temp_rad[1,1]
end_temp = temp_rad[1,ntemps]
if($ARGC == 1) {
# either 1 rad, an array of radiances, or
# an nx x ny array in nbands, where nbands must match instrument
# no band list
rad = $1
size = dim(rad)
if(size[3] == 1) {
# 1 rad or an array of rads
if(size[1]== 1 && size[2] == 1) {
# correct size for 1 radiance
# clone temperature to match number of bands in temp_rad array
rad_array = clone(rad, 1, 1, nbands)
} else if(size[1] != 1 || size[2] != 1) {
# an array of rads with only 1 band and no list specified
rad_array = clone(rad,1, 1, nbands)
}
} else {
# sent in an array of temps that must be dimensioned [nx, ny, nbands]
if(size[3] != nbands) {
# a problem
printf("incorrect z-size - must match number in instrument\n")
return(0)
} else {
#printf("ok - %d by %d array with correct number of bands %d\n", size[1], size[2], size[3])
rad_array = rad
}
}
# using all the bands in the instrument - set temp_rad_interp to temp_rad
temp_rad_interp = temp_rad
} else if ($ARGC == 2) {
# sent in an array of temperatures in 1 or more bands and specified which band(s)
rad_array = $1
size = dim(rad_array)
bandlist = $2
list_size = dim(bandlist)
# check format of bandlist
if(list_size[2] >1 || list_size[3] > 1) {
printf("bad format for bandlist - bands should be in x; ny and nz should be 1\n")
return(0)
}
nlist = list_size[1]
if(size[3] != nlist) {
# a problem
printf("incorrect z-size - if specifing 1 or more bands, nbands in image must be same as nbands in list\n")
return(0)
}
if(nlist > nbands) {
# a problem
printf("incorrect band choice - higher than number of bands in this instrument\n")
return(0)
}
# test to make sure no band in the list is higher than # of bands
max_list = max(bandlist[,1,1])
if(max_list > nbands) {
# a problem
printf("a band in the list (%d) is higher than the number of bands (%d)\n", max_list, nbands)
return(0)
}
# ok - passed the tests
if(nlist == 1) {
# only using 1 band: move the correct band from temp_rad array into temp_rad_interp
temp_rad_interp = cat(temp_rad[1], temp_rad[1+bandlist], x)
} else {
# sent in a list of bands - move the appropriate bands of temp_rad into temp_rad_interp
temp_rad_interp = create(nlist+1, ntemps, 1, format=float)
temp_rad_interp[1] = temp_rad[1]
for(i=1; i<=nlist; i+=1) {
temp_rad_interp[i+1] = temp_rad[bandlist[i] + 1]
}
}
}
# now do the easy part - interpolate in radiance vs temperature array
nbands_used = dim(temp_rad_interp)[1]-1
# debug mode
#printf("nbands=%d ntemps=%d size[1]=%d size[2]=%d size[3]=%d nbands_used=%d\n", nbands, ntemps, size[1], size[2], size[3], nbands_used)
temp = rad_array * 0.
# scale radiance to max emissivity
if(HasValue(max_emiss) == 0) {
max_emiss = 1.
}
#printf("max emiss = %.2f\n", max_emiss)
rad_array = rad_array / max_emiss
for(i=1; i <= nbands_used; i+=1) {
index = i+1
temp[,,i] = interp(temp_rad_interp[1], temp_rad_interp[index], rad_array[,,i])
}
# clean up to free memory
rad_array = 0.
# final test for temperatures outside range in temp_rad arrays
temp[where(temp < start_temp)] = 0.
temp[where(temp > end_temp)] = 0.
return(temp)
}
define tb2rad2(inst, lab1, lab2, lab3, tes, tes5, tes73, mtes, themis, aster, tims, modis, xaxis) {
if ($ARGC == 0) {
printf (" \n")
printf (" General routine to convert temperature to spectral radiance \n")
printf (" For spectrometers the units the are W cm-2 sr-1 /cm-1\n")
printf (" For broadband radiometers the units are W cm-2 sr-1 micron-1\n")
printf (" Radiance array returned is in same order as input wavelength or wavenumber\n")
printf (" of instrument (e.g. ascending wavenumber or wavelength) \n")
printf (" Default instrument is THEMIS\n")
printf (" \n")
printf (" usage: rad = tb2rad2(temp(K), inst=[lab1, lab2, tes, tes5, mtes, themis, aster, tims, modis])\n")
printf (" Input one temperature and instrument (default is THEMIS)\n")
printf (" inst='lab1' etc - specifies which instrument\n")
printf (" Returns rad[1,1,nbands]\n")
printf (" \n")
printf (" or: rad = tb2rad2(temp_array(K), inst='lab1',etc)\n")
printf (" Input array of temps and instrument: temp_array[nx, ny]\n")
printf (" Returns rad[nx,ny,nbands] \n")
printf (" \n")
printf (" or: rad = tb2rad2(temp_array, bandlist, inst='themis' etc)\n")
printf (" Input array of temps in partial set of 1 or more bands: temp_array[nx, ny, ibands] \n")
printf (" Broadband instruments only\n")
printf (" Dimension of ibands must match # of bands in bandlist \n")
printf (" Example: rad = tb2rad2(image, cat(3,5,7,x)) \n")
printf (" Returns rad[nx, ny, ibands] \n")
printf (" \n")
printf (" Note: Reads in appropriate radiance-to-temperature look-up table\n")
printf (" \n")
return(0)
}
# modified to include both 'tes=1' and 'inst="tes"' modes. prc `1/28/2011.
# changed from tb2rad2 to inst='lab1' mode, prc 12/16/2010
# if user sent in xaxis - assume they didn't also send in an 'inst'
if(HasValue(xaxis)) {
inst = 'spectrometer'
} else {
# check for 'old way' (tes=1) and convert to 'new way' (inst="tes")
args=cat("lab1", "lab2", "lab3", "tes", "tes5", "tes73", "mtes", "themis", "aster", "tims", "modis", axis=y)
for(i=1; i<=length(args); i+=1) {
if(HasValue(eval(args[,i]))==1) {
inst = args[,i]
}
}
}
# For spectrometers this routine accepts:
# 1 temp or an array of temps (z dim must equal # bands (e.g. 143 for TES))
# For broadband instrument this routine accepts:
# 1 temp, an array of temps, an array of temps in all bands for the instrument,
# or an array of temps in a subset of bands with a list of bands
# p. christenen 11/15/08 - derived from tbtorad
# tbtorad - p. christensen 10/2/01
# check for spectrometer or broadband
if(inst=='lab1' || inst=='lab2' || inst=='lab3' || inst=='tes' || inst=='tes5' || inst=='mtes' || inst=='spectrometer') {
# spectrometer
temp = $1
if(HasValue(xaxis)) {
x = xaxis
} else {
x = make_band(inst=inst)
}
nbands = dim(x)[3]
size=dim(temp)
rad = create(size[1], size[2], nbands, format=float)
# loop over x, y elements in input temp array
for(i=1; i<= size[1]; i+=1) {
for(j=1; j<= size[2]; j+=1) {
if(size[3] == 1) {
# sent in 1 temp
rad[i,j] = bbr(x, temp[i,j,1])
} else {
# sent in array of temps - 1 for each band
# z dimension must match nbands
if(size[3] != nbands) {
printf("z dimension (%d) of input temp array does not match nbands (%d)\n", size[3], nbands)
return(0)
} else {
rad[i,j] = bbr(x, temp[i,j])
}
}
}
}
# final test for radiances less than zero
rad[where(rad<0)] = 0.
return(rad)
} else {
# broadband instrument
# read in temp_to_radiance (temp_rad) array made by 'make_temp_rad' for broadband instruments
# temp_rad arrays are dimensioned: [xaxis+nbands, ntemps, 1]
# they contain the wavelength(microns) and nbands of integrated radiance values for each temperature
# default instrument is themis
# default path set up by Chris Edwards for davinci use on multiple platforms
PATH = $DV_SCRIPT_FILES
PATHI = PATH + "/instrument_parameters"
if(inst=='aster') {
temp_rad =read(PATHI+"/temp_rad_aster.vic")
} else if(inst=='tims') {
temp_rad =read(PATHI+"/temp_rad_tims.vic")
} else if(inst=='modis') {
# not done yet
} else if(inst=='themis') {
temp_rad = read(PATHI+'/temp_rad_v4')
} else {
# default is themis
temp_rad = read(PATHI+'/temp_rad_v4')
}
# set up the broadband instruments
nbands = dim(temp_rad)[1] - 1
ntemps = dim(temp_rad)[2]
if($ARGC == 1) {
# either 1 temp, an array of temps, or
# an nx x ny array in nbands, where nbands must match instrument
# no band list
temp = $1
size = dim(temp)
if(size[3] == 1) {
# 1 temp or an array of temps
if(size[1]== 1 && size[2] == 1) {
# correct size for 1 temperature
# clone temperature to match number of bands in temp_rad array
temp_array = clone(temp, 1, 1, nbands)
} else if(size[1] != 1 || size[2] != 1) {
# an array of temps with only 1 band and no list specified
temp_array = clone(temp,1, 1, nbands)
}
} else {
# sent in an array of temps that must be dimensioned [nx, ny, nbands]
if(size[3] != nbands) {
# a problem
printf("incorrect z-size - must match number in instrument\n")
return(0)
} else {
#printf("ok - %d by %d array with correct number of bands %d\n", size[1], size[2], size[3])
temp_array = temp
}
}
# using all the bands in the instrument - set temp_rad_interp to temp_rad
temp_rad_interp = temp_rad
} else if ($ARGC == 2) {
# sent in an array of temperatures in 1 or more bands and specified which band(s)
temp_array = $1
size = dim(temp_array)
bandlist = $2
list_size = dim(bandlist)
# check format of bandlist
if(list_size[2] >1 || list_size[3] > 1) {
printf("bad format for bandlist - bands should be in x; ny and nz should be 1\n")
return(0)
}
nlist = list_size[1]
if(size[3] != nlist) {
# a problem
printf("incorrect z-size - if specifing 1 or more bands, nbands in image must be same as nbands in list\n")
return(0)
}
if(nlist > nbands) {
# a problem
printf("incorrect band choice - higher than number of bands in this instrument\n")
return(0)
}
# test to make sure no band in the list is higher than # of bands
max_list = max(bandlist[,1,1])
if(max_list > nbands) {
# a problem
printf("a band in the list (%d) is higher than the number of bands (%d)\n", max_list, nbands)
return(0)
}
# ok - passed the tests
if(nlist == 1) {
# only using 1 band: move the correct band from temp_rad array into temp_rad_interp
temp_rad_interp = cat(temp_rad[1], temp_rad[1+bandlist], x)
} else {
# sent in a list of bands - move the appropriate bands of temp_rad into temp_rad_interp
temp_rad_interp = create(nlist+1, ntemps, 1, format=float)
temp_rad_interp[1] = temp_rad[1]
for(i=1; i<=nlist; i+=1) {
temp_rad_interp[i+1] = temp_rad[bandlist[i] + 1]
}
}
}
# now do the easy part - interpolate in radiance vs temperature array
nbands_used = dim(temp_rad_interp)[1]-1
printf("nbands=%d ntemps=%d size[1]=%d size[2]=%d size[3]=%d nbands_used=%d\n", nbands, ntemps, size[1], size[2], size[3], nbands_used)
rad = temp_array * 0.
for(i=1; i <= nbands_used; i+=1) {
index = i+1
rad[,,i] = interp(temp_rad_interp[index], temp_rad_interp[1], temp_array[,,i])
}
# clean up to free memory
temp_array = 0.
# final test for radiances less than zero
rad[where(rad<0)] = 0.
return(rad)
}
}
define make_band(inst, cm, wave, full, descend, apod, lab1, lab2, lab3, tes, tes5, tes73, mtes, themis, aster, tims, modis, master) {
# makes wavelength centers (and min and max) in wavelength and wavenumber
# for IR instruments
# instruments supported are lab1, lab2, lab3, tes, tes5, tes73, themis, aster, tims, master
# help section is at the bottom of the code block
# added master to instruments supported. 4/29/11 p. christensen
# modified to include both 'tes=1' and 'inst="tes"' modes. Name changed back to make_band() prc `1/28/2011.
# changed to 'inst= "_"' mode 1/22/2011 prc. name changed to make_band3()
# p. christensen 11/28/08
# default path set up by Chris Edwards for davinci use on multiple platforms
PATH = $DV_SCRIPT_FILES
PATHI = PATH +"/instrument_parameters"
struc = struct()
# do initial tests
# check for 'old way' (tes=1) and convert to 'new way' (inst="tes)
args=cat("lab1", "lab2", "lab3", "tes", "tes5", "tes73", "mtes", "themis", "aster", "tims", "modis", "master", axis=y)
for(i=1; i<=length(args); i+=1) {
if(HasValue(eval(args[,i]))==1) {
inst = args[,i]
}
}
if(HasValue(wave) && HasValue(cm)) {
printf("Can't request both 'wave' and 'cm'\n")
return(0)
}
if(HasValue(full) && HasValue(descend)) {
printf("Please don't request 'descend' in 'full' mode. Keep life simple\n")
return(0)
}
# check the instruments
if(inst == "lab1" || inst == "lab2" || inst == "lab3" || inst == "tes" || inst == "tes5" || inst == "tes73" || inst == "mtes") {
# do the spectrometers
if(HasValue(full) && HasValue(wave)) {
printf("'full' mode only returns default mode - don't use 'wave' for spectrometers or 'descend'\n")
return(0)
}
if(HasValue(cm) == 0 && HasValue(wave) == 0) {
# default for spectrometers is wavenumber
cm = 1
}
if(inst == "tes" || inst == "tes73") {
# borrowed from make_tesx prc 2/3/09
npts = 143
first_pt = 14
# set prime factor to default for single scan (1344; Det. 2 & 5)
nprime = 1344
neon_wavelength = 0.7032e-4
tes_res = 1. / (nprime * neon_wavelength)
# old make_xt2 hardcoded value tes_res = 10.5808820
bandcenter_cm = create(1,1,npts, start = tes_res * first_pt, step = tes_res, format=float)
# bandcenter_cm = make_tesx()
# truncate after 4 decimal places - legacy
bandcenter_cm = bandcenter_cm * 10000.
bandcenter_cm = int(bandcenter_cm)
bandcenter_cm = bandcenter_cm/10000.
nwave = dim(bandcenter_cm)[3]
if(HasValue(apod)) {
# do the approximation to S. Chase's apodization for center detector 2
# Data are from TES II Calibration Report Appendix 11/12/98
# subtract 0.5 to make the slope exactly half that of 5cm-1 case and give
# consistent results with 5cm-1 case and Calib Report Appendix
slope = (5.27 - 0.438) / (nwave-.5)
offset = .438
for(k=1; k<=nwave; k+=1) {
bandcenter_cm[1,1,k] = bandcenter_cm[1,1,k] + ((k-1)* slope + offset)
}
}
#make a 73 point tes spectrum
if(inst == "tes73") {
bandcenter_cm=cat(bandcenter_cm[,,9:35],bandcenter_cm[,,65:110],axis=z)
}
} else if(inst == "tes5") {
npts = 143 * 2
first_pt = 28
# set prime factor to default for double scan (1344*2; Det. 2 & 5)
nprime = 1344 * 2
# tes resolution for 1344 pt fft
neon_wavelength = 0.7032e-4
tes_res = 1. / (nprime * neon_wavelength)
# old make_xt2 hardcoded value tes_res = 10.5808820 / 2.
bandcenter_cm = create(1,1,npts, start = tes_res * first_pt, step = tes_res, format=float)
# bandcenter_cm = make_tesx(scan_len=2)
# truncate after 4 decimal places - legacy
bandcenter_cm = bandcenter_cm * 10000.
bandcenter_cm = int(bandcenter_cm)
bandcenter_cm = bandcenter_cm/10000.
nwave = dim(bandcenter_cm)[3]
if(HasValue(apod)) {
# do the approximation to S. Chase's apodization for center detector 2
# Data are from TES II Calibration Report Appendix 11/12/98
slope = (5.27 - 0.438) / (nwave-1)
offset = .438
for(k=1; k<=nwave; k+=1) {
bandcenter_cm[1,1,k] = bandcenter_cm[1,1,k] + ((k-1)* slope + offset)
}
}
} else if(inst == "mtes") {
# copied from make_mtesx()
npts = 512
start_pt = 35
end_pt = 201
# set wavenumber of first point downlinked (14 or 28 in PROM) #
# set prime factor
nprime = 1024;
laser_wavelength = 0.978
delta_x = (1./(nprime * laser_wavelength))*10000.
mtx = create(npts, 1, 1, format=float)
for(i=1; i<= npts; i+=1) {
# index (i) of 1 = DC term in FFT; index 2 = 9.9853 cm-1; etc
# index 1 = channel 0; etc
mtx[i] = float(i-1) * delta_x
}
# truncate after 4 decimal places
mtx = mtx * 10000.
mtx = int(mtx)
mtx = mtx/10000.
mtx = translate(mtx,x,z)[,,start_pt:end_pt]
bandcenter_cm = mtx
# bandcenter_cm = make_mtesx()
} else if(inst == "lab1") {
# compute the values
# taken from best fit to xaxis spectrum from Nicholet
first_pt = 221.777
# derived from best fit to xaxis spectrum from Nicholet
lab_res = 1.9284983
npts = 923
bandcenter_cm = create(1,1,npts, start = first_pt, step = lab_res, format=float)
# read in the values from a spectrum from the Nicholet
# bandcenter_cm = read(PATHI+"/lab1cmx.vic")
} else if(inst == "lab2") {
# compute the values
# taken from best fit to xaxis spectrum from Nicholet
first_pt = 200.564
# derived from best fit to xaxis spectrum from Nicholet
lab_res = 1.9284983
npts = 1971
bandcenter_cm = create(1,1,npts, start = first_pt, step = lab_res, format=float)
# read in the values from a spectrum from the Nicholet
# bandcenter_cm = read(PATHI+"/lab2cmx.vic")
} else if(inst == "lab3") {
# compute the values
# taken from best fit to xaxis spectrum from Nicholet
first_pt = 380.001
# derived from best fit to xaxis spectrum from Nicholet
lab_res = 1.9284983
npts = 840
bandcenter_cm = create(1,1,npts, start = first_pt, step = lab_res, format=float)
# read in the values from a spectrum from the Nicholet
# bandcenter_cm = read(PATHI+"/lab2cmx.vic")
}
# convert to wavelength in case it is wanted
bandcenter = cm2micron(bandcenter_cm)
# return all values if requested - only do default modes for 'full'
if(HasValue(full)) {
struc.bandcenter = bandcenter
struc.bandcenter_cm = bandcenter_cm
return(struc)
}
if(HasValue(wave)) {
# return wavelength
if(HasValue(descend)) {
# when doing spectrometers, wavelength version is already descending
} else {
# make wavelength into ascending order (default)
bandcenter = reverse_spectrum(bandcenter)
}
return(bandcenter)
} else {
# return wavenumber (default)
if(HasValue(descend)) {
# make wavenumber into descending order
bandcenter_cm = reverse_spectrum(bandcenter_cm)
} else {
# wavelength version is already ascending (default)
}
return(bandcenter_cm)
}
} else if(inst == "themis" || inst == "aster" || inst == "tims" || inst == "modis" || inst == "master") {
# do the broadband instruments
if(HasValue(full) && HasValue(cm)) {
printf("'full' mode only returns default mode - don't use 'cm' for broadband inst. or 'descend'\n")
return(0)
}
if(HasValue(cm) == 0 && HasValue(wave) == 0) {
# default for broadband instruments is wavelength
wave = 1
}
if (inst == "themis") {
# Make 10-point THEMIS wavelength and wavenumber axes
# source THEMIS calibration report
bandcenter=create(1,1,10, format=float)
bandmin=create(1,1,10, format=float)
bandmax=create(1,1,10, format=float)
bandcenter[1,1,1] = 6.78
bandcenter[1,1,2] = 6.7801
bandcenter[1,1,3] = 7.93
bandcenter[1,1,4] = 8.56
bandcenter[1,1,5] = 9.35
bandcenter[1,1,6] = 10.21
bandcenter[1,1,7] = 11.04
bandcenter[1,1,8] = 11.79
bandcenter[1,1,9] = 12.57
bandcenter[1,1,10] = 14.88
# source: P. Christensen analysis of themis_IR_filter_response_norm_v2.davinci
# wavelength is half-power (50%) point of normalized response
bandmin[1,1,1] = 6.277
bandmin[1,1,2] = 6.2775
bandmin[1,1,3] = 7.382
bandmin[1,1,4] = 7.984
bandmin[1,1,5] = 8.756
bandmin[1,1,6] = 9.668
bandmin[1,1,7] = 10.455
bandmin[1,1,8] = 11.265
bandmin[1,1,9] = 12.175
bandmin[1,1,10] = 14.46
# source: P. Christensen analysis of themis_IR_filter_response_norm_v2.davinci
# wavelength is half-power (50%) point of normalized response
bandmax[1,1,1] = 7.285
bandmax[1,1,2] = 7.2855
bandmax[1,1,3] = 8.470
bandmax[1,1,4] = 9.140
bandmax[1,1,5] = 9.950
bandmax[1,1,6] = 10.755
bandmax[1,1,7] = 11.635
bandmax[1,1,8] = 12.325
bandmax[1,1,9] = 12.987
bandmax[1,1,10] = 15.32
} else if(inst == "aster") {
# Make 5-point ASTER wavelength and wavenumber axes
# source: www.science.aster.ersdac.or.jp/en
bandcenter=create(1,1,5, format=float)
bandmin=create(1,1,5, format=float)
bandmax=create(1,1,5, format=float)
bandcenter[1,1,1] = 8.274
bandcenter[1,1,2] = 8.626
bandcenter[1,1,3] = 9.072
bandcenter[1,1,4] = 10.654
bandcenter[1,1,5] = 11.303
# source: P. Christensen analysis of aster_ir_spectral_response_wave.vic
# wavelength is half-power (50%) point of normalized response
bandmin[1,1,1] = 8.105
bandmin[1,1,2] = 8.455
bandmin[1,1,3] = 8.895
bandmin[1,1,4] = 10.325
bandmin[1,1,5] = 11.005
# source: P. Christensen analysis of aster_ir_spectral_response_wave.vic
# wavelength is half-power (50%) point of normalized response
bandmax[1,1,1] = 8.45
bandmax[1,1,2] = 8.800
bandmax[1,1,3] = 9.255
bandmax[1,1,4] = 10.985
bandmax[1,1,5] = 11.595
} else if (inst == "tims") {
# Make 6 point TIMS wavelength and wavenumber axes
# source: PRC analyis of tims.resp files from Elsa Abbot 12/18/08
# Made by 'make_tims_resp' - average of 10 tims.resp files
bandcenter=create(1,1,6, format=float)
bandmin=create(1,1,6, format=float)
bandmax=create(1,1,6, format=float)
bandcenter[1,1,1] = 8.38450
bandcenter[1,1,2] = 8.78470
bandcenter[1,1,3] = 9.18000
bandcenter[1,1,4] = 9.89410
bandcenter[1,1,5] = 10.7344
bandcenter[1,1,6] = 11.6222
# source: P. Christensen analysis of tims_ir_spectral_response_avg_wave.vic
bandmin[1,1,1] = 8.17
bandmin[1,1,2] = 8.58
bandmin[1,1,3] = 9.00
bandmin[1,1,4] = 9.53
bandmin[1,1,5] = 10.29
bandmin[1,1,6] = 11.28
bandmax[1,1,1] = 8.55
bandmax[1,1,2] = 8.95
bandmax[1,1,3] = 9.31
bandmax[1,1,4] = 10.21
bandmax[1,1,5] = 11.18
bandmax[1,1,6] = 11.79
} else if (inst == "modis") {
} else if (inst == "master") {
# thermal ir bands only
# Make 5-point MASTER wavelength and wavenumber axes
# source: c. edwards 4/28/11
bandcenter=create(1,1,10, format=float)
bandmin=create(1,1,10, format=float)
bandmax=create(1,1,10, format=float)
# source: P. Christensen analysis (by finding max of normaized bandpasses)
# of master_ir_spectral_response_avg_wave.vic
bandcenter[1,1,1] = 7.793
bandcenter[1,1,2] = 8.215
bandcenter[1,1,3] = 8.631
bandcenter[1,1,4] = 9.093
bandcenter[1,1,5] = 9.716
bandcenter[1,1,6] = 10.131
bandcenter[1,1,7] = 10.647
bandcenter[1,1,8] = 11.311
bandcenter[1,1,9] = 12.177
bandcenter[1,1,10] = 12.918
# source: P. Christensen hand analysis (by plotting) of master_ir_spectral_response_avg_wave.vic
bandmin[1,1,1] = 7.59
bandmin[1,1,2] = 7.93
bandmin[1,1,3] = 8.44
bandmin[1,1,4] = 8.89
bandmin[1,1,5] = 9.50
bandmin[1,1,6] = 9.93
bandmin[1,1,7] = 10.38
bandmin[1,1,8] = 11.05
bandmin[1,1,9] = 11.91
bandmin[1,1,10] = 12.68
bandmax[1,1,1] = 7.92
bandmax[1,1,2] = 8.40
bandmax[1,1,3] = 8.80
bandmax[1,1,4] = 9.29
bandmax[1,1,5] = 9.92
bandmax[1,1,6] = 10.34
bandmax[1,1,7] = 10.99
bandmax[1,1,8] = 11.72
bandmax[1,1,9] = 12.45
bandmax[1,1,10] = 13.15
} else {
printf("No instrument specified\n")
return(0)
}
# convert to wavenumber in case it is wanted
bandcenter_cm = 10000./bandcenter
bandmin_cm = 10000./bandmin
bandmax_cm = 10000./bandmax
# return all values if requested - only do default modes for 'full'
if(HasValue(full)) {
struc.bandcenter = bandcenter
struc.bandcenter_cm = bandcenter_cm
struc.bandmin = bandmin
struc.bandmin_cm = bandmin_cm
struc.bandmax = bandmax
struc.bandmax_cm = bandmax_cm
return(struc)
}
if(HasValue(cm)) {
if(HasValue(descend)) {
# when doing braodband, wavenumber version is already descending
} else {
# make wavenumber into ascending order (default)
bandcenter_cm = reverse_spectrum(bandcenter_cm)
}
return(bandcenter_cm)
} else {
# return wavelength (default)
if(HasValue(descend)) {
# make wavelength into descending order
bandcenter = reverse_spectrum(bandcenter)
} else {
# wavenumber version is already ascending (default)
}
return(bandcenter)
}
} else {
printf("No valid instrument specified\n\n")
printf (" Make bands ('xaxes') for major IR instruments\n")
printf (" Usage: x = make_band([inst='inst'] or [tes=1][tes5=1][tes73=1][mtes=1][themis=1][lab1=1][lab2=1]lab3=1][aster=1][tims=1][modis=1][full=1][cm=1][wave=1][descend=1]) \n")
printf (" Default is to return wavelength or wavenumber in natural order for specified instrument\n")
printf (" works in inst='inst' (e.g. inst='themis') or themis=1 modes\n")
printf (" i.e. ascending wavenumbers for spectrometers; ascending wavelength for broadband instruments\n")
printf (" [full = 1] Returns bandcenter and min and max (where appropriate) in cm-1 and microns\n")
printf (" 'full' mode only returns default mode (no descend)\n")
printf (" [cm = 1] Returns bandcenter in ascending cm-1\n")
printf (" [wave = 1] Returns bandcenter in ascending wavelength\n")
printf (" [descend = 1] Inverts default order\n")
printf (" [apod = 1] Applies approximation of S. Chase apodization to TES\n")
printf (" If cm flag is specified for broadband or wave flag for spectrometers, the order is still ascending\n")
printf (" descend flag inverts the default order\n")
printf (" \n")
printf (" p. christensen 11/28/08\n")
return(0)
}
}
define make_temp_rad(themis, aster, tims) {
if (HasValue(themis)==0 && HasValue(aster)==0 && HasValue(tims)==0) {
printf (" make tbtorad and radtotb look up table by integrating Planck function times THEMIS IR filter functions\n")
printf (" \n")
printf (" default is THEMIS, also does ASTER and TIMS \n")
printf (" \n")
printf (" creates array of temperature and spectral radiance, weighted by filter response \n")
printf (" spectral radiance is in units of W cm-2 str-1 micron-1 \n")
printf (" Array is [nbands+1,ntemps], where x dimension is temp and n spectral radiances \n")
printf (" [themis = 1] \n")
printf (" [aster = 1] \n")
printf (" [tims = 1] \n")
return(0)
}
# p.christensen 10/2/01
# generalized to include ASTER, TIMS, and MODIS: prc 11/08
######## history
# THEMIS is still version 4
# P. Christensen 11/14/08
# added PATH
# changed to spectral radiance - p. christensen 3/29/02
# increment to version 4
# changed start and end temps to 100. and 380. - p. christensen 3/14/02
# increment to version 3
#start_temp = 120.
#end_temp = 360.
# used up to 11/10/01 - and beyond
#d_temp = 0.1
# experiment - prc - 11/11/01
# only changed final temps by <0.001 prc
# wrote results to /themis/data/archive/temp_rad_5
# tested in test_temp_rad5
# used d_temp = 0.5 from here on
# v2 - prc 1/4/02
# used better relative spectral response - filter * window * beamsplitter (/themis/calib/themis_IR_response_norm_v2.davinci)
# used d_temp = 0.5
#################
d_temp = 0.5
start_temp = 100.
end_temp = 380.
# set path
# default path set up by Chris Edwards for davinci use on multiple platforms
PATH = $DV_SCRIPT_FILES
PATHI = PATH +"/instrument_parameters"
ntemps = int( (end_temp - start_temp) / d_temp + 1 )
# read in filter response functions [nbands+1 x nwaves x 1] - x[1] = wavelengths; x[2-n] = responses for each filter
# for themis f=[11,4000,1] - 1 xaxis + 10 bands at 4000 wavelengths
if(HasValue(aster)) {
f = read(PATHI+"/aster_ir_spectral_response_wave.vic")
} else if(HasValue(tims)) {
f = read(PATHI+"/tims_ir_spectral_response_avg_wave.vic")
} else if(HasValue(modis)) {
# not done yet
} else if(HasValue(themis)) {
f = ascii(PATHI+"/themis_IR_filter_response_norm_v2.davinci",format=float)
} else {
f = ascii(PATHI+"/themis_IR_filter_response_norm_v2.davinci",format=float)
}
nbands = int(dim(f)[1] - 1)
nwaves = int(dim(f)[2])
printf("start temp = %.1f end temp = %.1f d temp = %.1f\n", start_temp, end_temp, d_temp)
printf("nwaves = %d ntemps = %d nbands = %d\n", nwaves, ntemps, nbands)
# create array for spectral radiance for each band, each temperature and set to 0.
rsum = create(nbands, ntemps, 1, format=double)
rsum = rsum * 0.
# create array for temperatures
temps = create(1,ntemps,1,format=double)
temps = temps * 0.
# make array of delta wave
dwave = create(1, nwaves, format=double)
for(i=1; i<= nwaves-1; i+=1) {
dwave[,i] = f[1,i+1]-f[1,i]
}
dwave[,nwaves] = dwave[,nwaves-1]
# make bandpass integral
# sum filter response over all wavelengths
fsum = sum((f[2:(nbands+1)] * dwave),y)
# loop on temps
for(i=1; i<= ntemps; i+=1) {
# compute temp for this index
temp = start_temp + (i-1) * d_temp
# load temp array
temps[1,i,1]=temp
# get spectral radiance (W cm-2 micron-1 str-1) for each wavelength for this temperature
# f[1,,] contains wavelengths
rad = bbrw(f[1,,], temp)
# multiply spectral radiance * filter_response * dwave (micron) and sum over all wavelengths
# result is spectral radiance - W cm-2 str-1 micron-1
rsum[,i,] = sum( (rad * f[2:(nbands+1)] * dwave) ,y)
}
# compute spectral radiance (units of W cm-2 str-1 micron-1) - added prc 3/29/02
sp_rsum = rsum/fsum
# create final temp_rad array
temp_rad = temps//sp_rsum
#temp_rad = temps//float(sp_rsum)
if (HasValue(write)) {
# verson 4 3/12902 - spectral radiance
if(HasValue(aster)) {
name = "/temp_rad_aster.vic"
fileout = PATHI+ name
printf("writing file to %s\n", fileout)
write(temp_rad, fileout, vicar, force=1)
} else if(HasValue(tims)) {
fileout = PATHI+"/temp_rad_tims.vic"
write(temp_rad, fileout, vicar, force=1)
} else if (HasValue(modis)) {
# not done yet
} else {
# themis is default
# verson 4 3/12902 - spectral radiance
fileout = PATHI+"/temp_rad_v4"
printf("Writing is disabled for THEMIS to avoid accidentally changing\n")
printf(" the official THEMIS calibration files - PRC 12/19/08\n")
#printf("Writing temp_out file %s\n", fileout)
#write(temp_rad, fileout, vicar, force=1)
#write(fsum,"/themis/calib/ir_band_width_v2",vicar,force=1)
#write(fsum,"/themis/data/archive/ir_band_width_v2",vicar,force=1)
}
# verson 2 1/4/02 - new filter * window * beamsplitter data
# fileout = "/themis/calib/temp_rad_v2"
# printf("Writing temp_out file %s\n", fileout)
# write(temp_rad, fileout, vicar, force=1)
# write(temp_rad,"/themis/data/archive/temp_rad_v2",vicar,force=1)
# write(temp_rad,"/themis/data/archive/temp_rad_v1.1",vicar,force=1)
# write(temp_rad,"/themis/data/archive/temp_rad",vicar,force=1)
# write(fsum,"/themis/calib/ir_band_width_v2",vicar,force=1)
# write(fsum,"/themis/data/archive/ir_band_width_v2",vicar,force=1)
}
return(temp_rad)
}
define i2i(to, from, wave, cm, full, filters, descend, list, supported) {
if ($ARGC == 0 && HasValue(supported)==0 ) {
printf(" Convert spectra from one IR instrument to another\n")
printf(" \n")
printf(' Usage: spec_out = i2i(spec, from="from_inst", to="to_inst" [wave=1][cm][full][filters][descend])\n')
printf(" Allowed 'from' instruments are lab1, lab2, tes, tes5, tes73, and mtes\n")
printf(" Allowed 'to' instrument are lab1, lab2, tes, tes5, tes73, mtes, themis, aster, tims, master\n")
printf(" Both 'from' and 'to' can be arrays of xaxis values. Size of 'from' must equal size of spec\n")
printf(" Use 'to'=xaxis or 'from'=xaxis' to create or use customized output or input spectra.\n")
printf(" Default instrument input (from) spectra must be in ascending, cm-1 form\n")
printf(" Exception is converting broadband instrument from ascending wavelength\n")
printf(" to ascending cm\n")
printf(" This mode also returns the xaxis to avoid any confusion\n")
printf(" Ex: a = i2i(spect, from='themis', to='themis') returns 'a' in ascending cm form\n")
printf(" Default 'to' spectra are in ascending (low to high) cm for spectrometers\n")
printf(" or ascending wavelength for broadband instruments\n")
printf(" [wave=1] returns spectra in ascending wavelength form\n")
printf(" [cm=1] returns spectra in ascending wavenumber (cm) form\n")
printf(" [descend=1] returns spectrum in descending wavelength or wavenumber order\n")
printf(" Note: Non-standard cm or wave modes return both spectra and xaxis\n")
printf(" [list = list]. In spectral library mode, only move a portion of the resampled data\n")
printf(" Ex: list = '1//4//7//21:27, 33//35//51:60'\n")
printf(" [full=1] returns both spectrum and xaxis\n")
printf(" [filters=1] returns spectrum, xaxis, and filter functions\n")
printf(" \n")
printf(" Examples: speca = i2i(spec, from = 'lab1', to ='themis')\n")
printf(" speca = i2i(spec, from = 'lab1', to ='aster', wave=1)\n")
printf(" speca = i2i(spec, from = 'lab1', to ='lab1', wave=1)\n")
printf(" speca = i2i(spec, from = 'tes', to = 'aster', cm=1)\n")
printf(" speca = i2i(spec, from = 'lab1', to = my_out_axis)\n")
printf(" speca = i2i(spec, from = my_in_axis, to = my_out_axis)\n")
printf(" \n")
printf(" Spectral library mode examples:\n")
printf(" speclib = i2i(asulib, to ='aster', list='1//3//21:28, //33//41')\n")
printf(" \n")
printf(" p.christensen 11/08, 7/10\n")
return(0)
}
# added master to list of allow 'to' instrument
# modified to resample spectral library structures and move all elements,
# including sublib option using 'list' - prc 4/25/11
# modified to do special cases of from = to - prc
# reorganized significantly to not use to and from internally - prc 7/1/10
# changed to use 'to' and 'from' keywords - prc 6/30/2010
# added custom and xtospec - prc 3/24/2010
# removed resample option from broadband instruments - prc 1/18/09
# added list of supported insturments and TES 73 point spectra
#HERE is the description list of supported instruments
if(HasValue(supported)) {
list={}
list.list=cat("lab1",\
"lab2",\
"tes",\
"tes5",\
"tes73",\
"mtes",\
"themis",\
"tims",\
"aster",\
"master",axis=y);
list.description=cat("SpecLab1 sampling (200-2000 @ 2cm-1)",\
"SpecLab2 sampling (200-4000 @ 2cm-1)",\
"TES single sampling (148-1650 @ 10cm-1)",\
"TES double sampling (148-1655 @ 5cm-1)",\
"TES 73-point sampling (339-1301 @ 10cm-1)",\
"Mini-TES sampling (339-1997 @ 10cm-1)",\
"THEMIS IR sampling",\
"TIMS IR sampling",\
"ASTER IR sampling",\
"MASTER IR sampling",axis=y);
return(list);
}
# set up
in = $1
# test to see if user sent in a single standard spectral structure
if (type(in) == "STRUCT") {
if(HasValue(get_struct(in, "data")) == 0) {
printf("You sent in a structure, but it doesn't have a 'data' field\n")
return(0)
}
if(HasValue(from)==0){
from = in.xaxis
}
# set structure logical flag
st = 1
spec = in.data
} else {
# user sent in a spectrum
st = 0
spec = in
}
struc = struct()
# set path
# default path set up by Chris Edwards for davinci use on multiple platforms
PATH = $DV_SCRIPT_FILES
PATHI = PATH + "/instrument_parameters"
if(HasValue(filters)) {
# automaticaly set mode to 'full' if user requested the filter functions
full = 1
}
# do the initial checking of to and from, keywords or arrays
if(HasValue(from) == 0) {
printf("No from instrument specified\n")
return(0)
}
if(HasValue(to) == 0) {
printf("No to instrument specified\n")
return(0)
}
# check to see if 'to' is an x axis
format = format(to)
if(format != 'STRING') {
size = dim(to)
xto = to
inst_to = 'custom_to'
} else {
inst_to = to
}
# check to see if 'from' is an x axis
format = format(from)
if(format != 'STRING') {
size = dim(from)
xfrom = from
inst_from = 'custom_from'
} else {
inst_from = from
}
# check for special cases; these are ok only if doing the special case of
# converting broadband instrument from ascending wavelength to ascending wavenumber
if(inst_from == "themis" || inst_from == "aster" || inst_from == "tims" || inst_from == "modis"|| inst_from == "master") {
if(inst_to == "themis" && inst_from == "themis") {
xto = make_band(themis=1, cm=1)
} else if(inst_to == "aster" && inst_from == "aster") {
xto = make_band(aster=1, cm=1)
} else if(inst_to == "tims" && inst_from == "tims") {
xto = make_band(tims=1, cm=1)
} else if(inst_to == "master" && inst_from == "master") {
xto = make_band(master=1, cm=1)
} else {
printf("themis, aster, tims, modis, and master can only 'inst_from' if also 'to'\n")
return(0)
}
# invert spectrum
data = reverse_spectrum(spec)
if(HasValue(full)) {
# this modes does not return filter functions
struc.data = data
struc.xto = xto
return(struc)
} else {
return(data)
}
}
# check for more special cases; these are for doing the special case of
# converting spectrometer instrument from ascending wavenumber to ascending wavelength
if(inst_to == inst_from) {
if(inst_to == 'lab1' && inst_from == 'lab1') {
xto = make_band(lab1=1, wave=1)
} else if(inst_to == 'lab2' && inst_from == 'lab2') {
xto = make_band(lab2=1, wave=1)
} else if(inst_to == 'tes' && inst_from == 'tes') {
xto = make_band(tes=1, wave=1)
} else if(inst_to == 'tes5' && inst_from == 'tes5') {
xto = make_band(tes5=1, wave=1)
} else if(inst_to == 'tes73' && inst_from == 'tes73') {
xto = make_band(tes73=1, wave=1)
} else if(inst_to == 'mtes' && inst_from == 'mtes') {
xto = make_band(mtes=1, wave=1)
}
# invert spectrum
data = reverse_spectrum(spec)
if(HasValue(full)) {
# this modes does not return filter functions
struc.data = data
struc.xto = xto
return(struc)
} else {
return(data)
}
}
# do remaining checks
# check for legitimate 'from' instruments' for 'normal' cases
if(inst_from == "tes" || inst_from == "tes5" || inst_from == "tes73" || inst_from == "mtes" || inst_from == "lab1" || inst_from == "lab2" || inst_from == "custom_from") {
# these are ok - go on
} else {
printf("incorrect input instrument\n")
printf("Only lab1, lab2, tes, tes5, and mtes allowed for 'from' at this time\n")
printf("except in special broadband case of 'to' = 'from'\n")
return(0)
}
# check for legitimate 'to' instruments'
if(inst_to == "lab1" || inst_to == "lab2" || inst_to == "tes" || inst_to == "tes5" || inst_to == "mtes" || inst_to == "themis" || inst_to == "aster" || inst_to == "tims" || inst_to == "modis" || inst_to == "master" || inst_to=="tes73" || inst_to == "custom_to") {
} else {
printf("incorrect output instrument\n")
return(0)
}
# get the xaxis for 'from' spectra
if(HasValue(xfrom)==0) {
# no xaxis sent in (default) - get the 'from' xaxis
# xaxes are in cm form, ascending (low cm to high cm)
if(inst_from == "lab1") {
xfrom = make_band(lab1=1)
} else if(inst_from == "lab2") {
xfrom = make_band(lab2=1)
} else if(inst_from == "tes") {
xfrom = make_band(tes=1)
} else if(inst_from == "tes5") {
xfrom = make_band(tes5=1)
} else if(inst_from == "tes73") {
xfrom = make_band(tes73=1)
} else if(inst_from == "mtes") {
xfrom = make_band(mtes=1)
} else {
printf("Only lab1, lab2, tes, tes5, tes73, and mtes allowed for 'from' at this time\n")
return(0)
}
}
size = dim(spec)
nxfrom = size[1]
nyfrom = size[2]
# spec_len is length of from spectrum
spec_len = size[3]
# xfrom_len is length of 'from' 'xaxis'
xfrom_len = dim(xfrom)[3]
# check to make sure length of from spectra and xaxis match
if(xfrom_len != spec_len) {
printf("Length of spectrum (%d) does not match that of xaxis (%d)\n", spec_len, xfrom_len)
return(0)
}
# work through possible 'to' combinations
if(inst_to == "lab1" || inst_to == "lab2" || inst_to == "tes" || inst_to == "tes5" || inst_to == "mtes" || inst_to=="tes73" || inst_to == "custom_to") {
# the spectrometers - only do the resample approach
# xto is in cm form, ascending
if(inst_to == "lab1") {
xto = make_band(lab1=1)
} else if(inst_to == "lab2") {
xto = make_band(lab2=1)
} else if(inst_to == "tes") {
xto = make_band(tes=1)
} else if(inst_to == "tes5") {
xto = make_band(tes5=1)
} else if(inst_to == "tes73") {
xto = make_band(tes73=1)
} else if(inst_to == "mtes") {
xto = make_band(mtes=1)
} else if(inst_to == "custom_to") {
# do nothing - xaxis already set to xto
}
# do the resampling - ok for hyperspectral spectrometers
if($DV_OS=="win") {
specnew = resampleudf(spec, xfrom, xto).data
} else {
specnew = resample(spec, xfrom, xto).data
}
} else {
printf("\ndoing broadband\n")
# the broadband instruments - do a convolue
# read in spectral response versus wavelength
# wavenumber and response function are in ascending wavenmuber order
if(inst_to == "themis") {
# make xto in cm form, ascending (low cm to high cm) (high wave to low wave)
xto = make_band(themis=1, cm=1)
fati=read(PATHI+"/themis_ir_spectral_response_cm.vic")
} else if(inst_to == "aster") {
# make xto in cm form, ascending (low cm to high cm) (high wave to low wave)
xto = make_band(aster=1, cm=1)
fati=read(PATHI+"/aster_ir_spectral_response_cm.vic")
} else if(inst_to == "tims") {
# make xto in cm form, ascending (low cm to high cm) (high wave to low wave)
xto = make_band(tims=1, cm=1)
fati=read(PATHI+"/tims_ir_spectral_response_avg_cm.vic")
} else if(inst_to == "master") {
xto = make_band(master=1, cm=1)
fati=read(PATHI+"/master_ir_spectral_response_avg_cm.vic")
} else if(inst_to == "modis") {
}
# convolue input spectrum with instrument spectral response
# make sure input (from) xaxis is in ascending order
if(xfrom[1,1,xfrom_len] <= xfrom[1,1,1]) {
printf("input xaxis is in descending wavenumber range\n")
return(0)
}
# first resample spectral response array to input spectrum
# nx is number bands +1(xaxis) in spectral response array
nx= dim(fati)[1]
nbands = nx - 1
# nwaves is length of 'to' 'xaxis'
nwaves = dim(xto)[3]
# create output array
specnew = create(nxfrom, nyfrom, nbands, format=float)
# create new (resampled) spectral response array
filt_resample = create(nbands, 1, xfrom_len, format=float)
# loop over bands
for(i=1; i<=nbands; i+=1) {
# resample response function of 'to' instrument to 'from' xaxis
if($DV_OS=="win") {
resampled_response = resampleudf(fati[i+1], fati[1], xfrom)
} else {
resampled_response = resample(fati[i+1], fati[1], xfrom)
}
filt_resample[i] = resampled_response.data
specnew[,,i] = sum(spec * filt_resample[i], axis=z) / sum(filt_resample[i],axis=z)
}
# input spectrum was in ascending cm order; spectral response is in
# ascending cm order, and xto is in ascending cm order,
# but specnew is in band order - i.e. ascending
# wavelength order, descending cm order. Must invert specnew to put it into
# ascending cm order
specnew = reverse_spectrum(specnew)
if(HasValue(filters)) {
printf("set up to return filter functions\n")
struc.filters = filt_resample
struc.xfilters = xfrom
}
# set default condition for returned spectrum to 'wavelength' unless user specified 'cm'
if(HasValue(cm) == 0){
wave = 1
}
}
if(HasValue(wave)) {
# convert 'to' spectra to ascending wavelength form'
xto = cm2micron(xto)
# invert xaxis
xto = reverse_spectrum(xto)
# invert spectrum
specnew = reverse_spectrum(specnew)
if(HasValue(filters)) {
# invert filter function
struc.filters = reverse_spectrum(struc.filters)
# convert xfilters to wavelength and invert
struc.xfilters = reverse_spectrum(cm2micron(struc.xfilters))
}
}
if(HasValue(descend)) {
# invert both spectra and xaxis
specnew = reverse_spectrum(specnew)
xto = reverse_spectrum(xto)
}
# return data
if(st == 1) {
# send back a structure with new data and xaxis
if(HasValue(list)==0) {
# move entire structure
out_struc = in
# replace data and xaxis with resampled values
out_struc.data = specnew
out_struc.xaxis = xto
return(out_struc)
} else {
# move in user-specified vectors from structure
in.data = specnew
out_struc = sublib(in, list)
# reset the xaxis with the resampled xaxis
out_struc.xaxis = xto
return(out_struc)
}
} else {
if(HasValue(full)) {
struc.data = specnew
struc.xaxis = xto
return(struc)
} else {
# only return spectrum (default)
return(specnew)
}
}
}
define i2i_tutorial(index) {
printf("read in ASU spectral library\n")
cmd = "asu = read($DV_EX+'/ASU_minlib.hdf')"
echo(cmd)
eval(cmd)
pause("pausing")
if(HasValue(index)) {
i = index
} else {
i = 1
}
printf("\n**** Resample a lab spectrum to ASTER resolution and plot both vs wavenumber **\n\n")
printf("create lab1 x axis (default is wavenumber mode for spectrometers)\n")
cmd = "xlab1 = make_band(inst='lab1')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("create aster x axis in wavenumber mode\n")
cmd = "xastercm = make_band(inst='aster', cm=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample 1 lab spectrum to ASTER resolution with wavenumber xaxis\n")
cmd = "aster = i2i(asu.data[i], from = 'lab1', to = 'aster', cm=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("plot lab and resampled ASTER spectra\n")
cmd = "pplot({asu.data[i], aster}, {'Lab Spectrum', 'ASTER'}, {1,5}, xaxis={xlab1, xastercm}, xlabel = 'Wavenumber', ylabel = 'Emissivity', key = '1400, .95')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("\n*** A simpler approach ***\n\n")
printf("Resample to ASTER and return xaxis in wavenumber mode by using 'full' mode\n")
cmd = "aster = i2i(asu.data[i], from='lab1', to='aster', cm=1, full=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("plot lab and resampled ASTER spectra\n")
cmd = "pplot({asu.data[i], aster.data}, {'Lab Spectrum', 'ASTER'}, {1,5}, xaxis={asu.xaxis, aster.xaxis}, xlabel = 'Wavenumber', ylabel = 'Emissivity', key = '1400, .95')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("\n\n*** Example of how to do a bunch of instruments and plot vs wavelength\n\n")
printf("create aster x axis in wavelength mode (default is wavelength for broadband insts.)\n")
cmd = "xaster = make_band(inst='aster')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("create tims x axis in wavelength mode (default)\n")
cmd = "xtims = make_band(inst='tims')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("create themis x axis in wavelength mode (default)\n")
cmd = "xthemis = make_band(inst='themis')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("create lab1 x axis in wavelength mode\n")
cmd = "xlab1wave = make_band(inst='lab1', wave=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("create tes x axis in wavelength mode\n")
cmd = "xteswave = make_band(inst='tes', wave=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Convert lab spectrum to lab resolution with wavelength xaxis\n")
cmd = "lab1w = i2i(asu.data[i], from = 'lab1', to = 'lab1', wave=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to TES resolution with wavelength xaxis (default)\n")
cmd = "tes = i2i(asu.data[i], from = 'lab1', to = 'tes', wave=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to TIMS resolution with wavelength xaxis (default)\n")
cmd = "tims = i2i(asu.data[i], from = 'lab1', to = 'tims')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to TIMS resolution with wavelength xaxis (default)\n")
cmd = "themis = i2i(asu.data[i], from = 'lab1', to = 'themis')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to ASTER resolution with wavelength xaxis (default)\n")
cmd = "aster = i2i(asu.data[i], from = 'lab1', to = 'aster')"
echo(cmd)
eval(cmd)
pause("pausing")
printf("plot lab and resampled TES, THEMIS, ASTER, and TIMS spectra\n")
cmd = "pplot({lab1w, tes, themis, aster, tims}, {'Lab Spectrum', 'TES', 'THEMIS', 'ASTER', 'TIMS'}, {1,2,4,5,6}, xaxis={xlab1wave, xteswave, xthemis, xaster, xtims}, xlabel = 'Wavelength', ylabel = 'Emissivity', key = '12.5, .94', x1=6., x2=16.)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("\n\n**** Again - a simplier approach using 'full' mode in i2i ****\n\n")
printf("Resample lab spectrum to lab resolution with wavelength xaxis (default)\n")
cmd = "lab = i2i(asu.data[i], from = 'lab1', to = 'lab1', wave=1, full=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to TES resolution with wavelength xaxis (default)\n")
cmd = "tes = i2i(asu.data[i], from = 'lab1', to = 'tes', wave=1, full=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to THEMIS resolution with wavelength xaxis (default)\n")
cmd = "themis = i2i(asu.data[i], from = 'lab1', to = 'themis', wave=1, full=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to ASTER resolution with wavelength xaxis (default)\n")
cmd = "aster = i2i(asu.data[i], from = 'lab1', to = 'aster', wave=1, full=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("Resample lab spectrum to TIMS resolution with wavelength xaxis (default)\n")
cmd = "tims = i2i(asu.data[i], from = 'lab1', to = 'tims', wave=1, full=1)"
echo(cmd)
eval(cmd)
pause("pausing")
printf("plot lab and resampled TES, THEMIS, ASTER, and TIMS spectra\n")
cmd = "pplot({lab.data, tes.data, themis.data, aster.data, tims.data}, {'Lab Spectrum', 'TES', 'THEMIS', 'ASTER', 'TIMS'}, {1,2,4,5,6}, xaxis={lab.xaxis, tes.xaxis, themis.xaxis, aster.xaxis, tims.xaxis}, xlabel = 'Wavelength', ylabel = 'Emissivity', key = '12.5, .94', x1=6., x2=16.)"
echo(cmd)
eval(cmd)
pause("pausing")
}
define reverse_spectrum() {
if ($ARGC == 0) {
printf("Reverse the z dimension of an array\n")
printf("Usage: b = reverse_spectrum(a)\n")
printf(" p. christensen 12/08\n")
return(0)
}
spec = $1
nband = dim(spec)[3]
tmpspec = spec
for(i=1; i<=nband; i+=1) {
j = int((nband - (i-1)))
spec[,,j] = tmpspec[,,i]
}
return(spec)
}
define cm2micron() {
# convert wavenumber (input in cm) to micron
if ($ARGC == 0) {
printf("Convert array in cm-1 to microns\n")
printf("Usage: b = cm2micron(a)\n")
return(0)
}
# p. christensen 11/26/08
wave = 10000./$1
return(wave)
}
define r2t_hi(v){
if ($ARGC == 0) {
printf ("converts PRT resistance meassurments to temperature for bbhot \n")
printf ("(channels 3 and 4) using equations from ROSEMOUNT manual; this \n")
printf ("version is 1.5 that applies to PRTs with s/n 32147 and 31988 \n")
printf ("usage: r2t_hi(ch_3, ch_4) \n")
printf ("Written by Alice Baldridge - Thu Jun 15 13:41:16 MST 2006\n")
return(0)
}
if(HasValue(v)==0) {
v=1
}
#constants
A3=3.946065e-3
B3=-5.8755e-7
A4=3.947985e-3
B4=-5.8755e-7
Ro3=1001.01647
Ro4=1000.91666
#calculated values
W3=$1/Ro3
tp3 = ((A3^2-4*B3*(1-W3))^.5 - A3)/(2*B3)
r2t_hi_v1_temp3 = tp3+0.045*(tp3/100)*(tp3/100-1)*(tp3/419.58-1)*(tp3/630.74-1)
W4 = $2/Ro4
tp4 = ((A4^2-4*B4*(1-W4))^.5 - A4)/(2*B4)
r2t_hi_v1_temp4 = tp4+0.045*(tp4/100)*(tp4/100-1)*(tp4/419.58-1)*(tp4/630.74-1)
r2t_hi_v1_ave = (r2t_hi_v1_temp3+r2t_hi_v1_temp4)/2
if(v==1) printf ("Average temperature is \n")
return (r2t_hi_v1_ave)
}
define r2t_lo(v){
if ($ARGC == 0) {
printf ("converts PRT resistance meassurments to temperature for bbwarm \n")
printf ("(channels 1 and 2) using equations from ROSEMOUNT manual; this \n")
printf ("version is 1.5 that applies to PRTs with s/n 31985 and 31986 \n")
printf ("usage: r2t_hi(ch_1, ch_2) \n")
printf ("Written by Alice Baldridge - Thu Jun 15 13:41:16 MST 2006\n")
return(0)
}
if(HasValue(v)==0) {
v=1
}
# Constants
A1 = 3.946495e-3
B1 = -5.87549e-7
A2 = 3.947915e-3
B2 = -5.8755e-7
Ro1 = 1000.71666
Ro2 = 1001.59058
# Calculated values
W1 = $1/Ro1
tp1 = ((A1^2-4*B1*(1-W1))^.5 - A1)/(2*B1)
r2t_lo_temp1 = tp1+0.045*(tp1/100)*(tp1/100-1)*(tp1/419.58-1)*(tp1/630.74-1)
W2 = $2/Ro2
tp2 = ((A2^2-4*B2*(1-W2))^.5 - A2)/(2*B2)
r2t_lo_temp2 = tp2+0.045*(tp2/100)*(tp2/100-1)*(tp2/419.58-1)*(tp2/630.74-1)
r2t_lo_ave = (r2t_lo_temp1+r2t_lo_temp2)/2
if(v==1) printf("Average temperature is \n")
return(r2t_lo_ave)
}
define r2t_swri(v){
if ($ARGC < 4) {
printf("\nConverts PRT resistance measurements (ohms) to temperature (C) for BB #4 (SwRI)\n")
printf("using equations from the ROSEMOUNT manual \n\n")
printf("example: rt2_swri(ch1_lo,ch2_lo,ch1_hi,ch2_hi) \n\n")
printf("Osterloo/Hamilton 3/29/2010 \n\n")
return(NULL)
}
if(HasValue(v)==0) v=1
#Constants for BB #4 - PRT S/Ns 31991 and 31992 */
A1 = 3.947075e-3
B1 = -5.8755e-7
A2 = 3.946875e-3
B2 = -5.8755e-7
Ro1 = 1001.65018
Ro2 = 1000.40883
#Calculated values
W1 = $1/Ro1
tp1 = ((A1^2.0-4.0*B1*(1.0-W1))^0.5 - A1)/(2.0*B1)
r2t_lo_temp1 = tp1+0.045*(tp1/100.0)*(tp1/100.0-1.0)*(tp1/419.58-1.0)*(tp1/630.74-1.0)
W2 = $2/Ro2
tp2 = ((A2^2.0-4.0*B2*(1.0-W2))^.5 - A2)/(2.0*B2)
r2t_lo_temp2 = tp2+0.045*(tp2/100.0)*(tp2/100.0-1.0)*(tp2/419.58-1.0)*(tp2/630.74-1.0)
r2t_lo_avg = (r2t_lo_temp1+r2t_lo_temp2)/2.0
W3 = $3/Ro1
tp1_hi = ((A1^2.0-4.0*B1*(1.0-W3))^.5 - A1)/(2.0*B1)
r2t_hi_temp1 = tp1_hi+0.045*(tp1_hi/100.0)*(tp1_hi/100.0-1.0)*(tp1_hi/419.58-1.0)*(tp1_hi/630.74-1.0)
W4 = $4/Ro2
tp2_hi = ((A2^2.0-4.0*B2*(1.0-W4))^.5 - A2)/(2.0*B2)
r2t_hi_temp2 = tp2_hi+0.045*(tp2_hi/100.0)*(tp2_hi/100.0-1.0)*(tp2_hi/419.58-1.0)*(tp2_hi/630.74-1.0)
r2t_hi_avg = (r2t_hi_temp1+r2t_hi_temp2)/2.0
r2t_total = (r2t_lo_avg +r2t_hi_avg)/2.0
if(v!=0) printf ("Average temperature is %f\n",r2t_total)
return (r2t_total)
}
define emcal2(hotbb,warmbb,individual,ratw,dehyd,resample,noise_free,lab,max_emiss) {
if($ARGC==0) {
printf("\n")
printf ("emcal2() - Emissivity Calculation of Laboratory Spectra\n\n")
printf ("\tComputes an instument response function from measured emission, \n")
printf ("\tspectra of hot and warm blackbody and known blackbody Temperature. \n")
printf ("\tThen calculates emissivity using previously determined\n")
printf ("\tresponse function, hot blackbody spectrum, sample spectrum,\n")
printf ("\tand known environment temperature.\n\n")
printf ("Usage:\n")
printf ("\t$1=directory containing spectra\n")
printf ("\t$2=output file name\n")
printf ("\t$3=warm BB resistance values (Ch 101//Ch102 as 1313.3//1315.6(asu) or Ch1lo//Ch2lo//Ch1hi//Ch2hi(swri))\n")
printf ("\t$4=hot BB resistance values (Ch 103//Ch104 as 1314.3//1314.6(asu) or Ch1lo//Ch2lo//Ch1hi//Ch2hi(swri))\n")
printf ("Or\n")
printf ("\t$3=warm BB temperture (from r2t_lo() as 70.403)\n")
printf ("\t$4=hot BB temperture (from r2t_hi() as 100.334)\n\n")
printf ("Alternatively, if using the ASU LabView data acquisition software\n")
printf ("\t$1=the full path to the data qube written by the labview interface \n")
printf ("\t$2=the output file name (which will be written into the data qube directory\n")
printf ("Optional Arguments:\n")
printf ("\t$5=\tlist of environmental chamber temperatures\n")
printf ("\t\tmust have the same # of entries as spectra in $1\n")
printf ("\tlab=\tlocation where data was acquired (PRT calibration values are lab specific) (\"swri\" or Default=\"asu\")\n")
printf ("\tnoise_free=compute a \"noise free\" instrument response function\n\t\tand instrument radiance (Default=1)\n")
printf ("\thotbb=\thot blackbody partial filename (Default search = \"bbh\")\n")
printf ("\twarmbb=\twarm blackbody partial filename (Default search = \"bbw\")\n")
printf ("\tdehyd=\tadd dehydrated spectra to the output\n\t\tstructure (Uses dehyd2(), Default=0)\n")
printf ("\tindivdual=write the spectra out and individual text files with\n\t\tno labels for spectral library (Default=0)\n")
printf ("\tresample=resample all spectra to hot blackbody xaxis (Default=0) \n")
printf ("\tmax_emiss=optional maximum emissivity (e.g. 0.98) (default = 1.)\n")
printf ("\tratw=\tset up default options for RATW calibration (Default=0, deyhd=1,\n\t\tindiv=1 (plus modified label), resample=1) \n\n")
printf ("NOTE: This function uses irf_ri(), cal_rad(), and emissivity() to do calibration\n\n")
printf ("Written by C.Edwards. 3/18/2011\n\n")
return(null)
}
raw={}
out={}
dir=$1
outname=$2
if(HasValue(individual)==0) individual=0
if(HasValue(dehyd)==0) dehyd=0
if(HasValue(ratw)==0) ratw=0
if(HasValue(resample)==0) resample=0
if(HasValue(noise_free)==0) noise_free=1
if(HasValue(lab)==0) lab="asu"
if(HasValue(max_emiss)==0) max_emiss=1.
if(ratw==1) {
dehyd=0
lab="asu"
noise_free=1
individual=1
resample=1
}
#check to make sure the output file is a string and add a .hdf if it doesn't exist
if(type(outname)!="STRING"){
printf("Please use a string for output filename\n")
return(NULL)
}
if(strstr(outname, ".hdf")== 0) {
outname = outname+".hdf"
}
raw.hdfname=outname
raw.inputdir=dir
if(type($1)=="STRING" && $ARGC==2) {
verbose=0
input=load_pds(dir)
verbose=3
if(HasValue(get_struct(input,"spectral_data_table"))==0) {
printf("\nThe input file you specify is not a valid spectral qube\n")
printf("Please check your path and verify the input file name\n\n")
return(null)
}
raw.hotbbfile=dir
raw.warmbbfile=dir
raw.inputdir=dirname(dir)+"/"
spec_data_size=int(input.spectral_data_table.data.spec_data_size[,1]-2)
raw.data=create(1,1,spec_data_size,format=float,org=bsq,start=0,step=0)
raw.hotbb=create(1,1,spec_data_size,format=float,org=bsq,start=0,step=0)
raw.warmbb=create(1,1,spec_data_size,format=float,org=bsq,start=0,step=0)
envtemp=create(1,1,1,format=float,org=bsq,start=0,step=0)
raw.insttemp=create(1,1,1,format=float,org=bsq,start=0,step=0)
raw.speclist=text(0)
for(i=1;i<=length(input.spectral_data_table.data.acq_type);i+=1) {
if(input.spectral_data_table.data.acq_type[,i]=="S") {
raw.data=cat(raw.data,float(translate(input.spectral_data_table.data.spec_data[2:spec_data_size+1,i],x,z)),axis=x)
envtemp=cat(envtemp,float(input.spectral_data_table.data.env_temp[,i]),axis=x)
raw.insttemp=cat(raw.insttemp,float(input.spectral_data_table.data.inst_temp[,i]),axis=x)
raw.speclist=cat(raw.speclist,strsub(input.spectral_data_table.data.label[,i]," ",""),axis=y)
}
if(input.spectral_data_table.data.acq_type[,i]=="W") {
raw.warmbb=float(translate(input.spectral_data_table.data.spec_data[2:spec_data_size+1,i],x,z))
warmres=input.spectral_data_table.data.bb_res_1[,i]//input.spectral_data_table.data.bb_res_2[,i]
}
if(input.spectral_data_table.data.acq_type[,i]=="H") {
raw.hotbb=float(translate(input.spectral_data_table.data.spec_data[2:spec_data_size+1,i],x,z))
hotres=input.spectral_data_table.data.bb_res_1[,i]//input.spectral_data_table.data.bb_res_2[,i]
}
}
out.xaxis=translate(input.spectral_xaxis[2:spec_data_size+1],x,z)
raw.data=raw.data[2:]
envtemp=envtemp[2:]
raw.insttemp=raw.insttemp[2:]
raw.input=input
lab="asu"
} else {
warmres=$3
hotres=$4
#if we have a 5th argument it is the enviornment temperature array in x...
if($ARGC>4) {
if(dim($5)[2]>1 && dim($5)[1]==1) {
envtemp=float(translate($5,x,y))
} else if(dim($5)[2]==1 && dim($5)[1]>1){
envtemp=$5
} else {
printf("\nInvalid environmental temperature array supplied\n")
printf("Please re-enter the environmental array or remove the option\n")
printf("to enter the temperatures manually.\n\n")
return(null)
}
}
#set up the default variables
if(HasValue(hotbb)==0) {
hotbb="bbh"
} else {
hotbb=basename(hotbb,".CSV")
}
if(HasValue(warmbb)==0) {
warmbb="bbw"
} else {
warmbb=basename(warmbb,".CSV")
}
#define the lab where spectra were acquired
out.lab=lab
#check to make sure the input directory is a string
#also check that it exists
#test to make sure the directory ends with a /
if(type(dir)!="STRING"){
printf("Please use a string for the input directory\n")
return(NULL)
}
if(fexists(dir)==0) {
printf("Directory does not exist: %s\n",dir)
printf("Please enter a valid directory\n")
return(NULL)
}
if(basename(dir)==".") dir=$PWD
if(dir[length(dir)]!="/") dir=dir+"/"
#find the apporpriate files
list=syscall("ls "+dir+"*.CSV")
raw.speclist=text()
for(i=1;i<=length(list);i+=1) {
if(strstr(list[,i],warmbb)==0 && strstr(list[,i],hotbb)==0) {
raw.speclist=cat(raw.speclist,list[,i],axis=y)
} else if (strstr(list[,i],warmbb)!=0 ) {
raw.warmbbfile=list[,i]
} else if (strstr(list[,i],hotbb)!=0 ) {
raw.hotbbfile=list[,i]
}
}
#test to see that we found the blackbodies
if(HasValue(get_struct(raw,"hotbbfile"))==0 || HasValue(get_struct(raw,"warmbbfile"))==0) {
printf("\nCould not file the hot or warm blackbody file\n")
printf("Check then names and try again\n\n")
return(null)
}
verbose=0
#read in the black bodies and store an xaxis from the hot blackbody...
hotbb=translate(ascii(raw.hotbbfile,format=float,delim=","),y,z)
raw.hotbb=hotbb[2]
raw.warmbb=translate(ascii(raw.warmbbfile,format=float,delim=",")[2],y,z)
out.xaxis=hotbb[1]
#load the data, resampling if needed and user specified
raw.data=create(length(raw.speclist),1,dim(out.xaxis)[3],format=float,org=bsq)
for(i=1;i<=length(raw.speclist);i+=1) {
tmpdata=translate(ascii(raw.speclist[,i],delim=",",format=float),y,z)
if(resample==0 && dim(tmpdata)[3]!=dim(out.xaxis)[3]) {
printf("\nYour spectral data and xaxis do not match for at least one sample\n")
printf("Please rerun with resample=1\n\n")
verbose=3
return(null)
} else if(resample==1 && dim(tmpdata)[3]!=dim(out.xaxis)[3]) {
raw.data[i]=resample(oldy=tmpdata[2],oldx=tmpdata[1],newx=out.xaxis).data
} else {
raw.data[i]=tmpdata[2]
}
}
verbose=3
}
#check to see if we have resistances or temperatures
if(sum(dim(warmres))==3 && sum(dim(hotres))==3) {
raw.warmbbt=warmres
raw.hotbbt=hotres
} else {
if(lab=="asu") {
#check the dimensions of the Warm BB resistance values
if(isnum(warmres)==0 || dim(warmres)[1]!=2) {
printf("Please enter resistance values for the WarmBB as ch1//ch2 as $3\n")
return(NULL)
}
#check the dimensions of the Hot BB resistance values
if(isnum(hotres)==0 || dim(hotres)[1]!=2) {
printf("Please enter resistance values for the HotBB as ch3//ch4 as $4\n")
return(NULL)
}
#add these to the output struct
raw.ch1res=float(warmres[1])
raw.ch2res=float(warmres[2])
raw.ch3res=float(hotres[1])
raw.ch4res=float(hotres[2])
#convert the resistance values to temperatures
raw.warmbbt=r2t_lo(raw.ch1res,raw.ch2res,v=0)
raw.hotbbt=r2t_hi(raw.ch3res,raw.ch4res,v=0)
} else if (lab=="swri") {
#check the dimensions of the Warm BB resistance values
if(isnum(warmres)==0 || dim(warmres)[1]!=4) {
printf("Please enter resistance values for the WarmBB as ch1_lo//ch2_lo//ch1_hi//ch2_hi as $3\n")
return(NULL)
}
#check the dimensions of the Hot BB resistance values
if(isnum(hotres)==0 || dim(hotres)[1]!=4) {
printf("Please enter resistance values for the HotBB as ch1_lo//ch2_lo//ch1_hi//ch2_hi as $4\n")
return(NULL)
}
#add these to the output struct
raw.warm_ch1res_lo=float(warmres[1])
raw.warm_ch2res_lo=float(warmres[2])
raw.warm_ch1res_hi=float(warmres[3])
raw.warm_ch2res_hi=float(warmres[4])
raw.hot_ch1res_lo=float(hotres[1])
raw.hot_ch2res_lo=float(hotres[2])
raw.hot_ch1res_hi=float(hotres[3])
raw.hot_ch2res_hi=float(hotres[4])
#convert the resistance values to temperatures
raw.warmbbt=r2t_swri(raw.warm_ch1res_lo,raw.warm_ch2res_lo,raw.warm_ch1res_hi,raw.warm_ch2res_hi,v=0)
raw.hotbbt=r2t_swri(raw.hot_ch1res_lo,raw.hot_ch2res_lo,raw.hot_ch1res_hi,raw.hot_ch2res_hi,v=0)
} else {
printf("No valid lab location was specified\n")
printf("Pleas re-enter either \"asu\" or \"swri\"\n\n")
return(null)
}
}
#now we see if the user needs to input data or if it was supplied beforehand
userinput=0
if(HasValue(envtemp)) {
if(dim(envtemp)[1]!=dim(raw.data)[1]) {
printf("\nThe number of enviornement temperatures does not equal the number of spectra\n")
printf("Either remove the environment argument to enter manually, or fix the input\n")
printf("# of Spectra:\t\t%i\n# of Env Temperatures: \t%i\n\n",length(raw.speclist),dim(envtemp)[1])
return(null)
} else {
raw.envtemp=envtemp
}
} else {
userinput=1
}
#not supplied beforehand, get ready for some manual entry!!
if(userinput==1) {
raw.envtemp=create(length(raw.speclist),1,1,format=float,org=bsq,start=0,step=0)
printf("\nBeginning manual enviornmental temperature entry\n")
printf("Enter \"q\" to quit at any time\n")
for(i=1;i<=length(raw.speclist);i+=1) {
val=pause(sprintf("\nEnter the Chamber Temperature (Ch105 in degrees C) for\nSample: %s\n",basename(raw.speclist[,i],".CSV")))
if(val=="\n") {
i-=1
} else if (val[1,1]=="q" || val[1,1]=="Q") {
printf("\nExiting...\n\n")
return(null)
} else {
raw.envtemp[i]=atof(val)
}
}
}
out.raw=raw
if(noise_free!=0) {
#use irf_ri() to compute the noisefree instrument response function and instrument contributed radiance
out.irf_ri=irf_ri(bb1=raw.hotbb,t1=ctok(raw.hotbbt),bb2=raw.warmbb,t2=ctok(raw.warmbbt),xaxis=out.xaxis,noise_free=1)
} else {
#use irf_ri() to compute the standard instrument response function and instrument contributed radiance
out.irf_ri=irf_ri(bb1=raw.hotbb,t1=ctok(raw.hotbbt),bb2=raw.warmbb,t2=ctok(raw.warmbbt),xaxis=out.xaxis)
}
#use cal_rad() to compute calibrated radaince from a spectrum
out.cal_rad=cal_rad(spec=raw.data,ri=out.irf_ri.ri,irf=out.irf_ri.irf,xaxis=out.xaxis)
#use emissivity() to compute emissivity from calibrated radiance
out.emissivity=emissivity(out.cal_rad.radiance, downwelling_t=ctok(raw.envtemp),xaxis=out.xaxis,max_emiss=max_emiss)
#set up some convineient fields for the output structure
out.radiance=out.cal_rad.radiance
out.sample_temperature=ktoc(out.emissivity.target_temperature)
out.sample_t_channel=out.emissivity.pos_t1
out.sample_t_channel[where out.emissivity.target_temperature<=out.emissivity.threshold_t_warm]=out.emissivity.pos_t2
out.sample_t_wavenumber=translate(subset(out.xaxis,z=out.sample_t_channel),z,x)
out.data=out.emissivity.emissivity
#apply dehydration algorithm if the user specifies it
if(dehyd==1) {
dehyd={}
dehyd.original_data=out.data
for(i=1;i<=dim(out.data)[1];i+=1) {
out.data[i]=dehyd2(dehyd.original_data[i],out.xaxis)
}
out.dehyd=dehyd
}
#if ratw is selected then add the emcal emissivity of....to the label
if(ratw==1) {
out.label="emcal emissivity of "+basename(raw.speclist,".CSV")
} else {
out.label=basename(raw.speclist,".CSV")
}
#if individual is selected then write out vm compatible text files
if(individual==1) {
for(i=1;i<=length(out.label);i+=1) {
indiv={}
indiv.data=float(out.data[i])
indiv.xaxis=float(out.xaxis)
indiv.label=out.label[,i]
write_vm(indiv,raw.inputdir+basename(raw.speclist[,i],".CSV")+".txt")
}
}
if(ratw==1) {
out.label=basename(raw.speclist,".CSV")
}
#output the data
write(out,raw.inputdir+raw.hdfname,hdf,force=1)
return(out)
}
define emcal(cold, indiv, libspec, field_spec, resample, ratw, bbhot, bbwarm, dehyd) {
#added support for other names than standard bb names - c.edwards 1-11-08
#added checking for .hdf output suffix - c.edwards 1-11-08
#added dehyd2 support - c.edwards 1-11-08
#fixed spacing/verbosity for ease of viewing - c.edwards 1-11-08
#fixed indiv to write out individual text files- c.edwards 1-11-08
if($ARGC <4) {
printf ("emcal() - Emissivity Calculation of Laboratory Spectra\n\n")
printf (" Computes an instument response function from measured emission, \n")
printf (" spectra of hot and warm blackbody and known blackbody T. \n")
printf (" Then calculates emissivity using previously calculated\n")
printf (" response function, hot bb spectrum, hot sample spectrum,\n")
printf (" and known environment temperature.\n\n")
printf (" NOTE:REQUIRES thm module \n\n")
printf ("usage: $1=directory containing spectra \n")
printf (" $2=hot bb temp \n")
printf (" $3=warm bb temp \n")
printf (" $4=output file name\n")
printf ("\t Optional Arguments\n")
printf (" bbhot=hot black body filename (Default=\"bbhot.CSV\")\n")
printf (" bbwarm=warm black body filename (Default=\"bbwarm.CSV\")\n")
printf (" dehyd=add dehydrated spectra to the output structure (Uses dehyd2()) Default=\"no\"\n")
printf (" indiv=write the spectra out and individual text files with no labels for spectral library Default=\"no\"\n")
printf (" libspec=prompt for input data for spectral library\n")
printf (" resample=resample spectra to xaxis incase OMEGA saved and extra few \n")
printf (" cold=some or all files measured below chamber temperature\n")
printf (" field_spec=calibrate D&P spectra \n")
printf (" ratw=RATW files \n")
printf (" temp=prompt for temperature when sample temperature is known in degrees C\n")
printf (" wn=prompt for wavenumber for sample determination\n\n")
printf (" Written by Alice Baldridge - Thu Jun 15 13:41:16 MST 2006\n\n")
return(NULL)
}
directory = $1
directory=directory+"/"
if(fexists(directory)==0) {
printf("Directory does not exist: %s\n",directory)
printf("Please enter a valid directory\n")
return(NULL)
}
hot_bb_t=$2
if(isnum(hot_bb_t)==0) {
printf("Please enter a number for the Hot Black Body Temperature\n")
return(NULL)
}
warm_bb_t=$3
if(isnum(warm_bb_t)==0) {
printf("Please enter a number for the Warm Black Body Temperature\n")
return(NULL)
}
out=$4
if(type(out)!="STRING"){
printf("please use a string for output filename\n")
return(NULL)
}
pd = strstr(out, ".hdf")
if(pd == 0) {
out = out+".hdf"
}
deh="no"
if (HasValue(dehyd)) deh=dehyd
rat="no"
if (HasValue(ratw)) rat=ratw
ind="no"
if (HasValue(indiv)) ind=indiv
brr="no"
if (HasValue(cold)) brr=cold
lib="no"
if (HasValue(libspec)) lib=libspec
field="no"
if (HasValue(field_spec)) field=field_spec
resamp="no"
if (HasValue(resample)) resamp=resample
if(field=="yes"){
batch_extract(directory)
list =basename( syscall("ls -t "+directory+"*.txt"))
bbhot_name = directory + "WARMBB.WBB.txt"
bbwarm_name = directory + "COLDBB.CBB.txt"
gold_name = directory + "GOLD.DWR.txt"
}else{
list =basename( syscall("ls -t "+directory+"*.CSV"))
bbhot_name = directory + "bbhot.CSV"
bbwarm_name = directory + "bbwarm.CSV"
}
#added support for other names than standard bb names - c.edwards 1-11-08
if(HasValue(bbhot)) bbhot_name=directory+basename(bbhot)
if(HasValue(bbwarm)) bbwarm_name=directory+basename(bbwarm)
if(fexists(bbhot_name)==0 || fexists(bbwarm_name)==0) {
printf("Hot or Warm black body name is incorrect\n")
return(null)
}
len = length(list)
####################################
# read in the black bodies and xaxis
####################################
verbose=0
# structure containing the spectra
spec_struct = {}
# read in bbhot
if(field=="yes"){
tmp=ascii(bbhot_name, format=float)
}else{
tmp = ascii(bbhot_name,format=float,delim=",")
}
# add Xaxis to the spec_struct
spec_struct.xaxis = translate(tmp[1],from=y,to=z)
# add bbhot to spec_struct
spec_struct.hbb = translate(tmp[2],from=y,to=z)
spec_struct.hotbb_temperature=hot_bb_t
# read in bbwarm
if(field=="yes"){
tmp=ascii(bbwarm_name, format=float)
}else{
tmp = ascii(bbwarm_name,format=float,delim=",")
}
# add bbwarm to spect_struct
spec_struct.wbb = translate(tmp[2],from=y,to=z)
spec_struct.warmbb_temperature=warm_bb_t
# read in the gold plate
if(field=="yes"){
tmp=ascii(gold_name, format=float)
spec_struct.gold= translate(tmp[2],from=y,to=z)
}
##############################
# create the response function
##############################
spec_struct.response=(spec_struct.hbb-spec_struct.wbb)/(bbr(spec_struct.xaxis,ctok(hot_bb_t))-bbr(spec_struct.xaxis,ctok(warm_bb_t)))
spec_struct.response=float(spec_struct.response)
xplot(spec_struct.response[1,,],Xaxis=spec_struct.xaxis)
plim(0,4000,0,0)
nullim()
lines()
pause("\nDisplaying Response Function; Press \"Enter\" to continue")
#################################
# fill in the raw data and labels
#################################
spec_names = ""
spectra = spec_struct.xaxis*0
for(i=1;i<=len;i+=1) {
filename = list[,i]
if(field=="yes"){
if(filename !=basename(bbwarm_name) && filename != basename(bbhot_name) && filename != "GOLD.DWR.txt" && filename != "*.asc" && filename != "bbhot.CSV" && filename != "bbwarm.CSV"){
data = translate(ascii(directory+filename,format=float),from=y,to=z)
data = data[2]
extension = strstr(filename,".txt")
filename = filename[:extension-1]
# add to the data block
spec_names = cat(spec_names,filename,axis=y)
spectra = cat(spectra,data,axis=y)
}
}else{
if(filename !=basename(bbhot_name) && filename != basename(bbwarm_name) && filename != "bbhot.CSV" && filename != "bbwarm.CSV") {
data = translate(ascii(directory+filename,format=float,delim=","),from=y,to=z)
xtemp=data[1]
data = data[2]
if (resamp=="yes"){
data = resample(data, xtemp, spec_struct.xaxis).data
}
extension = strstr(filename,".CSV")
filename = filename[:extension-1]
# add to the data block
spec_names = cat(spec_names,filename,axis=y)
spectra = cat(spectra,data,axis=y)
}
}
}
verbose=3
# trim off the blank space of our spectra and spec_names
spec_names = spec_names[,2:]
spectra = spectra[,2:]
# paste these motherfuckers into the structure
spec_struct.raw = spectra
spec_struct.sample_name = spec_names
###################################
# radiance and emissivity calculation
###################################
emissivity=spec_struct.xaxis*0
radiance=spec_struct.xaxis*0
btemp=spec_struct.xaxis*0
dm = dim(spec_struct.raw)[2]
sample_temperature=""
chamber_temperature=""
sample_id=""
quality=""
category=""
latitude=""
longitude=""
location=""
locality=""
particle_size=""
citation=""
type=""
mineral_number=""
chemical_formula=""
subgroup=""
#calculate the gold plate radiance
if(field=="yes"){
gold_T=pause("Enter the gold plate temperature\n")
gold_T=atof(gold_T[,1])
gold_energy=bbr(spec_struct.xaxis, ctok(gold_T))
B_inst=spec_struct.hbb-(spec_struct.response*(bbr(spec_struct.xaxis,ctok(hot_bb_t))))
goldrad = (spec_struct.gold - B_inst)/spec_struct.response
factor=0.04
Ldwr= (goldrad-factor*gold_energy)/(1.0-factor)
}
for(k=1;k<=dm;k+=1) {
name=spec_struct.sample_name[,k]
#determine sample radiance
if(field=="yes"){
B_inst=spec_struct.hbb-(spec_struct.response*(bbr(spec_struct.xaxis,ctok(hot_bb_t))))
samp_T=pause("Enter the sample temperature\n")
samp_T=atof(samp_T[,1])
samp_energy=bbr(spec_struct.xaxis, ctok(samp_T))
rad = (spec_struct.raw[,k] - B_inst)/spec_struct.response
rad = float(rad)
}else{
B_inst=(bbr(spec_struct.xaxis,ctok(hot_bb_t))-(spec_struct.hbb/spec_struct.response))
inst_T=avg(btemp(spec_struct.xaxis[,,208:520],B_inst[,,208:520]))
printf("\nInstrument T is: %.2f\n", ktoc(inst_T))
energy=(bbr(spec_struct.xaxis,inst_T))
if(brr=="yes"){
opt_c=pause("Was "+name+" measured cold? \n")
if(opt_c[1,1] == "y") {
spec_struct.raw[,k]= (-1)*spec_struct.raw[,k]
}
}
rad = ((spec_struct.raw[,k]/spec_struct.response) + energy)
rad = float(rad)
}
#########################
#emissivity calculations
#########################
#determine sample maximum brightnes temperature
B_temp=btemp(spec_struct.xaxis,rad)
B_temp=float(B_temp)
if(field=="yes"){
kern=clone(1,1,20,1)
samp_T=max(thm.convolve(B_temp[1,,],kern)[,,250:500])
n=maxchan(thm.convolve(B_temp[1,,],kern)[,,250:500])+250
samp_T_new=ktoc(samp_T)
emcal_T_wavenumber=spec_struct.xaxis[,,n]
sample_temp=sprintf("%.2f\n",samp_T_new)
samp_T_new=ctok(samp_T_new)
sample_temp=sample_temp[1:(strlen(sample_temp)-1)]
sample_temperature=cat(sample_temperature, sample_temp, axis=y)
}else{
samp_T_new=ctok(30)
kern=clone(1.0,1,1,26)
samp_T=max(thm.convolve(B_temp[1,,],kern)[,,50:831])
if(brr=="yes"){
if(opt_c[1,1] == "y"){
samp_T_new=min(thm.convolve(B_temp[1,,],kern)[,,105:831])
m=minchan(thm.convolve(B_temp[1,,],kern)[,,105:831])+105
emcal_T_wavenumber=spec_struct.xaxis[,,m]
}else{
samp_T_new=samp_T
n=maxchan(thm.convolve(B_temp[1,,],kern)[,,105:831])+105
emcal_T_wavenumber=spec_struct.xaxis[,,n]
}
}else{
samp_T_new=samp_T
n=maxchan(thm.convolve(B_temp[1,,],kern)[,,50:831])+50
emcal_T_wavenumber=spec_struct.xaxis[,,n]
}
printf("Sample T for \""+name+"\" is: %.2f\n",ktoc(samp_T_new))
sample_t=ktoc(samp_T_new)
sample_temp=sprintf("%.2f\n",sample_t)
sample_temp=sample_temp[1:(strlen(sample_temp)-1)]
sample_temperature=cat(sample_temperature, sample_temp, axis=y)
}
printf("Sample T for sample \""+name+"\" is determined at: %.2f cm^-1\n",emcal_T_wavenumber)
B_samp = (bbr(spec_struct.xaxis,samp_T_new))
#determine emissivity
if(field=="yes"){
emis=(rad - Ldwr)/(B_samp-Ldwr)
emis = float(emis)
chamber_temperature="na"
}else{
#determine environmental radiance
env_T=pause("What is the chamber T for \""+name+"\"?\n")
chamber_t=env_T[1:(strlen(env_T)-1)]
if(env_T[1,1]=="q"){
return(0)
}else{
env_T=atof(env_T[,1])
env_rad=(bbr(spec_struct.xaxis,ctok(env_T)))
}
chamber_temperature=cat(chamber_temperature, chamber_t, axis=y)
emis=(((spec_struct.raw[,k]/spec_struct.response)-env_rad+energy)/(B_samp - env_rad))
emis = float(emis)
#water removal for RATW
if (rat=="yes"){
emis=dehyd2(emis,spec_struct.xaxis)
}
}
#plot
xplot(emis[1,,],Xaxis=spec_struct.xaxis)
lines()
plim(2000,200, 0.0, 1.05)
radiance=cat(radiance, rad, axis=y)
btemp=cat(btemp, B_temp, axis=y)
emissivity=cat(emissivity,emis,axis=y)
#####################################################
#enter the spec lib options for the individual files
#####################################################
if(lib=="yes"){
sampid=pause("Enter the sample id for "+name+" \n")
if(sampid == "\n"){
sampleid=""
}else{
sampleid = sampid[1:(strlen(sampid)-1)]
}
sample_id=cat(sample_id,sampleid, axis=y)
gory=pause("Enter the sample deconvolution category for "+name+" \n")
if (gory == "\n"){
egory = ""
}else{
egory = gory[1:(strlen(gory)-1)]
}
category=cat(category, egory, axis=y)
qual=pause("Enter the quality flag for "+name+": 1=Well characterized, pure, 2=Well characterized, minor impurities, 3=Well characterized, major impurities, 4=Not well characterizied\n")
if(qual[1,1]=="\n"){
qu="[4] Not well characterized"
}else{
if(qual[1,1]=="1"){
qu="[1] Well characterized, pure"
}else{
if(qual[1,1]=="2"){
qu="[2] Well characterized, minor impurities"
}else{
if(qual[1,1]=="3"){
qu="[3] Well characterized, major impurities"
}else{
if(qual[1,1]=="4"){
qu="[4] Not well characterized"
}}}}}
quality=cat(quality,qu,axis=y)
lat=pause("Enter the sample latitude for "+name+" \n")
if(lat=="\n"){
la=""
}else{
la=lat[1:(strlen(lat)-1)]
}
latitude=cat(latitude, la, axis=y)
long=pause("Enter the sample longitude for "+name+" \n")
if(long=="\n"){
lo=""
}else{
lo=long[1:(strlen(long)-1)]
}
longitude=cat(longitude, lo, axis=y)
loc=pause("Enter the sample location for "+name+" \n")
if(loc=="\n"){
tion=""
}else{
tion=loc[1:(strlen(loc)-1)]
}
location=cat(location, tion, axis=y)
local=pause("Enter the sample collection locality for "+name+" \n")
if(local=="\n"){
lity=""
}else{
lity=local[1:(strlen(local)-1)]
}
locality=cat(locality, lity, axis=y)
part=pause("Enter the particle size for "+name+" 1=Fine particulate, 2=Coarse particulate, 3=Pebble,4=Handsample\n")
if(part[1,1]=="\n"){
particlesize=""
}else{
if(part[1,1]=="1"){
particlesize="Fine particulate"
}else{
if(part[1,1]=="2"){
particlesize="Coarse particulate"
}else{
if(part[1,1]=="3"){
particlesize="Pebble"
}else{
if(part[1,1]=="4"){
particlesize="Handsample"
}}}}}
particle_size=cat(particle_size, particlesize, axis=y)
cit=pause("Enter the sample citation for "+name+" \n")
if(cit=="\n"){
cite=""
}else{
cite=cit[1:(strlen(cit)-1)]
}
citation=cat(citation, cite, axis=y)
typ=pause("Enter the sample type for "+name+" 1=Mineral/Phase, 2=Rock, 3=Soil/Regolith, 4=Meteorite/Lunar, 5=Other\n")
if(typ[1,1]=="\n"){
ty=""
}else{
if(typ[1,1]=="1"){
ty="Mineral/Phase"
printf("Enter ther dana mineral group for "+name+" \n")
printf("1=Native Elements, 2=Sulfides, 3=Oxides and Hydroxides, \n")
printf("4=Halides, 5=Carbonates, Borates and Nirtates, 6=Sulfates, \n")
printf("Chromates and Molydates, 7=Phosphates, Arsenates and Vanadates,\n")
printf("8=Organic Materials 9=Nesosilicates, 10=Sorosilicates, \n")
printf("11=Cyclosilicates, 12=Inosilicates, 13=Phyllosilicates, \n")
sub=pause("14=Tectosilicates, 15=Other Silicates, 16=Other \n")
if(sub[1,1]=="\n"){
sg=""
}else{
if(sub[1,1]=="1"){
sg="I - Native Elements"
}
if(sub[1:(strlen(sub)-1)]=="2"){
sg="II - Sulfides"
}
if(sub[1:(strlen(sub)-1)]=="3"){
sg="III - Oxides and Hydroxides"
}
if(sub[1:(strlen(sub)-1)]=="4"){
sg="IV - Halides"
}
if(sub[1:(strlen(sub)-1)]=="5"){
sg="V - Carbonates, Nitrates, Borates"
}
if(sub[1:(strlen(sub)-1)]=="6"){
sg="VI - Sulfates, Chromates, Molybdates"
}
if(sub[1:(strlen(sub)-1)]=="7"){
sg="VII - Phosphates, Arsenates, Vanadates"
}
if(sub[1:(strlen(sub)-1)]=="8"){
sg="IX - Organic Minerals"
}
if(sub[1:(strlen(sub)-1)]=="9"){
sg="VIII - Silicates - Nesosilicates (e.g. Olivine, Garnet)"
}
if(sub[1:(strlen(sub)-1)]=="10"){
sg="VIII - Silicates - Sorosilicates (e.g. Epidote)"
}
if(sub[1:(strlen(sub)-1)]=="11"){
sg="VIII - Silicates - Cyclosilicates (e.g. Tourmaline, Beryl)"
}
if(sub[1:(strlen(sub)-1)]=="12"){
sg="VIII - Silicates - Inosilicates (e.g. Pyroxene, Amphibole)"
}
if(sub[1:(strlen(sub)-1)]=="13"){
sg="VIII - Silicates - Phyllosilicates (e.g. Micas, Clays)"
}
if(sub[1:(strlen(sub)-1)]=="14"){
sg="VIII - Silicates - Tektosilicates (e.g. Quartz, Feldspars, Zeolites)"
}
if(sub[1:(strlen(sub)-1)]=="15"){
sg="VIII - Silicates - Other Silicates"
}
if(sub[1:(strlen(sub)-1)]=="16"){
sg="Other"
}}
minnum=pause("Enter the dana mineral number for "+name+" \n")
if(minnum=="\n"){
num=""
}else{
num=minnum[1:(strlen(minnum)-1)]
}
form=pause("Enter the chemical formula for "+name+" \n")
if(form=="\n"){
fo=""
}else{
fo=form[1:(strlen(form)-1)]
}
}
if(typ[1,1]=="2"){
ty="Rock"
num=""
fo=""
printf("Enter the rock subgroup for "+name+" \n")
printf("1=Igneous, 2=Sedimentary, 3=Metamorphic, \n")
sub=pause("4=Other\n")
if(sub[1,1]=="\n"){
sg=""
}else{
if(sub[1,1]=="1"){
sg="Igneous"
}else{
if(sub[1,1]=="2"){
sg="Sedimentary"
}else{
if(sub[1,1]=="3"){
sg="Metamorphic"
}else{
if(sub[1,1]=="4"){
sg="Other"
}}}}}
}
if(typ[1,1]=="3"){
ty="Soil/Regolith"
num=""
fo=""
sub=pause("Enter the soil/regolith subgroup for "+name+" \n")
if(sub=="\n"){
sg=""
}else{
sg=sub[1:(strlen(sub)-1)]
}
}
if(typ[1,1]=="4"){
ty="Meteorite/Lunar"
num=""
fo=""
printf("Enter the meteorite/lunar subgroup for "+name+" \n")
printf("1=Chondrite, 2=Primitive achondrite, 3=Asteroid/Lunar/Martian achondrite, \n")
sub=pause("4=Iron/stoney-iron achondrite \n")
if(sub[1,1]=="\n"){
sg=""
}else{
if(sub[1,1]=="1"){
sg="Chondrite"
}
if(sub[1,1]=="2"){
sg="Primitive achondrite"
}
if(sub[1,1]=="3"){
sg="Asteroid/Lunar/Martian achondrite"
}
if(sub[1,1]=="4"){
sg="Iron/Stoney-iron achondrite"
}}
}
if(typ[1,1]=="5"){
ty="Other"
}
}
type=cat(type, ty, axis=y)
mineral_number=cat(mineral_number, num, axis=y)
subgroup=cat(subgroup, sg, axis=y)
chemical_formula=cat(chemical_formula, fo, axis=y)
#close the lib=yes loop
}
#close the for loop
}
###############################
#Put everything in the structure
###############################
sample_temperature=sample_temperature[,2:]
spec_struct.sample_temperature=sample_temperature
chamber_temperature=chamber_temperature[,2:]
spec_struct.chamber_temperature=chamber_temperature
radiance= radiance[,2:]
spec_struct.radiance=radiance
btemp=btemp[,2:]
spec_struct.btemp=btemp
emissivity = emissivity[,2:]
spec_struct.data = emissivity
if (lib=="yes"){
sample_id=sample_id[,2:]
spec_struct.sample_id=sample_id
category=category[,2:]
spec_struct.category=category
quality = quality[,2:]
spec_struct.quality=quality
latitude=latitude[,2:]
spec_struct.latitude=latitude
longitude=longitude[,2:]
spec_struct.longitude=longitude
location=location[,2:]
spec_struct.sample_location=location
locality=locality[,2:]
spec_struct.collection_locality=locality
particle_size=particle_size[,2:]
spec_struct.particle_size=particle_size
citation=citation[,2:]
spec_struct.citation=citation
type=type[,2:]
spec_struct.group=type
mineral_number=mineral_number[,2:]
spec_struct.dana_mineral_number=mineral_number
chemical_formula=chemical_formula[,2:]
spec_struct.chemical_formula=chemical_formula
subgroup=subgroup[,2:]
spec_struct.type_subgroup=subgroup
}
###################################
# speclib fields "Spectral Info"(optional)
###################################
if(lib=="yes"){
date=pause("Enter the date that the spectra were acquired e.g. 2006-09-30 \n")
spec_struct.analysis_date= date[1:(strlen(date)-1)]
printf("Enter the spectrometer on which that the spectra were acquired:\n")
printf("1 = Nicolet Nexus 670 FTIR,2= Nicolet Nexus 470 FTIR,\n")
inst=pause("3 = D&P Field Spectrometer, 4 = Mattson-Cygnus 100 FTIR \n")
if(inst[1,1]=="1"){
spec_struct.instrument= "Nicolet Nexus 670 FTIR"
}else{
if(inst[1,1]=="2"){
spec_struct.instrument= "Nicolet Nexus 470 FTIR"
}else{
if(inst[1,1]=="3"){
spec_struct.instrument= "D&P Field Spectrometer Model 100-IR"
}else{
if(inst[1,1]=="4"){
spec_struct.instrument= "Mattson-Cygnus 100 FTIR"
}else{
spec_struct.instrument=inst[1:(strlen(inst)-1)]
}}}}
wn_low=pause("Enter the lower wavenumber range in cm-1\n")
spec_struct.wavenum_range_low = wn_low[1:(strlen(wn_low)-1)]
wn_hi=pause("Enter the upper wavenumber range in cm-1\n")
spec_struct.wavenum_range_high = wn_hi[1:(strlen(wn_hi)-1)]
res=pause("Enter the spectral resolution in cm-1\n")
spec_struct.resolution=res[1:(strlen(res)-1)]
fov=pause("Enter the field of view in centimeters\n")
spec_struct.field_of_view=fov[1:(strlen(fov)-1)]
person=pause("Enter the name of the person who acquired the spectra\n")
spec_struct.spectral_analysis_person=person[1:(strlen(person)-1)]
lab=pause("Enter the source lab for the spectra : 1=ASU, 2=UofH, 3=Brown, 4=Pitt, 5=Indian Inst of Tech, 6=Other \n")
if(lab[1,1]=="1"){
spec_struct.source_lab="Arizona State University"
}else{
if(lab[1,1]=="2"){
spec_struct.source_lab="University of Hawaii"
}else{
if(lab[1,1]=="3"){
spec_struct.source_lab="Brown University"
}else{
if(lab[1,1]=="4"){
spec_struct.source_lab="University of Pittsburg"
}else{
if(lab[1,1]=="5"){
spec_struct.source_lab="Indian Institute of Technology"
}else{
if(lab[1,1]==""){
spec_struct.source_lab="Other"
}}}}}}
}
###################################
# write data to file
###################################
if(deh=="yes") {
printf("\nRunning dehyd2()\n")
spec_struct.orig_data=spec_struct.data
spec_struct.data=dehyd2(spec_struct.orig_data,spec_struct.xaxis)
}
write(spec_struct,directory + out,hdf, force=1)
indiv=struct()
len2=dim(spec_struct.data)[2]
if (rat=="yes"){
for(l=1;l<=len2;l+=1) {
indiv.xaxis=spec_struct.xaxis
indiv.label="emcal emissivity of " + spec_struct.sample_name[,l]
indiv.data=spec_struct.data[,l]
write_vm(indiv,directory + spec_struct.sample_name[,l] + ".txt")
}
}
if (ind=="yes"){
printf("Writing individual files\n")
for(l=1;l<=len2;l+=1) {
indiv.data=spec_struct.data[,l]
indiv.xaxis=spec_struct.xaxis
indiv.label=spec_struct.sample_name[,l]
write_vm(indiv,directory + indiv.label + ".txt")
}
}
return(spec_struct)
}
define dehyd2() {
#added $DV_EX support
#Added $DV_SCRIPT_FILES support - 5-13-08
if($ARGC==0) {
printf("\n\"Dehydrate\" a lab spectrum\n")
printf("A resampled ratio of water sensitive bands is computed and compared to a pure water specturm \n\n")
printf("$1 = emissivity data\n")
printf("$2 = Xaxis\n")
printf("stolen from j.bandfield (c.edwards Oct 10,2006)\n\n")
return(null);
}
dehyd_water_data=$1
xaxis=$2
verbose=0
dehyd_water=read_vm($DV_SCRIPT_FILES+"/dehyd_water.txt")
dehyd_water=resample(dehyd_water.data,dehyd_water.xaxis,xaxis)
verbose=3
wat_index=1-(avg((dehyd_water.data[,,16]//dehyd_water.data[,,26]//dehyd_water.data[,,30]//dehyd_water.data[,,42]//dehyd_water.data[,,43]//dehyd_water.data[,,55]//dehyd_water.data[,,66]//dehyd_water.data[,,68]//dehyd_water.data[,,80])/(dehyd_water.data[,,12]//dehyd_water.data[,,22]//dehyd_water.data[,,32]//dehyd_water.data[,,39]//dehyd_water.data[,,46]//dehyd_water.data[,,57]//dehyd_water.data[,,64]//dehyd_water.data[,,70]//dehyd_water.data[,,78]))+avg((dehyd_water.data[,,634]//dehyd_water.data[,,643]//dehyd_water.data[,,653]//dehyd_water.data[,,679]//dehyd_water.data[,,687]//dehyd_water.data[,,697]//dehyd_water.data[,,706]//dehyd_water.data[,,755]//dehyd_water.data[,,771]//dehyd_water.data[,,780]//dehyd_water.data[,,788]//dehyd_water.data[,,797])/(dehyd_water.data[,,631]//dehyd_water.data[,,645]//dehyd_water.data[,,651]//dehyd_water.data[,,677]//dehyd_water.data[,,683]//dehyd_water.data[,,700]//dehyd_water.data[,,709]//dehyd_water.data[,,758]//dehyd_water.data[,,769]//dehyd_water.data[,,775]//dehyd_water.data[,,785]//dehyd_water.data[,,793])))*0.5
for(i=1;i<=dim(dehyd_water_data)[1];i+=1) {
for(j=1;j<=dim(dehyd_water_data)[2];j+=1) {
index=1-(avg((dehyd_water_data[i,j,16]//dehyd_water_data[i,j,26]//dehyd_water_data[i,j,30]//dehyd_water_data[i,j,42]//dehyd_water_data[i,j,43]//dehyd_water_data[i,j,55]//dehyd_water_data[i,j,66]//dehyd_water_data[i,j,68]//dehyd_water_data[i,j,80])/(dehyd_water_data[i,j,12]//dehyd_water_data[i,j,22]//dehyd_water_data[i,j,32]//dehyd_water_data[i,j,39]//dehyd_water_data[i,j,46]//dehyd_water_data[i,j,57]//dehyd_water_data[i,j,64]//dehyd_water_data[i,j,70]//dehyd_water_data[i,j,78]))+avg((dehyd_water_data[i,j,634]//dehyd_water_data[i,j,643]//dehyd_water_data[i,j,653]//dehyd_water_data[i,j,679]//dehyd_water_data[i,j,687]//dehyd_water_data[i,j,697]//dehyd_water_data[i,j,706]//dehyd_water_data[i,j,755]//dehyd_water_data[i,j,771]//dehyd_water_data[i,j,780]//dehyd_water_data[i,j,788]//dehyd_water_data[i,j,797])/(dehyd_water_data[i,j,631]//dehyd_water_data[i,j,645]//dehyd_water_data[i,j,651]//dehyd_water_data[i,j,677]//dehyd_water_data[i,j,683]//dehyd_water_data[i,j,700]//dehyd_water_data[i,j,709]//dehyd_water_data[i,j,758]//dehyd_water_data[i,j,769]//dehyd_water_data[i,j,775]//dehyd_water_data[i,j,785]//dehyd_water_data[i,j,793])))*0.5
ratio=index/wat_index
fix=1-((1-dehyd_water.data)*ratio)
dehyd_water_data[i,j]=float(dehyd_water_data[i,j]/fix)
}
}
#vm code
# index=1-(avg(dehyd_water_data[,,16//26//30//42//43//55//66//68//80]/dehyd_water_data[,,12//22//32//39//46//57//64//70//78])+avg(dehyd_water_data[,,634//643//653//679//687//697//706//755//771//780//788//797]/dehyd_water_data[,,631//645//651//677//683//700//709//758//769//775//785//793]))*0.5
# wat_index=1-(avg(dehyd_water.data[,,16//26//30//42//43//55//66//68//80]/dehyd_water.data[,,12//22//32//39//46//57//64//70//78])+avg(dehyd_water.data[,,634//643//653//679//687//697//706//755//771//780//788//797]/dehyd_water.data[,,631//645//651//677//683//700//709//758//769//775//785//793]))*0.5
return(dehyd_water_data)
}
define sublib() {
if($ARGC==0) {
printf("Subset a spectral library structure\n\n")
printf("$1 = library structure\n")
printf("$2 = subet() string\n\n")
printf("NOTE: This function uses subset(). See the subset() help for more information\n\n")
printf("C.Edawrds 4-8-11\n\n")
return(null)
}
lib=$1
if($ARGC<2) {
subsetstr=""
} else {
subsetstr=$2
}
sublib={}
key=get_struct_key(lib)
for(i=1;i<=length(lib);i+=1) {
data=lib[i]
if(type(data)!="TEXT") {
if(dim(data)[1]==1 && dim(data)[2]!=1) {
tmp=subset(data,y=strsub(subsetstr,",",""))
printf("Data in X\n")
} else if (dim(data)[1]!=1 && dim(data)[2]==1) {
tmp=subset(data,x=strsub(subsetstr,",",""))
printf("Data in y\n")
} else if (dim(data)[1]!=1 && dim(data)[2]!=1) {
tmp=subset(data,subsetstr)
} else {
tmp=data
}
} else {
tmp=subset(data,y=strsub(subsetstr,",",""))
printf("Data is TEXT\n")
}
add_struct(obj=sublib,name=key[,i],value=tmp)
}
return(sublib)
}
define sma(wave1,wave2,surface,bb,band,group,forceall,exclude,sort,noerr,resample,notchco2,nn) {
if ($ARGC < 2 || $ARGC > 3) {
printf (" \n")
printf (" sma=spectral mixture analysis \n")
printf (" \n")
printf (" $1 = mixed cube (or structure with .data and .xaxis elements)\n")
printf (" $2 = endmembers. $2 can be a standard structure with at least the following \n")
printf (" elements: .data(arranged [#specs-x, #specs-y, #bands]), .label, \n ")
printf (" and .xaxis (arranged [1,1,x-axis values]) or may be an array (arranged \n ")
printf (" [#specs-x, #specs-y, #bands] \n")
printf (" \n")
printf (" $1 and $2 must have an equal number of spectral bands. \n")
printf (" \n")
printf (" [$3] = endmembers to be forced despite negative concentrations (optional). The \n")
printf (" forced library must be in the same format as $2 \n")
printf (" elements. \n")
printf (" \n")
printf ("Options: \n")
printf (" surface =1 for atm-removed and modeled surface spectra in addition to normal output \n")
printf (" wave1 = wavenumber/micron/channel value for modeling (low); default=400 cm-1 \n")
printf (" wave2 =wavebumber/micron/channel value for modeling (high); default=1600 cm-1 \n")
printf (" band = 1 if wave1 and wave2 are given in channel numbers, instead of frequency (cm-1) \n")
printf (" or wavelength \n")
printf (" bb = 0 do not add blackbody to endmember matrix; bb added by default \n")
printf (" group = 1 additional output of model-derived modes summed by mineral group (eg. feldspar \n ")
printf (" abundance, pyroxene abundance). $2 must contain .group. Default is 1\n ")
printf (" \n")
printf (" forceall = 1 to keep negative endmember percentages (requires nn = 0 as well)\n")
printf (" exclude= vector list of endmembers to exclude (ex:2//39//40). \n")
printf (" noerr=1 do not calculate statistical errors (recommended for large cubes) \n")
printf (" resample=1 resample the mixed cube structure to the endmember library (default=0)\n")
printf (" resample=2 resample the endmember library to the mixed cube structure (default=0)\n")
printf (" sort = 1 if you want abundances sorted for each pixel; default is sorting \n")
printf (" notchco2 = 1 automatically remove CO2 band in data/library/forced centered at 669 +/- 74 wn\n")
printf (" notchco2 = N removve CO2 band in data/library/forced centered at 669 +/- N wn (Default is 0)\n")
printf (" nn = 0 (default) to use old fitting algorithm\n")
printf (" nn = 1 to use algorithm optimized for nonnegative least squares\n")
printf (" (NNLS, outlined in Lawson & Hanson 1974), which is faster and more accurate\n")
printf ("\n\n")
printf (" Examples: \n")
printf (" minlib=read('my_mineral_lib.hdf') \n")
printf (" atmlib=read('my_atm_lib.hdf') \n")
printf (" nw_scene=read('mtes_nw_raster.hdf') \n")
printf (" \n")
printf (" final=sma(nw_scene.spec, minlib, atmlib,wave1=230, wave2=1400,surface=1) \n")
printf (" --> Unmix the entire scene with mineral and atm endmembers, between 230-1400 cm-1, \n")
printf (" return normalized concentrations and atm-removed emissivity in addition to normal output. \n")
printf (" \n")
printf (" final2=sma(nw_scene.spec[1:30,1:30,], minlib, band=1, wave1=3, wave2=160) \n")
printf (" --> Unmix the top 30x30 spectra in the cube with mineral endmembers only, between channels \n")
printf (" 3-160. \n")
printf (" \n")
printf (" See also sort_cube, sum_group_conc, summary_sma, and summary_sma_group \n")
printf (" \n")
return(0)
}
# deanne rogers 12/2007
# modified to handle resample option 5/16/08 cedwards
# modified to add notchco2 option from deconvolve 7/30/10
# Modified by S. Marshall, 11-23-2010 (added nn)
# Modified to check for spectral libraries in the correct direction (for some reason that is x as it completely fails if its in y) 2-3-2011
# Read in emissivity spectra and library(ies)
em_cube=$1
libstruc=$2
if(HasValue(sort)==0) {
sort=1
}
if(HasValue(surface)==0) {
surface=0
}
#check for groups
if(type(libstruc)=="STRUCT") {
if(HasValue(get_struct(libstruc,"group"))) {
if(HasValue(group)==0) {
group=1
}
} else {
if(HasValue(group)==0) {
group=1
}
}
} else {
if(HasValue(group)==0) {
group=0
}
}
# Create output structure
smaout=struct()
#The spectral library ouputs spectra in a fashion that is not useable by sma (so make it useable)
if(type(libstruc)=="STRUCT") {
if(HasValue(get_struct(libstruc,"sample_id")) && HasValue(get_struct(libstruc,"shortlabel"))==0){
libstruc=reform_speclib(libstruc)
}
#unfortunately now we check to make sure the data is in the x direction for the library.
if(dim(libstruc.data)[1]==1 && dim(libstruc.data)[2]>=1) {
libstruc.data=translate(libstruc.data,y,x)
}
} else {
if(dim(libstruc)[1]==1 && dim(libstruc)[2]>=1) {
libstruc=translate(libstruc,y,x)
}
}
if($ARGC==3) {
atmstruc=$3
if(type(atmstruc)=="STRUCT") {
if(HasValue(get_struct(atmstruc,"sample_id")) && HasValue(get_struct(atmstruc,"shortlabel")) == 0) {
atmstruc=reform_speclib(atmstruc)
}
#unfortunately now we check to make sure the data is in the x direction for the library.
if(dim(atmstruc.data)[1]==1 && dim(atmstruc.data)[2]>=1) {
atmstruc.data=translate(atmstruc.data,y,x)
}
} else {
if(dim(atmstruc)[1]==1 && dim(atmstruc)[2]>=1) {
atmstruc=translate(atmstruc,y,x)
}
}
}
#check to see if we can resample
verbose=0
if(HasValue(resample)==0) resample=0
if((resample==1 || resample==2) && (type(em_cube)!="STRUCT" || HasValue(get_struct(em_cube,"data"))==0 || HasValue(get_struct(em_cube,"xaxis"))==0)) {
printf("A mixed structure with .data and .xaxis elements is requred for the \"resample\" option\n")
return(null)
}
#if the em_cube is a struct the we can possibly resample
if(type(em_cube)=="STRUCT") {
#set up labels for summary_sma(_group)
if(HasValue(get_struct(em_cube,"sample_name"))) smaout.sample_name=em_cube.sample_name
if(HasValue(get_struct(em_cube,"label"))) smaout.label=em_cube.label
#resample the spectra to the endmember library
if(resample==1 && HasValue(get_struct(em_cube,"xaxis")) && HasValue(get_struct(em_cube,"data")) && HasValue(get_struct(libstruc,"xaxis"))) {
smaout.original={}
em_cube.data=float(em_cube.data)
em_cube.xaxis=float(em_cube.xaxis)
smaout.original.data=em_cube.data
smaout.original.xaxis=em_cube.xaxis
if($DV_OS=="win") {
em_cube.data=resampleudf(em_cube.data,em_cube.xaxis,libstruc.xaxis).data
} else {
em_cube.data=resample(em_cube.data,em_cube.xaxis,libstruc.xaxis).data
}
} else if (resample==1 && (HasValue(get_struct(em_cube,"xaxis"))==0 || HasValue(get_struct(em_cube,"data"))==0 || HasValue(get_struct(libstruc,"xaxis"))==0)){
printf("Mixed cube strucure with .xaxis and .data elements is required for the \"resample=1\" option\n")
printf("Additionally an endmember strucutre with a .xaxis element is required\n")
verbose=1
return(null)
}
#resample the endmember library to the spectra
if(resample==2 && HasValue(get_struct(em_cube,"data")) && HasValue(get_struct(libstruc,"data")) && HasValue(get_struct(libstruc,"xaxis"))) {
libstruc.original={}
em_cube.data=float(em_cube.data)
em_cube.xaxis=float(em_cube.xaxis)
libstruc.original.data=libstruc.data
libstruc.original.xaxis=libstruc.xaxis
if($DV_OS=="win") {
libstruc.data=resampleudf(libstruc.data,libstruc.xaxis,em_cube.xaxis).data
} else {
libstruc.data=resample(libstruc.data,libstruc.xaxis,em_cube.xaxis).data
}
libstruc.xaxis=em_cube.xaxis
} else if(resample==2 && (HasValue(get_struct(em_cube,"data"))==0 || HasValue(get_struct(libstruc,"data"))==0 || HasValue(get_struct(libstruc,"xaxis"))==0)) {
printf("Mixed cube strucure with .xaxis and .data elements is required for the \"resample=2\" option\n")
printf("Additionally an endmember structure with .xaxis and .data elements is required\n")
verbose=1
return(null)
}
if(HasValue(get_struct(em_cube,"data"))){
em_cube=em_cube.data
} else if (HasValue(get_struct(em_cube,"data"))==0){
printf("No .data element was found in the mixed structure. Unable to continue.\n")
verbose=1
return(null)
}
} else {
em_cube=float(em_cube)
}
verbose=1
# Set flags for later use
labelflag=1
grpflag=1
# Determine if library is standard structure
if (type(libstruc)=="STRUCT"){
libstruc.data=float(libstruc.data)
if (HasValue(libstruc.data)==1) {
endmem=libstruc.data
libchan=dim(endmem)
} else {
endmem=libstruc
libchan=dim(endmem)
}
# Check if library has labels
if (HasValue(libstruc.label)==1) {
names=libstruc.label
} else{
names=0
labelflag=0
}
# Check if library has xaxis
if (HasValue(libstruc.xaxis)==1) {
x_ax=libstruc.xaxis
} else {
x_ax=create(1,1,libchan[3],start=1,step=1,format=float,org=bsq)
}
# If group=1 option was selected, check if library has groups
if(group==1) {
if (HasValue(libstruc.group)==1){
grpnames=libstruc.group
} else {
grpnames=0
grpflag=0
}
}
} else {
libstruc=float(libstruc)
endmem=libstruc
libchan=dim(endmem)
x_ax=create(1,1,libchan[3],start=1,step=1,format=float,org=bsq)
names=0
labelflag=0
grpnames=0
grpflag=0
if (HasValue(band)==0) {
wave1=1
wave2=dim(em_cube)[3]
printf("No wavenumber x-axis found. Using full spectral range. \n")
}
}
# Check that library and em_cube have the same number of channels
dimend=dim(em_cube)
if (dimend[3] != libchan[3]) {
printf(" $1 and $2 must have the same z-dimension. \n")
return(0)
}
if(sum(sum(endmem,axis=z)==0)!=0) {
printf("\nOne of the endmembers in your endmember library is composed of all zeros\n")
printf("Please check your library and try again\n\n")
return(null)
}
#Here is an auto/custom crop for the co2 band
if(HasValue(notchco2)==0){
notchco2=0
} else {
co2wn=669
if(notchco2==1) {
# use default value of 7 (historical)
# was 7 tes bands and is now stored as equivalent mini-TES wavenumbers
wco2 = 74.06
} else {
wco2 = notchco2
}
co2chan=int(round(interp(create(1,1,dim(x_ax)[3],start=1),x_ax,co2wn)))
#scale wavenumbers to channels
dwavex=x_ax[,,co2chan+1]-x_ax[,,co2chan]
nco2 = int(round(wco2/dwavex))
co2low = co2chan - nco2
co2high = co2chan + nco2
# emissivity cube
etmp = cat(em_cube[,,1:co2low], em_cube[,,co2high:], z)
em_cube = etmp
# library spectra
mtmp = cat(endmem[,,1:co2low], endmem[,,co2high:], z)
endmem = mtmp
# xaxis
xtmp = cat(x_ax[,,1:co2low], x_ax[,, co2high:], z)
x_ax = xtmp
if(type(libstruc)=="STRUCT") {
if(HasValue(libstruc.xaxis)==1) {
libstruc.xaxis=x_ax
libstruc.data=endmem
}
}
if(type(em_cube)=="STRUCT") {
if(HasValue(em_cube.xaxis)) {
em_cube.xaxis=x_ax
em_cube.data=em_cube
}
}
smaout.notchco2={}
smaout.notchco2.wco2=wco2
smaout.notchco2.co2chanlow=co2low
smaout.notchco2.co2chanhigh=co2high
smaout.notchco2.dwavex=dwavex
smaout.notchco2.co2low=co2wn-wco2
smaout.notchco2.co2high=co2wn+wco2
libchan=dim(endmem)
dimend=dim(em_cube)
}
#setup the output xaxis for easy plotting later.
smaout.xaxis=x_ax
#Check if there is an atmospheric library
if ($ARGC==3) {
smaout.forcedlib=atmstruc
#Check if atmospheric library is standard structure
if(type(atmstruc)=="STRUCT"){
if (HasValue(atmstruc.data)==1) {
norem=atmstruc.data
} else {
norem=atmstruc
}
#Check that the atm library has an xaxis
if (HasValue(atmstruc.xaxis)==1) {
atmxax=atmstruc.xaxis
} else {
atmxax=create(1,1,dim(norem)[3],start=1,step=1,format=float,org=bsq)
}
#Check that the atm library has labels
if (HasValue(atmstruc.label)==1) {
atmnames=atmstruc.label
} else {
atmnames=0
if (labelflag!=0) {
printf(" $2 and $3 must both have labels or both not have labels. \n")
}
}
# Check that the atm library has group names
if(group==1) {
if (HasValue(atmstruc.group)==1) {
atmgrpnames=atmstruc.group
} else {
atmgrpnames=0
if (grpflag!=0) {
printf(" $2 and $3 must both have group labels or both not have group labels. \n")
return(0)
}
}
}
} else {
#if the atmstruc is not a structure, we go by index only
norem=atmstruc
atmxax=create(1,1,dim(norem)[3],start=1,step=1,format=float,org=bsq)
atmnames=0
if (labelflag!=0) {
printf(" $2 and $3 must both have labels or both not have labels. \n")
}
atmgrpnames=0
if (grpflag!=0) {
printf(" $2 and $3 must both have group labels or both not have group labels. \n")
}
}
#again with the auto/custom co2 band removal (this time for the forcedlib)
if(notchco2!=0) {
co2chan=int(round(interp(create(1,1,dim(atmxax)[3],start=1),atmxax,co2wn)))
#scale wavenumbers to channels
dwavex=atmxax[,,co2chan+1]-atmxax[,,co2chan]
nco2 = int(round(wco2/dwavex))
co2low = co2chan - nco2
co2high = co2chan + nco2
# emissivity cube
noremtmp = cat(norem[,,1:co2low], norem[,,co2high:], z)
norem=noremtmp
# xaxis
atmxaxtmp = cat(atmxax[,,1:co2low], atmxax[,, co2high:], z)
atmxax=atmxaxtmp
if(type(smaout.forcedlib)=="STRUCT") {
if(HasValue(smaout.forcedlib.xaxis)==1) {
smaout.forcedlib.xaxis=atmxax
smaout.forcedlib.data=norem
}
}
}
#Check that the two libraries have the same number of channels
if (libchan[3] != dim(norem)[3]) {
printf(" $2 and $3 must have the same z-dimension. \n")
return(0)
}
#Cat atmospheric endmembers onto libst
endmem=cat(endmem,norem,x)
#Determine number of forced lib spectra
forced_specs=dim(norem)[1]
} else {
forced_specs=0
smaout.forcedlib=struct()
smaout.forcedlib.label="none"
}
# Remember full size of library so that it can be expanded back to original size later
dimfull=dim(endmem)
# Reduce library if exclude option is set (set excluded endmembers to zero)
if (HasValue(exclude)) {
smaout.excluded=int(translate(unique(sort(exclude)),y,x))
temp_end=endmem[1]
countv=1
count=1
while(count <= dim(endmem)[1]) {
while(countv<=dim(smaout.excluded)[1]) {
if(count==smaout.excluded[countv]) {
countv=countv+1
} else {
temp_end=cat(temp_end,endmem[count],x)
}
count=count+1
}
if(count <= dim(endmem)[1]) {
temp_end=cat(temp_end,endmem[count],x)
}
count=count+1
}
endmem=temp_end[2:]
}
# Determine number of endmembers not to be removed, add blackbody spectrum to library if requested
# There was previously a problem with this part
# Flat blackbody spectrum was added to endmem if bb omitted, but not if bb=1
# Fixed 11/23/2010
if (HasValue(bb)==1) {
if (equals(bb, 0) || equals(bb, 1)) { # Now checking to ensure that bb is either 0 or 1
bbval=bb
} else {
printf("Error! Value for bb must be 0 or 1!\n")
return(byte(0))
}
} else {
bbval=1
#endmem=cat(endmem,create(1,1,dim(endmem)[3],format=float,start=1,step=0),x) # This belongs outside
}
if (bbval == 1) {
endmem=cat(endmem,clone(float(1), 1,1,dim(endmem)[3]),x)
}
num_no_rem=forced_specs+bbval
# Check if errors should be calculated
if(HasValue(noerr)==1) {
no_calc_error=1
}else{
no_calc_error=0
}
# Determine wavelength range from user input
if (HasValue(wave1)) {
wv1=wave1
} else {
wv1=400
}
if (HasValue(wave2)){
wv2=wave2
} else {
wv2=1600
}
#Crop xaxis according to user input
if (HasValue(band)==1){ # if wave1 and wave 2 are input as channels
stband=wv1
endband=wv2
new_xax=x_ax[,,stband:endband]
new_endmem=endmem[,,stband:endband]
new_cube=em_cube[,,stband:endband]
} else {
# Convert wavenumber or micron start/stop input into channel/index start/stop bands
if (wv1 < x_ax[,,1]) {
stband=1
} else {
count=1
while(x_ax[,,count] < wv1) {
count=count+1
}
stband=count
}
if (x_ax[,,libchan[3]] <= wv2) {
endband=libchan[3]
} else {
count=1
while(x_ax[,,libchan[3]-count] > wv2) {
count=count+1
}
endband=libchan[3]-count
}
if (endband < stband) { #If the library xaxis (e.g., THEMIS) is backwards, switch the start and end channels
tmpband=stband
stband=endband
endband=tmpband
}
new_xax=x_ax[,,stband:endband]
new_endmem=endmem[,,stband:endband]
new_cube=em_cube[,,stband:endband]
}
# Determine whether to use optimimal nonnegative least squares algorithm or original sma algorithm
# Added 11/23/2010
if (HasValue(nn) == 1) {
if (equals(nn, 0) || equals(nn, 1)) { # Now checking to ensure that nn is either 0 or 1
nnval = nn
} else {
printf("\nError! Value for nn must be 0 or 1!\n\n")
return(byte(0))
}
} else {
nnval = 0 # By default, it will NOT use the nnls algorithm
}
# Transpose endmember matrix for matrix operations
new_endmem=translate(new_endmem,y,z)
new_xax=translate(new_xax,y,z)
# Get dimensions of emissivity cube and endmembers
mixvecs=dim(new_cube)
cnt=dim(new_endmem)
nend=cnt[1]
nsamp=(cnt[2])
# Warn user of underdetermined solution
if (nend > nsamp) {
printf ("You have more endmembers (%i) than bands (%i). \n",nend,nsamp)
return(0)
}
# Take strips off the cube and stack in the y-direction
em=new_cube[1,,]
em=translate(em, from=z, to=x)
count=2
for (count=2; count<=mixvecs[1,,]; count+=1){
# while (count <= mixvecs[1,,])
# em_temp=translate(new_cube[(count),,],from=x, to=y)
em_temp=translate(new_cube[(count),,],from=z, to=x)
em=cat(em,em_temp,y)
# count=count+1
}
emd = dim(em)
#create empty error matrix for populating
st_err=clone(float(0), nend,emd[2])
# Finally, to the core. Create transpose and square endmember matrix.
endmemT=translate(new_endmem,x,y)
emT=translate(em, from=x, to=y)
square=mxm(endmemT,new_endmem)
covm = byte(0) # Giving it an initial value, to avoid errors later if no_calc_error != 0
# Core section (different depending on value of nn) begins here
if (nnval == 0) { # Will use original algorithm
# Invert endmember matrix
square=minvert(square)
# Multiply inverse square matrix by endmember matrix.
sq_end=mxm(new_endmem,square)
# Multiply sq_end by array of emiss spectra producing the percentage matrix
perc=mxm(em,sq_end)
# Detect mixed spectra with neg. endmember percentages, loop through each spectrum
npositive=dim(new_endmem)
npositive=(npositive[1]-num_no_rem)
} else { # If nn == 1
# Main block
cnt1 = 1 # Counter to iterate through each (mixed) test spectrum
perc = clone(double(-32768), emd[2], nend)
if (num_no_rem == 0) { # If there's no blackbody component to be included, this is easy
for (cnt1 = 1; cnt1 <= emd[2]; cnt1++) {
perc[cnt1,] = lsqnn(new_endmem, emT[cnt1,], 0)
}
} else { # Need to be careful with forced endmembers
# Must call lsqsn to handle forced endmembers
for (cnt1 = 1; cnt1 <= emd[2]; cnt1++) {
perc[cnt1,] = lsqsn(new_endmem, emT[cnt1,], num_no_rem, 0)
}
}
perc=translate(perc,x,y) # So that it's in the proper shape for the next loop
}
if (HasValue(forceall)==0 || nnval!=0) { #If you don't want negative percentages, do this loop. Otherwise, skip to the end.
# If forceall == 1 and nn == 1, it has already used the nnls algorithm, and all concentrations will be positive
cnt1=1
while (cnt1 <= emd[2]) {
if (nnval == 0) {
# Compose library w/ no negative endmembers. Loop until no negative surface concentrations.
iterflag=0
while (min(perc[1:npositive,cnt1])<0) {
# Find positive percentages and add to new endmember matrix
newlib=new_endmem[1]
cnt2=1
while (cnt2 <= npositive) {
if (perc[cnt2,cnt1] > 0) {
newlib=newlib//new_endmem[cnt2]
}
cnt2=cnt2+1
}
if (bbval==1 || num_no_rem>0) {
newlib=newlib//new_endmem[(npositive+1):(npositive+num_no_rem)]
}
newlib=newlib[2:]
# Create transpose and square new endmember matrix
newlibT=translate(newlib,x,y)
square=mxm(newlibT,newlib)
# Invert new endmember matrix
square=minvert(square)
# Multiply inverse square matrix by new endmember matrix
sq_end=mxm(newlib,square)
# Multiply sq_end by transpose of emiss spectra producing the new 1x?x1 perc matrix
newperc=mxm(em[,cnt1],sq_end)
# Set negative percentages to zero before replacing new iteration percentages
negcheck=perc[1:(npositive),cnt1]
negcheck[where(negcheck<0)]=0
perc[1:(npositive),cnt1]=negcheck
# Replace original percentages with new percentages
cnt5=1
cnt6=1
while (cnt5 <= npositive) {
if (perc[cnt5,cnt1] > 0) {
perc[cnt5,cnt1]=newperc[cnt6]
cnt6=cnt6+1
}
cnt5=cnt5+1
}
#Add blackbody percentage back to new percent matrix
if (bbval==1 || num_no_rem > 0) {
perc[(npositive+1):(npositive+num_no_rem),cnt1]=newperc[cnt6:]
}
iterflag=1
}
#If no iterations were needed, set newlib and newperc to new_endmem and perc[,cnt1]
if(iterflag==0) {
newlib=new_endmem
newperc=perc[,cnt1]
}
} else { # If nn == 1
# Filling in needed variables
# Must avoid instances where A[i] == 0
#The past definition of npositive was incorrect.
#It is just the number of endmembers minus the number of forced endmembers
#It is not the number of positive endmemebers...Its the number that can only be positive or zero....
npositive = int(dim(perc[1:(nend-num_no_rem),cnt1])[1])
newlib = new_endmem[1,,]*.0 # Have to give it an initial value
newperc = perc[1,cnt1,]*0.
cnt2 = 1 # Counter
for (cnt2 = 1; cnt2 <= (nend - num_no_rem); cnt2++) {
if (perc[cnt2,cnt1,] > 0.) {
newlib = newlib//new_endmem[cnt2,,]
newperc = newperc//perc[cnt2,cnt1,]
}
}
if(dim(newlib)[1]!=1) {
newlib = newlib[2:,,] # Remove initial column
newperc = newperc[2:,,]
}
if (bbval==1 || num_no_rem>0) { # I think this is redundant, since num_no_rem includes the blackbody
newlib=newlib//new_endmem[(nend-num_no_rem+1):nend,,]
newperc = newperc//perc[(nend-num_no_rem+1):nend,cnt1,]
}
}
#Generate covariance matrix
if(no_calc_error==0) {
emT=translate(em[,cnt1,1],x,y)
newpercT=translate(newperc,x,y)
newlibT=translate(newlib,x,y)
term1=mxm(em[,cnt1,1],emT)
term2=mxm(newperc,newlibT)
term3=mxm(term2,emT)
dimnewlib=dim(newlib)
term4=nsamp-dimnewlib[1]
term5=minvert(mxm(newlibT,newlib))
covm=((term1-term3)/term4)*(term5)
#take statistical errors from sqrt of diagonal of covariance matrix
tmp_err=create(1,1,dimnewlib[1],format=float,start=0,step=0)
for (count=1; count<=dim(newlib)[1];count+=1) {
tmp_err[,,count]=sqrt(abs(covm[count,count]))
}
#expand st_err into same length as perc
count=1
for (i=1; i<=dim(perc)[1]; i+=1) {
if (perc[i,cnt1] != 0) {
st_err[i,cnt1]=tmp_err[,,count]
count++
}
}
}
#end error calculations
cnt1++
}
}
# End of core section (should be same after this for either value of nn)
smaout.covm=covm
# Reconstruct original spectra
perc=translate(perc,x,y)
endmem=translate(endmem,y,z)
recon=mxm(new_endmem,perc) #For RMS error calculation
reconfull=mxm(endmem,perc) #For modeled spectrum
dimperc=dim(perc)
# Reconstruct modeled surface spectra
if (surface==1) {
if (bbval==1) {
endmem_modsur=endmem[1:(npositive),,]//endmem[(nend),,]
perc_modsur=cat(perc[,1:(npositive),],perc[,(nend),],axis=y)
}
if (bbval==0){
endmem_modsur=endmem[1:(npositive),,]
perc_modsur=perc[,1:(npositive),]
}
modsur=mxm(endmem_modsur,perc_modsur)
}
# Reconstruct remaining data cubes from output
recon_cube=create(x=dimend[1,,],y=dimend[2,,],z=dimend[3,,],format=float,start=0,step=0)
perc_cube=create(x=mixvecs[1,,],y=mixvecs[2,,],z=dimperc[2,,], format=float,start=0,step=0)
if(no_calc_error==0) {
err_cube=create(x=mixvecs[1,,],y=mixvecs[2,,],z=dimperc[2,,], format=float,start=0,step=0)
}
#If your input mixed cube has a y-dimension > 1
if (mixvecs[2] > 1) {
perc=translate(perc,x,y)
recon=translate(recon,x,y)
reconfull=translate(reconfull,x,y)
for (count=1; count<=mixvecs[1,,]; count+=1){
start_spec=(count-1)*mixvecs[2,,]+1
stop_spec=count*mixvecs[2,,]
recon_temp=translate(reconfull[,start_spec:stop_spec,],from=x,to=z)
recon_cube[count,,]=recon_temp
perc_temp=translate(perc[,start_spec:stop_spec,],from=x,to=z)
perc_cube[count,,]=perc_temp
if(no_calc_error==0){
err_temp=translate(st_err[,start_spec:stop_spec,],from=x,to=z)
err_cube[count,,]=err_temp
}
}
} else {
recon_cube=translate(reconfull, from=y, to=z)
perc_cube=translate(perc, from=y, to=z)
if(no_calc_error==0) {
err_cube=translate(st_err,from=y,to=z)
err_cube=translate(err_cube,from=x,to=z)
}
}
# Generate blackbody plane
# There was a problem with this section where bb=0; fixed 11/23/2010
if (bbval == 1) {
smaout.bb = float(perc_cube[,,nend])
if (no_calc_error == 0) {
smaout.bberror = float(err_cube[,,nend])
err_cube = err_cube[,,1:(nend-1)]
}
perc_cube = perc_cube[,,1:(nend-1)]
smaout.normconc = float(perc_cube/sum(perc_cube, axis=z)*100.0)
} else { # Need this for sum_group_conc
smaout.bb = float(0*perc_cube[,,1])
if (no_calc_error == 0) {
smaout.bberror = smaout.bb
#err_cube=err_cube[,,1:(nend-1)]
}
}
#Calculate RMS error
rms_plane=new_cube-recon_cube[,,stband:endband]
rms_planefull=em_cube-recon_cube
# Create rematm and modsur cubes if requested
if(surface==1) {
modsur_cube=create(x=dimend[1],y=dimend[2],z=dimend[3],format=float,start=0,step=0)
modsur=translate(modsur,x,y)
for(count=1; count<=mixvecs[1,,]; count+=1){
start_spec=(count-1)*mixvecs[2,,]+1
stop_spec=count*mixvecs[2,,]
modsur_temp=translate(modsur[,start_spec:stop_spec,],from=x,to=z)
modsur_cube[count,,]=modsur_temp
}
rematm_cube=modsur_cube+rms_planefull
smaout.modsur=float(modsur_cube)
smaout.rematm=float(rematm_cube)
# Add constant to surface spectra to account for atm percentages
if(bbval==1) {
rematm_cube=rematm_cube+sum(perc_cube[,,(npositive+1):(npositive+num_no_rem-1)],axis=z)
modsur_cube=modsur_cube+sum(perc_cube[,,(npositive+1):(npositive+num_no_rem-1)],axis=z)
smaout.rematm=float(rematm_cube)
smaout.modsur=float(modsur_cube)
}
if(bbval==0) {
rematm_cube=rematm_cube+sum(perc_cube[,,(npositive+1):(npositive+num_no_rem)],axis=z)
modsur_cube=modsur_cube+sum(perc_cube[,,(npositive+1):(npositive+num_no_rem)],axis=z)
smaout.rematm=float(rematm_cube)
smaout.modsur=float(modsur_cube)
}
}
#Back to calculating RMS error
rms_plane=pow(rms_plane,2)
rms_plane=sum(rms_plane,z)
rms_plane=rms_plane/nsamp
rms_plane=pow(rms_plane, 0.5)
# Sort concentrations for each pixel if requested (for plot_sma)
if(sort==1) {
sorted_cube=sort_cube(float(perc_cube))
smaout.sort=int(sorted_cube)
}
# Expand percentage and error cubes to be original size of library (if vectors were excluded)
if(HasValue(exclude)==1) {
tmp_normperc_cube=tmp_perc_cube=create(x=mixvecs[1],y=mixvecs[2],z=dimfull[1],format=float,org=bsq,start=0,step=0)
if(no_calc_error==0){
tmp_err_cube=create(x=mixvecs[1],y=mixvecs[2],z=dimfull[1],format=float,org=bsq,start=0,step=0)
}
#expand out the sort array though...this is tricky
if(sort==1) {
tmp_sort_cube=create(x=mixvecs[1],y=mixvecs[2],z=dimfull[1],format=int,org=bsq,start=0,step=0)
tmp_sort_cube[,,:dim(smaout.sort)[3]]=smaout.sort
for(i=1;i<=dim(smaout.excluded)[1];i+=1) {
tmp_sort_cube[where tmp_sort_cube>=smaout.excluded[i] && tmp_sort_cube!=0]=tmp_sort_cube+1
}
}
count=1
countt=1
counttt=1
while(counttt<=dim(perc_cube)[3]) {
while(countt<=dim(smaout.excluded)[1]) {
if(count==smaout.excluded[countt]) {
countt=countt+1
count=count+1
} else {
tmp_perc_cube[,,count]=perc_cube[,,counttt]
tmp_normperc_cube[,,count]=smaout.normconc[,,counttt]
if(no_calc_error==0) {
tmp_err_cube[,,count]=err_cube[,,counttt]
}
count=count+1
counttt=counttt+1
}
}
if(counttt<=dim(perc_cube)[3]) {
tmp_perc_cube[,,count]=perc_cube[,,counttt]
tmp_normperc_cube[,,count]=smaout.normconc[,,counttt]
if(no_calc_error==0) {
tmp_err_cube[,,count]=err_cube[,,counttt]
}
}
count=count+1
counttt=counttt+1
}
perc_cube=tmp_perc_cube
smaout.normconc=tmp_normperc_cube
if(no_calc_error==0) {
err_cube=tmp_err_cube
}
if(sort==1) {
smaout.sort_full=tmp_sort_cube
}
} else {
if(sort==1) {
smaout.sort_full=smaout.sort
}
}
# Add to the output structure
smaout.measured=float(em_cube)
smaout.modeled=float(recon_cube)
smaout.conc=float(perc_cube)
smaout.rms=float(rms_plane)
smaout.nsamples=nsamp
smaout.endlib=libstruc
if(no_calc_error==0) {
smaout.error=float(err_cube)
smaout.normerror=float(smaout.error[]/sum(smaout.conc[],axis=z))*100
}
# if the input library was not a structure, add .label and .group with "none"
if (labelflag==0) {
smaout.endlib=struct()
smaout.endlib.data=libstruc
smaout.endlib.label="none"
smaout.endlib.group="none"
}
#setup the spectral range ouput
smaout.spectral_range = sprintf("Channels %i-%i", stband,endband)
smaout.spectral_channel_low=stband
smaout.spectral_channel_high=endband
smaout.wave1 = wv1
smaout.wave2 = wv2
#fix for weirdly high (but scaled properly) atm and modled surface spectra
if(surface==1) {
corr=1-(smaout.bb+sum(smaout.conc,axis=z))
smaout.modsur=smaout.modsur+corr
smaout.rematm=smaout.rematm+corr
}
# Group concentrations if requested--set up structure for call to sum_groups
if (group==1) {
if(grpflag==0){
printf("The library does not have .group. Concentrations will not be grouped. \n")
} else {
if($ARGC==3){
smaout.grouped=sum_group_conc(smaout,smaout.forcedlib)
} else {
smaout.grouped=sum_group_conc(smaout)
}
#find the posisition of the "Black body" element
pos=maxchan(smaout.grouped.grouped_labels=="Black body")
#extract the black body
smaout.grouped.grouped_bb=smaout.grouped.grouped_conc[,,pos]
#whittle down the error array and extract the black body error
if(no_calc_error==0) {
smaout.grouped.grouped_bberror=smaout.grouped.grouped_error[,,pos]
smaout.grouped.grouped_error=smaout.grouped.grouped_error[,,:pos-1]
}
#whittle down the conc and labels array
smaout.grouped.grouped_conc=smaout.grouped.grouped_conc[,,:pos-1]
smaout.grouped.grouped_labels=smaout.grouped.grouped_labels[,:pos-1]
#create a grouped_sort for the concentrations
smaout.grouped.grouped_sort_full=sort_cube(smaout.grouped.grouped_conc)
#create a normalized concentration
smaout.grouped.grouped_normconc=float(smaout.grouped.grouped_conc*0)
newsum=sum(smaout.grouped.grouped_conc,axis=z)
smaout.grouped.grouped_normconc=float(smaout.grouped.grouped_conc/newsum*100)
if(no_calc_error==0) {
#create a normalized error array
smaout.grouped.grouped_normerror=float(smaout.grouped.grouped_error[]/sum(smaout.grouped.grouped_conc[],axis=z))*100
}
}
}
if (nnval == 0) {
smaout.algorithm = "Original least squares"
} else {
smaout.algorithm = "Nonnegative least squares"
}
return(smaout)
}
define sort_cube() {
#sort in the z-direction, on a pixel-by-pixel basis
if ($ARGC ==0) {
printf ("Sort a cube in the z-direction, on a pixel-by-pixel basis. \n")
printf (" $1 = input cube \n")
return(0)
}
cube=$1
xdim=dim(cube)
ydim=dim(translate(cube,y,x))
zdim=dim(translate(cube,z,x))
band_list=create(1,1,zdim[1],format=format(cube), start=1,step=1)
sortband_cube=create(xdim,ydim,zdim,format=format(cube), start=0,step=0)
x_cnt=1
y_cnt=1
while (x_cnt <= xdim[1,,]) {
while (y_cnt <= ydim[1,,]) {
strip=create(1,1, zdim[1], format=format(cube))
strip[1,1,]=cube[x_cnt,y_cnt,]
sortband=create(1,1,zdim[1],format=format(cube), start=0,step=0)
two_col=cat(strip, band_list,x)
strip=sort(strip)
amax=max(strip)
count=1
cnt2=1
while (cnt2 <= zdim[1,,]) {
if (count > zdim[1,,]) {
count=1
}
while (count <= zdim[1,,]) {
if (two_col[1,1,count] == amax) {
sortband[1,1,cnt2]=two_col[2,1,count]
if (amax == 0) {
sortband[1,1,cnt2]=0
}
cnt3=zdim[1]-cnt2
cnt2=cnt2+1
strip=strip[1,1,1:cnt3]
amax=max(strip)
}
if (cnt2 >= zdim[1,,]+1) {
count=zdim[1,,]+1
}
count=count+1
}
}
sortband_cube[x_cnt,y_cnt,]=sortband[1,1,]
#return(sortband_cube)
y_cnt=y_cnt+1
}
x_cnt=x_cnt+1
y_cnt=1
}
return(int(sortband_cube))
}
define sum_group_conc() {
#Sum mineral percentages from sma output, works with individual spectra and cubes
if ($ARGC == 0) {
printf ("\n")
printf (" $1 = smaout structure\n")
printf (" [$2]= .forcedlib from sma() output (must contain .group) \n")
printf (" Example: \n")
printf (" mineral_maps=sum_groups(final.endlib,final.conc,final.measured,final.nsamples,final.bb,final.forcedlib) \n")
printf (" \n")
printf (" Returns mineral group concentration maps with labels: \n")
printf (" .grouped_conc,.grouped_labels \n")
printf (" Also returns propagated group errors \n")
printf (" See also summary_sma_groups()--gives summary table of grouped abundances for a \n")
printf (" given x,y position. \n")
printf (" \n")
printf (" Groups are formed by scanning .group, and forming a new group index every \n")
printf (" time it encounters a unique group label. So, 'sheet-silicate' and 'sheet silicate' would \n")
printf (" be different groups. If you want to combine groups, like 'clays' and 'glass', you have \n")
printf (" to change both labels so that they match (such as 'clays + glass') and re-run sum_group_conc.\n")
return(0)
}
smaout=$1
end2_lib=smaout.endlib
lib_groups=end2_lib.group
min_conc=smaout.conc
endspc=translate(end2_lib.data,y,z)
meas_spc=smaout.measured
numsamp=smaout.nsamples
bbc=smaout.bb
low_chan=smaout.spectral_channel_low
high_chan=smaout.spectral_channel_high
# old method of input...kinda messy
# end2_lib=$1
# lib_groups=end2_lib.group
# min_conc=$2
# endspc=translate(end2_lib.data,y,z)
# meas_spc=$3
# numsamp=$4
# bbc=$5
# low_chan=$6
# high_chan=$7
if($ARGC==2) {
atlib=$2
lib_groups=cat(lib_groups,atlib.group,y)
atmspc=translate(atlib.data,y,z)
endspc=cat(endspc,atmspc,x)
}
meas_spc=meas_spc[,,low_chan:high_chan]
endspc=endspc[,low_chan:high_chan]
min_conc=cat(min_conc,bbc,z)
lib_groups=cat(lib_groups,"Black body",y)
endspc=cat(endspc,endspc[1]/endspc[1],x)
if(length(lib_groups)!=dim(min_conc)[3]) {
printf("Number of group labels must equal z-direction of .conc. Perhaps you have an atmospheric library to add? \n")
printf("Type sum_group_conc() for help \n")
return(0)
}
#first lets find the unique elements in the label array
glabels=unique(lib_groups)
numgroups=length(glabels)
group_index=create(dim(min_conc)[3],1,1,format=int,start=0,step=0)
for(j=1;j<=length(glabels);j+=1) {
group_index+=translate((lib_groups==glabels[,j])*j,y,x)
}
sumconc=create(dim(min_conc)[1],dim(min_conc)[2],numgroups,format=float,start=0.0,step=0)
grp_error=create(dim(min_conc)[1],dim(min_conc)[2],numgroups,format=float,start=0,step=0)
#Sum the groups and errors
for(k=1;k<=dim(min_conc)[1];k+=1) {
for(m=1;m<=dim(min_conc)[2];m+=1) {
newconc=create(1,1,1,format=float,start=0,step=0)
newlib=create(1,dim(endspc)[2],1,format=float,start=0,step=0)
newgrpindex=0
for(p=1;p<=dim(min_conc)[3];p+=1) {
if(min_conc[k,m,p]!=0.000000) {
newlib=cat(newlib,endspc[p],x)
newconc=cat(newconc,min_conc[k,m,p],y)
newgrpindex=cat(newgrpindex,group_index[p],x)
}
}
if(dim(newlib)[1]>1) {
newlib=newlib[2:]
newconc=newconc[,2:]
newgrpindex=newgrpindex[2:] # now have endlib and percentage vector for concentrations > 0.0
} else {
newlib=endspc
newconc=translate(min_conc[k,m],y,z)
}
# Contruct covariance matrix
em=translate(meas_spc[k,m,],x,z)
emT=translate(em,x,y)
newconcT=translate(newconc,x,y)
newlibT=translate(newlib,x,y)
term1=mxm(em,emT)
term2=mxm(newconcT,newlibT)
term3=mxm(term2,emT)
dimnewlib=dim(newlib)
term4=numsamp-dimnewlib[1]
term5=minvert(mxm(newlibT,newlib))
covm=((term1-term3)/term4)*(term5)
#Now, from those whittled down matrices, sum the concentrations and errors for each group
if(newgrpindex[1]!=0) {
for(i=1;i<=dim(newgrpindex)[1];i+=1) {
tmp_conc=create(1,1,1,format=float,start=0.0,step=0)
for(j=1;j<=dim(newconc)[2];j+=1) {
if(newgrpindex[j]==newgrpindex[i]) {
tmp_conc=float(cat(tmp_conc,float(newconc[,j]),y))
grp_error[k,m,(newgrpindex[i])]=sum(cat(grp_error[k,m,(newgrpindex[i])],float(covm[i,j]),x),x)
}
}
sumconc[k,m,(newgrpindex[i])]=sum(tmp_conc,y)
}
}
}
}
gp=struct()
gp.grouped_conc=sumconc
gp.grouped_error=sqrt(abs(grp_error))
gp.grouped_labels=glabels
return(gp)
}
define summary_sma(ylow,yhigh,xlow,xhigh,group,debug,output) {
#re-written by c.edwards 8/25/10
#combined summary_sma and summary_sma_group (automatically normalizes for bb, not atm)
if (($ARGC!=1 && $ARGC!=3) || ($ARGC==1 && HasValue(xlow)==0 && HasValue(ylow)==0)) {
printf (" Make summary table of results for one pixel from \n")
printf (" sma() output. \n")
printf (" $1=output structure from sma() \n")
printf (" $2=x-coordinate \n")
printf (" $3=y-coordinate \n")
printf (" xlow=low value for x-range\n")
printf (" xhigh=high value for x-range\n")
printf (" ylow=low value for y-range\n")
printf (" yhigh=high value for y-range\n")
printf (" NOTE: either a range or coordinate must be entered\n")
printf (" \n")
printf (" Note that only concentrations > 0.0001 are printed out \n\n")
printf (" Options:\n")
printf (" group=1 print the .grouped abundances if they are present\n")
printf (" output=1 return a structure with the sorted abundances, error, and endmember names\n")
printf (" \n")
return(null)
}
if(HasValue(debug)==0) { # Debug option added by S. Marshall, 2010-11-09
debug=0
}
inpu=$1
if(HasValue(group)==0) {
group=0
}
if($ARGC>1) {
xcor=$2
ycor=$3
if(xcor>dim(inpu.conc)[1]) xcor=dim(inpu.conc)[1]
if(ycor>dim(inpu.conc)[2]) ycor=dim(inpu.conc)[2]
}
#begin handling the range case by checking to make sure a valid range is input
if((HasValue(xlow) && HasValue(xhigh)==0) || (HasValue(xhigh) && HasValue(xlow)==0) && $ARGC==1) {
printf("You must enter both a xlow and xhigh for a complete range\n")
return(null)
}
if((HasValue(ylow) && HasValue(yhigh)==0) || (HasValue(yhigh) && HasValue(ylow)==0) && $ARGC==1) {
printf("You must enter both a ylow and yhigh for a complete range\n")
return(null)
}
#set defaults for both 3 arg case and 1 arg case
if(HasValue(ylow)==0 && HasValue(ycor)) {
ylow=ycor
} else if (HasValue(ylow)==0) {
ylow=1
}
if(HasValue(yhigh)==0 && HasValue(ycor)){
yhigh=ycor
} else if (HasValue(yhigh)==0) {
yhigh=1
}
if(HasValue(xlow)==0 && HasValue(xcor)) {
xlow=xcor
} else if(HasValue(xlow)==0) {
xlow=1
}
if(HasValue(xhigh)==0 && HasValue(xcor)) {
xhigh=xcor
} else if(HasValue(xhigh)==0) {
xhigh=1
}
#make sure we don't excede the bounds of the data cube
if(HasValue(ylow)) {
if(ylow<1) ylow=1
if(ylow>dim(inpu.conc)[2]) ylow=dim(inpu.conc)[2]
}
if(HasValue(yhigh)){
if(yhigh>dim(inpu.conc)[2]) yhigh=dim(inpu.conc)[2]
}
if(HasValue(xlow)){
if(xlow<1) xlow=1
if(xlow>dim(inpu.conc)[1]) xlow=dim(inpu.conc)[1]
}
if(HasValue(xhigh)){
if(xhigh>dim(inpu.conc)[1]) xhigh=dim(inpu.conc)[1]
}
labelflag=0
errorflag=0
#extract the correct elements for the structure so we have consitent variable names
if(group==1 && HasValue(get_struct(inpu,"grouped"))==1) {
#the grouped case
conc=inpu.grouped.grouped_conc[xlow:xhigh,ylow:yhigh]
if(HasValue(inpu.grouped.grouped_normconc)) {
norm=inpu.grouped.grouped_normconc[xlow:xhigh,ylow:yhigh]
} else {
norm=conc*0.
}
sort=inpu.grouped.grouped_sort_full[xlow:xhigh,ylow:yhigh]
label=inpu.grouped.grouped_labels
if(HasValue(get_struct(inpu.grouped,"grouped_bb"))) {
bb=inpu.grouped.grouped_bb[xlow:xhigh,ylow:yhigh]
} else {
bb=0.
}
if(HasValue(get_struct(inpu.grouped,"grouped_error"))) {
error=inpu.grouped.grouped_error[xlow:xhigh,ylow:yhigh]
bberror=inpu.grouped.grouped_bberror[xlow:xhigh,ylow:yhigh]
errorflag=1
}
} else {
#the full data case
conc=inpu.conc[xlow:xhigh,ylow:yhigh]
if(HasValue(inpu.normconc)) {
norm=inpu.normconc[xlow:xhigh,ylow:yhigh]
} else {
norm=conc*0.
}
sort=inpu.sort_full[xlow:xhigh,ylow:yhigh]
if(inpu.endlib.label[,1]!="none") {
label=inpu.endlib.label
}
if(length(inpu.forcedlib.label)!=1) {
if(inpu.forcedlib.label[,1]!="none") {
label=cat(label,inpu.forcedlib.label,y)
}
}
if(HasValue(get_struct(inpu,"bb"))) {
bb=inpu.bb[xlow:xhigh,ylow:yhigh]
} else {
bb=0.
}
if(HasValue(get_struct(inpu,"error"))) {
error=inpu.error[xlow:xhigh,ylow:yhigh]
bberror=inpu.bberror[xlow:xhigh,ylow:yhigh]
errorflag=1
}
}
rms=inpu.rms[xlow:xhigh,ylow:yhigh]
#if we don't have any labels
if(HasValue(label)==0) {
label=create(1,dim(conc)[3],1,start=1,step=1,format=int)
labelflag=1
}
for(i=1;i<=xhigh-xlow+1;i+=1) {
for(j=1;j<=yhigh-ylow+1;j+=1) {
xcor=i
ycor=j
cnt=1
if (debug == 1) {
printf("xlow = %d, ylow = %d, xcor = %d, ycor = %d\n", xlow, ylow, xcor, ycor)
}
printf ("\n")
printf ("*********************Summary for Pixel Coordinate (%i,%i) ******************* \n", xlow+xcor-1,ycor+ylow-1)
if(HasValue(get_struct(inpu,"label"))) {
if(ycor+ylow-1==1 && xcor+xhigh-1!=1) {
printf ("\t\t Label: %s\n\n",inpu.label[,xcor+xlow-1])
} else {
printf ("\t\t Label: %s\n\n",inpu.label[,ycor+ylow-1])
}
}
if(HasValue(get_struct(inpu,"sample_name"))) {
if(ycor+ylow-1==1 && xcor+xhigh-1!=1) {
printf ("\t\t Label: %s\n\n",inpu.sample_name[,xcor+xlow-1])
} else {
printf ("\t\t Label: %s\n\n",inpu.sample_name[,ycor+ylow-1])
}
}
if(group==1) {
printf (" Group Abundance(%%) Normalized for BB(%%) \n")
} else {
printf (" Endmember Abundance(%%) Normalized for BB(%%) \n")
}
printf("\n")
#setup the output structure
struct={}
if(labelflag==0) {
struct.label=text(1)
} else {
struct.label=0
}
if(errorflag==1) {
struct.error=0.
struct.normerror=0.
}
struct.conc=0.
struct.normconc=0.
struct.endlib=create(1,1,dim(inpu.endlib.data)[3],format=float,start=0,step=0)
if(dim(inpu.endlib.data)[2]!=1) {
inpu.endlib.data=translate(inpu.endlib.data,x,y)
}
while(sort[i,j,cnt]>0 && cnt<=dim(sort)[3]) {
idx=sort[i,j,cnt]
if(conc[,,idx] !=0) {
if(conc[,,idx] > 0.0001 || conc[,,idx] < -0.0001) {
if(labelflag==0 && errorflag==1) {
printf ("%27s %11.2f +/- %5.2f %13.2f +/- %5.2f\n", label[1:25,idx], conc[i,j,idx]*100, error[i,j,idx]*100, norm[i,j,idx], (error[i,j,idx]/sum(conc[i,j],axis=z))*100)
} else if (labelflag==1 && errorflag==1) {
printf ("%27i %11.2f +/- %5.2f %13.2f +/- %5.2f\n", label[,idx], conc[i,j,idx]*100, error[i,j,idx]*100, norm[i,j,idx], (error[i,j,idx]/sum(conc[i,j],axis=z))*100)
} else if (labelflag==0 && errorflag==0) {
printf ("%27s %11.2f %18.2f \n", label[1:25,idx], conc[i,j,idx]*100, norm[i,j,idx])
} else if (labelflag==1 && errorflag==0) {
printf ("%27i %11.2f %18.2f \n", label[,idx], conc[i,j,idx]*100, norm[i,j,idx])
}
#output the data in a useful format
if(labelflag==0) {
struct.label=cat(struct.label,label[1:25,idx],axis=y)
} else {
struct.label=cat(struct.label,label[,idx],axis=y)
}
struct.conc=cat(struct.conc,conc[i,j,idx]*100,axis=x)
struct.normconc=cat(struct.normconc,norm[i,j,idx],axis=x)
struct.endlib=cat(struct.endlib,inpu.endlib.data[idx],axis=x)
if(errorflag==1) {
struct.error=cat(struct.error,error[i,j,idx]*100,axis=x)
struct.normerror=cat(struct.normerror,float(error[i,j,idx]/sum(conc[i,j],axis=z)*100),axis=x)
}
}
}
cnt=cnt+1
}
printf ("___________________________________________________________________________\n")
printf (" Sum (BB included) = %5.2f\n", float(sum(conc[i,j],z)+bb[i,j])*100)
if(sum(norm[i,j],z)!=0) {
printf (" Sum (BB normalized) = %5.2f\n", float(sum(norm[i,j],z)))
}
struct.bbsum=float(sum(conc[i,j],z)+bb[i,j])*100
struct.bbabundance=float(bb[i,j]*100)
if(errorflag==1) {
printf (" Blackbody Abundance = %5.2f +/- %5.2f\n", float(bb[i,j]*100), float(bberror[i,j]*100))
struct.bberror=float(bberror[i,j]*100)
}
if(errorflag==0) {
printf (" Blackbody Abundance = %5.2f \n", float(bb[i,j]*100))
}
printf (" RMS Error(%%) = " + float(rms[i,j]*100) + " \n")
printf ("\n")
}
}
if(HasValue(output)) {
struct.conc=struct.conc[2:]
struct.normconc=struct.normconc[2:]
struct.label=struct.label[,2:]
struct.endlib=struct.endlib[2:]
if(errorflag==1) {
struct.error=struct.error[2:]
struct.normerror=struct.normerror[2:]
}
return(struct)
}
}
define summary_sma_group(ylow,yhigh,xlow,xhigh) {
if (($ARGC!=1 && $ARGC!=3) || ($ARGC==1 && HasValue(xlow)==0 && HasValue(ylow)==0)) {
printf ("\n Make summary table of abundances grouped by mineral class \n")
printf (" for one pixel from sma() output. \n")
printf (" $1=sma() output (must have .grouped) \n")
printf (" $2=x-coordinate \n")
printf (" $3=y-coordinate \n")
printf (" xlow=low value for x-range\n")
printf (" xhigh=high value for x-range\n")
printf (" ylow=low value for y-range\n")
printf (" yhigh=high value for y-range\n")
printf (" NOTE: either a range or coordinate must be entered\n")
printf (" \n")
return(null)
}
inpu=$1
if($ARGC>1) {
xcor=$2
ycor=$3
if(xcor>dim(inpu.conc)[1]) xcor=dim(inpu.conc)[1]
if(ycor>dim(inpu.conc)[2]) ycor=dim(inpu.conc)[2]
}
#begin handling the range case by checking to make sure a valid range is input
if((HasValue(xlow) && HasValue(xhigh)==0) || (HasValue(xhigh) && HasValue(xlow)==0) && $ARGC==1) {
printf("You must enter both a xlow and xhigh for a complete range\n")
return(null)
}
if((HasValue(ylow) && HasValue(yhigh)==0) || (HasValue(yhigh) && HasValue(ylow)==0) && $ARGC==1) {
printf("You must enter both a ylow and yhigh for a complete range\n")
return(null)
}
#set defaults for both 3 arg case and 1 arg case
if(HasValue(ylow)==0 && HasValue(ycor)) {
ylow=ycor
} else if (HasValue(ylow)==0) {
ylow=1
}
if(HasValue(yhigh)==0 && HasValue(ycor)){
yhigh=ycor
} else if (HasValue(yhigh)==0) {
yhigh=1
}
if(HasValue(xlow)==0 && HasValue(xcor)) {
xlow=xcor
} else if(HasValue(xlow)==0) {
xlow=1
}
if(HasValue(xhigh)==0 && HasValue(xcor)) {
xhigh=xcor
} else if(HasValue(xhigh)==0) {
xhigh=1
}
#make sure we don't excede the bounds of the data cube
if(HasValue(ylow)) {
if(ylow<1) ylow=1
if(ylow>dim(inpu.conc)[2]) ylow=dim(inpu.conc)[2]
}
if(HasValue(yhigh)){
if(yhigh>dim(inpu.conc)[2]) yhigh=dim(inpu.conc)[2]
}
if(HasValue(xlow)){
if(xlow<1) xlow=1
if(xlow>dim(inpu.conc)[1]) xlow=dim(inpu.conc)[1]
}
if(HasValue(xhigh)){
if(xhigh>dim(inpu.conc)[1]) xhigh=dim(inpu.conc)[1]
}
#we can now just call summary_sma with the group=1 option
summary_sma(inpu,xlow=xlow,xhigh=xhigh,ylow=ylow,yhigh=yhigh,group=1)
}
define tdb2struct(lab1, lab2) {
if ($ARGC == 0) {
printf("\nConvert tdb structure or file path to hdf structure\n")
printf(" usage: a = tdb2struct(tdb_file or tdb_file_path, [lab1=1][lab2=1])\n")
printf(" \n")
printf(" where:\n")
printf(" tdb_file = tdb format structure (load_tdb option distribute=1) of data, labels, and xaxes\nOR\n")
printf(" tdb_file_path = path to tdb format file of data, labels, and xaxes\n")
printf(" options:\n")
printf(" [lab=1] resample to xlab1 (923 pt lab spectra (221.7 to 1999.8) (default))\n")
printf(" [lab=2] resample to xlab2 (1971 pt lab spectra (200.5 to 3999.7))\n")
printf("\np. christensen 11/24/2010\n\n")
return(null)
}
struc = struct()
if(type($1)=="STRING") {
a=load_tdb($1,distribute=1)
} else if(type($1)=="STRUCT") {
a = $1
} else {
printf("$1 is either not a STRUCT or a PATH to a TDB file\n")
return(null)
}
n = length(a)
xlab1 = make_band(lab1=1)
xlab2 = make_band(lab2=1)
if(HasValue(lab2)) {
# resample to xlab2
data = resample(translate(a[1].data,x,z), translate(a[1].xaxis,x,z), xlab2).data
xaxis = xlab2
} else if(HasValue(lab1)) {
# resample to xlab1 - default
data = resample(translate(a[1].data,x,z), translate(a[1].xaxis,x,z), xlab1).data
xaxis = xlab1
} else {
# resample to xlab1 - default
data = resample(translate(a[1].data,x,z), translate(a[1].xaxis,x,z), xlab1).data
xaxis = xlab1
}
label = rm_quote(a[1].label)
for(i=2; i<=n; i+=1) {
if(HasValue(lab2)) {
# resample to xlab2
datan = resample(translate(a[i].data,x,z), translate(a[i].xaxis,x,z), xlab2).data
} else if(HasValue(lab1)) {
# resample to xlab1 - default
datan = resample(translate(a[i].data,x,z), translate(a[i].xaxis,x,z), xlab1).data
} else {
# resample to xlab1 - default
datan = resample(translate(a[i].data,x,z), translate(a[i].xaxis,x,z), xlab1).data
}
data = cat(data, datan, x)
label = cat(label, rm_quote(a[i].label), y)
}
struc.data = data
struc.label = label
struc.xaxis = xaxis
return(struc)
}
define fit_bb(type,tlow,thigh,steps,wave1,wave2,nn,instT,instdT,diffbb) {
if($ARGC<2) {
printf("\nGeneric Blackbody fitting routine\n")
printf("By default this uses a non-negative least squares fitting routine\n")
printf("to model a psudo-blackbody curve with many blackbodies\n")
printf("The output is based on the sma() output\n\n")
printf("\t$1 is the data that will be fit\n")
printf("\t$2 is the corresponding xaxis data in wavenumbers (1/cm)\n\n")
printf("Options:\n")
printf("\ttlow =\tthe low temperature range to fit (Default is 273.15)\n")
printf("\tthigh =\tthe high temperature range to fit (Default is 373.15)\n")
printf("\tsteps =\tthe number of steps between tlow and thigh (Default is 100)\n")
printf("\ttype =\t\"inst\" sets default values of tlow=223, thigh=323, steps=100\n")
printf("\ttype =\t\"cold\" sets default values of tlow=50, thigh=200, steps=100\n")
printf("\ttype =\t\"warm\" sets default values of tlow=150, thigh=350, steps=100\n")
printf("\ttype =\t\"hot\" sets default values of tlow=250, thigh=500, steps=100\n")
printf("\ttype =\t\"full\" sets default values of tlow=50, thigh=500, steps=100\n")
printf("\tinstT = sets the middle instrument temperature (default is (tlow+thigh)/2)\n")
printf("\tinstdT = sets the deviation around the instrument temperature (default is 20)\n")
printf("\twave1 =\tminimum wavenumber for modeling (Default is min(xaxis))\n")
printf("\twave2 =\tmaximum wavenumber for modeling (Default is max(xaxis))\n")
printf("\tnn =\tuse the non-negative fitting routine (Default is 1)\n")
printf("\tdiffbb = models the differencd of two blackbodies using the same temperature ranges set by \"type\"\n")
printf("\t\tIt creates a range of blackbody temperature differences from thigh to tlow\n\n")
printf("c.edwards 5-5-2011\n\n")
return(null)
}
data=$1
xaxis=$2
maxsteps=dim(xaxis)[3]-1
#set the temperature ranges based on the desired fits
if(HasValue(type)) {
if(type=="inst") {
if(HasValue(tlow)==0) tlow=223
if(HasValue(thigh)==0) thigh=323
} else if(type=="cold") {
if(HasValue(tlow)==0) tlow=50
if(HasValue(thigh)==0) thigh=200
} else if(type=="warm") {
if(HasValue(tlow)==0) tlow=150
if(HasValue(thigh)==0) thigh=350
} else if(type=="hot") {
if(HasValue(tlow)==0) tlow=250
if(HasValue(thigh)==0) thigh=500
} else if(type=="full") {
if(HasValue(tlow)==0) tlow=50
if(HasValue(thigh)==0) thigh=500
} else {
printf("No valid location for defaults was entered\n")
printf("Please try again\n")
return(null)
}
}
#if we have a standard dT to be used, set it instead of a range
if(HasValue(instT)) {
if(HasValue(instdT)==0) {
instdT=20
}
if(HasValue(tlow)==0) tlow=instT-instdT
if(HasValue(thigh)==0) thigh=instT+instdT
}
#use nnls by default as this yeilds superior results in this case
#and in many cases, it is the only one that works
if(HasValue(nn)==0) {
nn=1
}
#set the wavelength ranges for fitting
if(HasValue(wave1)==0 && HasValue(wave2)==0) {
wave1=min(xaxis)
wave2=max(xaxis)
}
#finally if we don't have any other options, set the range
if(HasValue(tlow)==0) {
tlow=273.15
}
if(HasValue(thigh)==0) {
thigh=373.15
}
#set the number of steps
if(HasValue(steps)==0) {
steps=100
}
#check to see if we have too many steps
if(steps>maxsteps) {
printf("Error: more steps than allowed\n")
printf("Resetting to Xaxis length-1\n")
steps=maxsteps-1
}
#now we see if we are modeling bb differences or straight bbs
if(HasValue(diffbb)==0) {
#setup the bb range for modeling
bb={}
bb.data=create(steps,1,dim(xaxis)[3],start=0,step=0,format=float,org=bsq)
bb.temp=create(steps,1,1,start=0,step=0,format=float,org=bsq)
bb.label=text(steps)
bb.xaxis=xaxis
#temperature ranges based on the number of steps and tlow/thigh
for(i=1;i<=steps;i+=1) {
temp=tlow+(i-1)*((thigh-tlow)/float(steps))
bb.data[i]=bbr(xaxis,temp)
bb.label[,i]=sprintf("%.2fK Blackbody",temp)
bb.temp[i]=temp
}
} else {
#this is a little more complicated
#we take the sqrt of the number of steps to do an xy array difference of the
#total number of steps
stepssq=int(ceil(sqrt(steps)))
#check to see if we have too many steps
if(stepssq^2>maxsteps) {
stepssq=int(floor(sqrt(maxsteps-1)))
}
steps=stepssq^2
#same setup as before
bb={}
bb.data=create(steps,1,dim(xaxis)[3],start=0,step=0,format=float,org=bsq)
bb.temp=create(steps,2,1,start=0,step=0,format=float,org=bsq)
bb.xaxis=xaxis
#make the 2-D array of temperature differences
count=1
for(j=1;j<=stepssq;j+=1) {
for(i=1;i<=stepssq;i+=1) {
temp1=tlow+(i-1)*((thigh-tlow)/float(stepssq))
temp2=thigh-(j-1)*((thigh-tlow)/float(stepssq))
bb.data[count]=bbr(xaxis,temp2)-bbr(xaxis,temp1)
bb.temp[count]=cat(temp2,temp1,axis=y)
count++
}
}
#extract the values that have zero difference (this makes sma unhappy)
mask=sum(bb.data,axis=z)!=0
bb.data=extract(bb.data,mask)
bb.temp=extract(bb.temp,mask)
newsteps=dim(bb.temp)[1]
bb.label=text(newsteps)
#fill out the label after we remove the zero differences
for(i=1;i<=dim(bb.temp)[1];i+=1) {
bb.label[,i]=sprintf("%.2fK Blackbody - %.2fK Blackbody",bb.temp[i,1],bb.temp[i,2])
}
}
#model the data
out=sma(data,bb,bb=0,group=0,wave1=wave1,wave2=wave2,nn=nn,noerr=1)
#setup some output stats
if(HasValue(diffbb)==0) {
#setup the output
numpos=int(sum(out.sort!=0))
shorttemp=shortconc=create(numpos,1,1,start=0,step=0,format=float,org=bsq)
shortrad=create(numpos,1,dim(xaxis)[3],start=0,step=0,format=float,org=bsq)
#get only data that are non-zero
for(i=1;i<=numpos;i+=1) {
shorttemp[i]=bb.temp[out.sort[,,i]]
shortconc[i]=out.conc[,,out.sort[,,i]]
shortrad[i]=bb.data[out.sort[,,i]]
}
#here we calculate the normalized concentrations based on power and temperature
global(con)
shortpow=con.sigma*(shorttemp^4)
scaleconc=shortconc/shortpow
normconc=scaleconc/sum(scaleconc)
#output the data including a weighted average temperature
stats={}
stats.pow=shortpow
stats.normconc=normconc
stats.conc=shortconc
stats.temp=shorttemp
stats.rad=shortrad
stats.avgtemp=sum(stats.normconc*stats.temp)
} else {
#setup the additional output for diffbb
numpos=int(sum(out.sort!=0))
shorttemp=create(numpos,2,1,start=0,step=0,format=float,org=bsq)
shortconc=create(numpos,1,1,start=0,step=0,format=float,org=bsq)
#get the non-zero data
for(i=1;i<=numpos;i+=1) {
shorttemp[i]=bb.temp[out.sort[,,i]]
shortconc[i]=out.conc[,,out.sort[,,i]]
}
#calcualate a normalized concentration
normconc=shortconc/sum(shortconc)
#output the data into the stats structure
stats={}
stats.temp=shorttemp
stats.conc=shortconc
stats.normconc=normconc
}
out.stats=stats
return(out)
}
define sa(deg) {
if($ARGC == 0) {
printf("solid angle for phi from 0 to phi and theta from theta1 to theta2\n")
printf("usage: a = sa(phi, theta1(rad), theta2(rad) [deg])\n")
printf("Default is in radians; use deg=1 to input in degrees\n")
return(0)
}
# p. christensen 3/10
if(HasValue(deg)) {
phi = d2r($1)
t1 = d2r($2)
t2 = d2r($3)
printf("phi=%.2f t1= %.2f t2=%.2f\n", phi, t1, t2)
} else {
phi = $1
t1 = $2
t2 = $3
}
omega = phi * ( cos(t1) - cos(t2)); # steradians
return(omega)
}