diff --git a/cmd/ltt.go b/cmd/ltt.go index a2acfe0..f0ed8b8 100644 --- a/cmd/ltt.go +++ b/cmd/ltt.go @@ -93,8 +93,6 @@ Image width and height can be specified (in inch) with --image-width and --image if lttoutimagefile != "none" { // Save the plot to a PNG file. - fmt.Println(font.Length(float64(lttoutimagewidth)) * vg.Inch) - fmt.Println(font.Length(float64(lttoutimageheight)) * vg.Inch) if err = p.Save(font.Length(lttoutimagewidth)*vg.Inch, font.Length(lttoutimageheight)*vg.Inch, lttoutimagefile); err != nil { io.LogError(err) return diff --git a/tree/algo.go b/tree/algo.go index 8290cdc..0de9a68 100644 --- a/tree/algo.go +++ b/tree/algo.go @@ -965,9 +965,17 @@ type LTTData struct { // LTTData describes a Lineage to Time data point func (t *Tree) LTT() (lttdata []LTTData) { var lttdatadup []LTTData + var dists []float64 + var err error // We compute distance from root to all nodes - dists := t.NodeRootDistance() + // If the field [&date=] exists, then takes it + // Otherwise, computes the distance to the root + if dists, err = t.NodeDates(); err != nil { + io.LogError(err) + dists = t.NodeRootDistance() + } + // This initializes lttdatadup = make([]LTTData, len(dists)) // Version with one point per x, already summed up diff --git a/tree/tree.go b/tree/tree.go index db8e679..302dd35 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -953,6 +953,43 @@ func (t *Tree) computeDepthUnRooted() { } } +// Get Node dates +// Returns a slice of float correspsponding to all node dates (internal and external) +// Node IDs are their index in the slice. +// If one node does not have date or a malformed date, returns an error +func (t *Tree) NodeDates() (ndates []float64, err error) { + var date float64 + var pattern *regexp.Regexp + var matches []string + + ndates = make([]float64, 0) + pattern = regexp.MustCompile(`(?i)&date="(.+)"`) + nnodes := 0 + t.PreOrder(func(cur *Node, prev *Node, e *Edge) (keep bool) { + stop := false + if cur.Id() != nnodes { + err = fmt.Errorf("node id does not correspond to postorder traversal: %d vs %d", cur.Id(), nnodes) + stop = true + } else { + for _, c := range cur.Comments() { + matches = pattern.FindStringSubmatch(c) + if len(matches) < 2 { + err = fmt.Errorf("no date found: %s", c) + stop = true + } + if date, err = strconv.ParseFloat(matches[1], 64); err != nil { + err = fmt.Errorf("one of the node date is malformed: %s", c) + stop = true + } + ndates = append(ndates, date) + } + } + nnodes += 1 + return !stop + }) + return +} + // Computes distance of all nodes to root / pseudo root. // Indices of the nodes in the rdists slice correspond to node ids func (t *Tree) NodeRootDistance() (rdists []float64) {