Skip to content

Commit 1d67359

Browse files
authored
Illumina sample sheet v2 (#19)
* feature: Add Support Illumina NovaSeq Sample Sheets
1 parent e65a83a commit 1d67359

25 files changed

+518
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases).
99

1010
## Unreleased
1111

12+
## v1.14.0
13+
14+
### Added
15+
16+
- Support creating Illumina NovaSeq Sample Sheets (V2) for NovaSeqX
17+
1218
## v1.13.0
1319

1420
### Added

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ stan: vendor ## Runs a static analysis with phpstan
3131
.PHONY: test
3232
test: vendor ## Runs auto-review, unit, and integration tests with phpunit
3333
mkdir --parents .build/phpunit
34-
vendor/bin/phpunit --cache-result-file=.build/phpunit/result.cache
34+
vendor/bin/phpunit --cache-directory=.build/phpunit
3535

3636
vendor: composer.json
3737
composer validate --strict

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"phpstan/phpstan-phpunit": "^1",
3535
"phpstan/phpstan-strict-rules": "^1",
3636
"phpunit/phpunit": "^9 || ^10 || ^11",
37-
"rector/rector": "^0.17",
37+
"rector/rector": "^1",
3838
"thecodingmachine/phpstan-safe-rule": "^1.2"
3939
},
4040
"suggest": {

rector.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use Rector\CodeQuality\Rector\Concat\JoinStringConcatRector;
44
use Rector\Config\RectorConfig;
5+
use Rector\PHPUnit\Rector\Class_\PreferPHPUnitSelfCallRector;
56
use Rector\Set\ValueObject\SetList;
67

78
return static function (RectorConfig $rectorConfig): void {
@@ -17,6 +18,9 @@
1718
__DIR__ . '/tests/CSVArrayTest.php', // keep `\r\n` for readability
1819
],
1920
]);
21+
22+
$rectorConfig->rule(PreferPHPUnitSelfCallRector::class);
23+
2024
$rectorConfig->paths([__DIR__ . '/src', __DIR__ . '/tests']);
2125
$rectorConfig->phpstanConfig(__DIR__ . '/phpstan.neon');
2226
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\IlluminaSampleSheet;
4+
5+
class IlluminaSampleSheetException extends \Exception {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\IlluminaSampleSheet;
4+
5+
abstract class SampleSheet
6+
{
7+
/** @var array<Section> */
8+
protected array $sections = [];
9+
10+
public function addSection(Section $section): void
11+
{
12+
$this->sections[] = $section;
13+
}
14+
15+
public function toString(): string
16+
{
17+
$sectionStrings = array_map(
18+
fn (Section $section): string => $section->convertSectionToString(),
19+
$this->sections
20+
);
21+
22+
return implode("\n", $sectionStrings);
23+
}
24+
}

src/IlluminaSampleSheet/Section.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\IlluminaSampleSheet;
4+
5+
interface Section
6+
{
7+
public function convertSectionToString(): string;
8+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\IlluminaSampleSheet\V2\BclConvert;
4+
5+
use MLL\Utils\IlluminaSampleSheet\Section;
6+
7+
class BclConvertSection implements Section
8+
{
9+
protected SettingsSection $settingsSection;
10+
11+
protected DataSection $dataSection;
12+
13+
public function __construct(SettingsSection $settingsSection, DataSection $dataSection)
14+
{
15+
$this->settingsSection = $settingsSection;
16+
$this->dataSection = $dataSection;
17+
}
18+
19+
public function convertSectionToString(): string
20+
{
21+
$bclConvertLines = [
22+
$this->settingsSection->convertSectionToString(),
23+
$this->dataSection->convertSectionToString(),
24+
];
25+
26+
return implode("\n", $bclConvertLines);
27+
}
28+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\IlluminaSampleSheet\V2\BclConvert;
4+
5+
class BclSample
6+
{
7+
public int $lane;
8+
9+
/** Not using camelCase because the property names of this class must match the CSV file. */
10+
public string $sample_ID;
11+
12+
public string $index;
13+
14+
public ?string $index2 = null;
15+
16+
public ?string $overrideCycles = null;
17+
18+
public ?string $adapterRead1 = null;
19+
20+
public ?string $adapterRead2 = null;
21+
22+
public ?string $barcodeMismatchesIndex1 = null;
23+
24+
public ?string $barcodeMismatchesIndex2 = null;
25+
26+
public function __construct(
27+
int $lane,
28+
string $sample_ID,
29+
string $index
30+
) {
31+
$this->lane = $lane;
32+
$this->sample_ID = $sample_ID;
33+
$this->index = $index;
34+
}
35+
36+
/** @return array<int|string> */
37+
public function toArray(): array
38+
{
39+
return array_filter([
40+
$this->lane,
41+
$this->sample_ID,
42+
$this->index,
43+
$this->index2,
44+
$this->overrideCycles,
45+
$this->adapterRead1,
46+
$this->adapterRead2,
47+
$this->barcodeMismatchesIndex1,
48+
$this->barcodeMismatchesIndex2,
49+
]);
50+
}
51+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\IlluminaSampleSheet\V2\BclConvert;
4+
5+
use MLL\Utils\IlluminaSampleSheet\Section;
6+
7+
class DataSection implements Section
8+
{
9+
/** @var array<BclSample> */
10+
protected array $dataRows = [];
11+
12+
public function addSample(BclSample $bclSample): void
13+
{
14+
$this->dataRows[] = $bclSample;
15+
}
16+
17+
public function convertSectionToString(): string
18+
{
19+
/** @var array<string> $samplePropertiesOfFirstSample */
20+
$samplePropertiesOfFirstSample = array_keys(get_object_vars($this->dataRows[0]));
21+
foreach ($this->dataRows as $sample) {
22+
$actualProperties = array_keys(get_object_vars($sample));
23+
if ($samplePropertiesOfFirstSample !== $actualProperties) {
24+
throw new \Exception('All samples must have the same properties. Expected: ' . \Safe\json_encode($samplePropertiesOfFirstSample) . ', Actual: ' . \Safe\json_encode($actualProperties));
25+
}
26+
}
27+
28+
$bclConvertDataHeaderLines = $this->generateDataHeaderByProperties($samplePropertiesOfFirstSample);
29+
30+
$bclConvertDataLines = [
31+
'[BCLConvert_Data]',
32+
$bclConvertDataHeaderLines,
33+
];
34+
35+
foreach ($this->dataRows as $dataRow) {
36+
$bclConvertDataLines[] = implode(',', $dataRow->toArray());
37+
}
38+
39+
return implode("\n", $bclConvertDataLines) . "\n";
40+
}
41+
42+
/** @param array<string> $samplePropertiesOfFirstSample */
43+
protected function generateDataHeaderByProperties(array $samplePropertiesOfFirstSample): string
44+
{
45+
$samplePropertiesOfFirstSample = array_filter($samplePropertiesOfFirstSample, fn (string $value) // @phpstan-ignore-next-line Variable property access on a non-object required here
46+
=> $this->dataRows[0]->$value !== null);
47+
48+
$samplePropertiesOfFirstSample = array_map(fn (string $value) => ucfirst($value), $samplePropertiesOfFirstSample);
49+
50+
return implode(',', $samplePropertiesOfFirstSample);
51+
}
52+
}

0 commit comments

Comments
 (0)