// // 2008-04-11 Modified the tables vecP_ECCZ and vecC_ECCZ to fix 10hPa vecC value // and to contain data for 7hPa // MonitorParameterUpdates = 2 VS_LaunchParametersReady = 4 IF MonitorParameterUpdates < 1 AND VS_LaunchParametersReady > 1 I0 = SensorBackgroundCurrent IF VS_LaunchParametersReady > 3 MonitorParameterUpdates = 2 ENDIF VS_LaunchParametersReady = 0 ENDIF IF Sounding < 1 IF VS_FILEMAP$ == "EDT" // Notification comes from EDT-filemap Sounding = 2 Interval=2 GETDBDWORD("SYSPAR\\GeneralSoundingParameters", "PTUComputingDensity", Interval) // VEC(vecP_ECC6A@, -1e10, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 500, 1000, 1e10) VEC(vecC_ECC6A_25@, 1.16, 1.16, 1.124, 1.087, 1.054, 1.033, 1.024, 1.015, 1.010, 1.007, 1.005, 1.002, 1, 1) VEC(vecC_ECC6A_30@, 1.171, 1.171, 1.131, 1.092, 1.055, 1.032, 1.022, 1.015, 1.011, 1.008, 1.006, 1.004, 1, 1) // VEC(vecP_MAST@, -1e10, 3, 5, 10, 20, 30, 50, 100, 200, 1e10) VEC(vecC_MAST@, 1.177, 1.177, 1.133, 1.088, 1.053, 1.037, 1.020, 1.004, 1, 1) // VEC(vecP_ECCZ@, -1e10, 3, 5, 7, 10, 15, 20, 30, 50, 70, 100, 150, 200, 1e10) VEC(vecC_ECCZ@, 1.24, 1.24, 1.124, 1.087, 1.066, 1.048, 1.041, 1.029, 1.018, 1.013, 1.007, 1.002, 1, 1) // TotalPath$ = "SYSPAR\\Triggering\\Data\\OzoneParams" ENDIF ENDIF IF VS_TRIG_EVENT > 1.5 // Closing TotalCount = 0 WriteTotalToDb() END_TRIGGER EXIT ENDIF IF Sounding > 1 GETLEVELCOUNT("ODT", MaxLevel) IF Done < 1 Done = 2 IF CathodeSolutionVolume < 2.75 vs = 1 ELSE vs = 2 ENDIF P0 = CalibrationPressure IF P0 < 800 OR P0 > 1100 P0 = 1013 ENDIF I0 = SensorBackgroundCurrent A0 = 0.0012250380415 A1 = 0.000124111475632 A2 = -0.00000002687066130 CP0 = A0 + A1*P0 + A2*P0*P0 PrevP = P0 P = P0 WriteLevel = 1 Param1$ = "1" ret = GETDBDOUBLE("TimingOfSounding", "RsElapsedTimeToStart", Start) IF RejectRawDataTime < 1 RejectRawDataTime = 10 ENDIF IF Interval < 0.2 Interval = 2 ENDIF ENDIF // First level IF DoFirst < 1 // Find start time GETLEVELCOUNT("ODT", LevelIndex) GETSCALED("ODT", "time", LevelIndex, time1) // If last ODT-level is lower than the first EDT-level, we can't find initial values yet. IF time1 >= Start DoFirst = 2 WHILE LevelIndex > 1 AND time1 >= Start LevelIndex = LevelIndex - 1 GETSCALED("ODT", "time", LevelIndex, time1) ENDWHILE // Start is now either between this and the next level, or on next level. We can interpolate NextTimeToGet = Start GETSCALED("ODT", "time", LevelIndex+1, time2) // Interpolate O3 GETSCALED("ODT", "Data", LevelIndex, y1) GETSCALED("ODT", "Data", LevelIndex+1, y2) O3 = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) // Interpolate I GETSCALED("ODT", "I", LevelIndex, y1) GETSCALED("ODT", "I", LevelIndex+1, y2) I = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) // Interpolate Tbox GETSCALED("ODT", "Tbox", LevelIndex, y1) GETSCALED("ODT", "Tbox", LevelIndex+1, y2) Tbox = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) // Interpolate AUX GETSCALED("ODT", "AUX", LevelIndex, y1) GETSCALED("ODT", "AUX", LevelIndex+1, y2) AUX = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) // Interpolate Voltage GETSCALED("ODT", "Voltage", LevelIndex, y1) GETSCALED("ODT", "Voltage", LevelIndex+1, y2) Voltage = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) // Get P GETSCALED("EDT", "P", 1, P) IF Sensor$ == "ECC6A" Cef_ECC6A(P, vs) ELSE IF Sensor$ == "MAST" Cef_MAST(P) ELSE Cef_ECCZ(P) ENDIF ENDIF // Calculate O3 IF I0Type$ == "ECC6Z" // No pressure correction for I0 IBG = I0 ELSE // Do pressure correction IBG = I0 * (A0 + A1*P + A2*P*P) / CP0 ENDIF O3 = O3 * (I - IBG) * Cef // Write to filemap IF O3 > -30 AND P > 0 Total = 0 WRITELEVEL("CALC_OZONE", 0, NextTimeToGet-Start, O3, Tbox, 0, 7.8899*O3, AUX, Voltage) PrevO3 = O3 PrevData = Data ELSE // Invalid level, but initial value for O3 is needed WRITELEVEL("CALC_OZONE", 0, NextTimeToGet-Start, -32768.0, -32768.0, -32768.0, -32768.0) PrevP = P // Go back ODT until valid O3 value is found WHILE LevelIndex > 1 AND O3 < -30 LevelIndex -= 1 GETSCALED("ODT", "Data", LevelIndex, O3) GETSCALED("ODT", "I", LevelIndex, I) O3 *= Cef * (I - IBG) ENDWHILE PrevO3 = O3 PrevData = 0 ENDIF // Write first ozone value to a special db location. SETDBDOUBLE(TotalPath$, "SurfaceOzonePriorToLaunch", O3) WriteLevel += 1 NextTimeToGet += Interval ENDIF ENDIF IF DoFirst > 1 //////////////////////////////////////////////////////////////////////////////// // A regular level // In LevelIndex we have the last used ODT-level. LevelIndex can be increased, // as long as MaxLevel is not exceeded and time <= EDT-time. // WRITEFILE("c:\\calc_ozone_debug.txt", "a", "Regular level.\n") GETLEVELCOUNT("EDT", nEdtLevels) WHILE LevelIndex < MaxLevel AND WriteLevel <= nEdtLevels WHILE NextTimeToGet < time2 AND WriteLevel <= nEdtLevels // Interpolate O3 GETSCALED("ODT", "Data", LevelIndex, y1) GETSCALED("ODT", "Data", LevelIndex+1, y2) IF y1 < -30 OR y2 < -30 O3 = -32768.0 ELSE O3 = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) ENDIF // Interpolate I GETSCALED("ODT", "I", LevelIndex, y1) GETSCALED("ODT", "I", LevelIndex+1, y2) IF y1 < -30 OR y2 < -30 I = -32768.0 ELSE I = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) ENDIF // Interpolate Tbox GETSCALED("ODT", "Tbox", LevelIndex, y1) GETSCALED("ODT", "Tbox", LevelIndex+1, y2) IF y1 < -30 OR y2 < -30 OR time2 - time1 >= RejectRawDataTime Tbox = -32768.0 ELSE Tbox = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) ENDIF // Interpolate AUX GETSCALED("ODT", "AUX", LevelIndex, y1) GETSCALED("ODT", "AUX", LevelIndex+1, y2) AUX = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) // Interpolate Voltage GETSCALED("ODT", "Voltage", LevelIndex, y1) GETSCALED("ODT", "Voltage", LevelIndex+1, y2) Voltage = y1 + ((NextTimeToGet - time1) * (y2 - y1) / (time2 - time1)) GETSCALED("EDT", "P", WriteLevel, P) IF Sensor$ == "ECC6A" Cef_ECC6A(P, vs) ELSE IF Sensor$ == "MAST" Cef_MAST(P) ELSE Cef_ECCZ(P) ENDIF ENDIF // Calculate O3 IF I0Type$ == "ECC6Z" // No pressure correction for I0 IBG = I0 ELSE // Do pressure correction IBG = I0 * (A0 + A1*P + A2*P*P) / CP0 ENDIF // Calculate O3 IF O3 < -100 OR I < -100 O3 = -32768.0 ELSE O3 *= (I - IBG) * Cef ENDIF // Write level to filemap IF O3 > -3 AND P > 0 AND time2 - time1 < RejectRawDataTime Data = 3.945*(O3 + PrevO3) * LOG(PrevP / P) Data += PrevData Residual = 7.8899*O3 WRITELEVEL("CALC_OZONE", 0, NextTimeToGet-Start, O3, Tbox, Data, Residual, AUX, Voltage) WriteTotalToDb() PrevP = P PrevO3 = O3 PrevData = Data ELSE // Invalid level WRITELEVEL("CALC_OZONE", 0, NextTimeToGet-Start, -32768.0, -32768.0, -32768.0, -32768.0) ENDIF WriteLevel += 1 NextTimeToGet += Interval ENDWHILE // Between these levels no more interpolatable levels were found, // let's go to next level IF NextTimeToGet >= time2 LevelIndex += 1 time1 = time2 GETSCALED("ODT", "time", LevelIndex, time2) ENDIF GETLEVELCOUNT("EDT", nEdtLevels) ENDWHILE ENDIF ENDIF // If sounding... //********************************************************************************************* // Subroutines PROCEDURE Cef_ECC6A IF ARG2 > 1.5 VEC_VEC_INTERPOLATE(vecP_ECC6A@, vecC_ECC6A_30@, Cef, ARG1) ELSE VEC_VEC_INTERPOLATE(vecP_ECC6A@, vecC_ECC6A_25@, Cef, ARG1) ENDIF RETURN Cef ENDPROCEDURE PROCEDURE Cef_MAST VEC_VEC_INTERPOLATE(vecP_MAST@, vecC_MAST@, Cef, ARG1) RETURN Cef ENDPROCEDURE PROCEDURE Cef_ECCZ VEC_VEC_INTERPOLATE(vecP_ECCZ@, vecC_ECCZ@, Cef, ARG1) RETURN Cef ENDPROCEDURE PROCEDURE WriteTotalToDb TotalCount -= 1 IF TotalCount < 0.5 SETDBDOUBLE(TotalPath$, "IntegratedOzone", Data+Residual) SETDBDOUBLE(TotalPath$, "ResidualOzone", Residual) TotalCount = 5 ENDIF ENDPROCEDURE