У меня есть два файла, «тест» и «образец». каждый файл содержит «rs-числа», за которыми следуют «генотипы».
Файл теста меньше файла примера. только около 150 rs-номеров + их генотипы.
Тем не менее, образец файла содержит более 900k rs-номеров + их генотипы.
readTest () открывает «test.tsv», читает файл построчно и возвращает вектор кортежей. кортеж содержит (rs-номер, тип geno).
analysis () берет результат из readTest (), открывает файл примера, читает файл построчно, а затем выполняет сравнение.
пример из файла примера:
rs12124811 \ t1 \ t776546 \ ТАА \ г \ п
rs11240777 \ t1 \ t798959 \ TGG \ г \ п
rs12124811 и rs11240777 - это числа rs. АА и ГГ являются их генотипами.
время работы будет n * m. В моей версии этой программы на c ++ это занимает 30 секунд, в то время как версия Python занимает всего 15 секунд и 5 секунд с многопроцессорной обработкой.
vector<tuple<QString, QString>> readTest(string test){
// readTest can be done instantly
return tar_gene;
}
// tar_gene is the result from readTest()
// now call analyze. it reads through the sample.txt by line and does
// comparison.
QString analyze(string sample_name,
vector<tuple<QString, QString>> tar_gene
){
QString data_matches;
QFile file(QString::fromStdString(sample_name));
file.open(QIODevice::ReadOnly);
//skip first 20 lines
for(int i= 0; i < 20; i++){
file.readLine();
}
while(!file.atEnd()){ // O(m)
const QByteArray line = file.readLine();
const QList<QByteArray> tokens = line.split('\t');
// tar_gene is the result from readTest()
for (auto i: tar_gene){ // O(n*m)
// check if two rs-numbers are matched
if (get<0>(i) == tokens[0]){
QString i_rs = get<0>(i);
QString i_geno = get<1>(i);
QByteArray cur_geno = tokens[3].split('\r')[0];
// check if their genotypes are matched
if(cur_geno.length() == 2){
if (i_geno == cur_geno.at(0) || i_geno == cur_geno.at(1)){
data_matches += i_rs + '-' + i_geno + '\n';
break; // rs-numbers are unique. we can safely break
// the for loop
}
}
// check if their genotypes are matched
else if (cur_geno.length() == 1) {
if (i_geno == cur_geno.at(0)){
data_matches += i_rs + '-' + i_geno + '\n';
break; // rs-numbers are unique. we can safely break
// the for loop
}
}
}
}
}
return data_matches; // QString data_matches will be used in main() and
// printed out in text browser
}
Вот полный исходный код
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
QString analyze(string sample_name,
vector<tuple<QString, QString>> tar_gene,
int start, int end){
QString rs_matches, data_matches;
QFile file(QString::fromStdString(sample_name));
file.open(QIODevice::ReadOnly);
//skip first 20 lines
for(int i= 0; i < 20; i++){
file.readLine();
}
while(!file.atEnd()){
const QByteArray line = file.readLine();
const QList<QByteArray> tokens = line.split('\t');
for (auto i: tar_gene){
if (get<0>(i) == tokens[0]){
QString i_rs = get<0>(i);
QString i_geno = get<1>(i);
QByteArray cur_geno = tokens[3].split('\r')[0];
if(cur_geno.length() == 2){
if (i_geno == cur_geno.at(0) || i_geno == cur_geno.at(1)){
data_matches += i_rs + '-' + i_geno + '\n';
break;
}
}
else if (cur_geno.length() == 1) {
if (i_geno == cur_geno.at(0)){
data_matches += i_rs + '-' + i_geno + '\n';
break;
}
}
}
}
}
return data_matches;
}
vector<tuple<QString, QString>> readTest(string test){
vector<tuple<QString, QString>> tar_gene;
QFile file(QString::fromStdString(test));
file.open(QIODevice::ReadOnly);
file.readLine(); // skip first line
while(!file.atEnd()){
QString line = file.readLine();
QStringList templist;
templist.append(line.split('\t')[20].split('-'));
tar_gene.push_back(make_tuple(templist.at(0),
templist.at(1)));
}
return tar_gene;
}
void MainWindow::on_pushButton_analyze_clicked()
{
if(ui->comboBox_sample->currentIndex() == 0){
ui->textBrowser_rs->setText("Select a sample.");
return;
}
if(ui->comboBox_test->currentIndex() == 0){
ui->textBrowser_rs->setText("Select a test.");
return;
}
string sample = (ui->comboBox_sample->currentText().toStdString()) + ".txt";
string test = ui->comboBox_test->currentText().toStdString() + ".tsv";
vector<tuple<QString, QString>> tar_gene;
QFile file_test(QString::fromStdString(test));
if (!file_test.exists()) {
ui->textBrowser_rs->setText("The test file doesn't exist.");
return;
}
tar_gene = readTest(test);
QFile file_sample(QString::fromStdString(sample));
if (!file_sample.exists()) {
ui->textBrowser_rs->setText("The sample file doesn't exist.");
return;
}
clock_t t1,t2;
t1=clock();
QString result = analyze(sample, tar_gene, 0, 0);
t2=clock();
float diff ((float)t2-(float)t1);
float seconds = diff / CLOCKS_PER_SEC;
qDebug() << seconds;
ui->textBrowser_rsgeno->setText(result);
}
Как мне заставить его работать быстрее? Я переделал свою программу на C ++, потому что ожидал увидеть лучшую производительность, чем версия Python!
с @Felix помогает, моя программа теперь занимает 15 секунд. Я попробую многопоточность позже.
вот примеры файлов с исходными данными:
(test.tsv)
rs17760268-С
rs10439884-А
rs4911642-С
rs157640-G
... и больше. Они не отсортированы.
(sample.txt)
rs12124811 \ t1 \ t776546 \ ТАА \ г \ п
rs11240777 \ t1 \ t798959 \ TGG \ г \ п
... и больше. Они не отсортированы.
есть ли рекомендации по улучшению структуры данных или алгоритмов?