Skip to content

Commit

Permalink
OWtSNE: Add resume option
Browse files Browse the repository at this point in the history
  • Loading branch information
VesnaT committed Dec 21, 2018
1 parent b55c4f5 commit 3dd2277
Showing 1 changed file with 36 additions and 13 deletions.
49 changes: 36 additions & 13 deletions Orange/widgets/unsupervised/owtsne.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class OWtSNE(OWDataProjectionWidget):
embedding_variables_names = ("t-SNE-x", "t-SNE-y")

#: Runtime state
Running, Finished, Waiting = 1, 2, 3
Running, Finished, Waiting, Pending = 1, 2, 3, 4

class Outputs(OWDataProjectionWidget.Outputs):
preprocessor = Output("Preprocessor", Preprocess)
Expand All @@ -98,6 +98,7 @@ def __init__(self):
self.pca_data = None
self.projection = None
self.tsne_runner = None
self.tsne_iterator = None
self.__update_loop = None
# timer for scheduling updates
self.__timer = QTimer(self, singleShot=True, interval=1,
Expand All @@ -120,31 +121,42 @@ def _add_controls_start_box(self):
)

self.perplexity_spin = gui.spin(
box, self, "perplexity", 1, 500, step=1, alignment=Qt.AlignRight)
box, self, "perplexity", 1, 500, step=1, alignment=Qt.AlignRight,
callback=self._params_changed
)
form.addRow("Perplexity:", self.perplexity_spin)
self.perplexity_spin.setEnabled(not self.multiscale)
form.addRow(gui.checkBox(
box, self, "multiscale", label="Preserve global structure",
callback=self._multiscale_changed
))
self._multiscale_changed()

sbe = gui.hBox(self.controlArea, False, addToLayout=False)
gui.hSlider(
sbe, self, "exaggeration", minValue=1, maxValue=4, step=1)
sbe, self, "exaggeration", minValue=1, maxValue=4, step=1,
callback=self._params_changed
)
form.addRow("Exaggeration:", sbe)

sbp = gui.hBox(self.controlArea, False, addToLayout=False)
gui.hSlider(
sbp, self, "pca_components", minValue=2, maxValue=50, step=1)
sbp, self, "pca_components", minValue=2, maxValue=50, step=1,
callback=self._params_changed
)
form.addRow("PCA components:", sbp)

box.layout().addLayout(form)

gui.separator(box, 10)
self.runbutton = gui.button(box, self, "Run", callback=self._toggle_run)

def _params_changed(self):
self.__state = OWtSNE.Finished
self.__set_update_loop(None)

def _multiscale_changed(self):
self.perplexity_spin.setEnabled(not self.multiscale)
self._params_changed()

def check_data(self):
def error(err):
Expand Down Expand Up @@ -179,6 +191,8 @@ def _toggle_run(self):
if self.__state == OWtSNE.Running:
self.stop()
self.commit()
elif self.__state == OWtSNE.Pending:
self.resume()
else:
self.start()

Expand All @@ -189,8 +203,11 @@ def start(self):
self.__start()

def stop(self):
if self.__state == OWtSNE.Running:
self.__set_update_loop(None)
self.__state = OWtSNE.Pending
self.__set_update_loop(None)

def resume(self):
self.__set_update_loop(self.tsne_iterator)

def pca_preprocessing(self):
if self.pca_data is not None and \
Expand Down Expand Up @@ -231,13 +248,14 @@ def __start(self):
)(self.pca_data)

self.tsne_runner = TSNERunner(self.projection, step_size=50)

self.__set_update_loop(self.tsne_runner.run_optimization())
self.tsne_iterator = self.tsne_runner.run_optimization()
self.__set_update_loop(self.tsne_iterator)
self.progressBarInit(processEvents=None)

def __set_update_loop(self, loop):
if self.__update_loop is not None:
self.__update_loop.close()
if self.__state in (OWtSNE.Finished, OWtSNE.Waiting):
self.__update_loop.close()
self.__update_loop = None
self.progressBarFinished(processEvents=None)

Expand All @@ -253,8 +271,10 @@ def __set_update_loop(self, loop):
else:
self.setBlocking(False)
self.setStatusMessage("")
self.runbutton.setText("Start")
self.__state = OWtSNE.Finished
if self.__state in (OWtSNE.Finished, OWtSNE.Waiting):
self.runbutton.setText("Start")
if self.__state == OWtSNE.Pending:
self.runbutton.setText("Resume")
self.__timer.stop()

def __next_step(self):
Expand All @@ -271,13 +291,16 @@ def __next_step(self):
projection, progress = next(self.__update_loop)
assert self.__update_loop is loop
except StopIteration:
self.__state = OWtSNE.Finished
self.__set_update_loop(None)
self.unconditional_commit()
except MemoryError:
self.Error.out_of_memory()
self.__state = OWtSNE.Finished
self.__set_update_loop(None)
except Exception as exc:
self.Error.optimization_error(str(exc))
self.__state = OWtSNE.Finished
self.__set_update_loop(None)
else:
self.progressBarSet(100.0 * progress, processEvents=None)
Expand Down Expand Up @@ -319,8 +342,8 @@ def send_preprocessor(self):

def clear(self):
super().clear()
self.__set_update_loop(None)
self.__state = OWtSNE.Waiting
self.__set_update_loop(None)
self.pca_data = None
self.projection = None

Expand Down

0 comments on commit 3dd2277

Please sign in to comment.