teareduce 0.5.4__py3-none-any.whl → 0.5.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- teareduce/cleanest/__main__.py +57 -8
- teareduce/cleanest/centerchildparent.py +46 -0
- teareduce/cleanest/cleanest.py +16 -19
- teareduce/cleanest/cosmicraycleanerapp.py +262 -170
- teareduce/cleanest/definitions.py +30 -29
- teareduce/cleanest/imagedisplay.py +8 -9
- teareduce/cleanest/interpolation_a.py +5 -9
- teareduce/cleanest/interpolationeditor.py +156 -35
- teareduce/cleanest/modalprogressbar.py +182 -0
- teareduce/cleanest/parametereditor.py +98 -76
- teareduce/cleanest/reviewcosmicray.py +90 -62
- teareduce/version.py +1 -1
- {teareduce-0.5.4.dist-info → teareduce-0.5.5.dist-info}/METADATA +1 -1
- {teareduce-0.5.4.dist-info → teareduce-0.5.5.dist-info}/RECORD +18 -16
- {teareduce-0.5.4.dist-info → teareduce-0.5.5.dist-info}/WHEEL +0 -0
- {teareduce-0.5.4.dist-info → teareduce-0.5.5.dist-info}/entry_points.txt +0 -0
- {teareduce-0.5.4.dist-info → teareduce-0.5.5.dist-info}/licenses/LICENSE.txt +0 -0
- {teareduce-0.5.4.dist-info → teareduce-0.5.5.dist-info}/top_level.txt +0 -0
|
@@ -13,11 +13,13 @@ import tkinter as tk
|
|
|
13
13
|
from tkinter import ttk
|
|
14
14
|
from tkinter import messagebox
|
|
15
15
|
|
|
16
|
+
from .centerchildparent import center_on_parent
|
|
16
17
|
from .definitions import lacosmic_default_dict
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class ParameterEditor:
|
|
20
21
|
"""A dialog to edit L.A.Cosmic parameters."""
|
|
22
|
+
|
|
21
23
|
def __init__(self, root, param_dict, window_title, xmin, xmax, ymin, ymax, imgshape):
|
|
22
24
|
"""Initialize the parameter editor dialog.
|
|
23
25
|
|
|
@@ -31,12 +33,16 @@ class ParameterEditor:
|
|
|
31
33
|
Title of the dialog window.
|
|
32
34
|
xmin : int
|
|
33
35
|
Minimum x-coordinate of the region to be examined.
|
|
36
|
+
From 1 to NAXIS1.
|
|
34
37
|
xmax : int
|
|
35
38
|
Maximum x-coordinate of the region to be examined.
|
|
39
|
+
From 1 to NAXIS1.
|
|
36
40
|
ymin : int
|
|
37
41
|
Minimum y-coordinate of the region to be examined.
|
|
42
|
+
From 1 to NAXIS2.
|
|
38
43
|
ymax : int
|
|
39
44
|
Maximum y-coordinate of the region to be examined.
|
|
45
|
+
From 1 to NAXIS2.
|
|
40
46
|
imgshape : tuple
|
|
41
47
|
Shape of the image (height, width).
|
|
42
48
|
|
|
@@ -70,16 +76,17 @@ class ParameterEditor:
|
|
|
70
76
|
self.root.title(window_title)
|
|
71
77
|
self.param_dict = param_dict
|
|
72
78
|
# Set default region values
|
|
73
|
-
self.param_dict[
|
|
74
|
-
self.param_dict[
|
|
75
|
-
self.param_dict[
|
|
76
|
-
self.param_dict[
|
|
79
|
+
self.param_dict["xmin"]["value"] = xmin
|
|
80
|
+
self.param_dict["xmax"]["value"] = xmax
|
|
81
|
+
self.param_dict["ymin"]["value"] = ymin
|
|
82
|
+
self.param_dict["ymax"]["value"] = ymax
|
|
77
83
|
self.imgshape = imgshape
|
|
78
|
-
self.entries = {
|
|
84
|
+
self.entries = {"run1": {}, "run2": {}} # dictionary to hold entry widgets
|
|
79
85
|
self.result_dict = None
|
|
80
86
|
|
|
81
87
|
# Create the form
|
|
82
88
|
self.create_widgets()
|
|
89
|
+
center_on_parent(child=self.root, parent=self.root.master)
|
|
83
90
|
|
|
84
91
|
def create_widgets(self):
|
|
85
92
|
"""Create the widgets for the dialog."""
|
|
@@ -90,7 +97,10 @@ class ParameterEditor:
|
|
|
90
97
|
row = 0
|
|
91
98
|
|
|
92
99
|
# Subtitle for L.A.Cosmic parameters
|
|
93
|
-
|
|
100
|
+
default_font = tk.font.nametofont("TkDefaultFont")
|
|
101
|
+
bold_font = default_font.copy()
|
|
102
|
+
bold_font.configure(weight="bold", size=default_font.cget("size") + 2)
|
|
103
|
+
subtitle_label = tk.Label(main_frame, text="L.A.Cosmic Parameters", font=bold_font)
|
|
94
104
|
subtitle_label.grid(row=row, column=0, columnspan=4, pady=(0, 15))
|
|
95
105
|
row += 1
|
|
96
106
|
|
|
@@ -99,88 +109,101 @@ class ParameterEditor:
|
|
|
99
109
|
# so that we can update the color of run2 entries if they differ from run1.
|
|
100
110
|
self.entry_vars = {}
|
|
101
111
|
for key, info in self.param_dict.items():
|
|
102
|
-
if not key.startswith(
|
|
112
|
+
if not key.startswith("run1_"):
|
|
103
113
|
continue
|
|
104
114
|
# Parameter name label
|
|
105
|
-
label = tk.Label(main_frame, text=f"{key[5:]}:", anchor=
|
|
106
|
-
label.grid(row=row, column=0, sticky=
|
|
115
|
+
label = tk.Label(main_frame, text=f"{key[5:]}:", anchor="e", width=15)
|
|
116
|
+
label.grid(row=row, column=0, sticky="w", pady=5)
|
|
107
117
|
# Entry field for run1
|
|
108
118
|
self.entry_vars[key] = tk.StringVar()
|
|
109
|
-
self.entry_vars[key].trace_add(
|
|
119
|
+
self.entry_vars[key].trace_add("write", lambda *args: self.update_colour_param_run1_run2())
|
|
110
120
|
entry = tk.Entry(main_frame, textvariable=self.entry_vars[key], width=10)
|
|
111
|
-
entry.insert(0, str(info[
|
|
121
|
+
entry.insert(0, str(info["value"]))
|
|
112
122
|
entry.grid(row=row, column=1, padx=10, pady=5)
|
|
113
123
|
self.entries[key] = entry # dictionary to hold entry widgets
|
|
114
124
|
# Entry field for run2
|
|
115
|
-
key2 =
|
|
125
|
+
key2 = "run2_" + key[5:]
|
|
116
126
|
self.entry_vars[key2] = tk.StringVar()
|
|
117
|
-
self.entry_vars[key2].trace_add(
|
|
127
|
+
self.entry_vars[key2].trace_add("write", lambda *args: self.update_colour_param_run1_run2())
|
|
118
128
|
entry = tk.Entry(main_frame, textvariable=self.entry_vars[key2], width=10)
|
|
119
|
-
entry.insert(0, str(self.param_dict[key2][
|
|
129
|
+
entry.insert(0, str(self.param_dict[key2]["value"]))
|
|
120
130
|
entry.grid(row=row, column=2, padx=10, pady=5)
|
|
121
|
-
self.entries[
|
|
131
|
+
self.entries["run2_" + key[5:]] = entry # dictionary to hold entry widgets
|
|
122
132
|
# Type label
|
|
123
|
-
type_label = tk.Label(main_frame, text=f"({info['type'].__name__})", fg=
|
|
124
|
-
type_label.grid(row=row, column=3, sticky=
|
|
133
|
+
type_label = tk.Label(main_frame, text=f"({info['type'].__name__})", fg="gray", anchor="w", width=10)
|
|
134
|
+
type_label.grid(row=row, column=3, sticky="w", pady=5)
|
|
125
135
|
row += 1
|
|
126
136
|
# self.update_colour_param_run1_run2()
|
|
127
137
|
|
|
128
138
|
# Separator
|
|
129
|
-
separator1 = ttk.Separator(main_frame, orient=
|
|
130
|
-
separator1.grid(row=row, column=0, columnspan=4, sticky=
|
|
139
|
+
separator1 = ttk.Separator(main_frame, orient="horizontal")
|
|
140
|
+
separator1.grid(row=row, column=0, columnspan=4, sticky="ew", pady=(10, 10))
|
|
131
141
|
row += 1
|
|
132
142
|
|
|
133
143
|
# Subtitle for additional parameters
|
|
134
|
-
subtitle_label = tk.Label(main_frame, text="Additional Parameters", font=
|
|
144
|
+
subtitle_label = tk.Label(main_frame, text="Additional Parameters", font=bold_font)
|
|
135
145
|
subtitle_label.grid(row=row, column=0, columnspan=4, pady=(0, 15))
|
|
136
146
|
row += 1
|
|
137
147
|
|
|
138
148
|
# Dilation label and entry
|
|
139
|
-
label = tk.Label(main_frame, text="Dilation:", anchor=
|
|
140
|
-
label.grid(row=row, column=0, sticky=
|
|
149
|
+
label = tk.Label(main_frame, text="Dilation:", anchor="e", width=15)
|
|
150
|
+
label.grid(row=row, column=0, sticky="w", pady=5)
|
|
151
|
+
entry = tk.Entry(main_frame, width=10)
|
|
152
|
+
entry.insert(0, str(self.param_dict["dilation"]["value"]))
|
|
153
|
+
entry.grid(row=row, column=1, padx=10, pady=5)
|
|
154
|
+
self.entries["dilation"] = entry
|
|
155
|
+
type_label = tk.Label(
|
|
156
|
+
main_frame, text=f"({self.param_dict['dilation']['type'].__name__})", fg="gray", anchor="w", width=10
|
|
157
|
+
)
|
|
158
|
+
type_label.grid(row=row, column=2, sticky="w", pady=5)
|
|
159
|
+
row += 1
|
|
160
|
+
|
|
161
|
+
label = tk.Label(main_frame, text="Border Padding:", anchor="e", width=15)
|
|
162
|
+
label.grid(row=row, column=0, sticky="w", pady=5)
|
|
141
163
|
entry = tk.Entry(main_frame, width=10)
|
|
142
|
-
entry.insert(0, str(self.param_dict[
|
|
164
|
+
entry.insert(0, str(self.param_dict["borderpadd"]["value"]))
|
|
143
165
|
entry.grid(row=row, column=1, padx=10, pady=5)
|
|
144
|
-
self.entries[
|
|
145
|
-
type_label = tk.Label(
|
|
146
|
-
|
|
147
|
-
|
|
166
|
+
self.entries["borderpadd"] = entry
|
|
167
|
+
type_label = tk.Label(
|
|
168
|
+
main_frame, text=f"({self.param_dict['borderpadd']['type'].__name__})", fg="gray", anchor="w", width=10
|
|
169
|
+
)
|
|
170
|
+
type_label.grid(row=row, column=2, sticky="w", pady=5)
|
|
148
171
|
row += 1
|
|
149
172
|
|
|
150
173
|
# Separator
|
|
151
|
-
separator2 = ttk.Separator(main_frame, orient=
|
|
152
|
-
separator2.grid(row=row, column=0, columnspan=4, sticky=
|
|
174
|
+
separator2 = ttk.Separator(main_frame, orient="horizontal")
|
|
175
|
+
separator2.grid(row=row, column=0, columnspan=4, sticky="ew", pady=(10, 10))
|
|
153
176
|
row += 1
|
|
154
177
|
|
|
155
178
|
# Subtitle for region to be examined
|
|
156
|
-
subtitle_label = tk.Label(main_frame, text="Region to be Examined", font=
|
|
179
|
+
subtitle_label = tk.Label(main_frame, text="Region to be Examined", font=bold_font)
|
|
157
180
|
subtitle_label.grid(row=row, column=0, columnspan=4, pady=(0, 15))
|
|
158
181
|
row += 1
|
|
159
182
|
|
|
160
183
|
# Region to be examined label and entries
|
|
161
184
|
for key, info in self.param_dict.items():
|
|
162
|
-
if key.lower() in [
|
|
185
|
+
if key.lower() in ["xmin", "xmax", "ymin", "ymax"]:
|
|
163
186
|
# Parameter name label
|
|
164
|
-
label = tk.Label(main_frame, text=f"{key}:", anchor=
|
|
165
|
-
label.grid(row=row, column=0, sticky=
|
|
187
|
+
label = tk.Label(main_frame, text=f"{key}:", anchor="e", width=15)
|
|
188
|
+
label.grid(row=row, column=0, sticky="w", pady=5)
|
|
166
189
|
# Entry field
|
|
167
190
|
entry = tk.Entry(main_frame, width=10)
|
|
168
|
-
entry.insert(0, str(info[
|
|
191
|
+
entry.insert(0, str(info["value"]))
|
|
169
192
|
entry.grid(row=row, column=1, padx=10, pady=5)
|
|
170
193
|
self.entries[key] = entry # dictionary to hold entry widgets
|
|
171
194
|
# Type label
|
|
172
195
|
dumtext = f"({info['type'].__name__})"
|
|
173
|
-
if key.lower() in [
|
|
196
|
+
if key.lower() in ["xmin", "xmax"]:
|
|
174
197
|
dumtext += f" --> [1, {self.imgshape[1]}]"
|
|
175
198
|
else:
|
|
176
199
|
dumtext += f" --> [1, {self.imgshape[0]}]"
|
|
177
|
-
type_label = tk.Label(main_frame, text=dumtext, fg=
|
|
178
|
-
type_label.grid(row=row, column=2, sticky=
|
|
200
|
+
type_label = tk.Label(main_frame, text=dumtext, fg="gray", anchor="w", width=15)
|
|
201
|
+
type_label.grid(row=row, column=2, sticky="w", pady=5)
|
|
179
202
|
row += 1
|
|
180
203
|
|
|
181
204
|
# Separator
|
|
182
|
-
separator3 = ttk.Separator(main_frame, orient=
|
|
183
|
-
separator3.grid(row=row, column=0, columnspan=4, sticky=
|
|
205
|
+
separator3 = ttk.Separator(main_frame, orient="horizontal")
|
|
206
|
+
separator3.grid(row=row, column=0, columnspan=4, sticky="ew", pady=(10, 10))
|
|
184
207
|
row += 1
|
|
185
208
|
|
|
186
209
|
# Button frame
|
|
@@ -189,15 +212,15 @@ class ParameterEditor:
|
|
|
189
212
|
|
|
190
213
|
# OK button
|
|
191
214
|
ok_button = tk.Button(button_frame, text="OK", width=5, command=self.on_ok)
|
|
192
|
-
ok_button.pack(side=
|
|
215
|
+
ok_button.pack(side="left", padx=5)
|
|
193
216
|
|
|
194
217
|
# Cancel button
|
|
195
218
|
cancel_button = tk.Button(button_frame, text="Cancel", width=5, command=self.on_cancel)
|
|
196
|
-
cancel_button.pack(side=
|
|
219
|
+
cancel_button.pack(side="left", padx=5)
|
|
197
220
|
|
|
198
221
|
# Reset button
|
|
199
222
|
reset_button = tk.Button(button_frame, text="Reset", width=5, command=self.on_reset)
|
|
200
|
-
reset_button.pack(side=
|
|
223
|
+
reset_button.pack(side="left", padx=5)
|
|
201
224
|
|
|
202
225
|
def on_ok(self):
|
|
203
226
|
"""Validate and save the updated values"""
|
|
@@ -205,61 +228,60 @@ class ParameterEditor:
|
|
|
205
228
|
updated_dict = {}
|
|
206
229
|
|
|
207
230
|
for key, info in self.param_dict.items():
|
|
208
|
-
if key ==
|
|
231
|
+
if key == "nruns":
|
|
209
232
|
continue
|
|
210
233
|
entry_value = self.entries[key].get()
|
|
211
|
-
value_type = info[
|
|
234
|
+
value_type = info["type"]
|
|
212
235
|
|
|
213
236
|
# Convert string to appropriate type
|
|
214
237
|
if value_type == bool:
|
|
215
238
|
# Handle boolean conversion
|
|
216
|
-
if entry_value.lower() in [
|
|
239
|
+
if entry_value.lower() in ["true", "1", "yes"]:
|
|
217
240
|
converted_value = True
|
|
218
|
-
elif entry_value.lower() in [
|
|
241
|
+
elif entry_value.lower() in ["false", "0", "no"]:
|
|
219
242
|
converted_value = False
|
|
220
243
|
else:
|
|
221
244
|
raise ValueError(f"Invalid boolean value for {key}")
|
|
222
245
|
else:
|
|
223
246
|
converted_value = value_type(entry_value)
|
|
224
|
-
if
|
|
247
|
+
if "positive" in info and info["positive"] and converted_value < 0:
|
|
225
248
|
raise ValueError(f"Value for {key} must be positive")
|
|
226
249
|
|
|
227
|
-
updated_dict[key] = {
|
|
228
|
-
'value': converted_value,
|
|
229
|
-
'type': value_type
|
|
230
|
-
}
|
|
250
|
+
updated_dict[key] = {"value": converted_value, "type": value_type}
|
|
231
251
|
|
|
232
252
|
# Check whether any run1 and run2 parameters differ
|
|
233
253
|
nruns = 1
|
|
234
254
|
for key in self.param_dict.keys():
|
|
235
|
-
if key.startswith(
|
|
255
|
+
if key.startswith("run1_"):
|
|
236
256
|
parname = key[5:]
|
|
237
|
-
key2 =
|
|
238
|
-
if updated_dict[key][
|
|
257
|
+
key2 = "run2_" + parname
|
|
258
|
+
if updated_dict[key]["value"] != updated_dict[key2]["value"]:
|
|
239
259
|
nruns = 2
|
|
240
|
-
print(
|
|
241
|
-
|
|
260
|
+
print(
|
|
261
|
+
f"Parameter '{parname}' differs between run1 and run2: "
|
|
262
|
+
f"{updated_dict[key]['value']} (run1) vs {updated_dict[key2]['value']} (run2)"
|
|
263
|
+
)
|
|
242
264
|
|
|
243
265
|
# Additional validation for region limits
|
|
244
266
|
try:
|
|
245
|
-
if updated_dict[
|
|
267
|
+
if updated_dict["xmax"]["value"] <= updated_dict["xmin"]["value"]:
|
|
246
268
|
raise ValueError("xmax must be greater than xmin")
|
|
247
|
-
if updated_dict[
|
|
269
|
+
if updated_dict["ymax"]["value"] <= updated_dict["ymin"]["value"]:
|
|
248
270
|
raise ValueError("ymax must be greater than ymin")
|
|
249
271
|
self.result_dict = updated_dict
|
|
250
|
-
self.result_dict[
|
|
272
|
+
self.result_dict["nruns"] = {"value": nruns, "type": int, "positive": True}
|
|
251
273
|
if nruns not in [1, 2]:
|
|
252
274
|
raise ValueError("nruns must be 1 or 2")
|
|
253
275
|
self.root.destroy()
|
|
254
276
|
except ValueError as e:
|
|
255
|
-
messagebox.showerror(
|
|
256
|
-
|
|
257
|
-
|
|
277
|
+
messagebox.showerror(
|
|
278
|
+
"Invalid Inputs", "Error in region limits:\n" f"{str(e)}\n\nPlease check your inputs."
|
|
279
|
+
)
|
|
258
280
|
|
|
259
281
|
except ValueError as e:
|
|
260
|
-
messagebox.showerror(
|
|
261
|
-
|
|
262
|
-
|
|
282
|
+
messagebox.showerror(
|
|
283
|
+
"Invalid Inputs", f"Error converting value for {key}:\n{str(e)}\n\n" "Please check your inputs."
|
|
284
|
+
)
|
|
263
285
|
|
|
264
286
|
def on_cancel(self):
|
|
265
287
|
"""Close without saving"""
|
|
@@ -269,15 +291,15 @@ class ParameterEditor:
|
|
|
269
291
|
def on_reset(self):
|
|
270
292
|
"""Reset all fields to original values"""
|
|
271
293
|
self.param_dict = lacosmic_default_dict.copy()
|
|
272
|
-
self.param_dict[
|
|
273
|
-
self.param_dict[
|
|
274
|
-
self.param_dict[
|
|
275
|
-
self.param_dict[
|
|
294
|
+
self.param_dict["xmin"]["value"] = 1
|
|
295
|
+
self.param_dict["xmax"]["value"] = self.imgshape[1]
|
|
296
|
+
self.param_dict["ymin"]["value"] = 1
|
|
297
|
+
self.param_dict["ymax"]["value"] = self.imgshape[0]
|
|
276
298
|
for key, info in self.param_dict.items():
|
|
277
|
-
if key ==
|
|
299
|
+
if key == "nruns":
|
|
278
300
|
continue
|
|
279
301
|
self.entries[key].delete(0, tk.END)
|
|
280
|
-
self.entries[key].insert(0, str(info[
|
|
302
|
+
self.entries[key].insert(0, str(info["value"]))
|
|
281
303
|
|
|
282
304
|
def get_result(self):
|
|
283
305
|
"""Return the updated dictionary"""
|
|
@@ -287,10 +309,10 @@ class ParameterEditor:
|
|
|
287
309
|
"""Update the foreground color of run1 and run2 entries."""
|
|
288
310
|
# Highlight run2 parameter if different from run1
|
|
289
311
|
for key in self.param_dict.keys():
|
|
290
|
-
if key.startswith(
|
|
312
|
+
if key.startswith("run1_"):
|
|
291
313
|
parname = key[5:]
|
|
292
|
-
if key in self.entries and
|
|
293
|
-
if self.entries[key].get() != self.entries[
|
|
294
|
-
self.entries[
|
|
314
|
+
if key in self.entries and "run2_" + parname in self.entries:
|
|
315
|
+
if self.entries[key].get() != self.entries["run2_" + parname].get():
|
|
316
|
+
self.entries["run2_" + parname].config(fg="red")
|
|
295
317
|
else:
|
|
296
|
-
self.entries[
|
|
318
|
+
self.entries["run2_" + parname].config(fg="black")
|