Skip to content

Commit 46cdf1a

Browse files
committed
ObjStateCC introduced, pin is implemented, basic viz works, need to restore popups
1 parent 6899535 commit 46cdf1a

File tree

6 files changed

+108
-79
lines changed

6 files changed

+108
-79
lines changed

examples/notebooks/conditional-join-w-cmp.ipynb

Lines changed: 25 additions & 8 deletions
Large diffs are not rendered by default.

examples/scripts/conditional_join-w-plots.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
with pyjviz.CB("top") as top:
1919
with pyjviz.CB("c1") as c1:
20-
c1.set_method_call_opts('conditional_join', {'obj-state-output-type': 'plot'})
2120
res1 = df1.conditional_join(df2,
2221
('id', 'id', "<"),
2322
df_columns = {'id':'df_id'},
@@ -30,12 +29,11 @@
3029

3130
with top:
3231
with pyjviz.CB("c2") as c2:
33-
c2.set_method_call_opts('conditional_join', {'obj-state-output-type': 'plot'})
3432
res2 = df1.select_columns('value_1').conditional_join(
3533
df2.select_columns('val*'),
3634
('value_1', 'value_2A', '>'),
3735
('value_1', 'value_2B', '<'),
38-
)
36+
).pin()
3937

4038
print(res2)
4139
res2.describe()

pyjviz/obj_utils.py

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,78 @@
88
from . import wb_stack
99

1010
random_id = 0
11-
def dump_obj_state(obj, pyjviz_opts = None):
11+
def dump_obj_state(obj):
1212
caller_stack_entry = wb_stack.wb_stack.get_parent_of_current_entry()
1313
stack_entry = wb_stack.wb_stack.get_top()
14-
t_obj, _ = obj_tracking.tracking_store.get_tracking_obj(obj)
14+
t_obj, obj_found = obj_tracking.tracking_store.get_tracking_obj(obj)
1515

1616
global random_id
1717
obj_state_uri = f"<ObjState#{random_id}>"; random_id += 1
18-
1918
fstriplestore.triple_store.dump_triple(obj_state_uri, "rdf:type", "<ObjState>")
2019
fstriplestore.triple_store.dump_triple(obj_state_uri, "<obj>", t_obj.uri)
2120
fstriplestore.triple_store.dump_triple(obj_state_uri, "<part-of>", caller_stack_entry.uri)
2221
fstriplestore.triple_store.dump_triple(obj_state_uri, "<version>", f'"{t_obj.last_version_num}"')
22+
t_obj.last_obj_state_uri = obj_state_uri
2323
t_obj.last_version_num += 1
2424

25-
output_type = 'head'
26-
if pyjviz_opts:
27-
key_s = 'obj-state-output-type'
28-
output_type = pyjviz_opts.get(key_s) if key_s in pyjviz_opts else 'head'
29-
25+
dump_obj_state_cc(obj_state_uri, obj, output_type = 'head')
26+
27+
return t_obj
28+
29+
def dump_obj_state_cc(obj_state_uri, obj, output_type = 'head'):
3030
if isinstance(obj, pd.DataFrame):
31-
dump_DataFrame_obj_state(obj_state_uri, obj, output_type)
31+
dump_DataFrame_obj_state_cc(obj_state_uri, obj, output_type)
3232
elif isinstance(obj, pd.Series):
33-
dump_Series_obj_state(obj_state_uri, obj, output_type)
33+
dump_Series_obj_state_cc(obj_state_uri, obj, output_type)
3434
else:
3535
raise Exception(f"unknown obj type at {obj_state_uri}")
3636

37-
t_obj.last_obj_state_uri = obj_state_uri
38-
return t_obj
37+
def dump_DataFrame_obj_state_cc(obj_state_uri, df, output_type):
38+
ts = fstriplestore.triple_store
39+
global random_id
40+
obj_state_cc_uri = f"<ObjStateCC#{random_id}>"; random_id += 1
41+
42+
ts.dump_triple(obj_state_cc_uri, "rdf:type", "<ObjStateCC>")
43+
ts.dump_triple(obj_state_cc_uri, "<obj-state>", obj_state_uri)
3944

40-
def dump_DataFrame_obj_state(obj_state_uri, df, output_type):
41-
fstriplestore.triple_store.dump_triple(obj_state_uri, "<df-shape>", f'"{df.shape}"')
4245
if output_type == 'head':
46+
ts.dump_triple(obj_state_cc_uri, "rdf:type", "<CCGlance>")
47+
ts.dump_triple(obj_state_cc_uri, "<shape>", f'"{df.shape}"')
4348
df_head_html = df.head(10).applymap(lambda x: textwrap.shorten(str(x), 50)).to_html().replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;").replace("\n", "&#10;")
44-
fstriplestore.triple_store.dump_triple(obj_state_uri, "<df-head>", '"' + df_head_html + '"')
49+
ts.dump_triple(obj_state_cc_uri, "<df-head>", '"' + df_head_html + '"')
4550
elif output_type == 'plot':
51+
ts.dump_triple(obj_state_cc_uri, "rdf:type", "<CCBasicPlot>")
52+
ts.dump_triple(obj_state_cc_uri, "<df-shape>", f'"{df.shape}"')
4653
out_fd = io.BytesIO()
4754
fig = df.plot().get_figure()
4855
fig.savefig(out_fd)
4956
#ipdb.set_trace()
5057
im_s = base64.b64encode(out_fd.getvalue()).decode('ascii')
51-
fstriplestore.triple_store.dump_triple(obj_state_uri, '<df-plot>', '"' + im_s + '"')
58+
ts.dump_triple(obj_state_cc_uri, '<plot-im>', '"' + im_s + '"')
5259
else:
5360
raise Exception(f"unknown output_type: {output_type}")
5461

5562

56-
def dump_Series_obj_state(obj_state_uri, s, output_type):
57-
fstriplestore.triple_store.dump_triple(obj_state_uri, "<df-shape>", f'"{s.shape}"')
63+
def dump_Series_obj_state_cc(obj_state_uri, s, output_type):
64+
ts = fstriplestore.triple_store
65+
global random_id
66+
obj_state_cc_uri = f"<ObjStateCC#{random_id}>"; random_id += 1
67+
68+
ts.dump_triple(obj_state_cc_uri, "rdf:type", "<ObjStateCC>")
69+
ts.dump_triple(obj_state_cc_uri, "<obj-state>", obj_state_uri)
70+
5871
if output_type == 'head':
59-
pass
72+
ts.dump_triple(obj_state_cc_uri, "rdf:type", "<CCGlance>")
73+
ts.dump_triple(obj_state_cc_uri, "<shape>", f"{len(s)}")
6074
elif output_type == 'plot':
75+
ts.dump_triple(obj_state_cc_uri, "rdf:type", "<CCBasicPlot>")
76+
ts.dump_triple(obj_state_cc_uri, "<s-size>", f"{len(s)}")
6177
out_fd = io.BytesIO()
6278
fig = s.plot().get_figure()
6379
fig.savefig(out_fd)
6480
#ipdb.set_trace()
6581
im_s = base64.b64encode(out_fd.getvalue()).decode('ascii')
66-
fstriplestore.triple_store.dump_triple(obj_state_uri, '<df-plot>', '"' + im_s + '"')
82+
ts.dump_triple(obj_state_cc_uri, '<plot-im>', '"' + im_s + '"')
6783
else:
6884
raise Exception(f"unknown output_type: {output_type}")
6985

pyjviz/pf_pandas.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from contextlib import nullcontext
99

1010
from . import obj_tracking
11+
from . import obj_utils
1112
from . import wb_stack
1213
from . import wb_stack_entries
1314

@@ -47,9 +48,7 @@ def create(method_name, method_args, method_kwargs):
4748

4849
latest_method_call = wb_stack.wb_stack.get_latest_method_call()
4950
if latest_method_call is None:
50-
method_opts = wb_stack.wb_stack.get_top().method_opts
51-
pyjviz_opts = method_opts.get(method_name) if method_name in method_opts else {}
52-
ret = wb_stack_entries.MethodCall(method_name, pyjviz_opts)
51+
ret = wb_stack_entries.MethodCall(method_name)
5352
else:
5453
ret = nullcontext()
5554

@@ -76,10 +75,19 @@ def aux_init(func, *x, **y):
7675
if 1:
7776
old_to_datetime = pd.to_datetime
7877
pd.to_datetime = lambda *x, **y: DataFrameFunc("to_datetime", old_to_datetime)(*x, **y)
79-
78+
79+
if 1:
80+
# we need those registration of pin method to make sure method call syntax work
81+
# actual pin implementation is in MethodCall handle_* methods
82+
@pf.register_series_method
83+
def pin(s: pd.Series, output_type = 'head'): return s
84+
85+
@pf.register_dataframe_method
86+
def pin(df: pd.DataFrame, output_type = 'head'): return df
87+
8088
old_describe = pd.DataFrame.describe
8189
#del pd.DataFrame.describe
82-
90+
8391
@pf.register_dataframe_method
8492
def describe(df: pd.DataFrame) -> pd.DataFrame:
8593
print("override describe")

pyjviz/viz.py

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,55 +32,37 @@ def dump_subgraph(g, cc_uri, out_fd):
3232
dump_subgraph(g, subgraph, out_fd)
3333

3434
rq = """
35-
select ?obj_state ?version ?obj_type ?obj_uuid ?df_shape ?df_head ?df_im {
35+
select ?obj_state ?version ?obj_type ?obj_uuid {
3636
?obj_state rdf:type <ObjState>; <obj> ?obj.
3737
?obj rdf:type <Obj>; <obj-type> ?obj_type; <obj-uuid> ?obj_uuid.
3838
?obj_state <part-of>+ ?sg; <version> ?version .
39-
?obj_state <df-shape> ?df_shape .
40-
optional {?obj_state <df-head> ?df_head}
41-
optional {?obj_state <df-plot> ?df_im}
4239
}
4340
"""
44-
for obj_state, version, obj_type, obj_uudi, df_shape, df_head, df_im in g.query(rq, base = fstriplestore.base_uri, initBindings = {'sg': subgraph}):
45-
if fstriplestore.triple_store.output_dir:
46-
temp_dir = os.path.join(fstriplestore.triple_store.output_dir, "tmp")
47-
with tempfile.NamedTemporaryFile(dir = temp_dir, suffix = '.html', delete = False) as temp_fp:
48-
if df_head:
49-
node_bgcolor = "#88000022"
50-
popup_size = (800, 200)
51-
temp_fp.write(df_head.toPython().replace("&lt;", "<").replace("&gt;", ">").replace("&quot;", "'").replace("&#10;", "\n").encode('ascii'))
52-
elif df_im:
53-
node_bgcolor = "#44056022"
54-
popup_size = (900, 500)
55-
temp_fp.write(("<img src='data:image/png;base64," + df_im.toPython() + "'></img>").encode('ascii'))
56-
else:
57-
node_bgcolor = "#88000022"
58-
popup_size = (800, 200)
59-
temp_fp.write('NONE'.encode('ascii'))
41+
for obj_state, version, obj_type, obj_uudi in g.query(rq, base = fstriplestore.base_uri, initBindings = {'sg': subgraph}):
42+
obj_state_cc_rq = """
43+
select ?shape {
44+
?obj_state_cc <obj-state> ?obj_state.
45+
?obj_state_cc rdf:type <CCGlance>;
46+
<shape> ?shape
47+
}
48+
"""
6049

61-
href = f"""href="javascript:
62-
/* alert(location.pathname.match(/.*\//) + '\n' + '{temp_fp.name}' + '\n' + '{fstriplestore.triple_store.output_dir}'); */
63-
{{ window.open(location.pathname.match(/.*\//) + 'tmp/' + '{os.path.basename(temp_fp.name)}', '_blank', 'width={popup_size[0]},height={popup_size[1]}'); }}
64-
"
65-
"""
66-
else:
67-
href = ""
68-
node_bgcolor = "#88000022"
69-
popup_size = (800, 200)
70-
71-
#ipdb.set_trace()
72-
print(f"""
73-
node_{uri_to_dot_id(obj_state)} [
50+
node_bgcolor = "#88000022"
51+
for shape in g.query(obj_state_cc_rq, base = fstriplestore.base_uri, initBindings = {'obj_state': obj_state}):
52+
#ipdb.set_trace()
53+
shape = shape[0]
54+
print(f"""
55+
node_{uri_to_dot_id(obj_state)} [
7456
color="{node_bgcolor}"
7557
shape = rect
7658
label = <<table border="0" cellborder="0" cellspacing="0" cellpadding="4">
77-
<tr> <td> <b>{obj_state.split('/')[-1]}</b><br/>{obj_type} {df_shape} {version}</td> </tr>
78-
</table>>
79-
{href}
59+
<tr> <td> <b>{obj_state.split('/')[-1]}</b><br/>{obj_type} {shape.toPython()} {version}</td> </tr>
60+
</table>>
8061
];
8162
8263
""", file = out_fd)
8364

65+
8466
rq = """
8567
select ?method_call_obj ?method_name ?method_display ?method_count ?method_stack_depth ?method_stack_trace {
8668
?method_call_obj rdf:type <MethodCall>;

pyjviz/wb_stack_entries.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#import ipdb
1+
import ipdb
22
import threading
33
import pandas as pd
44
import base64
@@ -15,22 +15,27 @@
1515
class CodeBlock(wb_stack.WithBlock):
1616
def __init__(self, label = None, rdf_type = "CodeBlock"):
1717
super().__init__(label = label, rdf_type = rdf_type)
18-
self.method_opts = {}
19-
20-
def set_method_call_opts(self, method_name, pyjviz_opts):
21-
self.method_opts[method_name] = pyjviz_opts
2218

2319
CB = CodeBlock
2420

2521
method_counter = 0 # NB: should be better way to cout method calls
2622
class MethodCall(wb_stack.WithBlock):
2723
def __init__(self, method_name, pyjviz_opts = {}):
2824
super().__init__(label = method_name, rdf_type = "MethodCall")
25+
self.method_name = method_name
2926
self.method_bound_args = None
3027
self.nested_call_args = []
3128
self.pyjviz_opts = pyjviz_opts
3229

33-
def handle_start_method_call(self, method_name, method_signature, method_args, method_kwargs):
30+
def handle_start_method_call(self, method_name, method_signature, method_args, method_kwargs):
31+
if method_name == 'pin':
32+
arg0_obj = method_args[0]
33+
t_obj, obj_found = obj_tracking.tracking_store.get_tracking_obj(arg0_obj)
34+
if not obj_found:
35+
t_obj = obj_utils.dump_obj_state(arg0_obj)
36+
obj_utils.dump_obj_state_cc(t_obj.last_obj_state_uri, arg0_obj, 'plot')
37+
return method_args, method_kwargs
38+
3439
all_args = method_args
3540
self.method_signature = method_signature
3641
#ipdb.set_trace()
@@ -73,11 +78,14 @@ def handle_start_method_call(self, method_name, method_signature, method_args, m
7378
return new_args, new_kwargs
7479

7580
def handle_end_method_call(self, ret):
81+
if self.method_name == 'pin':
82+
return
83+
7684
ts = fstriplestore.triple_store
7785

7886
ret_obj = ret if not ret is None else obj
7987

80-
ret_t_obj = obj_utils.dump_obj_state(ret_obj, self.pyjviz_opts)
88+
ret_t_obj = obj_utils.dump_obj_state(ret_obj)
8189
ts.dump_triple(self.uri, "<method-call-return>", ret_t_obj.last_obj_state_uri)
8290

8391
# catching nested calls values returned after method call executed

0 commit comments

Comments
 (0)