Skip to main content

Scratch

In [1]:
%run prelude.ipy
In [21]:
code = data.hansen_2012.program_code("overload", "plusmixed")
aois = aoi.code_to_aois(code, filename="test.py", offset=(10, 10))
aois.to_csv("/home/hansenm/Fall 2013/Research/eyecode/models/mr_bits/programs/overload_plusmixed.txt",
            index=False, sep=' ')
aois
Out[21]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 64 entries, 0 to 63
Data columns (total 8 columns):
x           64  non-null values
y           64  non-null values
width       64  non-null values
height      64  non-null values
kind        64  non-null values
name        64  non-null values
text        64  non-null values
category    55  non-null values
dtypes: int64(4), object(4)
In [20]:
display_html(aois.to_html())
Out[20]:
x y width height kind name text category
0 9 8 13 23 token Token.Name 1 a identifier
1 20 8 13 23 token Token.Text 1 text
2 31 8 13 23 token Token.Operator 1 = operator
3 42 8 13 23 token Token.Text 2 text
4 53 8 13 23 token Token.Literal.Number.Integer 1 4 integer
5 9 31 13 23 token Token.Name 2 b identifier
6 20 31 13 23 token Token.Text 3 text
7 31 31 13 23 token Token.Operator 2 = operator
8 42 31 13 23 token Token.Text 4 text
9 53 31 13 23 token Token.Literal.Number.Integer 2 3 integer
10 9 54 57 23 token Token.Keyword 1 print keyword
11 64 54 13 23 token Token.Text 5 text
12 75 54 13 23 token Token.Name 3 a identifier
13 86 54 13 23 token Token.Text 6 text
14 97 54 13 23 token Token.Operator 3 + operator
15 108 54 13 23 token Token.Text 7 text
16 119 54 13 23 token Token.Name 4 b identifier
17 9 100 13 23 token Token.Name 5 c identifier
18 20 100 13 23 token Token.Text 8 text
19 31 100 13 23 token Token.Operator 4 = operator
20 42 100 13 23 token Token.Text 9 text
21 53 100 13 23 token Token.Literal.Number.Integer 3 7 integer
22 9 123 13 23 token Token.Name 6 d identifier
23 20 123 13 23 token Token.Text 10 text
24 31 123 13 23 token Token.Operator 5 = operator
25 42 123 13 23 token Token.Text 11 text
26 53 123 13 23 token Token.Literal.Number.Integer 4 2 integer
27 9 146 57 23 token Token.Keyword 2 print keyword
28 64 146 13 23 token Token.Text 12 text
29 75 146 13 23 token Token.Name 7 c identifier
30 86 146 13 23 token Token.Text 13 text
31 97 146 13 23 token Token.Operator 6 + operator
32 108 146 13 23 token Token.Text 14 text
33 119 146 13 23 token Token.Name 8 d identifier
34 9 192 13 23 token Token.Name 9 e identifier
35 20 192 13 23 token Token.Text 15 text
36 31 192 13 23 token Token.Operator 7 = operator
37 42 192 13 23 token Token.Text 16 text
38 53 192 13 23 token Token.Literal.String 1 " string
39 64 192 13 23 token Token.Literal.String 2 5 string
40 75 192 13 23 token Token.Literal.String 3 " string
41 9 215 13 23 token Token.Name 10 f identifier
42 20 215 13 23 token Token.Text 17 text
43 31 215 13 23 token Token.Operator 8 = operator
44 42 215 13 23 token Token.Text 18 text
45 53 215 13 23 token Token.Literal.String 4 " string
46 64 215 13 23 token Token.Literal.String 5 3 string
47 75 215 13 23 token Token.Literal.String 6 " string
48 9 238 57 23 token Token.Keyword 3 print keyword
49 64 238 13 23 token Token.Text 19 text
50 75 238 13 23 token Token.Name 11 e identifier
51 86 238 13 23 token Token.Text 20 text
52 97 238 13 23 token Token.Operator 9 + operator
53 108 238 13 23 token Token.Text 21 text
54 119 238 13 23 token Token.Name 12 f identifier
55 9 8 56 23 line line 1 a = 4 NaN
56 9 31 56 23 line line 2 b = 3 NaN
57 9 54 122 23 line line 3 print a + b NaN
58 9 100 56 23 line line 5 c = 7 NaN
59 9 123 56 23 line line 6 d = 2 NaN
60 9 146 122 23 line line 7 print c + d NaN
61 9 192 78 23 line line 9 e = " 5 " NaN
62 9 215 78 23 line line 10 f = " 3 " NaN
63 9 238 122 23 line line 11 print e + f NaN

In []:
pandas.set_printoptions(precision=2)
df = programs.copy()
df.columns = ["Base", "Version", "Code Ch", "Code Ln", "CC", "HE", "HV", "Ouput Ch", "Output Ln"]
df
In []:
s = df.to_latex(index=False)
open("../../../Journal Article/programs_table.tex", "w").write(s)
In [2]:
raw_fixes = data.busjahn_2013.raw_fixations()
#screen = data.busjahn_2013.program_image("rectangle")
screen = data.busjahn_2013.program_image("basketball")
#offset = (-320, -88)
#raw_fixes.fix_x = raw_fixes.fix_x.apply(lambda x: x + offset[0])
#raw_fixes.fix_y = raw_fixes.fix_y.apply(lambda y: y + offset[1])
In []:
fixes = raw_fixes[raw_fixes.trial_id == 8]
plot.fixations.circles(fixes, screen, radius_min=5, radius_max=5)
In []:
from PIL import Image
font_path = "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf"
blank = Image.new("RGB", screen.size, color="#FFFFFF")
lines = open("../../eyecode/data/busjahn_2013/programs/rectangle.java", "r").readlines()
plot.misc.render_code(lines, blank, font_path, 22, 21, offset=(340, 93))
plot.fixations.circles(fixes, blank, radius_min=5, radius_max=5)
In [2]:
img = data.busjahn_2013.program_image("basketball")
aois = data.busjahn_2013.areas_of_interest()
bb_aois = aois[aois.program == "basketball"]
In [3]:
plot.aoi.draw_rectangles(bb_aois[bb_aois.kind == "sub-line"], img)
Out[3]:
In [63]:
df2 = rects.copy()
df2["kind"] = "line"
df2["name"] = "line "
df2.width += df2.x - 300 + 15
df2.x = 300
df2.y -= 8
df2.height += 16
df2.to_csv("../../eyecode/data/busjahn_2013/areas_of_interest.csv")
aoi.draw_rectangles(df2, img)
Out[63]:
In [2]:
raw_fixes = data.busjahn_2013.raw_fixations()
aois = data.busjahn_2013.areas_of_interest()
In [10]:
df = aoi.hit_test(raw_fixes, aois)
df[:25]
/usr/local/lib/python2.7/dist-packages/pandas/core/config.py:570: DeprecationWarning: height has been deprecated.

  warnings.warn(d.msg, DeprecationWarning)
/usr/local/lib/python2.7/dist-packages/pandas/core/config.py:570: DeprecationWarning: height has been deprecated.

  warnings.warn(d.msg, DeprecationWarning)
/usr/local/lib/python2.7/dist-packages/pandas/core/config.py:570: DeprecationWarning: height has been deprecated.

  warnings.warn(d.msg, DeprecationWarning)

Out[10]:
exp_id trial_id start_ms duration_ms fix_x fix_y offset_kind aoi_line
0 0 8 250 184 423.437500 378.083344 none line 14
1 0 8 567 200 324.711548 67.538460 none NaN
2 0 8 867 183 415.625000 -3.750000 none NaN
3 0 8 1284 283 444.852936 159.117645 none line 3
4 0 8 2034 867 366.030792 133.842896 none line 3
5 0 8 2951 317 469.062500 143.449997 none line 3
6 0 8 3352 233 397.500000 210.000000 none line 6
7 0 8 3785 183 619.687500 221.500000 none line 6
8 0 8 4102 383 782.343750 205.875000 none line 6
9 0 8 4552 433 416.574066 275.481476 none line 10
10 0 8 5619 317 405.062500 322.700012 none line 12
11 0 8 5953 466 424.913788 295.827576 none line 10
12 0 8 6470 350 378.977264 496.909088 none line 19
13 0 8 7103 167 632.045471 513.181824 none line 19
14 0 8 7287 233 574.750000 515.333313 none line 22
15 0 8 7537 166 670.340881 523.727295 none line 22
16 0 8 12822 200 492.500000 774.307678 none line 32
17 0 8 13106 200 580.096130 771.153870 none line 32
18 0 8 13356 150 783.750000 775.200012 none line 32
19 0 8 13539 434 884.305542 778.592590 none line 34
20 0 8 14006 250 591.250000 782.375000 none line 32
21 0 8 14706 451 494.732147 783.214294 none line 32
22 0 8 15240 167 427.159088 769.272705 none line 32
23 0 8 15457 233 497.916656 837.599976 none line 36
24 0 8 16024 166 660.454529 770.636353 none line 32
In [9]:
line_fixes = data.busjahn_2013.line_fixations()
t_fixes = line_fixes[line_fixes.trial_id == 8]
fig = plot.fixations.line_timeline_single(t_fixes).figure
fig.tight_layout()
fig
Out[9]:
In [10]:
line_fixes = data.busjahn_2013.line_fixations()
t_fixes = line_fixes[line_fixes.trial_id == 9]
fig = plot.fixations.line_timeline_single(t_fixes).figure
fig.tight_layout()
fig
Out[10]:
In [4]:
aois = data.busjahn_2013.areas_of_interest()
screen = data.busjahn_2013.program_image("rectangle")
plot.aoi.draw_rectangles(aois[aois.kind == "signature"], screen)
Out[4]:
In [43]:
all_fixations = data.busjahn_2013.all_fixations()
all_fixations["aoi_method-call"].unique()
Out[43]:
array([nan, 'main-print1 name', 'main-print1 params',
       'main-constructor2 params', 'main-print2 name',
       'main-constructor2 name', 'main-print2 params', 'area-width name',
       'main-constructor1 params', 'area-width params',
       'main-constructor1 name', 'area-height name', 'area-height params'], dtype=object)
In [20]:
all_fixations = data.busjahn_2013.all_fixations()
aois = data.busjahn_2013.areas_of_interest()
line_fixations = data.busjahn_2013.line_fixations()
In [3]:
t8_fixes = all_fixations[all_fixations.trial_id == 8]
t9_fixes = all_fixations[all_fixations.trial_id == 9]
In [5]:
aoi.scanpath_from_fixations(t8_fixes, aoi_names={"line":[]}).to_csv("../../../Gaze Workshop/subject1_lines.csv")
In [6]:
aoi.scanpath_from_fixations(t9_fixes, aoi_names={"line":[]}).to_csv("../../../Gaze Workshop/subject2_lines.csv")
In [26]:
plot.fixations.line_timeline(line_fixations, step_size=500).figure
Out[26]:
In [27]:
code_image = Image.open("../../eyecode/data/busjahn_2013/images/rectangle-pygment.png")
In [48]:
plot.fixations.line_code_image(line_fixations, code_image, image_padding=5, bar_height=0.75, bar_mult=1.015, num_lines=23)
Out[48]:
In [50]:
plot.fixations.line_code_image(line_fixations[line_fixations.trial_id == 9], code_image, image_padding=5, bar_height=0.75, bar_mult=1.015, num_lines=23)
Out[50]:
In [32]:
line_order = data.busjahn_2013.lines_execution_order()
In [6]:
all_fixations = data.busjahn_2013.all_fixations()
t8_fixes = all_fixations[all_fixations.trial_id == 8]
sp = aoi.scanpath_from_fixations(t8_fixes, aoi_names={"line":[]}, repeats=False)
In [24]:
from nltk.util import ngrams
from nltk import FreqDist
In [35]:
N = 4
line_grams = set(ngrams(line_order.name, N))
fd = { k: v for k, v in FreqDist(ngrams(sp.values, N)).iteritems() if k in line_grams }
fd
Out[35]:
{}

In [3]:
all_fixations = data.busjahn_2013.all_fixations()
aois = data.busjahn_2013.areas_of_interest()
t9_fixes = all_fixations[all_fixations.trial_id == 9]
main_aoi = aois[(aois.kind == "block") & (aois.name == "main")].iloc[0]
main_bbox = main_aoi[["x", "y", "width", "height"]].values
In [79]:
main_fixes = t9_fixes.iloc[56:72]
density, counts = metrics.fixation_spatial_density(main_fixes, grid_bbox=main_bbox, num_rows=6, num_cols=8)
print density / len(main_fixes)
print counts.T
main_fixes.duration_ms.median()
0.01171875
[[ 0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  3.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  3.  2.  2.  0.  2.  1.]
 [ 0.  1.  0.  1.  1.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.]]

Out[79]:
258.5
In [80]:
flat_counts = counts.flatten()
equal_counts = np.zeros(shape=(1, len(flat_counts))) + (flat_counts.sum() / len(flat_counts))
scipy.spatial.distance.cosine(flat_counts, equal_counts)
Out[80]:
array([[ 0.60394098]])
In [36]:
con_aoi = aois[(aois.kind == "block") & (aois.name == "constructor")].iloc[0]
con_fixes = t9_fixes.iloc[73:89]
con_bbox = con_aoi[["x", "y", "width", "height"]].values
In [81]:
density, counts = metrics.fixation_spatial_density(con_fixes, grid_bbox=con_bbox, num_rows=6, num_cols=8)
print density / len(con_fixes)
print counts.T
con_fixes.duration_ms.median()
0.0143229166667
[[ 0.  1.  1.  2.  4.  1.  1.  1.]
 [ 0.  1.  0.  0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.  0.  0.  0.]
 [ 0.  2.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  1.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.]]

Out[81]:
283.0
In [82]:
flat_counts = counts.flatten()
equal_counts = np.zeros(shape=(1, len(flat_counts))) + (flat_counts.sum() / len(flat_counts))
scipy.spatial.distance.cosine(flat_counts, equal_counts)
Out[82]:
array([[ 0.59175171]])
In [69]:
main_fixes = t9_fixes.iloc[90:117]
density, counts = metrics.fixation_spatial_density(main_fixes, grid_bbox=main_bbox, num_rows=6, num_cols=8)
print density / len(main_fixes)
print counts.T
pyplot.imshow(counts.T, interpolation="none").figure
0.0108024691358
[[  0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   1.   0.   1.   0.]
 [  0.   0.   1.   1.   0.   0.   1.   1.]
 [  1.   0.   1.   4.  10.   0.   0.   0.]
 [  0.   0.   1.   0.   2.   0.   1.   0.]
 [  0.   0.   0.   0.   1.   0.   0.   0.]]

Out[69]:
In [74]:
import scipy.spatial
In [75]:
flat_counts = counts.flatten()
equal_counts = np.zeros(shape=(1, len(flat_counts))) + (flat_counts.sum() / len(flat_counts))
scipy.spatial.distance.cosine(flat_counts, equal_counts)
Out[75]:
array([[ 0.65950754]])
In [78]:
main_fixes = t9_fixes.iloc[128:]
density, counts = metrics.fixation_spatial_density(main_fixes, grid_bbox=main_bbox, num_rows=6, num_cols=8)
print density / len(main_fixes)
print counts.T
main_fixes.duration_ms.median()
pyplot.imshow(counts.T, interpolation="none").figure
0.0120614035088
[[ 0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  1.  0.  0.]
 [ 0.  0.  0.  0.  0.  1.  0.  0.]
 [ 0.  0.  0.  1.  0.  0.  3.  3.]
 [ 0.  0.  1.  1.  1.  1.  0.  2.]]

Out[78]:
In [77]:
flat_counts = counts.flatten()
equal_counts = np.zeros(shape=(1, len(flat_counts))) + (flat_counts.sum() / len(flat_counts))
scipy.spatial.distance.cosine(flat_counts, equal_counts)
Out[77]:
array([[ 0.57836298]])

In [2]:
all_fixations = data.busjahn_2013.all_fixations()
aois = data.busjahn_2013.areas_of_interest()
t8_fixes = all_fixations[all_fixations.trial_id == 8]
t9_fixes = all_fixations[all_fixations.trial_id == 9]
code_aoi = aois[aois.name == "code box"].iloc[0]
code_bbox = code_aoi[["x", "y", "width", "height"]].values
In [8]:
fun = lambda fixes: metrics.fixation_spatial_density(fixes, grid_bbox=code_bbox, num_rows=rows, num_cols=cols)[0]
s = util.rolling_func(t8_fixes, fun, 3000)
s.plot(figsize=(20, 8)).figure
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-0275357f6c9e> in <module>()
      2 code_bbox = code_aoi[["x", "y", "width", "height"]].values
      3 fun = lambda fixes: metrics.fixation_spatial_density(fixes, grid_bbox=code_bbox, num_rows=rows, num_cols=cols)[0]
----> 4 s = util.rolling_func(t8_fixes, fun, 3000)
      5 s.plot(figsize=(20, 8)).figure

TypeError: rolling_func() takes exactly 4 arguments (3 given)
In [118]:
s = util.rolling_func(t9_fixes, fun, 3000)
s.plot(figsize=(20, 8)).figure
Out[118]:
In [3]:
funs = {
    "density" : lambda fixes: metrics.fixation_spatial_density(fixes, grid_bbox=code_bbox, num_rows=10, num_cols=1)[0],
    "fcount" : lambda fixes: len(fixes),
    "duration" : lambda fixes: fixes["duration_ms"].mean()
}
In [4]:
def rolling_plot(df):
    from matplotlib.ticker import MultipleLocator, FormatStrFormatter, FuncFormatter
   
    fig = pyplot.figure(figsize=(25, 10))
    ax = pyplot.axes()
    axes = [ax, ax.twinx(), ax.twinx()]
    plots = [None] * len(axes)
    
    fig.subplots_adjust(left=0, right=0.75)
    axes[2].spines['right'].set_position(('axes', 1.1))
    axes[2].set_frame_on(True)
    axes[2].patch.set_visible(False)
    
    plots[0] = axes[0].plot(df.index, df.density, color="b", marker="o", markersize=10, label="Density")
    axes[0].set_ylabel("Spatial Density", color="b")
    axes[0].tick_params(axis="y", colors="b")
    
    axes[1].plot(df.index, df.duration, color="r", marker="*", markersize=10, label="Duration")
    axes[1].set_ylabel("Mean Fixation Duration (ms)", color="r")
    axes[1].tick_params(axis="y", colors="r")
    
    axes[2].plot(df.index, df.fcount, color="g", marker="^", markersize=10, label="Fix Count")
    axes[2].set_ylabel("Fixation Count", color="g")
    axes[2].tick_params(axis="y", colors="g")
    
    #ax.grid()
    ax.set_xlabel("Time (sec)")
    ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: str(int(x) / 1000)))
    ax.xaxis.set_major_locator(MultipleLocator(2000))
    for label in ax.get_xticklabels():
        label.set_rotation(90)
    
    return fig
In [12]:
def rolling_plot(df):
    from matplotlib.ticker import MultipleLocator, FormatStrFormatter, FuncFormatter
   
    fig = pyplot.figure(figsize=(15, 8))
    ax = pyplot.axes()
    axes = [ax, ax.twinx(), ax.twinx()]
    plots = [None] * len(axes)
    
    plots[0] = axes[0].plot(df.index, df.density, color="blue", linewidth=2, label="Density")    
    plots[1] = axes[1].plot(df.index, df.duration, color="red", linestyle="-.", linewidth=3, label="Duration")    
    plots[2] = axes[2].plot(df.index, df.fcount, color="green", linestyle="--", linewidth=2, label="Count")
    
    for a in axes:
        a.yaxis.set_visible(False)
        a.set_frame_on(False)
        a.xaxis.tick_bottom()
        a.xaxis.set_major_locator(pyplot.NullLocator())
        a.set_xlabel(r"Time $\rightarrow$", fontsize=25)
        
    fig.tight_layout()
    fig.subplots_adjust(top=0.9)
    axes[0].legend(bbox_to_anchor=(0.4, 1.1), frameon=False)
    axes[1].legend(bbox_to_anchor=(0.8, 1.1), frameon=False)
    axes[2].legend(bbox_to_anchor=(0.6, 1.1), frameon=False)
    ax.set_ylim(df.density.min() - 0.01, df.density.max() + 0.01)
    
    for a in axes:
        pyplot.setp(a.get_legend().get_texts(), fontsize=25)
    return fig
In [13]:
df = util.rolling_func(t8_fixes, funs, 4000, 1000).dropna()
fig = rolling_plot(df)
#fig.subplots_adjust(top=0.9)
#fig.axes[0].set_title("Rolling Fixation Metrics (Trial 8, W=4s, S=1s)", fontsize=20)
fig.savefig("../../../Gaze Workshop/paper/figures/rolling_8.pdf")
fig
Out[13]:
In [10]:
df = util.rolling_func(t9_fixes, funs, 4000, 1000).dropna()
fig = rolling_plot(df)
#fig.subplots_adjust(top=0.9)
#fig.axes[0].set_title("Rolling Fixation Metrics (Trial 9, W=4s, S=1s)", fontsize=20)
fig.savefig("../../../Gaze Workshop/paper/figures/rolling_9.pdf")
fig
Out[10]:
In [26]:
lf_all = data.busjahn_2013.line_fixations()
line_fixations = lf_all[lf_all.trial_id == 8]
num_lines = 23 #line_fixations.line.max()

# Gather list of times and line numbers (output box is line 0)
times_lines = dict(list(line_fixations[["start_ms", "line"]].values) +
                   list(line_fixations[["end_ms", "line"]].values))

sorted_times = sorted(times_lines.keys())
sorted_lines = [times_lines[k] for k in sorted_times]
max_time = max(sorted_times)

# Plot fixation lines and points
fig_width = int(np.ceil(max_time / 1000.0 / 8.0))
fig_height = int(np.ceil((num_lines + 1) / 4.0))
figsize = (fig_width, fig_height)
pyplot.figure(figsize=figsize)
ax = pyplot.axes()
ax.set_frame_on(False)
ax.yaxis.set_visible(False)
ax.xaxis.tick_bottom()
ax.xaxis.set_major_locator(pyplot.NullLocator())

ax.plot(sorted_times, sorted_lines, linewidth=1, color="black", label="Line")
#ax.grid()
#ax.set_title("Fixations By Line")

lines = np.arange(1, num_lines + 1)
ax.set_ylim(0.5, num_lines + 0.5)
#ax.set_yticks(lines)
#ax.set_yticklabels(lines)

#ax.set_ylabel("Line")
ax.invert_yaxis()

# Show time in seconds instead of millis
#ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: int(x / 1000)))
#ax.xaxis.set_major_locator(MultipleLocator(1000))
ax.set_xlim(-500, max_time + 1000)
ax.set_xlabel(r"Time $\rightarrow$", fontsize=20)
ax.set_xticklabels([])

fig = ax.figure
fig.tight_layout()

fig.subplots_adjust(top=0.9)
ax.legend(bbox_to_anchor=(0.55, 1.1), frameon=False, fontsize=20)

scan_coords = (2034, 18642)
min_y, max_y = ax.yaxis.get_data_interval()
scan_rect = pyplot.Rectangle((scan_coords[0], min_y), scan_coords[1] - scan_coords[0], max_y - min_y,
                             color="yellow", alpha=0.5)
ax.add_patch(scan_rect)

fig.savefig("../../../Gaze Workshop/paper/figures/timeline_8.pdf")
fig
Out[26]:
In [15]:
img = data.busjahn_2013.program_image("basketball")
code = data.busjahn_2013.program_code("basketball")
lines = [i + 1 if len(l.strip()) > 0 else "" for i, l in enumerate(code)]
plot.misc.add_line_numbers(img, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 18, lines,
                           line_height=1.905, offset=(10, 28))
Out[15]: