Source code for knitout_interpreter.knitout_operations.needle_instructions

"""Needle operations"""
from __future__ import annotations

from virtual_knitting_machine.Knitting_Machine import Knitting_Machine
from virtual_knitting_machine.knitting_machine_exceptions.Needle_Exception import Misaligned_Needle_Exception
from virtual_knitting_machine.machine_components.carriage_system.Carriage_Pass_Direction import Carriage_Pass_Direction
from virtual_knitting_machine.machine_components.needles.Needle import Needle
from virtual_knitting_machine.machine_components.yarn_management.Yarn_Carrier import Yarn_Carrier
from virtual_knitting_machine.machine_components.yarn_management.Yarn_Carrier_Set import Yarn_Carrier_Set
from virtual_knitting_machine.machine_constructed_knit_graph.Machine_Knit_Loop import Machine_Knit_Loop
from virtual_knitting_machine.machine_constructed_knit_graph.Machine_Knit_Yarn import Machine_Knit_Yarn

from knitout_interpreter.knitout_operations.knitout_instruction import Knitout_Instruction, Knitout_Instruction_Type


[docs] class Needle_Instruction(Knitout_Instruction): def __init__(self, instruction_type: Knitout_Instruction_Type, needle: Needle, direction: None | str | Carriage_Pass_Direction = None, needle_2: None | Needle = None, carrier_set: None | Yarn_Carrier_Set = None, comment: None | str = None): super().__init__(instruction_type, comment, interrupts_carriage_pass=False) self.carrier_set = carrier_set self.needle_2 = needle_2 if direction is not None and isinstance(direction, str): direction = Carriage_Pass_Direction.get_direction(direction) self.direction: None | Carriage_Pass_Direction = direction self.needle = needle self.carriage_pass = None self.made_loops: list[Machine_Knit_Loop] = [] self.moved_loops: list[Machine_Knit_Loop] = [] self.dropped_loops: list[Machine_Knit_Loop] = []
[docs] def get_yarns(self, knitting_machine: Knitting_Machine) -> dict[int, Machine_Knit_Yarn]: """Get the yarns currently active on the carriers. Args: knitting_machine: The knitting machine to access yarn data from. Returns: Dictionary mapping carrier IDs to the yarn that is currently active on them. """ return {cid: carrier.yarn for cid, carrier in self.get_carriers(knitting_machine).items()}
[docs] def get_carriers(self, knitting_machine: Knitting_Machine) -> dict[int, Yarn_Carrier]: """Get the carriers currently active for this instruction. Args: knitting_machine: The knitting machine to access carrier data from. Returns: Dictionary mapping carrier IDs to the carrier objects that are currently active. """ if self.carrier_set is None: return {} else: return {cid: knitting_machine.carrier_system[cid] for cid in self.carrier_set.carrier_ids}
@property def has_second_needle(self) -> bool: """Check if this instruction has a second needle. Returns: True if it has a second needle. """ return self.needle_2 is not None @property def has_direction(self) -> bool: """Check if this instruction has a direction value. Returns: True if it has a direction value. """ return self.direction is not None @property def has_carrier_set(self) -> bool: """Check if this instruction has a carrier set. Returns: True if it has a carrier set. """ return self.carrier_set is not None @property def implied_racking(self) -> None | int: """Get the racking required for this operation. Returns: None if no specific racking is required, or the required racking value to complete this operation. """ if self.has_second_needle: return int(Knitting_Machine.get_transfer_rack(self.needle, self.needle_2)) else: return None def _test_operation(self) -> None: """Test if the operation has all required parameters.""" if self.instruction_type.directed_pass: assert self.has_direction, f"Cannot {self.instruction_type} without a direction" if self.instruction_type.requires_second_needle: assert self.has_second_needle, f"Cannot {self.instruction_type} without target needle" if self.instruction_type.requires_carrier: assert self.has_carrier_set, f"Cannot {self.instruction_type} without a carrier set" def __str__(self) -> str: if self.has_direction: dir_str = f" {self.direction}" else: dir_str = "" if self.has_second_needle: n2_str = f" {self.needle_2}" else: n2_str = "" if self.has_carrier_set: cs_str = f" {self.carrier_set}" else: cs_str = "" return f"{self.instruction_type}{dir_str} {self.needle}{n2_str}{cs_str}{self.comment_str}"
[docs] class Loop_Making_Instruction(Needle_Instruction): """Base class for instructions that create loops.""" def __init__(self, instruction_type: Knitout_Instruction_Type, needle: Needle, direction: None | str | Carriage_Pass_Direction = None, needle_2: None | Needle = None, carrier_set: Yarn_Carrier_Set = None, comment: None | str = None): super().__init__(instruction_type, needle, direction, needle_2, carrier_set, comment)
[docs] class Knit_Instruction(Loop_Making_Instruction): """Instruction for knitting a loop on a needle.""" def __init__(self, needle: Needle, direction: str | Carriage_Pass_Direction, cs: Yarn_Carrier_Set, comment: None | str = None): super().__init__(Knitout_Instruction_Type.Knit, needle, direction=direction, carrier_set=cs, comment=comment)
[docs] def execute(self, machine_state: Knitting_Machine) -> bool: self._test_operation() self.dropped_loops, self.made_loops = machine_state.knit(self.carrier_set, self.needle, self.direction) return True # true even if loops is empty because the prior loops are dropped.
[docs] @staticmethod def execute_knit(machine_state: Knitting_Machine, needle: Needle, direction: str | Carriage_Pass_Direction, cs: Yarn_Carrier_Set, comment: str | None = None) -> Knit_Instruction: """Execute a knit instruction on the machine. Args: machine_state: The current machine model to update. needle: The needle to execute on. direction: The direction to execute in. cs: The yarn carriers set to execute with. comment: Additional details to document in the knitout. Returns: The instruction that was executed. """ instruction = Knit_Instruction(needle, direction, cs, comment) instruction.execute(machine_state) return instruction
[docs] class Tuck_Instruction(Loop_Making_Instruction): """Instruction for tucking yarn on a needle without dropping existing loops.""" def __init__(self, needle: Needle, direction: str | Carriage_Pass_Direction, cs: Yarn_Carrier_Set, comment: None | str = None): super().__init__(Knitout_Instruction_Type.Tuck, needle, direction=direction, carrier_set=cs, comment=comment)
[docs] def execute(self, machine_state: Knitting_Machine) -> bool: self._test_operation() self.made_loops = machine_state.tuck(self.carrier_set, self.needle, self.direction) return len(self.made_loops) > 0
[docs] @staticmethod def execute_tuck(machine_state: Knitting_Machine, needle: Needle, direction: str | Carriage_Pass_Direction, cs: Yarn_Carrier_Set, comment: str | None = None) -> Tuck_Instruction: """Execute a tuck instruction on the machine. Args: machine_state: The current machine model to update. needle: The needle to execute on. direction: The direction to execute in. cs: The yarn carriers set to execute with. comment: Additional details to document in the knitout. Returns: The instruction that was executed. """ instruction = Tuck_Instruction(needle, direction, cs, comment) instruction.execute(machine_state) return instruction
[docs] class Split_Instruction(Loop_Making_Instruction): """Instruction for splitting a loop between two needles.""" def __init__(self, needle: Needle, direction: Carriage_Pass_Direction, n2: Needle, cs: Yarn_Carrier_Set, comment: None | str = None): super().__init__(Knitout_Instruction_Type.Split, needle, direction=direction, needle_2=n2, carrier_set=cs, comment=comment)
[docs] def execute(self, machine_state: Knitting_Machine) -> bool: self._test_operation() aligned_needle = machine_state.get_aligned_needle(self.needle) if aligned_needle != self.needle_2: raise Misaligned_Needle_Exception(self.needle, self.needle_2) self.made_loops, self.moved_loops = machine_state.split(self.carrier_set, self.needle, self.direction) return len(self.made_loops) > 0 or len(self.moved_loops) > 0
[docs] @staticmethod def execute_split(machine_state: Knitting_Machine, needle: Needle, direction: str | Carriage_Pass_Direction, cs: Yarn_Carrier_Set, n2: Needle, comment: str | None = None) -> Split_Instruction: """Execute a split instruction on the machine. Args: machine_state: The current machine model to update. needle: The needle to execute on. direction: The direction to execute in. cs: The yarn carriers set to execute with. n2: The second needle to execute to. comment: Additional details to document in the knitout. Returns: The instruction that was executed. """ instruction = Split_Instruction(needle, direction, n2, cs, comment) instruction.execute(machine_state) return instruction
[docs] class Drop_Instruction(Needle_Instruction): """Instruction for dropping loops from a needle.""" def __init__(self, needle: Needle, comment: None | str = None): super().__init__(Knitout_Instruction_Type.Drop, needle, comment=comment)
[docs] def execute(self, machine_state: Knitting_Machine) -> bool: self._test_operation() self.dropped_loops = machine_state.drop(self.needle) return True
[docs] @staticmethod def execute_Drop(machine_state: Knitting_Machine, needle: Needle, comment: str | None = None) -> Drop_Instruction: """Execute a drop instruction on the machine. Args: machine_state: The current machine model to update. needle: The needle to execute on. comment: Additional details to document in the knitout. Returns: The instruction that was executed. """ instruction = Drop_Instruction(needle, comment) instruction.execute(machine_state) return instruction
[docs] class Xfer_Instruction(Needle_Instruction): """Instruction for transferring loops between needles.""" def __init__(self, needle: Needle, n2: Needle, comment: None | str = None, record_location: bool = True): super().__init__(Knitout_Instruction_Type.Xfer, needle, needle_2=n2, comment=comment) self.record_location: bool = record_location self.loop_crossings_made: dict[Machine_Knit_Loop, list[Machine_Knit_Loop]] = {} # Todo: Use loop crossing code.
[docs] def add_loop_crossing(self, left_loop: Machine_Knit_Loop, right_loop: Machine_Knit_Loop) -> None: """Update loop crossing to show transfers crossing loops. Args: left_loop: The left loop involved in the crossing. right_loop: The right loop involved in the crossing. """ if left_loop not in self.loop_crossings_made: self.loop_crossings_made[left_loop] = [] self.loop_crossings_made[left_loop].append(right_loop)
[docs] def execute(self, machine_state: Knitting_Machine) -> bool: self._test_operation() assert isinstance(self.needle_2, Needle) to_slider = self.needle_2.is_slider aligned_needle = machine_state.get_aligned_needle(self.needle, aligned_slider=to_slider) if aligned_needle != self.needle_2: raise Misaligned_Needle_Exception(self.needle, self.needle_2) self.moved_loops = machine_state.xfer(self.needle, to_slider=to_slider) return len(self.moved_loops) > 0
[docs] @staticmethod def execute_xfer(machine_state: Knitting_Machine, needle: Needle, n2: Needle, comment: str | None = None) -> Xfer_Instruction: """Execute a transfer instruction on the machine. Args: machine_state: The current machine model to update. needle: The needle to execute on. n2: The second needle to execute to. comment: Additional details to document in the knitout. Returns: The instruction that was executed. """ instruction = Xfer_Instruction(needle, n2, comment) instruction.execute(machine_state) return instruction
[docs] class Miss_Instruction(Needle_Instruction): """Instruction for positioning carriers above a needle without forming loops.""" def __init__(self, needle: Needle, direction: str | Carriage_Pass_Direction, cs: Yarn_Carrier_Set, comment: None | str = None): super().__init__(Knitout_Instruction_Type.Miss, needle, direction=direction, carrier_set=cs, comment=comment)
[docs] def execute(self, machine_state: Knitting_Machine) -> bool: """Position the carrier above the given needle. Args: machine_state: The machine state to update. Returns: True indicating the operation completed successfully. """ self._test_operation() machine_state.miss(self.carrier_set, self.needle, self.direction) return True
[docs] @staticmethod def execute_miss(machine_state: Knitting_Machine, needle: Needle, direction: str | Carriage_Pass_Direction, cs: Yarn_Carrier_Set, comment: str | None = None) -> Miss_Instruction: """Execute a miss instruction on the machine. Args: machine_state: The current machine model to update. needle: The needle to execute on. direction: The direction to execute in. cs: The yarn carriers set to execute with. comment: Additional details to document in the knitout. Returns: The instruction that was executed. """ instruction = Miss_Instruction(needle, direction, cs, comment) instruction.execute(machine_state) return instruction