/* Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg This software is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License (LGPL) for more details. You should have received a copy of the GNU Lesser General Public License (LGPL) along with this program. If not, see . */ /** \file jkqtpdatastorage.cpp * \ingroup jkqtpdatastorage */ #include "jkqtpdatastorage.h" #include #include /************************************************************************************************************************** * JKQTPcolumn **************************************************************************************************************************/ unsigned long long JKQTPcolumn::getRows() const { if (!valid || !datastore) return 0; JKQTPdatastoreItem* i=datastore->getItem(datastoreItem); if (i) return i->get_rows(); else return 0; } void JKQTPcolumn::copyData(QVector ©To) const { double* d=getPointer(0); copyTo.clear(); unsigned long long i, cnt=getRows(); if (cnt>0) { copyTo.resize(cnt); for (i=0; i JKQTPcolumn::copyData() { QVector d; copyData(d); return d; } double JKQTPcolumn::getValue(unsigned long long n) const { if (!datastore) return 0; if (!datastore->getItem(datastoreItem)) return 0; return datastore->getItem(datastoreItem)->get(datastoreOffset, n); } double *JKQTPcolumn::getPointer(unsigned long long n) const { if (!datastore) return 0; if (!datastore->getItem(datastoreItem)) return 0; return datastore->getItem(datastoreItem)->getPointer(datastoreOffset, n); } void JKQTPcolumn::setValue(unsigned long long n, double val) { if (!datastore) return ; if (!datastore->getItem(datastoreItem)) return; datastore->getItem(datastoreItem)->set(datastoreOffset, n, val); }; void JKQTPcolumn::copy(double* data, unsigned long long N, unsigned long long offset) { if (!datastore) return ; JKQTPdatastoreItem* it=datastore->getItem(datastoreItem); if (!it) return; for (unsigned long long i=0; iset(datastoreOffset, i+offset, data[i]); } } void JKQTPcolumn::exchange(double value, double replace) { if (!datastore) return ; for (unsigned long long i=0; idataformat=JKQTPsingleColumn; this->allocated=false; this->data=NULL; this->columns=0; this->rows=0; this->internal=true; } JKQTPdatastoreItem::JKQTPdatastoreItem(size_t columns, unsigned long long rows){ this->internal=true; this->allocated=false; if (columns>1) { this->dataformat=JKQTPmatrixRow; this->data=(double*)calloc(columns*rows, sizeof(double)); } else { this->dataformat=JKQTPsingleColumn; this->data=(double*)calloc(rows, sizeof(double)); } this->columns=columns; this->rows=rows; this->allocated=true; } void JKQTPdatastoreItem::resizeColumns(unsigned long long new_rows) { if (internal && allocated && data!=NULL) { free(data); data=NULL; } data=(double*)calloc(columns*new_rows, sizeof(double)); rows=new_rows; internal=true; allocated=true; } JKQTPdatastoreItem::JKQTPdatastoreItem(JKQTPdatastoreItemFormat dataformat, double* data, size_t columns, unsigned long long rows){ this->dataformat=dataformat; this->allocated=true; this->data=data; this->columns=columns; this->rows=rows; this->internal=false; } JKQTPdatastoreItem::JKQTPdatastoreItem(JKQTPdatastoreItemFormat dataformat, double *data, size_t columns, unsigned long long rows, bool internal) { this->dataformat=dataformat; this->allocated=true; this->data=data; this->columns=columns; this->rows=rows; this->internal=internal; } JKQTPdatastoreItem::~JKQTPdatastoreItem(){ if (internal && allocated && data!=NULL) { free(data); data=NULL; } } /************************************************************************************************************************** * JKQTPdatastore **************************************************************************************************************************/ size_t JKQTPdatastore::addItem(JKQTPdatastoreItem* item) { /*items.push_back(item); return items.size()-1;*/ items.insert(maxItemID, item); maxItemID++; return maxItemID-1; } size_t JKQTPdatastore::addColumn(JKQTPcolumn col) { columns.insert(maxColumnsID, col); maxColumnsID++; return maxColumnsID-1; } JKQTPdatastore::JKQTPdatastore() { maxItemID=0; maxColumnsID=0; clear(); } void JKQTPdatastore::clear(){ maxItemID=0; maxColumnsID=0; /*if (items.size()>0) { for (size_t i=0; i it(items); while (it.hasNext()) { it.next(); delete it.value(); } items.clear(); columns.clear(); } void JKQTPdatastore::deleteAllColumns(QString name, bool removeItems) { QList ids; QMapIterator it(columns); while (it.hasNext()) { it.next(); if (it.value().get_name()==name) { ids.append(it.key()); } } for (int i=0; i ids; QMapIterator it(columns); while (it.hasNext()) { it.next(); if (it.value().get_name().startsWith(prefix)) { ids.append(it.key()); } } for (int i=0; i it(columns); while (it.hasNext()) { it.next(); if (it.value().get_datastoreItem()==dsitem) { cnt++; } } if (cnt<=1) { delete items[dsitem]; items.remove(dsitem); } } columns.remove(column); } int JKQTPdatastore::getColumnNum(QString name) { if (columns.size()<=0) return -1; QMapIterator it(columns); while (it.hasNext()) { it.next(); if (it.value().get_name()==name) return it.key(); } return -1; } size_t JKQTPdatastore::ensureColumnNum(QString name) { if (columns.size()<=0) return -1; QMapIterator it(columns); while (it.hasNext()) { it.next(); if (it.value().get_name()==name) return it.key(); } return addColumn(0, name); } JKQTPcolumn JKQTPdatastore::getColumn(size_t i) const { return columns.value(i); } size_t JKQTPdatastore::addCopiedItem(JKQTPdatastoreItemFormat dataformat, double* data, size_t columnsnum, unsigned long long rows) { JKQTPdatastoreItem* it=NULL; if ((dataformat==JKQTPsingleColumn)||(columnsnum==1)) { return addCopiedItem(data, rows); } else if (dataformat==JKQTPmatrixColumn) { it=new JKQTPdatastoreItem(columnsnum, rows); for (size_t c=0; cset(c, r, data[c*rows+r]); } } } else if (dataformat==JKQTPmatrixColumn) { it=new JKQTPdatastoreItem(columnsnum, rows); for (unsigned long long r=0; rset(c, r, data[r*columnsnum+c]); } } } /*items.push_back(it); return items.size()-1;*/ return addItem(it); }; /** \brief add a new columns/item with \a rows rows to the datastore and return its ID. The item uses internal memory management. */ size_t JKQTPdatastore::addItem(unsigned long long rows) { /*items.push_back(new JKQTPdatastoreItem(1, rows)); return items.size()-1;*/ return addItem(new JKQTPdatastoreItem(1, rows)); }; /** \brief add a new item with \a rows rows and \a columns columns to the datastore and return its ID. The item uses internal memory management. */ size_t JKQTPdatastore::addItem(size_t columnsnum, unsigned long long rows) { /*items.push_back(new JKQTPdatastoreItem(columnsnum, rows)); return items.size()-1;*/ return addItem(new JKQTPdatastoreItem(columnsnum, rows)); }; /** \brief add one external column to the datastore. It contains \a rows rows.*/ size_t JKQTPdatastore::addItem(double* data, unsigned long long rows) { /*items.push_back(new JKQTPdatastoreItem(JKQTPsingleColumn, data, 1, rows)); return items.size()-1;*/ return addItem(new JKQTPdatastoreItem(JKQTPsingleColumn, data, 1, rows)); } size_t JKQTPdatastore::addInternalItem(double *data, unsigned long long rows) { JKQTPdatastoreItem* dsi=new JKQTPdatastoreItem(JKQTPsingleColumn, data, 1, rows, true); return addItem(dsi); }; /** \brief add an external memory block to the datastore. It contains \a rows rows and \a columns columns. \a dataformat determined the memory layout*/ size_t JKQTPdatastore::addItem(JKQTPdatastoreItemFormat dataformat, double* data, size_t columnsnum, unsigned long long rows) { /*items.push_back(new JKQTPdatastoreItem(dataformat, data, columnsnum, rows)); return items.size()-1;*/ return addItem(new JKQTPdatastoreItem(dataformat, data, columnsnum, rows)); }; /** \brief add one external array to the datastore. It contains \a rows rows. The data is copied and the copy managed internally */ size_t JKQTPdatastore::addCopiedItem(const double* data, unsigned long long rows) { JKQTPdatastoreItem* it=new JKQTPdatastoreItem(1, rows); if (data) { for (unsigned long long i=0; iset(0, i, data[i]); //std::cout<<"copy@"< &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name, unsigned long long stride) { return addCopiedColumn(data.data(), data.size(), stride, name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::addCopiedColumn(const QVector &data, QString name) { return addCopiedColumn(data.data(), data.size(), name); } size_t JKQTPdatastore::copyColumn(size_t old_column, unsigned long long start, unsigned long long stride, QString name) { JKQTPcolumn old=columns[old_column]; unsigned long long rows=old.getRows(); double* d=(double*)malloc(rows*sizeof(double)); double* dd=old.getPointer(0); int j=0; for (unsigned long long i=start; iset(0, i, start+(double)i * delta); //std::cout<<"copy@"<=0) return getNextLowerIndex(column, row, 0, end); else if (start>=0 && end<0) return getNextLowerIndex(column, row, start, col.getRows()-1); else if (start<0 && end<0) return getNextLowerIndex(column, row, 0, col.getRows()-1); else { double d=0; const double v=col.getValue(row); long long res=-1; for ( long long i=start; i<=end; i++) { if (i!=(long long)row) { const double v1=col.getValue(i); const double dd=v1-v; if ((dd<0) && ((fabs(dd)=0) return getNextHigherIndex(column, row, 0, end); else if (start>=0 && end<0) return getNextHigherIndex(column, row, start, col.getRows()-1); else if (start<0 && end<0) return getNextHigherIndex(column, row, 0, col.getRows()-1); else { double d=0; const double v=col.getValue(row); long long res=-1; for ( long long i=start; i<=end; i++) { if (i!=(long long)row) { const double v1=col.getValue(i); const double dd=v1-v; if ((dd>0) && ((fabs(dd)res) res=r; }*/ QMapIterator it(columns); while (it.hasNext()) { it.next(); unsigned long long r=it.value().getRows(); if (r>res) res=r; } return res; } void JKQTPdatastore::saveCSV(QString filename, QSet userColumns, QString separator, QString decimal_separator, QString comment, QString aroundStrings, char floatformat) { //std::cout< userColumns) { //std::cout< it(columns); int col=0; while (it.hasNext()) { it.next(); names.append(it.value().get_name()); col++; } return names; } void JKQTPdatastore::saveMatlab(QTextStream &txt, QSet userColumns) { //std::cout< varnames; txt.setLocale(loc); /* if (comment.size()>0) { txt< it(columns); while (it.hasNext()) { it.next(); if (!first) txt< it(columns); int col=0; int i=0; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(i)) { // convert the column name into a variable name (name cleanup!) If the column name is empty, we use a default name ("column") QString newvarbase=jkqtp_to_valid_variable_name(it.value().get_name().toStdString()).c_str(); if (newvarbase.isEmpty()) newvarbase="column"; int cnt=1; QString newvar=newvarbase; // now we make sure that the name is not already used, i.e. we compare it to all variable names used so far and if it has already been used, // an increasing number is added to the name. while (varnames.contains(newvar)) { newvar=newvarbase+QString::number(cnt); cnt++; } varnames.insert(newvar); txt< userColumns, QString separator, QString decimal_separator, QString comment, QString aroundStrings, char floatformat) { //std::cout<0) { txt< it(columns); int i=0; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(i)) { if (!first) txt< it(columns); int j=0; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(j)) { if (!first) txt<i) { QString num=QString("%1").arg(get(it.key(), i), 0, floatformat); num=num.replace(dsep, decimal_separator); txt< userColumns, QString floatformat) { Q_UNUSED(floatformat) // find out the decimal and the thousand separator QLocale loc=QLocale::c(); loc.setNumberOptions(QLocale::OmitGroupSeparator); //QChar dsep=loc.decimalPoint(); QFile f(filename); if (!f.open(QIODevice::WriteOnly|QIODevice::Text)) return; QTextStream txt(&f); txt.setLocale(loc); // write SYLK header txt<<"ID;P\n"; // write column headers QMapIterator it(columns); size_t c=1; int i=0; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(i)) { txt<<"C;Y1;X"< it(columns); c=1; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(i)) { if (it.value().getRows()>i) { txt< > JKQTPdatastore::getData(QStringList *columnNames, QSet userColumns) { QStringList cl; QList > res; // write column headers QMapIterator it(columns); size_t c=1; int i=0; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(i)) { QVector dat; for (unsigned long long i=0; i userColumns, QString floatformat) { Q_UNUSED(floatformat) // find out the decimal and the thousand separator QLocale loc=QLocale::c(); loc.setNumberOptions(QLocale::OmitGroupSeparator); //QChar dsep=loc.decimalPoint(); QFile f(filename); if (!f.open(QIODevice::WriteOnly|QIODevice::Text)) return; QTextStream txt(&f); txt.setLocale(loc); unsigned long long rows=getMaxRows(); // write DIF header txt< it(columns); size_t c=1; int i=0; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(i)) { txt< it(columns); c=1; int j=0; while (it.hasNext()) { it.next(); if (userColumns.isEmpty() || userColumns.contains(j)) { //qDebug()<datastore=datastore; reloadModel(); } JKQTPdatastoreModel::~JKQTPdatastoreModel() { } QVariant JKQTPdatastoreModel::data(const QModelIndex &index, int role) const { int row=index.row(); int column=index.column(); if (datastore) { if (role==Qt::DisplayRole || role==Qt::EditRole) { int col=datastore->getColumnIDs().value(column, -1); if (col>-1 && row>=0 && row<(int64_t)datastore->getColumn(col).getRows()) { return datastore->get(col, row); } } } return QVariant(); } Qt::ItemFlags JKQTPdatastoreModel::flags(const QModelIndex &/*index*/) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QVariant JKQTPdatastoreModel::headerData(int section, Qt::Orientation orientation, int role) const { if (datastore) { if (role==Qt::DisplayRole) { if (orientation==Qt::Horizontal) { if (section>=0 && section<(int64_t)datastore->getColumnCount()) { //qDebug()<<"columns: "<getColumnNames().size()<getColumnIDs().size()<<": "<getColumnNames(); return datastore->getColumnNames().value(section); } } else { return QString::number(section+1); } } } return QVariant(); } int JKQTPdatastoreModel::rowCount(const QModelIndex &/*parent*/) const { if (datastore) { return datastore->getMaxRows(); } return 0; } int JKQTPdatastoreModel::columnCount(const QModelIndex &/*parent*/) const { if (datastore) { return datastore->getColumnCount(); } return 0; } void JKQTPdatastoreModel::reloadModel() { #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) beginResetModel(); endResetModel(); #else reset(); #endif }