Notes prepared by L. Nicastro (INAF-IASF)
for the Astronomy doctorate course.

Bologna 19-23 May 2008


Operative systems: Linux and Windows (little)
Contacting me: nicastro at iasfbo . inaf . it
Last updated: 24/06/2009

Some resources you might need:

- Personal (partial) library (.tar.gz)
- "Astro-lib" Apr-2008 (.tar.gz)
- imdisp - Version 1.47 (05/06/2002)
- Set-up file: idl_setup.csh (tcsh)
- Set-up file: idl_setup.bash (bash)
- Startup file
- Demo programs (with data files)
- More demo data

A brief introduction
 IDL: what is it?
 Costs and installation
 Official courses

Manuals/Tutorials/Libraries
 On-line documentation
 Books
 User's programs (on the Web)
 Linux specific notes
 (IDL) System variables
 Some notes

To start ...
 Operative system check
 Graphics device check
 Operators
 Dimension degeneracy

Some simple graphics examples
 Preserving the X / Y ratio in PS files
 Circle?
 Defining a new plot symbol
 Let's make a square plot area
 Manual positioning
 More on USERSYM and plot symbols
 Multiple plots per page
 Distinct Y axes for two data sets
 Coordinate types: Data, Normalized, Device

Colors, Fonts and Images
 Colors (a fight, sometimes!)
 A useful (and standard) 19 colors table
 Background color for the PS device
 Fonts
 Some image visualization types
 IMDISP: a general purpose (user written) image display program
 Write/read an image in/from an ASCII file (not suggested)
 Write/read a GIF image
 Getting information about variables - SIZE function
 Using EXECUTE to build commands on the fly
 Logging commands into a file
 Files I/O
 Changing (work) directory
 Reading binary / ASCII files
 Reading a columns formatted ASCII file
 Plotting 'bins' (and their errors)
 X axis errors plotting
 Displaying an ASCII file and arrays
 Read/write FITS files
 Some simple procedures
 Interacting with the operative system


See also the practice day notes: day 1 and day 2.


A brief introduction
IDL: what is it?

IDL, the Interactive Data Language,
is the ideal software for data analysis,
visualization, and cross-platform
application development. IDL combines
all of the tools you need for any type
of project - from "quick-look,"
interactive analysis and display to
large-scale commercial programming
projects. All in an easy-to-use, fully
extensible environment.

Current IDL version (October 2007): 7.0. Web site: http://www.ittvis.com/idl/

Costs and installation:

Ask ITT for an offer. There are "personal" and "network" licenses. Suggested: "campus" or "student" license. Cost for profit companies are much higher.

Linux:
Downloadable from the net. Without the license code IDL can be used in demo mode for 7 minutes.
The license code + shell scripts + instructions to install it, are sent via mail once the DVD is received.
The paper manuals are no longer delivered. They are sold separately.

Windows:
Same as for Linux. In the old times, a 'HASP' key was supplied for the 'personal' license. Not sure it is still used.
Installation is very simple and makes use of a GUI (Windows-like).

Generally user's can contact the national representative office easily by phone or e-mail and receive an answer tipycally within 1 day.
ITT also offers specific software packages based on IDL, e.g. ENVI, IAS, Noesys, FLASHH, ION, 'IDL Analyst'.

IDL Virtual Machine:
It's a new facility offered since V. 6.0. It's a free tool which allows software developers to distribute compiled IDL code applets, or entire applications to colleagues and customers without additional licensing requirements or fees.

Official courses:

IDL course at various levels are available every year and last from 2 to 5 days. Costs are of the order of 1000 Euro.
For information check the Web site (free webinar are available) and/or contact ITT Italia.


Manuals/Tutorials/Libraries:
The main resource is the "IDL Online Help" which runs in the web browser. It is a major improvement introduced in version 6.x and makes its use really easy and "helpful". Just run idlhelp or type ? at the IDL> prompt.
The ITT pages www.ittvis.com/ProductServices/IDL/ProductDocumentation.aspx and www.ittvis.com/ProductServices/IDL/IDLTutorials.aspx have several Guides which are also available here.

The IDL version is (typically) not the latest. Try typing "IDL training" or "IDL tutorial" or similar in Google...

Tutorials:

http://www.us-vo.org/summer-school/2006/proceedings/presentations/idl_tutorial.html
US-VO Tutorial (summer school 2006)
http://www.ncnr.nist.gov/staff/dimeo/IDL_Training.html
Rob Dimeo's training courses at NCNR. See course I (PDF) and course 2 (PDF) (programs and data: course I (.tar.gz) and course 2 (.tar.gz))
http://www.astro.virginia.edu/class/oconnell/astr511/IDLguide.html
R. W. O'Connell - A Guide to IDL for Astronomers
http://www.iac.es/sieinvens/SINFIN/CursoIDL/cidl.php
IAC-SIE course by Reinhold Kroll
http://www.iac.es/sieinvens/SINFIN/CursoIDL/idlpp1.php
IAC-SIE: First Steps in IDL by Alexandre Vazdekis
http://www.eg.bucknell.edu/physics/ASTR201/IDLTutorial/
Bucknell University: Introduction to IDL and IDLAstro

On-line documentation:

General:
http://www.metvis.com.au/idl/
IDL resources @ METVIS Services. A fairly complete list of web resources.
http://www.dfanning.com/
Coyote's Guide to IDL Programming. A growing list of suggestions and example progams (see below).

ITT IDL manuals in PDF format (with data):
http://www.ittvis.com/ProductServices/IDL/ProductDocumentation.aspx
http://www.ittvis.com/ProductServices/IDL/IDLTutorials.aspx

Direct Graphics in IDL:
http://www.sljus.lu.se/stm/IDL/Surf_Tips/
Struan Gray's excellent tutorial on Extending IDL's Surface Plotting Routines.

Selected topics:
ftp://fermi.jhuapl.edu/s1r/idl/s1rlib/local_idl.html
Tutorials on some of the JHU/APL/S1R IDL Library routines.

Documentation and tips on IDL programming are also available at the ITT site:
http://www.ittvis.com/codebank/index.asp
and the IDL Astronomy User's Library:
http://idlastro.gsfc.nasa.gov/homepage.html

Old IDL FAQ:
http://www.astro.virginia.edu/class/oconnell/astr511/IDLresources/idl-faq-ivsoft-v4.html

Old IDL newsgroup:
comp.lang.idl-pvwave
 
Hosted by Google:
http://groups.google.com/group/comp.lang.idl-pvwave/topics
Mirrored at:
http://www.fotovallescrivia.it/public/news/comp.lang.idl-pvwave/comp.lang.idl-pvwave0.htm

Books:

David Fanning - "IDL Programming Techniques". Available at:
http://www.dfanning.com/documents/books.html (it was $65)

Ronn L. Kling: "Application Development with IDL, Combining Analytical
Methods with Widget Programming". Available at:
http://www.rlkling.com/html/textbook.htm (it was $55)

ITT's training manuals: see ITT web site.

User's libraries and programs (on the Web):

IDL Astronomy User's Library:
http://idlastro.gsfc.nasa.gov/homepage.html
- A reference site for all 'generic' Astronomical procedures
- Procedures documentation
- IDL-Databases of astronomical catalogues (small) ("tar" compressed files)
- NEWS

GLAST IDL Resources
http://glastweb.pg.infn.it/idl.htm

Eric Deutsch IDL Libraries Browser
http://www.astro.washington.edu/deutsch/idl/htmlhelp/index.html
http://www.astro.washington.edu/deutsch/idl/htmlhelp/slibrary28.html
ESRG UCSB Library

Craig B. Markwardt IDL Library
http://cow.physics.wisc.edu/~craigm/idl/

Soho library:
http://sohowww.nascom.nasa.gov/solarsoft/gen/idl/
- Various libraries, including WCS (World Coordinate System)
http://www.mps.mpg.de/projects/soho/sumer/text/cookbook.html
SUMER Data Cookbook

IDL Libraries at IAAT, Astronomy
http://astro.uni-tuebingen.de/software/idl/
---

REDUCE IDL Routines Depository
http://www.astro.uu.se/~piskunov/RESEARCH/REDUCE/
CCD Spectroscopy Data Reduction by N.E. Piskunov and J.A. Valenti

Extended IDL Help
http://astro.berkeley.edu/~marc/idlshare/general/html/


Linux specific notes:

Initialization file "idl_setup":
it can be found in the directory: /usr/local/itt/idl/bin
"idl_setup" or "idl_setup.csh" for the csh/tcsh shell and "idl_setup.bash" for bash. Even if on some systems you already have the IDL commands defined, I suggest to copy this file into your $HOME directory and edit it for personalizations.
To execute it automatically for every terminal:

csh/tcsh: at the end of the ".cshrc" (or .login) add
 source ~/idl_setup.csh
bash: alla fine del proprio ".bashrc" (or .bash_profile) add
 . ~/idl_setup.bash

IDL also uses X11 resources (read from the file ~/.Xdefaults or $XAPPLRESDIR/Idl).

idl.colors: number of color IDL can use (useful for PseudoColor devices).
idl.gr_depth: Depth, in bits, of the graphics device in use.
idl.retain: default parameter retain (Backing Store selection → graphics covered by other windows): 0= none, 1= by server, 2= by IDL.
idl.gr_visual: type of visual device to use: StaticGray, GrayScale, StaticColor, PseudoColor, TrueColor, DirectColor.
And so on. Check the help pages!

For example:

 Idl*fontlist: screen16
 Idl.colors: -16
 Idl.retain: 2
 Idl.gr_visual: PseudoColor

But the same (and more) parameters can be defined using a 'startup' file using IDL instructions. For example:

 print, 'Setting display attributes...'
 device, deco=0, retain=2, true=24 ; 24 bit true color display with backing store

  window, /free, /pixmap           ; Create window to allocate colors
  plot, [0]                        ; Might not be needed, but won't hurt
  wdelete, !d.window               ; Delete the window
  device, set_character_size=[6,9] ; Set the vector font size
  print, 'Number of colors allocated is ', !d.n_colors

Setting the keyword DECOMPOSED=1 means IDL must interpret the color indices as composed by 3 values (8-bits each) corresponding to the red, green and blue intensities (from the less to the most significative byte). This is the default for a display using TrueColor and DirectColor graphics (for example Windows and any machine equipped with graphics card with 16 million colors).
Setting this keyword to 0 means that IDL must interpret the color index (atually the less significant 8-bits) as the index of the PseudoColor color table. Consequently, this index is in the range 0 - 255. This "was" the default for UNIX machines (not Linux!) using a "standard" display and allowed users (like me) to write "standard" code which run on any machine. Nowdays, TrueColor displays are the standard, so what runs on Linux should run on Windows at the same way (graphically speaking).
The keyword PSEUDO is not allowed on Windows.

If you prefer, can use idlde, which launches a GUI 'Workbench'. In your home directory you'll have a subdir .idl/itt/idlworkbench-config-idl70 containing more dirs with the application preferences etc.
Preferences can be changed either manually or using the Workbench itself.



(IDL) System variables:

1- Costants
!PI, !DPI, !RADEG, !DTOR, !MAP, !VALUES

2- For the graphics
!D, !X, !Y, !Z, !P, !ORDER

3- Error Handling and Informative messages
!ERR, !ERR_STRING, !SYSERR_STRING, ...

4- IDL environment
!PATH, !PROMPT, !VERSION, ...

To add system variables:

IDL> DEFSYSV, 'Var_Name', Value [, /Read_only] [, EXISTS=i]
IDL> DEFSYSV, '!TEXTOUT', 1

Some notes:

1- IDL is not case sensitive (but, under Linux, the file names which store the IDL routines are case sensitive!).

2- IDL "procedures" are of type PROgram and FUNCTION (similarly to Fortran SUBROUTINE and FUNCTION) and both can have "comma separated" parameters and keywords. Parameters can be passed by reference or value, keywords can be passed by name or value using the format:
KEYWORD_NAME=name (valore) or simply /KEYWORD_NAME which translates into KEYWORD_NAME=1 (i.e. TRUE). Functions have their parameters and keywords passed in brackets. For example:

PRO: PLOT, FINDGEN(20), FINDGEN(20)^2, XSTYLE=1, YSTYLE=1, THICK=2
FUNCTION: cv = CONVERT_COORD( [0,1],[0,1],/NORM,/TO_DEV )
A series of commands make a "script" which IDL calls a MAIN. Script syntax is slightly (but significantly) different from that used in procedures.

3- Arrays are defined by comma separated values in square brackets:
(es. 1-d: a = [3,6,12,24,64], 2-d: b = [[2,4,6,8,10],[8,12,24,36,72]])
and the indices of the elements go from 0 to number_of elements - 1.
To extract an adjacent section one can use ":". For exasmple to transfer into the variable c the first 3 elements of a:
c = a[0:2] and to transfer those from the third to the last:
c = a[2:*]. To extract random elements one can use an array of integer values (chosen elements). For example:
i = [0,2,4] & c = a[i] will select first, third and fifth element of the array a.
In a two dimnensional array, the first index refers to the column, the second to the row (in Fortran it's the reverse).

4- Costant numbers containing the "." or "E" (es. 13., 2e3) are assumed to be of type FLOAT (4 bytes); those containing a "D" of type DOUBLE (8 bytes); those with an "L" at the end of type LONG INTEGER (4 bytes) o simply LONG; those ending with a "B" are of type BYTE; those with none of these letters are of type INTEGER (2 bytes).
Moreover: UL → UNSIGNED LONG, LL → 64-bit LONG, ULL → UNSIGNED 64-bit LONG.
To define an exadecimal value, add an "X" at the end of the string constant. Example: '2E'XB, 'FF'XL, ecc.
Similarly use "O" for octal constans. Please refer to the on-line help → Constants.
PAY ATTENTION TO THE THE DEFINITION OF INTEGER CONSTANTS WHICH COULD TRESPASS THE 32768 LIMIT (especially in the FOR loops!). Example:

 a = 7 & a = a+32760 & print, a
   32767
 a = 7 & a = a+32761 & print, a
  -32768

It would have been OK if I used "a = 7L"
If not sure, always add "L" at the and of integer values.

5- Keyword names can be truncated to the letter which makes it "unique".
For example if a command or procedure has as possible keywords CHARTHICK and CHARSIZE, then those can be truncated to CHART and CHARS, respectively.

6- Blank spaces (one or more) in expressions and statements containing operator, "=", ",", "&", etc. are optional;
an instruction line can be splitted in several lines adding a "$" at the end of each line (not the last one, of course). Example:

 PLOT, FINDGEN(20), FINDGEN(20)^2, XSTYLE=1, YSTYLE=1, THICK=2, $
 XRANGE=[-2,22], TITLE='Demo plot'

7- Several instruction lines can be concatenated on the same line using an "&" as separator. Example:

 a = fltarr(12) & b = dblarr(4,7) 

8- Comment lines (or part of it) start with a semicoln ";". Example:

 PLOT, alog(x),alog(y), xtype=1, ytype=1 ; logarithmic plot X vs. Y

9- The keyword FORMAT, used to have formatted I/O, uses the same notation as Fortran or C. Example:

 PRINT, [1,2,3,4], FORMAT='(4(I2,2X))'
 1   2   3   4

10- Alphanumeric strings are concatenated using a "+" sign. Example:

 a = "Example"  &  b = 'of strings'  &  c = 'concatenation.'
 ss = a +' '+ b +' '+ c  &  print, ss 
 Example of strings concatenation.

11- Plotting coordinates can be given using the following types:

 DATA   (defined by the data values)
 DEVICE (defined as pixel coordinates of the active device)
 NORMAL (defined in the fixed interval [0, 1] for all the axes)
Examples:
 PLOT, [0,10], [0,10], /data       ; default
 PLOTS, [.5,1], [.5,1], /norm      ; normalized
 PLOTS, [100,200], [100,200], /dev ; device

12- For the on-line help, "idlhelp" or, at the IDL> prompt:

 ? <Enter>
or
 ? item <Enter>

From now on, IDL intrinsic commands/instructions/PRO/FUNCTIONS will be reported in CAPITAL LETTERS whereas "external" (personal, etc.) programs will be reported in lower-case letters. Variable names will be lower-case too.


To start ...:
Run idl or idlde (the latter is the Windows default).

Operative system check:

IDL> HELP, !VERSION, /STR
** Structure !VERSION, 8 tags, length=104, data length=100:
   ARCH            STRING    'x86_64'
   OS              STRING    'linux'
   OS_FAMILY       STRING    'unix'
   OS_NAME         STRING    'linux'
   RELEASE         STRING    '7.0'
   BUILD_DATE      STRING    'Oct 25 2007'
   MEMORY_BITS     INT             64
   FILE_OFFSET_BITS
                   INT             64

In a program use the code:

  CASE !VERSION.OS_FAMILY OF
    'MacOS':...

    'unix' :...

    'Windows' :...
  ELSE :
  ENDCASE

Graphics device check:

IDL> HELP, /DEV
Available Graphics Devices: CGM HP LJ NULL PCL PRINTER PS REGIS TEK X Z
Current graphics device: X
    Server: X11.0, The XFree86 Project, Inc, Release 40300000
    Display Depth, Size: 24 bits, (1400,1050)
    Visual Class: TrueColor (4)
    Bits Per RGB: 8 (8/8/8)
    Physical Color Map Entries (Emulated / Actual): 256 / 256
    Colormap: Private, 16777216 colors.  Translation table: Enabled
    Graphics pixels: Decomposed,        Dither Method: Ordered
    Write Mask: 16777215 (decimal) ffffff (hex)
    Graphics Function: 3 (copy)
    Current Font: <default>,    Current TrueType Font: <default>
    Default Backing Store: Req from Server.
    Window Status: ---------------------
    id  typ(    x,  y,   backing store)    id  typ(   x,   y,   backing store)
     0: Win( 700, 525, Req from Server)

Operators:

IDL> a = INDGEN(10) ; array of integers 0-9

IDL> PRINT, a
       0       1       2       3       4       5       6       7       8       9

IDL> PRINT, 10 - a
      10       9       8       7       6       5       4       3       2       1

IDL> b = a < (10-a) ; the operator "<"

IDL> PRINT, b ; let's see the result...
       0       1       2       3       4       5       4       3       2       1

IDL> v = 12

IDL> v = v > 1 < 10 ; operators "<" and ">"

IDL> PRINT, v ; the result...
      10
IDL> b = a > (10-a) ; l'operatore ">"

IDL> PRINT, b ; the result...
      10       9       8       7       6       5       6       7       8       9

Logical operators are like in Fortran (but without "."):

LE GE GT LT NOT AND OR NOR
IDL> i = WHERE(b gt 7) ; the WHERE function returns the indices of its
                       ; array elements which satisfy the expression argument

IDL> HELP, i
I               LONG      = Array[5]

IDL> PRINT, i ; the indices of "b" satisfying the expression
           0           1           2           8           9

Let's substitute these elements with the average of the values >= 7 (which is 5)

IDL> b[i] = TOTAL(WHERE(b le 7, n))/n ; TOTAL performs the sum of its argument
; and the "n" parameter in the WHERE returns the number of elements in "b"
; which are >= 7
IDL> PRINT, b
       5       5       5       7       6       5       6       7       5       5

Multi-dim arrays multiplication:

IDL> array1 = [ [1, 2, 1], [2, -1, 2] ] ; array with 3 columns and 2 rows
IDL> array2 = [ [1, 3], [0, 1], [1, 1] ] ; array with 2 columns and 3 rows
IDL> PRINT, array1#array2 ; matrix multiplication (cols. x rows)
           7          -1           7
           2          -1           2
           3           1           3
IDL> a = array1##array2 ; matrix multiplication (rows x cols.)
IDL> HELP, a
A               LONG      = Array[2, 2]

Array expansion:

IDL> a = [ a, [[8,9],[10,11]] ] ; expand the array adding 2 extra columns
IDL> HELP, a
A               LONG      = Array[4, 2]
IDL> PRINT, a
           2           6           8           9
           4           7          10          11

Selecting columns or rows:

IDL> PRINT, a[*,0]  ; first row
           2           6           8           9
IDL> PRINT, a[1,*]  ; second column
           6
           7

Dimension degeneracy:

To remove an initial "single-element" dimension (refered as "degeneracy") the intrinsic REFORM function can be used:

IDL> ar1 = a[1,*] ; assign the second column of "a" to "ar1" 
IDL> HELP, ar1    ; note how we get a 2-d array having 1 column 
AR1             LONG      = Array[1, 2]
IDL> ar2 = REFORM(ar1)
IDL> HELP, ar2
AR2             LONG      = Array[2]

NOTE: to allow multiple lines cut-and-paste, from here to follow the prompt IDL> will be omitted.

Generally we assume that the commands in the following examples are given in the same order as reported for consistency. This within sections delimited by the horizontal lines.

To view the help of the routines for which the code exists on the IDL path (!PATH), one can use DOC_LIBRARY. For examle to see the help on DOC_LIBRARY itself:

 DOC_LIBRARY, 'doc_library'

----- Documentation for /usr/local/itt/idl/lib/doc_library.pro -----

 NAME:
        DOC_LIBRARY

 PURPOSE:
        Extract the documentation template of one or more IDL modules
        (procedures or functions).  This command provides a standard interface
        to the operating-system specific DL_DOS, DL_UNIX, and
        DL_VMS procedures.
...
- Note that on Linux the type of letters used (CAPITAL or not) matters as the routine name identifies the file name in your file system.
- Note that the extension ".pro" must be omitted (and the final ' can be omitted). Moreover if the file contains more routines with their header help section (we'll see later that the header comment starts conventionally with ;+ and ends with ;-), ONLY the first one is shown! Again, under Linux it is important to pay attention to UPPER and lower case letters.
Using always lower case letters in file names is adviceable. Again, for the system routines, the best way to get help is using the interactive web interface:

 From the Linux prompt: idlhelp
 From the IDL prompt: ?

Examples of help on procedures that can be found in the IDL_PATH / !PATH system variable (Linux / IDL):

DOC_LIBRARY, 'nxyreadf

DOC_LIBRARY, 'mpltw'

DOC_LIBRARY, 'pposn'

DOC_LIBRARY, 'sqplset'

DOC_LIBRARY, 'aitoff_grid2'

DOC_LIBRARY, 'lmfit' ; IDL routine with source code

...

Some simple graphics examples

Preserving the X / Y ratio in PS files:

 WINDOW, XSIZE=500, YSIZE=500 ; square graphics window

 PLOT, (INDGEN(21)-10)^2      ; plot a parabola using 21 points

 curdev = !D.NAME             ; save current graphics device (def. "X" or "WIN")

 SET_PLOT, 'PS'               ; switch to the PS device. By default open the file "idl.ps"

 DEVICE, XSIZE=6, YSIZE=6, /INCHES ; square window using inches instead of cm

 PLOT, (INDGEN(21)-10)^2       ; plot a parabola (X values are implicit)

 DEVICE, /CLOSE                ; close the file

 SET_PLOT, curdev              ; restore the original graphics device

... have a look to idl.ps.

Circle?
You can plot it in several ways. Here we use the external procedure "tvcircle".

 tvcircle, 5, 10, 50, /DATA ; by default values are in pixel,
                            ; here we chose to use DATA coordinats,
                            ; center at (10,50) and radius 5.
                            ; NORMALized coordinates are not allowed

 tvcircle, 100, 200, 200 ; Coord. pixel: center at (200,200) and radius 100

... to have a PS file see the previous example.

 PRINT, !D.X_CH_SIZE, !D.Y_CH_SIZE ; default character size (pixel)
      6       9

 PRINT, !X.MARGIN,!Y.MARGIN ; distance of the plot axes from the window borders
     10.0000     3.00000
      4.00000    2.00000

Therefore we do not have a square plotting area by default. Though we can have it (see below):

 pp = polygon(100) ; define un polygon with 100 vertexes using "polygon"
 HELP, pp
PP           FLOAT = Array[2, 101]

 PLOT, pp[0,*],pp[1,*]
 PLOT, pp[0,*],pp[1,*], THICK=2, LINESTYLE=3

... to have a PS file see the previous example.

Values for the Keyword LINESTYLE
Index Line style
0 Solid
1 Dotted (...)
2 Dashed (---)
3 Dash Dot (-.)
4 Dash Dot Dot (-...)
5 Long Dashes (__)

Defining a new plot symbol (MAX 49 vertexes!):

 pp = polygon(48)      ; poligon with 48 vertexes

 USERSYM, pp, /FILL    ; define a new "filled" symbol

 PLOT, pp[0,*],pp[1,*], PSYM=-8, SYMS=2 ; plot vertexes of the poligon using
                                        ; the new symbol connecting them
                                        ; (using -8) with size 2x default

Let's make a square plot area using "sqplset":

 sqplset, /SET    ; reset !X.MARGIN and !Y.MARGIN for CHARSIZE=1 (def.)

 PLOT, pp[0,*],pp[1,*], PSYM=-8

 sqplset, 2, /SET ; reset !X.MARGIN and !Y.MARGIN for CHARSIZE=2

 PLOT, pp[0,*],pp[1,*], PSYM=-8, CHARS=2

... can get the same result without touching system variables:

 sqplset, 2, xm, ym ; no reset, but returns the values into xm and ym

 PLOT, pp[0,*],pp[1,*], PSYM=-8, CHARS=2, XMARGIN=xm,YMARGIN=ym

Manual positioning:

 PRINT, !P.POSITION
      0.00000      0.00000      0.00000      0.00000

 PRINT, !P.REGION
      0.00000      0.00000      0.00000      0.00000

 PLOT, pp[0,*],pp[1,*], PSYM=-8, CHARS=2, XTIT='X val', YTIT='Y val'

 !P.REGION = [.1,.1,.9,.9]

 PLOT, pp[0,*],pp[1,*], PSYM=-8, CHARS=2, XTIT='X val', YTIT='Y val'

 PLOTS, [.1,.1], [.1,.9], /NORM ; use normalized coordinates (0 - 1)

 PLOTS, [.1,.9], [.1,.1], /NORM

 PLOTS, [.9,.9], [.1,.9], /NORM

 PLOTS, [.1,.9], [.9,.9], /NORM

Exercise: highlight a plot region using a single PLOTS command.

 !P.POSITION=[.1,.1,.9,.9]

 PLOT, pp[0,*],pp[1,*], PSYM=-8, CHARS=2, XTIT='X val', YTIT='Y val'

 PLOTS, [.1,.1], [.1,.9], /NORM, COLOR=0, LINE=2

 PLOTS, [.1,.9], [.1,.1], /NORM, COLOR=0, LINE=2

Restore defaults:

 !P.POSITION = 0 & !P.REGION = 0

A more appropriate positioning!

 PLOT, pp[0,*],pp[1,*], PSYM=-8, CHARS=2, POS=[.4,.4,.9,.9], $
       TIT='Plot region=[.4,.4,.9,.9]'

More on USERSYM and plot symbols:

 USERSYM, pp ; empty poligon

 PLOT, pp[0,*],pp[1,*], PSYM=-8, SYMS=2 ; connected plot with symbol size 2x

 USERSYM, pp, THICK=3 ; symbol thickness = 3

 PLOT, pp[0,*],pp[1,*], PSYM=-8, SYMS=2

Values for the Keyword PSYM
PSYM value Plot symbol
1 Plus sign (+)
2 Asterisk (*)
3 Period (.)
4 Diamond
5 Triangle
6 Square
7 X
8 User-defined. See USERSYM procedure.
9 Undefined
10 Histogram mode. Horizontal and vertical lines connect the plotted points, as opposed to the normal method of connecting points with straight lines.

Negative values of PSYM produce connected points with a line whose style is defined by the LINESTYLE keyword. For example a value of -5 produces a plot with data points marked by triangles and connected by a solid line (assuming no LINESTYLE is used).

Multiple plots per page:

 PRINT, !P.MULTI

 !P.MULTI = [0,2,3,0,0]  ; 2x3 plots (X x Y = cols x rows) left-to-right
                         ; the last two values can be omitted: [0,2,3]

 !P.MULTI = mpltw('2x3') ; use the FUNCTION "mpltw"

 FOR i = 1,6 DO PLOT, pp[0,*],pp[1,*], PSYM=-i

To have plots top-to-down:

 !P.MULTI = [0,2,3,0,1]       ; last element must be 1 to select "columns" direction

 !P.MULTI = mpltw('2x3',/COL) ; use the FUNCTION "mpltw" with the keyword COLUMN

 FOR i = 1,6 DO PLOT, pp[0,*],pp[1,*], PSYM=-i

Side-by-side plots (tick marks management) using "pposn":

 pos=pposn(2,3) ; request positions for a 2x3 grid
                ; (X x Y = columns x rows)

 PRINT, pos     ; values are in normalized coordinates (0 - 1)
    0.120000     0.540000     0.120000     0.540000     0.120000     0.540000
    0.673333     0.673333     0.386667     0.386667     0.100000     0.100000
    0.540000     0.960000     0.540000     0.960000     0.540000     0.960000
    0.960000     0.960000     0.673333     0.673333     0.386667     0.386667 

 a=HISTOGRAM(RANDOMN(seed,1000),BINS=.1) ; create the histogram of a random variable
                                         ; with normal distribution (Gauss).
                                         ; Have a look to the on-line help (or manual)
                                         ; for HISTOGRAM and RANDOMN

 PLOT, a, POS=pos[1,*]

 PLOT, a, POS=pos[1,*], XTICKN=[' ',' ',' ',' ']      ; empty label names (= " ")
 PLOT, a, POS=pos[1,*], XTICKS=2,XTICKN=[' ',' ',' '] ; 2 ticks along X (3 lab.)

 tn=[' ',' ',' '] ; let's use a variable

 PLOT, a, POS=pos[1,*], XTICKS=2,XTICKN=tn,XSTY=1 ; exact range along X

 PLOT, a, POS=pos[1,*], XTICKS=2,XTICKN=tn,XSTY=1,XRANGE=[0,60],XMINOR=4 ; new range

 tn=[' ',' ',' ',' ',' ',' ']
 ; Can also use the intrinsic function REPLICATE:
 tn=REPLICATE(' ',6)

 HELP, tn
TN              STRING    = Array[6]

 ERASE ; clean screen and plot the 6 graphs
 FOR i=0,5 DO PLOT, a, POS=pos[i,*], XTICKS=2,XTICKN=tn,XSTY=1, $
     XRANGE=[0,60],XMINOR=4,YTICKS=4,YTICKN=tn,YSTY=1,YMINOR=4,/NOERA

Exercise: have a look to "legend.pro" in the idl_astronomy library.

Distinct Y axes for two data sets:

To have two different Y axes for two different data sets (to be plot in the same plotting area) the intrinsic routine AXIS can be used:

 x = INDGEN(10)
 y1 = x
 y2 = x^2
 PLOT, x, y1, XSTYLE=1, YSTYLE=9, YTITLE='Y1', $ ; first plot without the right axis
       XTITLE='X'
 PLOT, x, y2, XSTYLE=5, YSTYLE=5, /NOERA         ; second plot without axes
 AXIS, YAXIS=1, YTITLE='Y2'                      ; right (Y) axis with label

Coordinate types: Data, Normal(ized), Device:

 c=loadct19() ; redefine first 19 colors (see below)

 PLOT, FINDGEN(10)^2

 PLOTS, 5,25,PSYM=1,COL=c[2]      ; def.=DATA

 XYOUTS, 5,25, 'Data Coords=5,25' ; write a string at coords (5,25)

 PLOTS, .5,.5,PSYM=1,COL=c[2],/NORM

 XYOUTS, .5,.5, 'Normal Coords=0.5,0.5',/NORM

 PLOTS, 150,250,PSYM=1,COL=c[2],/DEV

 XYOUTS, 150,250, 'Device Coords=150,250',/DEV

To convert from one type of coordinates to another we can use the intrinsic function CONVERT_COORD (by default it converts from DATA):

 cnorm = CONVERT_COORD([0,10],[0,100],/TO_NORM) ; convert to NORMAL coords
                                                ; the range of the above plot

 HELP, cnorm ; 3x2 matrix containing the (x, y, z) components
CNORM      FLOAT = Array[3, 2]

 PRINT, cnorm
       0.0937550    0.0937550      0.00000
       0.971880     0.953130      0.00000

 cdev = CONVERT_COORD([0,10],[0,100],/TO_DEV) ; convert to DEVICE coords

 PRINT, cdev ; what you see here is the result for a 400x300 pix. plotting window
       60.0020      36.0015     0.000000
       382.002      282.001     0.000000
 
 PRINT, cdev ; here is the result for a 640x512 pix. window
       60.0032      48.0026      0.00000
       622.003      488.003      0.00000


Colors, Fonts and Images

Colors (a fight? Sometimes.):

NOTE: graphics device "visual class", type and number of colors, once initialized, cannot be changed unless you restart IDL.

16-bit or 24-bit display with TrueColor and DirectColor color tables (eg. PCs):

 DEVICE, DECOMPOSED=0 ; interpret color index as "table" index
 LOADCT, 5            ; load STD GAMMA-II table. Can also use XLOADCT

 image = CONGRID(DIST(200), !D.X_Size, !D.Y_Size) ; use current window sizes

 TV, image            ; ... if nothing happens then try repeating the command

 LOADCT, 1
 TV, image

 ; To have information about the screen dimension and resolution
 dims = GET_SCREEN_SIZE(RESOLUTION=res)

 PRINT, dims, res
      1400.00      1050.00
     0.033857143     0.033904762

A useful (and standard) 19 colors table:

 c=loadct19() ; a personal FUNCTION to redefine the first 19 colors.
              ; It returns the indices associated to the table in "c".

 ; Empty frame without tick marks
 PLOT, [0], XRANGE=[0,10],YRANGE=[-1,20],XSTY=1,YSTY=1,TICKL=0.

 FOR i=0,18 DO PLOTS, [1,9], [i,i], THICK=4, COLOR=c[i] ; plot color bars

 c=loadct19(colors)

 PRINT, colors, FORMAT='(a)'
    White
    White
    Red
    Green
    Blue
    Cyan
    Magenta
    Yellow
    Orange
    Green+Yellow
    Green+Cyan
    Blue+Cyan
    Blue+Magenta
    Red+Magenta
    DarkGray
    LightGray
    DarkRed
    DarkGreen
    DarkBlue

 PLOT, [0], XRANGE=[0,10],YRANGE=[0,18],XSTY=4,YSTY=9,YTICKS=18, $
       CHARS=1.5, YTIT='!6Color index!3' ; plot the Y axis with no data

 FOR i=0,18 DO PLOTS, [1,9], [i,i], THICK=3, COLOR=c[i]

Demo program: plot 30 colored triangles:

coltria30

To change/edit the color table interactively:

xloadct
xpalette

Exercise: plot a grid 6x3 of colored "squares" using color indices 1-18 (and pposn).

Background color for the PS device

The system variable is !P.BACKGROUND (keyword for the PLOT and other programs is BACKGROUND) and it is = 255 for the PS device. For this device independently from the color assigned to the the index 255 the result is always a white background. To obtain any other desired color do as follows (we assume the variable c with the color indices has been defined):

 SET_PLOT, 'ps'

 DEVICE, /COLOR

 POLYFILL, [1,1,0,0,1], [1,0,0,1,1], /NORM, COLOR=c[12]
 
 PLOT, [0], XRANGE=[0,10],YRANGE=[-1,18],XSTY=9,YSTY=9,YTICKS=19, $
       XTICKS=10, /NOERA

 FOR j=1,8 DO FOR i=0,18 DO PLOTS, j, i, PSYM=j, THICK=3, COLOR=c[i]

Fonts:

Let's start having a look to vector fonts (Hershey) and "embedded" formatting commands.

Using the system variable: !P.FONT = -1Hershey (= 0Hardware)
(the corresponding keyword for PLOT, XYOUTS, etc. is FONT).
This is the default and is whta we have been using so far.
...

Device and TruType fonts:

 DEVICE, GET_FONTNAMES=names, FONT='*' ; available hardware fonts (for current device)
 HELP, names
NAMES           STRING    = Array[1483]

 DEVICE, GET_FONTNAMES=names,FONT='*fixed*' ; avalable "fixed" fonts
 PRINT, names
...

 DEVICE, FONT='-misc-fixed-medium-r-normal--20-140-100-100-c-100-iso8859-1'
 XYOUTS, .5, .6, "This is the selected FONT", CHARS=1.5,/NORMAL,ALIGN=.5
 XYOUTS, .5, .5, $
    '-misc-fixed-medium-r-normal--20-140-100-100-c-100-iso8859-1', $
    /NORMAL, ALIGN=.5, FONT=0 ; select the hardware font

 f = XFONT()             ; use XFONT to view fonts. Not available on Windows!
 PRINT, f
...

 SHOWFONT, 9, 'Math and Special symbols' ; show font 9 (sym. and  math)
 SHOWFONT, 10, 'Special'                 ; show font 10 (special)
 SHOWFONT, 'Helvetica Italic', 'Helvetica italic', /TT_FONT ; select TrueType
...

 DEVICE, SET_FONT='helvetica', /TT_FONT  ; select TrueType Helvetica font
 ERASE

 XYOUTS, .5, .6, "Font selezionato: HELVETICA", CHARS=2.5,/NORMAL,ALIGN=.5
...

 EFONT            ; font editor
 PS_SHOW_FONTS    ; create a PS file (idl.ps - 1.5 Mbytes) with the available
                  ; PostScript fonts
...
Available TrueType fonts
Font Family Italic Bold BoldItalic
Courier Courier Italic Courier Bold Courier Bold Italic
Helvetica Helvetica Italic Helvetica Bold Helvetica Bold Italic
Times Times Italic Times Bold Times Bold Italic
Monospace Symbol      
Symbol      

Example: vector font 7 and 9

To select a vector font permanently (in a program):

 XYOUTS, 0, 0, '!17' ; select Triplex Roman font
 PLOT, FINDGEN(12), TITLE='Font vettoriale !!17', CHARS=2

 findex = 16
 sfindex = '!' + STRTRIM(findex,1) ; remove initial white spaces from findex
 XYOUTS, 0, 0, sfindex             ; and select the Cyrillic font

 PLOT, FINDGEN(12)^3, TITLE='Font '+ sfindex +', Cyrillic', CHARS=1.5
...

 HELP, /STR, !D
...

Some image visualization types:

 WINDOW, XS=500,YS=400 ; create a 500x400 pixel window
 LOADCT, 5             ; load a color table

 image = CONGRID(DIST(200), !D.X_Size, !D.Y_Size) ; adapt a 200x200 image into the window

 TV, image         ; 2-D image filling the whole screen

 TV, BYTSCL(image) ; ... BYTE scaled (0 < x < !D.TABLE_SIZE)
                   ; this is the APPROPRIATE way to visualize it!

 ; or

 TVSCL, image

 TV, BYTSCL(image,MAX=100) ; ... with a max value cut = 100

Let's insert the image in the plotting area:

 PLOT, [0], XRANGE=[0,200],YRANGE=[0,200], CHARS=1.5, TICKL=-.02
 TV, BYTSCL(image), 0,0, /DATA ; image origin is at (0,0)

...it does not work: let's get the plot area dimensions in pixels:

 cv = CONVERT_COORD([0,199],[0,199],/TO_DEV) ; def. = da coord. DATA
 PRINT, cv
       105.003      60.0020     0.000000
       466.685      368.452     0.000000

 PLOT, [0], XRANGE=[0,200],YRANGE=[0,200], CHARS=1.5, TICKL=-.02
 TV, CONGRID(image,cv[0,1]-cv[0,0],cv[1,1]-cv[1,0]),1,1,/DATA

... shade surface:

 SHADE_SURF, image        ; default aspect is 30 deg X, 30 deg Z
 SHADE_SURF, image, AX=60 ; 60 deg X rotated
 SHADE_SURF, image, AZ=60 ; 60 deg Z rotated

... wire mesh:

 SURFACE, image ; too many pixels ...
 image = DIST(100) & SURFACE, image
 z = SHIFT(DIST(40), 20, 20) & z=EXP(-(z/10)^2) ; Gaussian function
 SURFACE, z

 ; Colored version using the "Rainbow + white" table
 imin = MIN(z, MAX=imax)
 shad = (z - imin)/(imax - imin) * 254 ; exclude index 255 = white!
 loadct, 39
 SURFACE, z, SHADES=shad

 ; LEGO version
 SURFACE, z, SHADES=shad, /LEGO

... contours:

 mai = MAX(image,MIN=mii) & PRINT, mii,mai
    0.000000      70.7107

 CONTOUR, image, LEVELS=FINDGEN(10)*(mai-mii)/9. + mii ; 10 levels with linear step

 mii = 5 & mai = 40
 levs = mii*10^((INDGEN(10)+1)*ALOG10(mai/mii)/9.) ; 10 levels with logarithmic step
 CONTOUR, image, LEVELS=levs
 c = loadct19()

 CONTOUR, image, LEVELS=levs, C_COLORS=c        ; color contours
 CONTOUR, image, LEVELS=levs, C_COLORS=c, /FILL ; filled contours

...image and contours:

 LOADCT, 5
 PLOT, [0], XRANGE=[0,100],YRANGE=[0,100], CHARS=1.5, XSTY=5, YSTY=5 ; no axes
 cv = CONVERT_COORD([0,99],[0,99],/TO_DEV)
 TV, CONGRID(image,cv[0,1]-cv[0,0],cv[1,1]-cv[1,0]),1,1, /DATA
 CONTOUR, image, LEVELS=levs, CHARS=1.5, XSTY=1, YSTY=1 
 WINDOW, 1 & LOADCT, 39 ; change window and color table
 SHOW3, z 
 SHOW3, image 
 SHOW3, image, E_CONTOUR={LEVELS: FINDGEN(10)*(mai-mii)/9. + mii}

Writing / reading ASCII files:

 z = SHIFT(DIST(40), 0, 20) & z = EXP(-(z/10)^2) ; a shifted Gaussian
 SURFACE, z 
 SURFACE, z[0:19,*]        ; only left half
 z1 = z[0:19,*] 
 OPENW, 1, 'hgauss1.out'   ; open for formatted output
 PRINTF, 1, z1             ; write using free format
                           ; first the X values (leftmost index)
      
 CLOSE, 1
      
 XDISPLAYFILE, 'hgauss1.out'   ; first row = z1[*,0] 
 PRINT, z1[*,0]
      
 z2 = FLTARR(20,40) 
 OPENR, lun, 'hgauss1.out', /GET_LUN  ; define unit "lun" automatically
 READF, lun, z2 
 FREE_LUN, lun                        ; free unit "lun"
      
 c = loadct19() 
 SURFACE, z2, color=c[2], /NOERA      ; OK
      
 OPENW, lun, 'hgauss2.out', /GET_LUN 
 PRINTF, lun, z1, FORMAT='(G12.6)'    ; single formatted column
 FREE_LUN, lun
      
 XDISPLAYFILE, 'hgauss2.out'
      
 z3 = FLTARR(20,40) 
 OPENR, lun, 'hgauss2.out', /GET_LUN 
 READF, lun, z3 
 CLOSE, lun 
 SURFACE, z3, color=c[3], /NOERA      ; OK

To use a binary format have a look to the on-line Help (for example see the function ASSOC).

IMDISP - a general purpose (user written) image display program:

IMDISP allows to visualize images without caring of the display type and graphics device in use. Can get information about it, together with the source code, at Liam Gumley web site. There are also a couple of demo programs.
A copy is available locally here - Version 1.47, (05/06/2002).
As usual use doc_library, 'imdisp' to get help on its usage.

Writing / reading a GIF image:

Screen dumping into a GIF file:

 WRITE_GIF, 'idl_dump.gif', TVRD(0,0, !D.X_VSIZE, !D.Y_VSIZE)

Viewing a GIF file:
(Only 8-bit images are supported)

 READ_GIF, 'ross_logo1.gif', ima, r,g,b
 HELP, ima,r,g,b
IMA             BYTE      = Array[661, 317]
R               BYTE      = Array[256]
G               BYTE      = Array[256]
B               BYTE      = Array[256]

 TVLCT, r,g,b ; load from the R G B variables the display color translation tables
 TV, ima      ; now can display the image

Note again that this to work properly requires the Graphics Device to use Combined Graphics pixels. This is set using the keyword DECOMPOSED=0 for the DEVICE command (see above). Using the HELP command should give:

 HELP, /DEVICE
...
    Colormap: Shared, 16777216 colors.  Translation table: Bypassed
    Graphics pixels: Combined,  Dither Method: Ordered
...
whereas for a Decomposed graphics device (the default, i.e. DECOMPOSED=1):
 HELP, /DEVICE
...
    Colormap: Private, 16777216 colors.  Translation table: Enabled
    Graphics pixels: Decomposed,        Dither Method: Ordered
...
Moreover, the plot window must be of appropriate size, otherwise can use CONGRID:
 TV, CONGRID(image, !D.X_Size, !D.Y_Size)

Rescaling could result in a very bad result.
See also QUERY_DICOM and READ_DICOM:

 DOC_LIBRARY, 'query_dicom'
   ...

 DOC_LIBRARY, 'read_dicom'
   ...

Let's modify a bit the image and save it. If we have less than 256 colors defined, then it's better to load a color table...

 LOADCT, 0
 TVLCT, r,g,b ; replace colors with those of the image

Now we need to manage a special COMMON block to make the changes effective. It is used by all the IDL routines which make use of colors (this suggestion comes form the old IDL FAQ):

 COMMON colors,r_orig,g_orig,b_orig,r_curr,g_curr,b_curr 
 r_orig = r & r_curr = r 
 g_orig = g & g_curr = g 
 b_orig = b & b_curr = b 

 xpalette ; edit the colors: recall that only the initial color are changed by the
          ; loaded image and can be modified. For example change the background.

 TV, ima ; re-display  

NOTE: if we have a TRUE color display, then can read the 3 channels separately:

 r =  TVRD(0, 0, 661, 317, 1)
 g =  TVRD(0, 0, 661, 317, 2)
 b =  TVRD(0, 0, 661, 317, 3)

Let's save into a file the selected screen pixels:

 WRITE_GIF, 'idl_dump2.gif', ima, r_orig,g_orig,b_orig

Have a look at the result:

$ display idl_dump2.gif &

Can also look at READ_TIFF / WRITE_TIFF (and the intrinsic: READ_JPEG, WRITE_JPEG, READ_PNG, WRITE_PNG)

Getting information about variables - SIZE function:

 image = DIST(100)
 HELP, image
IMAGE           FLOAT     = Array[100, 100]
 PRINT, SIZE(image)
       2         100         100           4       10000
 s = SIZE(image)
 types=['Undef','Byte','Int','Long','Float','Double','Complex','String', $
 'Structure','Dbl complex','Pointer','Object ref','Unsigned Int', $
 'Unsigned Long Int','64-bit Int','Unsigned 64-bit Int']

 PRINT, 'Image is a '+ STRTRIM(s[1],1) +'x'+ STRTRIM(s[2],1) +' '+ $
        types[s[3]] +' array.'

Using EXECUTE to build commands "on the fly":

 ; Define a mixed structure
 a = {Name: 'Struct demo', Intval: 12, Fltval: 2., Doublarr: DINDGEN(3,5)}
 HELP, a, /STRU
** Structure <1038d88>, 4 tags, length=136, refs=1:
   NAME            STRING    'Struct demo'
   INTVAL          INT             12
   FLTVAL          FLOAT           2.00000
   DOUBLARR        DOUBLE    Array[3, 5]
 vars = 'a'
 r = EXECUTE('dummy=SIZE('+vars+')')
 PRINT, dummy
       1           1           8           1

 IF (N_ELEMENTS(dummy) eq 4 and dummy(2) eq 8) THEN $ ; value 8 → structure
 comm = 'HELP,'+ vars +',/STRUC' else comm = 'HELP,'+ vars
 r = EXECUTE(comm)
** Structure <1038d88>, 4 tags, length=136, refs=1:
   NAME            STRING    'Struct demo'
   INTVAL          INT             12
   FLTVAL          FLOAT           2.00000
   DOUBLARR        DOUBLE    Array[3, 5]

 PRINT, r, ' "'+ comm +'"'
     1 "HELP,a,/STRUC"

To have the tag names of the structure use the function TAG_NAMES:

 PRINT, TAG_NAMES(a)
NAME INTVAL FLTVAL DOUBLARR

To know if a tag exists can use the personal function: tag_namex:

 DOC_LIBRARY, 'tag_namex'
...

 PRINT, tag_namex(a,'NAME')
   0
 PRINT, tag_namex(a,'EQUINOX')
  -1

Logging commands into a file:

 JOURNAL, 'session.pro' ; standard output goes also into a file.
....                    ; Execute commands/programs

 JOURNAL                ; close the file (and the logging)

Files I/O:

By default IDL reads files from the current directory. Tipically the best habit is to address files with their full path. To find or "address" files one can use FILEPATH, FINDFILE, PICKFILE.

 PRINT, FILEPATH('demo.pro')
/usr/local/itt/idl/demo.pro

 PRINT, FILEPATH('demo.pro',SUBDIR=['examples','demo','demosrc'])
/usr/local/itt/idl/examples/demo/demosrc/demo.pro

 ;This is the 'true' location of the program.

 PRINT, FILEPATH('demodat.asc',SUBDIR='SISSA/Data',ROOT='/home/nicastro')
/home/nicastro/SISSA/Data/demodat.asc

 PRINT, FILEPATH('demodat.asc',SUBDIR='SISSA/Data',ROOT=GETENV('HOME'))
...

 PRINT, FINDFILE('*.dat')

 ; note how to obtain/use the system variable HOME (Linux)...
 prodir=GETENV('HOME') +'/IDL/Lib'

 PRINT, prodir
/home/nicastro/IDL/Lib

 PRINT, '# of pro files in Lib dir.=', N_ELEMENTS(FINDFILE(prodir+'/*.pro'))
# of pro files in Lib dir.=         110

 datadir = GETENV('HOME') +'/IDL/Data'

 f = PICKFILE()

 f = PICKFILE(PATH=datadir,FILTER='*.dat',/READ) ; select read-only mode

 PRINT, f
...

Changing (work) directory:

Use the command CD. Format of its parameter (directory name) depends on the operative system. For example in Linux the directory separator character is "/" and "./" explicitly refers to the current directory - be sure that the directory exists.

 CD, '~/IDL/Programs'

 CD, '/usr/nicastro/IDL/Demos'

 CD, '$HOME/IDL/Boc'

Reading binary / ASCII files:

Basic commands include OPENR (open for reading), OPENW (open for writing), OPENU (update). For example:

 OPENR, Unit, File

 READF, WRITEF     ; read ASCII formatted
 READU, WRITEU     ; read binary unformatted
 READ, in          ; read parameter from standard input - keyboard
:

 instr = '10 20 30'
 READS, instr  ; read a string legge da stringa (see allowed keywords)

 CLOSE, unit       ; simple close
 FREE_LUN, unit    ; if the file was open using /GET_LUN

To move the pointer into an open unit use POINT_LUN, FSTAT, etc. See "File I/O Overview" in the online Help.

Reading a columns formatted ASCII file:

Again we assume Linux and the data are in ~/IDL/Data/demodat.ascC.

 file = FILEPATH('demodat.asc',SUBDIR='IDL/Data',ROOT=GETENV('HOME'))

 a = READ_ASCII(file) ; see also ASCII_TEMPLATE

 HELP, a, /STRU
** Structure <4031c988>, 1 tags, length=1860, refs=1:
   FIELD1          FLOAT     Array[3, 155]
 PRINT, a.field1
...

 a = READ_ASCII(file,DATA_START=22,HEADER=h,COUNT=n) ; data start at row 23
 PRINT, 'There are '+ STRTRIM(n,1) +' data records.'
There are 133 data records.

 PRINT, h
...

 PRINT, h, FORMAT='(a)' ; formatted output: one row per element
...

 PRINT, a.field1[*,0:3] ; print the first 3 rows
...

 tmpl = ASCII_TEMPLATE(file)

 HELP, tmpl, /STRU
...

 PRINT, tmpl.fildnames
 a = READ_ASCII(file,TEMPLATE=tmpl,HEADER=h)
 HELP, a, /STRU
...

 a = nxyreadf(file,ncol=7) ; use a personal function: by default it reads 2 columns
 HELP, a
...

 PLOT, a[0,*],a[1,*]
 PLOT, a[0,*],a[2,*]
 pos = pposn(2,3) & tn = [' ',' ',' ',' ',' ',' ']
 FOR i=0,5 DO PLOT, a[0,*],a[i+1,*], POS=pos[i,*], XTICKS=2,XTICKN=tn, $
     XSTY=1,XMINOR=4,YTICKS=4,YTICKN=tn,YSTY=1,YMINOR=4,/NOERA
...
See also the notes for practice day 2.

Plotting 'bins' (and their errors) using binplot and erplot:

Linux - assuming tha data are in ~/IDL/Data/ls3.out.

 b = nxyreadf('~/IDL/Data/ls3.out',ncol=3)
 PLOT, b[0,*],b[1,*], YRANGE=[800,2000], XSTY=1, YSTY=1
 PLOT, [0], XRANGE=[-10,40],YRANGE=[800,2000], XSTY=1, YSTY=1 ; the frame
 binplot, b[0,*],b[1,*]            ; bins plot (in the range [-10,40])
 binplot, b[0,*],b[1,*], /CONNECT  ; connecting the bins
 erplot, b[0,*],b[1,*],b[2,*]      ; error bars plotting
 ERASE & PLOT, a[0,*],b[1,*], YRANGE=[800,2000], XSTY=1, YSTY=1
 binplot, b[0,*],b[1,*], /CONNECT
 erplot, b[0,*],b[1,*],b[2,*],STEP=3, WIDTH=0 ; error bars every 3 bins using a "cap" width=0

X axis errors plotting:

The personal procedure binplot can be used to reach the aim. For example:

 x = FINDGEN(16)*10  & ex = SQRT(x)
 y = FINDGEN(16)*100 & ey = SQRT(y)

 PLOT, x,y, PSYM=4,SYMSIZE=1.5

 erplot, x, y, ey & binplot, x, y, ex

Displaying an ASCII file and arrays:

To this aim use XDISPLAYFILE, XDISPFILE, or even ASCII_TEMPLATE).

 XDISPLAYFILE, 'demodat.asc'   ; assume the file is in the current dir.
 DOC_LIBRARY, 'xdisplayfile'
 ...

 xdispfile, 'demodat.asc'
 DOC_LIBRARY, 'xdispfile'
 ...

 xdispfile,text = string(a.field1)

Read/write FITS files:

Let's read a FITS file containing an image (data and header):

1- using the procedure fits_read:

 fits_read, 'crab_dss2_r_6x6.fits', dat6, hdr6
 
 HELP, dat6, hdr6
DAT6               INT   = Array[356, 357]
HDR6            STRING   = Array[129]
 
 LOADCT, 5
 WINDOW, 0, XS=500, YS=400
 TV, CONGRID(BYTSCL(dat6), !D.X_Size, !D.Y_Size)

2- Using the function mrdfits:

 dat4 = mrdfits( 'crab_dss2_r_4x4.fits', 0, hdr4 )
 
 HELP, dat4, hdr4
DAT4               INT    = Array[238, 238]
HDR4            STRING    = Array[129]
 
 WINDOW, 1, XS=500, YS=400
 TV, CONGRID(BYTSCL(dat4), !D.X_Size, !D.Y_Size)

To read only the header:

 thehdr = headfits('crab_dss2_r_4x4.fits')
 
 xdispfile, TEXT=thehdr

If one prefers to transfer the entire file into a structure (header+data) then one can use other routines, like RDFITS_STRUCT or the one from my personal library fitsreadx. It is not distributed here (contact me for it) but it would be used like this:

 err = fitsreadx('crab_dss2_r_4x4.fits',d)
 
 PRINT, err ; if err not 0 then there was an error reading the file
   0
 
 HELP, d, /STRU ; would show information about the single "d" structure
...

Let's write a portion of the image into a new file using mwrfits:

 d4 = dat4[0:99,0:99]
 mwrfits, d4, 'outdata4.fits'

Let's read back the file:

 fits_read, 'outdata4.fits', d, h 
 
 PRINT, h
SIMPLE  =                    T /image conforms to FITS standard
BITPIX  =                   16 /bits per data value
NAXIS   =                    2 /number of axes
NAXIS1  =                  100 /
NAXIS2  =                  100 /
END

Let's write out also the header (use /CREATE to overwrite the file rather then append data to it):

 mwrfits, d4, 'outdata4.fits', hdr4, /CREA
 
 fits_read, 'outdata4.fits', d, h ; read back the whole file
 
 HELP, h
H              STRING    = Array[129]
 
 PRINT, h[0:7] ; show just the first 8 keywords
...

 ERASE
 TV, BYTSCL(d)

As an alternative fits_write could have been used:

 fits_write, 'outdata4.fits', d4, hdr4
 
 fits_read, 'outdata4.fits', dd, hh
 PRINT, hh[0:7]
... 

See also writefits. More advanced examples are reported in the notes for practice day 2.

Check the routines help in the Astronomical users' library for reading / writing FITS tables.


Some simple procedures:

NOTE: Must be in the directory where tha data file resides, or use the appropriate path.
A simple plotting procedure: demo1.pro in the "Demos" subdirectory "Demos" (please edit it).

 demo1
 DOC_LIBRARY, 'demo1'
 demo1, 'sub_grbm.out', /BIN
 demo1, 'sub_grbm.out', /BIN, CHARS=2, XRANGE=[-70,100]
 demo1, 'sub_grbm.out', /BIN, CHARS=2, XRANGE=[-70,100], YSTY=0
...

2-d plots in 3-d space: spaceplot.pro in the "Demos" subdir. (please edit it).

 spaceplot

 DOC_LIBRARY, 'spaceplot'

... a bit more advanced:

crabpulse.pro and cieloagn.pro in the "Demos" subdir. (please edit it).

 DOC_LIBRARY, 'crabpulse'
...

 DOC_LIBRARY, 'cieloagn'
...

Again, note that you must be in the "local" directory to read data. So:

 CD, '$HOME/IDL/Demos'

 crabpulse      ; Crab pulse profile and spectral index (B-SAX)

 cieloagn, /TOP ; AGNs and unidentified sources in the EGRET 3EG catalogue
                ; using Aitoff projection

Interacting with the operative system:

To avoid creating a new process ("son" of the current one):

 SPAWN, ['mv',tmpfile,fileok], /NOSHELL

 SPAWN, ['ls'], /NOSHELL

Creating a new process:

 SPAWN, 'ls *.fits', lista_ffits
 SPAWN, 'analise_data files_list', output_string, PID=processID, COUNT=nrows

Advanced programming makes use of other functions like CALL_EXTERNAL and CALL_PROCEDURE.
Not to forget the very handy function EXECUTE used above.

Please always refer to the on-line Help for more and detailed information about the used (and not-used) commands.

Go to the course Main page L. Nicastro, INAF-IASF, 2009-01-22