diff --git a/isis/notebooks/crop_cassiniIss.ipynb b/isis/notebooks/crop_cassiniIss.ipynb new file mode 100644 index 0000000000..36849f925b --- /dev/null +++ b/isis/notebooks/crop_cassiniIss.ipynb @@ -0,0 +1,385 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "b6c4ed37", + "metadata": {}, + "outputs": [], + "source": [ + "import pvl\n", + "import struct\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import datetime\n", + "import os\n", + "import binascii" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e45c31fe", + "metadata": {}, + "outputs": [], + "source": [ + "label_file = \"/Users/acpaquette/repos/ISIS3/build/N1472853667_1.LBL\"" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "4eccdc86", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "PVLModule([\n", + " ('PDS_VERSION_ID', 'PDS3')\n", + " ('RECORD_TYPE', 'FIXED_LENGTH')\n", + " ('RECORD_BYTES', 1048)\n", + " ('FILE_RECORDS', 1028)\n", + " ('^IMAGE_HEADER', ['N1472853667_1.IMG', 1])\n", + " ('^TELEMETRY_TABLE', ['N1472853667_1.IMG', 4])\n", + " ('^LINE_PREFIX_TABLE', ['N1472853667_1.IMG', 5])\n", + " ('^IMAGE', ['N1472853667_1.IMG', 5])\n", + " ('ANTIBLOOMING_STATE_FLAG', 'ON')\n", + " ('BIAS_STRIP_MEAN', 17.25049)\n", + " ('CALIBRATION_LAMP_STATE_FLAG', 'N/A')\n", + " ('COMMAND_FILE_NAME', 'trigger_6510_6.ioi')\n", + " ('COMMAND_SEQUENCE_NUMBER', 6510)\n", + " ('DARK_STRIP_MEAN', 0.0)\n", + " ('DATA_CONVERSION_TYPE', 'TABLE')\n", + " ('DATA_SET_ID', 'CO-S-ISSNA/ISSWA-2-EDR-V1.0')\n", + " ('DELAYED_READOUT_FLAG', 'NO')\n", + " ('DESCRIPTION', 'Incomplete product finalized due to truncated lines.')\n", + " ('DETECTOR_TEMPERATURE', Quantity(value=-89.243546, units='DEGC'))\n", + " ('EARTH_RECEIVED_START_TIME',\n", + " datetime.datetime(2004, 9, 3, 9, 54, 37, 232000, tzinfo=datetime.timezone.utc))\n", + " ('EARTH_RECEIVED_STOP_TIME',\n", + " datetime.datetime(2004, 9, 3, 9, 57, 12, 966000, tzinfo=datetime.timezone.utc))\n", + " ('ELECTRONICS_BIAS', 112)\n", + " ('EXPECTED_MAXIMUM', [0.756496, 1.9487])\n", + " ('EXPECTED_PACKETS', 519)\n", + " ('EXPOSURE_DURATION', 220000.0)\n", + " ('FILTER_NAME', ['CL1', 'CL2'])\n", + " ('FILTER_TEMPERATURE', -0.468354)\n", + " ('FLIGHT_SOFTWARE_VERSION_ID', '1.3')\n", + " ('GAIN_MODE_ID', '12 ELECTRONS PER DN')\n", + " ('IMAGE_MID_TIME',\n", + " datetime.datetime(2004, 9, 2, 21, 34, 26, 410000, tzinfo=datetime.timezone.utc))\n", + " ('IMAGE_NUMBER', '1472853667')\n", + " ('IMAGE_OBSERVATION_TYPE', frozenset({'SCIENCE'}))\n", + " ('IMAGE_TIME',\n", + " datetime.datetime(2004, 9, 2, 21, 36, 16, 410000, tzinfo=datetime.timezone.utc))\n", + " ('INSTRUMENT_DATA_RATE', 182.783997)\n", + " ('INSTRUMENT_HOST_NAME', 'CASSINI ORBITER')\n", + " ('INSTRUMENT_ID', 'ISSNA')\n", + " ('INSTRUMENT_MODE_ID', 'FULL')\n", + " ('INSTRUMENT_NAME', 'IMAGING SCIENCE SUBSYSTEM NARROW ANGLE')\n", + " ('INST_CMPRS_PARAM', ['N/A', 'N/A', 'N/A', 'N/A'])\n", + " ('INST_CMPRS_RATE', [3.6, 4.333807])\n", + " ('INST_CMPRS_RATIO', 1.845952)\n", + " ('INST_CMPRS_TYPE', 'LOSSLESS')\n", + " ('LIGHT_FLOOD_STATE_FLAG', 'ON')\n", + " ('METHOD_DESC', 'ISSPT2.5.3;Saturn-Ering;ISS_00ARI_DIFFUSRNG003_PRIME_4')\n", + " ('MISSING_LINES', 511)\n", + " ('MISSING_PACKET_FLAG', 'NO')\n", + " ('MISSION_NAME', 'CASSINI-HUYGENS')\n", + " ('MISSION_PHASE_NAME', 'TOUR PRE-HUYGENS')\n", + " ('OBSERVATION_ID', 'ISS_00ARI_DIFFUSRNG003_PRIME')\n", + " ('OPTICS_TEMPERATURE', [0.712693, 1.905708])\n", + " ('ORDER_NUMBER', 2)\n", + " ('PARALLEL_CLOCK_VOLTAGE_INDEX', 9)\n", + " ('PREPARE_CYCLE_INDEX', 12)\n", + " ('PRODUCT_CREATION_TIME',\n", + " datetime.datetime(2004, 9, 3, 10, 39, 14, tzinfo=datetime.timezone.utc))\n", + " ('PRODUCT_ID', '1_N1472853667.118')\n", + " ('PRODUCT_VERSION_TYPE', 'FINAL')\n", + " ('READOUT_CYCLE_INDEX', 10)\n", + " ('RECEIVED_PACKETS', 576)\n", + " ('SENSOR_HEAD_ELEC_TEMPERATURE', 1.633024)\n", + " ('SEQUENCE_ID', 'S03')\n", + " ('SEQUENCE_NUMBER', 2)\n", + " ('SEQUENCE_TITLE', 'ISS_00ARI_DIFFUSRNG003_PRIME')\n", + " ('SHUTTER_MODE_ID', 'NACONLY')\n", + " ('SHUTTER_STATE_ID', 'ENABLED')\n", + " ('SOFTWARE_VERSION_ID', 'ISS 9.00 02-05-2004')\n", + " ('SPACECRAFT_CLOCK_CNT_PARTITION', 1)\n", + " ('SPACECRAFT_CLOCK_START_COUNT', '1472853447.118')\n", + " ('SPACECRAFT_CLOCK_STOP_COUNT', '1472853667.118')\n", + " ('START_TIME',\n", + " datetime.datetime(2004, 9, 2, 21, 32, 36, 410000, tzinfo=datetime.timezone.utc))\n", + " ('STOP_TIME',\n", + " datetime.datetime(2004, 9, 2, 21, 36, 16, 410000, tzinfo=datetime.timezone.utc))\n", + " ('TARGET_DESC', 'Saturn-Ering')\n", + " ('TARGET_LIST', 'N/A')\n", + " ('TARGET_NAME', 'SATURN')\n", + " ('TELEMETRY_FORMAT_ID', 'UNK')\n", + " ('VALID_MAXIMUM', [9896, 4095])\n", + " ('IMAGE_HEADER',\n", + " {'BYTES': 3144,\n", + " 'HEADER_TYPE': 'VICAR2',\n", + " 'INTERCHANGE_FORMAT': 'ASCII',\n", + " 'RECORDS': 1,\n", + " '^DESCRIPTION': 'VICAR2.TXT'})\n", + " ('TELEMETRY_TABLE',\n", + " {'COLUMN': {'BYTES': 987,\n", + " 'DATA_TYPE': 'MSB_UNSIGNED_INTEGER',\n", + " 'NAME': 'NULL_PADDING',\n", + " 'START_BYTE': 61},\n", + " 'COLUMNS': 2,\n", + " 'INTERCHANGE_FORMAT': 'BINARY',\n", + " 'ROWS': 1,\n", + " 'ROW_BYTES': 1048,\n", + " '^STRUCTURE': 'TLMTAB.FMT'})\n", + " ('LINE_PREFIX_TABLE',\n", + " {'COLUMNS': 7,\n", + " 'INTERCHANGE_FORMAT': 'BINARY',\n", + " 'ROWS': 1024,\n", + " 'ROW_BYTES': 24,\n", + " 'ROW_SUFFIX_BYTES': 1024,\n", + " '^LINE_PREFIX_STRUCTURE': 'PREFIX2.FMT'})\n", + " ('IMAGE',\n", + " {'LINES': 1024,\n", + " 'LINE_PREFIX_BYTES': 24,\n", + " 'LINE_SAMPLES': 1024,\n", + " 'SAMPLE_BITS': 8,\n", + " 'SAMPLE_TYPE': 'SUN_INTEGER'})\n", + "])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pvl_label = pvl.load(label_file)\n", + "img_file = os.path.join(os.path.split(label_file)[0], pvl_label[\"^IMAGE\"][0])\n", + "pvl_label" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "616e7622", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "with open(img_file, 'rb') as fp:\n", + " byte_position = ((pvl_label[\"^IMAGE\"][1] - 1) * pvl_label[\"RECORD_BYTES\"])\n", + " b_original_header = fp.read(byte_position)\n", + " b_image_data = fp.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "10f0680b", + "metadata": {}, + "outputs": [], + "source": [ + "lut_list = [1, 3, 5, 7, 9, 11, 14, 16, 19, 22, 25, 28, 31, 35, 38, 42, 46, 49, 53, 57,\n", + "61, 65, 70, 74, 79, 83, 88, 93, 98, 103, 108, 113, 119, 125, 130, 136, 142,\n", + "148, 154, 160, 166, 173, 179, 186, 193, 199, 206, 213, 221, 228, 236, 243,\n", + "251, 259, 267, 275, 283, 291, 299, 307, 316, 324, 333, 342, 351, 360, 369,\n", + "379, 388, 398, 407, 417, 427, 437, 447, 457, 467, 478, 488, 499, 509, 520,\n", + "531, 542, 554, 565, 576, 588, 600, 611, 623, 635, 647, 659, 672, 684, 697,\n", + "709, 722, 735, 747, 761, 774, 787, 801, 814, 828, 842, 856, 870, 884, 898,\n", + "912, 926, 941, 955, 970, 985, 1000, 1015, 1030, 1045, 1061, 1076, 1092, 1108,\n", + "1124, 1140, 1156, 1172, 1188, 1204, 1221, 1237, 1254, 1271, 1288, 1305, 1322,\n", + "1339, 1357, 1374, 1392, 1410, 1428, 1446, 1464, 1482, 1500, 1518, 1537, 1555,\n", + "1574, 1593, 1612, 1631, 1650, 1669, 1689, 1708, 1728, 1748, 1768, 1788, 1808,\n", + "1828, 1848, 1868, 1889, 1909, 1930, 1951, 1971, 1993, 2014, 2035, 2057, 2078,\n", + "2100, 2121, 2143, 2165, 2187, 2209, 2232, 2254, 2276, 2299, 2322, 2344, 2367,\n", + "2390, 2413, 2437, 2460, 2484, 2507, 2531, 2555, 2579, 2603, 2627, 2651, 2676,\n", + "2700, 2725, 2749, 2774, 2799, 2824, 2849, 2874, 2900, 2925, 2951, 2977, 3003,\n", + "3029, 3055, 3081, 3107, 3133, 3160, 3186, 3213, 3239, 3266, 3293, 3321, 3348,\n", + "3375, 3403, 3430, 3458, 3486, 3514, 3542, 3570, 3598, 3627, 3655, 3684, 3712,\n", + "3741, 3770, 3799, 3828, 3857, 3887, 3916, 3946, 3976, 4005, 4035, 4065, 4095]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "4c26e15b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1048\n" + ] + } + ], + "source": [ + "sampling = (pvl_label['IMAGE']['SAMPLE_BITS']//8)\n", + "line_length = (pvl_label['IMAGE']['LINE_SAMPLES'] * sampling) + pvl_label['IMAGE']['LINE_PREFIX_BYTES']\n", + "print(line_length)\n", + "n_lines = 10\n", + "\n", + "\n", + "image_data = []\n", + "for j in range(n_lines):\n", + " start, stop = j*(line_length), (j+1)*(line_length)\n", + " if (sampling == 2):\n", + " dtype = np.int16\n", + " elif (sampling == 4):\n", + " dtype = np.float32\n", + " else:\n", + " dtype=np.int8\n", + " image_sample = np.frombuffer(b_image_data[start:stop], dtype=dtype, count=int((line_length)/sampling))\n", + " image_data.append(image_sample)\n", + "image_data = np.array(image_data)\n", + "\n", + "# Uncomment the following to compare with an ISIS cube\n", + "# if pvl_label[\"^IMAGE\"][0][0] == 'W':\n", + "# image_data = image_data.byteswap()\n", + "# else:\n", + "# image_data = np.reshape(np.array(list(map(lambda x: lut_list[x], image_data.flatten()))), (n_lines, line_length))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "3815ac94", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4620" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path_cropped_label = os.path.splitext(label_file)[0] + \".cropped.lbl\"\n", + "path_cropped_file = os.path.splitext(img_file)[0] + \".cropped.img\"\n", + "cropped_file = os.path.split(path_cropped_file)[1]\n", + "\n", + "new_label = pvl_label.copy()\n", + "new_label[\"IMAGE\"][\"LINES\"] = n_lines\n", + "new_label[\"^IMAGE\"][0] = cropped_file\n", + "new_label[\"^IMAGE_HEADER\"][0] = cropped_file\n", + "new_label[\"^TELEMETRY_TABLE\"][0] = cropped_file\n", + "new_label[\"^LINE_PREFIX_TABLE\"][0] = cropped_file\n", + "\n", + "with open(path_cropped_file, 'wb') as fp:\n", + " fp.write(b_original_header)\n", + " fp.write(image_data)\n", + " \n", + "pvl.dump(new_label, path_cropped_label)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28a7937d", + "metadata": {}, + "outputs": [], + "source": [ + "# Below lines used to compare the ISIS cube to the original label since qt 15.0 doesn't work on big sur\n", + "# as of 01/28/2022" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31bd22d4", + "metadata": {}, + "outputs": [], + "source": [ + "cube_file = \"/Path/to/test/output.cub\"\n", + "cube_label = pvl.load(cube_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3ea86dc", + "metadata": {}, + "outputs": [], + "source": [ + "with open(cube_file, 'rb') as fp:\n", + " fp.seek(cube_label[\"IsisCube\"][\"Core\"][\"StartByte\"] - 1)\n", + " b_cube_data = fp.read()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b175905", + "metadata": {}, + "outputs": [], + "source": [ + "line_length = cube_label[\"IsisCube\"][\"Core\"][\"Dimensions\"][\"Samples\"] * 2\n", + "n_lines = cube_label[\"IsisCube\"][\"Core\"][\"Dimensions\"][\"Lines\"]\n", + "\n", + "cube_data = []\n", + "for j in range(n_lines):\n", + " start, stop = j*(line_length), (j+1)*(line_length)\n", + " \n", + " cube_sample = np.frombuffer(b_cube_data[start:stop], dtype=np.int16, count=int(line_length/2))\n", + " cube_data.append(cube_sample)\n", + " \n", + "cube_data = np.array(cube_data)\n", + "# cube_data = np.where(cube_data == -32764, 4095, cube_data)\n", + "cube_data = np.where(cube_data < -32764, 1, cube_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8d8c29c", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "plt.figure(0, figsize=(20, 20))\n", + "plt.imshow(cube_data)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6db691e3", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/isis/src/cassini/apps/ciss2isis/ciss2isis.cpp b/isis/src/cassini/apps/ciss2isis/ciss2isis.cpp new file mode 100644 index 0000000000..61c4a8d75e --- /dev/null +++ b/isis/src/cassini/apps/ciss2isis/ciss2isis.cpp @@ -0,0 +1,449 @@ +#include "ciss2isis.h" +#include + +#include + +#include "CisscalFile.h" +#include "FileName.h" +#include "IException.h" +#include "IString.h" +#include "Preference.h" +#include "ProcessImportPds.h" +#include "ProcessByLine.h" +#include "Pvl.h" +#include "SpecialPixel.h" +#include "Stretch.h" +#include "Table.h" +#include "TextFile.h" + +using namespace std; + +namespace Isis{ + // Function prototypes + static double ComputeOverclockAvg(vector pixel); + static vector ConvertLinePrefixPixels(unsigned char *data); + static Table CreateLinePrefixTable(vector prefixData); + static void CreateStretchPairs(); + static void FixDns(Buffer &buf); + static void TranslateCassIssLabels(FileName &labelFile, Cube *ocube, Pvl *log); + //Global variables + static QString compressionType; + static QString dataConversionType; + static double flightSoftware; + static Stretch stretch; + static int sumMode; + static int validMax; + + void ciss2isis(UserInterface &ui, Pvl *log) { + //PROCESS 1: saves off label, header, and line prefix data ==========================================// + ProcessImportPds p; + Pvl label; + FileName in = ui.GetFileName("FROM"); + + try { + p.SetPdsFile(in.expanded(), "", label); + } + catch (IException &e) { + throw IException(e, IException::User, + QObject::tr("Error reading input file. Make sure it contains a PDS label."), + _FILEINFO_); + } + + //Checks if in file is rdr + if(label.hasObject("IMAGE_MAP_PROJECTION")) { + QString msg = "[" + in.name() + "] appears to be an rdr file."; + msg += " Use pds2isis."; + throw IException(IException::User, msg, _FILEINFO_); + } + + // Set the output bit type to SignedWord + CubeAttributeOutput &outAtt = ui.GetOutputAttribute("TO"); + outAtt.setPixelType(SignedWord); + outAtt.setMinimum((double)VALID_MIN2); + outAtt.setMaximum((double)VALID_MAX2); + Cube *ocube = p.SetOutputCube(ui.GetFileName("TO"), outAtt); + + TranslateCassIssLabels(in, ocube, log); + + //Save off header (includes vicar labels and binary telemetry header) + // No need to SetFileHeaderBytes() this is already done by ProcessImportPds automatically + int vicarLabelBytes = label.findObject("IMAGE_HEADER").findKeyword("BYTES"); + p.SaveFileHeader(); + + //Save off line prefix data, always 24 bytes of binary prefix per line,see SIS version 1.1 pg 103 + int linePrefixBytes = label.findObject("IMAGE").findKeyword("LINE_PREFIX_BYTES"); + p.SetDataPrefixBytes(linePrefixBytes); + p.SaveDataPrefix(); + + //SET PROGRESS TEXT, VALID MAXIMUM PIXEL VALUE, AND CREATE STRETCH IF NEEDED + if(dataConversionType != "Table") { //Conversion Type is 12Bit or 8LSB, only save off overclocked pixels + if(dataConversionType == "12Bit") { + p.Progress()->SetText("Image was 12 bit. No conversion needed. \nSaving line prefix data..."); + } + else { //if (dataConversionType == "8LSB") { + p.Progress()->SetText("Image was truncated to 8 least significant bits. No conversion needed. \nSaving line prefix data..."); + } + } + else { //if ConversionType == Table, Use LUT to create stretch pairs for conversion + CreateStretchPairs(); + // Pvl outputLabels; + Pvl *outputLabel = ocube->label(); + //Adjust Table-encoded values from 8 bit back to 12 bit. + PvlGroup &inst = outputLabel->findGroup("Instrument", Pvl::Traverse); + double biasStripMean = inst.findKeyword("BiasStripMean"); + inst.findKeyword("BiasStripMean").setValue(toString(stretch.Map(biasStripMean))); + inst.findKeyword("BiasStripMean").addComment("BiasStripMean value converted back to 12 bit."); + p.Progress()->SetText("Image was converted using 12-to-8 bit table. \nConverting prefix pixels back to 12 bit and saving line prefix data..."); + } + + p.StartProcess(); + + // Write line prefix data to table in output cube + vector > dataPrefix = p.DataPrefix(); + vector prefixBand0 = dataPrefix.at(0); //There is only one band so the outside vector only contains + // one entry and the inside vector only contains nl entries + Table linePrefixTable = CreateLinePrefixTable(prefixBand0); + ocube->write(linePrefixTable); + // Compute readout order (roo) and save to output cube's instrument group + unsigned char *header = (unsigned char *) p.FileHeader(); + int roo = *(header + 50 + vicarLabelBytes) / 32 % 2; //**** THIS MAY NEED TO BE CHANGED, + // SEE BOTTOM OF THIS FILE FOR IN DEPTH COMMENTS ON READOUTORDER + PvlGroup &inst = ocube->label()->findGroup("Instrument", Pvl::Traverse); + inst.addKeyword(PvlKeyword("ReadoutOrder", toString(roo))); + p.EndProcess(); + + // PROCESS 2 : Do 8 bit to 12 bit conversion for image ==============================================// + ProcessByLine p2; + QString ioFile = ui.GetFileName("TO"); + CubeAttributeInput att; + p2.SetInputCube(ioFile, att, ReadWrite); + //if ConversionType == 12Bit or 8LSB, only save off overclocked pixels + if(dataConversionType == "12Bit") { + p2.Progress()->SetText("Setting special pixels and saving as 16bit..."); + } + else if(dataConversionType == "8LSB") { + p2.Progress()->SetText("Setting special pixels and saving as 16bit..."); + } + //if ConversionType == Table, Use LUT to create stretch pairs for conversion + else { + p2.Progress()->SetText("Converting image pixels back to 12-bit and saving as 16bit..."); + } + p2.StartProcess(FixDns); + p2.EndProcess(); + } + + //call this method after stretch is closed in IsisMain() + // write data into table to save in output cube + // author Jeannie Walldren 2008-08-21 + Table CreateLinePrefixTable(vector prefixData) { + TableField overclockPixels("OverclockPixels", TableField::Double, 3); + //3 columns, first two are overclocked pixels and the third is their average + TableRecord linePrefixRecord; + linePrefixRecord += overclockPixels; + Table linePrefixTable("ISS Prefix Pixels", linePrefixRecord); + linePrefixTable.SetAssociation(Table::Lines); + for(int l = 0; l < (int)prefixData.size(); l++) { + unsigned char *linePrefix = (unsigned char *)(prefixData[l]); + linePrefixRecord[0] = ConvertLinePrefixPixels(linePrefix); + linePrefixTable += linePrefixRecord; + } + return linePrefixTable; + } + + //used by CreateLinePrefixTable() to convert prefix data + // author Jeannie Walldren 2008-08-21 + vector ConvertLinePrefixPixels(unsigned char *data) { + Buffer pixelBuf(1, 1, 1, SignedWord); + + vector calibrationPixels; + //Pixel data is MSB, see SIS version 1.1 page 17 + EndianSwapper swapper("MSB"); + + vector pixel; + //12 is start byte for First Overclocked Pixel Sum in Binary Line Prefix, SIS version 1.1 page 94 + pixel.push_back(swapper.ShortInt(& (data[12]))); + //22 is start byte for Last Overclocked Pixel Sum in Binary Line Prefix, see SIS version 1.1 page 94 + pixel.push_back(swapper.ShortInt(& (data[22]))); + pixel.push_back(ComputeOverclockAvg(pixel)); + for(int i = 0; i < (int)pixel.size(); i++) { + pixelBuf[0] = pixel[i]; + // Do 8 bit to 12 bit conversion for prefix data + FixDns(pixelBuf); + double pix = pixelBuf[0]; + if(pix == NULL8) { + calibrationPixels.push_back(NULL2); + } + else if(pix == LOW_REPR_SAT8) { + calibrationPixels.push_back(LOW_REPR_SAT2); + } + else if(pix == LOW_INSTR_SAT8) { + calibrationPixels.push_back(LOW_INSTR_SAT2); + } + else if(pix == HIGH_INSTR_SAT8) { + calibrationPixels.push_back(HIGH_INSTR_SAT2); + } + else if(pix == HIGH_REPR_SAT8) { + calibrationPixels.push_back(HIGH_REPR_SAT2); + } + else { + calibrationPixels.push_back(pix); + } + } + return calibrationPixels; + } + + // Called in IsisMain() if DataConversionType == Table + // Creates stretch pairs for mapping in Fix Dns + // author Jeannie Walldren 2008-08-21 + void CreateStretchPairs() { + // Set up the strech for the 8 to 12 bit conversion from file + PvlGroup &dataDir = Preference::Preferences().findGroup("DataDirectory"); + QString missionDir = (QString) dataDir["Cassini"]; + FileName *lutFile = new FileName(missionDir + "/calibration/lut/lut.tab"); + CisscalFile *stretchPairs = new CisscalFile(lutFile->expanded()); + // Create the stretch pairs + double temp1 = 0; + stretch.ClearPairs(); + for(int i = 0; i < stretchPairs->LineCount(); i++) { + QString line; + stretchPairs->GetLine(line); //assigns value to line + line = line.simplified(); + + foreach (QString value, line.split(QRegExp("[\\s,]"), QString::SkipEmptyParts)) { + stretch.AddPair(temp1, toDouble(value)); + temp1++; + } + } + stretchPairs->Close(); + return; + } + + /** + * The input buffer has a raw 16 bit buffer but the values are still 0 to 255. + * We know that 255 (stretched to 4095 if Table converted) is saturated. + * Sky pixels could have valid DN of 0, but missing pixels are also saved as 0, + * so it is impossible to distinguish between them. + * This method is used by ConvertLinePrefixPixels() and IsisMain() for ProcessByLine p2. + * author Jeannie Walldren 2008-08-21 + * + */ + void FixDns(Buffer &buf) { + for(int i = 0; i < buf.size(); i++) { + // zeros and negatives are valid DN values, according to scientists, + // but likelyhood of a zero in 16 bit is rare, + // so assume these are missing pixels and set them to null + if(buf[i] == 0) { + buf[i] = Null; + } + else if(dataConversionType == "Table") { + buf[i] = stretch.Map((int)buf[i]); + } + // save max values (4095 for table-converted images and 255 for others) as HRS + if(buf[i] >= validMax) { + buf[i] = Hrs; + } + } + } + + + /** + * This method uses the translation table to read labels and adds any + * other needed keywords to Instrument, BandBin, and Kernels groups + * Called in IsisMain() + * + * @param labelFile + * @param ocube + * + * @history 2008-08-21 Jeannie Walldren + * @history 2010-12-08 Sharmila Prasad - Removed traling 'Z' for Start, + * Stop and Image Time labels + * + */ + void TranslateCassIssLabels(FileName &labelFile, Cube *ocube, Pvl *log) { + // Get the directory where the CISS translation tables are. + QString dir = "$ISISROOT/appdata/translations"; + FileName transFile(dir + "/CassiniIss.trn"); + + // Get the translation manager ready + Pvl inputLabel(labelFile.expanded()); + PvlToPvlTranslationManager labelXlater(inputLabel, transFile.expanded()); + + // Pvl outputLabels; + Pvl *outputLabel = ocube->label(); + labelXlater.Auto(*(outputLabel)); + + //Add needed keywords that are not in translation table to cube's instrument group + PvlGroup &inst = outputLabel->findGroup("Instrument", Pvl::Traverse); + QString scc = inputLabel.findKeyword("SPACECRAFT_CLOCK_CNT_PARTITION"); + scc += "/" + (QString) inputLabel.findKeyword("SPACECRAFT_CLOCK_START_COUNT"); + inst.addKeyword(PvlKeyword("SpacecraftClockCount", scc)); + + //Add units of measurement to keywords from translation table + double exposureDuration = inst.findKeyword("ExposureDuration"); + inst.findKeyword("ExposureDuration").setValue(toString(exposureDuration), "Milliseconds"); + + int gainModeId = inst.findKeyword("GainModeId"); + inst.findKeyword("GainModeId").setValue(toString(gainModeId), "ElectronsPerDN"); + + PvlKeyword opticsTemp = inst.findKeyword("OpticsTemperature"); + inst.findKeyword("OpticsTemperature").setValue(opticsTemp[0]); + inst.findKeyword("OpticsTemperature").addValue(opticsTemp[1], "DegreesCelcius"); + + double instDataRate = inst.findKeyword("InstrumentDataRate"); + inst.findKeyword("InstrumentDataRate").setValue(toString(instDataRate), "KilobitsPerSecond"); + + // initialize global variables + dataConversionType = (QString) inst.findKeyword("DataConversionType"); + validMax = inputLabel.findKeyword("ValidMaximum")[1].toInt(); + sumMode = inst.findKeyword("SummingMode"); + compressionType = (QString) inst.findKeyword("CompressionType"); + IString fsw((QString) inst.findKeyword("FlightSoftwareVersionId")); + if(fsw == "Unknown") { + flightSoftware = 0.0; + } + else { + flightSoftware = fsw.ToDouble(); + } + + // Remove the trailing 'Z' in some pds labels + QString sUpdateTime = inst.findKeyword("StartTime")[0]; + sUpdateTime.remove(QRegExp("[Zz]")); + inst.findKeyword("StartTime").setValue(sUpdateTime); + + sUpdateTime = inst.findKeyword("StopTime")[0]; + sUpdateTime.remove(QRegExp("[Zz]")); + inst.findKeyword("StopTime").setValue(sUpdateTime); + + sUpdateTime = inst.findKeyword("ImageTime")[0]; + sUpdateTime.remove(QRegExp("[Zz]")); + inst.findKeyword("ImageTime").setValue(sUpdateTime); + + + // create BandBin group + QString filter = inputLabel.findKeyword("FilterName")[0] + "/" + + inputLabel.findKeyword("FilterName")[1]; + + QString instrumentID = inst.findKeyword("InstrumentId"); + QString cameraAngleDefs; + if(instrumentID.at(3) == 'N') { + cameraAngleDefs = dir + "/CassiniIssNarrowAngle.def"; + } + else if(instrumentID.at(3) == 'W') { + cameraAngleDefs = dir + "/CassiniIssWideAngle.def"; + } + + double center = 0; + double width = 0; + + TextFile cameraAngle(cameraAngleDefs); + int numLines = cameraAngle.LineCount(); + bool foundfilter = false; + for(int i = 0; i < numLines; i++) { + QString line; + cameraAngle.GetLine(line, true); + + QStringList tokens = line.simplified().split(" "); + if(tokens.count() > 2 && tokens.first() == filter) { + center = toDouble(tokens[1]); + width = toDouble(tokens[2]); + foundfilter = true; + break; + } + } + PvlGroup bandBin("BandBin"); + bandBin += PvlKeyword("FilterName", filter); + bandBin += PvlKeyword("OriginalBand", "1"); + + if(foundfilter) { + bandBin += PvlKeyword("Center", toString(center)); + bandBin += PvlKeyword("Width", toString(width)); + } + else { + PvlGroup msgGrp("Warnings"); + msgGrp += PvlKeyword("CameraAngleLookup", "Failed! No Camera information for filter combination: " + filter); + if (log) { + log->addGroup(msgGrp); + } + bandBin += PvlKeyword("Center", "None found for filter combination."); + bandBin += PvlKeyword("Width", "None found for filter combination."); + } + ocube->putGroup(bandBin); + + PvlGroup kerns("Kernels"); + + if(instrumentID == "ISSNA") { + kerns += PvlKeyword("NaifFrameCode", "-82360"); + } + else if(instrumentID == "ISSWA") { + kerns += PvlKeyword("NaifFrameCode", "-82361"); + } + else { + QString msg = "CISS2ISIS only imports Cassini ISS narrow "; + msg += "angle or wide angle images"; + throw IException(IException::User, msg, _FILEINFO_); + } + ocube->putGroup(kerns); + + return; + } + + + + // This method is called in ConvertLinePrefixPixels() and is + // modelled after IDL CISSCAL's OverclockAvg() in cassimg_define.pro + // author Jeannie Walldren 2008-08-21 + double ComputeOverclockAvg(vector pixel) { + // overclocks array is corrupt for lossy images (see cassimg_readvic.pro) + + if(compressionType != "Lossy" && flightSoftware < 1.3) { //numberOfOverclocks == 1 + // if Bltype CASSINI-ISS or CAS-ISS2, i.e. flight software version < 1.3 + // then there is only one column of valid overclocks in prefix pixels table, + // the first column contains nulls, so use column 2 as average + return pixel[1]; + } + else { //numberOfOverclocks == 2 + // number of columns of valid overclocks in prefix pixels table is 2 + // for CAS-ISS3 or CAS-ISS4, i.e. flight software version 1.3 or 1.4 + // calculate appropriate average (as in cassimg_define.pro, CassImg::OverclockAvg()) + if(sumMode == 1) { + return ((((double) pixel[0]) / 2 + ((double) pixel[1]) / 6) / 2); + } + if(sumMode == 2) { + return ((((double)pixel[0]) + ((double) pixel[1]) / 3) / 2); + } + if(sumMode == 4) { + return ((((double) pixel[0]) + ((double) pixel[1])) / 2); + } + else return 0; + } + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // File header and readout order comments... + // OUR FILE HEADER INCLUDES TWO SECTIONS: + // -The first is the VICAR label (SIS page 52). The number of bytes included here is calculated in the IsisMain() + // -The second is the Binary Label Header, or Binary Telemetry Header(SIS page 52). This contains 60 bytes (SIS page 84) of significant data. + // The READOUT ORDER of an image is the order in which the cameras were read. This is needed for radiometric calibration (CISSCAL). + // The possible values are : + // 0 : Narrow-angle camera was read out first + // 1 : Wide-angle camera was read out first + // IDL CISSCAL FILE CASSIMG_SUBTRACTDARK.PRO LINE 333: + // roo = bh[50]/32 MOD 2 ;Readout order is the 2nd bit of the 51st byte + // According to SIS page 92 (Field=Software, Valid Values), the readout order is index 2 (the THIRD bit) of the byte. + // Normally, we would assume that this was the third bit from the right, but there is some confusion on this matter. + // SIS page 17 says bits and bytes are both "big endian" for pixel data, but doesn't mention whether this includes the binary telemetry table data, + // Reading the first 3 bytes of the binary header and comparing with bit values described in SIS Table 7.3.2, + // if the bytes are read as most significant bit first (left-to-right), each value matches up except summation mode. + // In this case, SIS says they shoud be sum1:01, sum2:10, sum4:11. Actual values are sum1:00, sum2:01, sum4:10. + // The IDL code also appears to be written as though bits are read in this manner, accessing the third bit from the left (32 ~ 00100000). + // Since we haven't found a difinitive answer to this, we are mimicking the IDL code to determine the read out order. + // We have not found an image with roo = 1 as of yet to test this. + // If it is found to be the case that bits are read from left to right in this header, it may be more clear in the + // future to rewrite the line using a logical bitwise &-operator: roo = *(header+50+vicarLabelBytes) & (00100000); + // SOURCES : + // Cassini ISS Tour VICAR Image Data File and Detatched PDS Label SIS, Tour Version 1.1 December 1, 2004 + // IDL cisscal application files: cassimg_subtractdark.pro and linetime.pro + // -Jeannie Walldren 08/06/2008 + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +} diff --git a/isis/src/cassini/apps/ciss2isis/ciss2isis.h b/isis/src/cassini/apps/ciss2isis/ciss2isis.h new file mode 100644 index 0000000000..49f5238643 --- /dev/null +++ b/isis/src/cassini/apps/ciss2isis/ciss2isis.h @@ -0,0 +1,19 @@ +#ifndef ciss2isis_h +#define ciss2isis_h + +/** This is free and unencumbered software released into the public domain. + +The authors of ISIS do not claim copyright on the contents of this file. +For more details about the LICENSE terms and the AUTHORS, you will +find files of those names at the top level of this repository. **/ + +/* SPDX-License-Identifier: CC0-1.0 */ + +#include "Cube.h" +#include "UserInterface.h" + +namespace Isis { + extern void ciss2isis(UserInterface &ui, Pvl *log=nullptr); +} + +#endif diff --git a/isis/src/cassini/apps/ciss2isis/main.cpp b/isis/src/cassini/apps/ciss2isis/main.cpp index 6f427715e0..142b609ee8 100644 --- a/isis/src/cassini/apps/ciss2isis/main.cpp +++ b/isis/src/cassini/apps/ciss2isis/main.cpp @@ -6,456 +6,28 @@ find files of those names at the top level of this repository. **/ /* SPDX-License-Identifier: CC0-1.0 */ -//Source: Cassini ISS Tour VICAR Image Data File and Detatched PDS Label SIS, Tour Version 1.1 December 1, 2004 - #include "Isis.h" -#include -#include - -#include - -#include "CisscalFile.h" -#include "Cube.h" -#include "FileName.h" -#include "IException.h" -#include "IString.h" -#include "Preference.h" -#include "ProcessImportPds.h" -#include "ProcessByLine.h" +#include "Application.h" #include "Pvl.h" -#include "SpecialPixel.h" -#include "Stretch.h" -#include "Table.h" -#include "TextFile.h" -#include "UserInterface.h" +#include "ciss2isis.h" - -using namespace std; using namespace Isis; -// Function prototypes -double ComputeOverclockAvg(vector pixel); -vector ConvertLinePrefixPixels(unsigned char *data); -Table CreateLinePrefixTable(vector prefixData); -void CreateStretchPairs(); -void FixDns(Buffer &buf); -void TranslateCassIssLabels(FileName &labelFile, Cube *ocube); -//Global variables -QString compressionType; -QString dataConversionType; -double flightSoftware; -Stretch stretch; -int sumMode; -int validMax; - void IsisMain() { - //PROCESS 1: saves off label, header, and line prefix data ==========================================// - ProcessImportPds p; - Pvl label; UserInterface &ui = Application::GetUserInterface(); - FileName in = ui.GetFileName("FROM"); - + Pvl appLog; try { - p.SetPdsFile(in.expanded(), "", label); - } - catch (IException &e) { - throw IException(e, IException::User, - QObject::tr("Error reading input file. Make sure it contains a PDS label."), - _FILEINFO_); - } - - //Checks if in file is rdr - if(label.hasObject("IMAGE_MAP_PROJECTION")) { - QString msg = "[" + in.name() + "] appears to be an rdr file."; - msg += " Use pds2isis."; - throw IException(IException::User, msg, _FILEINFO_); - } - - // Set the output bit type to SignedWord - CubeAttributeOutput &outAtt = ui.GetOutputAttribute("TO"); - outAtt.setPixelType(SignedWord); - outAtt.setMinimum((double)VALID_MIN2); - outAtt.setMaximum((double)VALID_MAX2); - Cube *ocube = p.SetOutputCube(ui.GetFileName("TO"), outAtt); - - TranslateCassIssLabels(in, ocube); - - //Save off header (includes vicar labels and binary telemetry header) - // No need to SetFileHeaderBytes() this is already done by ProcessImportPds automatically - int vicarLabelBytes = label.findObject("IMAGE_HEADER").findKeyword("BYTES"); - p.SaveFileHeader(); - - //Save off line prefix data, always 24 bytes of binary prefix per line,see SIS version 1.1 pg 103 - int linePrefixBytes = label.findObject("IMAGE").findKeyword("LINE_PREFIX_BYTES"); - p.SetDataPrefixBytes(linePrefixBytes); - p.SaveDataPrefix(); - - //SET PROGRESS TEXT, VALID MAXIMUM PIXEL VALUE, AND CREATE STRETCH IF NEEDED - if(dataConversionType != "Table") { //Conversion Type is 12Bit or 8LSB, only save off overclocked pixels - validMax = 255; - if(dataConversionType == "12Bit") { - p.Progress()->SetText("Image was 12 bit. No conversion needed. \nSaving line prefix data..."); - } - else { //if (dataConversionType == "8LSB") { - p.Progress()->SetText("Image was truncated to 8 least significant bits. No conversion needed. \nSaving line prefix data..."); - } - } - else { //if ConversionType == Table, Use LUT to create stretch pairs for conversion - validMax = 4095; - CreateStretchPairs(); - // Pvl outputLabels; - Pvl *outputLabel = ocube->label(); - //Adjust Table-encoded values from 8 bit back to 12 bit. - PvlGroup &inst = outputLabel->findGroup("Instrument", Pvl::Traverse); - double biasStripMean = inst.findKeyword("BiasStripMean"); - inst.findKeyword("BiasStripMean").setValue(toString(stretch.Map(biasStripMean))); - inst.findKeyword("BiasStripMean").addComment("BiasStripMean value converted back to 12 bit."); - p.Progress()->SetText("Image was converted using 12-to-8 bit table. \nConverting prefix pixels back to 12 bit and saving line prefix data..."); - } - - p.StartProcess(); - - // Write line prefix data to table in output cube - vector > dataPrefix = p.DataPrefix(); - vector prefixBand0 = dataPrefix.at(0); //There is only one band so the outside vector only contains - // one entry and the inside vector only contains nl entries - Table linePrefixTable = CreateLinePrefixTable(prefixBand0); - ocube->write(linePrefixTable); - // Compute readout order (roo) and save to output cube's instrument group - unsigned char *header = (unsigned char *) p.FileHeader(); - int roo = *(header + 50 + vicarLabelBytes) / 32 % 2; //**** THIS MAY NEED TO BE CHANGED, - // SEE BOTTOM OF THIS FILE FOR IN DEPTH COMMENTS ON READOUTORDER - PvlGroup &inst = ocube->label()->findGroup("Instrument", Pvl::Traverse); - inst.addKeyword(PvlKeyword("ReadoutOrder", toString(roo))); - p.EndProcess(); - - // PROCESS 2 : Do 8 bit to 12 bit conversion for image ==============================================// - ProcessByLine p2; - QString ioFile = ui.GetFileName("TO"); - CubeAttributeInput att; - p2.SetInputCube(ioFile, att, ReadWrite); - //if ConversionType == 12Bit or 8LSB, only save off overclocked pixels - if(dataConversionType == "12Bit" || dataConversionType == "8LSB") { - p2.Progress()->SetText("Setting special pixels and saving as 16bit..."); - } - //if ConversionType == Table, Use LUT to create stretch pairs for conversion - else { - p2.Progress()->SetText("Converting image pixels back to 12-bit and saving as 16bit..."); + ciss2isis(ui, &appLog); } - p2.StartProcess(FixDns); - p2.EndProcess(); - return; -} - -//call this method after stretch is closed in IsisMain() -// write data into table to save in output cube -// author Jeannie Walldren 2008-08-21 -Table CreateLinePrefixTable(vector prefixData) { - TableField overclockPixels("OverclockPixels", TableField::Double, 3); - //3 columns, first two are overclocked pixels and the third is their average - TableRecord linePrefixRecord; - linePrefixRecord += overclockPixels; - Table linePrefixTable("ISS Prefix Pixels", linePrefixRecord); - linePrefixTable.SetAssociation(Table::Lines); - for(int l = 0; l < (int)prefixData.size(); l++) { - unsigned char *linePrefix = (unsigned char *)(prefixData[l]); - linePrefixRecord[0] = ConvertLinePrefixPixels(linePrefix); - linePrefixTable += linePrefixRecord; - } - return linePrefixTable; -} - -//used by CreateLinePrefixTable() to convert prefix data -// author Jeannie Walldren 2008-08-21 -vector ConvertLinePrefixPixels(unsigned char *data) { - Buffer pixelBuf(1, 1, 1, SignedWord); - - vector calibrationPixels; - //Pixel data is MSB, see SIS version 1.1 page 17 - EndianSwapper swapper("MSB"); - - vector pixel; - //12 is start byte for First Overclocked Pixel Sum in Binary Line Prefix, SIS version 1.1 page 94 - pixel.push_back(swapper.ShortInt(& (data[12]))); - //22 is start byte for Last Overclocked Pixel Sum in Binary Line Prefix, see SIS version 1.1 page 94 - pixel.push_back(swapper.ShortInt(& (data[22]))); - pixel.push_back(ComputeOverclockAvg(pixel)); - for(int i = 0; i < (int)pixel.size(); i++) { - pixelBuf[0] = pixel[i]; - // Do 8 bit to 12 bit conversion for prefix data - FixDns(pixelBuf); - double pix = pixelBuf[0]; - if(pix == NULL8) { - calibrationPixels.push_back(NULL2); - } - else if(pix == LOW_REPR_SAT8) { - calibrationPixels.push_back(LOW_REPR_SAT2); - } - else if(pix == LOW_INSTR_SAT8) { - calibrationPixels.push_back(LOW_INSTR_SAT2); - } - else if(pix == HIGH_INSTR_SAT8) { - calibrationPixels.push_back(HIGH_INSTR_SAT2); - } - else if(pix == HIGH_REPR_SAT8) { - calibrationPixels.push_back(HIGH_REPR_SAT2); - } - else { - calibrationPixels.push_back(pix); + catch (...) { + for (auto grpIt = appLog.beginGroup(); grpIt!= appLog.endGroup(); grpIt++) { + Application::Log(*grpIt); } + throw; } - return calibrationPixels; -} - -// Called in IsisMain() if DataConversionType == Table -// Creates stretch pairs for mapping in Fix Dns -// author Jeannie Walldren 2008-08-21 -void CreateStretchPairs() { - // Set up the strech for the 8 to 12 bit conversion from file - PvlGroup &dataDir = Preference::Preferences().findGroup("DataDirectory"); - QString missionDir = (QString) dataDir["Cassini"]; - FileName *lutFile = new FileName(missionDir + "/calibration/lut/lut.tab"); - CisscalFile *stretchPairs = new CisscalFile(lutFile->expanded()); - // Create the stretch pairs - double temp1 = 0; - stretch.ClearPairs(); - for(int i = 0; i < stretchPairs->LineCount(); i++) { - QString line; - stretchPairs->GetLine(line); //assigns value to line - line = line.simplified(); - foreach (QString value, line.split(QRegExp("[\\s,]"), QString::SkipEmptyParts)) { - stretch.AddPair(temp1, toDouble(value)); - temp1++; - } + for (auto grpIt = appLog.beginGroup(); grpIt!= appLog.endGroup(); grpIt++) { + Application::Log(*grpIt); } - stretchPairs->Close(); - return; } - -/** -* The input buffer has a raw 16 bit buffer but the values are still 0 to 255. -* We know that 255 (stretched to 4095 if Table converted) is saturated. -* Sky pixels could have valid DN of 0, but missing pixels are also saved as 0, -* so it is impossible to distinguish between them. -* This method is used by ConvertLinePrefixPixels() and IsisMain() for ProcessByLine p2. -* author Jeannie Walldren 2008-08-21 -* -*/ -void FixDns(Buffer &buf) { - for(int i = 0; i < buf.size(); i++) { - // zeros and negatives are valid DN values, according to scientists, - // but likelyhood of a zero in 16 bit is rare, - // so assume these are missing pixels and set them to null - if(buf[i] == 0) { - buf[i] = Null; - } - else if(dataConversionType == "Table") { - buf[i] = stretch.Map((int)buf[i]); - } - // save max values (4095 for table-converted images and 255 for others) as HRS - if(buf[i] == validMax) { - buf[i] = Hrs; - } - } -} - - -/** - * This method uses the translation table to read labels and adds any - * other needed keywords to Instrument, BandBin, and Kernels groups - * Called in IsisMain() - * - * @param labelFile - * @param ocube - * - * @history 2008-08-21 Jeannie Walldren - * @history 2010-12-08 Sharmila Prasad - Removed traling 'Z' for Start, - * Stop and Image Time labels - * - */ -void TranslateCassIssLabels(FileName &labelFile, Cube *ocube) { - // Get the directory where the CISS translation tables are. - QString dir = "$ISISROOT/appdata/translations"; - FileName transFile(dir + "/CassiniIss.trn"); - - // Get the translation manager ready - Pvl inputLabel(labelFile.expanded()); - PvlToPvlTranslationManager labelXlater(inputLabel, transFile.expanded()); - - // Pvl outputLabels; - Pvl *outputLabel = ocube->label(); - labelXlater.Auto(*(outputLabel)); - - //Add needed keywords that are not in translation table to cube's instrument group - PvlGroup &inst = outputLabel->findGroup("Instrument", Pvl::Traverse); - QString scc = inputLabel.findKeyword("SPACECRAFT_CLOCK_CNT_PARTITION"); - scc += "/" + (QString) inputLabel.findKeyword("SPACECRAFT_CLOCK_START_COUNT"); - inst.addKeyword(PvlKeyword("SpacecraftClockCount", scc)); - - //Add units of measurement to keywords from translation table - double exposureDuration = inst.findKeyword("ExposureDuration"); - inst.findKeyword("ExposureDuration").setValue(toString(exposureDuration), "Milliseconds"); - - int gainModeId = inst.findKeyword("GainModeId"); - inst.findKeyword("GainModeId").setValue(toString(gainModeId), "ElectronsPerDN"); - - PvlKeyword opticsTemp = inst.findKeyword("OpticsTemperature"); - inst.findKeyword("OpticsTemperature").setValue(opticsTemp[0]); - inst.findKeyword("OpticsTemperature").addValue(opticsTemp[1], "DegreesCelcius"); - - double instDataRate = inst.findKeyword("InstrumentDataRate"); - inst.findKeyword("InstrumentDataRate").setValue(toString(instDataRate), "KilobitsPerSecond"); - - // initialize global variables - dataConversionType = (QString) inst.findKeyword("DataConversionType"); - sumMode = inst.findKeyword("SummingMode"); - compressionType = (QString) inst.findKeyword("CompressionType"); - IString fsw((QString) inst.findKeyword("FlightSoftwareVersionId")); - if(fsw == "Unknown") { - flightSoftware = 0.0; - } - else { - flightSoftware = fsw.ToDouble(); - } - - // Remove the trailing 'Z' in some pds labels - QString sUpdateTime = inst.findKeyword("StartTime")[0]; - sUpdateTime.remove(QRegExp("[Zz]")); - inst.findKeyword("StartTime").setValue(sUpdateTime); - - sUpdateTime = inst.findKeyword("StopTime")[0]; - sUpdateTime.remove(QRegExp("[Zz]")); - inst.findKeyword("StopTime").setValue(sUpdateTime); - - sUpdateTime = inst.findKeyword("ImageTime")[0]; - sUpdateTime.remove(QRegExp("[Zz]")); - inst.findKeyword("ImageTime").setValue(sUpdateTime); - - - // create BandBin group - QString filter = inputLabel.findKeyword("FilterName")[0] + "/" + - inputLabel.findKeyword("FilterName")[1]; - - QString instrumentID = inst.findKeyword("InstrumentId"); - QString cameraAngleDefs; - if(instrumentID.at(3) == 'N') { - cameraAngleDefs = dir + "/CassiniIssNarrowAngle.def"; - } - else if(instrumentID.at(3) == 'W') { - cameraAngleDefs = dir + "/CassiniIssWideAngle.def"; - } - - double center = 0; - double width = 0; - - TextFile cameraAngle(cameraAngleDefs); - int numLines = cameraAngle.LineCount(); - bool foundfilter = false; - for(int i = 0; i < numLines; i++) { - QString line; - cameraAngle.GetLine(line, true); - - QStringList tokens = line.simplified().split(" "); - if(tokens.count() > 2 && tokens.first() == filter) { - center = toDouble(tokens[1]); - width = toDouble(tokens[2]); - foundfilter = true; - break; - } - } - PvlGroup bandBin("BandBin"); - bandBin += PvlKeyword("FilterName", filter); - bandBin += PvlKeyword("OriginalBand", "1"); - - if(foundfilter) { - bandBin += PvlKeyword("Center", toString(center)); - bandBin += PvlKeyword("Width", toString(width)); - } - else { - PvlGroup msgGrp("Warnings"); - msgGrp += PvlKeyword("CameraAngleLookup", "Failed! No Camera information for filter combination: " + filter); - Application::Log(msgGrp); - bandBin += PvlKeyword("Center", "None found for filter combination."); - bandBin += PvlKeyword("Width", "None found for filter combination."); - } - ocube->putGroup(bandBin); - - PvlGroup kerns("Kernels"); - - if(instrumentID == "ISSNA") { - kerns += PvlKeyword("NaifFrameCode", "-82360"); - } - else if(instrumentID == "ISSWA") { - kerns += PvlKeyword("NaifFrameCode", "-82361"); - } - else { - QString msg = "CISS2ISIS only imports Cassini ISS narrow "; - msg += "angle or wide angle images"; - throw IException(IException::User, msg, _FILEINFO_); - } - ocube->putGroup(kerns); - - return; -} - - - -// This method is called in ConvertLinePrefixPixels() and is -// modelled after IDL CISSCAL's OverclockAvg() in cassimg_define.pro -// author Jeannie Walldren 2008-08-21 -double ComputeOverclockAvg(vector pixel) { - // overclocks array is corrupt for lossy images (see cassimg_readvic.pro) - - if(compressionType != "Lossy" && flightSoftware < 1.3) { //numberOfOverclocks == 1 - // if Bltype CASSINI-ISS or CAS-ISS2, i.e. flight software version < 1.3 - // then there is only one column of valid overclocks in prefix pixels table, - // the first column contains nulls, so use column 2 as average - return pixel[1]; - } - else { //numberOfOverclocks == 2 - // number of columns of valid overclocks in prefix pixels table is 2 - // for CAS-ISS3 or CAS-ISS4, i.e. flight software version 1.3 or 1.4 - // calculate appropriate average (as in cassimg_define.pro, CassImg::OverclockAvg()) - if(sumMode == 1) { - return ((((double) pixel[0]) / 2 + ((double) pixel[1]) / 6) / 2); - } - if(sumMode == 2) { - return ((((double)pixel[0]) + ((double) pixel[1]) / 3) / 2); - } - if(sumMode == 4) { - return ((((double) pixel[0]) + ((double) pixel[1])) / 2); - } - else return 0; - } -} - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// File header and readout order comments... -// OUR FILE HEADER INCLUDES TWO SECTIONS: -// -The first is the VICAR label (SIS page 52). The number of bytes included here is calculated in the IsisMain() -// -The second is the Binary Label Header, or Binary Telemetry Header(SIS page 52). This contains 60 bytes (SIS page 84) of significant data. -// The READOUT ORDER of an image is the order in which the cameras were read. This is needed for radiometric calibration (CISSCAL). -// The possible values are : -// 0 : Narrow-angle camera was read out first -// 1 : Wide-angle camera was read out first -// IDL CISSCAL FILE CASSIMG_SUBTRACTDARK.PRO LINE 333: -// roo = bh[50]/32 MOD 2 ;Readout order is the 2nd bit of the 51st byte -// According to SIS page 92 (Field=Software, Valid Values), the readout order is index 2 (the THIRD bit) of the byte. -// Normally, we would assume that this was the third bit from the right, but there is some confusion on this matter. -// SIS page 17 says bits and bytes are both "big endian" for pixel data, but doesn't mention whether this includes the binary telemetry table data, -// Reading the first 3 bytes of the binary header and comparing with bit values described in SIS Table 7.3.2, -// if the bytes are read as most significant bit first (left-to-right), each value matches up except summation mode. -// In this case, SIS says they shoud be sum1:01, sum2:10, sum4:11. Actual values are sum1:00, sum2:01, sum4:10. -// The IDL code also appears to be written as though bits are read in this manner, accessing the third bit from the left (32 ~ 00100000). -// Since we haven't found a difinitive answer to this, we are mimicking the IDL code to determine the read out order. -// We have not found an image with roo = 1 as of yet to test this. -// If it is found to be the case that bits are read from left to right in this header, it may be more clear in the -// future to rewrite the line using a logical bitwise &-operator: roo = *(header+50+vicarLabelBytes) & (00100000); -// SOURCES : -// Cassini ISS Tour VICAR Image Data File and Detatched PDS Label SIS, Tour Version 1.1 December 1, 2004 -// IDL cisscal application files: cassimg_subtractdark.pro and linetime.pro -// -Jeannie Walldren 08/06/2008 -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/isis/src/cassini/apps/ciss2isis/tsts/narrowAngle/Makefile b/isis/src/cassini/apps/ciss2isis/tsts/narrowAngle/Makefile deleted file mode 100644 index f467f5cbb7..0000000000 --- a/isis/src/cassini/apps/ciss2isis/tsts/narrowAngle/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -APPNAME = ciss2isis - -labels.txt.IGNORELINES = Bytes StartByte TileSamples TileLines - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) from=$(INPUT)/N1472853667_1.LBL \ - to=$(OUTPUT)/N1472853667_1.truth.cub > /dev/null; - catlab from=$(OUTPUT)/N1472853667_1.truth.cub to=$(OUTPUT)/labels.txt > /dev/null; diff --git a/isis/src/cassini/apps/ciss2isis/tsts/wideAngle/Makefile b/isis/src/cassini/apps/ciss2isis/tsts/wideAngle/Makefile deleted file mode 100644 index af390ad05c..0000000000 --- a/isis/src/cassini/apps/ciss2isis/tsts/wideAngle/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -APPNAME =ciss2isis - -labels.txt.IGNORELINES = Bytes StartByte ByteOrder TileSamples TileLines - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) FROM=$(INPUT)/W1472855646_5.LBL \ - TO=$(OUTPUT)/W1472855646_5.truth.cub > /dev/null; - catlab from=$(OUTPUT)/W1472855646_5.truth.cub to=$(OUTPUT)/labels.txt > /dev/null; diff --git a/isis/tests/FunctionalTestsCiss2isis.cpp b/isis/tests/FunctionalTestsCiss2isis.cpp new file mode 100644 index 0000000000..4d6f3e4073 --- /dev/null +++ b/isis/tests/FunctionalTestsCiss2isis.cpp @@ -0,0 +1,272 @@ +#include + +#include "ciss2isis.h" +#include "Fixtures.h" +#include "Pvl.h" +#include "PvlGroup.h" +#include "TestUtilities.h" +#include "Histogram.h" + +#include "gtest/gtest.h" + +using namespace Isis; + +static QString APP_XML = FileName("$ISISROOT/bin/xml/ciss2isis.xml").expanded(); + +TEST(Ciss2Isis, Ciss2isisTestNac) { + Pvl appLog; + QTemporaryDir prefix; + QString cubeFileName = prefix.path() + "/ciss2isis_out.cub"; + QVector args = { "from=data/ciss2isis/N1472853667_1.cropped.lbl", + "to=" + cubeFileName }; + UserInterface options(APP_XML, args); + try { + ciss2isis(options, &appLog); + } + catch (IException &e) { + FAIL() << "Unable to ingest file: " << e.toString().toStdString().c_str() << std::endl; + } + + Cube outCube(cubeFileName); + Pvl *outLabel = outCube.label(); + + PvlGroup dimensions = outLabel->findGroup("Dimensions", Pvl::Traverse); + ASSERT_EQ((int)dimensions["Samples"], 1024); + ASSERT_EQ((int)dimensions["Lines"], 10); + ASSERT_EQ((int)dimensions["Bands"], 1); + + PvlGroup pixels = outLabel->findGroup("Pixels", Pvl::Traverse); + ASSERT_EQ(pixels["Type"][0].toStdString(), "SignedWord"); + ASSERT_EQ(pixels["ByteOrder"][0].toStdString(), "Lsb"); + ASSERT_EQ((double)pixels["Base"], 0.0); + ASSERT_EQ((double)pixels["Multiplier"], 1.0); + + std::istringstream iss(R"( + Group = Instrument + SpacecraftName = Cassini-Huygens + InstrumentId = ISSNA + TargetName = Saturn + StartTime = 2004-09-02T21:32:36.410 + StopTime = 2004-09-02T21:36:16.410 + ExposureDuration = 220000.0 + AntibloomingStateFlag = On + + # BiasStripMean value converted back to 12 bit. + BiasStripMean = 50.00196 + CompressionRatio = 1.845952 + CompressionType = Lossless + DataConversionType = Table + DelayedReadoutFlag = No + FlightSoftwareVersionId = 1.3 + GainModeId = 12 + GainState = 3 + ImageTime = 2004-09-02T21:36:16.410 + InstrumentDataRate = 182.783997 + OpticsTemperature = (0.712693, 1.905708 ) + ReadoutCycleIndex = 10 + ShutterModeId = NacOnly + ShutterStateId = Enabled + SummingMode = 1 + InstrumentModeId = Full + SpacecraftClockCount = 1/1472853447.118 + ReadoutOrder = 0 + End_Group + )"); + + PvlGroup truthInstGroup; + iss >> truthInstGroup; + PvlGroup &instGroup = outLabel->findGroup("Instrument", Pvl::Traverse); + + EXPECT_PRED_FORMAT2(AssertPvlGroupEqual, instGroup, truthInstGroup); + + std::istringstream arss(R"( + Group = Archive + DataSetId = CO-S-ISSNA/ISSWA-2-EDR-V1.0 + ImageNumber = 1472853667 + ObservationId = ISS_00ARI_DIFFUSRNG003_PRIME + ProductId = 1_N1472853667.118 + End_Group + )"); + + PvlGroup truthArchiveGroup; + arss >> truthArchiveGroup; + + PvlGroup &archiveGroup = outLabel->findGroup("Archive", Pvl::Traverse); + + EXPECT_PRED_FORMAT2(AssertPvlGroupEqual, archiveGroup, truthArchiveGroup); + + std::istringstream bbss(R"( + Group = BandBin + FilterName = CL1/CL2 + OriginalBand = 1 + Center = 651.065 + Width = 340.923 + End_Group + )"); + + PvlGroup truthBandBinGroup; + bbss >> truthBandBinGroup; + + PvlGroup &bandBinGroup = outLabel->findGroup("BandBin", Pvl::Traverse); + + EXPECT_PRED_FORMAT2(AssertPvlGroupEqual, bandBinGroup, truthBandBinGroup); + + // Check for the ISS prefix pixel table + ASSERT_TRUE(outLabel->hasObject("Table")); + EXPECT_EQ(outLabel->findObject("Table", Pvl::Traverse)["Name"][0], "ISS Prefix Pixels"); + + std::unique_ptr hist (outCube.histogram()); + EXPECT_NEAR(hist->Average(), 247.45226885705699, .00001); + EXPECT_EQ(hist->Sum(), 2470316); + EXPECT_EQ(hist->ValidPixels(), 9983); + EXPECT_NEAR(hist->StandardDeviation(), 27.779542219945746, .0001); +} + +TEST(Ciss2Isis, Ciss2isisTestWac) { + Pvl appLog; + QTemporaryDir prefix; + QString cubeFileName = prefix.path() + "/ciss2isis_out.cub"; + QVector args = { "from=data/ciss2isis/W1472855646_5.cropped.lbl", + "to=" + cubeFileName }; + UserInterface options(APP_XML, args); + try { + ciss2isis(options, &appLog); + } + catch (IException &e) { + FAIL() << "Unable to ingest file: " << e.toString().toStdString().c_str() << std::endl; + } + + Cube outCube(cubeFileName); + Pvl *outLabel = outCube.label(); + + PvlGroup dimensions = outLabel->findGroup("Dimensions", Pvl::Traverse); + ASSERT_EQ((int)dimensions["Samples"], 1024); + ASSERT_EQ((int)dimensions["Lines"], 10); + ASSERT_EQ((int)dimensions["Bands"], 1); + + PvlGroup pixels = outLabel->findGroup("Pixels", Pvl::Traverse); + ASSERT_EQ(pixels["Type"][0].toStdString(), "SignedWord"); + ASSERT_EQ(pixels["ByteOrder"][0].toStdString(), "Lsb"); + ASSERT_EQ((double)pixels["Base"], 0.0); + ASSERT_EQ((double)pixels["Multiplier"], 1.0); + + std::istringstream iss(R"( + Group = Instrument + SpacecraftName = Cassini-Huygens + InstrumentId = ISSWA + TargetName = Saturn + StartTime = 2004-09-02T22:09:15.409 + StopTime = 2004-09-02T22:09:15.409 + ExposureDuration = 5.0 + AntibloomingStateFlag = On + BiasStripMean = 72.644554 + CompressionRatio = NotCompressed + CompressionType = NotCompressed + DataConversionType = 12Bit + DelayedReadoutFlag = Yes + FlightSoftwareVersionId = 1.3 + GainModeId = 29 + GainState = 2 + ImageTime = 2004-09-02T22:09:15.409 + InstrumentDataRate = 182.783997 + OpticsTemperature = (7.024934, -999.0 ) + ReadoutCycleIndex = 0 + ShutterModeId = BothSim + ShutterStateId = Disabled + SummingMode = 1 + InstrumentModeId = Full + SpacecraftClockCount = 1/1472855646.121 + ReadoutOrder = 0 + End_Group + )"); + + PvlGroup truthInstGroup; + iss >> truthInstGroup; + PvlGroup &instGroup = outLabel->findGroup("Instrument", Pvl::Traverse); + + EXPECT_PRED_FORMAT2(AssertPvlGroupEqual, instGroup, truthInstGroup); + + std::istringstream arss(R"( + Group = Archive + DataSetId = CO-S-ISSNA/ISSWA-2-EDR-V1.0 + ImageNumber = 1472855646 + ObservationId = ISS_00ASA_MOS0ASWE001_UVIS + ProductId = 1_W1472855646.121 + End_Group + )"); + + PvlGroup truthArchiveGroup; + arss >> truthArchiveGroup; + + PvlGroup &archiveGroup = outLabel->findGroup("Archive", Pvl::Traverse); + + EXPECT_PRED_FORMAT2(AssertPvlGroupEqual, archiveGroup, truthArchiveGroup); + + std::istringstream bbss(R"( + Group = BandBin + FilterName = CL1/CL2 + OriginalBand = 1 + Center = 633.837 + Width = 285.938 + End_Group + )"); + + PvlGroup truthBandBinGroup; + bbss >> truthBandBinGroup; + + PvlGroup &bandBinGroup = outLabel->findGroup("BandBin", Pvl::Traverse); + + EXPECT_PRED_FORMAT2(AssertPvlGroupEqual, bandBinGroup, truthBandBinGroup); + + // Check for the ISS prefix pixel table + ASSERT_TRUE(outLabel->hasObject("Table")); + EXPECT_EQ(outLabel->findObject("Table", Pvl::Traverse)["Name"][0], "ISS Prefix Pixels"); + + std::unique_ptr hist (outCube.histogram()); + EXPECT_NEAR(hist->Average(), 70.914941406249994, .00001); + EXPECT_EQ(hist->Sum(), 726169); + EXPECT_EQ(hist->ValidPixels(), 10240); + EXPECT_NEAR(hist->StandardDeviation(), 0.84419124016427105, .0001); +} + +TEST(Ciss2Isis, Ciss2isisCustomMax) { + Pvl appLog; + QTemporaryDir prefix; + QString cubeFileName = prefix.path() + "/ciss2isis_out.cub"; + + QString inputLabel = "data/ciss2isis/W1472855646_5.cropped.lbl"; + QString updatedPvlLabel = prefix.path() + "/W1472855646_5.cropped.lbl"; + Pvl inputPvl(inputLabel); + inputPvl["VALID_MAXIMUM"][1] = "70"; + inputPvl.write(updatedPvlLabel); + QFile::copy("data/ciss2isis/W1472855646_5.cropped.img", prefix.path() + "/W1472855646_5.cropped.img"); + + QVector args = { "from=" + updatedPvlLabel, + "to=" + cubeFileName }; + UserInterface options(APP_XML, args); + try { + ciss2isis(options, &appLog); + } + catch (IException &e) { + FAIL() << "Unable to ingest file: " << e.toString().toStdString().c_str() << std::endl; + } + + Cube outCube(cubeFileName); + Pvl *outLabel = outCube.label(); + + PvlGroup dimensions = outLabel->findGroup("Dimensions", Pvl::Traverse); + ASSERT_EQ((int)dimensions["Samples"], 1024); + ASSERT_EQ((int)dimensions["Lines"], 10); + ASSERT_EQ((int)dimensions["Bands"], 1); + + PvlGroup pixels = outLabel->findGroup("Pixels", Pvl::Traverse); + ASSERT_EQ(pixels["Type"][0].toStdString(), "SignedWord"); + ASSERT_EQ(pixels["ByteOrder"][0].toStdString(), "Lsb"); + ASSERT_EQ((double)pixels["Base"], 0.0); + ASSERT_EQ((double)pixels["Multiplier"], 1.0); + + std::unique_ptr hist (outCube.histogram()); + EXPECT_EQ(hist->Maximum(), 69); + EXPECT_EQ(hist->ValidPixels(), 728); + EXPECT_EQ(hist->HrsPixels(), (1024 * 10) - hist->ValidPixels()); +} diff --git a/isis/tests/data/ciss2isis/N1472853667_1.cropped.img b/isis/tests/data/ciss2isis/N1472853667_1.cropped.img new file mode 100644 index 0000000000..90e70f04dc Binary files /dev/null and b/isis/tests/data/ciss2isis/N1472853667_1.cropped.img differ diff --git a/isis/tests/data/ciss2isis/N1472853667_1.cropped.lbl b/isis/tests/data/ciss2isis/N1472853667_1.cropped.lbl new file mode 100644 index 0000000000..fbbb061237 --- /dev/null +++ b/isis/tests/data/ciss2isis/N1472853667_1.cropped.lbl @@ -0,0 +1,111 @@ +PDS_VERSION_ID = PDS3 +RECORD_TYPE = FIXED_LENGTH +RECORD_BYTES = 1048 +FILE_RECORDS = 1028 +^IMAGE_HEADER = ('N1472853667_1.cropped.img', 1) +^TELEMETRY_TABLE = ('N1472853667_1.cropped.img', 4) +^LINE_PREFIX_TABLE = ('N1472853667_1.cropped.img', 5) +^IMAGE = ('N1472853667_1.cropped.img', 5) +ANTIBLOOMING_STATE_FLAG = ON +BIAS_STRIP_MEAN = 17.25049 +CALIBRATION_LAMP_STATE_FLAG = 'N/A' +COMMAND_FILE_NAME = 'trigger_6510_6.ioi' +COMMAND_SEQUENCE_NUMBER = 6510 +DARK_STRIP_MEAN = 0.0 +DATA_CONVERSION_TYPE = TABLE +DATA_SET_ID = 'CO-S-ISSNA/ISSWA-2-EDR-V1.0' +DELAYED_READOUT_FLAG = NO +DESCRIPTION = "Incomplete product finalized due to truncated lines." +DETECTOR_TEMPERATURE = -89.243546 +EARTH_RECEIVED_START_TIME = 2004-09-03T09:54:37.232Z +EARTH_RECEIVED_STOP_TIME = 2004-09-03T09:57:12.966Z +ELECTRONICS_BIAS = 112 +EXPECTED_MAXIMUM = (0.756496, 1.9487) +EXPECTED_PACKETS = 519 +EXPOSURE_DURATION = 220000.0 +FILTER_NAME = (CL1, CL2) +FILTER_TEMPERATURE = -0.468354 +FLIGHT_SOFTWARE_VERSION_ID = '1.3' +GAIN_MODE_ID = '12 ELECTRONS PER DN' +IMAGE_MID_TIME = 2004-09-02T21:34:26.410Z +IMAGE_NUMBER = '1472853667' +IMAGE_OBSERVATION_TYPE = {SCIENCE} +IMAGE_TIME = 2004-09-02T21:36:16.410Z +INSTRUMENT_DATA_RATE = 182.783997 +INSTRUMENT_HOST_NAME = 'CASSINI ORBITER' +INSTRUMENT_ID = ISSNA +INSTRUMENT_MODE_ID = FULL +INSTRUMENT_NAME = 'IMAGING SCIENCE SUBSYSTEM NARROW ANGLE' +INST_CMPRS_PARAM = ('N/A', 'N/A', 'N/A', 'N/A') +INST_CMPRS_RATE = (3.6, 4.333807) +INST_CMPRS_RATIO = 1.845952 +INST_CMPRS_TYPE = LOSSLESS +LIGHT_FLOOD_STATE_FLAG = ON +METHOD_DESC = "ISSPT2.5.3;Saturn-Ering;ISS_00ARI_DIFFUSRNG003_PRIME_4" +MISSING_LINES = 511 +MISSING_PACKET_FLAG = NO +MISSION_NAME = 'CASSINI-HUYGENS' +MISSION_PHASE_NAME = 'TOUR PRE-HUYGENS' +OBSERVATION_ID = ISS_00ARI_DIFFUSRNG003_PRIME +OPTICS_TEMPERATURE = (0.712693, 1.905708) +ORDER_NUMBER = 2 +PARALLEL_CLOCK_VOLTAGE_INDEX = 9 +PREPARE_CYCLE_INDEX = 12 +PRODUCT_CREATION_TIME = 2004-09-03T10:39:14Z +PRODUCT_ID = '1_N1472853667.118' +PRODUCT_VERSION_TYPE = FINAL +READOUT_CYCLE_INDEX = 10 +RECEIVED_PACKETS = 576 +SENSOR_HEAD_ELEC_TEMPERATURE = 1.633024 +SEQUENCE_ID = S03 +SEQUENCE_NUMBER = 2 +SEQUENCE_TITLE = ISS_00ARI_DIFFUSRNG003_PRIME +SHUTTER_MODE_ID = NACONLY +SHUTTER_STATE_ID = ENABLED +SOFTWARE_VERSION_ID = 'ISS 9.00 02-05-2004' +SPACECRAFT_CLOCK_CNT_PARTITION = 1 +SPACECRAFT_CLOCK_START_COUNT = '1472853447.118' +SPACECRAFT_CLOCK_STOP_COUNT = '1472853667.118' +START_TIME = 2004-09-02T21:32:36.410Z +STOP_TIME = 2004-09-02T21:36:16.410Z +TARGET_DESC = 'Saturn-Ering' +TARGET_LIST = 'N/A' +TARGET_NAME = SATURN +TELEMETRY_FORMAT_ID = UNK +VALID_MAXIMUM = (9896, 4095) +OBJECT = IMAGE_HEADER + INTERCHANGE_FORMAT = ASCII + HEADER_TYPE = VICAR2 + BYTES = 3144 + RECORDS = 1 + ^DESCRIPTION = 'VICAR2.TXT' +END_OBJECT = IMAGE_HEADER +OBJECT = TELEMETRY_TABLE + INTERCHANGE_FORMAT = BINARY + ROWS = 1 + COLUMNS = 2 + ROW_BYTES = 1048 + ^STRUCTURE = 'TLMTAB.FMT' + OBJECT = COLUMN + NAME = NULL_PADDING + DATA_TYPE = MSB_UNSIGNED_INTEGER + START_BYTE = 61 + BYTES = 987 + END_OBJECT = COLUMN +END_OBJECT = TELEMETRY_TABLE +OBJECT = LINE_PREFIX_TABLE + INTERCHANGE_FORMAT = BINARY + ROWS = 1024 + COLUMNS = 7 + ROW_BYTES = 24 + ROW_SUFFIX_BYTES = 1024 + ^LINE_PREFIX_STRUCTURE = 'PREFIX2.FMT' +END_OBJECT = LINE_PREFIX_TABLE +OBJECT = IMAGE + LINES = 10 + LINE_SAMPLES = 1024 + SAMPLE_BITS = 8 + SAMPLE_TYPE = SUN_INTEGER + LINE_PREFIX_BYTES = 24 +END_OBJECT = IMAGE +END diff --git a/isis/tests/data/ciss2isis/W1472855646_5.cropped.img b/isis/tests/data/ciss2isis/W1472855646_5.cropped.img new file mode 100644 index 0000000000..4f32060989 Binary files /dev/null and b/isis/tests/data/ciss2isis/W1472855646_5.cropped.img differ diff --git a/isis/tests/data/ciss2isis/W1472855646_5.cropped.lbl b/isis/tests/data/ciss2isis/W1472855646_5.cropped.lbl new file mode 100644 index 0000000000..1c4744ce94 --- /dev/null +++ b/isis/tests/data/ciss2isis/W1472855646_5.cropped.lbl @@ -0,0 +1,111 @@ +PDS_VERSION_ID = PDS3 +RECORD_TYPE = FIXED_LENGTH +RECORD_BYTES = 2072 +FILE_RECORDS = 1027 +^IMAGE_HEADER = ('W1472855646_5.cropped.img', 1) +^TELEMETRY_TABLE = ('W1472855646_5.cropped.img', 3) +^LINE_PREFIX_TABLE = ('W1472855646_5.cropped.img', 4) +^IMAGE = ('W1472855646_5.cropped.img', 4) +ANTIBLOOMING_STATE_FLAG = ON +BIAS_STRIP_MEAN = 72.644554 +CALIBRATION_LAMP_STATE_FLAG = OFF +COMMAND_FILE_NAME = 'trigger_1726_1.ioi' +COMMAND_SEQUENCE_NUMBER = 1726 +DARK_STRIP_MEAN = 90.287415 +DATA_CONVERSION_TYPE = '12BIT' +DATA_SET_ID = 'CO-S-ISSNA/ISSWA-2-EDR-V1.0' +DELAYED_READOUT_FLAG = YES +DESCRIPTION = "DSN gap truncation. Finalized using W1472855646_4.IMG." +DETECTOR_TEMPERATURE = -87.895164 +EARTH_RECEIVED_START_TIME = 2004-09-03T10:20:50.946Z +EARTH_RECEIVED_STOP_TIME = 2004-09-03T10:28:31.463Z +ELECTRONICS_BIAS = 112 +EXPECTED_MAXIMUM = (0.0, 0.0) +EXPECTED_PACKETS = 2277 +EXPOSURE_DURATION = 5.0 +FILTER_NAME = (CL1, CL2) +FILTER_TEMPERATURE = 3.192976 +FLIGHT_SOFTWARE_VERSION_ID = '1.3' +GAIN_MODE_ID = '29 ELECTRONS PER DN' +IMAGE_MID_TIME = 2004-09-02T22:09:15.409Z +IMAGE_NUMBER = '1472855646' +IMAGE_OBSERVATION_TYPE = {CALIBRATION} +IMAGE_TIME = 2004-09-02T22:09:15.409Z +INSTRUMENT_DATA_RATE = 182.783997 +INSTRUMENT_HOST_NAME = 'CASSINI ORBITER' +INSTRUMENT_ID = ISSWA +INSTRUMENT_MODE_ID = FULL +INSTRUMENT_NAME = 'IMAGING SCIENCE SUBSYSTEM WIDE ANGLE' +INST_CMPRS_PARAM = ('N/A', 'N/A', 'N/A', 'N/A') +INST_CMPRS_RATE = (16.0, 16.0) +INST_CMPRS_RATIO = 'N/A' +INST_CMPRS_TYPE = NOTCOMP +LIGHT_FLOOD_STATE_FLAG = ON +METHOD_DESC = "ISSPT2.5.2;Saturn;ISS_00ASA_MOS0ASWC001_UVIS_4" +MISSING_LINES = 449 +MISSING_PACKET_FLAG = YES +MISSION_NAME = 'CASSINI-HUYGENS' +MISSION_PHASE_NAME = 'TOUR PRE-HUYGENS' +OBSERVATION_ID = ISS_00ASA_MOS0ASWE001_UVIS +OPTICS_TEMPERATURE = (7.024934, -999.0) +ORDER_NUMBER = 2 +PARALLEL_CLOCK_VOLTAGE_INDEX = 9 +PREPARE_CYCLE_INDEX = 3 +PRODUCT_CREATION_TIME = 2004-09-06T10:31:30Z +PRODUCT_ID = '1_W1472855646.121' +PRODUCT_VERSION_TYPE = FINAL +READOUT_CYCLE_INDEX = 0 +RECEIVED_PACKETS = 1297 +SENSOR_HEAD_ELEC_TEMPERATURE = 2.270205 +SEQUENCE_ID = S03 +SEQUENCE_NUMBER = 2 +SEQUENCE_TITLE = '--' +SHUTTER_MODE_ID = BOTSIM +SHUTTER_STATE_ID = DISABLED +SOFTWARE_VERSION_ID = 'ISS 9.00 02-05-2004' +SPACECRAFT_CLOCK_CNT_PARTITION = 1 +SPACECRAFT_CLOCK_START_COUNT = '1472855646.121' +SPACECRAFT_CLOCK_STOP_COUNT = '1472855646.121' +START_TIME = 2004-09-02T22:09:15.409Z +STOP_TIME = 2004-09-02T22:09:15.409Z +TARGET_DESC = Saturn +TARGET_LIST = 'N/A' +TARGET_NAME = SATURN +TELEMETRY_FORMAT_ID = UNK +VALID_MAXIMUM = (4095, 4095) +OBJECT = IMAGE_HEADER + INTERCHANGE_FORMAT = ASCII + HEADER_TYPE = VICAR2 + BYTES = 4144 + RECORDS = 1 + ^DESCRIPTION = 'VICAR2.TXT' +END_OBJECT = IMAGE_HEADER +OBJECT = TELEMETRY_TABLE + INTERCHANGE_FORMAT = BINARY + ROWS = 1 + COLUMNS = 2 + ROW_BYTES = 2072 + ^STRUCTURE = 'TLMTAB.FMT' + OBJECT = COLUMN + NAME = NULL_PADDING + DATA_TYPE = MSB_UNSIGNED_INTEGER + START_BYTE = 61 + BYTES = 2011 + END_OBJECT = COLUMN +END_OBJECT = TELEMETRY_TABLE +OBJECT = LINE_PREFIX_TABLE + INTERCHANGE_FORMAT = BINARY + ROWS = 1024 + COLUMNS = 7 + ROW_BYTES = 24 + ROW_SUFFIX_BYTES = 2048 + ^LINE_PREFIX_STRUCTURE = 'PREFIX2.FMT' +END_OBJECT = LINE_PREFIX_TABLE +OBJECT = IMAGE + LINES = 10 + LINE_SAMPLES = 1024 + SAMPLE_BITS = 16 + SAMPLE_TYPE = SUN_INTEGER + LINE_PREFIX_BYTES = 24 +END_OBJECT = IMAGE +END