Skip to content

Commit 7a72449

Browse files
mrosseelclaude
andcommitted
fix: resolve lint errors for CI
- Add builtins = ["_"] for i18n function - Add per-file-ignores for notebooks - Remove unused imports (multiprocessing, utils, GITHUB_REPO) - Remove duplicate BallTree import - Rename ambiguous variable l to label - Apply ruff formatting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 1cb5199 commit 7a72449

29 files changed

Lines changed: 1108 additions & 718 deletions

python/PiFinder/audit_images.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ def check_object_image(catalog_object):
4444
aka_rec = conn.execute(
4545
f"""
4646
SELECT common_name from names
47-
where catalog = "{catalog_object['catalog']}"
48-
and sequence = "{catalog_object['sequence']}"
47+
where catalog = "{catalog_object["catalog"]}"
48+
and sequence = "{catalog_object["sequence"]}"
4949
and common_name like "NGC%"
5050
"""
5151
).fetchone()

python/PiFinder/auto_exposure.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ def handle(
534534
self._sweep_results = []
535535
logger.debug(
536536
f"Histogram handler activated: starting {self._sweep_steps}-step histogram sweep "
537-
f"from {self._sweep_exposures[0]/1000:.1f}ms to {self._sweep_exposures[-1]/1000:.1f}ms"
537+
f"from {self._sweep_exposures[0] / 1000:.1f}ms to {self._sweep_exposures[-1] / 1000:.1f}ms"
538538
)
539539
return self._sweep_exposures[0]
540540

@@ -548,16 +548,16 @@ def handle(
548548
self._sweep_results.append((sweep_exposure, viable, metrics))
549549

550550
logger.debug(
551-
f"Histogram analysis for {sweep_exposure/1000:.1f}ms: "
551+
f"Histogram analysis for {sweep_exposure / 1000:.1f}ms: "
552552
f"viable={'YES' if viable else 'NO'}, "
553553
f"mean={metrics['mean']:.1f}, std={metrics['std']:.1f}, sat={metrics['saturation_pct']:.1f}%"
554554
)
555555

556556
# Track viable exposures but continue sweep to find best option
557557
if viable:
558558
logger.debug(
559-
f"Histogram handler: found viable exposure {sweep_exposure/1000:.1f}ms "
560-
f"(step {self._sweep_index+1}/{self._sweep_steps}), continuing sweep"
559+
f"Histogram handler: found viable exposure {sweep_exposure / 1000:.1f}ms "
560+
f"(step {self._sweep_index + 1}/{self._sweep_steps}), continuing sweep"
561561
)
562562

563563
# If we've completed the sweep, settle on target exposure
@@ -574,22 +574,22 @@ def handle(
574574
# Use highest viable exposure for best star detection
575575
self._target_exposure = max(viable_exposures)
576576
logger.debug(
577-
f"Histogram handler: settling on highest viable exposure {self._target_exposure/1000:.1f}ms"
577+
f"Histogram handler: settling on highest viable exposure {self._target_exposure / 1000:.1f}ms"
578578
)
579579
else:
580580
# No viable exposures - use highest from sweep
581581
highest_exp = self._sweep_results[-1][0]
582582
self._target_exposure = highest_exp
583583
logger.debug(
584-
f"Histogram handler: no viable exposure found, using highest {highest_exp/1000:.1f}ms"
584+
f"Histogram handler: no viable exposure found, using highest {highest_exp / 1000:.1f}ms"
585585
)
586586
else:
587587
# Fallback to middle exposure
588588
middle_idx = len(self._sweep_exposures) // 2
589589
middle_exp = self._sweep_exposures[middle_idx]
590590
self._target_exposure = middle_exp
591591
logger.debug(
592-
f"Histogram handler: no analysis data, using middle {middle_exp/1000:.1f}ms"
592+
f"Histogram handler: no analysis data, using middle {middle_exp / 1000:.1f}ms"
593593
)
594594

595595
# Hold at target
@@ -602,7 +602,7 @@ def handle(
602602
if self._sweep_index < len(self._sweep_exposures):
603603
next_exp = self._sweep_exposures[self._sweep_index]
604604
logger.debug(
605-
f"Histogram handler: sweep step {self._sweep_index+1}/{self._sweep_steps}{next_exp/1000:.1f}ms"
605+
f"Histogram handler: sweep step {self._sweep_index + 1}/{self._sweep_steps}{next_exp / 1000:.1f}ms"
606606
)
607607
return next_exp
608608
else:
@@ -663,7 +663,7 @@ def __init__(
663663
logger.info(
664664
f"AutoExposure SNR: target_bg={target_background}, "
665665
f"range=[{min_background}, {max_background}] ADU, "
666-
f"exp_range=[{min_exposure/1000:.0f}, {max_exposure/1000:.0f}]ms, "
666+
f"exp_range=[{min_exposure / 1000:.0f}, {max_exposure / 1000:.0f}]ms, "
667667
f"adjustment={adjustment_factor}x"
668668
)
669669

@@ -694,7 +694,7 @@ def from_camera_profile(
694694
profile = get_camera_profile(camera_type)
695695

696696
# Derive thresholds from camera specs
697-
max_adu = (2 ** profile.bit_depth) - 1
697+
max_adu = (2**profile.bit_depth) - 1
698698
bias = profile.bias_offset
699699

700700
# min_background: bias + margin (2x bias or bias + 8, whichever larger)
@@ -726,7 +726,7 @@ def update(
726726
current_exposure: int,
727727
image: Image.Image,
728728
noise_floor: Optional[float] = None,
729-
**kwargs # Ignore other params (matched_stars, etc.)
729+
**kwargs, # Ignore other params (matched_stars, etc.)
730730
) -> Optional[int]:
731731
"""
732732
Update exposure based on background level.
@@ -756,7 +756,7 @@ def update(
756756
background = float(np.percentile(img_array, 10))
757757

758758
logger.debug(
759-
f"SNR AE: bg={background:.1f}, min={min_bg:.1f} ADU, exp={current_exposure/1000:.0f}ms"
759+
f"SNR AE: bg={background:.1f}, min={min_bg:.1f} ADU, exp={current_exposure / 1000:.0f}ms"
760760
)
761761

762762
# Determine adjustment
@@ -767,14 +767,14 @@ def update(
767767
new_exposure = int(current_exposure * self.adjustment_factor)
768768
logger.info(
769769
f"SNR AE: Background too low ({background:.1f} < {min_bg:.1f}), "
770-
f"increasing exposure {current_exposure/1000:.0f}ms → {new_exposure/1000:.0f}ms"
770+
f"increasing exposure {current_exposure / 1000:.0f}ms → {new_exposure / 1000:.0f}ms"
771771
)
772772
elif background > self.max_background:
773773
# Too bright - decrease exposure
774774
new_exposure = int(current_exposure / self.adjustment_factor)
775775
logger.info(
776776
f"SNR AE: Background too high ({background:.1f} > {self.max_background}), "
777-
f"decreasing exposure {current_exposure/1000:.0f}ms → {new_exposure/1000:.0f}ms"
777+
f"decreasing exposure {current_exposure / 1000:.0f}ms → {new_exposure / 1000:.0f}ms"
778778
)
779779
else:
780780
# Background is in acceptable range
@@ -908,7 +908,9 @@ def _update_pid(self, matched_stars: int, current_exposure: int) -> Optional[int
908908
# from crashing exposure when conditions change suddenly
909909
# (e.g., going from too many stars to too few stars)
910910
if self._last_error is not None:
911-
if (error > 0 and self._last_error < 0) or (error < 0 and self._last_error > 0):
911+
if (error > 0 and self._last_error < 0) or (
912+
error < 0 and self._last_error > 0
913+
):
912914
logger.debug(
913915
f"PID: Error sign changed ({self._last_error:.0f}{error:.0f}), resetting integral"
914916
)

python/PiFinder/camera_interface.py

Lines changed: 31 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,8 @@ def _process_pending_commands(self):
141141
self.exposure_time = int(exp_value)
142142
self.set_camera_config(self.exposure_time, self.gain)
143143
self._cfg.set_option("camera_exp", self.exposure_time)
144-
self._console_queue.put(
145-
"CAM: Exp=" + str(self.exposure_time)
146-
)
147-
logger.info(
148-
f"Manual exposure set: {self.exposure_time}µs"
149-
)
144+
self._console_queue.put("CAM: Exp=" + str(self.exposure_time))
145+
logger.info(f"Manual exposure set: {self.exposure_time}µs")
150146

151147
elif command.startswith("set_gain"):
152148
old_gain = self.gain
@@ -172,9 +168,7 @@ def _process_pending_commands(self):
172168
max_exposure=self._auto_exposure_pid.max_exposure,
173169
)
174170
elif handler_type == "reset":
175-
new_handler = ResetZeroStarHandler(
176-
reset_exposure=400000
177-
)
171+
new_handler = ResetZeroStarHandler(reset_exposure=400000)
178172
elif handler_type == "histogram":
179173
new_handler = HistogramZeroStarHandler(
180174
min_exposure=self._auto_exposure_pid.min_exposure,
@@ -186,12 +180,8 @@ def _process_pending_commands(self):
186180
)
187181

188182
if new_handler is not None:
189-
self._auto_exposure_pid._zero_star_handler = (
190-
new_handler
191-
)
192-
self._console_queue.put(
193-
f"CAM: AE Handler={handler_type}"
194-
)
183+
self._auto_exposure_pid._zero_star_handler = new_handler
184+
self._console_queue.put(f"CAM: AE Handler={handler_type}")
195185
logger.info(
196186
f"Auto-exposure zero-star handler changed to: {handler_type}"
197187
)
@@ -204,12 +194,8 @@ def _process_pending_commands(self):
204194
mode = command.split(":")[1]
205195
if mode in ["pid", "snr"]:
206196
self._auto_exposure_mode = mode
207-
self._console_queue.put(
208-
f"CAM: AE Mode={mode.upper()}"
209-
)
210-
logger.info(
211-
f"Auto-exposure mode changed to: {mode.upper()}"
212-
)
197+
self._console_queue.put(f"CAM: AE Mode={mode.upper()}")
198+
logger.info(f"Auto-exposure mode changed to: {mode.upper()}")
213199
else:
214200
logger.warning(
215201
f"Unknown auto-exposure mode: {mode} (valid: pid, snr)"
@@ -222,17 +208,13 @@ def _process_pending_commands(self):
222208
else:
223209
self.exposure_time = int(self.exposure_time * 0.75)
224210
self.set_camera_config(self.exposure_time, self.gain)
225-
self._console_queue.put(
226-
"CAM: Exp=" + str(self.exposure_time)
227-
)
211+
self._console_queue.put("CAM: Exp=" + str(self.exposure_time))
228212

229213
elif command == "exp_save":
230214
self._auto_exposure_enabled = False
231215
self._cfg.set_option("camera_exp", self.exposure_time)
232216
self._cfg.set_option("camera_gain", int(self.gain))
233-
self._console_queue.put(
234-
f"CAM: Exp Saved ({self.exposure_time}µs)"
235-
)
217+
self._console_queue.put(f"CAM: Exp Saved ({self.exposure_time}µs)")
236218
logger.info(
237219
f"Exposure saved and auto-exposure disabled: {self.exposure_time}µs"
238220
)
@@ -241,17 +223,12 @@ def _process_pending_commands(self):
241223
self._save_next_to = command.split(":")[1]
242224
self._console_queue.put("CAM: Save flag set")
243225

244-
elif (
245-
command.startswith("capture")
246-
and command != "capture_exp_sweep"
247-
):
226+
elif command.startswith("capture") and command != "capture_exp_sweep":
248227
captured_image = self.capture()
249228
self._camera_image.paste(captured_image)
250229

251230
if self._save_next_to:
252-
filename = (
253-
f"{utils.data_dir}/captures/{self._save_next_to}"
254-
)
231+
filename = f"{utils.data_dir}/captures/{self._save_next_to}"
255232
if not filename.endswith(".png"):
256233
filename += ".png"
257234
self.capture_file(filename)
@@ -278,9 +255,7 @@ def _process_pending_commands(self):
278255
self._console_queue.put("CAM: Started camera")
279256

280257
except ValueError as e:
281-
logger.error(
282-
f"Error processing camera command '{command}': {str(e)}"
283-
)
258+
logger.error(f"Error processing camera command '{command}': {str(e)}")
284259

285260
def _run_exposure_sweep(self, command):
286261
"""Capture exposure sweep for SQM testing."""
@@ -336,15 +311,11 @@ def _run_exposure_sweep(self, command):
336311

337312
exp_ms = exp_us / 1000
338313

339-
processed_filename = (
340-
sweep_dir / f"img_{i:03d}_{exp_ms:.2f}ms_processed.png"
341-
)
314+
processed_filename = sweep_dir / f"img_{i:03d}_{exp_ms:.2f}ms_processed.png"
342315
processed_img = self.capture()
343316
processed_img.save(str(processed_filename))
344317

345-
raw_filename = (
346-
sweep_dir / f"img_{i:03d}_{exp_ms:.2f}ms_raw.tiff"
347-
)
318+
raw_filename = sweep_dir / f"img_{i:03d}_{exp_ms:.2f}ms_raw.tiff"
348319
self.capture_raw_file(str(raw_filename))
349320

350321
logger.debug(
@@ -379,23 +350,19 @@ def _run_exposure_sweep(self, command):
379350
observer_lat=location.lat,
380351
observer_lon=location.lon,
381352
observer_altitude_m=location.altitude,
382-
gps_datetime=gps_datetime.isoformat()
383-
if gps_datetime
384-
else None,
353+
gps_datetime=gps_datetime.isoformat() if gps_datetime else None,
385354
reference_sqm=reference_sqm,
386355
ra_deg=ra_deg,
387356
dec_deg=dec_deg,
388357
altitude_deg=altitude_deg,
389358
azimuth_deg=azimuth_deg,
390-
notes=f"Exposure sweep: {num_images} images, {min_exp/1000:.1f}-{max_exp/1000:.1f}ms",
359+
notes=f"Exposure sweep: {num_images} images, {min_exp / 1000:.1f}-{max_exp / 1000:.1f}ms",
391360
)
392361
logger.info(
393362
f"Successfully saved sweep metadata to {sweep_dir}/sweep_metadata.json"
394363
)
395364
except Exception as e:
396-
logger.error(
397-
f"Failed to save sweep metadata: {e}", exc_info=True
398-
)
365+
logger.error(f"Failed to save sweep metadata: {e}", exc_info=True)
399366

400367
self._console_queue.put("CAM: Sweep done!")
401368
logger.info(
@@ -566,22 +533,29 @@ def get_image_loop(
566533
if self._auto_exposure_snr is None:
567534
# Use camera profile to derive thresholds
568535
try:
569-
cam_type = detect_camera_type(self.get_cam_type())
536+
cam_type = detect_camera_type(
537+
self.get_cam_type()
538+
)
570539
cam_type = f"{cam_type}_processed"
571-
self._auto_exposure_snr = (
572-
ExposureSNRController.from_camera_profile(cam_type)
540+
self._auto_exposure_snr = ExposureSNRController.from_camera_profile(
541+
cam_type
573542
)
574543
except ValueError as e:
575544
# Unknown camera, use defaults
576545
logger.warning(
577546
f"Camera detection failed: {e}, using default SNR thresholds"
578547
)
579-
self._auto_exposure_snr = ExposureSNRController()
548+
self._auto_exposure_snr = (
549+
ExposureSNRController()
550+
)
580551
# Get adaptive noise floor from shared state
581-
adaptive_noise_floor = self.shared_state.noise_floor()
552+
adaptive_noise_floor = (
553+
self.shared_state.noise_floor()
554+
)
582555
new_exposure = self._auto_exposure_snr.update(
583-
self.exposure_time, base_image,
584-
noise_floor=adaptive_noise_floor
556+
self.exposure_time,
557+
base_image,
558+
noise_floor=adaptive_noise_floor,
585559
)
586560
else:
587561
# PID mode: use star-count based controller (default)

python/PiFinder/catalog_imports/catalog_import_utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ def insert_catalog_max_sequence(catalog_name):
213213
if result:
214214
query = f"""
215215
update catalogs set max_sequence = {
216-
dict(result)['MAX(sequence)']} where catalog_code = '{catalog_name}'
216+
dict(result)["MAX(sequence)"]
217+
} where catalog_code = '{catalog_name}'
217218
"""
218219
db_c.execute(query)
219220
conn.commit()
@@ -322,7 +323,7 @@ def resolve_object_images():
322323
ORDER BY {priority_case_sql}
323324
) as priority_rank
324325
FROM catalog_objects co
325-
WHERE co.catalog_code IN ({','.join(['?'] * len(catalog_priority))})
326+
WHERE co.catalog_code IN ({",".join(["?"] * len(catalog_priority))})
326327
)
327328
SELECT
328329
o.id as object_id,

python/PiFinder/catalog_imports/specialized_loaders.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ def expand(name):
602602
for additional in parts[1:]:
603603
if additional.isdigit():
604604
# If the additional part is a number, add it directly
605-
expanded_list.append(f"{base_part[:-len(additional)]}{additional}")
605+
expanded_list.append(f"{base_part[: -len(additional)]}{additional}")
606606
else:
607607
expanded_list.append(additional)
608608
else:

python/PiFinder/catalog_imports/wds_loader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def handle_multiples(key, values) -> dict:
263263
coord_2000 = entry["Coordinates_2000"]
264264
coord_arcsec = entry["Coordinates_Arcsec"]
265265
logging.error(
266-
f"Empty or invalid RA/DEC detected for WDS object at line {i+1}"
266+
f"Empty or invalid RA/DEC detected for WDS object at line {i + 1}"
267267
)
268268
logging.error(f" Coordinates_2000: '{coord_2000}'")
269269
logging.error(f" Coordinates_Arcsec: '{coord_arcsec}'")
@@ -273,7 +273,7 @@ def handle_multiples(key, values) -> dict:
273273
)
274274
logging.error(f" Final RA: {entry['ra']}, DEC: {entry['dec']}")
275275
raise ValueError(
276-
f"Invalid RA/DEC coordinates for WDS object at line {i+1}: RA={entry['ra']}, DEC={entry['dec']}"
276+
f"Invalid RA/DEC coordinates for WDS object at line {i + 1}: RA={entry['ra']}, DEC={entry['dec']}"
277277
)
278278

279279
# make a dictionary of WDS objects to group duplicates

python/PiFinder/catalogs.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,7 @@ def is_loading(self) -> bool:
481481
def start_background_loading(self):
482482
"""Start deferred catalog loading in background thread.
483483
Call after event loop is ready to avoid SD I/O contention during startup."""
484-
if (
485-
hasattr(self, "_background_loader")
486-
and self._background_loader is not None
487-
):
484+
if hasattr(self, "_background_loader") and self._background_loader is not None:
488485
self._background_loader.start()
489486

490487
def __repr__(self):

0 commit comments

Comments
 (0)