~ubuntu-branches/ubuntu/raring/libpal-java/raring

« back to all changes in this revision

Viewing changes to src/pal/tree/SimpleNode.java

  • Committer: Package Import Robot
  • Author(s): Andreas Tille
  • Date: 2012-01-27 13:57:54 UTC
  • Revision ID: package-import@ubuntu.com-20120127135754-d63l3581f65fw9pk
Tags: upstream-1.5.1
ImportĀ upstreamĀ versionĀ 1.5.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// SimpleNode.java
 
2
//
 
3
// (c) 1999-2001 PAL Development Core Team
 
4
//
 
5
// This package may be distributed under the
 
6
// terms of the Lesser GNU General Public License (LGPL)
 
7
 
 
8
 
 
9
package pal.tree;
 
10
 
 
11
import pal.misc.*;
 
12
import java.io.*;
 
13
import pal.io.*;
 
14
import java.util.Hashtable;
 
15
import java.util.Enumeration;
 
16
 
 
17
 
 
18
/**
 
19
 * data structure for a node (includes branch) in a binary/non-binary
 
20
 * rooted/unrooted tree
 
21
 *
 
22
 * @version $Id: SimpleNode.java,v 1.27 2003/10/19 02:35:26 matt Exp $
 
23
 *
 
24
 * @author Korbinian Strimmer
 
25
 * @author Alexei Drummond
 
26
 */
 
27
public class SimpleNode implements AttributeNode {
 
28
 
 
29
        /** parent node */
 
30
        private Node parent;
 
31
 
 
32
        /** number of node as displayed */
 
33
        private int number;
 
34
 
 
35
        /** sequences associated with node */
 
36
        private byte[] sequence;
 
37
 
 
38
        /** length of branch to parent node */
 
39
        private double length;
 
40
 
 
41
        /** standard error of length of branch to parent node */
 
42
        private double lengthSE;
 
43
 
 
44
        /** height of this node */
 
45
        private double height;
 
46
 
 
47
        /** identifier of node/associated branch */
 
48
        private Identifier identifier;
 
49
 
 
50
        /** the attributes associated with this node. */
 
51
        private Hashtable attributes = null;
 
52
 
 
53
        //
 
54
        // Private stuff
 
55
        //
 
56
 
 
57
        private Node[] child;
 
58
 
 
59
        //
 
60
        // Serialization Stuff
 
61
        //
 
62
 
 
63
        static final long serialVersionUID=3472432765038556717L;
 
64
 
 
65
        //serialver -classpath ./classes pal.tree.SimpleNode
 
66
 
 
67
        /** I like doing things my self! */
 
68
        private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
 
69
                out.writeByte(3); //Version number
 
70
                out.writeObject(parent);
 
71
                out.writeInt(number);
 
72
                out.writeObject(sequence);
 
73
                out.writeDouble(length);
 
74
                out.writeDouble(lengthSE);
 
75
                out.writeDouble(height);
 
76
                out.writeObject(identifier);
 
77
                out.writeObject(child);
 
78
                out.writeObject(attributes);
 
79
        }
 
80
 
 
81
         private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
 
82
                        byte version = in.readByte();
 
83
                        switch(version) {
 
84
                                        case 1: {
 
85
                                                parent = (Node)in.readObject();
 
86
                                                number = in.readInt();
 
87
                                                sequence = (byte[])in.readObject();
 
88
                                                Object partial = (double[][][])in.readObject();
 
89
                                                length = in.readDouble();
 
90
                                                lengthSE = in.readDouble();
 
91
                                                height = in.readDouble();
 
92
                                                in.readDouble();
 
93
                                                identifier = (Identifier)in.readObject();
 
94
                                                child = (Node[])in.readObject();
 
95
                                                break;
 
96
                                        }
 
97
                                        case 2 : {
 
98
                                                //attributes are transient
 
99
 
 
100
                                                parent = (Node)in.readObject();
 
101
                                                number = in.readInt();
 
102
                                                sequence = (byte[])in.readObject();
 
103
                                                length = in.readDouble();
 
104
                                                lengthSE = in.readDouble();
 
105
                                                height = in.readDouble();
 
106
                                                identifier = (Identifier)in.readObject();
 
107
                                                child = (Node[])in.readObject();
 
108
                                                break;
 
109
                                        }
 
110
                                        default : {
 
111
                                                //attributes are not transient!
 
112
 
 
113
                                                parent = (Node)in.readObject();
 
114
                                                number = in.readInt();
 
115
                                                sequence = (byte[])in.readObject();
 
116
                                                length = in.readDouble();
 
117
                                                lengthSE = in.readDouble();
 
118
                                                height = in.readDouble();
 
119
                                                identifier = (Identifier)in.readObject();
 
120
                                                child = (Node[])in.readObject();
 
121
                                                attributes = (Hashtable)in.readObject();
 
122
                                        }
 
123
                        }
 
124
         }
 
125
 
 
126
        // the following constructors should eventually become
 
127
        // "friendly" to prevent anyone calling them directly.
 
128
        // Instead, the NodeFactory should be used!
 
129
 
 
130
        /** constructor default node */
 
131
        public SimpleNode()
 
132
        {
 
133
                parent = null;
 
134
                child =null;
 
135
                length = 0.0;
 
136
                lengthSE = 0.0;
 
137
                height = 0.0;
 
138
                identifier = Identifier.ANONYMOUS;
 
139
 
 
140
                number = 0;
 
141
                sequence = null;
 
142
        }
 
143
 
 
144
        public SimpleNode(String name, double branchLength) {
 
145
                this();
 
146
                identifier = new Identifier(name);
 
147
                length = branchLength;
 
148
 
 
149
        }
 
150
        /**
 
151
         * Constructor
 
152
         * @param children
 
153
         * @param branchLength
 
154
         * @throws IllegalArgumentException if only one child!
 
155
         */
 
156
        protected SimpleNode(Node[] children, double branchLength) {
 
157
                this();
 
158
                this.child = children;
 
159
                if(children.length==1) {
 
160
                  throw new IllegalArgumentException("Must have more than one child!");
 
161
                }
 
162
                for(int i = 0 ; i < child.length ; i++) {
 
163
                        child[i].setParent(this);
 
164
                }
 
165
                this.length = branchLength;
 
166
        }
 
167
        protected SimpleNode(Node[] children) {
 
168
                this(children, BranchLimits.MINARC);
 
169
        }
 
170
 
 
171
        /** constructor used to clone a node and all children */
 
172
        public SimpleNode(Node n)
 
173
        {
 
174
                this(n, true);
 
175
        }
 
176
 
 
177
 
 
178
 
 
179
        public void reset()
 
180
        {
 
181
                parent = null;
 
182
                child = null;
 
183
                length = 0.0;
 
184
                lengthSE = 0.0;
 
185
                height = 0.0;
 
186
                identifier = Identifier.ANONYMOUS;
 
187
 
 
188
                number = 0;
 
189
                sequence = null;
 
190
        }
 
191
 
 
192
        public SimpleNode(Node n, boolean keepIds) {
 
193
                init(n, keepIds);
 
194
                for (int i = 0; i < n.getChildCount(); i++) {
 
195
                        addChild(new SimpleNode(n.getChild(i), keepIds));
 
196
                }
 
197
        }
 
198
 
 
199
        public SimpleNode(Node n, LabelMapping lm) {
 
200
                init(n, true, lm);
 
201
                for (int i = 0; i < n.getChildCount(); i++) {
 
202
                        addChild(new SimpleNode(n.getChild(i), lm));
 
203
                }
 
204
        }
 
205
 
 
206
        protected void init(Node n) {
 
207
                init(n, true);
 
208
        }
 
209
        /**
 
210
         * Initialized node instance variables based on given Node.
 
211
         * children are ignored.
 
212
         */
 
213
        protected void init(Node n, boolean keepId) {
 
214
                init(n,keepId,null);
 
215
        }
 
216
        /**
 
217
         * Initialized node instance variables based on given Node.
 
218
         * children are ignored.
 
219
         * @param lm - may be null
 
220
         */
 
221
        protected void init(Node n, boolean keepId, LabelMapping lm) {
 
222
                parent = null;
 
223
                length = n.getBranchLength();
 
224
                lengthSE = n.getBranchLengthSE();
 
225
                height = n.getNodeHeight();
 
226
                if (keepId) {
 
227
                        if(lm!=null) {
 
228
                                identifier = lm.getLabelIdentifier(n.getIdentifier());
 
229
                        } else {
 
230
                                identifier = n.getIdentifier();
 
231
                        }
 
232
                } else { identifier = Identifier.ANONYMOUS; }
 
233
 
 
234
                number = n.getNumber();
 
235
                sequence = n.getSequence();
 
236
 
 
237
                if (n instanceof AttributeNode) {
 
238
                        AttributeNode attNode = (AttributeNode)n;
 
239
                        Enumeration e = attNode.getAttributeNames();
 
240
                        while ((e != null) && e.hasMoreElements()) {
 
241
                                String name = (String)e.nextElement();
 
242
                                setAttribute(name, attNode.getAttribute(name));
 
243
                        }
 
244
                }
 
245
 
 
246
                child = null;
 
247
        }
 
248
 
 
249
        /**
 
250
         * Returns the parent node of this node.
 
251
         */
 
252
        public final Node getParent() {
 
253
                return parent;
 
254
        }
 
255
 
 
256
        /** Set the parent node of this node. */
 
257
        public void setParent(Node node)
 
258
        {
 
259
                parent = node;
 
260
        }
 
261
 
 
262
        /**
 
263
         * removes parent.
 
264
         */
 
265
        public final void removeParent() {
 
266
                parent = null;
 
267
        }
 
268
 
 
269
        /**
 
270
         * Returns the sequence at this node, in the form of a String.
 
271
         */
 
272
        public String getSequenceString() {
 
273
                return new String(sequence);
 
274
        }
 
275
 
 
276
        /**
 
277
         * Returns the sequence at this node, in the form of an array of bytes.
 
278
         */
 
279
        public byte[] getSequence() {
 
280
                return sequence;
 
281
        }
 
282
 
 
283
        /**
 
284
         * Sets the sequence at this node, in the form of an array of bytes.
 
285
         */
 
286
        public void setSequence(byte[] s) {
 
287
                sequence = s;
 
288
        }
 
289
 
 
290
        /**
 
291
         * Get the length of the branch attaching this node to its parent.
 
292
         */
 
293
        public final double getBranchLength() {
 
294
                return length;
 
295
        }
 
296
 
 
297
        /**
 
298
         * Set the length of the branch attaching this node to its parent.
 
299
         */
 
300
        public final void setBranchLength(double value) {
 
301
                length = value;
 
302
        }
 
303
 
 
304
        /**
 
305
         * Get the length SE of the branch attaching this node to its parent.
 
306
         */
 
307
        public final double getBranchLengthSE() {
 
308
                return lengthSE;
 
309
        }
 
310
 
 
311
        /**
 
312
         * Set the length SE of the branch attaching this node to its parent.
 
313
         */
 
314
        public final void setBranchLengthSE(double value) {
 
315
                lengthSE = value;
 
316
        }
 
317
 
 
318
 
 
319
        /**
 
320
         * Get the height of this node relative to the most recent node.
 
321
         */
 
322
        public final double getNodeHeight() {
 
323
                return height;
 
324
        }
 
325
 
 
326
        /**
 
327
         * Set the height of this node relative to the most recent node.
 
328
         * @note corrects children branch lengths
 
329
         */
 
330
        public final void setNodeHeight(double value) {
 
331
                if(value<0) {
 
332
                        height = -value;
 
333
                } else {
 
334
                        height = value;
 
335
                }
 
336
                /*if(child!=null) {
 
337
                        for(int i = 0 ; i<child.length ; i++) {
 
338
                                child[i].setBranchLength(height-child[i].getNodeHeight());
 
339
                        }
 
340
                }*/
 
341
        }
 
342
        /**
 
343
         * Set the height of this node relative to the most recent node.
 
344
         * @param adjustChildBranchLengths if true
 
345
         */
 
346
        public final void setNodeHeight(double value,boolean adjustChildBranchLengths) {
 
347
                if(value<0) {
 
348
                        height = -value;
 
349
                } else {
 
350
                        height = value;
 
351
                }
 
352
                if(adjustChildBranchLengths &&child!=null) {
 
353
                        for(int i = 0 ; i<child.length ; i++) {
 
354
                                child[i].setBranchLength(height-child[i].getNodeHeight());
 
355
                        }
 
356
                }
 
357
        }
 
358
 
 
359
        /**
 
360
         * Returns the identifier for this node.
 
361
         */
 
362
        public final Identifier getIdentifier() {
 
363
                return identifier;
 
364
        }
 
365
 
 
366
        /**
 
367
         * Set identifier for this node.
 
368
         */
 
369
        public final void setIdentifier(Identifier id) {
 
370
                identifier = id;
 
371
                //return identifier;
 
372
        }
 
373
 
 
374
        public void setNumber(int n) {
 
375
                number = n;
 
376
        }
 
377
 
 
378
        public int getNumber() {
 
379
                return number;
 
380
        }
 
381
 
 
382
        /**
 
383
         * get child node
 
384
         *
 
385
         * @param n number of child
 
386
         *
 
387
         * @return child node
 
388
         */
 
389
        public Node getChild(int n)
 
390
        {
 
391
                return child[n];
 
392
        }
 
393
 
 
394
        /**
 
395
         * set child node
 
396
         *
 
397
         * @param n number
 
398
         * @node node new child node
 
399
         */
 
400
        public void setChild(int n, Node node)
 
401
        {
 
402
                child[n] = node;
 
403
                child[n].setParent(this);
 
404
        }
 
405
 
 
406
        /**
 
407
         * check whether this node is an internal node
 
408
         *
 
409
         * @return result (true or false)
 
410
         */
 
411
        public boolean hasChildren()
 
412
        {
 
413
                return !isLeaf();
 
414
        }
 
415
 
 
416
        /**
 
417
         * check whether this node is an external node
 
418
         *
 
419
         * @return result (true or false)
 
420
         */
 
421
        public boolean isLeaf() {
 
422
                return (getChildCount() == 0);
 
423
        }
 
424
 
 
425
        /**
 
426
         * check whether this node is a root node
 
427
         *
 
428
         * @return result (true or false)
 
429
         */
 
430
        public boolean isRoot()
 
431
        {
 
432
                if (parent == null)
 
433
                {
 
434
                        return true;
 
435
                }
 
436
                else
 
437
                {
 
438
                        return false;
 
439
                }
 
440
        }
 
441
 
 
442
 
 
443
        /**
 
444
         * add new child node
 
445
         *
 
446
         * @param n new child node
 
447
         */
 
448
        public void addChild(Node n)
 
449
        {
 
450
                insertChild(n, getChildCount());
 
451
        }
 
452
 
 
453
        /**
 
454
         * add new child node (insertion at a specific position)
 
455
         *
 
456
         * @param n new child node
 
457
         + @param pos position
 
458
         */
 
459
        public void insertChild(Node n, int pos)
 
460
        {
 
461
                int numChildren = getChildCount();
 
462
 
 
463
                Node[] newChild = new Node[numChildren + 1];
 
464
 
 
465
                for (int i = 0; i < pos; i++)
 
466
                {
 
467
                        newChild[i] = child[i];
 
468
                }
 
469
                newChild[pos] = n;
 
470
                for (int i = pos; i < numChildren; i++)
 
471
                {
 
472
                        newChild[i+1] = child[i];
 
473
                }
 
474
 
 
475
                child = newChild;
 
476
 
 
477
                n.setParent(this);
 
478
        }
 
479
 
 
480
 
 
481
        /**
 
482
         * remove child
 
483
         *
 
484
         * @param n number of child to be removed
 
485
         */
 
486
        public Node removeChild(int n)
 
487
        {
 
488
                int numChildren = getChildCount();
 
489
 
 
490
                if (n >= numChildren)
 
491
                {
 
492
                        throw new IllegalArgumentException("Nonexistent child");
 
493
                }
 
494
                Node[] newChild = new Node[numChildren-1];
 
495
 
 
496
                for (int i = 0; i < n; i++)
 
497
                {
 
498
                        newChild[i] = child[i];
 
499
                }
 
500
 
 
501
                for (int i = n; i < numChildren-1; i++)
 
502
                {
 
503
                        newChild[i] = child[i+1];
 
504
                }
 
505
 
 
506
                Node removed = child[n];
 
507
 
 
508
                //remove parent link from removed child!
 
509
                removed.setParent(null);
 
510
 
 
511
                child = newChild;
 
512
 
 
513
                return removed;
 
514
        }
 
515
 
 
516
        /**
 
517
         * determines the height of this node and its descendants
 
518
         * from branch lengths, assuming contemporaneous tips.
 
519
         */
 
520
        public void lengths2HeightsContemp()
 
521
        {
 
522
                double largestHeight = 0.0;
 
523
 
 
524
                if (!isLeaf())
 
525
                {
 
526
                        for (int i = 0; i < getChildCount(); i++)
 
527
                        {
 
528
                                NodeUtils.lengths2Heights(getChild(i));
 
529
 
 
530
                                double newHeight =
 
531
                                        getChild(i).getNodeHeight() + getChild(i).getBranchLength();
 
532
 
 
533
                                if (newHeight > largestHeight)
 
534
                                {
 
535
                                        largestHeight = newHeight;
 
536
                                }
 
537
                        }
 
538
                }
 
539
 
 
540
                setNodeHeight(largestHeight);
 
541
        }
 
542
 
 
543
        /**
 
544
         * Sets a named attribute to the given value.
 
545
         * @param name the name of the attribute
 
546
         * @param value the value to set the attribute
 
547
         */
 
548
        public final void setAttribute(String name, Object value) {
 
549
                if (attributes == null) attributes = new Hashtable();
 
550
                attributes.put(name, value);
 
551
        }
 
552
 
 
553
        /**
 
554
         * @return the attribute with the given name or null if it doesn't exist.
 
555
         * @param name the name of the attribute.
 
556
         */
 
557
        public final Object getAttribute(String name) {
 
558
                if (attributes == null) return null;
 
559
                return attributes.get(name);
 
560
        }
 
561
 
 
562
        /**
 
563
         * @return an enumeration of the attributes that this node has or null if the
 
564
         * node has no attributes.
 
565
         */
 
566
        public final Enumeration getAttributeNames() {
 
567
                if (attributes == null) return null;
 
568
                return attributes.keys();
 
569
        }
 
570
 
 
571
        /**
 
572
         * Returns the number of children this node has.
 
573
         */
 
574
        public final int getChildCount() {
 
575
                if (child == null) return 0;
 
576
                return child.length;
 
577
        }
 
578
 
 
579
        public String toString() {
 
580
                StringWriter sw = new StringWriter();
 
581
                NodeUtils.printNH(new PrintWriter(sw), this, true, false, 0, false);
 
582
                return sw.toString();
 
583
        }
 
584
}