X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FText%2FTradition%2FCollation.pm;h=ad7e7e3759732f1ad3df96f728537f78d17e4408;hb=cecbe56d2d40d98548a5d2a155fbf847ce0e7bbc;hp=fcdd1ff78959c66662fc5ac00a9481fba6afdf90;hpb=2a8127263ef278f3f14b480a12b84f9aa4f92fdc;p=scpubgit%2Fstemmatology.git diff --git a/lib/Text/Tradition/Collation.pm b/lib/Text/Tradition/Collation.pm index fcdd1ff..ad7e7e3 100644 --- a/lib/Text/Tradition/Collation.pm +++ b/lib/Text/Tradition/Collation.pm @@ -369,11 +369,23 @@ is( $c->reading('n21p0')->text, 'unto', "Reading n21p0 merged correctly" ); sub merge_readings { my $self = shift; + # Sanity check + my( $kept_obj, $del_obj, $combine, $combine_char ) = $self->_objectify_args( @_ ); + my $mergemeta = $kept_obj->is_meta; + throw( "Cannot merge meta and non-meta reading" ) + unless ( $mergemeta && $del_obj->is_meta ) + || ( !$mergemeta && !$del_obj->is_meta ); + if( $mergemeta ) { + throw( "Cannot merge with start or end node" ) + if( $kept_obj eq $self->start || $kept_obj eq $self->end + || $del_obj eq $self->start || $del_obj eq $self->end ); + } # We only need the IDs for adding paths to the graph, not the reading # objects themselves. - my( $kept, $deleted, $combine, $combine_char ) = $self->_stringify_args( @_ ); + my $kept = $kept_obj->id; + my $deleted = $del_obj->id; $self->_graphcalc_done(0); - + # The kept reading should inherit the paths and the relationships # of the deleted reading. foreach my $path ( $self->sequence->edges_at( $deleted ) ) { @@ -387,12 +399,10 @@ sub merge_readings { @wits{keys %$fwits} = values %$fwits; $self->sequence->set_edge_attributes( @vector, \%wits ); } - $self->relations->merge_readings( $kept, $deleted, $combine_char ); + $self->relations->merge_readings( $kept, $deleted, $combine ); # Do the deletion deed. if( $combine ) { - my $kept_obj = $self->reading( $kept ); - my $del_obj = $self->reading( $deleted ); my $joinstr = $combine_char; unless( defined $joinstr ) { $joinstr = '' if $kept_obj->join_next || $del_obj->join_prior; @@ -560,7 +570,8 @@ sub as_svg { throw( "Need GraphViz installed to output SVG" ) unless File::Which::which( 'dot' ); my $want_subgraph = exists $opts->{'from'} || exists $opts->{'to'}; - $self->calculate_ranks() unless( $self->_graphcalc_done || $opts->{'nocalc'} ); + $self->calculate_ranks() + unless( $self->_graphcalc_done || $opts->{'nocalc'} || !$self->linear ); if( !$self->has_cached_svg || $opts->{'recalc'} || $want_subgraph ) { my @cmd = qw/dot -Tsvg/; my( $svg, $err ); @@ -817,6 +828,7 @@ sub _path_display_label { # See if we are in a majority situation. my $maj = scalar( $self->tradition->witnesses ) * 0.6; + $maj = $maj > 5 ? $maj : 5; if( scalar keys %wits > $maj ) { unshift( @disp_ac, 'majority' ); return join( ', ', @disp_ac ); @@ -1077,6 +1089,8 @@ sub as_graphml { # serialize them. Otherwise set nval to undef so that the # key is excluded from this reading. $nval = $nval ? $n->_serialize_lexemes : undef; + } elsif( $d eq 'normal_form' && $n->normal_form eq $n->text ) { + $nval = undef; } if( $rankoffset && $d eq 'rank' && $n ne $self->start ) { # Adjust the ranks within the subgraph. @@ -1520,14 +1534,8 @@ sub calculate_ranks { # Do the rankings based on the relationship equivalence graph, starting # with the start node. - my $topo_start = $self->equivalence( $self->start->id ); - my $node_ranks = { $topo_start => 0 }; - my @curr_origin = ( $topo_start ); - # A little iterative function. - while( @curr_origin ) { - @curr_origin = _assign_rank( $self->equivalence_graph, - $node_ranks, @curr_origin ); - } + my ( $node_ranks, $rank_nodes ) = $self->relations->equivalence_ranks(); + # Transfer our rankings from the topological graph to the real one. foreach my $r ( $self->readings ) { if( defined $node_ranks->{$self->equivalence( $r->id )} ) { @@ -1557,41 +1565,6 @@ sub calculate_ranks { $self->_graphcalc_done(1); } -sub _assign_rank { - my( $graph, $node_ranks, @current_nodes ) = @_; - # Look at each of the children of @current_nodes. If all the child's - # parents have a rank, assign it the highest rank + 1 and add it to - # @next_nodes. Otherwise skip it; we will return when the highest-ranked - # parent gets a rank. - my @next_nodes; - foreach my $c ( @current_nodes ) { - warn "Current reading $c has no rank!" - unless exists $node_ranks->{$c}; - # print STDERR "Looking at child of node $c, rank " - # . $node_ranks->{$c} . "\n"; - foreach my $child ( $graph->successors( $c ) ) { - next if exists $node_ranks->{$child}; - my $highest_rank = -1; - my $skip = 0; - foreach my $parent ( $graph->predecessors( $child ) ) { - if( exists $node_ranks->{$parent} ) { - $highest_rank = $node_ranks->{$parent} - if $highest_rank <= $node_ranks->{$parent}; - } else { - $skip = 1; - last; - } - } - next if $skip; - my $c_rank = $highest_rank + 1; - # print STDERR "Assigning rank $c_rank to node $child \n"; - $node_ranks->{$child} = $c_rank; - push( @next_nodes, $child ); - } - } - return @next_nodes; -} - sub _clear_cache { my $self = shift; $self->wipe_svg if $self->has_cached_svg; @@ -1614,8 +1587,17 @@ sub flatten_ranks { next unless $rdg->has_rank; my $key = $rdg->rank . "||" . $rdg->text; if( exists $unique_rank_rdg{$key} ) { + # Make sure they don't have different grammatical forms + my $ur = $unique_rank_rdg{$key}; + if( $rdg->disambiguated && $ur->disambiguated ) { + my $rform = join( '//', map { $_->form->to_string } $rdg->lexemes ); + my $uform = join( '//', map { $_->form->to_string } $ur->lexemes ); + next unless $rform eq $uform; + } elsif( $rdg->disambiguated xor $ur->disambiguated ) { + next; + } # Combine! - # print STDERR "Combining readings at same rank: $key\n"; + #print STDERR "Combining readings at same rank: $key\n"; $changed = 1; $self->merge_readings( $unique_rank_rdg{$key}, $rdg ); # TODO see if this now makes a common point.