-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcldendro.pro
More file actions
338 lines (297 loc) · 11.4 KB
/
cldendro.pro
File metadata and controls
338 lines (297 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
; $Id: dendro_plot.pro,v 1.7 2005/02/01 20:24:19 scottm Exp $
; Copyright (c) 2003-2005, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
;+
; NAME:
; DENDRO_PLOT
;
; PURPOSE:
; Given a hierarchical tree cluster, as created by CLUSTER_TREE,
; the DENDRO_PLOT procedure draws a two-dimensional dendrite plot
; on the current direct graphics device.
;
; CALLING SEQUENCE:
; DENDRO_PLOT, Clusters, Linkdistance
;
; INPUTS:
; Clusters: A 2-by-(m-1) input array containing the cluster indices,
; where m is the number of items in the original dataset.
; This array is usually the result of the CLUSTER_TREE function.
;
; Linkdistance: An (m-1)-element input vector containing the distances
; between cluster items, as returned by the Linkdistance argument
; to the CLUSTER_TREE function.
;
; KEYWORD PARAMETERS:
; See the IDL Reference Manual for a description of the keywords.
;
; EXAMPLE:
; ; Given a set of points in two-dimensional space.
; m = 20
; data = 7*RANDOMN(-1, 2, m)
;
; ; Compute the Euclidean distance between each point.
; distance = DISTANCE_MEASURE(data)
;
; ; Compute the cluster analysis.
; clusters = CLUSTER_TREE(distance, linkdistance, LINKAGE=2)
;
; DENDRO_PLOT, clusters, linkdistance, $
; POSITION=[0.08, 0.1, 0.48, 0.9], $
; XSTYLE=9, YSTYLE=9, $
; XTITLE='Leaf', YTITLE='Distance'
;
; DENDRO_PLOT, clusters, linkdistance, $
; ORIENTATION=1, /NOERASE, $
; POSITION=[0.56, 0.1, 0.96, 0.9], $
; XSTYLE=9, YSTYLE=9, $
; XTITLE='Distance', YTITLE='Leaf'
;
; MODIFICATION HISTORY:
; Written by: CT, RSI, Sept 2003
; Modified:
;
;-
;-------------------------------------------------------------------------
pro cldendro, clusters, linkdistance, merger, $
CHARSIZE=charsizeIn, $
CHARTHICK=charthick, $
COLOR=colorIn, $
FONT=font, $
LABEL_CHARSIZE=labelCharsizeIn, $
LABEL_CHARTHICK=labelCharthickIn, $
LABEL_COLOR=labelColorIn, $
LABEL_NAMES=labelNamesIn, $
LABEL_ORIENTATION=labelOrientIn, $
LINECOLOR=lineColorIn, $
LINESTYLE=lineStyle, $
ORIENTATION=orientationIn, $
OVERPLOT=overplot, $
THICK=lineThick, $
XRANGE=xrangeIn, YRANGE=yrangeIn, $
XSTYLE=xstyleIn, YSTYLE=ystyleIn, $
XTICKLEN=xticklenIn, YTICKLEN=yticklenIn, $
XTICKS=xticksIn, YTICKS=yticksIn, $
XTICKV=xtickvIn, YTICKV=ytickvIn, $
XTICKNAME=xticknameIn, YTICKNAME=yticknameIn, $
XTITLE=xtitleIn, YTITLE=ytitleIn, $
_REF_EXTRA=_extra
; compile_opt idl2
; ON_ERROR, 2
if (N_PARAMS() ne 3) then $
MESSAGE, 'Incorrect number of arguments.'
; Retrieve the vertex and connectivity for the dendrogram.
DENDROGRAM, clusters, linkdistance, outverts, outconn, $
LEAFNODES=leafnodes
dvals =merger[indgen(sqrt(n_elements(merger))), $
indgen(sqrt(n_elements(merger)))]
leafy = where(outverts[1, *] eq 0)
outverts[1, *] = max(dvals)-outverts[1, *]
outverts[1, leafy] = dvals[leafnodes[outverts[0, leafy]]]
dimC = SIZE(clusters, /DIMENSIONS)
m = dimC[1] + 1
if (N_ELEMENTS(labelNamesIn) eq m) then begin
; Rearrange labels to match the new leaf node positions.
labelNames = labelNamesIn[leafnodes]
endif else begin
if (N_ELEMENTS(labelNamesIn) ne 1) then $
labelNames = STRTRIM(leafnodes, 2)
endelse
color = (N_ELEMENTS(colorIn) gt 0) ? colorIn : !P.color
charsize = N_ELEMENTS(charsizeIn) ? charsizeIn : $
(!P.CHARSIZE ne 0 ? !P.CHARSIZE : 1)
lineColor = (N_ELEMENTS(lineColorIn) gt 0) ? lineColorIn : color
orientation = (N_ELEMENTS(orientationIn) eq 1) ? orientationIn : 0
xrange = (N_ELEMENTS(xrangeIn) eq 2) ? xrangeIn : [-1, m]
maxx = MAX(outverts[1,*], MIN=minn)
yrange = (N_ELEMENTS(yrangeIn) eq 2) ? yrangeIn : $
[0*(minn-0.1*(maxx-minn)), maxx + 0.1*(maxx - minn)]
if (orientation lt 0) || (orientation gt 3) || $
(orientation ne FIX(orientation)) then $
MESSAGE, 'Illegal keyword value for ORIENTATION.'
if ((orientation eq 0) || (orientation eq 2)) then begin
xx = REFORM(outverts[0,*], 4, m-1)
yy = REFORM(outverts[1,*], 4, m-1)
xticklen = 1e-5
xticks = 1
xtickname = [' ',' '] ; suppress
if (orientation eq 2) then $
yrange = yrange[[1,0]]
; Allow these keywords for the Y axis.
if (N_ELEMENTS(ytitleIn) eq 1) then $
ytitle = ytitleIn
if (N_ELEMENTS(yticklenIn) gt 0) then $
yticklen = yticklenIn
if (N_ELEMENTS(yticksIn) gt 0) then $
yticks = yticksIn
if (N_ELEMENTS(ytickvIn) gt 0) then $
ytickv = ytickvIn
if (N_ELEMENTS(yticknameIn) gt 0) then $
ytickname = yticknameIn
endif else begin
xx = REFORM(outverts[1,*], 4, m-1)
yy = REFORM(outverts[0,*], 4, m-1)
tmp = xrange
xrange = (orientation eq 1) ? yrange : yrange[[1,0]]
yrange = tmp
yticklen = 1e-5
yticks = 1
ytickname = [' ',' '] ; suppress
; Allow these keywords for the X axis.
if (N_ELEMENTS(xtitleIn) eq 1) then $
xtitle = xtitleIn
if (N_ELEMENTS(xticklenIn) gt 0) then $
xticklen = xticklenIn
if (N_ELEMENTS(xticksIn) gt 0) then $
xticks = xticksIn
if (N_ELEMENTS(xtickvIn) gt 0) then $
xtickv = xtickvIn
if (N_ELEMENTS(xticknameIn) gt 0) then $
xtickname = xticknameIn
endelse
if (~KEYWORD_SET(overplot)) then begin
xstyle = (N_ELEMENTS(xstyleIn) eq 1) ? xstyleIn : 1
ystyle = (N_ELEMENTS(ystyleIn) eq 1) ? ystyleIn : 1
PLOT, [0,1], /NODATA, $
CHARSIZE=charsize, $
CHARTHICK=charthick, $
COLOR=color, $
FONT=font, $
XSTYLE=xstyle, $
YSTYLE=ystyle, $
XTICKLEN=xticklen, YTICKLEN=yticklen, $
XRANGE=xrange, YRANGE=yrange, $
XTICKS=xticks, YTICKS=yticks, $
XTICKV=xtickv, YTICKV=ytickv, $
XTICKNAME=xtickname, YTICKNAME=ytickname, $
XTITLE=xtitle, YTITLE=ytitle, $
_EXTRA=_extra
endif
for i=0,m-2 do begin
PLOTS, xx[*,i], yy[*,i], $
COLOR=lineColor, $
LINESTYLE=lineStyle, $
THICK=lineThick
endfor
if (N_ELEMENTS(labelNames) eq m) then begin
; Construct the labels. This is complicated because we can't use AXIS
; ticks (because there is a limit of 60), and so we need to compute
; the positions ourself. We also allow different label angles.
labelColor = (N_ELEMENTS(labelColorIn) gt 0) ? $
labelColorIn : color
labelCharsize = (N_ELEMENTS(labelCharsizeIn) gt 0) ? $
labelCharsizeIn : charsize
if (labelCharsize le 0) then $
labelCharsize = 1
if (N_ELEMENTS(labelCharthickIn) gt 0) then $
labelCharthick = labelCharthickIn $
else if (N_ELEMENTS(charthick) gt 0) then $
labelCharthick = charthick
xdevice = labelCharsize*!D.x_ch_size
char = CONVERT_COORD([[0,0], [xdevice, 0]], /DEVICE, /TO_DATA)
width = char[0,1] - char[0,0]
ydevice = labelCharsize*!D.y_ch_size
char = CONVERT_COORD([[0,0], [0, ydevice]], /DEVICE, /TO_DATA)
height = char[1,1] - char[1,0]
char = CONVERT_COORD([[0,0], [ydevice, 0]], /DEVICE, /TO_DATA)
sideways = char[0,1] - char[0,0]
if ((orientation eq 0) || (orientation eq 2)) then begin
xloc = LINDGEN(m)
yloc = FLTARR(m)
; If label orient not provided, rotate by 90 deg if labels
; are too long. This is just a guess.
labelOrient = N_ELEMENTS(labelOrientIn) ? labelOrientIn : $
((MAX(STRLEN(labelNames)) le 2) ? 0 : 90)
endif else begin
xloc = FLTARR(m)
yloc = LINDGEN(m)
labelOrient = N_ELEMENTS(labelOrientIn) ? labelOrientIn : 0
endelse
; Reduce orientation to -180...+180
labelOrient mod= 360
if (labelOrient gt 180) then labelOrient -= 360 $
else if (labelOrient lt -180) then labelOrient += 360
angle = FLOAT(labelOrient)
case orientation of
0: begin ; leafs at bottom
if (angle eq 0) then begin
labelAlign = 0.5
yloc -= 1.5*height
endif else begin
labelAlign = (angle gt 0) ? 1 : 0
; Adjust baseline for pivoting about the bottom.
yloc -= (1.4 - ABS(angle)/90)*height
xloc += 0.4*sideways*(angle gt 0 ? 1 : -1)
endelse
end
2: begin ; leafs at top
labelAlign = (angle eq 0) ? 0.5 : $
((angle gt 0) ? 0 : 1)
yloc += 0.4*height
xloc += 0.4*sideways*angle/90 + $
0.4*width*(1-ABS(angle)/90)*(angle gt 0 ? -1 : 1)
end
1: begin ; leafs at left
if (ABS(angle) eq 90) then begin
labelAlign = 0.5
xloc -= 0.75*width
if (angle eq -90) then $
xloc -= 0.8*sideways
endif else begin
labelAlign = 1
xloc -= width* $
(angle eq 0 ? 0.5 : (angle gt 0 ? 0.3 : 1))
yloc -= height* $
(angle eq 0 ? 0.4 : (angle gt 0 ? 0.1 : 0.5))
endelse
end
3: begin ; leafs at right
if (ABS(angle) eq 90) then begin
labelAlign = 0.5
xloc += 0.75*width
if (angle eq 90) then $
xloc += 0.8*sideways
endif else begin
labelAlign = 0
xloc += width* $
(angle eq 0 ? 0.5 : (angle gt 0 ? 1.1 : 0.3))
yloc -= height* $
(angle eq 0 ? 0.4 : (angle gt 0 ? 0.5 : 0.1))
endelse
end
endcase
XYOUTS, xloc, yloc, labelNames, $
ALIGN=labelAlign, $
CHARSIZE=labelCharsize, $
CHARTHICK=labelCharthick, $
COLOR=labelColor, $
FONT=font, $
ORIENTATION=labelOrient
endif
; Add the title for the leaf axis.
if ((orientation eq 0) || (orientation eq 2)) then begin
if (N_ELEMENTS(xtitleIn) eq 1) then begin
AXIS, XAXIS=(orientation eq 2), $
CHARSIZE=charsize, $
CHARTHICK=charthick, $
COLOR=color, $
FONT=font, $
XSTYLE=xstyle, $
XTICKLEN=1e-5, $
XTICKS=1, XTICKNAME = [' ',' '], $
XTITLE=xtitleIn
endif
endif else begin
if (N_ELEMENTS(ytitleIn) eq 1) then begin
AXIS, YAXIS=(orientation eq 3), $
CHARSIZE=charsize, $
CHARTHICK=charthick, $
COLOR=color, $
FONT=font, $
YSTYLE=ystyle, $
YTICKLEN=1e-5, $
YTICKS=1, YTICKNAME = [' ',' '], $
YTITLE=ytitleIn
endif
endelse
end