### Homegrown IDL Routines by JohnJohn

Note to potential end users:

I have provided these programs free of charge as a service to the Astronomy and IDL community. Take what you need and I hope you find something useful. If you find a bug, send me a note and I'll be happy to try and fix it when I get a chance.

On the other hand, PLEASE refrain from sending me emails asking for help with your specific research project. If my code compiles for you, consider it AS-IS. I have a lot on my plate and I don't have the necessary time to figure out why your model is not converging or why my code won't work in your S/N regime. I can, however, assure you that you are not the only person struggling with their research right now. Good luck and hang in there!

This page was created by the IDL library routine `mk_html_help`. For more information on this routine, refer to the IDL Online Help Navigator or type:

`     ? mk_html_help`

at the IDL command line prompt.

# Routine Descriptions

[Next Routine] [List of Routines]
``` NAME:

PURPOSE:
Add or subtract the apparent magnitudes of two stars.

CATEGORY:

CALLING SEQUENCE:

INPUTS:

MA  -  The magnitude of star A
MB  -  The magnitude of the star to be added to A

OPTIONAL INPUTS:

KEYWORD PARAMETERS:

/SUBTRACT  -  Subtract the flux of B from A

OUTPUTS:

The composite magnitude of Star A and B

EXAMPLE:

IDL> ma = 7.0
IDL> mb = 7.0
6.24743

MODIFICATION HISTORY:

Created sometime in ought-four by JohnJohn

```

## ATROUS

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
ATROUS
PURPOSE:
Perform a 1-D "a trous" wavelet decomposition on an image.

CALLING SEQUENCE:
decomposition = ATROUS( spectrum [, filter = filter,  \$
n_scales = n_scales, /check]

INPUTS:
SPECTRUM -- A 1-D Image to Filter

KEYWORD PARAMETERS:
FILTER -- A 1D (!!) array representing the filter to be used.
Defaults to a B_3 spline filter (see Stark & Murtaugh
"Astronomical Image and Data Analysis", Spinger-Verlag,
2002, Appendix A)
N_SCALES -- Set to name of variable to receive the number of
scales performed by the decomposition.
CHECK -- Check number of scales to be performed and return.
OUTPUTS:
DECOMPOSITION -- A 2-D array with scale running along the 2nd axis
(large scales -> small scales). The first plane
of the array is the smoothed image. To recover
the image at any scale, just total the array
along the 2nd dimension up to the scale desired.

RESTRICTIONS:
Uses FFT convolutions which edge-wrap instead of mirroring the
edges as suggested by Stark & Mutaugh.  Wait for it.

MODIFICATION HISTORY:

Mon Oct 6 11:49:50 2003, Erik Rosolowsky
Written.
24 April 2005, JohnJohn: Rewrote as a function, converted to work
with 1D spectra rather than 2D images.

```

(See idlprocs/atrous.pro)

## ATROUS_FILTER

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
ATROUS_FILTER

PURPOSE:
Smooth a 1D spectrum using an a trous wavlet transform
See Starck et al. (1997, ApJ 482:1011-1020)
Starck et al. (2002, PASP 114:1051S)

CALLING SEQUENCE:
new = atrous_filter(spec, noisemodel [,n_scale=, nsig=])

INPUTS:
SPEC: Spectrum to be smoothed

NOISEMODEL: Vector containing uncertainty in each pixel in
SPEC. If measurment uncertainties are Poisson, then
NOISEMODEL = sqrt(SPEC)

KEYWORD PARAMETERS:
N_SCALE: Number of scales in discrete wavelet transform.
Cannot exceed alog(n_elements(spec))/alog(2) - 2

NSIG: Sigma threashold below which features are set to zero
Lower NSIG means more smoothing.

OUTPUTS:
NEW: Smoothed spectrum

DEPENDANCIES:
Uses FAN.pro:
http://astron.berkeley.edu/~johnjohn/idl.html#FAN

MODIFICATION HISTORY:
Written 25 April 2005 by JohnJohn

```

## BENCHMARK

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
BENCHMARK

PURPOSE:
To determine which of two operations or procedures is faster.
;
EXPLANATION:
By conducting a procedure NREPS times, we get an
average time for its operation.  By gathering NAVGS of these
averages we can remove statistical outliers (perhaps the computer
was busy doing something else?) and determine a mean time for
the procedure's operation. This routine is also useful for comparing
two procedures designed to accomplish the same goal.

CALLING SEQUENCE:
benchmark [,NREPS=nreps][,NAVGS=navgs][,/TEST]

INPUTS:
None.

OPTIONAL INPUTS:
NREPS : number of repetitions to determine time average.
NAVGS : number of averages to conduct.

OUTPUTS:
None.

OPTIONAL OUTPUTS:
None.

KEYWORDS:
TEST : Do nothing over and over; a check of system performance.

COMMON BLOCKS:
None.

PROCEDURES CALLED:
CHAUVENET
LEGEND
GETCOLOR

EXAMPLE:
Find which is faster: fltarr(100) or replicate(0,100)
Copy "fltarr(100)" into testroutine1 module below.
Copy "replicate(0,100)" into testroutine2 module below.

IDL> benchmark, nreps=1d3, navgs=1d3

REVISION HISTORY:
Written by T. Robishaw, Berkeley 15 Mar 2001
```

(See idlprocs/benchmark.pro)

## CCPEAK

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
CCPEAK

PURPOSE:
Locates the precise location of the peak in the
cross-correlation function between two vectors.
(Locates LAG_max)

CALLING SEQUENCE:

LAG_max = CCPEAK(VEC1, VEC2 [, RADIUS ])

INPUTS:

VEC1, VEC2 - Functions to be cross-correlated

OPTIONAL INPUTS:

RADIUS -  How many array elements around the
nominal peak where polynomial fit
should be performed.

OUTPUTS:

LAG_max - Lag at which cross-correlation
function is maximized

RESTRICTIONS:

Uses my POLYFIT procedure, not IDL's
POLY_FIT

Uses C_CORRELATE to perform cross-correlation

MODIFICATION HISTORY:
Written sometime in December 2002 by JohnJohn
07 June 2003 JJ - Fixed bug where CF was being indexed out of
range. Also limited the minimum and maximum lag returned to be
min(lag) and max(lag), respectively.
26 June 2003 JJ - Default radius is now 50 rather than 10
```

(See idlprocs/ccpeak.pro)

## COL_STRUCT

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
COL_STRUCT

PURPOSE:
Create an array of structures based on a white-space
delimited string array (e.g. the output from a spawn
command). Each white-space separated "column" is assigned
to a structure field, and each element or "line" in the
string array is assigned to a structure element.

CALLING SEQUENCE:
result = col_struct(lines, tagnames [, types=])

INPUTS:
LINES: String array containing white-space delimited values
TAGNAMES: The name of each column in the string array

KEYWORD PARAMETERS:
TYPES: The data type of each structure tag
i = integer
f = float
d = double
a = string
b = byte

OUTPUTS:
An array of structures

CALLS:

EXAMPLE:

IDL> spawn,'cat data.txt'
HD123   00.0123 -40.48939       7.6     standard
HD423   10.213  -44.40031       8.1     binary
HD1000  14.213  24.00131        3.2     test
IDL> spawn,'cat data.txt', lines
IDL> struct = col_struct(lines, ['star','ra','dec','vmag','notes'] \$
IDL> , types=['a','f','f','f','a'])
IDL> help, struct, /structure
** Structure <2167ce0>, 5 tags, length=36, data length=36, refs=1:
STAR            STRING    'HD123'
RA              FLOAT         0.0123000
DEC             FLOAT          -40.4894
VMAG            FLOAT           7.60000
NOTES           STRING    'standard'
IDL> help, struct
STRUCT          STRUCT    = ->  Array[3]

MODIFICATION HISTORY:

23 Nov 2005 - JohnJohn created
```

(See idlprocs/col_struct.pro)

## CONSEC

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
CONSEC

PURPOSE:
Finds sets of consecutive numbers in
an array.

CALLING SEQUENCE:
CONSEC, ARRAY, LO, HI [, NUM, /SAME]

INPUTS:
ARRAY:  Umm, the array.

KEYWORDS:
SAME:   Search for elements which are the same, rather than
consecutive.
OUTPUTS:
LO: The lower index limit of each set
of consecutive numbers. Each set
goes from LO_i to HI_i

HI: The upper index limit

OPTIONAL OUTPUTS:
NUM:          The number of sets.
DISTRIBUTION: Array containing the number of elements in each
set

OPTIONAL KEYWORDS:
SAME: Search for consecutive elements containing the same value.

EXAMPLE:

IDL> a = [findgen(3),findgen(3)+6]
IDL> print,a
0.00000    1.00000    2.00000    6.00000    7.00000    8.00000

IDL> consec,a,l,h,n
IDL> print,l
0       3
IDL> print,h
2       5
IDL> print,n
2
IDL> print,a[l[0]:h[0]]
0.00000      1.00000      2.00000

MODIFICATION HISTORY:
Written in January 2003 by JohnJohn
4-16-2005 JohnJohn   Found a bug where -1 was returned if there
were only two identical elemeents and /SAME. New logic introduced
to deal with this special case. Also added DISTRIBUTION keyword.

```

(See idlprocs/consec.pro)

## COUNTER

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
COUNTER
PURPOSE:
Print a progress status to the screen on a single
line. This is WAY cooler than it sounds.

CALLING SEQUENCE:
COUNTER, NUMBER, OUTOF  [,INFOSTRING, /PERCENT, WAIT_TIME=variable]

INPUTS:
NUMBER:  The current number. Usually the loop index variable
OUTOF:   The total number of iterations. The last loop index

OPTIONAL INPUTS:

INFOSTRING: A string telling the user what is being
counted e.g. 'Flat '

KEYWORD PARAMETERS:

PERCENT: Set to output update in percent completed
percent = rount(number/outof) * 100

TIMELEFT:  Set to append estimated time remaining.
STARTTIME= Used in conjunction w/ /TIMELEFT. Named variable
that stores the start time of the loop, used for
calculation of time remaining

WAIT_TIME:  Used for test and demo purposes only. See
example below.

OUTPUTS:
Status is printed to the screen and updated on a single line.

SIDE EFFECTS:
This program takes much longer than a simple
print statement. So use COUNTER judiciously.
If your loop consists of only a couple
of relatively quick commands, updating the
status with this program could take up a
significant portion of the loop time!

PROCEDURE:
Put counter statement inside your loop, preferably at the end.

PROCEDURES CALLED:

EXAMPLE:
Try this to see how it works:

IDL> for i = 0,4 do counter,i,4,'test ',wait=.5

MODIFICATION HISTORY:
Written by JohnJohn, Berkeley 06 January 2003
07-Apr-2008 JohnJohn: Finally fixed /TIMELEFT and STARTTIME keywords
```

(See idlprocs/counter.pro)

## CREATE_STRUCT

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
CREATE_STRUCT
PURPOSE:
Create an IDL structure from a list of tag names and dimensions
EXPLANATION:
Dynamically create an IDL structure variable from list of tag names
and data types of arbitrary dimensions.   Useful when the type of
structure needed is not known until run time.

Unlike the intrinsic function CREATE_STRUCT(), this procedure does not
require the user to know the number of tags before run time.   (Note
there is no name conflict since the intrinsic CREATE_STRUCT is a
function, and this file contains a procedure.)
CALLING SEQUENCE:
CREATE_STRUCT, STRUCT, strname, tagnames, tag_descript,
[ DIMEN = , /CHATTER, /NODELETE ]

INPUTS:
STRNAME -   name to be associated with structure (string)
Must be unique for each structure created.   Set
STRNAME = '' to create an anonymous structure

TAGNAMES -  tag names for structure elements
(string or string array)

TAG_DESCRIPT -  String descriptor for the structure, containing the
tag type and dimensions.  For example, 'A(2),F(3),I', would
be the descriptor for a structure with 3 tags, strarr(2),
fltarr(3) and Integer scalar, respectively.
Allowed types are 'A' for strings, 'B' or 'L' for unsigned byte
integers, 'I' for integers, 'J' for longword integers,
'F' or 'E' for floating point, 'D' for double precision
'C' for complex, and 'M' for double complex
Uninterpretable characters in a format field are ignored.

For vectors, the tag description can also be specified by
a repeat count.  For example, '16E,2J' would specify a
structure with two tags, fltarr(16), and lonarr(2)

OPTIONAL KEYWORD INPUTS:
DIMEN -    number of dimensions of structure array (default is 1)

CHATTER -  If /CHATTER is set, then CREATE_STRUCT will display
the dimensions of the structure to be created, and prompt
the user whether to continue.  Default is no prompt.

NODELETE - If /NODELETE is set, then the temporary file created
CREATE_STRUCT will not be deleted upon exiting.   See below

OUTPUTS:
STRUCT -   IDL structure, created according to specifications

EXAMPLES:

IDL> create_struct, new, 'name',['tag1','tag2','tag3'], 'D(2),F,A(1)'

will create a structure variable new, with structure name NAME

To see the structure of new:

IDL> help,new,/struc
** Structure NAME, 3 tags, 20 length:
TAG1            DOUBLE         Array(2)
TAG2            FLOAT          0.0
TAG3            STRING         Array(1)

PROCEDURE:
Generates a temporary procedure file using input information with
the desired structure data types and dimensions hard-coded.
This file is then executed with CALL_PROCEDURE.

NOTES:
If CREATE_STRUCT cannot write a temporary .pro file in the current
directory, then it will write the temporary file in the getenv('HOME')
directory.

At present, can fail if a tag_name cannot be used as a proper
structure component definition, e.g., '0.10' will not
work, but a typical string like 'RA' or 'DEC' will.
A partial workaround checks for characters '\' and '/'
and '.' and converts them to '_'. in a tag_name.

Note that 'L' now specifies a LOGICAL (byte) data type and not a
a LONG data type for consistency with FITS binary tables

RESTRICTIONS:
The name of the structure must be unique, for each structure created.
Otherwise, the new variable will have the same structure as the
previous definition (because the temporary procedure will not be
recompiled).  ** No error message will be generated  ***

SUBROUTINES CALLED:
FDECOMP, GETTOK(), REPCHR()

MODIFICATION HISTORY:
Version 1.0 RAS January 1992
Modified 26 Feb 1992 for Rosat IDL Library (GAR)
Modified Jun 1992 to accept arrays for tag elements -- KLV, Hughes STX
Accept anonymous structures W. Landsman  HSTX    Sep. 92
Accept 'E' and 'J' format specifications   W. Landsman Jan 93
'L' format now stands for logical and not long array
Accept repeat format for vectors        W. Landsman Feb 93
Accept complex and double complex (for V4.0)   W. Landsman Jul 95
Work for long structure definitions  W. Landsman Aug 97
Converted to IDL V5.0   W. Landsman   September 1997
Write temporary file in HOME directory if necessary  W. Landsman Jul 98
Use OPENR,/DELETE for OS-independent file removal W. Landsman Jan 99
```

## CURSE

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
CURSE

PURPOSE:
Print the position and optionally the value of a
mouse click on a plot. Wrapper for IDL's CURSOR
procedure.

CATEGORY:

CALLING SEQUENCE:

CURSE [,IMAGE]

OPTIONAL INPUTS:

IMAGE - 2-D array currently displayed. Z value
is printed along with position.

OUTPUTS:

PROCEDURE:
Plot or display data. Execute curse and click
on the image. When done, click negative X value.

RESTRICTIONS:
This is best used for CCD or spectral data where
there are no negative ordinate or X-axis values.

Don't worry about the name. It's just short for
CURSOR but way cooler sounding. Author not responsible
for actual curses.

MODIFICATION HISTORY:
Written sometime in Dec 2002 by JohnJohn
02.07.2003  JJ  Modified so any click outside of the
plot range causes CURSE to exit
```

(See idlprocs/curse.pro)

## DRAWRAND

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
DrawRand

PURPOSE:
Draw a random set of N values X following the probability
distribution function P(X).

CATEGORY:

Statistical fun

CALLING SEQUENCE:

result = DrawRand( USERFUNC, NNUM, XRANGE [, /BUILTIN, YMAX =] )

INPUTS:

USERFUNC -  The name of a user-defined function that
provides P(X). This function must be pre-
compiled. The probablility function P(X)
returned by USERFUNC should be "normalized"
such that the most likely value X = Xo should
produce P(Xo) = 1.0 with all other values of
P(X) scaled accordingly and the minimum value
P(X)_min = 0

Alternatively, you may specify the range
of possible P(X) values using the YMAX =
keyword.

USERFUNC is ignored if /BUILTIN is set

NNUM     -  The number of random values to be returned

XRANGE   -  The limits on the range of values X can take.
If this input is not supplied, then the
function USERFUNC should return the xrange
when no inputs are supplied to USERFUNC, i.e.
the following, or similar, line should be in
USERFUNC:

if n_params() = 0 then return, xrange

OUTPUTS:

result    -  A random set of NNUM values of X which follow
the PDF defined in USERFUNC.

KEYWORDS:

YMAX      -  Specifies the maximum value returned by
USERFUNC.
BUILTIN   -  Use the built-in function DRAWRAND_FUNC
to return P(X).

PROCEDURE:
For a single value (NNUM = 1):

1) Choose a uniform random number Xi between XRANGE[0] and
XRANGE[1] and a uniform random value Yi between 0 and 1
2) Evaluate P(Xi)
a) if P(Xi) > Yi then return Xi

EXAMPLE:

MODIFICATION HISTORY:
Written by John "JohnJohn" Johnson 23-Apr-2004
Heavily revised by Jason Wright 24-Apr-2004
```

(See idlprocs/drawrand.pro)

## FAN

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
FAN

PURPOSE:
Take the outer product of the input ARRAY and a
UNIT_VECTOR to "fan out" a 1D vector into an array
comprised of the vector repeated row-wise NFAN times.
Useful for array-wise mathematics (Look Ma, no FOR loops!)

CALLING SEQUENCE:
result = fan(array [,nfan, /transpose])

INPUTS:
ARRAY - 1D array, input vector
NFAN  - number of times to repeat the input vector,
default is N_ELEMENTS(ARRAY)

KEYWORD PARAMETERS:

TRANSPOSE - Repeat the input vector column-wise

OUTPUTS:
A 2D array with N_ELEMENTS(ARRAY) columns and NFAN
rows.

EXAMPLE:
Fan a FINDGEN of 3 elements, twice.

IDL> a = findgen(3)
IDL> print,fan(a,2)
0.00000      1.00000      2.00000
0.00000      1.00000      2.00000

MODIFICATION HISTORY:
Created sometime in ought-2 by JohnJohn
06 Dec 2002 JohnJohn- Added some error handling at the beginning
```

(See idlprocs/fan.pro)

## FIFTEENB

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
FIFTEENB

PURPOSE:
Return the string version of the octal character
"15b which print's a new line to the screen. Used
by COUNTER.PRO This is a separate routine because the
unclosed quotation mark messes up IDLWAVE in Emacs, and
I can't have that!

CATEGORY:

CALLING SEQUENCE:

result = fifteenb()

INPUTS:

OPTIONAL INPUTS:

KEYWORD PARAMETERS:

OUTPUTS:

result is set to string("15b)

OPTIONAL OUTPUTS:

COMMON BLOCKS:

SIDE EFFECTS:

RESTRICTIONS:

PROCEDURE:

EXAMPLE:

MODIFICATION HISTORY:

```

(See idlprocs/fifteenb.pro)

## FILLARR

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
FILLARR

PURPOSE:
This function generates an array from MIN to MAX with
step size DEL. If an integer number of steps cannot be
fit between MIN and MAX, then MAX will be adjusted to
be as close as the specified maximum as possible.

CATEGORY:

CALLING SEQUENCE:
f = fillarr(n, min, max [,fan=, transfan=, /double])

INPUTS:
DEL:  The desired step size
MIN:  The value of the first array element in F
MAX:  The value of the last array element in F if
(MAX-MIN)/DEL is an integer. Adjusted otherwise.

OPTIONAL INPUTS:

KEYWORD PARAMETERS:

FANNNED:    Number of times the array is to be repeated.
The final dimensions of F  will be
fix((MAX-MIN)/DEL) + 1 columns by FANNED ows.

/TRANSPOSE  Final dimensions of F wil be FAN columns by
fix((MAX-MIN)/DEL) + 1 rows if FAN is specified.

OUTPUTS:

F:    Final array. If input parameters are double precision,
then F will be double as well. F is float otherwise.

RESTRICTIONS:

You'll need FAN.PRO to use the fan= keyword.
http://astron.berkeley.edu/~johnjohn/idl.html#FAN

EXAMPLE:

For an array that runs from 2 to 5 in steps of .7

IDL> f = fillarr(.7,2,5)
IDL> print, f
2.00000      2.70000      3.40000     4.10000    4.80000

MODIFICATION HISTORY:
Written by John "JohnJohn" Johnson 21-Feb-2002
22-Feb-2002 JohnJohn- Fixed precision bug
23-Feb-2002 JohnJohn- Calculations performed in double precision.
Output in double precision if input is
double.
01-Mar-2002 JohnJohn- Much props to Tim Robishaw (Tdogg) for helping
me understand machine precision and finally fixing
the precision bug.
23 Apr 2002 JohnJohn- Modified the /FAN operation to match my new
FAN procedure. Default direction of the
fanning process is in the column direction,
i.e. a 5-element array with FAN=2 will yeild a
5x2 array rather than the other way around.
06 Dec 2002 JohnJohn- Modified the /FAN operation again to run using
the actuall FAN proceedure which is faster
than doing two separate operations for fanning
and taking the transpose. duh.
14 Apr 2005 JohnJohn- Fixed bug where if n_params() eq 2, then MIN
was being modified. Input variable now
protected by renaming MIN as MININ.
```

(See idlprocs/fillarr.pro)

## FINDEL

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
FINDEL

PURPOSE:
Find the index in ARRAY that is the closest match to
a scalar VALUE.

CATEGORY:
Array Handling (?)

CALLING SEQUENCE:

result = findel(value, array, /matrix)

INPUTS:

ARRAY - vector to be searched
VALUE - Scalar value to be matched

OUTPUTS:

RESULT - The index of ARRAY which is the closest to VALUE

EXAMPLE:

IDL> array = [1.3, 2.4, 3.5, 4.2]
IDL> value = 3.1
IDL> result = findel(value, array)
IDL> print,result
2
IDL> print,array[result]
3.50000

MODIFICATION HISTORY:

Wheel reinvented (I'm sure) sometime around 12.17.2002 by JohnJohn
11.16.2003  JohnJohn - If /matrix set return array containing [col,row].

```

(See idlprocs/findel.pro)

## HLINE

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
HLINE

PURPOSE:
Draw a horizontal line on a pre-existing plot window.

CALLING SEQUENCE:
HLINE, VAL

INPUTS:

VAL: The y-value where the vertical line should be drawn

KEYWORD PARAMETERS:

All keyword parameters are passed to OPLOT.

SIDE EFFECTS:

Causes a horizontal line to appear on your screen.

RESTRICTIONS:

This program won't do anything else. Sorry, them's the
restrictions.

EXAMPLE:

Draw a horizontal line at x = 4
IDL> plot, findgen(10)
IDL> hline, 4

MODIFICATION HISTORY:
Written sometime in 2003 by JohnJohn
4 June 2009: Modified to handle case of /xlog (hat tip to Michael Williams)

```

(See idlprocs/hline.pro)

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:

PURPOSE:
Add a tag to a pre-existing array of strutures

CALLING SEQUENCE:

INPUTS:
tag_name - The name of a new structure tag to be added
value    - The value to be assigned to the new tag

KEYWORD PARAMETERS:

array_tag - Set this keyword flag if value is an array that
should be inserted into a single tag, e.g. if
struct.tag_name = fltarr(10)

OUTPUTS:

A new array of structures

RESTRICTIONS:

Only works with anonymous structures. But the code is 46%
faster than the ICG routine ADD_TAG2. Tested using Tim
Robishaw's BENCHMARK.

EXAMPLE:

struct = {a: 0., b: 'blah'}
help,new,/struct
** Structure <2453f8>, 3 tags, length=32, data length=21, refs=1:
A               FLOAT           0.00000
B               STRING    'blah'
NEW             BYTE         0

MODIFICATION HISTORY:

20 Apr 2005 - JohnJohn created
20 Apr 2005 - Fixed so that NEW is actually assigned the value
VALUE rather than just 0. Thank's Louis!
```

## JJGAUSSFIT

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
JJGAUSSFIT

PURPOSE:
Fits a gaussian to a 1D distribution of points, This is a wrapper
for Craig Markwardt's infinitely useful fitting package MPFIT.

Unlike IDL's GAUSSFIT, this function optionally accounts
for measurement errors

Fits the function:

f(x) = a0 * exp(-z^2/2) + a3

where

z = (x - a1)/a2

CATEGORY:

Getting the job done (TCB).

CALLING SEQUENCE:

fit = jjgaussfit(x, y [, param])

INPUTS:
x:  independant variable
y:  independant variable

KEYWORDS:

FIXAMP=, FIXCEN=,  FIXWID=, FIXBG=: Scalar value at which the
centroid, amplitude, width or background (offset),
respectively, should be held fixed during the fit.

LIMITAMP=, LIMITCEN=, LIMITWID=, LIMITBG=: 2-element array
specifying lower and upper limits of the centroid, amplitude,
width or background (offset), respectively.

MOVIE: Play a movie during the fit procedure.

GUESS: 4-element array containing the parameter guesses. If
guesses are not set manually, then parameter guesses are
determined automatically.

GUESS[0] = Amplitude
GUESS[1] = Centroid
GUESS[2] = Sigma width
GUESS[3] = Background offset

YERR: 1 sigma errors associated with each Y

OUTPUTS:

FIT: The best-fit Gaussian evaluated at each X
PARAM: 4 element vector containing the fit parameters
param = [a0, a1, a2, a3]

EXAMPLE:

x = findgen(121) * 0.25 - 15
y = 1d2 * exp(-x^2) + 2
yn = 1d2 - (y + randomn(seed, 121)*sqrt(y))
p0 = [-110, 0.05, 1.1, 90]
g = jjgaussfit(x, yn, a, yerr=sqrt(y), guess=p0, /movie)

MODIFICATION HISTORY:
12 Dec 2003 Written by JohnJohn
05 Dec 2004 JJ - fixed bug in FWHM guess
22 Feb 2005 JJ - fixed to work with negative amplitudes. Stole
parameter guesses from GAUSSFIT.PRO
06 Mar 2005 JJ - added MOVIE keyword.
15 Mar 2005 JJ - modified parameter guess logic to w ork  with
continuum-normalized absorption lines
18 Mar 2005 JJ - added GUESS keyword
```

(See idlprocs/jjgaussfit.pro)

## JZAP

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
JZAP

PURPOSE:
Kills cosmic rays dead. Designed for echelle orders, but works
for images as well.

CALLING SEQUENCE:
smoothim=, /noreplace ]

INPUTS:
OLDRORDER - Original image with cosmic rays.

KEYWORD PARAMETERS:
NSIG      - Number of standard deviations above it's neighbors
a pixel must stand in order to be considered a
cosmic ray candidate.

same dimensions as OLDORDER.

the number of columns in OLDORDER.

SMOOTHIM  - The median-smoothed image of the order is returned
through this keyword.

NOREPLACE - By default, cosmic rays are replaced by the
corresponding pixel in a median smoothed image of
the order. /NOREPLACE does not perform this
step. Use NOREPLACE when JZAP is used in
conjunction with an Optimal Extraction algorthim.

OPTIONAL OUTPUTS:
NEWORDER  - New image sans cosmic rays.

SIDE EFFECTS:
Replaces cosmic rays with the median of the neighborhood unless
the NOREPLACE keyword is set.

RESTRICTIONS:
Uses a while loop to iterate. May be kinda slow. But I haven't
found a better way to get rid of cosmics in a rectified
exchelle order.

JZAP is most sensitive in the dispersion direction and works
best with low-signal spectra. (Cosmic rays in the MIKE
spectrograph run preferentially in the cross-dispersion direction)

PROCEDURE:
All peaks in the image are located in the dispersion (row-wise)
direction. Cosmic rays are identified as those peaks which
stand out NSIG standard deviations above their neighbors on the
left *and* right. This prevents line features from being
identified as cosmics. Emission lines may stand out from the spetrum,
but each pixel in a line will not A) be a peak and B) stand out
NSIG from its neighbors on both sides. This process is repeated
in the cross-dispersion direction.

EXAMPLE:

IDL> im = randomn(seed,200,20)
IDL> im[randomu(seed,8)*2000+2000] = randomu(seed,8)*50+20
IDL> jzap,im,nim
IDL> display,im,max=10
IDL> display,nim,max=10

MODIFICATION HISTORY:
Written by JohnJohn in April 2003
04 June 2003 JohnJohn   Added NOREPLACE, SMOOTHIM and fixed error on
line 113 where D3 was supposed to be D4.
```

(See idlprocs/jzap.pro)

## MAKEARR

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
MAKEARR

PURPOSE:
This procedure will generate an array of lenght N which
runs from values MIN to MAX

CATEGORY:

CALLING SEQUENCE:
f = makearr(n, min, max [,fan=, transfan=, /double])

INPUTS:

N:    The number of desired array elements in F
MIN:  The value of the first array element in F
MAX:  The value of the last array element in F

OPTIONAL INPUTS:

KEYWORD PARAMETERS:

FANNED:     Number of times the array is to be repeated.
The final dimensions of F  will be N columns
by FANNED rows.
/TRANSPOSE  Final dimensions of F wil be FAN columns by N
rows if FAN is specified.

OUTPUTS:

F:    Final array

RESTRICTIONS:

You'll need FAN.PRO to use the fan= keyword.
http://astron.berkeley.edu/~johnjohn/idl.html#FAN

EXAMPLE:

If you want a 5 element array which runs from 2 to 4:

IDL> f = makearr(5,2,4)
IDL> print, f
2.00000      2.50000      3.00000      3.50000      4.00000

MODIFICATION HISTORY:
Written by John "JohnJohn" Johnson somewhere around Oct-2001
20 Feb 2002 JohnJohn- Added /FAN and /TRANSPOSE keywords.
23 Feb 2002 JohnJohn- Calculations performed in double precision.
Output in double precision if all input
parameters are double.
01 Mar 2002 Tim Robishaw- Spiffed up with a little Tim.
08 Mar 2002 JohnJohn- changed the order of operations to keep the
last number of the array equal to MAX with no
error. Props to Carl Heiles.
23 Apr 2002 JohnJohn- Modified the /FAN operation to match my new
FAN procedure. Default direction of the
fanning process is in the column direction,
i.e. a 5-element array with FAN=2 will yeild a
5x2 array rather than the other way around.
14 Apr 2005 JohnJohn- Fixed bug where if n_params() eq 2, then MIN
was being modified. Input variable now
protected by renaming MIN as MININ.
```

(See idlprocs/makearr.pro)

## MAKE_CIRC

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
MAKE_CIRC

PURPOSE:
create a circle on a pre-existing array

CATEGORY:

array

CALLING SEQUENCE:

result = make_circ(array, radius [, indices, cent = [xo,yo],
val = val])

INPUTS:

array:    2-D array on which to draw the circle

OPTIONAL INPUTS:

indices:  array of the index values of ARRAY which fall
within one RADIUS of the center

KEYWORD PARAMETERS:

center:   array holding the x and y coordinate of the
centroid, center of the input array chosen by default
val:      value to set array elements which fall within one RADIUS

OUTPUTS:

2-D array

EXAMPLE:

to draw a circle on a blank array
IDL> blank = fltarr(5,5)
IDL> result = make_circ(blank, 1)
IDL> print, result
0.00000      0.00000      0.00000      0.00000      0.00000
0.00000      0.00000      1.00000      0.00000      0.00000
0.00000      1.00000      1.00000      1.00000      0.00000
0.00000      0.00000      1.00000      0.00000      0.00000
0.00000      0.00000      0.00000      0.00000      0.00000

MODIFICATION HISTORY:
Originally written by JohnJohn sometime around ought-one.
Robishaw taught me how to do this. He is wicked cool.
```

(See idlprocs/make_circ.pro)

## MAKE_HERM

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
MAKE_HERM

PURPOSE:
Generate the coefficients for the first
N Hermite Polynomials, H_0...H_n

CALLING SEQUENCE:

MAKE_HERM, N, C_n, [,/TRANSPOSE]

INPUTS:
N:   The desired number of terms.

KEYWORD PARAMETERS:

/TRANSPOSE  Set if you want the
C_n matrix to be
transposed

OUTPUTS:
C_n: An (N+1) x (N+1) matrix of
coeffiecients

EXAMPLE:

The first 3 Hermite Polynomials are
H_0 = 1
H_1 = 2x
H_2 = -2 + 4x^2

IDL> make_herm, 2, c
IDL> print, c
1.0000000       0.0000000       0.0000000
0.0000000       2.0000000       0.0000000
-2.0000000       0.0000000       4.0000000

MODIFICATION HISTORY:
Created sometime in 2002 by JohnJohn for PSF
modeling. If you use this, let me know!
```

(See idlprocs/make_herm.pro)

## PEAKS

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
PEAKS

PURPOSE:
Find the peaks in a vector (spectrum) which lie
NSIG above the standard deviation of all peaks in
the spectrum

CALLING SEQUENCE:
result = peaks(y, nsig [,npk])

INPUTS:
Y - Vector (usually a spectrum) in which you want to
locate peaks.
NSIG - Number of sigma above the standard deviation of
all peaks to search.

OUTPUTS:

RESULT - Vector holding the indecies of the peaks in Y

OPTIONAL OUTPUTS:

NPK - The number of peaks located

NOTES:

NSIG is NOT the number of sigma above the noise in the spectrum.
It's instead a measure of the significance of a peak. First, all
peaks are located. Then the standard deviation of the peaks is
calculated using ROBUST_SIGMA (see Goddard routines online). Then
peaks which are NSIG above the sigma of all peaks are selected.

EXAMPLE:

IDL> y = randomn(seed,2000)
IDL> pk = peaks(y,2)
IDL> plot,y
IDL> oplot,pk,y[pk],ps=2

MODIFICATION HISTORY:

```

(See idlprocs/peaks.pro)

## PICKMIN

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
PICKMIN

PURPOSE:
Moves a sampling window through an
array and picks out the index of the
local minimum (or maximum) in each
window.

CALLING SEQUENCE:

RESULT = PICKMIN( ARRAY [, NWIN, WINDOW = WINDOW, /MAX])

INPUTS:

ARRAY:  Input array

KEYWORD PARAMETERS:

WINDOW: Window size. Default is 32
/MAX:   Find maxima instead of minima

OUTPUTS:

RESULT: Indeces of local minimum within
each window.

OPTIONAL OUTPUTS:

NWIN:   The number of windows used based
on size of WINDOW.

Written by JohnJohn in December 2002.
09.11.2003   JJ  Implemented strategic use of double precision
```

(See idlprocs/pickmin.pro)

## POLYFIT

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
POLYFIT

PURPOSE:
Fit a polynomial to a function using linear least-squares
NOTE:
Twice as fast as POLY_FIT.PRO as tested by Robishaw's
BENCHMARK.PRO due to the miracle of loopless IDL code.

Uses JohnJohn's FAN.PRO
http://astron.berkeley.edu/~johnjohn/idlprocs/fan.pro

CALLING SEQUENCE:
coeffs = polyfit(t, y_of_t, degree [, yfit, dum, covariance=])

KEYWORDS
MODIFICATION HISTORY:
Written by JohnJohn long ago in ought 1 after attending Carl
Heiles' lecture on line fitting.
```

(See idlprocs/polyfit.pro)

## ROBUST_MEAN

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
Robust_Mean

PURPOSE:
Outlier-resistant determination of the mean and standard deviation.

EXPLANATION:
Robust_Mean trims away outliers using the median and the median
absolute deviation.    An approximation formula is used to correct for
the trunction caused by trimming away outliers

CALLING SEQUENCE:
mean = Robust_Mean( VECTOR, Sigma_CUT, Sigma_Mean, Num_RejECTED)

INPUT ARGUMENT:
VECTOR    = Vector to average
Sigma_CUT = Data more than this number of standard deviations from the
median is ignored. Suggested values: 2.0 and up.

OUTPUT ARGUMENT:
Mean  = the mean of the input vector, numeric scalar

KEYWORDS:

GoodInd = The indices of the values not rejected

OPTIONAL OUTPUTS:
Sigma_Mean = the approximate standard deviation of the mean, numeric
scalar.  This is the Sigma of the distribution divided by sqrt(N-1)
where N is the number of unrejected points. The larger
SIGMA_CUT, the more accurate. It will tend to underestimate the
true uncertainty of the mean, and this may become significant for
cuts of 2.0 or less.
Num_RejECTED = the number of points trimmed, integer scalar

EXAMPLE:
IDL> a = randomn(seed, 10000)    ;Normal distribution with 10000 pts
IDL> Robust_Mean,a, 3, mean, meansig, num    ;3 Sigma clipping
IDL> print, mean, meansig,num

The mean should be near 0, and meansig should be near 0.01 ( =
1/sqrt(10000) ).
PROCEDURES USED:
AVG() - compute simple mean
REVISION HISTORY:
Written, H. Freudenreich, STX, 1989; Second iteration added 5/91.
Use MEDIAN(/EVEN)    W. Landsman   April 2002
Correct conditional test, higher order truncation correction formula
R. Arendt/W. Landsman   June 2002
New truncation formula for sigma H. Freudenriech  July 2002
```

(See idlprocs/robust_mean.pro)

## SHIFT_INTERP

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
SHIFT_INTERP

PURPOSE:
Shift an array by a non-integer amount
using interpolation.

CALLING SEQUENCE:

RESULT = SHIFT_INTERP( SPEC, MOVE, /SPLINE )

INPUTS:

SPEC:   Array to be shifted
MOVE:   Amount to shift. If SPEC is 1-D, then MOVE is a
scalar. If SPEC is 2-D and if MOVE is a scalar, shift is applied
only in X-direction. If MOVE is a 2-D array, then shift is
applied in both directions.

OUTPUTS:

RESULT:  Shifted array

KEYWORD PARAMETERS:

SPLINE:  Use spline rather than linear interpolation. For 1-D
only.

SIDE EFFECTS:

Don't use this with excessively noisy
data lest you interpolate and therefor exacerbate
the noise.

EXAMPLE:

Create a gaussian and shift it to the right
by 0.5

IDL> x = findgen(81)-40
IDL> g = exp(-x^2/10.^2)
IDL> plot,x,g,/xs
IDL> gs = shift_interp(g,0.5)
IDL> oplot,x,gs,lines=3
IDL> gsreal = exp(-(x-0.5)^2/10.^2)
IDL> print,stdev(gsreal[1:*] - gs[1:*])/max(gs)
1.0892190e-06

MODIFICATION HISTORY:
02.08.2003   Written by JohnJohn
04.28.2003   JJ - Fixed problem where nothing would be returned for
integer shifts. Now handles integer shifts as if it were SHIFT.PRO
05.02.2003   JJ - Now uses faster spline method. SPLINE.PRO is
slooowwwww...
06.04.2003   JJ - Now uses linear interpolation by default and spline
interpolation as a keyword option.
06.09.2003   JJ - Corrected mistake by repacing IF bigmove GT 0 with
IF abs(bigmove) GT 0
11.02.2005   JJ - Added 2-D shifting for my imaging peeps.
```

## SIGFIG

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
SIGFIG

PURPOSE:
Accept a scalar numerical value or an array of numbers and
return the numbers as strings with the specified number of
significant figures.

CALLING SEQUENCE:
RESULT = SigFig(Number, Nfig [, /SCIENTIFIC, /PLUSSES, /NUMERICAL)

INPUTS:
Number - Scalar or array of numerical values (float, double, int)
Nfig   - Number of signficant figures desired in the output

OUTPUTS:
String representation of the input with the specified number
of signficant figures.

KEYWORD PARAMTERS:
/SCIENTIFIC - return the numbers in scientific notation
/PLUSSES    - Include plus signs for positive numbers
/NUMERICAL  - Return numerical, rather than string, values

EXAMPLE:
IDL> print, sigfig(-0.0001234, 2)
-0.00012
IDL> print, sigfig(1.234, 1)
1.
IDL> print, sigfig(1234, 1)
1000
IDL> print, sigfig(-0.0001234, 2, /sci)
-1.2e-4
IDL> print, sigfig(1234, 2, /plus)
+1200
IDL> print, sigfig(1234, 2, /plus, /sci)
+1.2e+3

MODIFICATION HISTORY:
Inspired long ago by Erik Rosolowsky's SIGFIG:
http://www.cfa.harvard.edu/~erosolow/idl/lib/lib.html#SIGFIG

This version written by JohnJohn Sept 29, 2005

24 Oct 2007 - If result is a single number, return scalar value
instead of an 1-element array. Thanks Mike Liu.
2 Apr 2008 - Fixed 1-element array issue, but for real this time.
```

(See idlprocs/sigfig.pro)

## STR

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
STR

PURPOSE:
Do what the IDL-native STRING doesn't do well

CATEGORY:
String manipulation

CALLING SEQUENCE:
RESULT = STR( INSTRING, length=, format=, char=, /trail )

INPUTS:
INSTRING - Input string array to be formatted

OPTIONAL INPUTS:

KEYWORD PARAMETERS:
LENGTH=  Final length of each outpu string.
FORMAT=  Normal IDL Format string, passed to STRING()
CHAR  =  Single character to be appended to each output string in
order to be of length LENGTH
/TRAIL=  Set if CHAR is to be appended rather than prepended

OUTPUTS:
RESULT - Formated array of length equal to input

OPTIONAL OUTPUTS:

COMMON BLOCKS:

SIDE EFFECTS:

RESTRICTIONS:

PROCEDURE:

EXAMPLE:
IDL> print,str(1)
1
IDL> print,str(1, char='0', length=3)
001
IDL> print,str(1, char='*', length=3, /trail)
1**
IDL> print,str(1.0, format='(f3.1)')
1.0

MODIFICATION HISTORY:
Created sometime in 2003 by JohnJohn
14 May 2009 - JJ: reduced looping by using HISTOGRAM magic

```

(See idlprocs/str.pro)

## STRUCT_CONV

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
STRUCT_CONV

PURPOSE:
Convert a structure containing array fields of the same length
N_el into an N_el array of structures

CALLING SEQUENCE:

new_struct = struct_conv( old_struct)

RESTRICTIONS:

You'll need the Goddard routine create_struct:
http://astro.berkeley.edu/~johnjohn/idl.html#CREATE_STRUCT

INPUTS:
old_struct: The original structure containing arrays of the
same length in each of its fields

OUTPUTS:
new_struct: An array of structures

EXAMPLE:

old = {a: fltarr(100), b: fltarr(100)}
help, old
OLD             STRUCT    = ->  Array[1]
help, old, /str
** Structure <5fe1f8>, 2 tags, length=800, data length=800, refs=1:
A               FLOAT     Array[100]
B               FLOAT     Array[100]
new = struct_conv(old)
help, new
NEW             STRUCT    = ->  Array[100]
help, new, /str
** Structure <5d5c58>, 2 tags, length=8, data length=8, refs=1:
A               FLOAT           0.00000
B               FLOAT           0.00000

MODIFICATION HISTORY:
Written by JohnJohn sometime in early ought 5.
```

(See idlprocs/struct_conv.pro)

## VIEW

[Previous Routine] [Next Routine] [List of Routines]
``` NAME:
VIEW

PURPOSE:
Look at an array one row at a time. Useful for viewing
echelle spectra arrays one order at a time. Click the
screen to move to the next row.

CATEGORY:

CALLING SEQUENCE:
VIEW, ARRAY [,SM=SM]

INPUTS:
ARRAY - 2D array of stuff you wanna look at

OPTIONAL INPUTS:

KEYWORD PARAMETERS:
SM - Smooth each row by this amount.

All other keyword parameters are passed on to PLOT. See
? PLOT for list of plotting keywords.

OUTPUTS:
Pretty plot.

PROCEDURE:

EXAMPLE:

MODIFICATION HISTORY:
Written a long time ago by JohnJohn
```

(See idlprocs/view.pro)

## VLINE

[Previous Routine] [List of Routines]
``` NAME:
VLINE

PURPOSE:
Draw a vertical line on a pre-existing plot window.

CALLING SEQUENCE:
VLINE, VAL

INPUTS:

VAL: The x-value or array of x-values where the vertical
line(s) should be drawn

KEYWORD PARAMETERS:

All keyword parameters are passed to OPLOT.

SIDE EFFECTS:

Causes a vertical line to appear on your screen.

RESTRICTIONS:

This program won't do anything else. Sorry, them's the
restrictions.

EXAMPLE:

Draw a vertical line at x = 0
IDL> plot, findgen(10)
IDL> vline, 5

MODIFICATION HISTORY:
Written sometime in 2003 by JohnJohn
4 June 2009: Modified to handle case of /xlog (hat tip to Michael Williams)

```

(See idlprocs/vline.pro)