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;
161 tempTblFile = pdsLabFile;
162 m_pdsTableStart = tableStartRecord;
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: [" 175 + tableFileLowercase.expanded() +
"]";
178 tableFile = tableFileLowercase.
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";
470 m_recordBytes = (int) tabObj.
findKeyword(
"RECORD_BYTES");
475 m_recordBytes = (int) tabObj.
findKeyword(
"ROW_BYTES") +
481 m_recordBytes = (int) label.
findKeyword(
"RECORD_BYTES");
484 QString trueTableName;
487 trueTableName = tableName;
489 + label[
"^" + tableName][0];
491 else if (tabObj.
objects() == 1) {
493 tableDetails = &tabObj.
object(0);
495 + tabObj[
"^" + trueTableName][0];
498 int ncols = (int) tableDetails->
findKeyword(
"COLUMNS");
499 m_pdsTableType = QString(tableDetails->
findKeyword(
"INTERCHANGE_FORMAT"));
500 if (m_pdsTableType !=
"ASCII" && m_pdsTableType.toUpper() !=
"BINARY") {
501 QString msg =
"Unable to import the PDS table [" + tableName
502 +
"] from the PDS file [" 503 + pdsTableFile +
"] into Isis. " 504 "The PDS INTERCHANGE_FORMAT [" + m_pdsTableType
505 +
"] is not supported. Valid values are ASCII or BINARY.";
508 m_rowBytes = tableDetails->
findKeyword(
"ROW_BYTES");
513 while (colobj != tableDetails->
endObject()) {
514 if (colobj->isNamed(
"COLUMN")) {
515 m_coldesc.push_back(getColumnDescription(*colobj, icol));
522 if (ncols != columns()) {
524 msg <<
"Number of columns in the COLUMNS label keyword (" << ncols
525 <<
") does not match number of COLUMN objects found (" 527 cout << msg.str() << endl;
549 void ImportPdsTable::loadTable(
const QString &pdsTableFile) {
553 QString tempTblFile(pdsTableFile);
558 while (tfile.
GetLine(tline,
false)) {
559 if (irow >= m_trows)
break;
561 (void) processRow(irow, tline);
587 ImportPdsTable::getColumnDescription(
PvlObject &colobj,
int nth)
const {
589 cd.
m_name = colobj[
"NAME"][0];
592 if (m_pdsTableType ==
"ASCII") {
593 cd.
m_dataType = getGenericType(colobj[
"DATA_TYPE"][0]).toUpper();
596 cd.
m_dataType = colobj[
"DATA_TYPE"][0].toUpper();
610 cd.
m_items = (int) colobj[
"ITEMS"];
632 if ( (nth >= columns()) || ( nth < 0) ) {
633 QString mess =
"Index (" + QString::number(nth) +
634 ") into Columns invalid (max: " + QString::number(columns()) +
")";
639 return (m_coldesc[nth]);
658 QString cName = getFormattedName(colName);
659 ColumnTypes::iterator col = m_coldesc.begin();
660 while (col != m_coldesc.end()) {
661 QString c = getFormattedName(col->m_name);
662 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
684 QString cName = getFormattedName(colName);
685 ColumnTypes::const_iterator col = m_coldesc.begin();
686 while (col != m_coldesc.end()) {
687 QString c = getFormattedName(col->m_name);
688 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
705 QString ImportPdsTable::getColumnValue(
const QString &tline,
707 const QString &delimiter)
const {
729 const QString &delimiter)
const {
732 QString value = getColumnValue(tline, cdesc, delimiter);
738 if ( delimiter.isEmpty() )
return (
QStringList(value));
740 return ( value.split(delimiter, QString::SkipEmptyParts) );
746 for (
int i = 0 ; i < cdesc.
m_items ; i++) {
747 fields.push_back(value.mid(pos, cdesc.
m_itemBytes));
774 QString ImportPdsTable::getFormattedName(
const QString &colname)
const {
775 QString cname = QString(colname).replace(QRegExp(
"[(),]"),
" ").simplified();
777 bool uppercase =
true;
779 for (
int i = 0 ; i < cname.size() ; i++) {
781 oString.push_back(cname[i].toUpper());
784 else if ( (cname[i] ==
' ') || (cname[i] ==
'_') ) {
788 oString.push_back(cname[i].toLower());
813 QString ImportPdsTable::getGenericType(
const QString &ttype)
const {
814 return ttype.split(
"_").last();
837 QString name = getFormattedName(cdesc.
m_name);
838 if (m_pdsTableType ==
"ASCII") {
839 if ( dtype ==
"INTEGER" ) {
840 return (
TableField(name, TableField::Integer));
842 else if ( ((dtype ==
"DOUBLE")
844 || (dtype ==
"FLOAT")) ) {
845 return (
TableField(name, TableField::Double));
852 return makeFieldFromBinaryTable(cdesc);
873 for (
int i = 0 ; i < ctypes.size() ; i++) {
904 data.
Trim(
" \t\r\n");
908 data.
Trim(
" \t\r\n");
912 QString str(tfield.
size(),
' ');
913 str.insert(0, data.
Trim(
" \t\r\n").
ToQt());
918 QString msg =
"Conversion failure of column " + cdesc.
m_name;
943 for (
int i = 0 ; i < ctypes.size() ; i++) {
944 extract(cols, ctypes[i], record[i]);
965 void ImportPdsTable::fillTable(
Table &table,
968 if (m_pdsTableType ==
"ASCII") {
969 for (
int i = 0 ; i < m_rows.size() ; i++) {
971 table += extract(m_rows[i], cols, record);
974 QString msg =
"Failed to convert data in row [" +
toString((
int) i) +
"]";
981 QString tempTblFile = m_pdsTableFile;
982 ifstream pdsFileStream(tempTblFile.toLatin1().data(), ifstream::binary);
984 if (!pdsFileStream) {
985 IString msg =
"Unable to open file containing PDS table [" 986 + tempTblFile +
"].";
991 QScopedPointer<char, QScopedPointerArrayDeleter<char> > rowBuffer(
new char[m_recordBytes]);
992 for (
int i = 1; i < m_pdsTableStart; i++) {
993 pdsFileStream.read(rowBuffer.data(), m_recordBytes);
996 for (
int rowIndex = 0; rowIndex < m_trows; rowIndex++) {
997 pdsFileStream.read(rowBuffer.data(), m_recordBytes);
998 TableRecord rec = extractBinary(rowBuffer.data(), record);
1014 int ImportPdsTable::columns()
const {
1015 return (m_coldesc.size());
1026 int ImportPdsTable::rows()
const {
1027 return (m_rows.size());
1048 for (
int colIndex = 0; colIndex < columns(); colIndex++) {
1049 QString columnName = m_coldesc[colIndex].m_name;
1050 for (
int fieldIndex = 0 ; fieldIndex < record.
Fields() ; fieldIndex++) {
1051 QString fieldName = record[fieldIndex].name();
1052 if (fieldName == columnName) {
1053 int startByte = m_coldesc[colIndex].m_startByte;
1054 int numBytes = m_coldesc[colIndex].m_numBytes;
1056 if (record[fieldIndex].isInteger()) {
1058 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1060 int fieldValue = endianSwap.
Int(&columnValue);
1061 record[fieldIndex] = fieldValue;
1064 else if (record[fieldIndex].isDouble()) {
1067 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1068 double fieldValue = endianSwap.
Double(&columnValue);
1069 record[fieldIndex] = fieldValue;
1072 else if (record[fieldIndex].isReal()) {
1075 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1076 float fieldValue = endianSwap.
Float(&columnValue);
1077 record[fieldIndex] = fieldValue;
1080 else if (record[fieldIndex].isText()) {
1081 QString fieldValue(numBytes,
'\0');
1082 for (
int byte = 0; byte < numBytes; byte++) {
1083 fieldValue[byte] = rowBuffer[startByte + byte];
1085 record[fieldIndex] = fieldValue;
1120 QString name = cdesc.
m_name;
1121 if (dataType ==
"MSB_INTEGER" || dataType ==
"INTEGER" 1122 || dataType ==
"SUN_INTEGER" || dataType ==
"MAC_INTEGER") {
1124 QString msg =
"Only 4 byte integer values are supported in Isis. " 1125 "PDS Column [" + cdesc.
m_name 1126 +
"] has an integer DATA_TYPE with [BYTES = " 1130 setPdsByteOrder(
"MSB");
1131 return TableField(name, TableField::Integer);
1133 else if (dataType ==
"LSB_INTEGER" || dataType ==
"VAX_INTEGER" 1134 || dataType ==
"PC_INTEGER" ) {
1136 QString msg =
"Only 4 byte integer values are supported in Isis. " 1137 "PDS Column [" + cdesc.
m_name 1138 +
"] has an integer DATA_TYPE with [BYTES = " 1142 setPdsByteOrder(
"LSB");
1143 return TableField(name, TableField::Integer);
1145 else if (dataType ==
"FLOAT" 1146 || dataType ==
"REAL" 1147 || dataType ==
"SUN_REAL" 1148 || dataType ==
"MAC_REAL" 1149 || dataType ==
"IEEE_REAL" ) {
1150 setPdsByteOrder(
"MSB");
1158 IString msg =
"Only 4 byte or 8 byte real values are supported in Isis. " 1159 "PDS Column [" + cdesc.
m_name 1160 +
"] has a real DATA_TYPE with [BYTES = " 1165 else if (dataType ==
"PC_REAL") {
1166 setPdsByteOrder(
"LSB");
1174 QString msg =
"Only 4 byte or 8 byte real values are supported in Isis. " 1175 "PDS Column [" + cdesc.
m_name 1176 +
"] has a real DATA_TYPE with [BYTES = " 1181 else if (dataType.contains(
"CHARACTER")
1182 || dataType.contains(
"ASCII")
1183 || dataType ==
"DATE" || dataType ==
"TIME" ) {
1189 +
"] has an unsupported DATA_TYPE [" 1206 void ImportPdsTable::setPdsByteOrder(QString byteOrder) {
1207 if (!m_byteOrder.isEmpty() && m_byteOrder != byteOrder) {
1208 QString msg =
"Unable to import the binary PDS table [" + m_tableName
1209 +
"]. The column DATA_TYPE values indicate differing byte " 1213 m_byteOrder = byteOrder;
1227 bool ImportPdsTable::processRow(
const int &row,
const QString &rowdata) {
1229 for (
int i = 0 ; i < columns() ; i++) {
1230 cols.push_back(getColumnValue(rowdata, m_coldesc[i]));
1232 m_rows.append(cols);
PvlObject & object(const int index)
Return the object at the specified index.
QString path() const
Returns the path of the file name.
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.
File name manipulation and expansion.
int objects() const
Returns the number of objects.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
double ToDouble() const
Returns the floating point value the IString represents.
int m_itemBytes
Number bytes per item.
int toInt(const QString &string)
Global function to convert from a string to an integer.
Namespace for the standard library.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
QString m_name
Name of column.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
int ToInteger() const
Returns the object string as an integer.
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 ...
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
QString name() const
Returns the container name.
QList< PvlObject >::iterator PvlObjectIterator
The counter for objects.
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
bool isInteger() const
Determines whether the field type is Integer.
#define _FILEINFO_
Macro for the filename and line number.
double Double(void *buf)
Swaps a double precision value.
QString ToQt() const
Retuns the object string as a QString.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
bool GetLine(QString &line, const bool skipComments=true)
Gets next line from file.
int size() const
Returns the number of values stored for the field at each record.
Container for cube-like labels.
int m_items
Number of items in column.
Provides access to sequential ASCII stream I/O.
QString baseName() const
Returns the name of the file without the path and without extensions.
Class for storing Table blobs information.
int m_startByte
Starting byte of data.
Adds specific functionality to C++ strings.
Namespace for ISIS/Bullet specific routines.
int Fields() const
Returns the number of fields that are currently in the record.
Class for storing an Isis::Table's field information.
int m_numBytes
Number bytes in column.
bool isDouble() const
Determines whether the field type is Double.
QString m_dataType
PDS table DATA_TYPE of column.
Contains Pvl Groups and Pvl Objects.
PvlObjectIterator beginObject()
Returns the index of the beginning object.
bool fileExists() const
Returns true if the file exists; false otherwise.
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.