In [1]:
%matplotlib inline

# %install_ext https://raw.github.com/cjdrake/ipython-magic/master/gvmagic.py
%load_ext gvmagic

import os
from collections import Counter
from operator import itemgetter

import pandas as pd

from discoursegraphs import (info, print_dot, get_span, select_nodes_by_layer,
                             select_neighbors_by_layer, istoken, tokens2text)
from discoursegraphs.readwrite import ConanoDocumentGraph, RSTGraph
from discoursegraphs.readwrite.rst import get_rst_relations, get_segment_spans_from_rst_relation
from discoursegraphs.readwrite.conano import get_conano_units, get_connective
from discoursegraphs.util import TokenMapper, natural_sort_key

In [2]:
DOC_ID = 'maz-2316'
MAZ_ROOTDIR = os.path.expanduser('~/corpora/potsdam-commentary-corpus-2.0.0/')
CONANO_TESTFILE = os.path.join(MAZ_ROOTDIR, 'connectors/{}.xml'.format(DOC_ID))
RST_TESTFILE = os.path.join(MAZ_ROOTDIR, 'rst/{}.rs3'.format(DOC_ID))

In [3]:
def segment2text(docgraph, segment_node):
    return ' '.join(docgraph.get_token(tok_id)
                    for tok_id in get_span(docgraph, segment_node))

In [4]:
cdg = ConanoDocumentGraph(CONANO_TESTFILE)
rdg = RSTGraph(RST_TESTFILE)

In [5]:
rdg.merge_graphs(cdg)
merged_graph = rdg # you don't need to do this; new variable is only introduced for convenience

In [6]:
rdg_unotokenized = RSTGraph(RST_TESTFILE, tokenize=False)
#info(rdg_unotokenized)

In [7]:
#%dotstr print_dot(rdg_unotokenized)

In [8]:
connectives_only = ConanoDocumentGraph(CONANO_TESTFILE)
#info(connectives_only)
#info(merged_graph)

In [9]:
#%dotstr print_dot(merged_graph)

Connective spans


In [10]:
token_mapper = TokenMapper(merged_graph)

unit_ranges = []
for unit_id, token_ids in get_conano_units(merged_graph):
    unit_ranges.append( (unit_id,
                         get_connective(merged_graph, unit_id),
                         token_mapper.id2index[token_ids[0]],
                         token_mapper.id2index[token_ids[-1]]) )

In [11]:
pd.DataFrame(unit_ranges, columns=['unit-id', 'connective', 'start-token', 'end-token'])


Out[11]:
unit-id connective start-token end-token
0 1:ext denn 2 32
1 1:int denn 33 54
2 2:ext aber 55 63
3 2:int aber 64 76
4 4:ext obwohl 64 76
5 4:int obwohl 77 84
6 5:ext und 77 79
7 5:int und 80 84
8 7:ext obwohl 95 136
9 7:int obwohl 104 127
10 8:ext und 104 113
11 8:int und 114 127
12 11:ext deshalb 149 188
13 11:int deshalb 137 148

RST spans


In [12]:
rst_ranges = []
for dom_node_id, rel_name, token_ids in get_rst_relations(merged_graph):
    rst_ranges.append( (dom_node_id, rel_name,
                        token_mapper.id2index[token_ids[0]],
                        token_mapper.id2index[token_ids[-1]]) )

In [13]:
pd.DataFrame(rst_ranges, columns=['relation-id', 'relation-name', 'start-token', 'end-token'])


Out[13]:
relation-id relation-name start-token end-token
0 rst:16 antithesis 55 84
1 rst:17 interpretation 55 91
2 rst:14 reason 55 189
3 rst:13 conjunction 149 189
4 rst:10 evidence 137 189
5 rst:18 evidence 55 136
6 rst:5 concession 64 84
7 rst:2 evidence 2 54
8 rst:3 e-elaboration 33 54
9 rst:9 preparation 92 136
10 rst:22 joint 2 54

In [14]:
for dom_node_id in get_rst_relations(merged_graph, data=False):
    print dom_node_id, merged_graph.node[dom_node_id]['layers'], merged_graph.node[dom_node_id]['rst:segment_type'], merged_graph.node[dom_node_id].get('rst:group_type')
    for neighbor in merged_graph.neighbors(dom_node_id):
        layers = merged_graph.node[neighbor]['layers']
        if 'rst:segment' in layers or 'rst:group' in layers:
            print u"\t{0} {1}: {2}".format(neighbor,
                                       merged_graph.node[neighbor]['rst:segment_type'],
                                       segment2text(merged_graph, neighbor))
    print '\n'


rst:16 set(['rst', 'rst:group']) nucleus span
	rst:4 satellite: Dass die Aubis letztlich den Berliner Senat stürzte ,
	rst:5 nucleus: in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden -


rst:17 set(['rst', 'rst:group']) nucleus span
	rst:16 nucleus: Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden -
	rst:7 satellite: ist nur noch eine stadtgeschichtliche Fußnote .


rst:14 set(['rst', 'rst:group']) nucleus span
	rst:10 nucleus: Deshalb muss sich Wansing auch nicht vor Folgen des Verkaufs fürchten : Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist . Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .
	rst:20 satellite: Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden - ist nur noch eine stadtgeschichtliche Fußnote . Zum Beweis : Die damalige Aufsichtsratschefin Margit Spielmann wird am Samstag - obwohl sie bis heute nicht für ihre Wobra-Arbeit entlastet wurde und Schliesing noch im Vorjahr mit der Möglichkeit einer Klage gegen sie drohte - von der SPD wieder als Brandenburger Bundestagsabgeordnete nominiert .


rst:13 set(['rst', 'rst:group']) satellite multinuc
	rst:12 nucleus: Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .
	rst:11 nucleus: Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist .


rst:10 set(['rst', 'rst:segment']) nucleus None
	rst:13 satellite: Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist . Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .


rst:18 set(['rst', 'rst:group']) nucleus span
	rst:17 nucleus: Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden - ist nur noch eine stadtgeschichtliche Fußnote .
	rst:15 satellite: Zum Beweis : Die damalige Aufsichtsratschefin Margit Spielmann wird am Samstag - obwohl sie bis heute nicht für ihre Wobra-Arbeit entlastet wurde und Schliesing noch im Vorjahr mit der Möglichkeit einer Klage gegen sie drohte - von der SPD wieder als Brandenburger Bundestagsabgeordnete nominiert .


rst:5 set(['rst', 'rst:segment']) nucleus None
	rst:6 satellite: obwohl Geld verschleudert und Mieter verramscht wurden -


rst:2 set(['rst', 'rst:segment']) nucleus None
	rst:24 satellite: Denn noch heute sind die schmerzlichen Folgen jederzeit in der Stadt präsent , den die unüberlegten Wobra-Verkäufe an die Aubis auslösten .


rst:3 set(['rst', 'rst:segment']) nucleus None
	rst:23 satellite: den die unüberlegten Wobra-Verkäufe an die Aubis auslösten .


rst:9 set(['rst', 'rst:segment']) nucleus None
	rst:8 satellite: Zum Beweis :


rst:22 set(['rst', 'rst:group', 'rst:root']) nucleus multinuc
	rst:21 nucleus: Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden - ist nur noch eine stadtgeschichtliche Fußnote . Zum Beweis : Die damalige Aufsichtsratschefin Margit Spielmann wird am Samstag - obwohl sie bis heute nicht für ihre Wobra-Arbeit entlastet wurde und Schliesing noch im Vorjahr mit der Möglichkeit einer Klage gegen sie drohte - von der SPD wieder als Brandenburger Bundestagsabgeordnete nominiert . Deshalb muss sich Wansing auch nicht vor Folgen des Verkaufs fürchten : Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist . Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .
	rst:19 nucleus: Fast möchte man Andreas Wansing , den Geschäftsführer der Wobra , händeringend bitten , von seinem Plan Abstand zu nehmen , aus dem Bestand der Wobra hinaus Wohnungen zu verkaufen . Denn noch heute sind die schmerzlichen Folgen jederzeit in der Stadt präsent , den die unüberlegten Wobra-Verkäufe an die Aubis auslösten .



In [15]:
for dom_node_id in get_rst_relations(merged_graph, data=False):
    if 'rst:segment' in merged_graph.node[dom_node_id]['layers']:
        print dom_node_id, sorted([n for n in merged_graph.neighbors(dom_node_id)
                                   if istoken(merged_graph, n)], key=natural_sort_key)


rst:10 ['rst:rst:10_0', 'rst:rst:10_1', 'rst:rst:10_2', 'rst:rst:10_3', 'rst:rst:10_4', 'rst:rst:10_5', 'rst:rst:10_6', 'rst:rst:10_7', 'rst:rst:10_8', 'rst:rst:10_9', 'rst:rst:10_10', 'rst:rst:10_11']
rst:5 ['rst:rst:5_0', 'rst:rst:5_1', 'rst:rst:5_2', 'rst:rst:5_3', 'rst:rst:5_4', 'rst:rst:5_5', 'rst:rst:5_6', 'rst:rst:5_7', 'rst:rst:5_8', 'rst:rst:5_9', 'rst:rst:5_10', 'rst:rst:5_11', 'rst:rst:5_12']
rst:2 ['rst:rst:2_0', 'rst:rst:2_1', 'rst:rst:2_2', 'rst:rst:2_3', 'rst:rst:2_4', 'rst:rst:2_5', 'rst:rst:2_6', 'rst:rst:2_7', 'rst:rst:2_8', 'rst:rst:2_9', 'rst:rst:2_10', 'rst:rst:2_11', 'rst:rst:2_12', 'rst:rst:2_13', 'rst:rst:2_14', 'rst:rst:2_15', 'rst:rst:2_16', 'rst:rst:2_17', 'rst:rst:2_18', 'rst:rst:2_19', 'rst:rst:2_20', 'rst:rst:2_21', 'rst:rst:2_22', 'rst:rst:2_23', 'rst:rst:2_24', 'rst:rst:2_25', 'rst:rst:2_26', 'rst:rst:2_27', 'rst:rst:2_28', 'rst:rst:2_29', 'rst:rst:2_30']
rst:3 ['rst:rst:3_0', 'rst:rst:3_1', 'rst:rst:3_2', 'rst:rst:3_3', 'rst:rst:3_4', 'rst:rst:3_5', 'rst:rst:3_6', 'rst:rst:3_7', 'rst:rst:3_8', 'rst:rst:3_9', 'rst:rst:3_10', 'rst:rst:3_11', 'rst:rst:3_12']
rst:9 ['rst:rst:9_0', 'rst:rst:9_1', 'rst:rst:9_2', 'rst:rst:9_3', 'rst:rst:9_4', 'rst:rst:9_5', 'rst:rst:9_6', 'rst:rst:9_7', 'rst:rst:9_8', 'rst:rst:9_9', 'rst:rst:9_10', 'rst:rst:9_11', 'rst:rst:9_12', 'rst:rst:9_13', 'rst:rst:9_14', 'rst:rst:9_15', 'rst:rst:9_16', 'rst:rst:9_17', 'rst:rst:9_18', 'rst:rst:9_19', 'rst:rst:9_20', 'rst:rst:9_21', 'rst:rst:9_22', 'rst:rst:9_23', 'rst:rst:9_24', 'rst:rst:9_25', 'rst:rst:9_26', 'rst:rst:9_27', 'rst:rst:9_28', 'rst:rst:9_29', 'rst:rst:9_30', 'rst:rst:9_31', 'rst:rst:9_32', 'rst:rst:9_33', 'rst:rst:9_34', 'rst:rst:9_35', 'rst:rst:9_36', 'rst:rst:9_37', 'rst:rst:9_38', 'rst:rst:9_39', 'rst:rst:9_40', 'rst:rst:9_41']

In [17]:
for rel_id in get_rst_relations(merged_graph, data=False):
    print rel_id
    segment_spans = get_segment_spans_from_rst_relation(merged_graph, rel_id)
    for span, span_tokens in segment_spans.iteritems():
        print "\t", span, tokens2text(merged_graph, span_tokens)
    print


rst:16
	S Dass die Aubis letztlich den Berliner Senat stürzte ,
	N in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden -

rst:17
	S ist nur noch eine stadtgeschichtliche Fußnote .
	N Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden -

rst:14
	S Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden - ist nur noch eine stadtgeschichtliche Fußnote . Zum Beweis : Die damalige Aufsichtsratschefin Margit Spielmann wird am Samstag - obwohl sie bis heute nicht für ihre Wobra-Arbeit entlastet wurde und Schliesing noch im Vorjahr mit der Möglichkeit einer Klage gegen sie drohte - von der SPD wieder als Brandenburger Bundestagsabgeordnete nominiert .
	N Deshalb muss sich Wansing auch nicht vor Folgen des Verkaufs fürchten : Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist . Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .

rst:13
	N1 Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .
	N2 Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist .

rst:10
	S Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist . Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .
	N Deshalb muss sich Wansing auch nicht vor Folgen des Verkaufs fürchten :

rst:18
	S Zum Beweis : Die damalige Aufsichtsratschefin Margit Spielmann wird am Samstag - obwohl sie bis heute nicht für ihre Wobra-Arbeit entlastet wurde und Schliesing noch im Vorjahr mit der Möglichkeit einer Klage gegen sie drohte - von der SPD wieder als Brandenburger Bundestagsabgeordnete nominiert .
	N Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden - ist nur noch eine stadtgeschichtliche Fußnote .

rst:5
	S obwohl Geld verschleudert und Mieter verramscht wurden -
	N in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste -

rst:2
	S Denn noch heute sind die schmerzlichen Folgen jederzeit in der Stadt präsent , den die unüberlegten Wobra-Verkäufe an die Aubis auslösten .
	N Fast möchte man Andreas Wansing , den Geschäftsführer der Wobra , händeringend bitten , von seinem Plan Abstand zu nehmen , aus dem Bestand der Wobra hinaus Wohnungen zu verkaufen .

rst:3
	S den die unüberlegten Wobra-Verkäufe an die Aubis auslösten .
	N Denn noch heute sind die schmerzlichen Folgen jederzeit in der Stadt präsent ,

rst:9
	S Zum Beweis :
	N Die damalige Aufsichtsratschefin Margit Spielmann wird am Samstag - obwohl sie bis heute nicht für ihre Wobra-Arbeit entlastet wurde und Schliesing noch im Vorjahr mit der Möglichkeit einer Klage gegen sie drohte - von der SPD wieder als Brandenburger Bundestagsabgeordnete nominiert .

rst:22
	N1 Dass die Aubis letztlich den Berliner Senat stürzte , in Brandenburg aber kein Politiker auch nur eine Spur Verantwortung übernehmen musste - obwohl Geld verschleudert und Mieter verramscht wurden - ist nur noch eine stadtgeschichtliche Fußnote . Zum Beweis : Die damalige Aufsichtsratschefin Margit Spielmann wird am Samstag - obwohl sie bis heute nicht für ihre Wobra-Arbeit entlastet wurde und Schliesing noch im Vorjahr mit der Möglichkeit einer Klage gegen sie drohte - von der SPD wieder als Brandenburger Bundestagsabgeordnete nominiert . Deshalb muss sich Wansing auch nicht vor Folgen des Verkaufs fürchten : Zum einen ist es möglich , dass der Verkauf vernünftig vorbereitet und mit den Mietern abgesprochen ist . Zum anderen musste außer Mietern und Mitarbeitern bei der Wobra noch niemand für die Fehler des Managements und des Aufsichtsrates ernsthaft büßen .
	N2 Fast möchte man Andreas Wansing , den Geschäftsführer der Wobra , händeringend bitten , von seinem Plan Abstand zu nehmen , aus dem Bestand der Wobra hinaus Wohnungen zu verkaufen . Denn noch heute sind die schmerzlichen Folgen jederzeit in der Stadt präsent , den die unüberlegten Wobra-Verkäufe an die Aubis auslösten .


In [40]:
def get_segment_token_offsets(segment_token_list, token_map):
    """
    Parameters
    ----------
    segment_token_list : list of str
        sorted list of token IDs (i.e. the tokens
        that this segment spans)
    token_mapper : dict of (str, int)
        a map from token IDs to token indices
    
    Returns
    -------
    first_token_index : int
        index of the first token of the segment
    last_token_index : int
        index of the last token of the segment
    """
    return token_map[segment_token_list[0]], token_map[segment_token_list[-1]]

In [55]:
# for dom_node_id, rel_name, token_ids in get_rst_relations(merged_graph):
#     rst_ranges.append( (dom_node_id, rel_name,
#                         token_mapper.id2index[token_ids[0]],
#                         token_mapper.id2index[token_ids[-1]]) )

token_map = TokenMapper(merged_graph).id2index

rst_segment_ranges = []
for dom_node_id, rel_name, token_ids in get_rst_relations(merged_graph):
#     print dom_node_id
    segments = get_segment_spans_from_rst_relation(merged_graph, dom_node_id)
    for segment_pair in itertools.combinations(segments, 2):
        for seg_id in segment_pair:
            start, end = get_segment_token_offsets(segments[seg_id], token_map)
#             print '\t', dom_node_id+':'+seg_id, rel_name, start, end
            rst_segment_ranges.append( (dom_node_id+':'+seg_id, rel_name, start, end) )

In [80]:
import networkx as nx

for node_id in nx.topological_sort(merged_graph):
    if node_id in list(select_nodes_by_layer(merged_graph, layer={'rst:segment', 'rst:group'})):
        if merged_graph.node[node_id].get('rst:segment_type') != 'isolated':
            print node_id,


rst:22 rst:21 rst:19 rst:2 rst:24 rst:3 rst:23 rst:14 rst:10 rst:13 rst:12 rst:11 rst:20 rst:18 rst:15 rst:9 rst:8 rst:17 rst:7 rst:16 rst:4 rst:5 rst:6

In [77]:
merged_graph.node['rst:1']


Out[77]:
{'label': u'[i]:rst:segment:1',
 'layers': {'rst', 'rst:segment'},
 'rst:rel_name': '',
 'rst:segment_type': 'isolated',
 'rst:text': u'Ungef\xe4hrlicher Verkauf'}

In [81]:
rst_segments_df = pd.DataFrame(rst_segment_ranges, columns=['segment-id', 'rst-relation', 'start-token', 'end-token'])
rst_segments_df


Out[81]:
segment-id rst-relation start-token end-token
0 rst:16:S antithesis 55 63
1 rst:16:N antithesis 64 84
2 rst:17:S interpretation 85 91
3 rst:17:N interpretation 55 84
4 rst:14:S reason 55 136
5 rst:14:N reason 137 189
6 rst:13:N1 conjunction 167 189
7 rst:13:N2 conjunction 149 166
8 rst:10:S evidence 149 189
9 rst:10:N evidence 137 148
10 rst:18:S evidence 92 136
11 rst:18:N evidence 55 91
12 rst:5:S concession 77 84
13 rst:5:N concession 64 76
14 rst:2:S evidence 33 54
15 rst:2:N evidence 2 32
16 rst:3:S e-elaboration 46 54
17 rst:3:N e-elaboration 33 45
18 rst:9:S preparation 92 94
19 rst:9:N preparation 95 136
20 rst:22:N1 joint 55 189
21 rst:22:N2 joint 2 54

In [82]:
rst_segments_df.save?

In [ ]: