FUNCTION make_xrt_emiss_model, modelname, wave, temp, spec, abund_model, $ ioneq_model, dens_model, wlength=wlength, $ tlength=tlength, data_files=data_files, $ comments=comments, outfile=outfile, verbose=verbose, $ quiet=quiet, qabort=qabort, qstop=qstop ; ========================================================================= ;+ ; PROJECT: ; Solar-B / XRT ; ; NAME: ; ; MAKE_XRT_EMISS_MODEL ; ; CATEGORY: ; ; Instrument response ; ; PURPOSE: ; ; This program helps users put a spectral emission model into a ; structure format that other XRT routines will expect. The benefit ; is that the routines which calculate the XRT x-ray responses may be ; used in a modular manner with the user's choice of spectral ; emission codes. ; (This routine deprecates, and provides extended functionality ; of, the older routines and ; .) ; ; CALLING SEQUENCE: ; ; Result = MAKE_XRT_EMISS_MODEL( modelname, wave, temp, spec, ; abund_model, ioneq_model, dens_model [,wlength=wlength] ; [,tlength=tlength] [,data_files=data_files] ; [,comments=comments] [,outfile=outfile] [,/verbose] ; [,/quiet] [,qabort=qabort] [,/qstop] ) ; ; INPUTS: ; ; MODELNAME - [Mandatory, param] (string scalar) ; This will be the name/ID given to this spectral model. ; It should be sufficiently distinctive to be ; searched on. ; WAVE - [Mandatory, param] (float array, [Nwavelengths]) ; This is a 1D array of monotonically ; increasing wavelengths. Units = 'Angstroms'. Must ; correlate to one dimension of the SPEC array. ; (See "WLENGTH".) ; TEMP - [Mandatory, param] (float array, [Ntemperatures]) ; This is a 1D array of monotonically ; increasing temperatures. Units = 'degrees Kelvin'. ; Must correlate to one dimension of the SPEC array. ; (See "TLENGTH".) ; SPEC - [Mandatory, param] ; (float array, [Nwavelengths, Ntemperatures]) ; This is a 2D array of a spectral emission model. ; Units = 'ph cm^3 s^-1 sr^-1 A^-1'. This variable ; is dependent on WAVE and TEMP. (See "WLENGTH" and ; "TLENGTH".) ; ABUND_MODEL - [Mandatory, param] (string scalar) ; This is a brief description or reference for the ; abundance model that was used to calculate the ; spectra. ; IONEQ_MODEL - [Mandatory, param] (string scalar) ; This is a brief description or reference for the ; ionization equilibrium model that was used to ; calculate the spectra. ; DENS_MODEL - [Mandatory, param] (string scalar) ; This is a brief description or reference for the ; density or emission measure model that was used to ; calculate the spectra. ; WLENGTH - [Optional, keyword] (long scalar) ; 0 < WLENGTH =< n_elements(WAVE) ; Indicates sublength of WAVE array that contains ; valid values, starting at the zero-th index. Only the ; range [0:WLENGTH-1] of WAVE and of the corresponding ; dimension of SPEC will be utilized. Values outside ; this range may be zeroed. Default behavior is to set ; this value equal to the length of the WAVE input ; array. ; TLENGTH - [Optional, keyword] (long scalar) ; 0 < TLENGTH =< n_elements(TEMP) ; Indicates sublength of TEMP array that contains ; valid values, starting at the zero-th index. Only the ; range [0:TLENGTH-1] of TEMP and of the corresponding ; dimension of SPEC will be utilized. Values outside ; this range may be zeroed. Default behavior is to set ; this value equal to the length of the TEMP input ; array. ; DATA_FILES - [Optional, keyword] ; (string scalar or array, [N le 5]) ; These are the source files for the emission model. ; It is up to the user whether they wish to list ; provide them. ; COMMENTS - [Optional, keyword] ; (string scalar or array, [N le 5]) ; There is a field in the generated structure to ; store any relevant comments. ; OUTFILE - [Optional] (string scalar) ; Write the constructed spectral emission model ; structure to the specified file, using . ; The extension ".geny" will be automatically appended ; to the filename. See "Return" output for structure ; description. ; ; KEYWORDS: ; ; /VERBOSE - [Optional] (Boolean) If set, print out extra ; information. Overrides "/quiet" (see Note #2). ; /QUIET - [Optional] (Boolean) If set, suppress messages ; (see Note #2). ; /QSTOP - [Optional] (Boolean) For debugging. ; ; OUTPUTS: ; ; Return - (structure scalar, type=anonymous) ; (OUTVAR) Returns the constructed spectral emission model ; structure. E.g.: ; TYPE STRING 'XRT_emiss_model' ; EMS_STR_VERSION: STRING (anonymous) ; EMS_STR_DESCR: STRING 'Solar spectral emission model ; in XRT-compatible format.' ; NAME: STRING 'XRT default (APED/APEC)' ; WAVE: FLOAT Array[5000] ; WAVE_UNITS: STRING 'Angstroms' ; TEMP: FLOAT Array[50] ; TEMP_UNITS: STRING 'K' ; SPEC: FLOAT Array[5000,50] ; SPEC_UNITS: STRING 'ph cm^3 s^-1 sr^-1 A^-1' ; WLENGTH: LONG 5000 ; TLENGTH: LONG 50 ; ABUND_MODEL: STRING 'Photospheric abundances' ; IONEQ_MODEL: STRING 'Mazotta et al. (1998)' ; DENS_MODEL: STRING '1e10 g cm^-3' ; DATA_FILES: STRING Array[5] ; HISTORY: STRING Array[3] ; COMMENTS: STRING Array[5] ; ; QABORT - [Optional] (Boolean) Indicates that the program ; exited gracefully without completing. (Might be ; useful for calling programs.) ; 0: Program ran to completion. ; 1: Program aborted before completion. ; ; EXAMPLES: ; ; ; COMMON BLOCKS: ; ; none ; ; NOTES: ; ; 1) This routine is part of a modular approach to calculating ; the XRT response functions. A user may use this routine ; to put a spectral emission code into a standardized format ; that related XRT routines will understand. Most spectral model ; codes/atomic databases can generate the required ; inputs in some defined file format and structure. ; ; 2) There are three levels of verbosity. ; a) "verbose" = highest priority. All errors and messages are ; displayed. ("if q_vb") ; b) "quiet" = lower priority. No errors or messages are ; displayed. ("if q_qt") ; c) neither = lowest priority. All errors and some messages are ; displayed. ("if not q_qt") ; ; 3) This routine deprecates, and provides extended functionality ; of, the older routines and ; . ; ; CONTACT: ; ; Comments, feedback, and bug reports regarding this routine may be ; directed to this email address: ; xrt_manager ~at~ head.cfa.harvard.edu ; ; MODIFICATION HISTORY: ; progver = 'v2008-Sep-05' ;--- (M.Weber) Created ; from , v2007-May-16. ; All of the response codes were redesigned to ; provide more information and to work ; together better. progver = 'v2008-Oct-01' ;--- (M.Weber) Reviewed version. ; ;- ; ========================================================================= ; === Initial setup ============================== ;=== Set Booleans which control print statements. ;=== Keyword "verbose" overrules "quiet". q_vb = keyword_set(verbose) q_qt = keyword_set(quiet) and (q_vb eq 0) ;=== Initialize program constants. prognam = 'MAKE_XRT_EMISS_MODEL' prognul = ' ' ;=== Announce version of program. if q_vb then box_message, prognam+': Running ' + progver + '.' if q_vb then print, prognam+': Performing initial setup...' ;=== Set some keyword Booleans. qwlength = keyword_set(wlength) qtlength = keyword_set(tlength) qdatafil = keyword_set(data_files) qcommnts = keyword_set(comments) qoutfile = keyword_set(outfile) qstop = keyword_set(qstop) qabort = 0B if (not keyword_set(comments)) then comments = '' if q_vb then print, prognam+': Performing initial setup...OK' ; === Check inputs =============================== if q_vb then print, prognam+': Checking inputs...' ;=== Abort if the mandatory number of inputs are not provided. if (n_params() ne 7) then begin if (not q_qt) then box_message, prognam+': Missing inputs.' $ + 'See program header. Aborting...' qabort = 1B return, 0 endif if ((datatype(modelname) ne 'STR') $ or (n_elements(modelname) ne 1)) then begin if (not q_qt) then box_message, $ [prognam+': Input MODELNAME has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif if ((is_number(wave[0]) eq 0B) or (n_dimensions(wave) ne 1)) then begin if (not q_qt) then box_message, $ [prognam+': Input WAVE has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif if ((is_number(temp[0]) eq 0B) or (n_dimensions(temp) ne 1)) then begin if (not q_qt) then box_message, $ [prognam+': Input TEMP has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif if ((is_number(spec[0]) eq 0B) or (n_dimensions(spec) ne 2)) then begin if (not q_qt) then box_message, $ [prognam+': Input SPEC has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif else begin if ((n_elements(spec[*,0]) ne n_elements(wave)) $ or (n_elements(spec[0,*]) ne n_elements(temp))) then begin if (not q_qt) then box_message, $ [prognam+': Input SPEC dimensions do not match [WAVE,TEMP].', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif endelse if ((datatype(abund_model) ne 'STR') $ or (n_elements(abund_model) ne 1)) then begin if (not q_qt) then box_message, $ [prognam+': Input ABUND_MODEL has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif else begin if (abund_model eq '') then begin if (not q_qt) then box_message, $ [prognam+': Input ABUND_MODEL is empty. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif endelse if ((datatype(ioneq_model) ne 'STR') $ or (n_elements(ioneq_model) ne 1)) then begin if (not q_qt) then box_message, $ [prognam+': Input IONEQ_MODEL has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif else begin if (ioneq_model eq '') then begin if (not q_qt) then box_message, $ [prognam+': Input IONEQ_MODEL is empty. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif endelse if ((datatype(dens_model) ne 'STR') $ or (n_elements(dens_model) ne 1)) then begin if (not q_qt) then box_message, $ [prognam+': Input DENS_MODEL has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif else begin if (dens_model eq '') then begin if (not q_qt) then box_message, $ [prognam+': Input DENS_MODEL is empty. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif endelse ;=== Make sure WLENGTH has the right type. if qwlength then begin if (is_number(wlength)) then begin if ((datatype(wlength) ne 'INT') and (datatype(wlength) ne 'LON')) $ then qabort = 1B if (n_elements(wlength) ne 1) then qabort = 1B endif else begin qabort = 1B endelse endif else wlength = n_elements(wave) if qabort then begin if (not q_qt) then box_message, $ [prognam+': Input WLENGTH has wrong type. ', $ prognul+' See program header. Aborting...'] return, 0 endif ;=== Make sure WLENGTH has the right size. if ((wlength lt 1) or (wlength gt n_elements(wave))) then begin if (not q_qt) then box_message, $ [prognam+': Input WLENGTH is too small or too big', $ prognul+' compared to the size of WAVE.', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif ;=== Make sure TLENGTH has the right type. if qtlength then begin if (is_number(tlength)) then begin if ((datatype(tlength) ne 'INT') and (datatype(tlength) ne 'LON')) $ then qabort = 1B if (n_elements(tlength) ne 1) then qabort = 1B endif else begin qabort = 1B endelse endif else tlength = n_elements(temp) if qabort then begin if (not q_qt) then box_message, $ [prognam+': Input TLENGTH has wrong type. ', $ prognul+' See program header. Aborting...'] return, 0 endif ;=== Make sure TLENGTH has the right size. if ((tlength lt 1) or (tlength gt n_elements(temp))) then begin if (not q_qt) then box_message, $ [prognam+': Input TLENGTH is too small or too big', $ prognul+' compared to the size of TEMP.', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif wave_temp = wave[0:wlength-1] wdeltas = shift(wave_temp,-1) - wave_temp ss = where(wdeltas le 0.0, wcount) ;; A legitimate (always monotonically increasing) WAVE_TEMP will have a ;; single negative value at the end for the wraparound. if (wcount gt 1) then begin if (not q_qt) then box_message, $ [prognam+': Input WAVE[0:WLENGTH-1] does not montonically', $ prognul+' increase. See program header. Aborting...'] qabort = 1B return, 0 endif ;=== Make sure DATA_FILES has the right type. if qdatafil then begin if ((datatype(data_files) ne 'STR') $ or (n_elements(data_files) gt 5)) then begin if (not q_qt) then box_message, $ [prognam+': Input DATA_FILES has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif endif else data_files = strarr(5) ;=== Make sure COMMENTS has the right type. if qcommnts then begin if ((datatype(comments) ne 'STR') $ or (n_elements(comments) gt 5)) then begin if (not q_qt) then box_message, $ [prognam+': Input COMMENTS has wrong type. ', $ prognul+' See program header. Aborting...'] qabort = 1B return, 0 endif endif else comments = strarr(5) if qoutfile then begin if ((datatype(outfile) ne 'STR') $ or (n_elements(outfile) ne 1)) then begin if (q_qt eq 0) then box_message, $ [prognam+': Output OUTFILE has wrong type. ', $ prognul+' See program header.', $ prognul+' Proceeding, but will not write to OUTFILE...'] qoutfile = 0B return, 0 endif endif if q_vb then print, prognam+': Checking inputs...OK' ; === Reform inputs to desired shape =================== if q_vb then print, prognam+': Cleaning and padding the inputs...' ;=== Make sure unused areas of WAVE, TEMP, and SPEC are zeroed out, ;=== as specified. if (q_vb eq 1) then print, prognam+': Zeroing unused addresses of ' $ + 'WAVE, TEMP, and SPEC.' if (wlength lt n_elements(wave)) then wave[wlength:*] = 0.0 if (tlength lt n_elements(temp)) then temp[tlength:*] = 0.0 if ( (wlength lt n_elements(wave)) and (tlength lt n_elements(temp)) ) $ then spec[wlength:*,tlength:*] = 0.0 ;=== Add empty strings to DATA_FILES to make it strarr(5). data_files_temp = strarr(5) data_files_temp[0:(n_elements(data_files)-1)] = data_files data_files = data_files_temp if (q_vb eq 1) then print, prognam+': Padding DATA_FILES up to strarr(5).' ;=== Add empty strings to COMMENTS to make it strarr(5). comments_temp = strarr(5) comments_temp[0:(n_elements(comments)-1)] = comments comments = comments_temp if (q_vb eq 1) then print, prognam+': Padding COMMENTS up to strarr(5).' if q_vb then print, prognam+': Cleaning and padding the inputs...OK' ; === Generate emission model structure ================ if q_vb then print, prognam+': Generating emission model structure...' outvar = {type: '', $ ems_str_version: '', $ ems_str_descr: '', $ name: '', $ wave: fltarr(n_elements(wave)), $ wave_units: '', $ temp: fltarr(n_elements(temp)), $ temp_units: '', $ spec: fltarr(n_elements(wave),n_elements(temp)), $ spec_units: '', $ wlength: 0L, $ tlength: 0L, $ abund_model: '', $ ioneq_model: '', $ dens_model: '', $ data_files: strarr(5), $ history: strarr(3), $ comments: strarr(5) } outvar.type = 'XRT_EMISS_MODEL' outvar.ems_str_version = '' outvar.ems_str_descr = 'Specifies a spectral emission model in ' $ +'XRT-compatible format.' outvar.name = string(modelname[0]) outvar.wave = float(wave) outvar.wave_units = 'Angstroms' outvar.temp = float(temp) outvar.temp_units = 'K' outvar.spec = float(spec) outvar.spec_units = 'ph cm^3 s^-1 sr^-1 A^-1' outvar.wlength = long(wlength[0]) outvar.tlength = long(tlength[0]) outvar.abund_model = string(abund_model[0]) outvar.ioneq_model = string(ioneq_model[0]) outvar.dens_model = string(dens_model[0]) outvar.data_files = string(data_files[0:4]) outvar.comments = string(comments[0:4]) if q_vb then print, prognam+': Generating emission model structure...OK' ; === Finish ===================================== get_utc, utc, /stime outvar.history[0] = prognam+' '+progver+': ('+utc+' UTC) Generated {' $ + outvar.type+'} structure with name "' $ + outvar.name+'".' if qoutfile then begin if q_vb then print, prognam+': Writing OUTFILE...' savegenx, file=outfile, outvar if q_vb then print, prognam+': Writing OUTFILE...OK' endif if q_vb then print, prognam+': ... Finished.' if qstop then stop return, outvar END ;======================================================================