Coverage for src / zooc / run / temps_scan.py: 44%

58 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-11 21:45 +0000

1"""Methods for measuring Z-offset at given temperature ranges.""" 

2from __future__ import annotations 

3 

4import logging 

5from abc import ABC, abstractmethod 

6from collections.abc import Callable 

7from dataclasses import dataclass 

8from typing import override 

9 

10from zooc.data.offset_temp import OffsetTemp 

11from zooc.data.temps import Temps 

12 

13from .measure_z import MeasureZ 

14from .run_calibrate import RunCalibrate 

15 

16logger = logging.getLogger(__name__) 

17 

18 

19@dataclass(kw_only=True) 

20class TempScan(RunCalibrate, ABC): 

21 """Base class for various methods scanning through temperatures and measuring Z-offset. 

22 

23 :param klipper_module: See parent class: :py:class:`.run_calibrate.RunCalibrate`. 

24 :param gcmd: See parent class: :py:class:`.run_calibrate.RunCalibrate`. 

25 :param run_config: See parent class: :py:class:`.run_calibrate.RunCalibrate`. 

26 """ 

27 

28 @abstractmethod 

29 def get_temp_steps(self) -> int: 

30 """Get the number of temperature steps in the scan. 

31 

32 :return: Number of temperature steps. 

33 """ 

34 

35 @abstractmethod 

36 def scan(self, measure_z: MeasureZ, temps_set: Callable[[Temps], None]) -> list[OffsetTemp]: 

37 """Scan temperatures and run the Z-measurement method on each state. 

38 

39 Heat the printer through the temperatures and run the Z-measurement method. 

40 

41 :param measure_z: Z-measure method. Takes care of settling etc. 

42 :param temps_set: Callback to set temperatures. 

43 :return: List of measured Z-offsets for each scanned temperature. 

44 """ 

45 

46 

47@dataclass(kw_only=True) 

48class TempScanSimple(TempScan): 

49 """Simple and fast temperature scan. 

50 

51 Heat the system to selected temperatures while keeping the other at reference value and call callback. 

52 

53 :param klipper_module: See parent class: :py:class:`TempScan`. 

54 :param gcmd: See parent class: :py:class:`TempScan`. 

55 :param run_config: See parent class: :py:class:`TempScan`. 

56 """ 

57 

58 @override 

59 def get_temp_steps(self) -> int: 

60 return len(self.run_config.bed_temps) + len(self.run_config.extruder_temps) 

61 

62 @override 

63 def scan(self, measure_z: MeasureZ, temps_set: Callable[[Temps], None]) -> list[OffsetTemp]: 

64 measure_datas = [] 

65 # Run bed temps at reference extruder temp 

66 extruder_temp_ref = self.run_config.temps_ref.extruder_temp 

67 for bed_temp in self.run_config.bed_temps: 

68 temps = Temps.klipper(bed_temp, extruder_temp_ref) 

69 temps_set(temps) 

70 z_offset, aux_data = measure_z.measure() 

71 measure_datas.append(OffsetTemp.build(temps=temps, z_offset=z_offset, aux_data=aux_data)) 

72 

73 # Run extruder temps at reference bed temp 

74 bed_temp_ref = self.run_config.temps_ref.bed_temp 

75 for extruder_temp in self.run_config.extruder_temps: 

76 temps = Temps.klipper(bed_temp_ref, extruder_temp) 

77 temps_set(temps) 

78 z_offset, aux_data = measure_z.measure() 

79 measure_datas.append(OffsetTemp.build(temps=temps, z_offset=z_offset, aux_data=aux_data)) 

80 

81 return measure_datas 

82 

83 

84@dataclass(kw_only=True) 

85class TempScanFull(TempScan): 

86 """Scan all bed and extruder temperatures, i.e. full matrix. 

87 

88 :param klipper_module: See parent class: :py:class:`TempScan`. 

89 :param gcmd: See parent class: :py:class:`TempScan`. 

90 :param run_config: See parent class: :py:class:`TempScan`. 

91 """ 

92 

93 @override 

94 def get_temp_steps(self) -> int: 

95 return len(self.run_config.bed_temps) * len(self.run_config.extruder_temps) 

96 

97 @override 

98 def scan(self, measure_z: MeasureZ, temps_set: Callable[[Temps], None]) -> list[OffsetTemp]: 

99 measure_datas = [] 

100 

101 bed_temps: list[float] = self.run_config.bed_temps 

102 extruder_temps: list[float] = list(self.run_config.extruder_temps) # make copy 

103 

104 for bed_temp in bed_temps: 

105 for extruder_temp in extruder_temps: 

106 temps = Temps.klipper(bed_temp, extruder_temp) 

107 temps_set(temps) 

108 z_offset, aux_data = measure_z.measure() 

109 logger.info(f"Z-offset measured at {temps} z={z_offset:.3f} mm") 

110 logger.debug(f"aux_data={aux_data}") 

111 measure_datas.append(OffsetTemp.build(temps=temps, z_offset=z_offset, aux_data=aux_data)) 

112 # Next round, start from the previous extruder temperature, i.e. in reversed order. 

113 extruder_temps.reverse() # reverse in-place 

114 return measure_datas