From 2ec244b1268211c205393781894890e3fd140c6c Mon Sep 17 00:00:00 2001 From: Syed Nakib Hossain Date: Tue, 10 Dec 2024 14:57:09 +0000 Subject: [PATCH 1/7] Nextflow ProteinFunction: support for SQLite db --- .../bin/store_polyphen_scores.pl | 35 +++++++++------ .../ProteinFunction/bin/store_sift_scores.pl | 33 ++++++++------ nextflow/ProteinFunction/main.nf | 43 ++++++++++++++++--- .../nf_modules/database_utils.nf | 27 ++++++++++++ .../ProteinFunction/nf_modules/polyphen2.nf | 12 +++--- nextflow/ProteinFunction/nf_modules/sift.nf | 12 +++--- 6 files changed, 122 insertions(+), 40 deletions(-) diff --git a/nextflow/ProteinFunction/bin/store_polyphen_scores.pl b/nextflow/ProteinFunction/bin/store_polyphen_scores.pl index 58a127815f..0b82bde196 100755 --- a/nextflow/ProteinFunction/bin/store_polyphen_scores.pl +++ b/nextflow/ProteinFunction/bin/store_polyphen_scores.pl @@ -6,6 +6,7 @@ use Digest::MD5 qw(md5_hex); my ($species, $port, $host, $user, $pass, $dbname, + $offline, $sqlite, $peptide, $output_file, $model) = @ARGV; # Extract model name @@ -62,18 +63,28 @@ # save the predictions to the database unless they are null matrices if ( $any_results ){ - my $var_dba = Bio::EnsEMBL::Variation::DBSQL::DBAdaptor->new( - '-species' => $species, - '-port' => $port, - '-host' => $host, - '-user' => $user, - '-pass' => $pass, - '-dbname' => $dbname - ); - my $pfpma = $var_dba->get_ProteinFunctionPredictionMatrixAdaptor - or die "Failed to get matrix adaptor"; - $pfpma->store($pred_matrix); - $var_dba->dbc and $var_dba->dbc->disconnect_if_idle(); + if (!$offline){ + my $var_dba = Bio::EnsEMBL::Variation::DBSQL::DBAdaptor->new( + '-species' => $species, + '-port' => $port, + '-host' => $host, + '-user' => $user, + '-pass' => $pass, + '-dbname' => $dbname + ); + my $pfpma = $var_dba->get_ProteinFunctionPredictionMatrixAdaptor + or die "Failed to get matrix adaptor"; + $pfpma->store($pred_matrix); + $var_dba->dbc and $var_dba->dbc->disconnect_if_idle(); + } + + if ($sqlite){ + my $dbh = DBI->connect("dbi:SQLite:dbname=$db","",""); + my $sth = $dbh->prepare("INSERT INTO predictions VALUES(?, ?, ?)"); + + my $attrib_id = $model_name eq "humdiv" ? 269 : 268; + $sth->execute($pred_matrix->translation_md5, $attrib_id, $pred_matrix->serialize) + } } else { warn "Skipping: no results to store\n"; } diff --git a/nextflow/ProteinFunction/bin/store_sift_scores.pl b/nextflow/ProteinFunction/bin/store_sift_scores.pl index 6f23fac79f..94592c7d4a 100755 --- a/nextflow/ProteinFunction/bin/store_sift_scores.pl +++ b/nextflow/ProteinFunction/bin/store_sift_scores.pl @@ -6,6 +6,7 @@ use Digest::MD5 qw(md5_hex); my ($species, $port, $host, $user, $pass, $dbname, + $offline, $sqlite, $peptide, $res_file) = @ARGV; # parse the results file @@ -49,18 +50,26 @@ # save the predictions to the database if ($results_available == 1 ){ - my $var_dba = Bio::EnsEMBL::Variation::DBSQL::DBAdaptor->new( - '-species' => $species, - '-port' => $port, - '-host' => $host, - '-user' => $user, - '-pass' => $pass, - '-dbname' => $dbname - ); - my $pfpma = $var_dba->get_ProteinFunctionPredictionMatrixAdaptor - or die "Failed to get matrix adaptor"; - $pfpma->store($pred_matrix); - $var_dba->dbc and $var_dba->dbc->disconnect_if_idle(); + if (!$offline){ + my $var_dba = Bio::EnsEMBL::Variation::DBSQL::DBAdaptor->new( + '-species' => $species, + '-port' => $port, + '-host' => $host, + '-user' => $user, + '-pass' => $pass, + '-dbname' => $dbname + ); + my $pfpma = $var_dba->get_ProteinFunctionPredictionMatrixAdaptor + or die "Failed to get matrix adaptor"; + $pfpma->store($pred_matrix); + $var_dba->dbc and $var_dba->dbc->disconnect_if_idle(); + } + + if ($sqlite){ + my $dbh = DBI->connect("dbi:SQLite:dbname=$db","",""); + my $sth = $dbh->prepare("INSERT INTO predictions VALUES(?, ?, ?)"); + $sth->execute($pred_matrix->translation_md5, 267, $pred_matrix->serialize) + } } else { warn "Skipping: no results to store\n"; } diff --git a/nextflow/ProteinFunction/main.nf b/nextflow/ProteinFunction/main.nf index 738055c46b..6267818e76 100644 --- a/nextflow/ProteinFunction/main.nf +++ b/nextflow/ProteinFunction/main.nf @@ -18,6 +18,12 @@ params.port = null params.user = null params.pass = null params.database = null +params.offline = false + +// SQLite database params +params.sqlite = false +params.sqlite_dir = params.outdir +params.sqlite_db = null // SIFT params params.sift_run_type = "NONE" @@ -84,7 +90,9 @@ if (params.help) { // Module imports include { decompress } from './nf_modules/utils.nf' include { translate_fasta } from './nf_modules/translations.nf' -include { store_translation_mapping } from './nf_modules/database_utils.nf' +include { store_translation_mapping; + init_sqlite_db; + postprocess_sqlite_db } from './nf_modules/database_utils.nf' include { run_sift_pipeline } from './nf_modules/sift.nf' include { run_pph2_pipeline } from './nf_modules/polyphen2.nf' @@ -101,8 +109,19 @@ if (!params.translated) { } } -if (!params.host || !params.port || !params.user || !params.pass || !params.database) { - exit 1, "Error: --host, --port, --user, --pass and --database need to be defined" +if (!params.offline && (!params.host || !params.port || !params.user || !params.pass || !params.database)) { + exit 1, "ERROR: --host, --port, --user, --pass and --database need to be defined" +} + +if (!params.offline && !params.sqlite) { + log.info "WARNING: --offline mode selected, setting --sqlite to true." + params.sqlite = true +} + +if (params.sqlite) { + if (!params.sqlite_db) { + params.sqlite_db = params.sqlite_dir + "/" + params.species + 'PolyPhen_SIFT.db' + } } // Check run type for each protein function predictor @@ -156,6 +175,12 @@ def getFiles (files) { } workflow { + if (params.sqlite) { + sqlite_db_prep = init_sqlite_db() + } else { + sqlite_db_prep = "ready" + } + // Translate transcripts from GTF and FASTA if no translation FASTA is given if (!params.translated) { translate_fasta(getFiles(params.gtf), getFiles(params.fasta)) @@ -180,12 +205,18 @@ workflow { name: "translation_mapping.tsv", storeDir: params.outdir, newLine: true) { it.id + "\t" + it.md5 } - store_translation_mapping(translation_mapping) + if (!params.offline) { + store_translation_mapping(translation_mapping) + } // Get unique translations based on MD5 hashes of their sequences translated = translated.unique { it.md5 } // Run protein function prediction - if ( params.sift_run_type != "NONE" ) run_sift_pipeline( translated ) - if ( params.pph_run_type != "NONE" ) run_pph2_pipeline( translated ) + if ( params.sift_run_type != "NONE" ) run_sift_pipeline( translated, sqlite_db_prep ) + if ( params.pph_run_type != "NONE" ) run_pph2_pipeline( translated, sqlite_db_prep ) + + if ( params.sqlite ) { + postprocess_sqlite_db() + } } diff --git a/nextflow/ProteinFunction/nf_modules/database_utils.nf b/nextflow/ProteinFunction/nf_modules/database_utils.nf index 737dca9050..c5de1262c6 100644 --- a/nextflow/ProteinFunction/nf_modules/database_utils.nf +++ b/nextflow/ProteinFunction/nf_modules/database_utils.nf @@ -90,3 +90,30 @@ process get_current_MD5_translations { EOF """ } + +process init_sqlite_db { + output: stdout + + cache false + + """ + #!/usr/bin/perl + my $dbh = DBI->connect("dbi:SQLite:dbname=${params.sqlite_db}","",""); + + $dbh->do("DROP TABLE IF EXISTS predictions"); + $dbh->do("CREATE TABLE predictions(md5, analysis, matrix)"); + """ +} + +process postprocess_sqlite_db { + output: stdout + + cache false + + """ + #!/usr/bin/perl + my $dbh = DBI->connect("dbi:SQLite:dbname=${params.sqlite_db}","",""); + + $dbh->do("CREATE INDEX md5_idx ON predictions(md5)"); + """ +} \ No newline at end of file diff --git a/nextflow/ProteinFunction/nf_modules/polyphen2.nf b/nextflow/ProteinFunction/nf_modules/polyphen2.nf index 1e189eac9e..f9823f028f 100644 --- a/nextflow/ProteinFunction/nf_modules/polyphen2.nf +++ b/nextflow/ProteinFunction/nf_modules/polyphen2.nf @@ -99,8 +99,8 @@ process store_pph2_scores { tuple val(peptide), path(weka_output), val(model) """ - store_polyphen_scores.pl $species ${params.port} ${params.host} \ - ${params.user} ${params.pass} ${params.database} \ + store_polyphen_scores.pl ${species} ${params.offline} ${params.sqlite_db} \ + ${params.port} ${params.host} ${params.user} ${params.pass} ${params.database} \ ${peptide.seqString} ${weka_output} ${model} """ } @@ -110,12 +110,14 @@ include { delete_prediction_data; update_meta } from './database_utils.nf' include { filter_existing_translations } from './translations.nf' workflow run_pph2_pipeline { - take: translated + take: + translated + sqlite_db_prep main: - if ( params.pph_run_type == "UPDATE" ) { + if ( params.pph_run_type == "UPDATE" && !params.offline ) { translated = filter_existing_translations( "polyphen_%", translated ) wait = "ready" - } else if ( params.pph_run_type == "FULL" ) { + } else if ( params.pph_run_type == "FULL" && !params.offline ) { delete_prediction_data("polyphen_%") wait = delete_prediction_data.out get_pph2_version() diff --git a/nextflow/ProteinFunction/nf_modules/sift.nf b/nextflow/ProteinFunction/nf_modules/sift.nf index 95cec3fc4f..1ee2902c92 100644 --- a/nextflow/ProteinFunction/nf_modules/sift.nf +++ b/nextflow/ProteinFunction/nf_modules/sift.nf @@ -108,8 +108,8 @@ process store_sift_scores { tuple val(peptide), path(sift_scores) """ - store_sift_scores.pl ${species} ${params.port} ${params.host} \ - ${params.user} ${params.pass} ${params.database} \ + store_sift_scores.pl ${species} ${params.offline} ${params.sqlite_db} \ + ${params.port} ${params.host} ${params.user} ${params.pass} ${params.database} \ ${peptide.seqString} ${sift_scores} """ } @@ -131,12 +131,14 @@ workflow update_sift_db_version { } workflow run_sift_pipeline { - take: translated + take: + translated + sqlite_db_prep main: - if ( params.sift_run_type == "UPDATE" ) { + if ( params.sift_run_type == "UPDATE" && !params.offline ) { translated = filter_existing_translations( "sift", translated ) wait = "ready" - } else if ( params.sift_run_type == "FULL" ) { + } else if ( params.sift_run_type == "FULL" && !params.offline ) { delete_prediction_data("sift") wait = delete_prediction_data.out update_sift_version() From 9a015843e30278601dc48842253725c15d4e7a6c Mon Sep 17 00:00:00 2001 From: Syed Nakib Hossain Date: Wed, 18 Dec 2024 17:12:26 +0000 Subject: [PATCH 2/7] Convert min to float to avoid rounding error --- nextflow/utils/utils.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nextflow/utils/utils.nf b/nextflow/utils/utils.nf index c8d3ce662f..173947da5e 100644 --- a/nextflow/utils/utils.nf +++ b/nextflow/utils/utils.nf @@ -71,6 +71,8 @@ def check_JVM_mem (min=0.4) { @param min Min memory in GiB (default: 0.4) */ + // converts min to float to avoid error while rounding + min = min / 10.0 * 10.0 mem = Runtime.getRuntime().maxMemory() / (1024 ** 3) // in GiB if (mem < min) { log.error """ From 12a847c7d9c284921436fb7fcb9f5632af6e7102 Mon Sep 17 00:00:00 2001 From: Syed Nakib Hossain Date: Wed, 18 Dec 2024 17:13:02 +0000 Subject: [PATCH 3/7] Fix nextflow and bash variable conflict --- .../nf_modules/database_utils.nf | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/nextflow/ProteinFunction/nf_modules/database_utils.nf b/nextflow/ProteinFunction/nf_modules/database_utils.nf index c5de1262c6..c3dd79bfa4 100644 --- a/nextflow/ProteinFunction/nf_modules/database_utils.nf +++ b/nextflow/ProteinFunction/nf_modules/database_utils.nf @@ -98,22 +98,30 @@ process init_sqlite_db { """ #!/usr/bin/perl - my $dbh = DBI->connect("dbi:SQLite:dbname=${params.sqlite_db}","",""); - $dbh->do("DROP TABLE IF EXISTS predictions"); - $dbh->do("CREATE TABLE predictions(md5, analysis, matrix)"); + use DBI; + + my \$dbh = DBI->connect("dbi:SQLite:dbname=${params.sqlite_db}","",""); + \$dbh->do("DROP TABLE IF EXISTS predictions"); + \$dbh->do("CREATE TABLE predictions(md5, analysis, matrix)"); """ } process postprocess_sqlite_db { + input: + val sift_run + val polyphen_run + output: stdout cache false """ #!/usr/bin/perl - my $dbh = DBI->connect("dbi:SQLite:dbname=${params.sqlite_db}","",""); + + use DBI; - $dbh->do("CREATE INDEX md5_idx ON predictions(md5)"); + my \$dbh = DBI->connect("dbi:SQLite:dbname=${params.sqlite_db}","",""); + \$dbh->do("CREATE INDEX md5_idx ON predictions(md5)"); """ } \ No newline at end of file From aa6c46b74cfa5990f872222cbb0df5f97e37455f Mon Sep 17 00:00:00 2001 From: Syed Nakib Hossain Date: Wed, 18 Dec 2024 17:14:03 +0000 Subject: [PATCH 4/7] Update slurm config; add 137 in retry code --- nextflow/ProteinFunction/nextflow.config | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nextflow/ProteinFunction/nextflow.config b/nextflow/ProteinFunction/nextflow.config index a9afe3c670..cf6ca218f1 100644 --- a/nextflow/ProteinFunction/nextflow.config +++ b/nextflow/ProteinFunction/nextflow.config @@ -10,8 +10,12 @@ profiles { } } - //untested - slurm { process.executor = 'slurm' } + slurm { + process { + executor = 'slurm' + time = '3d' + } + } } singularity { @@ -28,9 +32,9 @@ process { // Exit status codes: // - 130: job exceeded LSF allocated memory // - 140: job exceeded SLURM allocated resources (memory, CPU, time) - errorStrategy = { task.exitStatus in [130, 140] ? 'retry' : 'finish' } + errorStrategy = { task.exitStatus in [130, 137, 140] ? 'retry' : 'finish' } withLabel: retry_before_ignoring { - errorStrategy = { task.exitStatus in [130, 140] ? 'retry' : 'ignore' } + errorStrategy = { task.exitStatus in [130, 137, 140] ? 'retry' : 'ignore' } } maxRetries = 3 } From 8e9835fe7c6588c7f16cd8410ca54a0b5820d4f6 Mon Sep 17 00:00:00 2001 From: Syed Nakib Hossain Date: Wed, 18 Dec 2024 17:15:06 +0000 Subject: [PATCH 5/7] Fix SQLite db path and post process --- nextflow/ProteinFunction/main.nf | 34 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/nextflow/ProteinFunction/main.nf b/nextflow/ProteinFunction/main.nf index 6267818e76..fbbef4dbd4 100644 --- a/nextflow/ProteinFunction/main.nf +++ b/nextflow/ProteinFunction/main.nf @@ -21,10 +21,9 @@ params.database = null params.offline = false // SQLite database params -params.sqlite = false -params.sqlite_dir = params.outdir -params.sqlite_db = null - +params.sqlite = params.offline +params.sqlite_dir = params.outdir.startsWith("/") ? params.outdir : "${workflow.launchDir}/${params.outdir}" // supports Unix-like only +params.sqlite_db = "${params.sqlite_dir}/${params.species}_PolyPhen_SIFT.db" // SIFT params params.sift_run_type = "NONE" params.median_cutoff = 2.75 // as indicated in SIFT's README @@ -113,15 +112,8 @@ if (!params.offline && (!params.host || !params.port || !params.user || !params. exit 1, "ERROR: --host, --port, --user, --pass and --database need to be defined" } -if (!params.offline && !params.sqlite) { - log.info "WARNING: --offline mode selected, setting --sqlite to true." - params.sqlite = true -} - -if (params.sqlite) { - if (!params.sqlite_db) { - params.sqlite_db = params.sqlite_dir + "/" + params.species + 'PolyPhen_SIFT.db' - } +if (params.offline) { + log.info "INFO: --offline mode selected, --sqlite will be turned on by default. If you do not wish to generate SQLite db please use --sqlite 0." } // Check run type for each protein function predictor @@ -213,10 +205,20 @@ workflow { translated = translated.unique { it.md5 } // Run protein function prediction - if ( params.sift_run_type != "NONE" ) run_sift_pipeline( translated, sqlite_db_prep ) - if ( params.pph_run_type != "NONE" ) run_pph2_pipeline( translated, sqlite_db_prep ) + if ( params.sift_run_type != "NONE" ) { + sift_run = run_sift_pipeline( translated, sqlite_db_prep ) + } + else { + sift_run = "done" + } + if ( params.pph_run_type != "NONE" ) { + run_pph2_pipeline( translated, sqlite_db_prep ) + } + else { + polyphen_run = "done" + } if ( params.sqlite ) { - postprocess_sqlite_db() + postprocess_sqlite_db(sift_run, polyphen_run) } } From ef4e6bb393b2dd922fd6ea66988f2488b8fa06d3 Mon Sep 17 00:00:00 2001 From: Syed Nakib Hossain Date: Wed, 18 Dec 2024 17:59:39 +0000 Subject: [PATCH 6/7] Fix process flow --- nextflow/ProteinFunction/main.nf | 6 ++---- nextflow/ProteinFunction/nf_modules/polyphen2.nf | 7 +++++++ nextflow/ProteinFunction/nf_modules/sift.nf | 7 +++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/nextflow/ProteinFunction/main.nf b/nextflow/ProteinFunction/main.nf index fbbef4dbd4..d0d7ca010e 100644 --- a/nextflow/ProteinFunction/main.nf +++ b/nextflow/ProteinFunction/main.nf @@ -207,14 +207,12 @@ workflow { // Run protein function prediction if ( params.sift_run_type != "NONE" ) { sift_run = run_sift_pipeline( translated, sqlite_db_prep ) - } - else { + } else { sift_run = "done" } if ( params.pph_run_type != "NONE" ) { run_pph2_pipeline( translated, sqlite_db_prep ) - } - else { + } else { polyphen_run = "done" } diff --git a/nextflow/ProteinFunction/nf_modules/polyphen2.nf b/nextflow/ProteinFunction/nf_modules/polyphen2.nf index f9823f028f..74b534e14a 100644 --- a/nextflow/ProteinFunction/nf_modules/polyphen2.nf +++ b/nextflow/ProteinFunction/nf_modules/polyphen2.nf @@ -98,6 +98,9 @@ process store_pph2_scores { val species tuple val(peptide), path(weka_output), val(model) + output: + stdout + """ store_polyphen_scores.pl ${species} ${params.offline} ${params.sqlite_db} \ ${params.port} ${params.host} ${params.user} ${params.pass} ${params.database} \ @@ -122,6 +125,8 @@ workflow run_pph2_pipeline { wait = delete_prediction_data.out get_pph2_version() update_meta("polyphen_version", get_pph2_version.out) + } else { + wait = "ready" } // Run PolyPhen-2 and Weka run_pph2_on_all_aminoacid_substitutions(translated) @@ -131,4 +136,6 @@ workflow run_pph2_pipeline { run_weka(weka_model, run_pph2_on_all_aminoacid_substitutions.out) store_pph2_scores(wait, // wait for data deletion params.species, run_weka.out) + emit: + store_sift_scores.out } diff --git a/nextflow/ProteinFunction/nf_modules/sift.nf b/nextflow/ProteinFunction/nf_modules/sift.nf index 1ee2902c92..ce1681eed2 100644 --- a/nextflow/ProteinFunction/nf_modules/sift.nf +++ b/nextflow/ProteinFunction/nf_modules/sift.nf @@ -107,6 +107,9 @@ process store_sift_scores { val species tuple val(peptide), path(sift_scores) + output: + stdout + """ store_sift_scores.pl ${species} ${params.offline} ${params.sqlite_db} \ ${params.port} ${params.host} ${params.user} ${params.pass} ${params.database} \ @@ -143,6 +146,8 @@ workflow run_sift_pipeline { wait = delete_prediction_data.out update_sift_version() update_sift_db_version( file(params.blastdb) ) + } else { + wait = "ready" } // Align translated sequences against BLAST database to run SIFT align_peptides(translated, @@ -152,4 +157,6 @@ workflow run_sift_pipeline { store_sift_scores(wait, // wait for data deletion params.species, run_sift_on_all_aminoacid_substitutions.out) + emit: + store_sift_scores.out } From 96d80ff5b4a02f0712dc22790c443f97897fa719 Mon Sep 17 00:00:00 2001 From: Syed Nakib Hossain Date: Wed, 8 Jan 2025 16:05:24 +0000 Subject: [PATCH 7/7] Fix param order and db name --- nextflow/ProteinFunction/bin/store_polyphen_scores.pl | 6 +++--- nextflow/ProteinFunction/bin/store_sift_scores.pl | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nextflow/ProteinFunction/bin/store_polyphen_scores.pl b/nextflow/ProteinFunction/bin/store_polyphen_scores.pl index 0b82bde196..ad3c958a5d 100755 --- a/nextflow/ProteinFunction/bin/store_polyphen_scores.pl +++ b/nextflow/ProteinFunction/bin/store_polyphen_scores.pl @@ -5,8 +5,8 @@ use Bio::EnsEMBL::Variation::ProteinFunctionPredictionMatrix; use Digest::MD5 qw(md5_hex); -my ($species, $port, $host, $user, $pass, $dbname, - $offline, $sqlite, +my ($species, $offline, $sqlite, + $port, $host, $user, $pass, $dbname, $peptide, $output_file, $model) = @ARGV; # Extract model name @@ -79,7 +79,7 @@ } if ($sqlite){ - my $dbh = DBI->connect("dbi:SQLite:dbname=$db","",""); + my $dbh = DBI->connect("dbi:SQLite:dbname=$sqlite","",""); my $sth = $dbh->prepare("INSERT INTO predictions VALUES(?, ?, ?)"); my $attrib_id = $model_name eq "humdiv" ? 269 : 268; diff --git a/nextflow/ProteinFunction/bin/store_sift_scores.pl b/nextflow/ProteinFunction/bin/store_sift_scores.pl index 94592c7d4a..527cf06f28 100755 --- a/nextflow/ProteinFunction/bin/store_sift_scores.pl +++ b/nextflow/ProteinFunction/bin/store_sift_scores.pl @@ -5,8 +5,8 @@ use Bio::EnsEMBL::Variation::ProteinFunctionPredictionMatrix; use Digest::MD5 qw(md5_hex); -my ($species, $port, $host, $user, $pass, $dbname, - $offline, $sqlite, +my ($species, $offline, $sqlite, + $port, $host, $user, $pass, $dbname, $peptide, $res_file) = @ARGV; # parse the results file @@ -66,7 +66,7 @@ } if ($sqlite){ - my $dbh = DBI->connect("dbi:SQLite:dbname=$db","",""); + my $dbh = DBI->connect("dbi:SQLite:dbname=$sqlite","",""); my $sth = $dbh->prepare("INSERT INTO predictions VALUES(?, ?, ?)"); $sth->execute($pred_matrix->translation_md5, 267, $pred_matrix->serialize) }