Assays - Snailz Docs

Skip to content

# Assays

Represent and generate assays.

## `Assay`

Bases: `BaseModel`

Represent a single assay.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`id` | `str` | unique ID | required
`specimen_id` | `str` | specimen assayed | required
`machine_id` | `str` | machine used | required
`person_id` | `str` | who did assay | required
`performed` | `date` | date assay performed | `datetime.date(2025, 4, 1)`
`treatments` | `Grid` | treatments applied | required
`readings` | `Grid` | readings obtained | required

Source code in `src/snailz/assays.py`

     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
    class Assay(BaseModel):
        """Represent a single assay."""

        id: str = Field(description="unique ID")
        specimen_id: str = Field(description="specimen assayed")
        machine_id: str = Field(description="machine used")
        person_id: str = Field(description="who did assay")
        performed: date = Field(
            default=DEFAULT_START_DATE, description="date assay performed"
        )
        treatments: Grid = Field(description="treatments applied")
        readings: Grid = Field(description="readings obtained")

        _id_generator: ClassVar = generic_id_generator(lambda i: f"A{i:04d}")

        @staticmethod
        def generate(params, specimen, machine, person):
            """Generate an assay for a specimen."""

            treatments = Assay._make_treatments(params)
            readings = Assay._make_readings(params, specimen, treatments)
            return Assay(
                id=next(Assay._id_generator),
                specimen_id=specimen.id,
                machine_id=machine.id,
                person_id=person.id,
                performed=choose_assay_date(params, specimen),
                treatments=treatments,
                readings=readings,
            )

        @staticmethod
        def _make_treatments(params):
            """Generate grid of treatments."""

            grid = Grid(size=params.plate_size)
            for x in range(grid.size):
                for y in range(grid.size):
                    grid[x, y] = random.choice("CS")

            return grid

        @staticmethod
        def _make_readings(params, specimen, treatments):
            """Make grid of readings."""
            grid = Grid(size=params.plate_size)
            for x in range(grid.size):
                for y in range(grid.size):
                    if treatments[x, y] == "C":
                        mean = 0.0
                    elif specimen.is_mutant:
                        mean = params.mean_mutant
                    else:
                        mean = params.mean_normal
                    grid[x, y] = abs(mean + random.gauss(0, params.reading_noise))

            return grid

        @staticmethod
        def all_csv(writer, assays):
            """Write all assays as a single CSV."""
            writer.writerow(
                [
                    "id",
                    "specimen",
                    "machine",
                    "person",
                    "performed",
                    "row",
                    "col",
                    "treatment",
                    "reading",
                ]
            )
            for a in assays:
                for x in range(a.readings.size):
                    for y in range(a.readings.size):
                        writer.writerow(
                            [
                                a.id,
                                a.specimen_id,
                                a.machine_id,
                                a.person_id,
                                a.performed.isoformat(),
                                y + 1,
                                chr(ord("A") + x),
                                a.treatments[x, y],
                                round(a.readings[x, y], PRECISION),
                            ]
                        )

        def to_csv(self, writer, write_treatments):
            """Save as CSV."""
            padding = [""] * (self.treatments.size - 4)
            for name, value in (
                ("id", self.id),
                ("specimen", self.specimen_id),
                ("machine", self.machine_id),
                ("person", self.person_id),
                ("performed", self.performed.isoformat()),
            ):
                writer.writerow([name, value] + padding)

            if write_treatments:
                grid = self.treatments
                convert = lambda x: x
            else:
                grid = self.readings
                convert = lambda x: round(x, PRECISION)

            title = [""] + [chr(ord("A") + i) for i in range(grid.size)]
            writer.writerow(title)
            for y in range(grid.size):
                row = [f"{y + 1}"] + [convert(grid[x, y]) for x in range(grid.size)]
                writer.writerow(row)

### `generate(params, specimen, machine, person)` `staticmethod`

Generate an assay for a specimen.

Source code in `src/snailz/assays.py`

    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    @staticmethod
    def generate(params, specimen, machine, person):
        """Generate an assay for a specimen."""

        treatments = Assay._make_treatments(params)
        readings = Assay._make_readings(params, specimen, treatments)
        return Assay(
            id=next(Assay._id_generator),
            specimen_id=specimen.id,
            machine_id=machine.id,
            person_id=person.id,
            performed=choose_assay_date(params, specimen),
            treatments=treatments,
            readings=readings,
        )

### `_make_treatments(params)` `staticmethod`

Generate grid of treatments.

Source code in `src/snailz/assays.py`

    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    @staticmethod
    def _make_treatments(params):
        """Generate grid of treatments."""

        grid = Grid(size=params.plate_size)
        for x in range(grid.size):
            for y in range(grid.size):
                grid[x, y] = random.choice("CS")

        return grid

### `_make_readings(params, specimen, treatments)` `staticmethod`

Make grid of readings.

Source code in `src/snailz/assays.py`

    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    @staticmethod
    def _make_readings(params, specimen, treatments):
        """Make grid of readings."""
        grid = Grid(size=params.plate_size)
        for x in range(grid.size):
            for y in range(grid.size):
                if treatments[x, y] == "C":
                    mean = 0.0
                elif specimen.is_mutant:
                    mean = params.mean_mutant
                else:
                    mean = params.mean_normal
                grid[x, y] = abs(mean + random.gauss(0, params.reading_noise))

        return grid

### `all_csv(writer, assays)` `staticmethod`

Write all assays as a single CSV.

Source code in `src/snailz/assays.py`

     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
    @staticmethod
    def all_csv(writer, assays):
        """Write all assays as a single CSV."""
        writer.writerow(
            [
                "id",
                "specimen",
                "machine",
                "person",
                "performed",
                "row",
                "col",
                "treatment",
                "reading",
            ]
        )
        for a in assays:
            for x in range(a.readings.size):
                for y in range(a.readings.size):
                    writer.writerow(
                        [
                            a.id,
                            a.specimen_id,
                            a.machine_id,
                            a.person_id,
                            a.performed.isoformat(),
                            y + 1,
                            chr(ord("A") + x),
                            a.treatments[x, y],
                            round(a.readings[x, y], PRECISION),
                        ]
                    )

### `to_csv(writer, write_treatments)`

Save as CSV.

Source code in `src/snailz/assays.py`

    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    def to_csv(self, writer, write_treatments):
        """Save as CSV."""
        padding = [""] * (self.treatments.size - 4)
        for name, value in (
            ("id", self.id),
            ("specimen", self.specimen_id),
            ("machine", self.machine_id),
            ("person", self.person_id),
            ("performed", self.performed.isoformat()),
        ):
            writer.writerow([name, value] + padding)

        if write_treatments:
            grid = self.treatments
            convert = lambda x: x
        else:
            grid = self.readings
            convert = lambda x: round(x, PRECISION)

        title = [""] + [chr(ord("A") + i) for i in range(grid.size)]
        writer.writerow(title)
        for y in range(grid.size):
            row = [f"{y + 1}"] + [convert(grid[x, y]) for x in range(grid.size)]
            writer.writerow(row)