Soumyaratna commited on
Commit
13a088c
·
1 Parent(s): 13d6a22

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +172 -0
  2. requirement.txt +312 -0
app.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import pandas as pd
4
+ import matplotlib.pyplot as plt
5
+ import streamlit as st
6
+ from sklearn.neighbors import KNeighborsClassifier
7
+ from sklearn.model_selection import train_test_split
8
+ from sklearn.metrics import accuracy_score
9
+ from mlxtend.evaluate import bias_variance_decomp
10
+ import numpy as np
11
+
12
+ # Use a dark background style for plots
13
+ plt.style.use('dark_background')
14
+
15
+ # Function to generate custom data
16
+ def generate_data(n_classes, n_samples, pattern='Linear'):
17
+ X = np.zeros((n_classes*n_samples, 2))
18
+ y = np.zeros(n_classes*n_samples, dtype='uint8')
19
+ for j in range(n_classes):
20
+ ix = range(n_samples*j, n_samples*(j+1))
21
+ if pattern == 'Spiral':
22
+ r = np.linspace(0.0, 1, n_samples) # radius
23
+ t = np.linspace(j*4, (j+1)*4, n_samples) + np.random.randn(n_samples)*0.2 # theta
24
+ X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
25
+ elif pattern == 'Linear':
26
+ X[ix] = np.random.rand(n_samples, 2) * [j * 2, 1] + np.random.randn(n_samples, 2) * 0.2
27
+ elif pattern == 'Concentric Circle':
28
+ t = np.linspace(0, 2*np.pi, n_samples)
29
+ r = j/float(n_classes) + np.random.randn(n_samples)*0.1
30
+ X[ix] = np.c_[r*np.cos(t), r*np.sin(t)]
31
+ elif pattern == 'Blob':
32
+ t = np.linspace(0, 2*np.pi, n_samples)
33
+ r = 0.8 + np.random.randn(n_samples)*0.1
34
+ X[ix] = np.c_[r*np.cos(t), r*np.sin(t)] + np.random.randn(n_samples, 2)*0.2
35
+ elif pattern == 'Crescent':
36
+ half_samples = int(n_samples / 2)
37
+ theta = np.linspace(j * np.pi, (j + 2) * np.pi, n_samples)
38
+ r = np.linspace(1.0, 2.5, half_samples)
39
+ r = np.concatenate((r, np.linspace(2.5, 1.0, half_samples)))
40
+ X[ix] = np.c_[r*np.sin(theta), r*np.cos(theta)]
41
+ elif pattern == 'Normal':
42
+ for j in range(n_classes):
43
+ ix = range(n_samples*j, n_samples*(j+1))
44
+ X[ix] = np.random.randn(n_samples, 2) * 0.5 + np.random.randn(2) * j * 2
45
+ y[ix] = j
46
+ return X, y
47
+ elif pattern == 'Random':
48
+ X[ix] = np.random.randn(n_samples, 2)*0.5 + np.random.randn(2)*j*2
49
+ else:
50
+ raise ValueError('Invalid pattern: {}'.format(pattern))
51
+ y[ix] = j
52
+ return X, y
53
+
54
+ # Function to plot decision boundary and calculate model evaluation metrics
55
+ def keffect(k):
56
+ X, y = generate_data(num_classes, num_data_points, pattern=pattern)
57
+
58
+ knn = KNeighborsClassifier(n_neighbors=k)
59
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=42)
60
+ knn.fit(X_train,y_train)
61
+ y_pred = knn.predict(X_test)
62
+
63
+ accuracy = accuracy_score(y_test, y_pred)
64
+ mse, bias, var = bias_variance_decomp(knn, X_train, y_train, X_test, y_test, loss='mse', num_rounds=200, random_seed=1)
65
+
66
+ # Create a meshgrid for decision boundary plotting
67
+ a = np.arange(start=X_train[:,0].min()-1, stop=X_train[:,0].max()+1, step=0.01)
68
+ b = np.arange(start=X_train[:,1].min()-1, stop=X_train[:,1].max()+1, step=0.01)
69
+ XX, YY = np.meshgrid(a, b)
70
+ input_array = np.array([XX.ravel(), YY.ravel()]).T
71
+ labels = knn.predict(input_array)
72
+
73
+ # Plot decision boundary
74
+ fig, ax = plt.subplots(figsize=(fig_width, fig_height))
75
+ ax.set_facecolor('#FFF')
76
+ ax.contourf(XX, YY, labels.reshape(XX.shape), alpha=selected_alpha, cmap='Set1', edgecolors='black')
77
+ scatter = ax.scatter(X[:,0], X[:,1], c=y, cmap='Set1', edgecolors='black')
78
+ ax.set_title('K-Nearest Neighbors (K = {})'.format(k), color='white')
79
+ ax.set_xlabel('Feature 1', color='white')
80
+ ax.set_ylabel('Feature 2', color='white')
81
+ ax.tick_params(axis='x', colors='white')
82
+ ax.tick_params(axis='y', colors='white')
83
+
84
+ # Remove top and right spines
85
+ ax.spines['right'].set_visible(False)
86
+ ax.spines['left'].set_visible(False)
87
+ ax.spines['top'].set_visible(False)
88
+ ax.spines['bottom'].set_visible(False)
89
+
90
+ result = [accuracy, mse, bias, var]
91
+ return fig, result
92
+
93
+ # Function to plot bias-variance tradeoff
94
+ def plot_bias_variance_tradeoff(start_value, end_value):
95
+ X, y = generate_data(num_classes, num_data_points, pattern=pattern)
96
+
97
+ ks = range(start_value, end_value)
98
+ mse, bias, var = [], [], []
99
+ for k in ks:
100
+ knn = KNeighborsClassifier(n_neighbors=k)
101
+ mse_k, bias_k, var_k = bias_variance_decomp(knn, X, y, X, y, loss='mse', num_rounds=200, random_seed=1)
102
+ mse.append(mse_k)
103
+ bias.append(bias_k)
104
+ var.append(var_k)
105
+
106
+ fig, ax = plt.subplots(figsize=(fig_width, fig_height))
107
+ ax.plot(ks, mse, label='MSE', color='crimson')
108
+ ax.plot(ks, bias, label='Bias', color='magenta')
109
+ ax.plot(ks, var, label='Variance', color='cyan')
110
+ ax.legend()
111
+ ax.set_title('Bias-Variance Tradeoff', color='white')
112
+ ax.set_xlabel('Number of Neighbors (K)', color='white')
113
+ ax.set_ylabel('Error', color='white')
114
+ ax.tick_params(axis='x', colors='white')
115
+ ax.tick_params(axis='y', colors='white')
116
+ ax.set_xticks(list(range(start_value, end_value, 5)) + [end_value])
117
+ ax.set_facecolor('#000')
118
+
119
+ return fig
120
+
121
+ # Create a streamlit app to interact with the functions
122
+ st.set_page_config(page_title='K-Nearest Neighbors', layout='wide')
123
+ st.title('K-Nearest Neighbors')
124
+
125
+ with st.sidebar:
126
+ # Set up Streamlit sidebar
127
+ st.sidebar.header("Plot Settings")
128
+ [fig_width, fig_height] = [st.sidebar.slider(label, 1, 20, default) for label, default in [("Figure Width", 10), ("Figure Height", 6)]]
129
+ selected_alpha = st.sidebar.slider('Select the transparency of the decision boundary', min_value=0.0, max_value=1.0, value=0.5, step=0.1)
130
+
131
+ st.write("---")
132
+ st.sidebar.header("Data Settings")
133
+ pattern = st.selectbox('Select a pattern', ['Linear', 'Concentric Circle', 'Spiral', 'Blob', 'Crescent', 'Normal', 'Random'])
134
+ num_classes = st.slider('Select the number of classes', min_value=2, max_value=10, value=2, step=1)
135
+ num_data_points = st.slider('Select the number of data points', min_value=20, max_value=200, value=40, step=20)
136
+
137
+ st.write("---")
138
+ st.sidebar.header("Select the number of neighbors (K)")
139
+ selected_k = st.slider(label="", min_value=1, max_value=50, value=3, step=1)
140
+
141
+ st.write("---")
142
+ st.sidebar.header("Select a range for bias-variance tradeoff")
143
+ range_slider = st.slider(
144
+ label="",
145
+ min_value=1,
146
+ max_value=50,
147
+ value=(1, 20),
148
+ step=1
149
+ )
150
+ start_value, end_value = range_slider
151
+
152
+ st.write("---")
153
+
154
+ if st.button('Get Decision Boundary'):
155
+ # st.write('Decision Boundary')
156
+ fig, result = keffect(min(selected_k, num_data_points))
157
+ st.write(fig)
158
+
159
+ st.write('Model evaluation metrics')
160
+ st.write('Accuracy:', round(result[0], 3))
161
+ st.write('MSE:', round(result[1], 3))
162
+ st.write('Bias:', round(result[2], 3))
163
+ st.write('Variance:', round(result[3], 3))
164
+
165
+ if st.button('Get Bias-Variance Tradeoff'):
166
+ # st.write('Bias-Variance Tradeoff')
167
+ fig2 = plot_bias_variance_tradeoff(min(start_value, num_data_points), min(end_value, num_data_points))
168
+ st.write(fig2)
169
+
170
+
171
+
172
+
requirement.txt ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ absl-py==1.4.0
2
+ aiohttp==3.8.1
3
+ aiosignal==1.2.0
4
+ alabaster==0.7.12
5
+ altair==4.2.2
6
+ anaconda-client==1.7.2
7
+ anaconda-navigator==1.9.12
8
+ anaconda-project==0.8.3
9
+ appdirs==1.4.4
10
+ apyori==1.1.2
11
+ argh==0.26.2
12
+ asn1crypto==1.3.0
13
+ astroid @ file:///C:/ci/astroid_1592487315634/work
14
+ astropy==4.0.1.post1
15
+ astunparse==1.6.3
16
+ async-timeout==4.0.2
17
+ atomicwrites==1.4.0
18
+ attrs==19.3.0
19
+ autopep8 @ file:///tmp/build/80754af9/autopep8_1592412889138/work
20
+ Babel==2.8.0
21
+ backcall==0.2.0
22
+ backports.functools-lru-cache==1.6.1
23
+ backports.shutil-get-terminal-size==1.0.0
24
+ backports.tempfile==1.0
25
+ backports.weakref==1.0.post1
26
+ backports.zoneinfo==0.2.1
27
+ bcrypt==3.1.7
28
+ beautifulsoup4==4.9.1
29
+ bitarray @ file:///C:/ci/bitarray_1594751093906/work
30
+ bkcharts==0.2
31
+ bleach==3.1.5
32
+ blinker==1.6.2
33
+ bokeh @ file:///C:/ci/bokeh_1593178781838/work
34
+ boto==2.49.0
35
+ Bottleneck==1.3.2
36
+ brotlipy==0.7.0
37
+ cachetools==5.3.0
38
+ certifi==2020.6.20
39
+ cffi==1.14.0
40
+ chardet==3.0.4
41
+ charset-normalizer==2.0.12
42
+ click==7.1.2
43
+ cloudpickle @ file:///tmp/build/80754af9/cloudpickle_1594141588948/work
44
+ clyent==1.2.2
45
+ colorama==0.4.3
46
+ comtypes==1.1.7
47
+ conda==4.10.1
48
+ conda-build==3.18.11
49
+ conda-package-handling==1.7.0
50
+ conda-verify==3.4.2
51
+ contextlib2==0.6.0.post1
52
+ cryptography==2.9.2
53
+ cycler==0.10.0
54
+ Cython==0.29.23
55
+ cytoolz==0.10.1
56
+ dask @ file:///tmp/build/80754af9/dask-core_1594156306305/work
57
+ dateparser==1.1.1
58
+ decorator==4.4.2
59
+ defusedxml==0.6.0
60
+ diff-match-patch @ file:///tmp/build/80754af9/diff-match-patch_1594828741838/work
61
+ distlib==0.3.2
62
+ distributed @ file:///C:/ci/distributed_1594742844291/work
63
+ docopt==0.6.2
64
+ docutils==0.16
65
+ entrypoints==0.3
66
+ et-xmlfile==1.0.1
67
+ etils==1.0.0
68
+ fastcache==1.1.0
69
+ filelock==3.0.12
70
+ flake8==3.8.3
71
+ Flask==1.1.2
72
+ flatbuffers==2.0.7
73
+ frozenlist==1.3.0
74
+ fsspec==0.7.4
75
+ future==0.18.2
76
+ gast==0.4.0
77
+ gensim==4.1.2
78
+ gevent @ file:///C:/ci/gevent_1593005471151/work
79
+ gitdb==4.0.10
80
+ GitPython==3.1.31
81
+ glob2==0.7
82
+ gmpy2==2.0.8
83
+ google-auth==2.16.1
84
+ google-auth-oauthlib==0.4.6
85
+ google-pasta==0.2.0
86
+ greenlet==0.4.16
87
+ grpcio==1.51.3
88
+ h5py==2.10.0
89
+ HeapDict==1.0.1
90
+ html5lib @ file:///tmp/build/80754af9/html5lib_1593446221756/work
91
+ idna @ file:///tmp/build/80754af9/idna_1593446292537/work
92
+ imageio @ file:///tmp/build/80754af9/imageio_1594161405741/work
93
+ imagesize==1.2.0
94
+ importlib-metadata==6.0.0
95
+ importlib-resources==5.12.0
96
+ intervaltree @ file:///tmp/build/80754af9/intervaltree_1594361675072/work
97
+ ipykernel @ file:///C:/ci/ipykernel_1594745408489/work/dist/ipykernel-5.3.2-py3-none-any.whl
98
+ ipython @ file:///C:/ci/ipython_1593447482397/work
99
+ ipython_genutils==0.2.0
100
+ ipywidgets==7.5.1
101
+ isort==4.3.21
102
+ itsdangerous==1.1.0
103
+ jax==0.3.14
104
+ jaxlib==0.3.14
105
+ jdcal==1.4.1
106
+ jedi @ file:///C:/ci/jedi_1592833825077/work
107
+ Jinja2==2.11.2
108
+ joblib @ file:///tmp/build/80754af9/joblib_1594236160679/work
109
+ json5==0.9.5
110
+ jsonschema==3.2.0
111
+ jupyter==1.0.0
112
+ jupyter-client @ file:///tmp/build/80754af9/jupyter_client_1594826976318/work
113
+ jupyter-console==6.1.0
114
+ jupyter-core==4.6.3
115
+ jupyterlab==2.1.5
116
+ jupyterlab-server @ file:///tmp/build/80754af9/jupyterlab_server_1594164409481/work
117
+ keras==2.11.0
118
+ keyring @ file:///C:/ci/keyring_1593109799227/work
119
+ kiwisolver==1.2.0
120
+ lazy-object-proxy==1.4.3
121
+ libarchive-c==2.9
122
+ libclang==15.0.6.1
123
+ llvmlite==0.33.0
124
+ locket==0.2.0
125
+ lxml @ file:///C:/ci/lxml_1594822774489/work
126
+ Markdown==3.4.1
127
+ markdown-it-py==2.2.0
128
+ MarkupSafe==1.1.1
129
+ matplotlib @ file:///C:/ci/matplotlib-base_1592837548929/work
130
+ mccabe==0.6.1
131
+ mdurl==0.1.2
132
+ menuinst==1.4.16
133
+ mistune==0.8.4
134
+ mkl-fft==1.1.0
135
+ mkl-random==1.1.1
136
+ mkl-service==2.3.0
137
+ mlxtend @ file:///home/conda/feedstock_root/build_artifacts/mlxtend_1606368531479/work
138
+ mne==1.3.1
139
+ mock==4.0.2
140
+ more-itertools==8.4.0
141
+ mpmath==1.1.0
142
+ msgpack==1.0.0
143
+ multidict==6.0.2
144
+ multipledispatch==0.6.0
145
+ navigator-updater==0.2.1
146
+ nbconvert==5.6.1
147
+ nbformat==5.0.7
148
+ networkx @ file:///tmp/build/80754af9/networkx_1594377231366/work
149
+ nltk @ file:///tmp/build/80754af9/nltk_1592496090529/work
150
+ nose==1.3.7
151
+ notebook==6.0.3
152
+ numba==0.50.1
153
+ numexpr==2.7.1
154
+ numpy==1.23.1
155
+ numpydoc @ file:///tmp/build/80754af9/numpydoc_1594166760263/work
156
+ oauthlib==3.2.2
157
+ olefile==0.46
158
+ openpyxl @ file:///tmp/build/80754af9/openpyxl_1594167385094/work
159
+ opt-einsum==3.3.0
160
+ packaging==20.4
161
+ pandas @ file:///C:/ci/pandas_1592833613419/work
162
+ pandocfilters==1.4.2
163
+ paramiko==2.7.1
164
+ parso==0.7.0
165
+ partd==1.1.0
166
+ path==13.1.0
167
+ pathlib2==2.3.5
168
+ pathtools==0.1.2
169
+ patsy==0.5.1
170
+ pep8==1.7.1
171
+ pexpect==4.8.0
172
+ pickleshare==0.7.5
173
+ Pillow @ file:///C:/ci/pillow_1594298230227/work
174
+ pipreqs==0.4.13
175
+ pkginfo==1.5.0.1
176
+ platformdirs==3.2.0
177
+ pluggy==0.13.1
178
+ ply==3.11
179
+ pooch==1.7.0
180
+ praw==7.5.0
181
+ prawcore==2.3.0
182
+ prometheus-client==0.8.0
183
+ prompt-toolkit==3.0.5
184
+ protobuf==3.19.6
185
+ psutil==5.7.0
186
+ py @ file:///tmp/build/80754af9/py_1593446248552/work
187
+ pyarrow==11.0.0
188
+ pyasn1==0.4.8
189
+ pyasn1-modules==0.2.8
190
+ pycodestyle==2.6.0
191
+ pycosat==0.6.3
192
+ pycparser @ file:///tmp/build/80754af9/pycparser_1594388511720/work
193
+ pycurl==7.43.0.5
194
+ pydeck==0.8.1b0
195
+ pydocstyle @ file:///tmp/build/80754af9/pydocstyle_1592848020240/work
196
+ pyflakes==2.2.0
197
+ Pygments==2.15.1
198
+ pylint @ file:///C:/ci/pylint_1592482039483/work
199
+ Pympler==1.0.1
200
+ PyNaCl @ file:///C:/ci/pynacl_1595000047588/work
201
+ pyodbc===4.0.0-unsupported
202
+ pyOpenSSL @ file:///tmp/build/80754af9/pyopenssl_1594392929924/work
203
+ pyparsing==2.4.7
204
+ pyreadline==2.1
205
+ pyrsistent==0.16.0
206
+ PySocks==1.7.1
207
+ pytest==5.4.3
208
+ python-binance==1.0.15
209
+ python-dateutil==2.8.1
210
+ python-jsonrpc-server @ file:///tmp/build/80754af9/python-jsonrpc-server_1594397536060/work
211
+ python-language-server @ file:///C:/ci/python-language-server_1594162130238/work
212
+ pytz==2020.1
213
+ pytz-deprecation-shim==0.1.0.post0
214
+ PyWavelets==1.1.1
215
+ pywin32==227
216
+ pywin32-ctypes==0.2.0
217
+ pywinpty==0.5.7
218
+ PyYAML==5.3.1
219
+ pyzmq==19.0.1
220
+ QDarkStyle==2.8.1
221
+ QtAwesome==0.7.2
222
+ qtconsole @ file:///tmp/build/80754af9/qtconsole_1592848611704/work
223
+ QtPy==1.9.0
224
+ regex @ file:///C:/ci/regex_1593419644658/work
225
+ requests @ file:///tmp/build/80754af9/requests_1592841827918/work
226
+ requests-oauthlib==1.3.1
227
+ rich==13.3.4
228
+ rope==0.17.0
229
+ rsa==4.9
230
+ Rtree==0.9.4
231
+ ruamel_yaml==0.15.87
232
+ scikit-image==0.16.2
233
+ scikit-learn @ file:///C:/ci/scikit-learn_1592853510272/work
234
+ scipy @ file:///C:/ci/scipy_1592916963468/work
235
+ seaborn==0.10.1
236
+ Send2Trash==1.5.0
237
+ simplegeneric==0.8.1
238
+ singledispatch==3.4.0.3
239
+ sip==4.19.13
240
+ six==1.15.0
241
+ smart-open==5.2.1
242
+ smmap==5.0.0
243
+ snowballstemmer==2.0.0
244
+ sortedcollections==1.2.1
245
+ sortedcontainers==2.2.2
246
+ soupsieve==2.0.1
247
+ Sphinx @ file:///tmp/build/80754af9/sphinx_1594223420021/work
248
+ sphinxcontrib-applehelp==1.0.2
249
+ sphinxcontrib-devhelp==1.0.2
250
+ sphinxcontrib-htmlhelp==1.0.3
251
+ sphinxcontrib-jsmath==1.0.1
252
+ sphinxcontrib-qthelp==1.0.3
253
+ sphinxcontrib-serializinghtml==1.1.4
254
+ sphinxcontrib-websupport @ file:///tmp/build/80754af9/sphinxcontrib-websupport_1593446360927/work
255
+ spyder @ file:///C:/ci/spyder_1594830825244/work
256
+ spyder-kernels @ file:///C:/ci/spyder-kernels_1594751670175/work
257
+ SQLAlchemy @ file:///C:/ci/sqlalchemy_1593445271541/work
258
+ statsmodels==0.11.1
259
+ streamlit==1.21.0
260
+ sympy @ file:///C:/ci/sympy_1594234545115/work
261
+ tables==3.6.1
262
+ tblib==1.6.0
263
+ tensorboard==2.11.2
264
+ tensorboard-data-server==0.6.1
265
+ tensorboard-plugin-wit==1.8.1
266
+ tensorflow==2.11.0
267
+ tensorflow-estimator==2.11.0
268
+ tensorflow-intel==2.11.0
269
+ tensorflow-io-gcs-filesystem==0.31.0
270
+ termcolor==2.2.0
271
+ terminado==0.8.3
272
+ testpath==0.4.4
273
+ textblob==0.17.1
274
+ threadpoolctl @ file:///tmp/tmp9twdgx9k/threadpoolctl-2.1.0-py3-none-any.whl
275
+ toml @ file:///tmp/build/80754af9/toml_1592853716807/work
276
+ toolz==0.10.0
277
+ tornado==6.0.4
278
+ tqdm @ file:///tmp/build/80754af9/tqdm_1593446365756/work
279
+ traitlets==4.3.3
280
+ typing_extensions==4.5.0
281
+ tzdata==2022.1
282
+ tzlocal==4.1
283
+ ujson==1.35
284
+ unicodecsv==0.14.1
285
+ update-checker==0.18.0
286
+ urllib3==1.25.9
287
+ validators==0.20.0
288
+ virtualenv==20.4.7
289
+ virtualenvwrapper-win==1.2.6
290
+ watchdog @ file:///C:/ci/watchdog_1593447437088/work
291
+ wcwidth @ file:///tmp/build/80754af9/wcwidth_1593447189090/work
292
+ webencodings==0.5.1
293
+ websocket-client==1.3.1
294
+ websockets==9.1
295
+ Werkzeug==1.0.1
296
+ widgetsnbextension==3.5.1
297
+ win-inet-pton==1.1.0
298
+ win-unicode-console==0.5
299
+ wincertstore==0.2
300
+ wrapt==1.11.2
301
+ xlrd==1.2.0
302
+ XlsxWriter==1.2.9
303
+ xlwings==0.19.5
304
+ xlwt==1.3.0
305
+ xmltodict==0.12.0
306
+ yapf @ file:///tmp/build/80754af9/yapf_1593528177422/work
307
+ yarg==0.1.9
308
+ yarl==1.7.2
309
+ zict==2.0.0
310
+ zipp==3.1.0
311
+ zope.event==4.4
312
+ zope.interface==4.7.1