- More Maths

- Natural logarithm: ALOG(X)
- Base 10 log: ALOG10(X)
- Trigonometric functions: SIN(X), COS(X), TAN(X)
- Inverse Trig functions: ASIN(X), ACOS(X), ATAN(X)
- All Trig functions are based on Radians
- Scientific Notation: 6e+7 = 60,000,000. 3e-4 = 0.0003
- Absolute Value: ABS(X)

- Definition of an Array

An array is a matrix variable. It can be used to store whole rows, columns, tables, or even cubes of data. Arrays are made up of many individual elements, which are the same as variables. For instance, if A is an array of length 10, it would look like:______________________________ |0||1||2||3||4||5||6||7||8||9| ------------------------------

Where 0 - 9 are the indicies of the individual array elements. The first element in an array always has the index of 0. Array elements are accessed with [] square brackets. Each element can be treated just as any variable would. For instance, A[1] = 5*3. Arrays can be very useful for instance when you want to store the prices of 50 different items or when you want to store the flux of an object at thousands of different wavelengths. - Arrays in IDL
- Unlike most languages, in IDL many operations can be performed directly on the entire array instead of having to loop through individual array elements. For instance, A = A * 2 will double the value of every element in the array A without you having to use the traditional FOR J=0, N do A[J] = A[J] * 2.
- Multidimensional arrays:

Arrays do not have to be 1-dimensional. They can hold whole tables or cubes of data. If an array has multiple dimensions, its elements are accessed by specifying the row and column (and depth if 3D) within the square brackets:print,A[3,4] threeDarray[3,1,6] = twoDarray[4,0] * 5 + X

- Creating Arrays in IDL:

Arrays can be created for every data type in IDL (integer, float, etc.). There are two ways to make an array for each data type. One of them will create an empty array i.e. every element will have its value set to 0 or null. The other will create a prenumbered array in which every element will have its value set to its index i.e. A[0]=0, A[1]=1, ..., A[20]=20.

Again, since the first element in an array has an index 0, if you create a 10-element array, its highest element is 9, so you can access X[0], X[1], ..., and X[9].Data Type Create Empty Array Create Numbered Array Integer X=INTARR(10) X=INDGEN(10) Long X=LONARR(10) X=LINDGEN(10) Float X=FLTARR(10) X=FINDGEN(10) Double X=DBLARR(10) X=DINDGEN(10) String X=STRARR(10) X=SINDGEN(10)

- Multidimensional Arrays can be created by putting (cols,rows) instead of just the number of elements. X=INTARR(10,5) would then create an array that would hold a table of 10 columns and 5 rows, or 50 total elements. The individual elements can be accessed by X[0,0],X[1,0],...,X[9,4] or they can be accessed by the 1-dimensional index X[0], X[1],...,X[49]. X[col,row] is usually the preferred way to access elements, but if you create a numbered array X=FINDGEN(10,5) it will use the 1-dimensional index to do the numbering (i.e. X[0,0]=0, X[1,0]=1,...,X[0,1]=10,...,X[9,4]=49.

A = [5, 3, 7, 9, 0, 1] B = [[3,2],[4,7],[6,3]]

Creates an array A of length 6 and a 2-dimensional array B with 2 columns and 3 rows. - Arrays and Maths

IDL is unique in that it is array based. That means that any arithmatic operation can be used on an entire array and not just individual elements.A = FINDGEN(10) A=[0,1,2,3,4,5,6,7,8,9] B = FINDGEN(10)*10+100 B=[100,110,120,130,140,150,160,170,180,190] A = A+2 every element in A is incremented by 2 so A=[2,3,...,11] B = B/20. every element in B is divided by 20. so B=[5,5.5,6,...,9.5] A = A*B every element in A is multiplied by the corresponding element in B so A=[0,110,240,...,1710] print,A > B takes the greater value of each element i.e.A[0] > B[0], A[1] > B[1],... Matrix Multiplication: a=[[1,2],[3,4]] b=[[10,5],[3,1]] print,a#b 25 40 6 10 print,b#a 16 7 42 19 print,a##b 16 7 42 19

- Array subscripts
- Extra dimensions:

IDL allows you to specify "extra" dimensions for an array as long as the extra dimensions are all zero. For example, if A = fltarr(10), then A[5] and A[5,0] would both access the sixth element of A. If B is a scalar (or ordinary variable), B=2 and you type print,B[0], IDL will treat it just as if you typed print,B and return the value 2. - Subscript Ranges:

- A range of subscripts can be specified by [i:j]. For instance, A[5:9] would return an array of the 6th through 10th elements of A. B[3:6,2] would return colums 4 through 7 for row 3 of B and B[2:4, 0:3] would return columns 3 through 5 for the first 4 rows of B.
- All elements are represented by *. B[2:4,*] would return columns 3 through 5 for all rows of B. A[*,2] would return all columns for row 3 of A.
- All elements from a given element to the last are represented by [i:*]. For instance if A = fltarr(20), then A[5:*] would return an array consisting of A[5] through A[19]. B[0,3:*] would return the first column for rows 4 and up of B.

- Arrays as subscripts:

Arrays can also be used to subscript other arrays. For example:A = [6,5,1,8,4,3] B = [0,2,4,1] C = A[B] print, C

Results in 6 1 4 5. The first element of C is 6 because A[B[0]] = A[0] = 6. The second element is 1 because A[B[1]] = A[2] = 1 and so on. The command A[[1,3],7:9] = 3 sets the following 6 elements of A to the value 3: A[1,7], A[3,7], A[1,8], A[3,8], A[1,9], and A[3,9].

- Extra dimensions:
- Array operations
- MAX: Return the maximum value in an array. If A=[2,4,7,1,3,-1,5] then print,MAX(A) will return 7. MAX(A[3:*]) though, would return 5.
- MIN: Similar to MAX, returns the minimum value in an array. MIN(A) would return -1. One option that can be set in either MAX or MIN is /NAN. In IDL, if a number is invalid (for instance the log of a negative number), it is represented by NaN or Not a Number. If I took B = alog10(A) then B[5] would be NaN since it is the log of -1. If I then took MIN(B), it would return NaN. If, however I specify MIN(B,/NAN) then all NaNs are treated as missing data and it would return 0 (log of 1).
- N_ELEMENTS: Returns the number of elements in an array. n_elements(A) = 7. If B = findgen(3,6) then n_elements(b) = 18.
- SIZE: Returns an array. If S = SIZE(A) then S = [1,7,4,7]. The first element of size is n, the number of dimensions of the array. The next n elements are the lengths of each dimension. The next to last element is the type of array it is (find SIZE in ? to see the codes for different datatypes. 4 means float), and the last element is the number of elements in the array (same as you get with N_ELEMENTS). So if B = findgen(3,6) then SIZE(B) = [2,3,6,4,18].
- SORT: Returns an array of subscripts that allow access to the elements of the array in ascending order. SORT(A) returns [5,3,0,4,1,6,2] because the element with index 5 is -1, the lowest value, then index 3 has value 1, ... A common use would be A[SORT(A)], which results in [-1,1,2,3,4,5,7].
- REVERSE: Returns the current array reversed. REVERSE(A) returns [5,-1,3,1,7,4,2] and REVERSE(A[SORT(A)]) returns [7,5,4,3,2,1,-1].
- TOTAL: Returns the sum of all elements of the array. TOTAL(A) returns 21.0000
- AVG: Returns the average of the elements in the array. AVG(A) returns 3.0000, and AVG(A[2:5]) returns 2.5000
- TRANSPOSE: Returns a transpose of the array. B=TRANSPOSE(A)
- ROTATE: Rotates the current array. B=ROTATE(A,n) where n is from 0 to 7 and defines how many degrees to rotate and whether the array should be transposed as well (see ROTATE in ? for which values of n do what).
- SHIFT: Shifts the elements of an array by a specified number, and wraps around the end. SHIFT(A,3) = [3,-1,5,2,4,7,1]. SHIFT(A,-1) = [4,7,1,3,-1,5,2].

- Bubble Sort

Many times, you'll want to write your own sort routine, based on your own criteria. One of the simplest sorting routines is the bubble sort. The bubble sort has a good efficiency, with time complexity of the order n^2. Quick sorts, heaps, and winner trees can sort with better time complexity, of order n*log(n), but are much more complicated to design. In its simplest version, say you have an array A of numbers (or Strings) that you want to sort from lowest to highest (or alphabetically):FOR j=0,n_elements(A)-2 do begin FOR l=j+1,n_elements(A)-1 do begin IF A[l] lt A[j] then begin temp=A[j] A[j]=A[l] A[l]=temp ENDIF ENDFOR ENDFOR

The first loop goes from the first element to the n-1 element. The second loop goes from the current position of the first loop and checks the rest of the array. If it finds any values less than that at the current position of the first loop, it swaps the two positions. Example:A = [3, 6, 0, 4] j=0, l=2: A[l]=0 < A[j]=3 so they are swapped A = [0, 6, 3, 4] j=1, l=2: A[l]=3 < A[j]=6 so they are swapped A = [0, 3, 6, 4] j=2, l=3: A[l]=4 < A[j]=6 so they are swapped A = [0, 3, 4, 6]

This would work the same way with strings for instance if you had A = ["Moss","Walsh","Drejer","Roberson"] since Drejer < Moss < Roberson < Walsh

Say you want to sort these 4 basketball players by their scoring averages and the basketball players are in an array names, while their averages are in an array points:FOR j=0,n_elements(points)-2 do begin FOR l=j+1,n_elements(points)-1 do begin IF points[l] gt points[j] then begin temp=points[j] points[j]=points[l] points[l]=temp temp=names[j] names[j]=names[l] names[l]=temp ENDIF ENDFOR ENDFOR

The names are now sorted by how many points per game they score, highest listed first (Roberson, Walsh, Moss, Drejer if anyone wants to know). - WHERE function

The WHERE function is one of the most powerful features of IDL. It allows you to sort, find, and manipulate data within arrays in numerous ways. The structure is B = WHERE(condition involving A) where A and B are arrays.- Finding where datapoints are 0 or nonzero

To find out the indices where array elements equal zero:B = WHERE(A EQ 0)

B is now an array containing the index number of all elements i of A where A[i] = 0. Similarly, to find where an array contains nonzero elements, type B = WHERE(A NE 0). - Finding maxima and minima

As mentioned earlier, maxima and minima of an array A are given by MAX(A) and MIN(A). Therefore finding the index that corresponds to the maxima or minima of an array is given by:B = WHERE(A EQ MAX(A)) B = WHERE(A EQ MIN(A))

- Finding data in specific ranges

If you're looking for the indices of elements whose value is in a specific range, you could use the following:B = WHERE(A GT 5 AND A LE 10)

- Finding the values of the data

The above line of code give you the index numbers of elements in A that are between 5 and 10. If you want the actual values of those elements:B = A[WHERE(A GT 5 AND A LE 10)]

- When WHERE returns -1

If the condition is never true in the array (for instance if no element of A above is between 5 and 10), then WHERE returns the scalar -1 instead of the normal array. Thus it is usually useful to check whether any elements in the array met the specified condition:B = WHERE(A GT 5 AND A LE 10) If B[0] NE -1 THEN BEGIN B=A[B] print,"These values are between 5 and 10",B ENDIF

If B=-1, B[0] will also return -1 because IDL will ignore the [0]. If B is an array of indices, then B[0], the first index, will not be -1. When you are looking for a max or min, or any other time you're only looking for one particular index number, it may be useful to set B=B[0]:B = WHERE(A EQ MAX(A)) B = B[0]

Now B is a scalar, so you can just use B instead of B[0] throughout the rest of the program. - Finding values in a corresponding array:

Going back to the example of the names of Gator b-ball players in an array called names and their scoring averages in an array called points, what if you wanted to print out the names of all players that are averaging over 10 points per game:X = WHERE(points ge 10) IF X[0] NE -1 THEN print,names[X]

- Using selected index ranges:

If you only want to look at a selected range within an array, you can subscript the array within the conditional of the WHERE command:B = WHERE(A[15:20] gt 5)

It is important to remember B will contain the indices of A[15:20], a 6 element array, that are greater than 5. It will NOT contain the indices of A that are greater than 5. If A[15:20]=[3,6,5,0,9,7] then B=WHERE(A[15:20] gt 5) will result in B=[1,4,5]. If you want the indices of A you then need to add 15 since A[15] is the 0th element of A[15:20]. So B=WHERE(A[15:20] gt 5)+15 will result in B=[16,19,20], which are the three elements of A that are within the selected range and greater than 5. - Additional example:

I was just asked a question that ends up using the WHERE function, so I'll provide this as an additional example of how versatile the function is. Say you have an array and you want to find out the index of the datapoint closest to 1.2:B = WHERE(ABS(X-1.2) EQ MIN(ABS(X-1.2)))

- Finding where datapoints are 0 or nonzero

Notes: Before writing this program, copy the file /astro/data/homer0/warner/MBH/IRAF/M7.fits to your local directory. To read the .fits file, use the following line:

fits_read,'M7.fits',fluxThe array flux will be a 13992 element array containing the flux values for the spectra of a quasar. You have to generate your own x-axis wavelength scale when reading in .fits files. The information to do this is located in the header (see next week's File I/O). For this example, you of course need another 13992 element array. The first wavelength is 500 angstroms and there is an interval of 0.5 angstroms between every point.