Skip to content

Commit 49e2c81

Browse files
committed
Timer improvement
- Improved timer for review as discussed with Max : instead of a per-slice timer, it is now global and can be paused when needed. That time amount is recorded in the csv and recovered on subsequent review sessions
1 parent e462c4e commit 49e2c81

File tree

2 files changed

+80
-33
lines changed

2 files changed

+80
-33
lines changed

napari_cellseg3d/plugin_dock.py

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22
import warnings
3-
from datetime import datetime
3+
from datetime import datetime, timedelta
44
from pathlib import Path
55

66
import napari
@@ -16,6 +16,7 @@
1616
GUI_MAXIMUM_WIDTH = 225
1717
GUI_MAXIMUM_HEIGHT = 350
1818
GUI_MINIMUM_HEIGHT = 300
19+
TIMER_FORMAT = "%H:%M:%S"
1920

2021

2122
"""
@@ -44,20 +45,24 @@ def __init__(self, parent: "napari.viewer.Viewer"):
4445
"""napari.viewer.Viewer: viewer in which the widget is displayed"""
4546

4647
# add some buttons
47-
self.button = ui.Button(
48-
"1", self.button_func, parent=self, fixed=False
49-
)
48+
self.button = ui.Button("1", self.button_func, parent=self, fixed=True)
5049
self.time_label = ui.make_label("", self)
5150
self.time_label.setVisible(False)
5251

53-
io_panel, io_layout = ui.make_container(vertical=False)
52+
self.pause_box = ui.CheckBox(
53+
"Pause", self.pause_timer, parent=self, fixed=True
54+
)
55+
56+
io_panel, io_layout = ui.make_container()
57+
io_layout.addWidget(self.button, alignment=ui.ABS_AL)
5458
io_layout.addWidget(
5559
ui.combine_blocks(
56-
left_or_above=self.button,
60+
left_or_above=self.pause_box,
5761
right_or_below=self.time_label,
5862
horizontal=True,
5963
)
60-
) # , alignment=utils.ABS_AL)
64+
, alignment=ui.ABS_AL)
65+
6166
io_panel.setLayout(io_layout)
6267
io_panel.setMaximumWidth(GUI_MAXIMUM_WIDTH)
6368
layout.addWidget(io_panel, alignment=ui.ABS_AL)
@@ -76,7 +81,40 @@ def __init__(self, parent: "napari.viewer.Viewer"):
7681
"""Whether to load as folder or single file"""
7782

7883
self.start_time = datetime.now()
79-
self.time = None
84+
self.time_elapsed = timedelta()
85+
self.pause_start = None
86+
self.is_paused = False
87+
# self.pause_time = None
88+
89+
def pause_timer(self):
90+
"""Pause the timer for the review time"""
91+
if self.pause_box.isChecked():
92+
self.time_label.setVisible(True)
93+
94+
self.pause_start = datetime.now()
95+
self.time_elapsed += self.pause_start - self.start_time
96+
self.pause_box.setText("Resume timer")
97+
self.time_label.setText(
98+
f"({utils.time_difference(timedelta(),self.time_elapsed)})"
99+
)
100+
self.is_paused = True
101+
else:
102+
self.time_label.setVisible(False)
103+
self.pause_box.setText("Pause timer")
104+
105+
# self.pause_time = datetime.now() - self.pause_start
106+
self.start_time = datetime.now()
107+
self.is_paused = False
108+
self.update_time_csv()
109+
110+
def update_time_csv(self):
111+
if not self.is_paused:
112+
self.time_elapsed += datetime.now() - self.start_time
113+
self.start_time = datetime.now()
114+
str_time = utils.time_difference(timedelta(), self.time_elapsed)
115+
print(f"Time elapsed : {str_time}")
116+
self.df.at[0, "time"] = str_time
117+
self.df.to_csv(self.csv_path)
80118

81119
def prepare(self, label_dir, filetype, model_type, checkbox, as_folder):
82120
"""Initialize the Datamanager, which loads the csv file and updates it
@@ -127,7 +165,7 @@ def load_csv(self, label_dir, model_type, checkbox):
127165
print(label_dir)
128166
csvs = sorted(list(Path(label_dir).glob(f"{model_type}*.csv")))
129167
if len(csvs) == 0:
130-
df, csv_path = self.create(
168+
df, csv_path = self.create_csv(
131169
label_dir, model_type
132170
) # df, train_data_dir, ...
133171
else:
@@ -146,11 +184,18 @@ def load_csv(self, label_dir, model_type, checkbox):
146184
df.to_csv(csv_path)
147185
else:
148186
pass
149-
self.start_time = datetime.now()
150-
self.time = self.start_time
187+
188+
recorded_time = df.at[0, "time"]
189+
# print("csv load time")
190+
# print(recorded_time)
191+
t = datetime.strptime(recorded_time, TIMER_FORMAT)
192+
self.time_elapsed = timedelta(
193+
hours=t.hour, minutes=t.minute, seconds=t.second
194+
)
195+
# print(self.time_elapsed)
151196
return df, csv_path
152197

153-
def create(self, label_dir, model_type, filename=None):
198+
def create_csv(self, label_dir, model_type, filename=None):
154199
"""
155200
Create a new dataframe and save the csv
156201
Args:
@@ -182,6 +227,8 @@ def create(self, label_dir, model_type, filename=None):
182227
"time": [""] * len(labels),
183228
}
184229
)
230+
df.at[0, "time"] = "00:00:00"
231+
185232
csv_path = os.path.join(label_dir, f"{model_type}_train0.csv")
186233
print("csv path for create")
187234
print(csv_path)
@@ -204,6 +251,7 @@ def update(self, slice_num):
204251
205252
"""
206253
self.slice_num = slice_num
254+
self.update_time_csv()
207255

208256
print(f"New slice review started at {utils.get_time()}")
209257
# print(self.df)
@@ -214,41 +262,40 @@ def update(self, slice_num):
214262
self.slice_num -= 1
215263
self.update_button()
216264

217-
self.time = datetime.now()
265+
# self.time = datetime.now()
218266

219-
if self.button.text() == "Not checked":
220-
self.time_label.setVisible(False)
221-
else:
222-
self.time_label.setVisible(True)
223-
self.time_label.setText(
224-
f"Previously completed in {self.df.at[self.df.index[self.slice_num], 'time']}"
225-
)
267+
# if self.button.text() == "Not checked":
268+
# self.time_label.setVisible(False)
269+
# else:
270+
# self.time_label.setVisible(True)
271+
# self.time_label.setText(
272+
# f"Previously completed in {self.df.at[self.df.index[self.slice_num], 'time']}"
273+
# )
274+
# self.df.at[0, "time"] = self.time_elapsed
226275

227276
def button_func(self): # updates csv every time you press button...
228277
if self.viewer.dims.ndisplay != 2:
229278
# TODO test if undefined behaviour or if okay
230279
warnings.warn("Please switch back to 2D mode !")
231280
return
232-
if self.button.text() == "Not checked":
233281

234-
start_time = self.time
235-
finish_time = datetime.now()
236-
self.time = finish_time
282+
self.update_time_csv()
283+
# finish_time = datetime.now()
284+
# self.time_elapsed = finish_time - self.start_time
237285

238-
time_diff = utils.time_difference(start_time, finish_time)
239-
print(f"Time taken : {time_diff}")
286+
if self.button.text() == "Not checked":
287+
# time_diff = utils.time_difference(self.start_time, finish_time)
288+
# print(f"Time taken : {time_diff}")
240289

241290
self.button.setText("Checked")
242-
self.time_label.setVisible(True)
243-
self.time_label.setText(f"Completed in {time_diff}")
291+
# self.time_label.setVisible(True)
292+
# self.time_label.setText(f"Completed in {time_diff}")
244293
self.df.at[self.df.index[self.slice_num], "train"] = "Checked"
245-
self.df.at[self.df.index[self.slice_num], "time"] = time_diff
246-
self.df.to_csv(self.csv_path)
247294

295+
self.df.to_csv(self.csv_path)
248296
else:
249297
self.button.setText("Not checked")
250-
self.time_label.setVisible(False)
251-
self.time = datetime.now()
298+
# self.time_label.setVisible(False)
252299
self.df.at[self.df.index[self.slice_num], "train"] = "Not checked"
253300
self.df.to_csv(self.csv_path)
254301

napari_cellseg3d/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def time_difference(time_start, time_finish, as_string=True):
155155
"""
156156
Args:
157157
time_start (datetime): time to subtract to time_finish
158-
time_finish (datetime): time to add to (-time_start)
158+
time_finish (datetime): time to add to subtract time_start to
159159
as_string (bool): if True, returns a string with the full time diff. Otherwise, returns as a list [hours,minutes,seconds]
160160
"""
161161

0 commit comments

Comments
 (0)