Coder Social home page Coder Social logo

Sweep: Refactor generally to improve quality the file visualization.php and maintainbility plus readable by following psr 1, psr 2, psr 12 standards about php-dna HOT 1 CLOSED

liberu-genealogy avatar liberu-genealogy commented on September 26, 2024 2
Sweep: Refactor generally to improve quality the file visualization.php and maintainbility plus readable by following psr 1, psr 2, psr 12 standards

from php-dna.

Comments (1)

sweep-ai avatar sweep-ai commented on September 26, 2024

🚀 Here's the PR! #160

See Sweep's progress at the progress dashboard!
💎 Sweep Pro: I'm using GPT-4. You have unlimited GPT-4 tickets. (tracking ID: 4cf2e13800)

Tip

I can email you next time I complete a pull request if you set up your email here!


Actions (click)

  • ↻ Restart Sweep

Step 1: 🔎 Searching

I found the following snippets in your repository. I will now analyze these snippets and come up with a plan.

Some code snippets I think are relevant in decreasing order of relevance (click to expand). If some file is missing from here, you can mention the path in the ticket description.

<?php
declare(strict_types=1);
namespace Php8\Migration;
use Exception;
use InvalidArgumentException;
class VariadicInherit
{
const ERR_MAGIC_SIGNATURE = 'WARNING: magic method signature for %s does not appear to match required signature';
const ERR_REMOVED = 'WARNING: the following function has been removed: %s. Use this instead: %s';
const ERR_IS_RESOURCE = 'WARNING: this function no longer produces a resource: %s. Usage of "is_resource($item)" should be replaced with "!empty($item)';
const ERR_MISSING_KEY = 'ERROR: missing configuration key %s';
const ERR_INVALID_KEY = 'ERROR: this configuration key is either missing or not callable: ';
const ERR_FILE_NOT_FOUND = 'ERROR: file not found: %s';
const WARN_BC_BREAKS = 'WARNING: the code in this file might not be compatible with PHP 8';
const NO_BC_BREAKS = 'SUCCESS: the code scanned in this file is potentially compatible with PHP 8';
const MAGIC_METHODS = 'The following magic methods were detected:';
const OK_PASSED = 'PASSED this scan: %s';
const TOTAL_BREAKS = 'Total potential BC breaks: %d' . PHP_EOL;
const KEY_REMOVED = 'removed';
const KEY_CALLBACK = 'callbacks';
const KEY_MAGIC = 'magic';
const KEY_RESOURCE = 'resource';
public $config = [];
public $contents = '';
public $messages = [];
public $magic = [];
/**
* @param array $config : scan config
*/
public function __construct(array $config)
{
$this->config = $config;
$required = [self::KEY_CALLBACK, self::KEY_REMOVED, self::KEY_MAGIC, self::KEY_RESOURCE];
foreach ($required as $key) {
if (!isset($this->config[$key])) {
$message = sprintf(self::ERR_MISSING_KEY, $key);
throw new InvalidArgumentException($message);
}
}
}
/**
* Grabs contents
* Initializes messages to []
* Converts "\r" and "\n" to ' '
*
* @param string $fn : name of file to scan
* @return string $name : classnames
*/
public function getFileContents(string $fn) : string
{
if (!file_exists($fn)) {
$this->contents = '';
throw new InvalidArgumentException(sprintf(self::ERR_FILE_NOT_FOUND, $fn));
}
$this->clearMessages();
$this->contents = file_get_contents($fn);
$this->contents = str_replace(["\r","\n"],['', ' '], $this->contents);
return $this->contents;
}
/**
* Extracts the value immediately following the supplied word up until the supplied end
*
* @param string $contents : text to search (usually $this->contents)
* @param string $key : starting keyword or set of characters
* @param string $delim : ending delimiter
* @return string $name : classnames
*/
public static function getKeyValue(string $contents, string $key, string $delim)
{
$pos = strpos($contents, $key);
if ($pos === FALSE) return '';
$end = strpos($contents, $delim, $pos + strlen($key) + 1);
$key = substr($contents, $pos + strlen($key), $end - $pos - strlen($key));
if (is_string($key)) {
$key = trim($key);
} else {
$key = '';
}
$key = trim($key);
return $key;
}
/**
* Clears messages
*
* @return void
*/
public function clearMessages() : void
{
$this->messages = [];
$this->magic = [];
}
/**
* Returns messages
*
* @param bool $clear : If TRUE, reset messages to []
* @return array $messages : accumulated messages
*/
public function getMessages(bool $clear = FALSE) : array
{
$messages = $this->messages;
if ($clear) $this->clearMessages();
return $messages;
}
/**
* Returns 0 and adds OK message
*
* @param string $function
* @return int 0
*/
public function passedOK(string $function) : int
{
$this->messages[] = sprintf(self::OK_PASSED, $function);
return 0;
}
/**
* Runs all scans
*
* @return int $found : number of potential BC breaks found
*/
public function runAllScans() : int
{
$found = 0;
$found += $this->scanRemovedFunctions();
$found += $this->scanIsResource();
$found += $this->scanMagicSignatures();
echo __METHOD__ . ':' . var_export($this->messages, TRUE) . "\n";
$found += $this->scanFromCallbacks();
return $found;
}
/**
* Check for removed functions
*
* @return int $found : number of BC breaks detected
*/
public function scanRemovedFunctions() : int
{
$found = 0;
$config = $this->config[self::KEY_REMOVED] ?? NULL;
// we add this extra safety check in case this method is called separately
if (empty($config)) {
$message = sprintf(self::ERR_MISSING_KEY, self::KEY_REMOVED);
throw new Exception($message);
}
foreach ($config as $func => $replace) {
$search1 = ' ' . $func . '(';
$search2 = ' ' . $func . ' (';
if (strpos($this->contents, $search1) !== FALSE
|| strpos($this->contents, $search2) !== FALSE) {
$this->messages[] = sprintf(self::ERR_REMOVED, $func, $replace);
$found++;
}
}
return ($found === 0) ? $this->passedOK(__FUNCTION__) : $found;
}
/**
* Check for is_resource usage
* If "is_resource" found, check against list of functions
* that no longer produce resources in PHP 8
*
* @return int $found : number of BC breaks detected
*/
public function scanIsResource() : int
{
$found = 0;
$search = 'is_resource';
// if "is_resource" not found discontinue search
if (strpos($this->contents, $search) === FALSE) return $this->passedOK(__FUNCTION__);
// pull list of functions that now return objects instead of resources
$config = $this->config[self::KEY_RESOURCE] ?? NULL;
// we add this extra safety check in case this method is called separately
if (empty($config)) {
$message = sprintf(self::ERR_MISSING_KEY, self::KEY_RESOURCE);
throw new Exception($message);
}
foreach ($config as $func) {
if ((strpos($this->contents, $func) !== FALSE)) {
$this->messages[] = sprintf(self::ERR_IS_RESOURCE, $func);
$found++;
}
}
return ($found === 0) ? $this->passedOK(__FUNCTION__) : $found;
}
/**
* Scan for magic method signatures
* NOTE: doesn't check inside parentheses.
* only checks for return data type + displays found and correct signatures for manual comparison
*
* @return int $found : number of invalid return data types
*/
public function scanMagicSignatures() : int
{
// locate all magic methods
$found = 0;
$matches = [];
if (!empty($matches[1])) {
$this->messages[] = self::MAGIC_METHODS;
$config = $this->config[self::KEY_MAGIC] ?? NULL;
// we add this extra safety check in case this method is called separately
if (empty($config)) {
$message = sprintf(self::ERR_MISSING_KEY, self::KEY_MAGIC);
throw new Exception($message);
}
foreach ($matches[1] as $name) {
$key = '__' . $name;
// skip if key not found. must not be a defined magic method
if (!isset($config[$key])) continue;
// record official signature
$this->messages[] = 'Signature: ' . ($config[$key]['signature'] ?? 'Signature not found');
$sub = $this->getKeyValue($this->contents, $key, '{');
if ($sub) {
$sub = $key . $sub;
// record found signature
$this->messages[] = 'Actual : ' . $sub;
// look for return type
if (strpos($sub, ':')) {
$ptn = '/.*?\(.*?\)\s*:\s*' . $config[$key]['return'] . '/';
// test for a match
if (!preg_match($ptn, $sub)) {
$this->messages[] = sprintf(self::ERR_MAGIC_SIGNATURE, $key);
$found++;
}
}
}
}
}
//echo __METHOD__ . ':' . var_export($this->messages, TRUE) . "\n";
return ($found === 0) ? $this->passedOK(__FUNCTION__) : $found;
}
/**
* Runs all scans key as defined in $this->config (bc_break_scanner.config.php)
*
* @return int $found : number of potential BC breaks found
*/
public function scanFromCallbacks()
{
$found = 0;
$list = array_keys($this->config[self::KEY_CALLBACK]);
foreach ($list as $key) {
$config = $this->config[self::KEY_CALLBACK][$key] ?? NULL;
if (empty($config['callback']) || !is_callable($config['callback'])) {
$message = sprintf(self::ERR_INVALID_KEY, self::KEY_CALLBACK . ' => ' . $key . ' => callback');
throw new InvalidArgumentException($message);
}
if ($config['callback']($this->contents)) {
$this->messages[] = $config['msg'];
$found++;
}
}
return $found;
}
public function homozygous_snps(string $chrom = "")
{
trigger_error("This method has been renamed to `homozygous`.", E_USER_DEPRECATED);
return $this->homozygous($chrom);
}
public function is_valid()
{
trigger_error("This method has been renamed to `valid` and is now a property.", E_USER_DEPRECATED);
return $this->valid;
}
public function predict_ancestry(
?string $output_directory = null,
bool $write_predictions = false,
?string $models_directory = null,
?string $aisnps_directory = null,
?int $n_components = null,
?int $k = null,
?string $thousand_genomes_directory = null,
?string $samples_directory = null,
?string $algorithm = null,
?string $aisnps_set = null
) {
// Method implementation goes here
}
public function getPredictions(
$output_directory,
$write_predictions,
$models_directory,
$aisnps_directory,
$n_components,
$k,
$thousand_genomes_directory,
$samples_directory,
$algorithm,
$aisnps_set
) {
if (!$this->valid) {
// If the object is not valid, return an empty array
return [];
}
// Check if ezancestry package is installed
if (!class_exists('ezancestry\commands\Predict')) {
// Throw an exception if the ezancestry package is not installed
throw new Exception('Ancestry prediction requires the ezancestry package; please install it');
}
$predict = new ezancestry\commands\Predict();
// Call the predict method of the ezancestry\commands\Predict class
$predictions = $predict->predict(
$this->snps,
$output_directory,
$write_predictions,
$models_directory,
$aisnps_directory,
$n_components,
$k,
$thousand_genomes_directory,
$samples_directory,
$algorithm,
$aisnps_set
);
// Get the maxPop values from the first prediction
$maxPopValues = $this->maxPop($predictions[0]);
// Add the predictions to the maxPopValues array
$maxPopValues['ezancestry_df'] = $predictions;
// Return the maxPopValues array
return $maxPopValues;
}
private function maxPop($row)
{
// Extract the values from the $row array
$popcode = $row['predicted_population_population'];
$popdesc = $row['population_description'];
$poppct = $row[$popcode];
$superpopcode = $row['predicted_population_superpopulation'];
$superpopdesc = $row['superpopulation_name'];
$superpoppct = $row[$superpopcode];
// Return an array with the extracted values
return [
'population_code' => $popcode,
'population_description' => $popdesc,
'_percent' => $poppct,
'superpopulation_code' => $superpopcode,
'superpopulation_description' => $superpopdesc,
'population_percent' => $superpoppct,
];
}
/**
* Computes cluster overlap based on given threshold.
*
* @param float $cluster_overlap_threshold The threshold for cluster overlap.
* @return DataFrame The computed cluster overlap DataFrame.
*/
public function compute_cluster_overlap($cluster_overlap_threshold = 0.95) {
// Sample data for cluster overlap computation
$data = [
"cluster_id" => ["c1", "c3", "c4", "c5", "v5"],
"company_composition" => [
"23andMe-v4",
"AncestryDNA-v1, FTDNA, MyHeritage",
"23andMe-v3",
"AncestryDNA-v2",
"23andMe-v5, LivingDNA",
],
"chip_base_deduced" => [
"HTS iSelect HD",
"OmniExpress",
"OmniExpress plus",
"OmniExpress plus",
"Illumina GSAs",
],
"snps_in_cluster" => array_fill(0, 5, 0),
"snps_in_common" => array_fill(0, 5, 0),
];
// Create a DataFrame from the data and set "cluster_id" as the index
$df = new DataFrame($data);
$df->setIndex("cluster_id");
$to_remap = null;
if ($this->build != 37) {
// Create a clone of the current object for remapping
$to_remap = clone $this;
$to_remap->remap(37); // clusters are relative to Build 37
$self_snps = $to_remap->snps()->select(["chrom", "pos"])->dropDuplicates();
} else {
$self_snps = $this->snps()->select(["chrom", "pos"])->dropDuplicates();
}
// Retrieve chip clusters from resources
$chip_clusters = $this->resources->get_chip_clusters();
// Iterate over each cluster in the DataFrame
foreach ($df->indexValues() as $cluster) {
// Filter chip clusters based on the current cluster
$cluster_snps = $chip_clusters->filter(function ($row) use ($cluster) {
return strpos($row["clusters"], $cluster) !== false;
})->select(["chrom", "pos"]);
// Update the DataFrame with the number of SNPs in the cluster and in common with the current object
$df->loc[$cluster]["snps_in_cluster"] = count($cluster_snps);
$df->loc[$cluster]["snps_in_common"] = count($self_snps->merge($cluster_snps, "inner"));
// Calculate overlap ratios for cluster and self
$df["overlap_with_cluster"] = $df["snps_in_common"] / $df["snps_in_cluster"];
$df["overlap_with_self"] = $df["snps_in_common"] / count($self_snps);
// Find the cluster with the maximum overlap
$max_overlap = array_keys($df["overlap_with_cluster"], max($df["overlap_with_cluster"]))[0];
// Check if the maximum overlap exceeds the threshold for both cluster and self
if (
$df["overlap_with_cluster"][$max_overlap] > $cluster_overlap_threshold &&
$df["overlap_with_self"][$max_overlap] > $cluster_overlap_threshold
) {
// Update the current object's cluster and chip based on the maximum overlap
$this->cluster = $max_overlap;
$this->chip = $df["chip_base_deduced"][$max_overlap];
$company_composition = $df["company_composition"][$max_overlap];
// Check if the current object's source is present in the company composition
if (strpos($company_composition, $this->source) !== false) {
if ($this->source === "23andMe" || $this->source === "AncestryDNA") {
// Extract the chip version from the company composition
$i = strpos($company_composition, "v");
$this->chip_version = substr($company_composition, $i, $i + 2);
}
} else {
// Log a warning about the SNPs data source not found
}
}
}
// Return the computed cluster overlap DataFrame
return $df;

<?php
/**
* php-dna.
*
* Utility functions.
*
* @author Devmanateam <[email protected]>
* @copyright Copyright (c) 2020-2023, Devmanateam
* @license MIT
*
* @link http://github.com/familytree365/php-dna
*/
namespace Dna\Snps;
use Exception;
use ZipArchive;
use Dna\Snps\Utils;
/**
* The Singleton class defines the `GetInstance` method that serves as an
* alternative to constructor and lets clients access the same instance of this
* class over and over.
*/
// from multiprocessing import Pool; // You can use parallel or pthreads for multi-processing in PHP
// import os; // PHP has built-in OS functions
// import re; // PHP has built-in RegExp functions
// import shutil; // PHP has built-in filesystem functions
// import tempfile; // PHP has built-in temporary file functions
// import zipfile; // PHP has built-in ZipArchive class available
// from atomicwrites import atomic_write; // You can use a library or implement atomic writes in PHP
// import pandas as pd; // There is no direct PHP alternative to pandas; consider using array functions or a data manipulation library
class Parallelizer
{
private bool $_parallelize;
private ?int $_processes;
public function __construct(bool $parallelize = false, ?int $processes = null): void
{
$this->_parallelize = $parallelize;
/**
* Utils class provides utility functions for file manipulation, parallel processing,
* and other common tasks. It includes methods for gzipping files, creating directories,
* fetching current UTC time, saving data as CSV, cleaning strings, and zipping files.
*/
$this->_processes = $processes ?? os_cpu_count();
}
public function __invoke(callable $f, array $tasks): array
{
if ($this->_parallelize) {
// PHP does not have built-in support for parallel processing similar to Python's multiprocessing.
// Consider using alternative approaches or libraries for parallel processing in PHP.
// This example code is commented out as it requires the "parallel" PECL extension.
// $runtime = new \parallel\Runtime();
// $futures = [];
// foreach ($tasks as $task) {
// $futures[] = $runtime->run($f, [$task]);
// }
// return array_map(fn($future) => $future->value, $futures);
return array_map($f, $tasks); // Fallback to sequential processing
} else {
return array_map($f, $tasks);
}
}
function os_cpu_count(): int
{
// Use this function if you need to get the number of CPU cores in PHP
// You might need to adjust this code based on your environment
if (substr(php_uname('s'), 0, 7) == 'Windows') {
return (int) shell_exec('echo %NUMBER_OF_PROCESSORS%');
} else {
return (int) shell_exec('nproc');
}
}
}
class Utils
{
public static function gzip_file(string $src, string $dest): string
{
/**
* Gzip a file.
*
* @param string $src Path to file to gzip
* @param string $dest Path to output gzip file
*
* @return string Path to gzipped file
*/
$bufferSize = 4096;
$srcFile = fopen($src, "rb");
if ($srcFile === false) {
throw new Exception("Cannot open source file");
}
try {
$destFile = fopen($dest, "wb");
if ($destFile === false) {
throw new Exception("Cannot create destination file");
}
try {
$gzFile = gzopen($dest, "wb");
if ($gzFile === false) {
throw new Exception("Cannot create gzipped file");
}
try {
while (!feof($srcFile)) {
$buffer = fread($srcFile, $bufferSize);
gzwrite($gzFile, $buffer);
}
} finally {
gzclose($gzFile);
}
} finally {
fclose($destFile);
}
} finally {
fclose($srcFile);
}
return $dest;
}
}
/**
* Creates a directory if it doesn't exist.
*
* @param string $path Path to the directory to create.
* @return void
*/
public static function create_dir(string $path): void
{
if (!file_exists($path)) {
mkdir($path, 0777, true);
}
}
/**
* Gets the current UTC time.
*
* @return string Current UTC time in 'Y-m-d H:i:s' format.
*/
public static function get_utc_now(): string
{
return gmdate('Y-m-d H:i:s');
}
/**
* Saves data as a CSV file.
*
* @param array $data Data to save.
* @param string $filename Path to the CSV file.
* @return void
*/
public static function save_df_as_csv(array $data, string $filename): void
{
$fp = fopen($filename, 'w');
foreach ($data as $row) {
fputcsv($fp, $row);
}
fclose($fp);
}
/**
* Cleans a string to be used as a variable name.
*
* @param string $str String to clean.
* @return string Cleaned string.
*/
public static function clean_str(string $str): string
{
return preg_replace('/[^A-Za-z0-9_]/', '', $str);
}
/**
* Zips a file.
*
* @param string $src Path to the file to zip.
* @param string $dest Path to the output zip file.
* @return void
*/
public static function zip_file(string $src, string $dest): void
{
$zip = new ZipArchive();
if ($zip->open($dest, ZipArchive::CREATE) === TRUE) {
$zip->addFile($src, basename($src));
$zip->close();
}


Step 2: ⌨️ Coding

Modify src/Snps/VariedicInherit.php with contents:

Refactor the VariedicInherit class in the src/Snps/VariedicInherit.php file to adhere to PSR-1, PSR-2, and PSR-12 coding standards.

Update <original_code> with the necessary changes:
<original_code>

Update block with the necessary changes:
- [X] Modify `src/Snps/VariedicInherit.php` ✓ https://github.com/liberu-genealogy/php-dna/commit/f4afb22a3ce1353f8d1dbcc9b79139a1c79c643d [Edit](https://github.com/liberu-genealogy/php-dna/edit/sweep/refactor_generally_to_improve_quality_th_79eb7/src/Snps/VariedicInherit.php)
Modify src/Snps/VariedicInherit.php with contents: Update the `__construct()` method in the `VariedicInherit` class to follow PSR standards. Update with the necessary changes: /** * @param array $config : scan config */ public function __construct(array $config) { $this->config = $config; $required = [self::KEY_CALLBACK, self::KEY_REMOVED, self::KEY_MAGIC, self::KEY_RESOURCE]; foreach ($required as $key) { if (!isset($this->config[$key])) { $message = sprintf(self::ERR_MISSING_KEY, $key); throw new InvalidArgumentException($message); } } } Update block with the necessary changes: /** * VariadicInherit constructor. * * @param array $config Scan configuration * @throws InvalidArgumentException If a required configuration key is missing */ public function __construct(array $config) { $this->config = $config; $required = [ self::KEY_CALLBACK, self::KEY_REMOVED, self::KEY_MAGIC, self::KEY_RESOURCE, ]; foreach ($required as $key) { if (!isset($this->config[$key])) { $message = sprintf(self::ERR_MISSING_KEY, $key); throw new InvalidArgumentException($message); } } }
- [X] Modify `src/Snps/VariedicInherit.php` ✓ https://github.com/liberu-genealogy/php-dna/commit/f4afb22a3ce1353f8d1dbcc9b79139a1c79c643d [Edit](https://github.com/liberu-genealogy/php-dna/edit/sweep/refactor_generally_to_improve_quality_th_79eb7/src/Snps/VariedicInherit.php)
Modify src/Snps/VariedicInherit.php with contents: Update the `getFileContents()` method in the `VariedicInherit` class to follow PSR standards. Update with the necessary changes: /** * Grabs contents * Initializes messages to [] * Converts "\r" and "\n" to ' ' * * @param string $fn : name of file to scan * @return string $name : classnames */ public function getFileContents(string $fn) : string { if (!file_exists($fn)) { $this->contents = ''; throw new InvalidArgumentException(sprintf(self::ERR_FILE_NOT_FOUND, $fn)); } $this->clearMessages(); $this->contents = file_get_contents($fn); $this->contents = str_replace(["\r","\n"],['', ' '], $this->contents); return $this->contents; } Update block with the necessary changes: /** * Get the contents of a file. * * @param string $filePath Path to the file to scan * @return string The file contents with line breaks replaced by spaces * @throws InvalidArgumentException If the file is not found */ public function getFileContents(string $filePath): string { if (!file_exists($filePath)) { $this->contents = ''; throw new InvalidArgumentException( sprintf(self::ERR_FILE_NOT_FOUND, $filePath) ); } $this->clearMessages(); $this->contents = file_get_contents($filePath); $this->contents = str_replace(["\r", "\n"], ['', ' '], $this->contents); return $this->contents; }
- [X] Modify `src/Snps/VariedicInherit.php` ✓ https://github.com/liberu-genealogy/php-dna/commit/f4afb22a3ce1353f8d1dbcc9b79139a1c79c643d [Edit](https://github.com/liberu-genealogy/php-dna/edit/sweep/refactor_generally_to_improve_quality_th_79eb7/src/Snps/VariedicInherit.php)
Modify src/Snps/VariedicInherit.php with contents: Update the `getKeyValue()` method in the `VariedicInherit` class to follow PSR standards. Update with the necessary changes: public static function getKeyValue(string $contents, string $key, string $delim) { $pos = strpos($contents, $key); if ($pos === FALSE) return ''; $end = strpos($contents, $delim, $pos + strlen($key) + 1); $key = substr($contents, $pos + strlen($key), $end - $pos - strlen($key)); if (is_string($key)) { $key = trim($key); } else { $key = ''; } $key = trim($key); return $key; } Update block with the necessary changes: /** * Get the value of a key from a string. * * @param string $contents The string to search * @param string $key The key to search for * @param string $delimiter The delimiter to use * @return string The value of the key, or an empty string if not found */ public static function getKeyValue( string $contents, string $key, string $delimiter ): string { $position = strpos($contents, $key); if ($position === false) { return ''; } $end = strpos($contents, $delimiter, $position + strlen($key) + 1); $value = substr( $contents, $position + strlen($key), $end - $position - strlen($key) ); return is_string($value) ? trim($value) : ''; }
- [X] Modify `src/Snps/VariedicInherit.php` ✓ https://github.com/liberu-genealogy/php-dna/commit/f4afb22a3ce1353f8d1dbcc9b79139a1c79c643d [Edit](https://github.com/liberu-genealogy/php-dna/edit/sweep/refactor_generally_to_improve_quality_th_79eb7/src/Snps/VariedicInherit.php)
Modify src/Snps/VariedicInherit.php with contents: Refactor the `VariedicInherit` class in the `src/Snps/VariedicInherit.php` file to adhere to PSR-1, PSR-2, and PSR-12 coding standards. Update with the necessary changes: Update block with the necessary changes:
- [X] Modify `src/Snps/VariedicInherit.php` ✓ https://github.com/liberu-genealogy/php-dna/commit/f4afb22a3ce1353f8d1dbcc9b79139a1c79c643d [Edit](https://github.com/liberu-genealogy/php-dna/edit/sweep/refactor_generally_to_improve_quality_th_79eb7/src/Snps/VariedicInherit.php)
Modify src/Snps/VariedicInherit.php with contents: Update the `homozygous_snps()`, `is_valid()`, `predict_ancestry()`, `getPredictions()`, and `maxPop()` methods in the `VariedicInherit` class to follow PSR standards. Update with the necessary changes: public function homozygous_snps(string $chrom = "") { trigger_error("This method has been renamed to `homozygous`.", E_USER_DEPRECATED); return $this->homozygous($chrom); } public function is_valid() { trigger_error("This method has been renamed to `valid` and is now a property.", E_USER_DEPRECATED); return $this->valid; } public function predict_ancestry( ?string $output_directory = null, bool $write_predictions = false, ?string $models_directory = null, ?string $aisnps_directory = null, ?int $n_components = null, ?int $k = null, ?string $thousand_genomes_directory = null, ?string $samples_directory = null, ?string $algorithm = null, ?string $aisnps_set = null ) { // Method implementation goes here } public function getPredictions( $output_directory, $write_predictions, $models_directory, $aisnps_directory, $n_components, $k, $thousand_genomes_directory, $samples_directory, $algorithm, $aisnps_set ) { if (!$this->valid) { // If the object is not valid, return an empty array return []; } // Check if ezancestry package is installed if (!class_exists('ezancestry\commands\Predict')) { // Throw an exception if the ezancestry package is not installed throw new Exception('Ancestry prediction requires the ezancestry package; please install it'); } $predict = new ezancestry\commands\Predict(); // Call the predict method of the ezancestry\commands\Predict class $predictions = $predict->predict( $this->snps, $output_directory, $write_predictions, $models_directory, $aisnps_directory, $n_components, $k, $thousand_genomes_directory, $samples_directory, $algorithm, $aisnps_set ); // Get the maxPop values from the first prediction $maxPopValues = $this->maxPop($predictions[0]); // Add the predictions to the maxPopValues array $maxPopValues['ezancestry_df'] = $predictions; // Return the maxPopValues array return $maxPopValues; } private function maxPop($row) { // Extract the values from the $row array $popcode = $row['predicted_population_population']; $popdesc = $row['population_description']; $poppct = $row[$popcode]; $superpopcode = $row['predicted_population_superpopulation']; $superpopdesc = $row['superpopulation_name']; $superpoppct = $row[$superpopcode]; // Return an array with the extracted values return [ 'population_code' => $popcode, 'population_description' => $popdesc, '_percent' => $poppct, 'superpopulation_code' => $superpopcode, 'superpopulation_description' => $superpopdesc, 'population_percent' => $superpoppct, ]; } Update block with the necessary changes: /** * Get homozygous SNPs for a given chromosome. * * @param string $chromosome The chromosome to get homozygous SNPs for * @return mixed The result of the homozygous() method * @deprecated Use the homozygous() method instead */ public function homozygous_snps(string $chromosome = '') { trigger_error( 'This method has been renamed to `homozygous`.', E_USER_DEPRECATED ); return $this->homozygous($chromosome); } /** * Check if the object is valid. * * @return bool The value of the "valid" property * @deprecated Use the "valid" property instead */ public function is_valid(): bool { trigger_error( 'This method has been renamed to `valid` and is now a property.', E_USER_DEPRECATED ); return $this->valid; } /** * Predict ancestry using the ezancestry package. * * @param string|null $outputDirectory The output directory for predictions * @param bool $writePredictions Whether to write the predictions to files * @param string|null $modelsDirectory The directory containing the models * @param string|null $aisnpsDirectory The directory containing the AIsnps * @param int|null $nComponents The number of components for the model * @param int|null $k The number of nearest neighbors to use * @param string|null $thousandGenomesDirectory The directory containing the 1000 Genomes data * @param string|null $samplesDirectory The directory containing the samples * @param string|null $algorithm The algorithm to use for prediction * @param string|null $aisnpsSet The set of AIsnps to use * @return array The predicted ancestry values * @throws Exception If the ezancestry package is not installed */ public function predict_ancestry( ?string $outputDirectory = null, bool $writePredictions = false, ?string $modelsDirectory = null, ?string $aisnpsDirectory = null, ?int $nComponents = null, ?int $k = null, ?string $thousandGenomesDirectory = null, ?string $samplesDirectory = null, ?string $algorithm = null, ?string $aisnpsSet = null ): array { return $this->getPredictions( $outputDirectory, $writePredictions, $modelsDirectory, $aisnpsDirectory, $nComponents, $k, $thousandGenomesDirectory, $samplesDirectory, $algorithm, $aisnpsSet ); } /** * Get ancestry predictions using the ezancestry package. * * @param string|null $outputDirectory The output directory for predictions * @param bool $writePredictions Whether to write the predictions to files * @param string|null $modelsDirectory The directory containing the models * @param string|null $aisnpsDirectory The directory containing the AIsnps * @param int|null $nComponents The number of components for the model * @param int|null $k The number of nearest neighbors to use * @param string|null $thousandGenomesDirectory The directory containing the 1000 Genomes data * @param string|null $samplesDirectory The directory containing the samples * @param string|null $algorithm The algorithm to use for prediction * @param string|null $aisnpsSet The set of AIsnps to use * @return array The predicted ancestry values * @throws Exception If the ezancestry package is not installed or the object is not valid */ public function getPredictions( ?string $outputDirectory = null, bool $writePredictions = false, ?string $modelsDirectory = null, ?string $aisnpsDirectory = null, ?int $nComponents = null, ?int $k = null, ?string $thousandGenomesDirectory = null, ?string $samplesDirectory = null, ?string $algorithm = null, ?string $aisnpsSet = null ): array { if (!$this->valid) { return []; } if (!class_exists('ezancestry\commands\Predict')) { throw new Exception( 'Ancestry prediction requires the ezancestry package; please install it' ); } $predict = new ezancestry\commands\Predict(); $predictions = $predict->predict( $this->snps, $outputDirectory, $writePredictions, $modelsDirectory, $aisnpsDirectory, $nComponents, $k, $thousandGenomesDirectory, $samplesDirectory, $algorithm, $aisnpsSet ); $maxPopValues = $this->maxPop($predictions[0]); $maxPopValues['ezancestry_df'] = $predictions; return $maxPopValues; } /** * Get the maximum population values from a prediction row. * * @param array $row The prediction row * @return array The maximum population values */ private function maxPop(array $row): array { $populationCode = $row['predicted_population_population']; $populationDescription = $row['population_description']; $populationPercent = $row[$populationCode]; $superpopulationCode = $row['predicted_population_superpopulation']; $superpopulationDescription = $row['superpopulation_name']; $superpopulationPercent = $row[$superpopulationCode]; return [ 'population_code' => $populationCode, 'population_description' => $populationDescription, '_percent' => $populationPercent, 'superpopulation_code' => $superpopulationCode, 'superpopulation_description' => $superpopulationDescription, 'population_percent' => $superpopulationPercent, ]; }
- [X] Modify `src/Snps/VariedicInherit.php` ✓ https://github.com/liberu-genealogy/php-dna/commit/f4afb22a3ce1353f8d1dbcc9b79139a1c79c643d [Edit](https://github.com/liberu-genealogy/php-dna/edit/sweep/refactor_generally_to_improve_quality_th_79eb7/src/Snps/VariedicInherit.php)
Modify src/Snps/VariedicInherit.php with contents: Update the `compute_cluster_overlap()` method in the `VariedicInherit` class to follow PSR standards. Update with the necessary changes: /** * Computes cluster overlap based on given threshold. * * @param float $cluster_overlap_threshold The threshold for cluster overlap. * @return DataFrame The computed cluster overlap DataFrame. */ public function compute_cluster_overlap($cluster_overlap_threshold = 0.95) { // Sample data for cluster overlap computation $data = [ "cluster_id" => ["c1", "c3", "c4", "c5", "v5"], "company_composition" => [ "23andMe-v4", "AncestryDNA-v1, FTDNA, MyHeritage", "23andMe-v3", "AncestryDNA-v2", "23andMe-v5, LivingDNA", ], "chip_base_deduced" => [ "HTS iSelect HD", "OmniExpress", "OmniExpress plus", "OmniExpress plus", "Illumina GSAs", ], "snps_in_cluster" => array_fill(0, 5, 0), "snps_in_common" => array_fill(0, 5, 0), ]; // Create a DataFrame from the data and set "cluster_id" as the index $df = new DataFrame($data); $df->setIndex("cluster_id"); $to_remap = null; if ($this->build != 37) { // Create a clone of the current object for remapping $to_remap = clone $this; $to_remap->remap(37); // clusters are relative to Build 37 $self_snps = $to_remap->snps()->select(["chrom", "pos"])->dropDuplicates(); } else { $self_snps = $this->snps()->select(["chrom", "pos"])->dropDuplicates(); } // Retrieve chip clusters from resources $chip_clusters = $this->resources->get_chip_clusters(); // Iterate over each cluster in the DataFrame foreach ($df->indexValues() as $cluster) { // Filter chip clusters based on the current cluster $cluster_snps = $chip_clusters->filter(function ($row) use ($cluster) { return strpos($row["clusters"], $cluster) !== false; })->select(["chrom", "pos"]); // Update the DataFrame with the number of SNPs in the cluster and in common with the current object $df->loc[$cluster]["snps_in_cluster"] = count($cluster_snps); $df->loc[$cluster]["snps_in_common"] = count($self_snps->merge($cluster_snps, "inner")); // Calculate overlap ratios for cluster and self $df["overlap_with_cluster"] = $df["snps_in_common"] / $df["snps_in_cluster"]; $df["overlap_with_self"] = $df["snps_in_common"] / count($self_snps); // Find the cluster with the maximum overlap $max_overlap = array_keys($df["overlap_with_cluster"], max($df["overlap_with_cluster"]))[0]; // Check if the maximum overlap exceeds the threshold for both cluster and self if ( $df["overlap_with_cluster"][$max_overlap] > $cluster_overlap_threshold && $df["overlap_with_self"][$max_overlap] > $cluster_overlap_threshold ) { // Update the current object's cluster and chip based on the maximum overlap $this->cluster = $max_overlap; $this->chip = $df["chip_base_deduced"][$max_overlap]; $company_composition = $df["company_composition"][$max_overlap]; // Check if the current object's source is present in the company composition if (strpos($company_composition, $this->source) !== false) { if ($this->source === "23andMe" || $this->source === "AncestryDNA") { // Extract the chip version from the company composition $i = strpos($company_composition, "v"); $this->chip_version = substr($company_composition, $i, $i + 2); } } else { // Log a warning about the SNPs data source not found } } } // Return the computed cluster overlap DataFrame return $df; } } Update block with the necessary changes: /** * Compute cluster overlap based on a given threshold. * * @param float $clusterOverlapThreshold The threshold for cluster overlap * @return DataFrame The computed cluster overlap DataFrame */ public function computeClusterOverlap(float $clusterOverlapThreshold = 0.95): DataFrame { $data = [ 'cluster_id' => ['c1', 'c3', 'c4', 'c5', 'v5'], 'company_composition' => [ '23andMe-v4', 'AncestryDNA-v1, FTDNA, MyHeritage', '23andMe-v3', 'AncestryDNA-v2', '23andMe-v5, LivingDNA', ], 'chip_base_deduced' => [ 'HTS iSelect HD', 'OmniExpress', 'OmniExpress plus', 'OmniExpress plus', 'Illumina GSAs', ], 'snps_in_cluster' => array_fill(0, 5, 0), 'snps_in_common' => array_fill(0, 5, 0), ]; $df = new DataFrame($data); $df->setIndex('cluster_id'); $toRemap = null; if ($this->build !== 37) { $toRemap = clone $this; $toRemap->remap(37); $selfSnps = $toRemap->snps()->select(['chrom', 'pos'])->dropDuplicates(); } else { $selfSnps = $this->snps()->select(['chrom', 'pos'])->dropDuplicates(); } $chipClusters = $this->resources->getChipClusters(); foreach ($df->indexValues() as $cluster) { $clusterSnps = $chipClusters->filter( function ($row) use ($cluster) { return strpos($row['clusters'], $cluster) !== false; } )->select(['chrom', 'pos']); $df->loc[$cluster]['snps_in_cluster'] = count($clusterSnps); $df->loc[$cluster]['snps_in_common'] = count($selfSnps->merge($clusterSnps, 'inner')); $df['overlap_with_cluster'] = $df['snps_in_common'] / $df['snps_in_cluster']; $df['overlap_with_self'] = $df['snps_in_common'] / count($selfSnps); $maxOverlap = array_keys($df['overlap_with_cluster'], max($df['overlap_with_cluster']))[0]; if ( $df['overlap_with_cluster'][$maxOverlap] > $clusterOverlapThreshold && $df['overlap_with_self'][$maxOverlap] > $clusterOverlapThreshold ) { $this->cluster = $maxOverlap; $this->chip = $df['chip_base_deduced'][$maxOverlap]; $companyComposition = $df['company_composition'][$maxOverlap]; if (strpos($companyComposition, $this->source) !== false) { if ($this->source === '23andMe' || $this->source === 'AncestryDNA') { $i = strpos($companyComposition, 'v'); $this->chip_version = substr($companyComposition, $i, $i + 2); } } else { // Log a warning about the SNPs data source not found } } } return $df; } }
--- ## Step 3: 🔁 Code Review I have finished reviewing the code for completeness. I did not find errors for [`sweep/refactor_generally_to_improve_quality_th_79eb7`](https://github.com/liberu-genealogy/php-dna/commits/sweep/refactor_generally_to_improve_quality_th_79eb7). ---
🎉 Latest improvements to Sweep:
  • New dashboard launched for real-time tracking of Sweep issues, covering all stages from search to coding.
  • Integration of OpenAI's latest Assistant API for more efficient and reliable code planning and editing, improving speed by 3x.
  • Use the GitHub issues extension for creating Sweep issues directly from your editor.
💡 To recreate the pull request edit the issue title or description. Something wrong? [Let us know](https://community.sweep.dev/). *This is an automated message generated by [Sweep AI](https://sweep.dev).*

from php-dna.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.