Skip to content

napari_ndev._plate_mapper #

PlateMapper #

A class for creating and manipulating plate maps.

Attributes:

  • plate_size (int) –

    The size of the plate (e.g., 96, 384). Defaults to 96.

  • leading_zeroes (bool) –

    Whether to include leading zeroes in the column labels. Defaults to False.

  • treatments (dict) –

    A dictionary mapping treatments to conditions and well ranges.

  • wells (dict) –

    A dictionary mapping plate sizes to the number of rows and columns.

  • plate_map (DataFrame) –

    The plate map DataFrame with well labels.

  • pivoted_plate_map (DataFrame) –

    The wide-formatted plate map DataFrame with treatments as columns. Pivots only one treatment at a time.

  • styled_plate_map (Styler) –

    The styled pivoted plate map DataFrame with different background colors for each unique value.

Methods:

  • __init__

    Initializes a PlateMapper object.

  • create_empty_plate_map

    Creates an empty plate map DataFrame for a given plate size.

  • assign_treatments

    Assigns treatments to specific wells in a plate map.

  • get_pivoted_plate_map

    Pivots a plate map DataFrame to create a wide-formatted DataFrame with a single treatment as columns.

  • get_styled_plate_map

    Styles a plate map DataFrame with different background colors for each unique value.

Source code in src/napari_ndev/_plate_mapper.py
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
class PlateMapper:
    """
    A class for creating and manipulating plate maps.

    Attributes
    ----------
    plate_size : int
        The size of the plate (e.g., 96, 384).
        Defaults to 96.
    leading_zeroes : bool
        Whether to include leading zeroes in the column labels.
        Defaults to False.
    treatments : dict
        A dictionary mapping treatments to conditions and well ranges.
    wells : dict
        A dictionary mapping plate sizes to the number of rows and columns.
    plate_map : pandas.DataFrame
        The plate map DataFrame with well labels.
    pivoted_plate_map : pandas.DataFrame
        The wide-formatted plate map DataFrame with treatments as columns.
        Pivots only one treatment at a time.
    styled_plate_map : pandas.io.formats.style.Styler
        The styled pivoted plate map DataFrame with different background
        colors for each unique value.

    Methods
    -------
    __init__(plate_size=96)
        Initializes a PlateMapper object.
    create_empty_plate_map()
        Creates an empty plate map DataFrame for a given plate size.
    assign_treatments(treatments)
        Assigns treatments to specific wells in a plate map.
    get_pivoted_plate_map(treatment)
        Pivots a plate map DataFrame to create a wide-formatted DataFrame with a single treatment as columns.
    get_styled_plate_map(treatment, palette='colorblind')
        Styles a plate map DataFrame with different background colors for each unique value.

    """

    def __init__(self, plate_size=96, treatments=None, leading_zeroes=False, ):
        """
        Initialize a PlateMapper object.

        Parameters
        ----------
        plate_size : int, optional
            The size of the plate. Defaults to 96.
        leading_zeroes : bool, optional
            Whether to include leading zeroes in the column labels.
            Defaults to False.
        treatments : dict, optional
            A dictionary mapping treatments to conditions and well ranges.
            If provided, the treatments will be assigned to the plate map.
            Defaults to None.

        """
        self.plate_size = plate_size
        self.leading_zeroes = leading_zeroes
        self.wells = {
            6: (2, 3),
            12: (3, 4),
            24: (4, 6),
            48: (6, 8),
            96: (8, 12),
            384: (16, 24),
        }
        self.plate_map = self.create_empty_plate_map()
        self.pivoted_plate_map = None
        self.styled_plate_map = None

        if treatments:
            self.assign_treatments(treatments)
            # pivot the first key in treatments
            self.get_styled_plate_map(next(iter(treatments.keys())))

    def create_empty_plate_map(self):
        """
        Create an empty plate map DataFrame for a given plate size.

        Returns
        -------
        pandas.DataFrame
            The empty plate map DataFrame with well labels.

        """
        num_rows, num_columns = self.wells[self.plate_size]

        row_labels = list(string.ascii_uppercase)[:num_rows]
        if self.leading_zeroes:
            column_labels = [f'{i:02d}' for i in range(1, num_columns + 1)]
        else:
            column_labels = list(range(1, num_columns + 1))

        well_rows = row_labels * num_columns
        well_rows.sort()  # needed to sort the rows correctly
        well_columns = column_labels * num_rows

        well_labels_dict = {'row': well_rows, 'column': well_columns}

        plate_map_df = pd.DataFrame(well_labels_dict)

        plate_map_df['well_id'] = plate_map_df['row'] + plate_map_df[
            'column'
        ].astype(str)
        self.plate_map = plate_map_df
        return plate_map_df

    def assign_treatments(self, treatments):
        """
        Assign treatments to specific wells in a plate map.

        Parameters
        ----------
        treatments : dict
            A dictionary mapping treatments to conditions and well ranges.

        Returns
        -------
        pandas.DataFrame
            The updated plate map with treatments assigned to specific wells.

        """
        for treatment, conditions in treatments.items():
            for condition, wells in conditions.items():
                for well in wells:
                    if ':' in well:
                        start, end = well.split(':')
                        start_row, start_col = start[0], int(start[1:])
                        end_row, end_col = end[0], int(end[1:])
                        well_condition = (
                            (self.plate_map['row'] >= start_row)
                            & (self.plate_map['row'] <= end_row)
                            & (self.plate_map['column'].astype(int) >= start_col)
                            & (self.plate_map['column'].astype(int) <= end_col)
                        )
                    else:
                        row, col = well[0], int(well[1:])
                        well_condition = (
                            (self.plate_map['row'] == row)
                            & (self.plate_map['column'] == col)
                        )

                    self.plate_map.loc[well_condition, treatment] = condition
        return self.plate_map

    def get_pivoted_plate_map(self, treatment):
        """
        Pivot a plate map DataFrame to create a wide-formatted DataFrame with a single treatment as columns.

        Parameters
        ----------
        treatment : str
            The column name of the treatment variable in the plate map DataFrame.

        Returns
        -------
        pandas.DataFrame
            The wide-formatted plate map DataFrame with treatments as columns.

        """
        plate_map_pivot = self.plate_map.pivot(
            index='row', columns='column', values=treatment
        )
        self.pivoted_plate_map = plate_map_pivot
        return plate_map_pivot

    def get_styled_plate_map(self, treatment, palette='colorblind'):
        """
        Style a plate map with background colors for each unique value.

        Parameters
        ----------
        treatment : str
            The column name of the treatment variable in the plate map DataFrame.
        palette : str or list, optional
            The color palette to use for styling. Defaults to 'colorblind'.

        Returns
        -------
        pandas.io.formats.style.Styler
            The styled plate map DataFrame with different background colors for each unique value.

        """
        from seaborn import color_palette

        self.pivoted_plate_map = self.get_pivoted_plate_map(treatment)

        unique_values = pd.unique(self.pivoted_plate_map.values.flatten())
        unique_values = unique_values[pd.notna(unique_values)]

        color_palette_hex = color_palette(palette).as_hex()
        # Create an infinite iterator that cycles through the palette
        palette_cycle = itertools.cycle(color_palette_hex)
        # Use next() to get the next color
        color_dict = {value: next(palette_cycle) for value in unique_values}

        def get_background_color(value): # pragma: no cover
            if pd.isna(value):
                return ''
            return f'background-color: {color_dict[value]}'

        plate_map_styled = (
            self.pivoted_plate_map.style.applymap(get_background_color)
            .set_caption(f'{treatment} Plate Map')
            .format(lambda x: '' if pd.isna(x) else x)
        )
        self.styled_plate_map = plate_map_styled

        return plate_map_styled

__init__ #

__init__(plate_size=96, treatments=None, leading_zeroes=False)

Initialize a PlateMapper object.

Parameters:

  • plate_size #

    (int, default: 96 ) –

    The size of the plate. Defaults to 96.

  • leading_zeroes #

    (bool, default: False ) –

    Whether to include leading zeroes in the column labels. Defaults to False.

  • treatments #

    (dict, default: None ) –

    A dictionary mapping treatments to conditions and well ranges. If provided, the treatments will be assigned to the plate map. Defaults to None.

Source code in src/napari_ndev/_plate_mapper.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def __init__(self, plate_size=96, treatments=None, leading_zeroes=False, ):
    """
    Initialize a PlateMapper object.

    Parameters
    ----------
    plate_size : int, optional
        The size of the plate. Defaults to 96.
    leading_zeroes : bool, optional
        Whether to include leading zeroes in the column labels.
        Defaults to False.
    treatments : dict, optional
        A dictionary mapping treatments to conditions and well ranges.
        If provided, the treatments will be assigned to the plate map.
        Defaults to None.

    """
    self.plate_size = plate_size
    self.leading_zeroes = leading_zeroes
    self.wells = {
        6: (2, 3),
        12: (3, 4),
        24: (4, 6),
        48: (6, 8),
        96: (8, 12),
        384: (16, 24),
    }
    self.plate_map = self.create_empty_plate_map()
    self.pivoted_plate_map = None
    self.styled_plate_map = None

    if treatments:
        self.assign_treatments(treatments)
        # pivot the first key in treatments
        self.get_styled_plate_map(next(iter(treatments.keys())))

assign_treatments #

assign_treatments(treatments)

Assign treatments to specific wells in a plate map.

Parameters:

  • treatments #

    (dict) –

    A dictionary mapping treatments to conditions and well ranges.

Returns:

  • DataFrame

    The updated plate map with treatments assigned to specific wells.

Source code in src/napari_ndev/_plate_mapper.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
def assign_treatments(self, treatments):
    """
    Assign treatments to specific wells in a plate map.

    Parameters
    ----------
    treatments : dict
        A dictionary mapping treatments to conditions and well ranges.

    Returns
    -------
    pandas.DataFrame
        The updated plate map with treatments assigned to specific wells.

    """
    for treatment, conditions in treatments.items():
        for condition, wells in conditions.items():
            for well in wells:
                if ':' in well:
                    start, end = well.split(':')
                    start_row, start_col = start[0], int(start[1:])
                    end_row, end_col = end[0], int(end[1:])
                    well_condition = (
                        (self.plate_map['row'] >= start_row)
                        & (self.plate_map['row'] <= end_row)
                        & (self.plate_map['column'].astype(int) >= start_col)
                        & (self.plate_map['column'].astype(int) <= end_col)
                    )
                else:
                    row, col = well[0], int(well[1:])
                    well_condition = (
                        (self.plate_map['row'] == row)
                        & (self.plate_map['column'] == col)
                    )

                self.plate_map.loc[well_condition, treatment] = condition
    return self.plate_map

create_empty_plate_map #

create_empty_plate_map()

Create an empty plate map DataFrame for a given plate size.

Returns:

  • DataFrame

    The empty plate map DataFrame with well labels.

Source code in src/napari_ndev/_plate_mapper.py
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def create_empty_plate_map(self):
    """
    Create an empty plate map DataFrame for a given plate size.

    Returns
    -------
    pandas.DataFrame
        The empty plate map DataFrame with well labels.

    """
    num_rows, num_columns = self.wells[self.plate_size]

    row_labels = list(string.ascii_uppercase)[:num_rows]
    if self.leading_zeroes:
        column_labels = [f'{i:02d}' for i in range(1, num_columns + 1)]
    else:
        column_labels = list(range(1, num_columns + 1))

    well_rows = row_labels * num_columns
    well_rows.sort()  # needed to sort the rows correctly
    well_columns = column_labels * num_rows

    well_labels_dict = {'row': well_rows, 'column': well_columns}

    plate_map_df = pd.DataFrame(well_labels_dict)

    plate_map_df['well_id'] = plate_map_df['row'] + plate_map_df[
        'column'
    ].astype(str)
    self.plate_map = plate_map_df
    return plate_map_df

get_pivoted_plate_map #

get_pivoted_plate_map(treatment)

Pivot a plate map DataFrame to create a wide-formatted DataFrame with a single treatment as columns.

Parameters:

  • treatment #

    (str) –

    The column name of the treatment variable in the plate map DataFrame.

Returns:

  • DataFrame

    The wide-formatted plate map DataFrame with treatments as columns.

Source code in src/napari_ndev/_plate_mapper.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def get_pivoted_plate_map(self, treatment):
    """
    Pivot a plate map DataFrame to create a wide-formatted DataFrame with a single treatment as columns.

    Parameters
    ----------
    treatment : str
        The column name of the treatment variable in the plate map DataFrame.

    Returns
    -------
    pandas.DataFrame
        The wide-formatted plate map DataFrame with treatments as columns.

    """
    plate_map_pivot = self.plate_map.pivot(
        index='row', columns='column', values=treatment
    )
    self.pivoted_plate_map = plate_map_pivot
    return plate_map_pivot

get_styled_plate_map #

get_styled_plate_map(treatment, palette='colorblind')

Style a plate map with background colors for each unique value.

Parameters:

  • treatment #

    (str) –

    The column name of the treatment variable in the plate map DataFrame.

  • palette #

    (str or list, default: 'colorblind' ) –

    The color palette to use for styling. Defaults to 'colorblind'.

Returns:

  • Styler

    The styled plate map DataFrame with different background colors for each unique value.

Source code in src/napari_ndev/_plate_mapper.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def get_styled_plate_map(self, treatment, palette='colorblind'):
    """
    Style a plate map with background colors for each unique value.

    Parameters
    ----------
    treatment : str
        The column name of the treatment variable in the plate map DataFrame.
    palette : str or list, optional
        The color palette to use for styling. Defaults to 'colorblind'.

    Returns
    -------
    pandas.io.formats.style.Styler
        The styled plate map DataFrame with different background colors for each unique value.

    """
    from seaborn import color_palette

    self.pivoted_plate_map = self.get_pivoted_plate_map(treatment)

    unique_values = pd.unique(self.pivoted_plate_map.values.flatten())
    unique_values = unique_values[pd.notna(unique_values)]

    color_palette_hex = color_palette(palette).as_hex()
    # Create an infinite iterator that cycles through the palette
    palette_cycle = itertools.cycle(color_palette_hex)
    # Use next() to get the next color
    color_dict = {value: next(palette_cycle) for value in unique_values}

    def get_background_color(value): # pragma: no cover
        if pd.isna(value):
            return ''
        return f'background-color: {color_dict[value]}'

    plate_map_styled = (
        self.pivoted_plate_map.style.applymap(get_background_color)
        .set_caption(f'{treatment} Plate Map')
        .format(lambda x: '' if pd.isna(x) else x)
    )
    self.styled_plate_map = plate_map_styled

    return plate_map_styled