1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPhyloXMLTreeReader.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "vtkPhyloXMLTreeReader.h"
16
17 #include "vtkBitArray.h"
18 #include "vtkCharArray.h"
19 #include "vtkDataSetAttributes.h"
20 #include "vtkDoubleArray.h"
21 #include "vtkFieldData.h"
22 #include "vtkFloatArray.h"
23 #include "vtkInformationStringKey.h"
24 #include "vtkIntArray.h"
25 #include "vtkLongArray.h"
26 #include "vtkNew.h"
27 #include "vtkTree.h"
28 #include "vtkTreeDFSIterator.h"
29 #include "vtkInformation.h"
30 #include "vtkInformationVector.h"
31 #include "vtkMutableDirectedGraph.h"
32 #include "vtkObjectFactory.h"
33 #include "vtkShortArray.h"
34 #include "vtkSmartPointer.h"
35 #include "vtkStreamingDemandDrivenPipeline.h"
36 #include "vtkStringArray.h"
37 #include "vtkUnsignedCharArray.h"
38 #include "vtkUnsignedIntArray.h"
39 #include "vtkUnsignedLongArray.h"
40 #include "vtkUnsignedShortArray.h"
41 #include "vtkXMLDataElement.h"
42 #include "vtkXMLDataParser.h"
43
44 vtkStandardNewMacro(vtkPhyloXMLTreeReader);
45
46 //----------------------------------------------------------------------------
vtkPhyloXMLTreeReader()47 vtkPhyloXMLTreeReader::vtkPhyloXMLTreeReader()
48 {
49 vtkTree *output = vtkTree::New();
50 this->SetOutput(output);
51 // Releasing data for pipeline parallelism.
52 // Filters will know it is empty.
53 output->ReleaseData();
54 output->Delete();
55
56 this->NumberOfNodes = 0;
57 this->HasBranchColor = false;
58 }
59
60 //----------------------------------------------------------------------------
~vtkPhyloXMLTreeReader()61 vtkPhyloXMLTreeReader::~vtkPhyloXMLTreeReader()
62 {
63 }
64
65 //----------------------------------------------------------------------------
GetOutput()66 vtkTree* vtkPhyloXMLTreeReader::GetOutput()
67 {
68 return this->GetOutput(0);
69 }
70
71 //----------------------------------------------------------------------------
GetOutput(int idx)72 vtkTree* vtkPhyloXMLTreeReader::GetOutput(int idx)
73 {
74 return vtkTree::SafeDownCast(this->GetOutputDataObject(idx));
75 }
76
77 //----------------------------------------------------------------------------
SetOutput(vtkTree * output)78 void vtkPhyloXMLTreeReader::SetOutput(vtkTree *output)
79 {
80 this->GetExecutive()->SetOutputData(0, output);
81 }
82
83 //----------------------------------------------------------------------------
GetDataSetName()84 const char* vtkPhyloXMLTreeReader::GetDataSetName()
85 {
86 return "phylogeny";
87 }
88
89 //----------------------------------------------------------------------------
SetupEmptyOutput()90 void vtkPhyloXMLTreeReader::SetupEmptyOutput()
91 {
92 this->GetOutput()->Initialize();
93 }
94
95 //----------------------------------------------------------------------------
ReadXMLData()96 void vtkPhyloXMLTreeReader::ReadXMLData()
97 {
98 vtkXMLDataElement *rootElement = this->XMLParser->GetRootElement();
99 this->CountNodes(rootElement);
100 vtkNew<vtkMutableDirectedGraph> builder;
101
102 // Initialize the edge weight array
103 vtkNew<vtkDoubleArray> weights;
104 weights->SetNumberOfComponents(1);
105 weights->SetName("weight");
106 //the number of edges = number of nodes -1 for a tree
107 weights->SetNumberOfValues(this->NumberOfNodes - 1);
108 weights->FillComponent(0, 0.0);
109 builder->GetEdgeData()->AddArray(weights.GetPointer());
110
111 // Initialize the names array
112 vtkNew<vtkStringArray> names;
113 names->SetNumberOfComponents(1);
114 names->SetName("node name");
115 names->SetNumberOfValues(this->NumberOfNodes);
116 builder->GetVertexData()->AddArray(names.GetPointer());
117
118 // parse the input file to create the tree
119 this->ReadXMLElement(rootElement, builder.GetPointer(), -1);
120
121 vtkTree *output = this->GetOutput();
122 if (!output->CheckedDeepCopy(builder.GetPointer()))
123 {
124 vtkErrorMacro(<<"Edges do not create a valid tree.");
125 return;
126 }
127
128 // assign branch color from parent to child where none was specified.
129 this->PropagateBranchColor(output);
130
131 // check if our input file contained edge weight information
132 bool haveWeights = false;
133 for (vtkIdType i = 0; i < weights->GetNumberOfTuples(); ++i)
134 {
135 if (weights->GetValue(i) != 0.0)
136 {
137 haveWeights = true;
138 break;
139 }
140 }
141 if (!haveWeights)
142 {
143 return;
144 }
145
146 vtkNew<vtkDoubleArray> nodeWeights;
147 nodeWeights->SetNumberOfValues(output->GetNumberOfVertices());
148
149 //set node weights
150 vtkNew<vtkTreeDFSIterator> treeIterator;
151 treeIterator->SetStartVertex(output->GetRoot());
152 treeIterator->SetTree(output);
153 while (treeIterator->HasNext())
154 {
155 vtkIdType vertex = treeIterator->Next();
156 vtkIdType parent = output->GetParent(vertex);
157 double weight = 0.0;
158 if (parent >= 0)
159 {
160 weight = weights->GetValue(output->GetEdgeId(parent, vertex));
161 weight += nodeWeights->GetValue(parent);
162 }
163 nodeWeights->SetValue(vertex, weight);
164 }
165
166 nodeWeights->SetName("node weight");
167 output->GetVertexData()->AddArray(nodeWeights.GetPointer());
168 }
169
170 //----------------------------------------------------------------------------
CountNodes(vtkXMLDataElement * element)171 void vtkPhyloXMLTreeReader::CountNodes(vtkXMLDataElement *element)
172 {
173 if (strcmp(element->GetName(), "clade") == 0)
174 {
175 this->NumberOfNodes++;
176 }
177
178 int numNested = element->GetNumberOfNestedElements();
179 for(int i = 0; i < numNested; ++i)
180 {
181 this->CountNodes(element->GetNestedElement(i));
182 }
183 }
184
185 //----------------------------------------------------------------------------
ReadXMLElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g,vtkIdType vertex)186 void vtkPhyloXMLTreeReader::ReadXMLElement(vtkXMLDataElement *element,
187 vtkMutableDirectedGraph *g, vtkIdType vertex)
188 {
189 bool inspectNested = true;
190 if (strcmp(element->GetName(), "clade") == 0)
191 {
192 vtkIdType child = this->ReadCladeElement(element, g, vertex);
193 // update our current vertex to this newly created one.
194 vertex = child;
195 }
196
197 else if (strcmp(element->GetName(), "name") == 0)
198 {
199 this->ReadNameElement(element, g, vertex);
200 }
201 else if (strcmp(element->GetName(), "description") == 0)
202 {
203 this->ReadDescriptionElement(element, g);
204 }
205
206 else if (strcmp(element->GetName(), "property") == 0)
207 {
208 this->ReadPropertyElement(element, g, vertex);
209 }
210
211 else if (strcmp(element->GetName(), "branch_length") == 0)
212 {
213 this->ReadBranchLengthElement(element, g, vertex);
214 }
215
216 else if (strcmp(element->GetName(), "confidence") == 0)
217 {
218 this->ReadConfidenceElement(element, g, vertex);
219 }
220
221 else if (strcmp(element->GetName(), "color") == 0)
222 {
223 this->ReadColorElement(element, g, vertex);
224 inspectNested = false;
225 }
226
227 else if (strcmp(element->GetName(), "phyloxml") != 0 &&
228 strcmp(element->GetName(), "phylogeny") != 0)
229 {
230 vtkWarningMacro(<< "Unsupported PhyloXML tag encountered: "
231 << element->GetName());
232 }
233
234 if (!inspectNested)
235 {
236 return;
237 }
238
239 int numNested = element->GetNumberOfNestedElements();
240 for(int i = 0; i < numNested; ++i)
241 {
242 this->ReadXMLElement(element->GetNestedElement(i), g, vertex);
243 }
244 }
245
246 //----------------------------------------------------------------------------
ReadCladeElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g,vtkIdType parent)247 vtkIdType vtkPhyloXMLTreeReader::ReadCladeElement(vtkXMLDataElement *element,
248 vtkMutableDirectedGraph *g, vtkIdType parent)
249 {
250 // add a new vertex to the graph
251 vtkIdType vertex = -1;
252 if (parent == -1)
253 {
254 vertex = g->AddVertex();
255 }
256 else
257 {
258 vertex = g->AddChild(parent);
259 // check for branch length attribute
260 double weight = 0.0;
261 element->GetScalarAttribute("branch_length", weight);
262 g->GetEdgeData()->GetAbstractArray("weight")->SetVariantValue(
263 g->GetEdgeId(parent, vertex), vtkVariant(weight));
264 }
265
266 // set a default (blank) name for this vertex here since
267 // vtkStringArray does not support a default value.
268 g->GetVertexData()->GetAbstractArray("node name")->SetVariantValue(
269 vertex, vtkVariant(""));
270
271 return vertex;
272 }
273
274 //----------------------------------------------------------------------------
ReadNameElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g,vtkIdType vertex)275 void vtkPhyloXMLTreeReader::ReadNameElement(vtkXMLDataElement *element,
276 vtkMutableDirectedGraph *g, vtkIdType vertex)
277 {
278 std::string name = "";
279 if (element->GetCharacterData() != NULL)
280 {
281 name = this->GetTrimmedString(element->GetCharacterData());
282 }
283 // support for phylogeny-level name (as opposed to clade-level name)
284 if (vertex == -1)
285 {
286 vtkNew<vtkStringArray> treeName;
287 treeName->SetNumberOfComponents(1);
288 treeName->SetName("phylogeny.name");
289 treeName->SetNumberOfValues(1);
290 treeName->SetValue(0, name);
291 g->GetVertexData()->AddArray(treeName.GetPointer());
292 }
293 else
294 {
295 g->GetVertexData()->GetAbstractArray("node name")->SetVariantValue(
296 vertex, vtkVariant(name));
297 }
298 }
299
300 //----------------------------------------------------------------------------
ReadDescriptionElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g)301 void vtkPhyloXMLTreeReader::ReadDescriptionElement(vtkXMLDataElement *element,
302 vtkMutableDirectedGraph *g)
303 {
304 std::string description = "";
305 if (element->GetCharacterData() != NULL)
306 {
307 description = this->GetTrimmedString(element->GetCharacterData());
308 }
309 vtkNew<vtkStringArray> treeDescription;
310 treeDescription->SetNumberOfComponents(1);
311 treeDescription->SetName("phylogeny.description");
312 treeDescription->SetNumberOfValues(1);
313 treeDescription->SetValue(0, description);
314 g->GetVertexData()->AddArray(treeDescription.GetPointer());
315 }
316
317 //----------------------------------------------------------------------------
ReadPropertyElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g,vtkIdType vertex)318 void vtkPhyloXMLTreeReader::ReadPropertyElement(vtkXMLDataElement *element,
319 vtkMutableDirectedGraph *g, vtkIdType vertex)
320 {
321 const char *datatype = element->GetAttribute("datatype");
322 if (!datatype)
323 {
324 vtkErrorMacro(<<"property element is missing the datatype attribute");
325 return;
326 }
327
328 const char *ref = element->GetAttribute("ref");
329 if (!ref)
330 {
331 vtkErrorMacro(<<"property element is missing the ref attribute");
332 return;
333 }
334
335 const char *appliesTo = element->GetAttribute("applies_to");
336 if (!appliesTo)
337 {
338 vtkErrorMacro(<<"property element is missing the applies_to attribute");
339 return;
340 }
341
342 // get the name of this property from the ref tag.
343 std::string propertyName = "property.";
344 propertyName += this->GetStringAfterColon(ref);
345
346 // get the authority for this property from the ref tag
347 std::string authority = this->GetStringBeforeColon(ref);
348
349 // get what type of data will be stored in this array.
350 std::string typeOfData = this->GetStringAfterColon(datatype);
351
352 // get the value for this property as a string
353 std::string propertyValue =
354 this->GetTrimmedString(element->GetCharacterData());
355
356 // check if this property applies to a clade, or to the whole tree
357 unsigned int numValues = this->NumberOfNodes;
358 if (vertex == -1)
359 {
360 propertyName = "phylogeny." + propertyName;
361 numValues = 1;
362 vertex = 0;
363 }
364
365 if (typeOfData.compare("string") == 0 ||
366 typeOfData.compare("duration") == 0 ||
367 typeOfData.compare("dateTime") == 0 ||
368 typeOfData.compare("time") == 0 ||
369 typeOfData.compare("date") == 0 ||
370 typeOfData.compare("gYearMonth") == 0 ||
371 typeOfData.compare("gYear") == 0 ||
372 typeOfData.compare("gMonthDay") == 0 ||
373 typeOfData.compare("gDay") == 0 ||
374 typeOfData.compare("gMonth") == 0 ||
375 typeOfData.compare("anyURI") == 0 ||
376 typeOfData.compare("normalizedString") == 0 ||
377 typeOfData.compare("token") == 0 ||
378 typeOfData.compare("hexBinary") == 0 ||
379 typeOfData.compare("base64Binary") == 0)
380 {
381 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
382 {
383 vtkNew<vtkStringArray> propertyArray;
384 propertyArray->SetNumberOfComponents(1);
385 propertyArray->SetNumberOfValues(numValues);
386 propertyArray->SetName(propertyName.c_str());
387 g->GetVertexData()->AddArray(propertyArray.GetPointer());
388 }
389 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
390 vertex, vtkVariant(propertyValue));
391 }
392
393 else if (typeOfData.compare("boolean") == 0)
394 {
395 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
396 {
397 vtkNew<vtkBitArray> propertyArray;
398 propertyArray->SetNumberOfComponents(1);
399 propertyArray->SetNumberOfValues(numValues);
400 propertyArray->SetName(propertyName.c_str());
401 g->GetVertexData()->AddArray(propertyArray.GetPointer());
402 }
403 int prop = 0;
404 if (propertyValue.compare("true") == 0 ||
405 propertyValue.compare("1") == 0)
406 {
407 prop = 1;
408 }
409 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
410 vertex, vtkVariant(prop));
411 }
412
413 else if (typeOfData.compare("decimal") == 0 ||
414 typeOfData.compare("float") == 0 ||
415 typeOfData.compare("double") == 0)
416 {
417 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
418 {
419 vtkNew<vtkDoubleArray> propertyArray;
420 propertyArray->SetNumberOfComponents(1);
421 propertyArray->SetNumberOfValues(numValues);
422 propertyArray->SetName(propertyName.c_str());
423 g->GetVertexData()->AddArray(propertyArray.GetPointer());
424 }
425 double prop = strtod(propertyValue.c_str(), NULL);
426 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
427 vertex, vtkVariant(prop));
428 }
429
430 else if (typeOfData.compare("int") == 0 ||
431 typeOfData.compare("integer") == 0 ||
432 typeOfData.compare("nonPositiveInteger") == 0 ||
433 typeOfData.compare("negativeInteger") == 0)
434 {
435 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
436 {
437 vtkNew<vtkIntArray> propertyArray;
438 propertyArray->SetNumberOfComponents(1);
439 propertyArray->SetNumberOfValues(numValues);
440 propertyArray->SetName(propertyName.c_str());
441 g->GetVertexData()->AddArray(propertyArray.GetPointer());
442 }
443 int prop = strtol(propertyValue.c_str(), NULL, 0);
444 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
445 vertex, vtkVariant(prop));
446 }
447
448 else if (typeOfData.compare("long") == 0)
449 {
450 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
451 {
452 vtkNew<vtkLongArray> propertyArray;
453 propertyArray->SetNumberOfComponents(1);
454 propertyArray->SetNumberOfValues(numValues);
455 propertyArray->SetName(propertyName.c_str());
456 g->GetVertexData()->AddArray(propertyArray.GetPointer());
457 }
458 long prop = strtol(propertyValue.c_str(), NULL, 0);
459 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
460 vertex, vtkVariant(prop));
461 }
462
463 else if (typeOfData.compare("short") == 0)
464 {
465 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
466 {
467 vtkNew<vtkShortArray> propertyArray;
468 propertyArray->SetNumberOfComponents(1);
469 propertyArray->SetNumberOfValues(numValues);
470 propertyArray->SetName(propertyName.c_str());
471 g->GetVertexData()->AddArray(propertyArray.GetPointer());
472 }
473 short prop = strtol(propertyValue.c_str(), NULL, 0);
474 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
475 vertex, vtkVariant(prop));
476 }
477
478 else if (typeOfData.compare("byte") == 0)
479 {
480 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
481 {
482 vtkNew<vtkCharArray> propertyArray;
483 propertyArray->SetNumberOfComponents(1);
484 propertyArray->SetNumberOfValues(numValues);
485 propertyArray->SetName(propertyName.c_str());
486 g->GetVertexData()->AddArray(propertyArray.GetPointer());
487 }
488 char prop = strtol(propertyValue.c_str(), NULL, 0);
489 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
490 vertex, vtkVariant(prop));
491 }
492
493 else if (typeOfData.compare("nonNegativeInteger") == 0 ||
494 typeOfData.compare("positiveInteger") == 0 ||
495 typeOfData.compare("unsignedInt") == 0)
496 {
497 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
498 {
499 vtkNew<vtkUnsignedIntArray> propertyArray;
500 propertyArray->SetNumberOfComponents(1);
501 propertyArray->SetNumberOfValues(numValues);
502 propertyArray->SetName(propertyName.c_str());
503 g->GetVertexData()->AddArray(propertyArray.GetPointer());
504 }
505 unsigned int prop = strtoul(propertyValue.c_str(), NULL, 0);
506 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
507 vertex, vtkVariant(prop));
508 }
509 else if (typeOfData.compare("unsignedLong") == 0)
510 {
511 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
512 {
513 vtkNew<vtkUnsignedLongArray> propertyArray;
514 propertyArray->SetNumberOfComponents(1);
515 propertyArray->SetNumberOfValues(numValues);
516 propertyArray->SetName(propertyName.c_str());
517 g->GetVertexData()->AddArray(propertyArray.GetPointer());
518 }
519 unsigned long prop = strtoul(propertyValue.c_str(), NULL, 0);
520 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
521 vertex, vtkVariant(prop));
522 }
523 else if (typeOfData.compare("unsignedShort") == 0)
524 {
525 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
526 {
527 vtkNew<vtkUnsignedShortArray> propertyArray;
528 propertyArray->SetNumberOfComponents(1);
529 propertyArray->SetNumberOfValues(numValues);
530 propertyArray->SetName(propertyName.c_str());
531 g->GetVertexData()->AddArray(propertyArray.GetPointer());
532 }
533 unsigned short prop = strtoul(propertyValue.c_str(), NULL, 0);
534 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
535 vertex, vtkVariant(prop));
536 }
537 else if (typeOfData.compare("unsignedByte") == 0)
538 {
539 if (!g->GetVertexData()->HasArray(propertyName.c_str()))
540 {
541 vtkNew<vtkUnsignedCharArray> propertyArray;
542 propertyArray->SetNumberOfComponents(1);
543 propertyArray->SetNumberOfValues(numValues);
544 propertyArray->SetName(propertyName.c_str());
545 g->GetVertexData()->AddArray(propertyArray.GetPointer());
546 }
547 unsigned char prop = strtoul(propertyValue.c_str(), NULL, 0);
548 g->GetVertexData()->GetAbstractArray(propertyName.c_str())->SetVariantValue(
549 vertex, vtkVariant(prop));
550 }
551
552 vtkAbstractArray *propertyArray =
553 g->GetVertexData()->GetAbstractArray(propertyName.c_str());
554
555 // add annotations to this array if it was just created.
556 if (propertyArray->GetInformation()->GetNumberOfKeys() == 0)
557 {
558 // authority (required attribute)
559 vtkInformationStringKey *authorityKey =
560 new vtkInformationStringKey("authority", "vtkPhyloXMLTreeReader");
561 propertyArray->GetInformation()->Set(authorityKey, authority.c_str());
562
563 // applies_to (required attribute)
564 vtkInformationStringKey *appliesToKey =
565 new vtkInformationStringKey("applies_to", "vtkPhyloXMLTreeReader");
566 propertyArray->GetInformation()->Set(appliesToKey, appliesTo);
567
568 // unit (optional attribute)
569 const char *unit = element->GetAttribute("unit");
570 if (unit)
571 {
572 vtkInformationStringKey *unitKey =
573 new vtkInformationStringKey("unit", "vtkPhyloXMLTreeReader");
574 propertyArray->GetInformation()->Set(unitKey, unit);
575 }
576 }
577 }
578
579 //----------------------------------------------------------------------------
ReadBranchLengthElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g,vtkIdType vertex)580 void vtkPhyloXMLTreeReader::ReadBranchLengthElement(vtkXMLDataElement *element,
581 vtkMutableDirectedGraph *g, vtkIdType vertex)
582 {
583 std::string weightStr = this->GetTrimmedString(element->GetCharacterData());
584 double weight = strtod(weightStr.c_str(), NULL);
585
586 // This assumes that the vertex only has one incoming edge.
587 // We have to use GetInEdge because g does not have a GetParent()
588 // method.
589 g->GetEdgeData()->GetAbstractArray("weight")->SetVariantValue(
590 g->GetInEdge(vertex, 0).Id, vtkVariant(weight));
591 }
592
593 //----------------------------------------------------------------------------
ReadConfidenceElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g,vtkIdType vertex)594 void vtkPhyloXMLTreeReader::ReadConfidenceElement(vtkXMLDataElement *element,
595 vtkMutableDirectedGraph *g, vtkIdType vertex)
596 {
597 // get the confidence value
598 double confidence = 0.0;
599 if (element->GetCharacterData() != NULL)
600 {
601 std::string confidenceStr =
602 this->GetTrimmedString(element->GetCharacterData());
603 confidence = strtod(confidenceStr.c_str(), NULL);
604 }
605
606 // get the confidence type
607 const char *type = element->GetAttribute("type");
608
609 // support for phylogeny-level name (as opposed to clade-level name)
610 if (vertex == -1)
611 {
612 vtkNew<vtkDoubleArray> treeConfidence;
613 treeConfidence->SetNumberOfComponents(1);
614 treeConfidence->SetName("phylogeny.confidence");
615 treeConfidence->SetNumberOfValues(1);
616 treeConfidence->SetValue(0, confidence);
617
618 // add the confidence type as an Information type on this array
619 vtkInformationStringKey *key =
620 new vtkInformationStringKey("type", "vtkPhyloXMLTreeReader");
621 treeConfidence->GetInformation()->Set(key, type);
622
623 g->GetVertexData()->AddArray(treeConfidence.GetPointer());
624 }
625 else
626 {
627 if (!g->GetVertexData()->HasArray("confidence"))
628 {
629 vtkNew<vtkDoubleArray> confidenceArray;
630 confidenceArray->SetNumberOfComponents(1);
631 confidenceArray->SetNumberOfValues(this->NumberOfNodes);
632 confidenceArray->SetName("confidence");
633
634 // add the confidence type as an Information type on this array
635 vtkInformationStringKey *key =
636 new vtkInformationStringKey("type", "vtkPhyloXMLTreeReader");
637 confidenceArray->GetInformation()->Set(key, type);
638
639 g->GetVertexData()->AddArray(confidenceArray.GetPointer());
640 }
641 g->GetVertexData()->GetAbstractArray("confidence")->SetVariantValue(
642 vertex, vtkVariant(confidence));
643 }
644 }
645
646 //----------------------------------------------------------------------------
ReadColorElement(vtkXMLDataElement * element,vtkMutableDirectedGraph * g,vtkIdType vertex)647 void vtkPhyloXMLTreeReader::ReadColorElement(vtkXMLDataElement *element,
648 vtkMutableDirectedGraph *g, vtkIdType vertex)
649 {
650 // get the color values
651 unsigned char red = 0;
652 unsigned char green = 0;
653 unsigned char blue = 0;
654 int numNested = element->GetNumberOfNestedElements();
655 for(int i = 0; i < numNested; ++i)
656 {
657 vtkXMLDataElement *childElement = element->GetNestedElement(i);
658 if (childElement->GetCharacterData() == NULL)
659 {
660 continue;
661 }
662 std::string childVal =
663 this->GetTrimmedString(childElement->GetCharacterData());
664 unsigned char val = static_cast<unsigned char>(strtod(childVal.c_str(), NULL));
665 if (strcmp(childElement->GetName(), "red") == 0)
666 {
667 red = val;
668 }
669 else if (strcmp(childElement->GetName(), "green") == 0)
670 {
671 green = val;
672 }
673 else if (strcmp(childElement->GetName(), "blue") == 0)
674 {
675 blue = val;
676 }
677 }
678
679 // initialize the color array if necessary
680 if (!g->GetVertexData()->HasArray("color"))
681 {
682 vtkNew<vtkUnsignedCharArray> colorArray;
683 colorArray->SetNumberOfComponents(3);
684 colorArray->SetComponentName(0, "red");
685 colorArray->SetComponentName(1, "green");
686 colorArray->SetComponentName(2, "blue");
687 colorArray->SetNumberOfTuples(this->NumberOfNodes);
688 colorArray->SetName("color");
689 colorArray->FillComponent(0, 0);
690 colorArray->FillComponent(1, 0);
691 colorArray->FillComponent(2, 0);
692 g->GetVertexData()->AddArray(colorArray.GetPointer());
693 this->HasBranchColor = true;
694
695 // also set up an array so we can keep track of which vertices
696 // have color.
697 this->ColoredVertices = vtkSmartPointer<vtkBitArray>::New();
698 this->ColoredVertices->SetNumberOfComponents(1);
699 this->ColoredVertices->SetName("colored vertices");
700 for (int i = 0; i < this->NumberOfNodes; ++i)
701 {
702 this->ColoredVertices->InsertNextValue(0);
703 }
704 }
705
706 // store this color value in the array
707 vtkUnsignedCharArray *colorArray = vtkUnsignedCharArray::SafeDownCast(
708 g->GetVertexData()->GetAbstractArray("color"));
709 colorArray->SetTuple3(vertex, red, green, blue);
710 this->ColoredVertices->SetValue(vertex, 1);
711 }
712
713 //----------------------------------------------------------------------------
PropagateBranchColor(vtkTree * tree)714 void vtkPhyloXMLTreeReader::PropagateBranchColor(vtkTree *tree)
715 {
716 if (!this->HasBranchColor)
717 {
718 return;
719 }
720
721 vtkUnsignedCharArray *colorArray = vtkUnsignedCharArray::SafeDownCast(
722 tree->GetVertexData()->GetAbstractArray("color"));
723 if (!colorArray)
724 {
725 return;
726 }
727
728 for (vtkIdType vertex = 1; vertex < tree->GetNumberOfVertices(); ++vertex)
729 {
730 if (this->ColoredVertices->GetValue(vertex) == 0)
731 {
732 vtkIdType parent = tree->GetParent(vertex);
733 double *color = colorArray->GetTuple3(parent);
734 colorArray->SetTuple3(vertex, color[0], color[1], color[2]);
735 }
736 }
737 }
738
739 //----------------------------------------------------------------------------
GetTrimmedString(const char * input)740 std::string vtkPhyloXMLTreeReader::GetTrimmedString(const char *input)
741 {
742 std::string trimmedString = "";
743 std::string whitespace = " \t\r\n";
744 std::string untrimmed = input;
745 size_t strBegin = untrimmed.find_first_not_of(whitespace);
746 if (strBegin != std::string::npos)
747 {
748 size_t strEnd = untrimmed.find_last_not_of(whitespace);
749 trimmedString = untrimmed.substr(strBegin, strEnd - strBegin + 1);
750 }
751 return trimmedString;
752 }
753
754 //----------------------------------------------------------------------------
GetStringBeforeColon(const char * input)755 std::string vtkPhyloXMLTreeReader::GetStringBeforeColon(const char *input)
756 {
757 std::string fullStr(input);
758 size_t strEnd = fullStr.find(':');
759 std::string retStr =
760 fullStr.substr(0, strEnd);
761 return retStr;
762 }
763
764 //----------------------------------------------------------------------------
GetStringAfterColon(const char * input)765 std::string vtkPhyloXMLTreeReader::GetStringAfterColon(const char *input)
766 {
767 std::string fullStr(input);
768 size_t strBegin = fullStr.find(':') + 1;
769 std::string retStr =
770 fullStr.substr(strBegin, fullStr.size() - strBegin + 1);
771 return retStr;
772 }
773
774 //----------------------------------------------------------------------------
FillOutputPortInformation(int,vtkInformation * info)775 int vtkPhyloXMLTreeReader::FillOutputPortInformation(int, vtkInformation* info)
776 {
777 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkTree");
778 return 1;
779 }
780
781 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)782 void vtkPhyloXMLTreeReader::PrintSelf(ostream& os, vtkIndent indent)
783 {
784 this->Superclass::PrintSelf(os,indent);
785 }
786