Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases).

## Unreleased

## v5.17.0

### Added

- Support creating Lightcycler Sample Sheets for Absolute Quantification

## v5.16.0

### Added
Expand Down
57 changes: 57 additions & 0 deletions src/LightcyclerSampleSheet/AbsoluteQuantificationSample.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php declare(strict_types=1);

namespace MLL\Utils\LightcyclerSampleSheet;

use MLL\Utils\Microplate\Coordinates;
use MLL\Utils\Microplate\CoordinateSystem12x8;

class AbsoluteQuantificationSample
{
public string $sampleName;

public string $filterCombination;

public string $hexColor;

public string $sampleType;

public string $concentration;

/** @var Coordinates<CoordinateSystem12x8>|null */
public ?Coordinates $replicationOf;

/** @param Coordinates<CoordinateSystem12x8>|null $replicationOf */
public function __construct(
string $sampleName,
string $filterCombination,
string $hexColor,
string $sampleType,
string $concentration,
?Coordinates $replicationOf = null
) {
$this->sampleName = $sampleName;
$this->filterCombination = $filterCombination;
$this->hexColor = $hexColor;
$this->sampleType = $sampleType;
$this->concentration = $concentration;
$this->replicationOf = $replicationOf;
}

/** @return list<string> */
public function toSerializableArray(string $coordinatesString): array
{
$replicationOf = $this->replicationOf instanceof Coordinates
? "\"{$this->replicationOf->toString()}\""
: '""';

return [
Coordinates::fromString($coordinatesString, new CoordinateSystem12x8())->toString(),
"\"{$this->sampleName}\"",
$replicationOf,
$this->filterCombination,
"$00{$this->hexColor}",
"\"{$this->sampleType}\"",
"\"{$this->concentration}\"",
];
}
}
30 changes: 30 additions & 0 deletions src/LightcyclerSampleSheet/AbsoluteQuantificationSheet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types=1);

namespace MLL\Utils\LightcyclerSampleSheet;

use Illuminate\Support\Collection;
use MLL\Utils\StringUtil;

class AbsoluteQuantificationSheet
{
public const HEADER_COLUMNS = [
'"General:Pos"',
'"General:Sample Name"',
'"General:Repl. Of"',
'"General:Filt. Comb."',
'"Sample Preferences:Color"',
'"Abs Quant:Sample Type"',
'"Abs Quant:Concentration"',
];

/** @param Collection<string, AbsoluteQuantificationSample> $samples */
public function generate(Collection $samples): string
{
return $samples
->map(fn (AbsoluteQuantificationSample $well, string $coordinateFromKey): array => $well->toSerializableArray($coordinateFromKey))
->prepend(self::HEADER_COLUMNS)
->map(fn (array $row): string => implode(StringUtil::TAB, $row))
->implode(StringUtil::WINDOWS_NEW_LINE)
. StringUtil::WINDOWS_NEW_LINE;
}
}
9 changes: 4 additions & 5 deletions src/LightcyclerSampleSheet/RelativeQuantificationSheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
namespace MLL\Utils\LightcyclerSampleSheet;

use Illuminate\Support\Collection;
use MLL\Utils\StringUtil;

class RelativeQuantificationSheet
{
protected const WINDOWS_NEW_LINE = "\r\n";
protected const TAB_SEPARATOR = "\t";
public const HEADER_COLUMNS = [
'"General:Pos"',
'"General:Sample Name"',
Expand All @@ -22,8 +21,8 @@ public function generate(Collection $samples): string
return $samples
->map(fn (RelativeQuantificationSample $well, string $coordinateFromKey): array => $well->toSerializableArray($coordinateFromKey))
->prepend(self::HEADER_COLUMNS)
->map(fn (array $row): string => implode(self::TAB_SEPARATOR, $row))
->implode(self::WINDOWS_NEW_LINE)
. self::WINDOWS_NEW_LINE;
->map(fn (array $row): string => implode(StringUtil::TAB, $row))
->implode(StringUtil::WINDOWS_NEW_LINE)
. StringUtil::WINDOWS_NEW_LINE;
}
}
4 changes: 4 additions & 0 deletions src/StringUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

class StringUtil
{
public const WINDOWS_NEW_LINE = "\r\n";

public const TAB = "\t";

/** https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 */
public const UTF_8_BOM = "\xEF\xBB\xBF";

Expand Down
52 changes: 52 additions & 0 deletions tests/LightcyclerSampleSheet/AbsoluteQuantificationSheetTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php declare(strict_types=1);

namespace MLL\Utils\Tests\LightcyclerSampleSheet;

use Illuminate\Support\Collection;
use MLL\Utils\LightcyclerSampleSheet\AbsoluteQuantificationSample;
use MLL\Utils\LightcyclerSampleSheet\AbsoluteQuantificationSheet;
use MLL\Utils\Microplate\Coordinates;
use MLL\Utils\Microplate\CoordinateSystem12x8;
use MLL\Utils\StringUtil;
use PHPUnit\Framework\TestCase;

final class AbsoluteQuantificationSheetTest extends TestCase
{
public function testGenerateWithFakeData(): void
{
$coordinateSystem = new CoordinateSystem12x8();

$samples = Collection::make([
'A1' => new AbsoluteQuantificationSample('Standard_1', '485-520', 'FF0000', 'Standard', '1000.0', null),
'B1' => new AbsoluteQuantificationSample('Standard_1', '485-520', 'FF0001', 'Standard', '1000.0', Coordinates::fromString('A1', $coordinateSystem)),
'C1' => new AbsoluteQuantificationSample('Standard_2', '485-520', '00FF00', 'Standard', '100.0', null),
'D1' => new AbsoluteQuantificationSample('Standard_2', '485-520', '00FF01', 'Standard', '100.0', Coordinates::fromString('C1', $coordinateSystem)),
'E1' => new AbsoluteQuantificationSample('Sample_001', '485-520', '0000FF', 'Unknown', '', null),
'F1' => new AbsoluteQuantificationSample('Sample_001', '485-520', '0000FE', 'Unknown', '', Coordinates::fromString('E1', $coordinateSystem)),
'G1' => new AbsoluteQuantificationSample('Sample_002', '485-520', 'FFFF00', 'Unknown', '', null),
'H1' => new AbsoluteQuantificationSample('Sample_002', '485-520', 'FFFF01', 'Unknown', '', Coordinates::fromString('G1', $coordinateSystem)),
'A2' => new AbsoluteQuantificationSample('NTC', '485-520', '000000', 'Negative Control', '', null),
'B2' => new AbsoluteQuantificationSample('NTC', '485-520', '000001', 'Negative Control', '', Coordinates::fromString('A2', $coordinateSystem)),
]);

$sheet = new AbsoluteQuantificationSheet();
$result = $sheet->generate($samples);

$expected = <<<EOT
"General:Pos"\t"General:Sample Name"\t"General:Repl. Of"\t"General:Filt. Comb."\t"Sample Preferences:Color"\t"Abs Quant:Sample Type"\t"Abs Quant:Concentration"
A1\t"Standard_1"\t""\t485-520\t$00FF0000\t"Standard"\t"1000.0"
B1\t"Standard_1"\t"A1"\t485-520\t$00FF0001\t"Standard"\t"1000.0"
C1\t"Standard_2"\t""\t485-520\t$0000FF00\t"Standard"\t"100.0"
D1\t"Standard_2"\t"C1"\t485-520\t$0000FF01\t"Standard"\t"100.0"
E1\t"Sample_001"\t""\t485-520\t$000000FF\t"Unknown"\t""
F1\t"Sample_001"\t"E1"\t485-520\t$000000FE\t"Unknown"\t""
G1\t"Sample_002"\t""\t485-520\t$00FFFF00\t"Unknown"\t""
H1\t"Sample_002"\t"G1"\t485-520\t$00FFFF01\t"Unknown"\t""
A2\t"NTC"\t""\t485-520\t$00000000\t"Negative Control"\t""
B2\t"NTC"\t"A2"\t485-520\t$00000001\t"Negative Control"\t""
EOT;

self::assertSame(StringUtil::normalizeLineEndings($expected), $result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ final class RelativeQuantificationSheetTest extends TestCase
{
public function testGenerate(): void
{
$coordinateSystem = new CoordinateSystem12x8();

$samples = Collection::make([
'A1' => new RelativeQuantificationSample('Sample 1', '498-640', 'FF378A', null),
'B1' => new RelativeQuantificationSample('Sample 2', '498-640', '4899D1', null),
'C1' => new RelativeQuantificationSample('Sample 3', '498-640', '8528B9', null),
'D1' => new RelativeQuantificationSample('Sample 4', '498-640', '8E05D9', null),
'E1' => new RelativeQuantificationSample('Sample 5', '498-640', '4080A5', Coordinates::fromString('C12', new CoordinateSystem12x8())),
'E1' => new RelativeQuantificationSample('Sample 5', '498-640', '4080A5', Coordinates::fromString('C12', $coordinateSystem)),
]);

$sheet = new RelativeQuantificationSheet();
Expand Down
Loading