← Back to Archives

Extracting data points from plots, images in IDL

(aka, "I've got this dang figure and can't get access to the original data (or at least not fast enough)... how do I extract the data points from the plot / image?")

So you would like to extract points from a figure and you have access to IDL? Well, you're lucky that I've written the code for it.

;+
; NAME:
;	extract_points
;
; PURPOSE:
;	To facilitate the extraction of data points from a JPEG figure.
;
; EXPLANATION:
;	extract_points is pretty simple.  It reads in a JPEG file,
;	re-sizes it, and then prompts the user to do a bunch of
;	clicking to define the axes and then select points to output.
;
; CALLING SEQUENCE:
;	 extract_points, file, out_arr $
;	   [, xsize=XSIZE, retain=RETAIN]
;
; INPUTS:
;	file - a simple string that holds the JPEG filename.
;
; OUTPUT:
;	out_arr - a n x 2 floating point array with n being the number
;	          of points the user clicked on.
;
; REVISION HISTORY:
;       Written by:  Joseph Lorenzo Hall, 18 Feb 2003.
;-

pro extract_points, file, out_arr, xsize=XSIZE, retain=RETAIN

read_jpeg, file, im			      ;READ IN JPEG

;RESIZE AND DISPLAY JPEG
if n_elements(xsize) ne 1 then $
   x_pix = 640 else x_pix=xsize			;SET WINDOW SIZE
im_sz = size(im)				;GET IMAGE DIMENSIONS
jpg_type = im_sz[0]

if jpg_type eq 2 then begin			;8-BIT, 16-BIT
im_sz = size(im,/dim)
aspect = float(im_sz[1]) / float(im_sz[0])	;ASPECT RATIO
new_im = congrid(im,x_pix,x_pix*aspect)		;RESIZE IMAGE
endif

if jpg_type eq 3 then begin			;24-BIT
im_sz = size(im,/dim)
aspect = float(im_sz[2]) / float(im_sz[1])	;ASPECT RATIO
new_im = $
    congrid(im,im_sz[0],x_pix,x_pix*aspect)	;RESIZE IMAGE
endif

window, retain=retain, xsize=x_pix, $	;OPEN A SIZED WINDOW
	ysize=x_pix*aspect 

CASE StrUpCase(!D.Name) OF		;FANNING SUGGESTS THIS
   'WIN': Device, Decomposed=1
   'MAC': Device, Decomposed=1
    'X' : Device, Decomposed=1
   ELSE:
ENDCASE

if jpg_type eq 3 then tv, new_im, true=1
if jpg_type eq 2 then tv, new_im

;PROMPT TO CLICK ON A TICK LABELS ON X-AXIS
print, ' '
print, ' Please click on the FIRST labeled tick mark on the X-AXIS'
cursor, x1_x, x1_y, /normal, /down
print, ' Please enter the label of this tick mark:'
read, x1_val
print, ' Please click on the LAST labeled tick mark on the X-AXIS'
cursor, x2_x, x2_y, /normal, /down
print, ' Please enter the label of this tick mark:'
read, x2_val

;THE FOLLOWING ALLOWS A TRANFORMATION FROM NORMAL TO DATA COORDINATES
x_pix_diff = x2_x - x1_x
x_val_diff = x2_val - x1_val
x_scale = x_val_diff / x_pix_diff
x_int   = x1_val - x1_x * x_scale

;PROMPT TO CLICK ON A TICK LABEL ON Y-AXIS
print, ' '
print, ' Please click on the FIRST labeled tick mark on the Y-AXIS'
cursor, y1_x, y1_y, /normal, /down
print, ' Please enter the label of this tick mark:'
read, y1_val
print, ' Please click on the LAST labeled tick mark on the Y-AXIS'
cursor, y2_x, y2_y, /normal, /down
print, ' Please enter the label of this tick mark:'
read, y2_val

y_pix_diff = y2_y - y1_y
y_val_diff = y2_val - y1_val
y_scale = y_val_diff / y_pix_diff
y_int   = y1_val - y1_y * y_scale

cfx = [x_int,x_scale]
cfy = [y_int,y_scale]

repeat begin
 print, ' '
 print, ' Begin pixel input. Click on a data point to add it to your array.'
 print, ' Click on middle or right button to exit.'

 flag = 0
 repeat begin
   cursor, x, y, /normal, /down
   if !mouse.button eq 1 then begin
    if flag ne 1 then begin
     flag = 1
     x_arr = x & y_arr = y
    endif else begin
     x_arr = [x_arr,x] & y_arr = [y_arr,y]
    endelse
   endif
 endrep until !mouse.button ge 2

 npts = n_elements(x_arr)
 as = sort(x_arr)
 x_arr = x_arr(as) & y_arr = y_arr(as)	
 out_arr = fltarr(npts,2)
 out_arr[*,0] = poly(x_arr,cfx)
 out_arr[*,1] = poly(y_arr,cfy)

 print, "Are you satisfied with your extraction (0=Sure am, 1=Nope)?"
 read, ans

endrep until (ans eq 0)
end