Isis 3.0 Application Source Code Reference |
Home |
00001 /** 00002 * @file 00003 * $Revision: 1.3 $ 00004 * $Date: 2009/05/27 21:26:15 $ 00005 * 00006 * Unless noted otherwise, the portions of Isis written by the USGS are public 00007 * domain. See individual third-party library and package descriptions for 00008 * intellectual property information,user agreements, and related information. 00009 * 00010 * Although Isis has been used by the USGS, no warranty, expressed or implied, 00011 * is made by the USGS as to the accuracy and functioning of such software 00012 * and related material nor shall the fact of distribution constitute any such 00013 * warranty, and no responsibility is assumed by the USGS in connection 00014 * therewith. 00015 * 00016 * For additional information, launch 00017 * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see 00018 * the Privacy & Disclaimers page on the Isis website, 00019 * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on 00020 * http://www.usgs.gov/privacy.html. 00021 */ 00022 00023 #include <cmath> //use ceiling and floor functions 00024 #include <vector> 00025 #include "Application.h" 00026 #include "Brick.h" 00027 #include "CisscalFile.h" 00028 #include "CissLabels.h" 00029 #include "Cube.h" 00030 #include "DarkCurrent.h" 00031 #include "NumericalApproximation.h" 00032 #include "Message.h" 00033 #include "Preference.h" 00034 #include "Progress.h" 00035 #include "Pvl.h" 00036 #include "SpecialPixel.h" 00037 #include "iException.h" 00038 #include "iString.h" 00039 00040 using namespace std; 00041 namespace Isis { 00042 /** 00043 * Constructs a DarkCurrent object. Sets class variables. 00044 * 00045 * @param cissLab <B>CissLabels</B> object from Cassini ISS cube 00046 * @throws Isis::iException::Pvl If the input image has an 00047 * invalid InstrumentDataRate or SummingMode. 00048 * @internal 00049 * @history 2008-11-05 Jeannie Walldren - Original Version 00050 * @history 2009-05-27 Jeannie Walldren - Updated instrument data rate range 00051 * for telemetry rate of 32. 00052 */ 00053 DarkCurrent::DarkCurrent(Isis::CissLabels &cissLab) { 00054 p_compType = cissLab.CompressionType(); 00055 p_dataConvType = cissLab.DataConversionType(); 00056 p_expDur = cissLab.ExposureDuration(); 00057 p_flightSoftware = cissLab.FlightSoftwareVersion(); 00058 p_gainMode = cissLab.GainModeId(); 00059 p_narrow = cissLab.NarrowAngle(); 00060 p_sum = cissLab.SummingMode(); 00061 00062 if(cissLab.ReadoutCycleIndex() == "Unknown") { 00063 p_readoutIndex = -999; 00064 } 00065 else { 00066 p_readoutIndex = cissLab.ReadoutCycleIndex().ToInteger(); 00067 } 00068 00069 if(p_compType == "NotCompressed") { 00070 p_compRatio = 1.0; 00071 } 00072 else { 00073 p_compRatio = cissLab.CompressionRatio().ToDouble(); 00074 } 00075 00076 if(cissLab.DelayedReadoutFlag() == "No") { 00077 p_btsm = 0; 00078 } 00079 else if(cissLab.DelayedReadoutFlag() == "Yes") { 00080 p_btsm = 1; 00081 } 00082 else { 00083 p_btsm = -1; 00084 } 00085 00086 double instDataRate = cissLab.InstrumentDataRate(); 00087 if(instDataRate >= 60.0 && instDataRate <= 61.0) p_telemetryRate = 8; 00088 else if(instDataRate >= 121.0 && instDataRate <= 122.0) p_telemetryRate = 16; 00089 else if(instDataRate >= 182.0 && instDataRate <= 183.0) p_telemetryRate = 24; 00090 else if(instDataRate >= 203.0 && instDataRate <= 204.0) p_telemetryRate = 32; 00091 else if(instDataRate >= 304.0 && instDataRate <= 305.0) p_telemetryRate = 40; 00092 else if(instDataRate >= 365.0 && instDataRate <= 366.0) p_telemetryRate = 48; 00093 else throw iException::Message(iException::Pvl, 00094 "Input file contains invalid InstrumentDataRate. See Software Interface Specification (SIS), Version 1.1, page 31.", 00095 _FILEINFO_); 00096 00097 p_readoutOrder = cissLab.ReadoutOrder(); 00098 00099 switch(p_sum.ToInteger()) { 00100 case 1: 00101 p_lines = 1024; 00102 break; 00103 case 2: 00104 p_lines = 512; 00105 break; 00106 case 4: 00107 p_lines = 256; 00108 break; 00109 default: 00110 throw iException::Message(iException::Pvl, 00111 "Input file contains invalid SummingMode. See Software Interface Specification (SIS), Version 1.1, page 31.", 00112 _FILEINFO_); 00113 } 00114 p_samples = p_lines; 00115 p_startTime.resize(p_samples); 00116 p_endTime.resize(p_samples); 00117 p_duration.resize(p_samples); 00118 for(int i = 0; i < p_samples; i++) { 00119 p_startTime[i].resize(p_lines); 00120 p_endTime[i].resize(p_lines); 00121 p_duration[i].resize(p_lines); 00122 } 00123 }//end constructor 00124 00125 00126 /** 00127 * @brief Compute dark current values to subtract from image 00128 * 00129 * This method computes the dark current DN values to be 00130 * subtracted from each pixel and returns those values in an 00131 * array of the equal dimension to the image. 00132 * 00133 * @returns <b>vector <vector <double> ></b> Final array of 00134 * dark current DNs to be subtracted 00135 * @throws Isis::iException::Pvl If the input image has an 00136 * unknown ReadoutCycleIndex or DelayedReadoutFlag. 00137 * @throws Isis::iException::Pvl If the input image has an 00138 * invalid GainModeId. 00139 * @throws Isis::iException::Math If MakeDarkArray() returns a 00140 * vector of zeros. 00141 * @see MakeDarkArray() 00142 * 00143 * @internal 00144 * @history 2008-11-05 Jeannie Walldren - Original Version 00145 * @history 2009-01-26 Jeannie Walldren - Changed declarations of 2 00146 * dimensional vectors 00147 */ 00148 vector <vector <double> > DarkCurrent::ComputeDarkDN() { //get dark_DN 00149 if(p_readoutIndex == -999) { 00150 throw iException::Message(iException::Pvl, 00151 "Readout cycle index is unknown.", 00152 _FILEINFO_); 00153 } 00154 if(p_btsm == -1) { 00155 throw iException::Message(iException::Pvl, 00156 "Delayed readout flag is unknown.", 00157 _FILEINFO_); 00158 } 00159 vector <vector <double> > dark_e(p_samples), dark_DN(p_samples); 00160 for(unsigned int i = 0; i < dark_e.size(); i++) { 00161 dark_e[i].resize(p_lines); 00162 dark_DN[i].resize(p_lines); 00163 } 00164 00165 // create new file 00166 dark_e = DarkCurrent::MakeDarkArray(); 00167 int notzero = 0; 00168 for(unsigned int i = 0; i < dark_e.size(); i++) { 00169 for(unsigned int j = 0; j < dark_e[0].size(); j++) { 00170 if(dark_e[i][j] != 0.0) { 00171 notzero++; 00172 } 00173 } 00174 } 00175 if(notzero != 0) { 00176 // correct for gain: 00177 double gain2, gainRatio; 00178 if(p_narrow) { 00179 gain2 = 30.27; 00180 switch(p_gainMode) { // GainState()){ 00181 case 215: //gs = 0: 00182 gainRatio = 0.135386; 00183 break; 00184 case 95: //1: 00185 gainRatio = 0.309569; 00186 break; 00187 case 29: //2: 00188 gainRatio = 1.0; 00189 break; 00190 case 12: //3: 00191 gainRatio = 2.357285; 00192 break; 00193 default: 00194 throw iException::Message(iException::Pvl, 00195 "Input file contains invalid GainModeId. See Software Interface Specification (SIS), Version 1.1, page 29.", 00196 _FILEINFO_); 00197 } 00198 } 00199 else { 00200 gain2 = 27.68; 00201 switch(p_gainMode) { // GainState()){ 00202 case 215://0: 00203 gainRatio = 0.125446; 00204 break; 00205 case 95://1: 00206 gainRatio = 0.290637; 00207 break; 00208 case 29://2: 00209 gainRatio = 1.0; 00210 break; 00211 case 12://3: 00212 gainRatio = 2.360374; 00213 break; 00214 default: 00215 throw iException::Message(iException::Pvl, 00216 "Input file contains invalid GainModeId. See Software Interface Specification (SIS), Version 1.1, page 29.", 00217 _FILEINFO_); 00218 } 00219 } 00220 for(unsigned int i = 0; i < dark_e.size(); i++) { 00221 for(unsigned int j = 0; j < dark_e[0].size(); j++) { 00222 dark_DN[i][j] = (dark_e[i][j] / (gain2 / gainRatio)); 00223 } 00224 } 00225 return dark_DN; 00226 } 00227 else { 00228 throw iException::Message(iException::Math, 00229 "Error in dark simulation; dark array conatains all zeros.", 00230 _FILEINFO_); 00231 } 00232 }//end ComputeDarkDN 00233 00234 00235 /** 00236 * @brief Compute time spent on CCD for given line 00237 * 00238 * Compute the line-time from light-flood erase to read out for a 00239 * given image line. Returns the real seconds that the given 00240 * line spends on the CCD. The parameter <B>lline</B> must be 00241 * between 1 and 1024. 00242 * 00243 * @param lline Current line should range from 1 to 1024 00244 * @returns <b>double</b> Time in seconds spent on CCD for given 00245 * line 00246 * @throws Isis::iException::Programmer If the input parameter is 00247 * out of valid range. 00248 * @throws Isis::iException::Pvl If the input image contains an 00249 * invalid number of lines. 00250 * @throws Isis::iException::Pvl If the input image has an 00251 * invalid ReadoutCycleIndex. 00252 * @internal 00253 * @history 2008-11-05 Jeannie Walldren - Original Version 00254 * @history 2009-05-27 Jeannie Walldren - Updated with new idl cisscal 00255 * version, 3.6, linetime code. 00256 */ 00257 double DarkCurrent::ComputeLineTime(int lline) { //returns the time for this line, takes the line number 00258 // this method mimics linetime.pro from idl's cisscal program 00259 double fsw; 00260 if(p_flightSoftware == "Unknown") { 00261 fsw = 0.0; 00262 } 00263 else fsw = p_flightSoftware.ToDouble(); 00264 00265 double linetime; 00266 double tlm = p_telemetryRate / 8; 00267 // updated idl code - change t0 initial value: 00268 double t0 = p_expDur / 1000 + 0.020; //time from erase to first line 00269 t0 = t0 + 0.68 * (p_lines - lline) / ((double) p_lines); 00270 //time due to 680ms erase 00271 int line = lline - 1; //lline is from 1 to 1024 => line is from 0 to 1023 00272 if(line < 0 || line > 1023) { 00273 iString msg = "DarkCurrent: For ComputeLineTime(lline), lline must be between 1 and 1024." + iString(lline) + " out of range"; 00274 throw iException::Message(iException::Programmer, msg.c_str() , _FILEINFO_); 00275 } 00276 00277 double r1 = 0; 00278 if(p_compType == "Lossy") { 00279 switch(p_lines) { 00280 case 256: 00281 r1 = 89.754; 00282 break; 00283 case 512: 00284 r1 = 110.131; 00285 break; 00286 case 1024: 00287 r1 = 201.734; 00288 break; 00289 default: 00290 throw iException::Message(iException::Pvl, 00291 "Input file contains invalid number of lines. See Software Interface Specification (SIS), Version 1.1, page 50.", 00292 _FILEINFO_); 00293 } 00294 double linetime = t0 + line / r1; 00295 return linetime; 00296 } 00297 double data; 00298 if(p_dataConvType == "12Bit") { 00299 data = 16.0; 00300 } 00301 else { 00302 data = 8.0; 00303 } 00304 00305 double correction = 1.0; 00306 // Telemetry rate factors (0,8,16,24,32,40,48 pps) 00307 // The fastest science packet production rate is 48 packets per second. 00308 // When the camera is creating less packets per second, it can have more 00309 // time to service the CCD. This can lead to a faster readout. This 00310 // effect is mostly seen in full or non compressed modes. 00311 00312 double r0; 00313 if(p_compType == "NotCompressed") { 00314 // Non-compressed modes 00315 // The following non-compressed rates were measured in ITL tests at 48 00316 // packets per second. Rates are specified in lines per second. The 00317 // values are for full, sum2 and sum4 modes. Flight software timing 00318 // is accurate to 5ms, so rates are specified to 2 decimal places. 00319 00320 // Ratio of rate for FSW 1.4 vs 1.3 (EGSE tests at 48 and 24pps) 00321 00322 double rate_nc = 0; 00323 double telem_nc = 0; 00324 double telem_nc0 = 0; 00325 if(p_dataConvType == "12Bit") { // not converted 00326 switch(p_lines) { 00327 case 1024: { // full, not converted 00328 rate_nc = 67.49; 00329 if(fsw >= 1.4) { 00330 correction = 1.0027; 00331 } 00332 telem_nc0 = 1.0161; 00333 switch(p_telemetryRate) { 00334 case 8: { 00335 telem_nc = 1.0128; 00336 break; 00337 } 00338 case 16: { 00339 telem_nc = 1.0095; 00340 break; 00341 } 00342 case 24: { 00343 telem_nc = 1.0082; 00344 break; 00345 } 00346 case 32: { 00347 telem_nc = 1.0031; 00348 break; 00349 } 00350 case 40: { 00351 telem_nc = 1.0033; 00352 break; 00353 } 00354 case 48: { 00355 telem_nc = 1.0; 00356 break; 00357 } 00358 } 00359 break; 00360 } 00361 case 512: { // sum2, not converted 00362 rate_nc = 85.11; 00363 if(fsw >= 1.4) { 00364 correction = 1.0073; 00365 } 00366 telem_nc0 = 1.0297; 00367 switch(p_telemetryRate) { 00368 case 8: { 00369 telem_nc = 1.0296; 00370 break; 00371 } 00372 case 16: { 00373 telem_nc = 1.0252; 00374 break; 00375 } 00376 case 24: { 00377 telem_nc = 1.0148; 00378 break; 00379 } 00380 case 32: { 00381 telem_nc = 1.0114; 00382 break; 00383 } 00384 case 40: { 00385 telem_nc = 1.0071; 00386 break; 00387 } 00388 case 48: { 00389 telem_nc = 1.0; 00390 break; 00391 } 00392 } 00393 break; 00394 } 00395 case 256: { // sum4, not converted 00396 rate_nc = 142.54; 00397 if(fsw >= 1.4) { 00398 correction = 1.0087; 00399 } 00400 telem_nc0 = 1.0356; 00401 switch(p_telemetryRate) { 00402 case 8: { 00403 telem_nc = 1.0320; 00404 break; 00405 } 00406 case 16: { 00407 telem_nc = 1.0260; 00408 break; 00409 } 00410 case 24: { 00411 telem_nc = 1.0201; 00412 break; 00413 } 00414 case 32: { 00415 telem_nc = 1.0128; 00416 break; 00417 } 00418 case 40: { 00419 telem_nc = 1.0057; 00420 break; 00421 } 00422 case 48: { 00423 telem_nc = 1.0; 00424 break; 00425 } 00426 } 00427 break; 00428 } 00429 } 00430 } 00431 else { // converted 00432 switch(p_lines) { 00433 case 1024: { // full, converted 00434 rate_nc = 71.96; 00435 if(fsw >= 1.4) { 00436 correction = 1.0016; 00437 } 00438 telem_nc0 = 1.0194; 00439 switch(p_telemetryRate) { 00440 case 8: { 00441 telem_nc = 1.0148; 00442 break; 00443 } 00444 case 16: { 00445 telem_nc = 1.0028; 00446 break; 00447 } 00448 case 24: { 00449 telem_nc = 1.0011; 00450 break; 00451 } 00452 case 32: { 00453 telem_nc = 1.0014; 00454 break; 00455 } 00456 case 40: { 00457 telem_nc = 1.0009; 00458 break; 00459 } 00460 case 48: { 00461 telem_nc = 1.0; 00462 break; 00463 } 00464 } 00465 break; 00466 } 00467 case 512: { // sum2, converted 00468 rate_nc = 88.99; 00469 if(fsw >= 1.4) { 00470 correction = 1.0042; 00471 } 00472 telem_nc0 = 1.0248; 00473 switch(p_telemetryRate) { 00474 case 8: { 00475 telem_nc = 1.0219; 00476 break; 00477 } 00478 case 16: { 00479 telem_nc = 1.0173; 00480 break; 00481 } 00482 case 24: { 00483 telem_nc = 1.0151; 00484 break; 00485 } 00486 case 32: { 00487 telem_nc = 1.0097; 00488 break; 00489 } 00490 case 40: { 00491 telem_nc = 1.0057; 00492 break; 00493 } 00494 case 48: { 00495 telem_nc = 1.0; 00496 break; 00497 } 00498 } 00499 break; 00500 } 00501 case 256: { // sum4, converted 00502 rate_nc = 152.12; 00503 if(fsw >= 1.4) { 00504 correction = 0.9946; 00505 } 00506 telem_nc0 = 1.0010; 00507 switch(p_telemetryRate) { 00508 case 8: { 00509 telem_nc = 1.0000; 00510 break; 00511 } 00512 case 16: { 00513 telem_nc = 0.9970; 00514 break; 00515 } 00516 case 24: { 00517 telem_nc = 0.9910; 00518 break; 00519 } 00520 case 32: { 00521 telem_nc = 0.9821; 00522 break; 00523 } 00524 case 40: { 00525 telem_nc = 0.9763; 00526 break; 00527 } 00528 case 48: { 00529 telem_nc = 1.0; 00530 break; 00531 } 00532 } 00533 break; 00534 } 00535 } 00536 } 00537 r1 = rate_nc * telem_nc * correction; 00538 r0 = rate_nc * telem_nc0 * correction; 00539 } 00540 else { // Lossy has already returned linetime, so (p_compType == "Lossless") 00541 // Lossless linear model 00542 // The following are least square fits for Lossless modes at 48pps. There is 00543 // a fit for each summation mode and converted and not converted (12bit). 00544 00545 // RMS of fit 0.255 0.076 0.496 not converted 00546 // RMS of fit 0.172 0.162 0.429 converted 00547 00548 // Ratio of rate for FSW 1.4 vs 1.3 (EGSE tests at 48 and 24pps) 00549 00550 double rate0 = 0; 00551 double slope = 0; 00552 double telem_L = 0; 00553 double telem_L0 = 0; 00554 00555 if(p_dataConvType == "12Bit") { // not converted 00556 switch(p_lines) { 00557 case 1024: { // full, not converted 00558 rate0 = 67.673; 00559 slope = 1.6972; // +/- 0.0102 00560 00561 if(fsw >= 1.4) { 00562 correction = 0.9999; 00563 } 00564 telem_L0 = 1.0276; 00565 switch(p_telemetryRate) { 00566 case 8: { 00567 telem_L = 1.0284; 00568 break; 00569 } 00570 case 16: { 00571 telem_L = 1.0182; 00572 break; 00573 } 00574 case 24: { 00575 telem_L = 1.0122; 00576 break; 00577 } 00578 case 32: { 00579 telem_L = 1.0048; 00580 break; 00581 } 00582 case 40: { 00583 telem_L = 1.0016; 00584 break; 00585 } 00586 case 48: { 00587 telem_L = 1.0; 00588 break; 00589 } 00590 } 00591 break; 00592 } 00593 case 512: { // sum2, not converted 00594 rate0 = 90.568; 00595 slope = 0.3671; // +/- 0.0255 00596 00597 if(fsw >= 1.4) { 00598 correction = 1.0034; 00599 } 00600 telem_L0 = 1.0030; 00601 switch(p_telemetryRate) { 00602 case 8: { 00603 telem_L = 0.9979; 00604 break; 00605 } 00606 case 16: { 00607 telem_L = 0.9933; 00608 break; 00609 } 00610 case 24: { 00611 telem_L = 0.9854; 00612 break; 00613 } 00614 case 32: { 00615 telem_L = 0.9884; 00616 break; 00617 } 00618 case 40: { 00619 telem_L = 1.0023; 00620 break; 00621 } 00622 case 48: { 00623 telem_L = 1.0; 00624 break; 00625 } 00626 } 00627 break; 00628 } 00629 case 256: { // sum4, not converted 00630 rate0 = 150.593; 00631 slope = 0.4541; // +/-0.0450 00632 00633 if(fsw >= 1.4) { 00634 correction = 1.0073; 00635 } 00636 telem_L0 = 1.0011; 00637 switch(p_telemetryRate) { 00638 case 8: { 00639 telem_L = 0.9976; 00640 break; 00641 } 00642 case 16: { 00643 telem_L = 0.9894; 00644 break; 00645 } 00646 case 24: { 00647 telem_L = 0.9864; 00648 break; 00649 } 00650 case 32: { 00651 telem_L = 1.0000; 00652 break; 00653 } 00654 case 40: { 00655 telem_L = 1.0000; 00656 break; 00657 } 00658 case 48: { 00659 telem_L = 1.0; 00660 break; 00661 } 00662 } 00663 break; 00664 } 00665 } 00666 } 00667 else { // converted 00668 switch(p_lines) { 00669 case 1024: { // full, converted 00670 rate0 = 74.862; 00671 slope = 0.4918; // +/- 0.0069 00672 if(fsw >= 1.4) { 00673 correction = 1.0019; 00674 } 00675 telem_L0 = 1.0013; 00676 switch(p_telemetryRate) { 00677 case 8: { 00678 telem_L = 1.0004; 00679 break; 00680 } 00681 case 16: { 00682 telem_L = 0.9935; 00683 break; 00684 } 00685 case 24: { 00686 telem_L = 0.9920; 00687 break; 00688 } 00689 case 32: { 00690 telem_L = 1.0002; 00691 break; 00692 } 00693 case 40: { 00694 telem_L = 0.9992; 00695 break; 00696 } 00697 case 48: { 00698 telem_L = 1.0; 00699 break; 00700 } 00701 } 00702 break; 00703 } 00704 case 512: { // sum2, converted 00705 rate0 = 91.429; 00706 slope = 0.4411; // +/- 0.0182 00707 if(fsw >= 1.4) { 00708 correction = 1.0050; 00709 } 00710 telem_L0 = 1.0013; 00711 switch(p_telemetryRate) { 00712 case 8: { 00713 telem_L = 0.9950; 00714 break; 00715 } 00716 case 16: { 00717 telem_L = 1.0000; 00718 break; 00719 } 00720 case 24: { 00721 telem_L = 1.0000; 00722 break; 00723 } 00724 case 32: { 00725 telem_L = 1.0000; 00726 break; 00727 } 00728 case 40: { 00729 telem_L = 1.0001; 00730 break; 00731 } 00732 case 48: { 00733 telem_L = 1.0; 00734 break; 00735 } 00736 } 00737 break; 00738 } 00739 case 256: { // sum4, converted 00740 rate0 = 152.350; 00741 slope = 0.5417; // +/- 0.0697 00742 if(fsw >= 1.4) { 00743 correction = 1.0080; 00744 } 00745 telem_L0 = 0.9986; 00746 switch(p_telemetryRate) { 00747 case 8: { 00748 telem_L = 0.9863; 00749 break; 00750 } 00751 case 16: { 00752 telem_L = 1.0017; 00753 break; 00754 } 00755 case 24: { 00756 telem_L = 1.0021; 00757 break; 00758 } 00759 case 32: { 00760 telem_L = 1.0010; 00761 break; 00762 } 00763 case 40: { 00764 telem_L = 1.0017; 00765 break; 00766 } 00767 case 48: { 00768 telem_L = 1.0; 00769 break; 00770 } 00771 } 00772 break; 00773 } 00774 } 00775 } 00776 double ro_ratefit = rate0 + slope * p_compRatio; 00777 r1 = ro_ratefit * telem_L * correction; 00778 r0 = ro_ratefit * telem_L0 * correction; 00779 } 00780 00781 // Calculation of BIU swap line which occurs upon completion of first packet 00782 // If one or more complete lines can fit into the first packet of 440 words, 00783 // they are moved from the Image Buffer allowing more to be read from the CCD 00784 // before the BIU pause. 00785 // Note: must also account for 4-word line header on each line 00786 double tratio = p_compRatio; 00787 if(p_compType == "Lossless" && tratio < 2.0) { 00788 tratio = 2.0; 00789 } 00790 int fpacket = 440 / (4 + ((int)(p_lines * data / 16 / tratio))); 00791 int biu_line = fpacket + 1; 00792 00793 // if camera is opposite of read_out_order (second) 00794 // Calculate number of lines read in early pad of 0.262 seconds 00795 // BIU swap occurs after these number of lines or when 00796 // first science packet is complete (at biu_line) which 00797 // ever is greater 00798 bool second = false; 00799 00800 if(p_narrow && p_readoutOrder == 1) { 00801 second = true; 00802 } 00803 else if(!p_narrow && p_readoutOrder == 0) { 00804 second = true; 00805 } 00806 00807 // First line after biu wait is at 0.289 seconds 00808 double biutime = 0.289; 00809 int early_lines = 1; 00810 if(second && p_btsm == 0) { 00811 early_lines = ((int)(0.262 * r0)) + 1; 00812 if(early_lines > biu_line) { 00813 biu_line = early_lines; 00814 } 00815 // If there is 0.262 pad before readout window (i.e. second image) 00816 // then biu swap occurs 2 rti later (0.25 sec) 00817 biutime = 0.539; 00818 } 00819 00820 double rate; 00821 if(p_lines < 1024) { 00822 rate = r1; 00823 if(p_btsm == 1) { 00824 rate = r0; // No science packet rate 00825 } 00826 if(p_btsm == 0 && line >= biu_line && fsw < 1.4) { 00827 linetime = t0 + biutime + (line - biu_line) / rate; 00828 } 00829 else { 00830 linetime = t0 + line / rate; 00831 } 00832 return linetime; 00833 } 00834 // Only FULL images can fill image buffer and cause r2 rate 00835 double r2 = 3.5989 * tlm; // ITL measured 00836 if(p_dataConvType != "12Bit") { 00837 r2 = 7.1989 * tlm; // ITL measured 00838 } 00839 // For Lossless, r2 depends on compression ratio: but not faster than r1. 00840 00841 if(p_compType == "Lossless") { 00842 // r2 = cdsr * lines per packet 00843 // lines per packet = data words per packet / data words per line 00844 // data words per packet = (440 * 2% + 467 * 98%) - 4 (line header) = 462.46 00845 // data words per line = 4 (line header) + (1024 or 512)/tratio 00846 r2 = p_telemetryRate * 462.46 / (4.0 + 1024.0 * data / 16.0 / tratio); 00847 } 00848 if(r1 < r2) { 00849 r2 = r1; 00850 } 00851 // Due to bug, FSW < 1.4 did not use 4K words of image buffer 00852 int buffer; 00853 if(fsw < 1.4) { 00854 buffer = 336; 00855 } 00856 else { 00857 buffer = 340; 00858 } 00859 if(p_dataConvType != "12Bit") { 00860 buffer = 2 * buffer; 00861 } 00862 // Stores 2 compressed lines into one 00863 if(p_compType == "Lossless") { 00864 buffer = 2 * buffer; 00865 } 00866 // Due to bug, FSW < 1.4 declared image buffer full with one free line 00867 if(fsw < 1.4) { 00868 buffer = buffer - 1; 00869 } 00870 // Now treat more complicated 1x1 case. 00871 int line_break; 00872 if(p_btsm == 0) { 00873 int inbuffer; 00874 if(fsw >= 1.4) { 00875 // Calculate line break 00876 // Transmit starts at biutime after readout starts 00877 // after early_lines initially read before biutime 00878 // buffer has buffer-inbuffer left to fill 00879 early_lines = ((int)(biutime * r0)) + 1; 00880 if(early_lines > fpacket) { 00881 inbuffer = early_lines - fpacket; 00882 } 00883 else inbuffer = 0; 00884 if(r2 >= r1) { 00885 line_break = 1024; 00886 } 00887 else { 00888 line_break = early_lines + ((int)(r1 * (buffer - inbuffer) / (r1 - r2))) + 1; 00889 } 00890 linetime = t0 + line / r1; 00891 if(line > line_break) { 00892 linetime = t0 + line_break / r1 + (line - line_break) / r2; 00893 } 00894 } 00895 else { 00896 // Calculate line break 00897 // Transmit starts and readout resumes at biutime 00898 // after biu_lines initially read before biutime 00899 // fpacket lines in 1st packet, max(early_lines-fpacket,0) in buffer 00900 if(early_lines > fpacket) { 00901 inbuffer = early_lines - fpacket; 00902 } 00903 else { 00904 inbuffer = 0; 00905 } 00906 00907 if(r2 >= r1) { 00908 line_break = 1024; 00909 } 00910 else { 00911 line_break = biu_line + ((int)(r1 * (buffer - inbuffer) / (r1 - r2))) + 1; 00912 } 00913 linetime = t0 + line / r1; 00914 if(line >= biu_line && line <= line_break) { 00915 linetime = t0 + biutime + (line - biu_line) / r1; 00916 } 00917 if(line > line_break) { 00918 linetime = t0 + biutime + (line_break - biu_line) / r1 + (line - line_break) / r2; 00919 } 00920 } 00921 } 00922 else { // p_btsm == 1 00923 // t1 is amount of time botsim image waits for first image readout window 00924 // t1 only depends on readout index and telem rate: 00925 // t1 is first camera readout window plus pad plus biu swap 00926 int readout; 00927 switch((int) p_readoutIndex / 4) { 00928 case 0: 00929 readout = 50; 00930 break; 00931 case 1: 00932 readout = 25; 00933 break; 00934 case 2: 00935 readout = 14; 00936 break; 00937 case 3: 00938 readout = 6; 00939 break; 00940 default: 00941 throw iException::Message(iException::Pvl, 00942 "Input file contains invalid ReadoutCycleIndex. See Software Interface Specification (SIS), Version 1.1, page 40.", 00943 _FILEINFO_); 00944 } 00945 double t1; 00946 if(readout * (6.0 / ((double)(tlm))) - ((int) readout * (6.0 / ((double)(tlm)))) < .5) { 00947 t1 = floor(readout * (6.0 / ((double)(tlm)))) + 0.539; 00948 } 00949 else { 00950 t1 = ceil(readout * (6.0 / ((double)(tlm)))) + 0.539; 00951 } 00952 linetime = t0 + line / r0; 00953 int line_break = buffer + fpacket + 1; // Full buffer 00954 // NotCompressed 12Bit always stops and waits when buffer filled 00955 if(p_dataConvType == "12Bit" && p_compType == "NotCompressed") { 00956 if(line >= line_break) { 00957 linetime = t0 + t1 + (line - line_break) / r2; 00958 } 00959 return linetime; 00960 } 00961 // Line at which transmission starts 00962 // Reading stops during BIU swap (0.25 sec) for FSW < 1.4 00963 int trans_line; 00964 double biu_swap; 00965 if(fsw < 1.4) { 00966 trans_line = ((int)((t1 - 0.25) * r0)) + 1; 00967 biu_swap = 0.25; 00968 } 00969 else { 00970 trans_line = ((int)(t1 * r0)) + 1; 00971 biu_swap = 0.0; 00972 } 00973 // NOTCOMP TABLE/8LSB may start reading out before buffer is filled 00974 // LOSSLESS 12BIT may start reading out before buffer is filled 00975 // If buffer is filled first, rest is read out at r2 00976 // If t0+t1 occurs first then read continues at r1 until filled, then at r2 00977 if((p_dataConvType != "12Bit" && p_compType == "NotCompressed") 00978 || (p_dataConvType == "12Bit" && p_compType == "Lossless")) { 00979 if(trans_line >= line_break) { 00980 if(line >= line_break) { 00981 linetime = t0 + t1 + (line - line_break) / r2; // waits 00982 } 00983 } 00984 else { 00985 if(r2 >= r1) { 00986 line_break = 1024; 00987 } 00988 else { 00989 line_break = trans_line + ((int)((line_break - trans_line) * r1 / (r1 - r2))) + 1; 00990 } 00991 if(line > trans_line) { 00992 linetime = t0 + trans_line / r0 + (line - trans_line) / r1 + biu_swap; 00993 } 00994 if(line > line_break) { 00995 linetime = t0 + trans_line / r0 + (line_break - trans_line) / r1 + (line - line_break) / r2 + biu_swap; 00996 } 00997 } 00998 return linetime; 00999 } 01000 // LOSSLESS with 8LSB or TABLE fits in image memory 01001 if(p_dataConvType != "12Bit" && p_compType == "LOSSLESS" && line > trans_line) { 01002 linetime = t0 + trans_line / r0 + (line - trans_line) / r1 + biu_swap; 01003 } 01004 } 01005 return linetime; 01006 }// end ComputeLineTime 01007 01008 01009 01010 /** 01011 * @brief Find dark current files for this image. 01012 * 01013 * Determines which dark parameters file and bias distortion 01014 * table, if any, should be used for this image and assigns these 01015 * filenames to p_dparamfile and p_bdpath, respectively. These 01016 * are dependent on the Instrument ID (ISSNA or ISSWA) and 01017 * Instrument Mode ID (Full, Sum2, or Sum4). 01018 * 01019 * @see DarkParameterFile() 01020 * @see BiasDistortionTable() 01021 * 01022 * @internal 01023 * @history 2008-11-05 Jeannie Walldren - Original Version 01024 */ 01025 void DarkCurrent::FindDarkFiles() { 01026 // Get the directory where the CISS darkcurrent directory is 01027 PvlGroup &dataDir = Preference::Preferences().FindGroup("DataDirectory"); 01028 iString missionDir = (string) dataDir["Cassini"]; 01029 iString darkDir(missionDir + "/calibration/darkcurrent/"); 01030 01031 iString instrumentId(""); 01032 01033 if(p_narrow) { 01034 instrumentId += "nac"; 01035 p_bdpath = darkDir + "nac_bias_distortion.tab"; 01036 } 01037 else { 01038 instrumentId += "wac"; 01039 } 01040 iString instModeId(""); 01041 if(p_sum.ToInteger() > 1) { 01042 instModeId = instModeId + "sum" + p_sum; 01043 } 01044 else { 01045 instModeId += "full"; 01046 } 01047 p_dparamfile = darkDir + instrumentId + "_median_dark_parameters" + "?????" + "." + instModeId + ".cub"; 01048 p_dparamfile.HighestVersion(); 01049 return; 01050 }//end FindDarkFiles 01051 01052 01053 /** 01054 * Computes begin time, end time, and duration for each pixel of 01055 * the image. 01056 * 01057 * @see ComputeLineTime() 01058 * 01059 * @internal 01060 * @history 2008-11-05 Jeannie Walldren - Original Version 01061 */ 01062 void DarkCurrent::ComputeTimeArrays() { 01063 // this method mimics get_line_times method of cassimg_subtractdark.pro from idl's cisscal program 01064 int numberNegTime = 0; 01065 vector <double> timeToRead(p_lines); 01066 for(int i = 0; i < p_lines; i++) { 01067 timeToRead[i] = ComputeLineTime(i + 1); 01068 if(timeToRead[i] < 0) { 01069 numberNegTime++; 01070 } 01071 } 01072 if(numberNegTime > 0) return; 01073 for(int i = 0; i < p_lines; i++) { 01074 for(int j = 0; j <= i; j++) { 01075 p_endTime[i][j] = timeToRead[i-j]; 01076 } 01077 for(int j = 0; j <= i; j++) { 01078 if(j < i) { 01079 p_startTime[i][j] = p_endTime[i][j+1]; 01080 } 01081 else { 01082 p_startTime[i][j] = 0.0; 01083 } 01084 p_duration[i][j] = p_endTime[i][j] - p_startTime[i][j]; 01085 } 01086 } 01087 for(int i = 0; i < p_lines; i++) { 01088 for(int j = 0; j < p_samples; j++) { 01089 if(p_duration[i][j] <= 0) { 01090 p_duration[i][j] = 0; 01091 //I belive this is equivalent to the IDL code : 01092 // p_duration(*,*) = p_duration(*,*) > 0.0 01093 } 01094 } 01095 } 01096 for(int i = 0; i < p_lines; i++) { 01097 for(int j = 0; j < p_samples; j++) { 01098 p_endTime[i][j] = p_startTime[i][j] + p_duration[i][j]; 01099 } 01100 } 01101 return; 01102 }//end ComputeTimeArrays 01103 01104 01105 /** 01106 * @brief Creates dark array 01107 * This method reads in the coefficients from the dark 01108 * parameters file, calls MakeManyLineDark() to create dark_e, 01109 * removes artifacts of this array be taking the median of every 01110 * 5 values, and corrects for the average bias distortion at the 01111 * beginning of each line. 01112 * 01113 * @returns <b>vector <vector <double> ></b> Secondary dark 01114 * array removed of artifacts and corrected for average 01115 * bias distortion. 01116 * @throws Isis::iException::Io If the dark parameter file or 01117 * bias distortion table is not found. 01118 * @throws Isis::iException::Io If p_startTime equals p_endTime 01119 * for all pixels. 01120 * @see FindDarkFiles() 01121 * @see ComputeTimeArrays() 01122 * @see MakeManyLineDark() 01123 * 01124 * @internal 01125 * @history 2008-11-05 Jeannie Walldren - Original Version 01126 * @history 2009-01-26 Jeannie Walldren - Changed declarations of 2 01127 * dimensional vectors 01128 */ 01129 vector <vector <double> > DarkCurrent::MakeDarkArray() { //return dark_e 01130 // this method mimics makedarkarray method of cassimg_subtractdark.pro from idl's cisscal program 01131 FindDarkFiles(); 01132 if(!p_dparamfile.Exists()) { 01133 throw iException::Message(iException::Io, 01134 "DarkParameterFile ***" 01135 + p_dparamfile.Expanded() + "*** not found.", _FILEINFO_); 01136 } 01137 if(p_narrow && (!p_bdpath.Exists())) { 01138 throw iException::Message(iException::Io, 01139 "BiasDistortionFile ***" 01140 + p_bdpath.Expanded() + "*** not found.", _FILEINFO_); 01141 } 01142 ComputeTimeArrays();//fill in values for p_startTime, p_endTime, p_duration 01143 int good = 0; 01144 for(int i = 0; i < p_lines; i++) { 01145 for(int j = 0; j < p_samples; j++) { 01146 if(p_startTime[i][j] != p_endTime[i][j]) { 01147 good++; 01148 } 01149 } 01150 } 01151 if(good != 0) { 01152 //read the coefficient cube into a Brick 01153 Brick *darkCoefficients; 01154 Cube dparamCube; 01155 dparamCube.open(p_dparamfile.Expanded()); 01156 darkCoefficients = new Brick(p_samples, p_lines, 8, dparamCube.getPixelType()); 01157 darkCoefficients->SetBasePosition(1, 1, 1); 01158 dparamCube.read(*darkCoefficients); 01159 dparamCube.close(); 01160 // Assume WAC dark current is 0 for 0.005 ms. This is not the case for 01161 // the NAC where there are negative values near the left edge of the frame: 01162 if(!p_narrow) { 01163 for(int i = 0; i < p_lines; i++) { 01164 for(int j = 0; j < p_samples; j++) { 01165 (*darkCoefficients)[darkCoefficients->Index(i+1, j+1, 1)] = 0.0; 01166 } 01167 } 01168 } 01169 // add functionality for summed images: 01170 vector <vector <double> > dark_e(p_samples), di1(p_samples); 01171 for(unsigned int i = 0; i < dark_e.size(); i++) { 01172 dark_e[i].resize(p_lines); 01173 di1[i].resize(p_lines); 01174 } 01175 01176 dark_e = MakeManyLineDark(*darkCoefficients); 01177 01178 // Median-ed dark images have some spikes below the fitted curve. 01179 // These are probably artifacts and the next section removes them. 01180 vector <double> neighborhood(5); 01181 01182 //replace each value of di1 with the median of neighborhood of 5 values 01183 for(int i = 0; i < p_lines; i++) { 01184 for(int j = 0; j < p_samples; j++) { 01185 if(j < 2 || j > (p_samples - 3)) { 01186 di1[i][j] = dark_e[i][j]; 01187 } 01188 else { 01189 for(int n = -2; n < 3; n++) { 01190 neighborhood[n+2] = dark_e[i][j+n]; 01191 } 01192 //sort these five values 01193 sort(neighborhood.begin(), neighborhood.end()); 01194 for(int f = 0; f < 5; f++) { 01195 } 01196 //set equal to median 01197 di1[i][j] = neighborhood[2]; 01198 } 01199 } 01200 } 01201 for(int i = 0; i < p_lines; i++) { 01202 for(int j = 0; j < p_samples; j++) { 01203 if(di1[i][j] - dark_e[i][j] > 10) { 01204 dark_e[i][j] = di1[i][j]; 01205 } 01206 } 01207 } 01208 // correct for the average bias distortion at the beginning of each line: 01209 if(p_narrow) { 01210 CisscalFile *biasDist = new CisscalFile(p_bdpath.Expanded()); 01211 vector<double> samp, bias_distortion; 01212 for(int i = 0; i < biasDist->LineCount(); i++) { 01213 iString line; 01214 biasDist->GetLine(line); //assigns value to line 01215 line = line.ConvertWhiteSpace(); 01216 line = line.Compress(); 01217 line = line.TrimHead(" "); 01218 if(line == "") { 01219 break; 01220 } 01221 samp.push_back(line.Token(" ").ToDouble()); 01222 bias_distortion.push_back(line.Trim(" ").ToDouble()); 01223 } 01224 biasDist->Close(); 01225 for(int i = 0; i < 21; i++) { 01226 for(int j = 0; j < p_lines; j++) { 01227 dark_e[i][j] = dark_e[i][j] - bias_distortion[i]; 01228 } 01229 } 01230 } 01231 return dark_e; 01232 } 01233 throw iException::Message(iException::Io, 01234 "StartTime == EndTime for all pixels.", 01235 _FILEINFO_); 01236 }//end MakeDarkArray 01237 01238 /** 01239 * @brief Creates preliminary dark array from dark parameters 01240 * file and line-time information 01241 * 01242 * Compute one line of a synthetic dark frame from timing tables 01243 * and dark current parameters for each pixel using a spline 01244 * interpretation method and evaluating at the start and end 01245 * times for that pixel. 01246 * 01247 * @param darkBrick Containing the coefficients found in the dark 01248 * parameters file for each pixel. 01249 * 01250 * @returns <b>vector <vector <double> ></b> Preliminary dark 01251 * array using the darkBrick values 01252 * 01253 * @internal 01254 * @history 2008-11-05 Jeannie Walldren - Original Version 01255 * @history 2009-01-26 Jeannie Walldren - Changed declarations of 2 01256 * dimensional vectors 01257 */ 01258 vector <vector <double> > DarkCurrent::MakeManyLineDark(Brick &darkBrick) { //returns dark_e 01259 // this method mimics make_manyline_dark method of cassimg_subtractdark.pro from idl's cisscal program 01260 int num_params = 8; 01261 vector <vector <double> > dark(p_samples), v1(num_params); 01262 vector <double> temp(p_samples), tgrid(num_params); 01263 vector <double> c(2), timespan(2); 01264 01265 for(unsigned int i = 0; i < dark.size(); i++) { 01266 dark[i].resize(p_lines); 01267 } 01268 for(int i = 0; i < num_params; i++) { 01269 v1[i].resize(num_params); 01270 switch(i) { 01271 case 0: 01272 tgrid[i] = 0.0; 01273 break; 01274 case 1: 01275 tgrid[i] = 10.0; 01276 break; 01277 case 2: 01278 tgrid[i] = 32.0; 01279 break; 01280 case 3: 01281 tgrid[i] = 100.0; 01282 break; 01283 case 4: 01284 tgrid[i] = 220.0; 01285 break; 01286 case 5: 01287 tgrid[i] = 320.0; 01288 break; 01289 case 6: 01290 tgrid[i] = 460.0; 01291 break; 01292 case 7: 01293 tgrid[i] = 1200.0; 01294 break; 01295 default: 01296 tgrid[i] = Null; 01297 } 01298 } 01299 for(int j = 0; j < num_params; j++) { 01300 v1[j][j] = 1.0; 01301 } 01302 Progress progress; 01303 progress.SetText("Computing dark current array..."); 01304 progress.SetMaximumSteps(p_lines); 01305 progress.CheckStatus(); 01306 for(int jline = 0; jline < p_lines; jline++) { 01307 for(int i = 0; i < p_samples; i++) { 01308 temp[i] = darkBrick[darkBrick.Index(i+1, jline+1, 1)]; // constant term 01309 } 01310 // sum the contribution from every pixel downstream of jline, including jline 01311 for(int kline = 0; kline <= jline; kline++) { 01312 // derive coefficients so that parameters can be multiplied and added 01313 // rather than interpolated 01314 timespan[0] = p_startTime[jline][kline]; 01315 timespan[1] = p_endTime[jline][kline]; 01316 // Interpolate by fitting a cubic spline to the 01317 // 4 point neighborhood (x[i-1], x[i], x[i+1], x[i+2]) surrounding 01318 // the interval, x[i] <= u < x[i+1]. 01319 NumericalApproximation spline(NumericalApproximation::CubicNeighborhood); 01320 for(int j = 0; j < num_params; j++) { 01321 spline.AddData(tgrid, v1[j]); 01322 //spline.Compute(); 01323 c = spline.Evaluate(timespan); 01324 spline.Reset(); 01325 c[0] = c[1] - c[0]; 01326 if(c[0] != 0.0) { 01327 for(int i = 0; i < p_samples; i++) { 01328 temp[i] = temp[i] + c[0] * darkBrick[darkBrick.Index(i+1, kline+1, j+1)]; 01329 } 01330 } 01331 } 01332 } 01333 for(int i = 0; i < p_samples; i++) { 01334 dark[i][jline] = temp[i]; 01335 } 01336 01337 progress.CheckStatus(); 01338 } 01339 return dark; 01340 }//end MakeManyLineDark 01341 }//end namespace Isis 01342