CollateX format for GraphML output changed; parser update
Tara L Andrews [Wed, 14 Mar 2012 14:36:16 +0000 (15:36 +0100)]
14 files changed:
lib/Text/Tradition/Analysis.pm
lib/Text/Tradition/Collation.pm
lib/Text/Tradition/Collation/RelationshipStore.pm
lib/Text/Tradition/Parser/CollateX.pm
stemmaweb/lib/stemmaweb/Controller/Stexaminer.pm
stemmaweb/root/css/relationship.css
stemmaweb/root/js/relationship.js
stemmaweb/root/src/relate.tt
t/data/Collatex-16.xml
t/stemma.t
t/text_tradition_analysis.t
t/text_tradition_collation.t
t/text_tradition_collation_relationshipstore.t
t/text_tradition_parser_collatex.t

index 8bfaf1a..fda5137 100644 (file)
@@ -56,6 +56,8 @@ is 0 (i.e. the first).
 =item * merge_types - Specify a list of relationship types, where related readings 
 should be treated as identical for the purposes of analysis.
 
+=item * exclude_type1 - Exclude those ranks whose groupings have only type-1 variants.
+
 =back
 
 =begin testing
@@ -150,7 +152,13 @@ sub run_analysis {
        my %lacunae;
        foreach my $rank ( @ranks ) {
                my $missing = [ @lacunose ];
-               push( @groups, group_variants( $tradition, $rank, $missing, \@collapse ) );
+               my $rankgroup = group_variants( $tradition, $rank, $missing, \@collapse );
+               if( $opts{'exclude_type1'} ) {
+                       # Check to see whether this is a "useful" group.
+                       my( $rdgs, $grps ) = _useful_variant( $rankgroup );
+                       next unless @$rdgs;
+               }
+               push( @groups, $rankgroup );
                $lacunae{$rank} = $missing;
        }
        $DB::single = 1;
@@ -187,8 +195,8 @@ relationships in @merge_relationship_types as equivalent.  $lacunose should
 be a reference to an array, to which the sigla of lacunose witnesses at this 
 rank will be appended.
 
-Returns two ordered lists $readings, $groups, where $readings->[$n] is attested
-by the witnesses listed in $groups->[$n].
+Returns a hash $group_readings where $rdg is attested by the witnesses listed 
+in $group_readings->{$rdg}.
 
 =cut
 
index 7c22786..68b2adf 100644 (file)
@@ -338,15 +338,15 @@ $c->flatten_ranks();
 ok( $c->reading( 'n21p0' ), "New reading exists" );
 is( scalar $c->readings, $rno, "Reading add offset by flatten_ranks" );
 
-# Combine n3 and n4
+# Combine n3 and n4 ( with his )
 $c->merge_readings( 'n3', 'n4', 1 );
 ok( !$c->reading('n4'), "Reading n4 is gone" );
 is( $c->reading('n3')->text, 'with his', "Reading n3 has both words" );
 
-# Collapse n25 and n26
-$c->merge_readings( 'n25', 'n26' );
-ok( !$c->reading('n26'), "Reading n26 is gone" );
-is( $c->reading('n25')->text, 'rood', "Reading n25 has an unchanged word" );
+# Collapse n9 and n10 ( rood / root )
+$c->merge_readings( 'n9', 'n10' );
+ok( !$c->reading('n10'), "Reading n10 is gone" );
+is( $c->reading('n9')->text, 'rood', "Reading n9 has an unchanged word" );
 
 # Combine n21 and n21p0
 my $remaining = $c->reading('n21');
@@ -1407,7 +1407,7 @@ ok( $c->has_cached_table, "Alignment table was cached" );
 is( $c->alignment_table, $table, "Cached table returned upon second call" );
 $c->calculate_ranks;
 is( $c->alignment_table, $table, "Cached table retained with no rank change" );
-$c->add_relationship( 'n9', 'n23', { 'type' => 'spelling' } );
+$c->add_relationship( 'n24', 'n23', { 'type' => 'spelling' } );
 isnt( $c->alignment_table, $table, "Alignment table changed after relationship add" );
 
 =end testing
@@ -1585,7 +1585,7 @@ my @common = $c->calculate_common_readings();
 is( scalar @common, 8, "Found correct number of common readings" );
 my @marked = sort $c->common_readings();
 is( scalar @common, 8, "All common readings got marked as such" );
-my @expected = qw/ n1 n12 n16 n19 n20 n5 n6 n7 /;
+my @expected = qw/ n1 n11 n16 n19 n20 n5 n6 n7 /;
 is_deeply( \@marked, \@expected, "Found correct list of common readings" );
 
 =end testing
@@ -1672,14 +1672,14 @@ my $t = Text::Tradition->new(
     );
 my $c = $t->collation;
 
-is( $c->common_predecessor( 'n9', 'n23' )->id, 
+is( $c->common_predecessor( 'n24', 'n23' )->id, 
     'n20', "Found correct common predecessor" );
-is( $c->common_successor( 'n9', 'n23' )->id, 
+is( $c->common_successor( 'n24', 'n23' )->id, 
     '#END#', "Found correct common successor" );
 
 is( $c->common_predecessor( 'n19', 'n17' )->id, 
     'n16', "Found correct common predecessor for readings on same path" );
-is( $c->common_successor( 'n21', 'n26' )->id, 
+is( $c->common_successor( 'n21', 'n10' )->id, 
     '#END#', "Found correct common successor for readings on same path" );
 
 =end testing
index f7d4f04..55d6943 100644 (file)
@@ -41,12 +41,12 @@ my @v1 = $c->add_relationship( 'n21', 'n22', { 'type' => 'meaning' } );
 is( scalar @v1, 1, "Added a single relationship" );
 is( $v1[0]->[0], 'n21', "Got correct node 1" );
 is( $v1[0]->[1], 'n22', "Got correct node 2" );
-my @v2 = $c->add_relationship( 'n9', 'n23', 
+my @v2 = $c->add_relationship( 'n24', 'n23', 
        { 'type' => 'spelling', 'scope' => 'global' } );
 is( scalar @v2, 2, "Added a global relationship with two instances" );
 @v1 = $c->del_relationship( 'n22', 'n21' );
 is( scalar @v1, 1, "Deleted first relationship" );
-@v2 = $c->del_relationship( 'n8', 'n13' );
+@v2 = $c->del_relationship( 'n12', 'n13' );
 is( scalar @v2, 2, "Deleted second global relationship" );
 my @v3 = $c->del_relationship( 'n1', 'n2' );
 is( scalar @v3, 0, "Nothing deleted on non-existent relationship" );
index 7191f7e..68948d5 100644 (file)
@@ -56,7 +56,7 @@ my $t = Text::Tradition->new(
     'file'  => $cxfile,
     );
 
-is( ref( $t ), 'Text::Tradition', "Parsed our own GraphML" );
+is( ref( $t ), 'Text::Tradition', "Parsed a CollateX input" );
 if( $t ) {
     is( scalar $t->collation->readings, 26, "Collation has all readings" );
     is( scalar $t->collation->paths, 32, "Collation has all paths" );
@@ -66,7 +66,7 @@ if( $t ) {
     my $transposed = $t->collation->reading( 'n15' );
     my @related = $transposed->related_readings;
     is( scalar @related, 1, "Reading links to transposed version" );
-    is( $related[0]->id, 'n17', "Correct transposition link" );
+    is( $related[0]->id, 'n18', "Correct transposition link" );
 }
 
 =end testing
@@ -74,8 +74,9 @@ if( $t ) {
 =cut
 
 my $IDKEY = 'number';
-my $CONTENTKEY = 'token';
-my $TRANSKEY = 'identical';
+my $CONTENTKEY = 'tokens';
+my $EDGETYPEKEY = 'type';
+my $WITKEY = 'witnesses';
 
 sub parse {
     my( $tradition, $opts ) = @_;
@@ -83,78 +84,58 @@ sub parse {
     my $collation = $tradition->collation;
 
        # First add the readings to the graph.
-    my $extra_data = {}; # Keep track of info to be processed after all
-                         # nodes have been created
+       ## Assume the start node has no text and id 0, and the end node has
+       ## no text and ID [number of nodes] - 1.
+    my $endnode = scalar @{$graph_data->{'nodes'}} - 1;
     foreach my $n ( @{$graph_data->{'nodes'}} ) {
         unless( defined $n->{$IDKEY} && defined $n->{$CONTENTKEY} ) {
-            warn "Did not find an ID or token for graph node, can't add it";
+               if( defined $n->{$IDKEY} && $n->{$IDKEY} == 0 ) {
+                       # It's the start node.
+                       $n->{$IDKEY} = $collation->start->id;
+               } elsif ( defined $n->{$IDKEY} && $n->{$IDKEY} == $endnode ) {
+                       # It's the end node.
+                       $n->{$IDKEY} = $collation->end->id;
+               } else {
+                       # Something is probably wrong.
+                               warn "Did not find an ID or token for graph node, can't add it";
+               } 
             next;
         }
-        my %node_data = %$n;
+        # Node ID should be an XML name, so prepend an 'n' if necessary.
+        if( $n->{$IDKEY} =~ /^\d/ ) {
+                       $n->{$IDKEY} = 'n' . $n->{$IDKEY};
+               }
+               # Create the reading.
         my $gnode_args = { 
-               'id' => delete $node_data{$IDKEY},
-               'text' => delete $node_data{$CONTENTKEY},
+               'id' => $n->{$IDKEY},
+               'text' => $n->{$CONTENTKEY},
         };
         my $gnode = $collation->add_reading( $gnode_args );
-
-        # Whatever is left is extra info to be processed later,
-        # e.g. a transposition link.
-        if( keys %node_data ) {
-            $extra_data->{$gnode->id} = \%node_data;
-        }
     }
         
     # Now add the path edges.
     foreach my $e ( @{$graph_data->{'edges'}} ) {
-        my %edge_data = %$e;
-        my $from = delete $edge_data{'source'};
-        my $to = delete $edge_data{'target'};
-
-        # In CollateX, we have a distinct witness data ID per witness,
-        # so that we can have multiple witnesses per edge.  We want to
-        # translate this to one witness per edge in our own
-        # representation.
-        foreach my $ekey ( keys %edge_data ) {
-            my $wit = $edge_data{$ekey};
-            # Create the witness object if it does not yet exist.
-            unless( $tradition->witness( $wit ) ) {
-                $tradition->add_witness( 'sigil' => $wit );
-            }
-            $collation->add_path( $from->{$IDKEY}, $to->{$IDKEY}, $wit );
+        my $from = $e->{'source'};
+        my $to = $e->{'target'};
+        
+        ## Edge data keys are ID (which we don't need), witnesses, and type.
+        ## Type can be 'path' or 'relationship'; 
+        ## witnesses is a comma-separated list.
+               if( $e->{$EDGETYPEKEY} eq 'path' ) {
+                       ## Add the path for each witness listesd.
+            # Create the witness objects if they does not yet exist.
+            foreach my $wit ( split( /, /, $e->{$WITKEY} ) ) {
+                               unless( $tradition->witness( $wit ) ) {
+                                       $tradition->add_witness( 'sigil' => $wit );
+                               }
+                               $collation->add_path( $from->{$IDKEY}, $to->{$IDKEY}, $wit );
+                       }
+        } else { # type 'relationship'
+               $collation->add_relationship( $from->{$IDKEY}, $to->{$IDKEY},
+                       { 'type' => 'transposition' } );
         }
     }
 
-    # Process the extra node data if it exists.
-    foreach my $nodeid ( keys %$extra_data ) {
-        my $ed = $extra_data->{$nodeid};
-        if( exists $ed->{$TRANSKEY} ) {
-            my $tn_reading = $collation->reading( $nodeid );
-            my $main_reading = $collation->reading( $ed->{$TRANSKEY} );
-            if( $collation->linear ) {
-                $collation->add_relationship( $tn_reading, $main_reading,
-                       { type => 'transposition' } );
-            } else {
-                $collation->merge_readings( $main_reading, $tn_reading );
-            }
-        } # else we don't have any other tags to process yet.
-    }
-
-    # Find the beginning and end nodes of the graph.  The beginning node
-    # has no incoming edges; the end node has no outgoing edges.
-    my( $begin_node, $end_node );
-    my @starts = $collation->sequence->source_vertices();
-    my @ends = $collation->sequence->sink_vertices();
-    if( @starts != 1 ) {
-       warn "Found more or less than one start vertex: @starts";
-    } else {
-       $collation->merge_readings( $collation->start, @starts );
-    }
-    if( @ends != 1 )  {
-       warn "Found more or less than one end vertex: @ends";
-    } else {
-       $collation->merge_readings( $collation->end, @ends );
-    }
-    
     # Rank the readings.
     $collation->calculate_common_readings(); # will implicitly rank
 
index 1449ad2..cb9990f 100644 (file)
@@ -37,7 +37,7 @@ sub index :Path :Args(1) {
                $c->stash->{text_title} = $tradition->name;
                $c->stash->{template} = 'stexaminer.tt'; 
                # TODO Run the analysis as AJAX from the loaded page.
-               my $t = run_analysis( $tradition );
+               my $t = run_analysis( $tradition, 'exclude_type1' => 1 );
                # Stringify the reading groups
                foreach my $loc ( @{$t->{'variants'}} ) {
                        my $mst = wit_stringify( $loc->{'missing'} );
index 0d85213..e2e2f25 100644 (file)
@@ -74,6 +74,15 @@ span.apimore {
     padding-top: 5px;
     padding-bottom: 5px;    
 }
+#loading_overlay {
+       display: none;
+       position: absolute;
+       height: 500px;
+       width: 89%;
+       z-index: 2;
+       opacity: 0.7;
+       background-color: #c5c5c5;
+}
 #dialog_overlay {
     display: none;
     position: absolute;
index 414b78c..64bd041 100644 (file)
@@ -21,6 +21,8 @@ function getRelationshipURL() {
 }
 
 function svgEnlargementLoaded() {
+       //Give some visual evidence that we are working
+       $('#loading_overlay').show();
     //Set viewbox widht and height to widht and height of $('#svgenlargement svg').
     //This is essential to make sure zooming and panning works properly.
     $('#svgenlargement ellipse').attr( {stroke:'green', fill:'#b3f36d'} );
@@ -42,6 +44,7 @@ function svgEnlargementLoaded() {
     //used to calculate min and max zoom level:
     start_element_height = $("#svgenlargement .node title:contains('#START#')").siblings('ellipse')[0].getBBox().height;
     add_relations();
+    // $('#loading_overlay').hide();
 }
 
 function add_relations() {
index 72ea8e1..07b9b0a 100644 (file)
@@ -19,6 +19,7 @@ $(function() {
        </div>
 
        <div id="enlargement_container">        
+               <div id="loading_overlay"></div>
                <div id="enlargement">
                <div id="svgenlargement" style="height: 500px;"></div>
                </div>
index 7554174..869d665 100644 (file)
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
-    <key attr.name="number" attr.type="int" for="node" id="d1"/>
-    <key attr.name="token" attr.type="string" for="node" id="d0"/>
-    <key attr.name="identical" attr.type="string" for="node" id="d2"/>
-    <key attr.name="A" attr.type="string" for="edge" id="w0"/>
-    <key attr.name="B" attr.type="string" for="edge" id="w1"/>
-    <key attr.name="C" attr.type="string" for="edge" id="w2"/>
-    <graph edgedefault="directed" id="g0" parse.edgeids="canonical" parse.edges="32" parse.nodeids="canonical" parse.nodes="26" parse.order="nodesfirst">
+<?xml version="1.0" ?>
+<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
+    xmlns:xsi="http://www.C.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
+    <key id="d0" for="node" attr.name="number" attr.type="int"/>
+    <key id="d1" for="node" attr.name="tokens" attr.type="string"/>
+    <key id="d2" for="edge" attr.name="number" attr.type="int"/>
+    <key id="d3" for="edge" attr.name="type" attr.type="string"/>
+    <key id="d4" for="edge" attr.name="witnesses" attr.type="string"/>
+    <graph id="g0" edgedefault="directed" parse.nodeids="canonical" parse.edgeids="canonical"
+        parse.order="nodesfirst">
         <node id="n0">
-            <data key="d0">#</data>
-            <data key="d1">n0</data>
+            <data key="d0">0</data>
+            <data key="d1"/>
         </node>
         <node id="n1">
-            <data key="d0">when</data>
-            <data key="d1">n1</data>
+            <data key="d0">1</data>
+            <data key="d1">when</data>
         </node>
         <node id="n2">
-            <data key="d0">april</data>
-            <data key="d1">n2</data>
+            <data key="d0">2</data>
+            <data key="d1">april</data>
         </node>
         <node id="n3">
-            <data key="d0">with</data>
-            <data key="d1">n3</data>
+            <data key="d0">3</data>
+            <data key="d1">with</data>
         </node>
         <node id="n4">
-            <data key="d0">his</data>
-            <data key="d1">n4</data>
+            <data key="d0">4</data>
+            <data key="d1">his</data>
         </node>
         <node id="n5">
-            <data key="d0">showers</data>
-            <data key="d1">n5</data>
+            <data key="d0">5</data>
+            <data key="d1">showers</data>
         </node>
         <node id="n6">
-            <data key="d0">sweet</data>
-            <data key="d1">n6</data>
+            <data key="d0">6</data>
+            <data key="d1">sweet</data>
         </node>
         <node id="n7">
-            <data key="d0">with</data>
-            <data key="d1">n7</data>
-        </node>
-       <node id="n8">
-           <data key="d0">teh</data>
-           <data key="d1">n8</data>
-       </node>
-       <node id="n9">
-           <data key="d0">teh</data>
-           <data key="d1">n9</data>
-       </node>
+            <data key="d0">7</data>
+            <data key="d1">with</data>
+        </node>
+        <node id="n8">
+            <data key="d0">8</data>
+            <data key="d1">april</data>
+        </node>
+        <node id="n9">
+            <data key="d0">11</data>
+            <data key="d1">fruit</data>
+        </node>
+        <node id="n10">
+            <data key="d0">12</data>
+            <data key="d1">the</data>
+        </node>
         <node id="n11">
-            <data key="d0">april</data>
-            <data key="d1">n11</data>
-            <data key="d2">n2</data>
+            <data key="d0">13</data>
+            <data key="d1">teh</data>
         </node>
         <node id="n12">
-            <data key="d0">fruit</data>
-            <data key="d1">n12</data>
+            <data key="d0">14</data>
+            <data key="d1">march</data>
         </node>
         <node id="n13">
-            <data key="d0">the</data>
-            <data key="d1">n13</data>
+            <data key="d0">15</data>
+            <data key="d1">drought</data>
         </node>
         <node id="n14">
-            <data key="d0">drought</data>
-            <data key="d1">n14</data>
+            <data key="d0">16</data>
+            <data key="d1">of</data>
         </node>
         <node id="n15">
-            <data key="d0">march</data>
-            <data key="d1">n15</data>
-            <data key="d2">n17</data>
+            <data key="d0">17</data>
+            <data key="d1">march</data>
         </node>
         <node id="n16">
-            <data key="d0">of</data>
-            <data key="d1">n16</data>
+            <data key="d0">18</data>
+            <data key="d1">drought</data>
         </node>
         <node id="n17">
-            <data key="d0">march</data>
-            <data key="d1">n17</data>
+            <data key="d0">19</data>
+            <data key="d1">has</data>
         </node>
         <node id="n18">
-            <data key="d0">drought</data>
-            <data key="d1">n18</data>
-            <data key="d2">n14</data>
+            <data key="d0">20</data>
+            <data key="d1">pierced</data>
         </node>
         <node id="n19">
-            <data key="d0">has</data>
-            <data key="d1">n19</data>
+            <data key="d0">21</data>
+            <data key="d1">unto</data>
         </node>
         <node id="n20">
-            <data key="d0">pierced</data>
-            <data key="d1">n20</data>
+            <data key="d0">22</data>
+            <data key="d1">to</data>
         </node>
         <node id="n21">
-            <data key="d0">unto</data>
-            <data key="d1">n21</data>
+            <data key="d0">23</data>
+            <data key="d1">teh</data>
         </node>
         <node id="n22">
-            <data key="d0">to</data>
-            <data key="d1">n22</data>
+            <data key="d0">24</data>
+            <data key="d1">the</data>
         </node>
         <node id="n23">
-            <data key="d0">the</data>
-            <data key="d1">n23</data>
+            <data key="d0">9</data>
+            <data key="d1">rood</data>
         </node>
-        <node id="n25">
-            <data key="d0">rood</data>
-            <data key="d1">n25</data>
-        </node>
-        <node id="n26">
-            <data key="d0">root</data>
-            <data key="d1">n26</data>
+        <node id="n24">
+            <data key="d0">10</data>
+            <data key="d1">root</data>
         </node>
-        <node id="n27">
-            <data key="d0">#</data>
-            <data key="d1">n27</data>
+        <node id="n25">
+            <data key="d0">25</data>
+            <data key="d1"/>
         </node>
         <edge id="e0" source="n0" target="n1">
-            <data key="w0">A</data>
-            <data key="w2">C</data>
-            <data key="w1">B</data>
+            <data key="d2">0</data>
+            <data key="d3">path</data>
+            <data key="d4">A, B, C</data>
         </edge>
         <edge id="e1" source="n1" target="n2">
-            <data key="w0">A</data>
+            <data key="d2">1</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e2" source="n2" target="n3">
-            <data key="w0">A</data>
+        <edge id="e2" source="n1" target="n5">
+            <data key="d2">2</data>
+            <data key="d3">path</data>
+            <data key="d4">B, C</data>
         </edge>
-        <edge id="e3" source="n3" target="n4">
-            <data key="w0">A</data>
+        <edge id="e3" source="n2" target="n3">
+            <data key="d2">3</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e4" source="n4" target="n5">
-            <data key="w0">A</data>
+        <edge id="e4" source="n8" target="n9">
+            <data key="d2">4</data>
+            <data key="d3">path</data>
+            <data key="d4">B, C</data>
         </edge>
         <edge id="e5" source="n5" target="n6">
-            <data key="w0">A</data>
-            <data key="w1">B</data>
-            <data key="w2">C</data>
+            <data key="d2">5</data>
+            <data key="d3">path</data>
+            <data key="d4">A, B, C</data>
+        </edge>
+        <edge id="e6" source="n3" target="n4">
+            <data key="d2">6</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
+        </edge>
+        <edge id="e7" source="n9" target="n10">
+            <data key="d2">7</data>
+            <data key="d3">path</data>
+            <data key="d4">A, B</data>
+        </edge>
+        <edge id="e8" source="n9" target="n11">
+            <data key="d2">8</data>
+            <data key="d3">path</data>
+            <data key="d4">C</data>
+        </edge>
+        <edge id="e9" source="n6" target="n7">
+            <data key="d2">9</data>
+            <data key="d3">path</data>
+            <data key="d4">A, B, C</data>
+        </edge>
+        <edge id="e10" source="n7" target="n8">
+            <data key="d2">10</data>
+            <data key="d3">path</data>
+            <data key="d4">B, C</data>
+        </edge>
+        <edge id="e11" source="n10" target="n13">
+            <data key="d2">11</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e6" source="n6" target="n7">
-            <data key="w0">A</data>
-            <data key="w1">B</data>
-            <data key="w2">C</data>
+        <edge id="e12" source="n10" target="n12">
+            <data key="d2">12</data>
+            <data key="d3">path</data>
+            <data key="d4">B</data>
         </edge>
-        <edge id="e7" source="n1" target="n5">
-            <data key="w2">C</data>
-            <data key="w1">B</data>
+        <edge id="e13" source="n11" target="n13">
+            <data key="d2">13</data>
+            <data key="d3">path</data>
+            <data key="d4">C</data>
         </edge>
-       <edge id="e8" source="n12" target="n8">
-            <data key="w2">C</data>
-       </edge>
-       <edge id="e9" source="n8" target="n14">
-            <data key="w2">C</data>
-       </edge>
-        <edge id="e10" source="n7" target="n11">
-            <data key="w2">C</data>
-            <data key="w1">B</data>
+        <edge id="e14" source="n7" target="n9">
+            <data key="d2">14</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e11" source="n7" target="n12">
-            <data key="w0">A</data>
+        <edge id="e15" source="n3" target="n4">
+            <data key="d2">15</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e12" source="n11" target="n12">
-            <data key="w2">C</data>
-            <data key="w1">B</data>
+        <edge id="e16" source="n13" target="n14">
+            <data key="d2">16</data>
+            <data key="d3">path</data>
+            <data key="d4">A, C</data>
         </edge>
-        <edge id="e13" source="n12" target="n13">
-            <data key="w0">A</data>
-            <data key="w1">B</data>
+        <edge id="e17" source="n12" target="n14">
+            <data key="d2">17</data>
+            <data key="d3">path</data>
+            <data key="d4">B</data>
         </edge>
-        <edge id="e14" source="n13" target="n14">
-            <data key="w0">A</data>
+        <edge id="e18" source="n4" target="n5">
+            <data key="d2">18</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e15" source="n13" target="n15">
-            <data key="w1">B</data>
+        <edge id="e19" source="n14" target="n15">
+            <data key="d2">19</data>
+            <data key="d3">path</data>
+            <data key="d4">A, C</data>
         </edge>
-        <edge id="e16" source="n14" target="n16">
-            <data key="w0">A</data>
-            <data key="w2">C</data>
+        <edge id="e20" source="n14" target="n16">
+            <data key="d2">20</data>
+            <data key="d3">path</data>
+            <data key="d4">B</data>
         </edge>
-        <edge id="e17" source="n15" target="n16">
-            <data key="w1">B</data>
+        <edge id="e22" source="n15" target="n17">
+            <data key="d2">22</data>
+            <data key="d3">path</data>
+            <data key="d4">A, C</data>
         </edge>
-        <edge id="e18" source="n16" target="n17">
-            <data key="w0">A</data>
-            <data key="w2">C</data>
+        <edge id="e23" source="n16" target="n17">
+            <data key="d2">23</data>
+            <data key="d3">path</data>
+            <data key="d4">B</data>
         </edge>
-        <edge id="e19" source="n16" target="n18">
-            <data key="w1">B</data>
+        <edge id="e24" source="n17" target="n18">
+            <data key="d2">24</data>
+            <data key="d3">path</data>
+            <data key="d4">A, B, C</data>
         </edge>
-        <edge id="e20" source="n17" target="n19">
-            <data key="w0">A</data>
-            <data key="w2">C</data>
+        <edge id="e25" source="n18" target="n19">
+            <data key="d2">25</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e21" source="n18" target="n19">
-            <data key="w1">B</data>
+        <edge id="e26" source="n18" target="n20">
+            <data key="d2">26</data>
+            <data key="d3">path</data>
+            <data key="d4">B</data>
         </edge>
-        <edge id="e22" source="n19" target="n20">
-            <data key="w0">A</data>
-            <data key="w2">C</data>
-            <data key="w1">B</data>
+        <edge id="e27" source="n18" target="n21">
+            <data key="d2">27</data>
+            <data key="d3">path</data>
+            <data key="d4">C</data>
         </edge>
-        <edge id="e23" source="n20" target="n21">
-            <data key="w0">A</data>
+        <edge id="e28" source="n19" target="n22">
+            <data key="d2">28</data>
+            <data key="d3">path</data>
+            <data key="d4">A</data>
         </edge>
-        <edge id="e24" source="n20" target="n22">
-            <data key="w1">B</data>
+        <edge id="e29" source="n20" target="n22">
+            <data key="d2">29</data>
+            <data key="d3">path</data>
+            <data key="d4">B</data>
         </edge>
-        <edge id="e25" source="n21" target="n23">
-            <data key="w0">A</data>
+        <edge id="e30" source="n21" target="n23">
+            <data key="d2">30</data>
+            <data key="d3">path</data>
+            <data key="d4">C</data>
         </edge>
-        <edge id="e26" source="n22" target="n23">
-            <data key="w1">B</data>
+        <edge id="e31" source="n22" target="n24">
+            <data key="d2">31</data>
+            <data key="d3">path</data>
+            <data key="d4">A, B</data>
         </edge>
-        <edge id="e27" source="n20" target="n9">
-            <data key="w2">C</data>
+        <edge id="e32" source="n23" target="n25">
+            <data key="d2">32</data>
+            <data key="d3">path</data>
+            <data key="d4">C</data>
         </edge>
-        <edge id="e28" source="n9" target="n25">
-            <data key="w2">C</data>
+        <edge id="e33" source="n24" target="n25">
+            <data key="d2">33</data>
+            <data key="d3">path</data>
+            <data key="d4">A, B</data>
         </edge>
-        <edge id="e29" source="n23" target="n26">
-            <data key="w0">A</data>
-            <data key="w1">B</data>
+        <edge id="e36" source="n8" target="n2">
+            <data key="d2">36</data>
+            <data key="d3">transposition</data>
         </edge>
-        <edge id="e30" source="n26" target="n27">
-            <data key="w0">A</data>
-            <data key="w1">B</data>
+        <edge id="e37" source="n13" target="n16">
+            <data key="d2">37</data>
+            <data key="d3">transposition</data>
         </edge>
-        <edge id="e31" source="n25" target="n27">
-            <data key="w2">C</data>
+        <edge id="e38" source="n15" target="n12">
+            <data key="d2">38</data>
+            <data key="d3">transposition</data>
         </edge>
     </graph>
 </graphml>
-
index 697d0d2..404b686 100644 (file)
@@ -18,9 +18,9 @@ my $tradition = Text::Tradition->new(
     );
 # Set up some relationships
 my $c = $tradition->collation;
-$c->add_relationship( 'n25', 'n26', { 'type' => 'spelling' } );
-$c->add_relationship( 'n9', 'n23', { 'type' => 'spelling' } );
-$c->add_relationship( 'n8', 'n13', { 'type' => 'spelling' } );
+$c->add_relationship( 'n23', 'n24', { 'type' => 'spelling' } );
+$c->add_relationship( 'n9', 'n10', { 'type' => 'spelling' } );
+$c->add_relationship( 'n12', 'n13', { 'type' => 'spelling' } );
 $c->calculate_ranks();
 
 my $stemma = $tradition->add_stemma( dotfile => 't/data/simple.dot' );
index 8340d4c..74428ef 100644 (file)
@@ -55,8 +55,7 @@ foreach my $row ( @{$data->{'variants'}} ) {
        unless( exists $expected_genealogical{$row->{'id'}} ) {
                $expected_genealogical{$row->{'id'}} = 1;
        }
-       my $gen_bool = $row->{'genealogical'} ? 1 : 0;
-       is( $gen_bool, $expected_genealogical{$row->{'id'}}, 
+       is( $row->{'genealogical'}, $expected_genealogical{$row->{'id'}}, 
                "Got correct genealogical flag for row " . $row->{'id'} );
 }
 is( $data->{'variant_count'}, 58, "Got right total variant number" );
index 0dcb081..8c29c02 100644 (file)
@@ -30,15 +30,15 @@ $c->flatten_ranks();
 ok( $c->reading( 'n21p0' ), "New reading exists" );
 is( scalar $c->readings, $rno, "Reading add offset by flatten_ranks" );
 
-# Combine n3 and n4
+# Combine n3 and n4 ( with his )
 $c->merge_readings( 'n3', 'n4', 1 );
 ok( !$c->reading('n4'), "Reading n4 is gone" );
 is( $c->reading('n3')->text, 'with his', "Reading n3 has both words" );
 
-# Collapse n25 and n26
-$c->merge_readings( 'n25', 'n26' );
-ok( !$c->reading('n26'), "Reading n26 is gone" );
-is( $c->reading('n25')->text, 'rood', "Reading n25 has an unchanged word" );
+# Collapse n9 and n10 ( rood / root )
+$c->merge_readings( 'n9', 'n10' );
+ok( !$c->reading('n10'), "Reading n10 is gone" );
+is( $c->reading('n9')->text, 'rood', "Reading n9 has an unchanged word" );
 
 # Combine n21 and n21p0
 my $remaining = $c->reading('n21');
@@ -106,7 +106,7 @@ ok( $c->has_cached_table, "Alignment table was cached" );
 is( $c->alignment_table, $table, "Cached table returned upon second call" );
 $c->calculate_ranks;
 is( $c->alignment_table, $table, "Cached table retained with no rank change" );
-$c->add_relationship( 'n9', 'n23', { 'type' => 'spelling' } );
+$c->add_relationship( 'n24', 'n23', { 'type' => 'spelling' } );
 isnt( $c->alignment_table, $table, "Alignment table changed after relationship add" );
 }
 
@@ -128,7 +128,7 @@ my @common = $c->calculate_common_readings();
 is( scalar @common, 8, "Found correct number of common readings" );
 my @marked = sort $c->common_readings();
 is( scalar @common, 8, "All common readings got marked as such" );
-my @expected = qw/ n1 n12 n16 n19 n20 n5 n6 n7 /;
+my @expected = qw/ n1 n11 n16 n19 n20 n5 n6 n7 /;
 is_deeply( \@marked, \@expected, "Found correct list of common readings" );
 }
 
@@ -146,14 +146,14 @@ my $t = Text::Tradition->new(
     );
 my $c = $t->collation;
 
-is( $c->common_predecessor( 'n9', 'n23' )->id, 
+is( $c->common_predecessor( 'n24', 'n23' )->id, 
     'n20', "Found correct common predecessor" );
-is( $c->common_successor( 'n9', 'n23' )->id, 
+is( $c->common_successor( 'n24', 'n23' )->id, 
     '#END#', "Found correct common successor" );
 
 is( $c->common_predecessor( 'n19', 'n17' )->id, 
     'n16', "Found correct common predecessor for readings on same path" );
-is( $c->common_successor( 'n21', 'n26' )->id, 
+is( $c->common_successor( 'n21', 'n10' )->id, 
     '#END#', "Found correct common successor for readings on same path" );
 }
 
index 9f9ed65..6b9db2b 100644 (file)
@@ -27,12 +27,12 @@ my @v1 = $c->add_relationship( 'n21', 'n22', { 'type' => 'meaning' } );
 is( scalar @v1, 1, "Added a single relationship" );
 is( $v1[0]->[0], 'n21', "Got correct node 1" );
 is( $v1[0]->[1], 'n22', "Got correct node 2" );
-my @v2 = $c->add_relationship( 'n9', 'n23', 
+my @v2 = $c->add_relationship( 'n24', 'n23', 
        { 'type' => 'spelling', 'scope' => 'global' } );
 is( scalar @v2, 2, "Added a global relationship with two instances" );
 @v1 = $c->del_relationship( 'n22', 'n21' );
 is( scalar @v1, 1, "Deleted first relationship" );
-@v2 = $c->del_relationship( 'n8', 'n13' );
+@v2 = $c->del_relationship( 'n12', 'n13' );
 is( scalar @v2, 2, "Deleted second global relationship" );
 my @v3 = $c->del_relationship( 'n1', 'n2' );
 is( scalar @v3, 0, "Nothing deleted on non-existent relationship" );
index 733cf1b..3b95ecd 100644 (file)
@@ -20,7 +20,7 @@ my $t = Text::Tradition->new(
     'file'  => $cxfile,
     );
 
-is( ref( $t ), 'Text::Tradition', "Parsed our own GraphML" );
+is( ref( $t ), 'Text::Tradition', "Parsed a CollateX input" );
 if( $t ) {
     is( scalar $t->collation->readings, 26, "Collation has all readings" );
     is( scalar $t->collation->paths, 32, "Collation has all paths" );
@@ -30,7 +30,7 @@ if( $t ) {
     my $transposed = $t->collation->reading( 'n15' );
     my @related = $transposed->related_readings;
     is( scalar @related, 1, "Reading links to transposed version" );
-    is( $related[0]->id, 'n17', "Correct transposition link" );
+    is( $related[0]->id, 'n18', "Correct transposition link" );
 }
 }