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