; Copyright (c) 1998-2014 ER, JDD, A.P. Hitchcock  All rights reserved
;+
;NAME:
;		MISC.PRO
;
;LAST CHANGED: ----------------------------------- 	321 Jul 2014
;
; PURPOSE:
;	This is a set of utility programs
; originally written by Eli Rotenberg & Jonathan Denlinger
;
; CATEGORY: utility, stand alone
;
; CALLING SEQUENCE:
;	RESULT = [NAME](options)
;  fct asc( char )		-- convert char to ascii code
;  fct chr( ascii)		-- convert ascii code to character
;  fct num2str(num,format)	-- simpler syntax than built-in STRING fct
;  fct int2str, num, DIGITS=digits
;     -- integer(s) to string with optional padded zeros
;        if num is an array output adds brackets and commas ([#,...])
;  fct str2arr, str, delimit [, LEN=len, /INT]
;	-- extract an array of values from a string
;  fct ZM, image, mag		-- zoom image size, magnification can be noninteger
;  fct RANGEN, npts, min, max [,option] -- returns preinitialized 1D floating array
;	option: INCR=increment (recalculates npts; max is then to nearest increment)
;  fct GET_LIMITS, arr		-- returns [start, end] vector of 1D array
;  fct GET_RANGE, arr		-- returns [min, max] vector any dimen array
;  fct INDEX, arr, val,  --returns index of 1D array closest to the given value(s)
;	 	/MODE selects alternate method, /TIM - prints execution time
;
; INPUTS:
;		routine specific
;
; COMMON BLOCKS: none
;
; MODIFICATION HISTORY:
;
;  9/21/95 jdd  added INCR option to RANGEN
;  2/13/96 jdd  added STR2ARR
;  (14-nov-00 cgz)
;  NOTE : Nothing other than CHR, NUM2STR, and GET_RANGE is used in AXIS.
;		The calls to these routines can be more efficient by using explicit calls of IDL primitives
;		CHR has been replaced in PARSEBYTES.PRO and READSTRINGBIG.PRO
;		NUM2STR has been replaced in WINDOWS.PRO
;		GET_RANGE has been replaced in AX_ORDER.PRO and PLOT2D.PRO
;		MISC.PRO is now obsolete and can be eliminated
; (15-nov-00 cgz) Replaced call of NCOLS function by explicit (SIZE(var))(1)
; (15-nov-00 cgz)	ASC not called anywhere within AXIS
;				CHR called within PARSEBYTES and READSTRINGBIG - replaced 14nov00
;				NUM2STR called within WINDOW - replaced 14nov00
;				INT2STR not called anywhere within AXIS
;				STR@ARR not called anywhere within AXIS
;				ZM called from within the retired STRUCTURE
;				RANGEN called from within the retired STRUCTURE and the retired MISC
;				GET_LIMITS called from within the retired MISC
;				GET_RANGE called from within AX_ORDER - replaced 14nov00
;									PLOT2D - replaced 14nov00
;									and the retired MISC
;				INDEX not called anywhere within AXIS
; (22-Jul-14 aph) AXIS standard header added
;		num2str is called from win2tif
;-


function asc,char
;===============================
  return,byte(char)
end

function chr,asc
;===============================
  return,string(byte(asc))
end

function num2str, num, format
;===============================
;for single numbers, calling sequence is num2str(1.2345, 'F3.4')
  if keyword_set(format) eq 0 then format='F10.4'
  return,strtrim(string(num, form='(' + format + ')'),1)
end

function int2str, num, DIGITS=digits
;===============================
; pads leading zeros if desired by specifying # digits
; if input is an array, output includes [ , , ]
on_error,2
s=size(num)
array=0
outstr=''
if s(0) gt 0 then begin
   array=1
   outstr='['
endif
np=n_elements(num)
for j=0, np-1 do begin
   if j>0 then outstr=outstr+','
   ndigits=floor(alog10(num(j)+0.01))>0+1
   format='i'+string(format='(i1)',ndigits)
   if not keyword_set(digits) then digits=ndigits
   npad=(digits-ndigits)>0
   pad=''
   for i=0,(npad-1) do pad=pad+'0'
   outstr=outstr+pad+string(num(j), form='(' + format + ')')
endfor
if array then outstr=outstr+']'
return, outstr
end

function str2arr, str, delimit, LEN=len, INT=int, VAL=val
;========================================================
on_error,2
if n_elements(delimit) eq 0 then delimit=','
sarr=STR_SEP(str, delimit)
np=n_elements(sarr)

narr=fltarr(np)
reads, str, narr
if keyword_set(len) then begin
   if len lt np then $
	narr=narr(0:len-1) $
   else begin
	if not keyword_set(val) then val=-1.
   	tmp=fltarr(len) + val
	tmp(0:np-1)=narr
	narr=tmp
   endelse
endif
if keyword_set(int) then narr=fix(narr)
return, narr
end

function zm, image, mag
;======================
;zoom image size by non-integer scale
on_error,2
s=size(image)
fx=long( s(1)*mag )
fy=long( s(2)*mag )
out=congrid( image, fx, fy, interp=1 )
return, out
end

function extendarr, arr, newsize, FILLVAL=val
;=========================================
on_error, 2
s=size(arr)
typ=s(n_elements(s)-2)		; second to last
np=s(n_elements(s)-1)
if typ ne 7 and not keyword_set(val) then val=0
CASE typ OF
'2': newarr=intarr(newsize) + val
'4': newarr=fltarr(newsize) + val
'7': begin
 	if not keyword_set(val) then val=''
	newarr=strarr(newsize) + val
     end
ENDCASE
if newsize lt np then newarr=arr(0:newsize-1) $
else newarr(0:np-1)=arr
return, newarr
end


function rangen, npts, minn, maxx, INCR=inc, PRINT=print
;=========================================
;returns preinitialized 1D floating array (FINDGEN variant)
;values range from minn to maxx; INCR recalculates npts
on_error,2
if keyword_set(inc) then begin
   npts = ROUND( (maxx-minn)/float(inc) ) +1
endif else begin
   inc=(maxx-minn)/float(npts-1)
endelse
x=findgen(npts)*inc + minn
if keyword_set(print) then print, 'Npts=',npts, ', Increment=', inc
return, x
end

function get_limits, arr
;================================
; return vector with [start, end] values of a 1D array
on_error,2
;np=ncols(arr)
np=(size(arr))(1)
return, [arr(0),arr(np-1)]
end

function get_range, arr
;================================
; return vector with [min, max] values of n-dim array
on_error,2
return, [min(arr),max(arr)]
end

function INDEX, arr, val, MODE=minn, TIM=tim
;================================
;returns index of 1D array closest to the given value(s)
;val can be scalar or a 1D array
on_error,2
;check for arr only being 1D?
np=n_elements(arr)
nv=n_elements(val)
iarr=intarr( nv )
sttim=systime(1)
if keyword_set(minn) then $
   for i=0,nv do r=min( (arr - val)^2, iarr(i) ) $
else $
   iarr=round( interpol( findgen(np), arr, val ) )

if keyword_set(tim) then print, systime(1)-sttim, 'secs'
return, reform( iarr )
end
