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