aigarmic.plate ============== .. py:module:: aigarmic.plate .. autoapi-nested-parse:: Class implementation for plates Classes ------- .. autoapisummary:: aigarmic.plate.Model aigarmic.plate.Plate aigarmic.plate.PlateSet Functions --------- .. autoapisummary:: aigarmic.plate.split_by_grid aigarmic.plate.get_image_paths aigarmic.plate.get_concentration_from_path aigarmic.plate.plate_set_from_dir Module Contents --------------- .. py:function:: split_by_grid(image: numpy.ndarray, n_rows: int, n_cols: int, visualise_contours: bool = False, plate_name: Optional[str] = None) -> list[list[numpy.ndarray]] Split an agar plate image into individual colony sub-images using a grid overlay. :param image: image file loaded using cv2.imread :param n_rows: number of rows in the grid :param n_cols: number of columns in the grid :param visualise_contours: if True, display the contours found (useful for validation) :param plate_name: name of plate to display in visualisation (useful for validation) :return: matrix of sub-images .. py:class:: Model(key: Optional[list[str]]) Bases: :py:obj:`abc.ABC` Helper class that provides a standard way to create an ABC using inheritance. .. py:method:: get_key() -> list[str] Return key to convert model output to human-readable label :return: .. py:method:: predict(image) -> dict :abstractmethod: .. py:function:: get_image_paths(dir_path, extensions: tuple[str, Ellipsis] = ('.jpg', '.JPG')) -> Union[list[str], dict[str, list[str]]] If there are no subdirectories in dir, returns a list of image paths If there are subdirectories, returns a dict of 'subdir_name': 'path' :param dir_path: Path to directory containing images :param extensions: Tuple of image extensions to search for :return: List of image paths or dict of 'subdir_name': 'path' .. py:function:: get_concentration_from_path(path: Union[str, pathlib.Path]) -> float get concentration from plate image path, e.g. antibiotic1/0.125.jpg -> 0.125 :param path: Path to plate image :return: Concentration .. py:class:: Plate(drug: str, concentration: float, image: Optional[Union[str, cv2.typing.MatLike]] = None, n_row: Optional[int] = None, n_col: Optional[int] = None, growth_code_matrix: Optional[list[list[int]]] = None, visualise_contours: bool = False, model: Optional[aigarmic.model.Model] = None, key: Optional[list[str]] = None) .. py:method:: add_growth_code_matrix(growth_code_matrix: list[list[int]]) -> None .. py:method:: valid_growth_code_matrix(growth_code_matrix: list[list[int]]) -> bool .. py:method:: matrix_dimensions(matrix) -> tuple[int, Ellipsis] :staticmethod: Get dimensions of a matrix :param matrix: matrix to get dimensions of :raises ValueError: if matrix is not 2D or is not a valid matrix :return: tuple of dimensions .. py:method:: split_images(visualise_contours: bool = False) -> None Splits images into individual colony images using grid :param visualise_contours: Visualise the contours of the plate (useful for validation of grid splitting) .. py:method:: import_image(image: numpy.ndarray) -> None Import and save image of agar plate :param image: loaded using cv2.imread .. py:method:: get_colony_image(index: Optional[tuple[int, int]] = None) -> tuple[numpy.ndarray, str] Pulls colony image and associated code-stamp Code-stamps are strings containing, in sequence: - Antibiotic name - Antibiotic concentration - Row (i) index - Column (j) index If no index is provided (default) a random image is given @param index: tuple of row and column index @return: tuple of image and code-stamp (e.g., "drug_0.125_i_1_j_2") .. py:method:: link_model(model: aigarmic.model.Model) -> None Link model to plate for predictions :param model: Model to link .. py:method:: get_key() -> Optional[list[str]] Get key from linked Model :raises: LookupError: No linked model to get key from :return: Key (or None if one is not found) .. py:method:: set_key(key: list[str]) -> None Set plate key. Checks whether differs from linked model key (if any), and warns if different. :param key: List of growth categories (zero-indexed) .. py:method:: annotate_images(model: Optional[aigarmic.model.Model] = None) -> list[list[str]] Annotate plate images :param model: linked model to use for predictions :return: Two-dimensional list of growth annotations .. py:method:: print_matrix() -> None Print growth matrix in human-readable format .. py:method:: get_inaccurate_images(threshold: float = 0.9) -> set[tuple[int, int]] Get indexes of images with prediction accuracy below threshold :param threshold: Prediction threshold :return: Set containing indices of inaccurate images .. py:method:: review_poor_images(threshold: float = 0.9, save_dir: str = None) -> list[tuple[int, int]] Review and re-classify images with prediction accuracy below threshold. Classes should be zero indexed (e.g., 0, 1, 2). Currently, only supports up to 9. If save_dir provided then colony images will also be saved to a subdirectory (named after the new classification), to allow for future use in training. Enter new classification for each image using numbers (e.g., 0/1/2) on keyboard, press enter to skip, press esc to stop reviewing the plate. :param threshold: Prediction threshold to identify inaccurate images :param save_dir: Directory to save re-classified images :return: List of indices of re-classified images .. py:method:: convert_growth_codes(key: list[str]) -> list[list[str]] Convert growth codes to human-readable format using key E.g., [0, 1, 2] -> ["No growth", "Poor growth", "Good growth"] Sets self.growth_matrix :param key: List of growth codes (zero-indexed) :return: Growth matrix .. py:method:: __repr__() -> str Return repr(self). .. py:method:: __lt__(other) -> bool Return self bool Return self==value. .. py:method:: __gt__(other) -> bool Return self>value. .. py:method:: __le__(other) -> bool Return self<=value. .. py:method:: __ge__(other) -> bool Return self>=value. .. py:method:: __ne__(other) -> bool Return self!=value. .. py:method:: __hash__() -> int Return hash(self). .. py:class:: PlateSet(plates_list: list[Plate], key: Optional[list[str]] = None) .. py:method:: valid_dimensions() -> bool Check if all plates in PlateSet have the same x and y dimensions :return: True if all plates have the same dimensions, False otherwise .. py:method:: get_all_plates() -> list[Plate] Returns a sorted list of all plates in the PlateSet, including the control plate :return: List of Plate objects .. py:method:: convert_mic_matrix(mic_format: str = 'string') -> numpy.array Converts format of MIC matrix :param mic_format: Format to convert to (only "string" is supported) :return: matrix (array) of MIC values .. py:method:: calculate_mic(no_growth_key_items: tuple[int, Ellipsis]) -> numpy.array Calculate MIC matrix using image predictions. Sets self.mic_matrix :param no_growth_key_items: tuple of key items that should be classified as "no growth" for MIC purposes :return: MIC matrix .. py:method:: generate_qc() -> numpy.array Generate QC matrix for PlateSet, as follows: "F" = FAIL - no growth in positive control plate, result should be disregarded "W" = WARNING - more than one change in concentration gradient. There should only be one change at the MIC breakpoint (where the images change from growth to no/poor growth). Depending on the application of the results, manual confirmation should be considered for warnings. "P" = PASS - no QC issues found :return: Matrix of QC values (strings) .. py:method:: review_poor_images(threshold: float = 0.9, save_dir: Optional[str] = None) -> list[list[tuple[int, int]]] Review and re-classify images with prediction accuracy below threshold. Currently, supports up to 0--9 classes. If save_dir provided then colony images will also be saved to a subdirectory (named after the new classification), to allow for future use in training. Enter new classification for each image using 0/1/2 on keyboard, or press enter (or esc) to skip. :param threshold: Prediction threshold to identify inaccurate images :param save_dir: Directory to save re-classified images :return: List of indices of re-classified images .. py:method:: get_csv_data() -> list[dict] Get MIC and QC data in a format suitable for CSV export: List of dicts containing: - Antibiotic: Antibiotic name - Position: Position of the colony (e.g., A1, B2, etc.) - MIC: MIC value - QC: QC value (P, W, F) :return: List of dicts with MIC and QC data .. py:method:: __repr__() -> str Return repr(self). .. py:function:: plate_set_from_dir(path: Union[str, pathlib.Path], drug: str, model: aigarmic.model.Model, n_row: int = 8, n_col: int = 12, **kwargs) -> PlateSet Create a PlateSet from a directory of images. Images are annotated using the provided model. :param path: directory containing plate images (.jpg) with filenames indicating antibiotic concentration :param drug: name of drug :param model: model file to use for predictions :param n_row: number of rows in the plates :param n_col: number of columns in the plates :param kwargs: additional keyword arguments to pass to Plate constructor :return: PlateSet with MIC and QC values