30 #include <QScopedPointer>
58 ImportPdsTable::ImportPdsTable() {
61 m_tableName =
"TABLE";
88 ImportPdsTable::ImportPdsTable(
const QString &pdsLabFile,
89 const QString &pdsTableFile,
90 const QString &pdsTableName) {
91 m_tableName = pdsTableName;
92 load(pdsLabFile, pdsTableFile, pdsTableName);
99 ImportPdsTable::~ImportPdsTable() {
104 QString ImportPdsTable::name()
const {
105 return (m_tableName);
113 void ImportPdsTable::setName(
const QString &name) {
147 void ImportPdsTable::load(
const QString &pdsLabFile,
148 const QString &pdsTableFile,
149 const QString &pdsTableName) {
153 loadLabel(pdsLabFile, tempTblFile, pdsTableName);
154 if (!pdsTableFile.isEmpty()) tempTblFile = pdsTableFile;
160 int tableStartRecord =
toInt(tableFile.baseName());
161 tempTblFile = pdsLabFile;
162 m_pdsTableStart = tableStartRecord;
167 if (!tableFile.fileExists()) {
170 + tableFile.name().toLower());
171 if (!tableFileLowercase.fileExists()) {
172 IString msg =
"Unable to import PDS table. Neither of the following "
173 "possible table files were found: ["
174 + tableFile.expanded() +
"] or ["
175 + tableFileLowercase.expanded() +
"]";
178 tableFile = tableFileLowercase.expanded();
179 tempTblFile = tableFile.expanded();
183 if (m_pdsTableType ==
"ASCII") {
184 loadTable(tempTblFile);
186 m_pdsTableFile = tempTblFile;
201 bool ImportPdsTable::hasColumn(
const QString &colName)
const {
202 return (findColumn(colName) != 0);
226 QString ImportPdsTable::getColumnName(
const unsigned int &index,
227 const bool &formatted)
const {
228 if ((
int) index >= columns() - 1) {
229 QString msg =
"Unable to import the binary PDS table [" + m_tableName
230 +
"] into Isis. The requested column index ["
231 +
toString((
int) index) +
"] exceeds the last column index ["
235 QString name = m_coldesc[index].m_name;
236 if (formatted) name = getFormattedName(name);
257 QStringList ImportPdsTable::getColumnNames(
const bool &formatted)
const {
259 for (
int i = 0 ; i < columns() ; i++) {
260 QString name = m_coldesc[i].m_name;
261 if (formatted) name = getFormattedName(name);
262 colnames.push_back(name);
283 QString ImportPdsTable::getType(
const QString &colName)
const {
310 bool ImportPdsTable::setType(
const QString &colName,
311 const QString &dataType) {
316 return (column != 0);
333 Table ImportPdsTable::importTable(
const QString &isisTableName) {
336 Table table(isisTableName, record);
337 fillTable(table, m_coldesc, record);
341 QString msg =
"Unable to import the PDS table [" + m_tableName
342 +
"] from the PDS file [" + m_pdsTableFile +
"] into Isis.";
365 Table ImportPdsTable::importTable(
const QString &colnames,
366 const QString &isisTableName) {
367 return (importTable(colnames.split(
","), isisTableName));
389 const QString &isisTableName) {
391 for (
int i = 0 ; i < colnames.size() ; i++) {
392 const ColumnDescr *descr = findColumn(colnames[i]);
394 QString msg =
"Unable to import the PDS table [" + m_tableName
395 +
"] into Isis. The requested column name ["
396 + colnames[i] +
"] does not "
400 ctypes.push_back(*descr);
405 Table table(isisTableName, record);
406 fillTable(table, ctypes, record);
416 void ImportPdsTable::init() {
453 void ImportPdsTable::loadLabel(
const QString &pdsLabFile,
454 QString &pdsTableFile,
455 const QString &tblname) {
459 QString tableName = ( tblname.isEmpty() ) ? m_tableName : tblname;
461 QString msg =
"The PDS file " + pdsLabFile +
462 " does not have the required TABLE object, ["
463 + tableName +
"]. The PDS label file is probably invalid";
469 m_recordBytes = (int) tabObj.
findKeyword(
"RECORD_BYTES");
472 m_recordBytes = (int) label.
findKeyword(
"RECORD_BYTES");
475 QString trueTableName;
478 trueTableName = tableName;
480 + label[
"^" + tableName][0];
482 else if (tabObj.
objects() == 1) {
484 tableDetails = &tabObj.
object(0);
486 + tabObj[
"^" + trueTableName][0];
489 int ncols = (int) tableDetails->
findKeyword(
"COLUMNS");
490 m_pdsTableType = QString(tableDetails->
findKeyword(
"INTERCHANGE_FORMAT"));
491 if (m_pdsTableType !=
"ASCII" && m_pdsTableType.toUpper() !=
"BINARY") {
492 QString msg =
"Unable to import the PDS table [" + tableName
493 +
"] from the PDS file ["
494 + pdsTableFile +
"] into Isis. "
495 "The PDS INTERCHANGE_FORMAT [" + m_pdsTableType
496 +
"] is not supported. Valid values are ASCII or BINARY.";
499 m_rowBytes = tableDetails->
findKeyword(
"ROW_BYTES");
504 while (colobj != tableDetails->
endObject()) {
505 if (colobj->isNamed(
"COLUMN")) {
506 m_coldesc.push_back(getColumnDescription(*colobj, icol));
513 if (ncols != columns()) {
515 msg <<
"Number of columns in the COLUMNS label keyword (" << ncols
516 <<
") does not match number of COLUMN objects found ("
518 cout << msg.str() << endl;
540 void ImportPdsTable::loadTable(
const QString &pdsTableFile) {
544 QString tempTblFile(pdsTableFile);
549 while (tfile.
GetLine(tline,
false)) {
550 if (irow >= m_trows)
break;
552 (void) processRow(irow, tline);
578 ImportPdsTable::getColumnDescription(
PvlObject &colobj,
int nth)
const {
580 cd.
m_name = colobj[
"NAME"][0];
583 if (m_pdsTableType ==
"ASCII") {
584 cd.
m_dataType = getGenericType(colobj[
"DATA_TYPE"][0]).toUpper();
587 cd.
m_dataType = colobj[
"DATA_TYPE"][0].toUpper();
601 cd.
m_items = (int) colobj[
"ITEMS"];
623 if ( (nth >= columns()) || ( nth < 0) ) {
624 QString mess =
"Index (" + QString::number(nth) +
625 ") into Columns invalid (max: " + QString::number(columns()) +
")";
630 return (m_coldesc[nth]);
649 QString cName = getFormattedName(colName);
650 ColumnTypes::iterator col = m_coldesc.begin();
651 while (col != m_coldesc.end()) {
652 QString c = getFormattedName(col->m_name);
653 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
675 QString cName = getFormattedName(colName);
676 ColumnTypes::const_iterator col = m_coldesc.begin();
677 while (col != m_coldesc.end()) {
678 QString c = getFormattedName(col->m_name);
679 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
696 QString ImportPdsTable::getColumnValue(
const QString &tline,
698 const QString &delimiter)
const {
720 const QString &delimiter)
const {
723 QString value = getColumnValue(tline, cdesc, delimiter);
729 if ( delimiter.isEmpty() )
return (
QStringList(value));
731 return ( value.split(delimiter, QString::SkipEmptyParts) );
737 for (
int i = 0 ; i < cdesc.
m_items ; i++) {
738 fields.push_back(value.mid(pos, cdesc.
m_itemBytes));
765 QString ImportPdsTable::getFormattedName(
const QString &colname)
const {
766 QString cname = QString(colname).replace(QRegExp(
"[(),]"),
" ").simplified();
768 bool uppercase =
true;
770 for (
int i = 0 ; i < cname.size() ; i++) {
772 oString.push_back(cname[i].toUpper());
775 else if ( (cname[i] ==
' ') || (cname[i] ==
'_') ) {
779 oString.push_back(cname[i].toLower());
804 QString ImportPdsTable::getGenericType(
const QString &ttype)
const {
805 return ttype.split(
"_").last();
828 QString name = getFormattedName(cdesc.
m_name);
829 if (m_pdsTableType ==
"ASCII") {
830 if ( dtype ==
"INTEGER" ) {
831 return (
TableField(name, TableField::Integer));
833 else if ( ((dtype ==
"DOUBLE")
835 || (dtype ==
"FLOAT")) ) {
836 return (
TableField(name, TableField::Double));
843 return makeFieldFromBinaryTable(cdesc);
864 for (
int i = 0 ; i < ctypes.size() ; i++) {
895 data.
Trim(
" \t\r\n");
899 data.
Trim(
" \t\r\n");
903 QString str(tfield.
size(),
' ');
904 str.insert(0, data.
Trim(
" \t\r\n").
ToQt());
909 QString msg =
"Conversion failure of column " + cdesc.
m_name;
934 for (
int i = 0 ; i < ctypes.size() ; i++) {
935 extract(cols, ctypes[i], record[i]);
956 void ImportPdsTable::fillTable(
Table &table,
959 if (m_pdsTableType ==
"ASCII") {
960 for (
int i = 0 ; i < m_rows.size() ; i++) {
962 table += extract(m_rows[i], cols, record);
965 QString msg =
"Failed to convert data in row [" +
toString((
int) i) +
"]";
972 QString tempTblFile = m_pdsTableFile;
973 ifstream pdsFileStream(tempTblFile.toLatin1().data(), ifstream::binary);
975 if (!pdsFileStream) {
976 IString msg =
"Unable to open file containing PDS table ["
977 + tempTblFile +
"].";
982 QScopedPointer<char, QScopedPointerArrayDeleter<char> > rowBuffer(
new char[m_recordBytes]);
983 for (
int i = 1; i < m_pdsTableStart; i++) {
984 pdsFileStream.read(rowBuffer.data(), m_recordBytes);
987 for (
int rowIndex = 0; rowIndex < m_trows; rowIndex++) {
988 pdsFileStream.read(rowBuffer.data(), m_recordBytes);
989 TableRecord rec = extractBinary(rowBuffer.data(), record);
1005 int ImportPdsTable::columns()
const {
1006 return (m_coldesc.size());
1017 int ImportPdsTable::rows()
const {
1018 return (m_rows.size());
1039 for (
int colIndex = 0; colIndex < columns(); colIndex++) {
1040 QString columnName = m_coldesc[colIndex].m_name;
1041 for (
int fieldIndex = 0 ; fieldIndex < record.
Fields() ; fieldIndex++) {
1042 QString fieldName = record[fieldIndex].name();
1043 if (fieldName == columnName) {
1044 int startByte = m_coldesc[colIndex].m_startByte;
1045 int numBytes = m_coldesc[colIndex].m_numBytes;
1047 if (record[fieldIndex].isInteger()) {
1049 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1051 int fieldValue = endianSwap.
Int(&columnValue);
1052 record[fieldIndex] = fieldValue;
1055 else if (record[fieldIndex].isDouble()) {
1058 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1059 double fieldValue = endianSwap.
Double(&columnValue);
1060 record[fieldIndex] = fieldValue;
1063 else if (record[fieldIndex].isReal()) {
1066 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1067 float fieldValue = endianSwap.
Float(&columnValue);
1068 record[fieldIndex] = fieldValue;
1071 else if (record[fieldIndex].isText()) {
1072 QString fieldValue(numBytes,
'\0');
1073 for (
int byte = 0; byte < numBytes; byte++) {
1074 fieldValue[byte] = rowBuffer[startByte + byte];
1076 record[fieldIndex] = fieldValue;
1111 QString name = cdesc.
m_name;
1112 if (dataType ==
"MSB_INTEGER" || dataType ==
"INTEGER"
1113 || dataType ==
"SUN_INTEGER" || dataType ==
"MAC_INTEGER") {
1115 QString msg =
"Only 4 byte integer values are supported in Isis. "
1116 "PDS Column [" + cdesc.
m_name
1117 +
"] has an integer DATA_TYPE with [BYTES = "
1121 setPdsByteOrder(
"MSB");
1122 return TableField(name, TableField::Integer);
1124 else if (dataType ==
"LSB_INTEGER" || dataType ==
"VAX_INTEGER"
1125 || dataType ==
"PC_INTEGER" ) {
1127 QString msg =
"Only 4 byte integer values are supported in Isis. "
1128 "PDS Column [" + cdesc.
m_name
1129 +
"] has an integer DATA_TYPE with [BYTES = "
1133 setPdsByteOrder(
"LSB");
1134 return TableField(name, TableField::Integer);
1136 else if (dataType ==
"FLOAT"
1137 || dataType ==
"REAL"
1138 || dataType ==
"SUN_REAL"
1139 || dataType ==
"MAC_REAL"
1140 || dataType ==
"IEEE_REAL" ) {
1141 setPdsByteOrder(
"MSB");
1149 IString msg =
"Only 4 byte or 8 byte real values are supported in Isis. "
1150 "PDS Column [" + cdesc.
m_name
1151 +
"] has a real DATA_TYPE with [BYTES = "
1156 else if (dataType ==
"PC_REAL") {
1157 setPdsByteOrder(
"LSB");
1165 QString msg =
"Only 4 byte or 8 byte real values are supported in Isis. "
1166 "PDS Column [" + cdesc.
m_name
1167 +
"] has a real DATA_TYPE with [BYTES = "
1172 else if (dataType.contains(
"CHARACTER")
1173 || dataType.contains(
"ASCII")
1174 || dataType ==
"DATE" || dataType ==
"TIME" ) {
1180 +
"] has an unsupported DATA_TYPE ["
1197 void ImportPdsTable::setPdsByteOrder(QString byteOrder) {
1198 if (!m_byteOrder.isEmpty() && m_byteOrder != byteOrder) {
1199 QString msg =
"Unable to import the binary PDS table [" + m_tableName
1200 +
"]. The column DATA_TYPE values indicate differing byte "
1204 m_byteOrder = byteOrder;
1218 bool ImportPdsTable::processRow(
const int &row,
const QString &rowdata) {
1220 for (
int i = 0 ; i < columns() ; i++) {
1221 cols.push_back(getColumnValue(rowdata, m_coldesc[i]));
1223 m_rows.append(cols);
PvlObject & object(const int index)
Return the object at the specified index.
int m_colnum
Column number.
float Float(void *buf)
Swaps a floating point value.
void clear()
Clears all values and units for this PvlKeyword object.
PvlObjectIterator endObject()
Returns the index of the ending object.
QString ToQt() const
Retuns the object string as a QString.
File name manipulation and expansion.
double ToDouble() const
Returns the floating point value the IString represents.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
int m_itemBytes
Number bytes per item.
int toInt(const QString &string)
Global function to convert from a string to an integer.
QString m_name
Name of column.
int ToInteger() const
Returns the object string as an integer.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
bool hasKeyword(const QString &kname, FindOptions opts) const
See if a keyword is in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within ...
QList< PvlObject >::iterator PvlObjectIterator
The counter for objects.
int Fields() const
Returns the number of fields that are currently in the record.
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
#define _FILEINFO_
Macro for the filename and line number.
double Double(void *buf)
Swaps a double precision value.
bool isInteger() const
Determines whether the field type is Integer.
int objects() const
Returns the number of objects.
bool isDouble() const
Determines whether the field type is Double.
bool GetLine(QString &line, const bool skipComments=true)
Gets next line from file.
Container for cube-like labels.
int m_items
Number of items in column.
Provides access to sequential ASCII stream I/O.
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
Class for storing Table blobs information.
int size() const
Returns the number of values stored for the field at each record.
int m_startByte
Starting byte of data.
Adds specific functionality to C++ strings.
Class for storing an Isis::Table's field information.
int m_numBytes
Number bytes in column.
QString m_dataType
PDS table DATA_TYPE of column.
Contains Pvl Groups and Pvl Objects.
PvlObjectIterator beginObject()
Returns the index of the beginning object.
QString path() const
Returns the path.
QString name() const
Returns the container name.
IString Trim(const std::string &chars)
Removes characters from the beginning and end of the IString.
int Int(void *buf)
Swaps a 4 byte integer value.